Files
github-profile-readme-gener…/src/pages/index.js
T
2020-07-21 18:37:15 +05:30

304 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useState, useEffect } from "react"
import MarkdownPreview from "../components/markdownPreview";
import Markdown from '../components/markdown';
import Header from '../components/header';
import Title from '../components/title';
import Subtitle from '../components/subtitle';
import Work from '../components/work';
import Social from '../components/social';
import Addons from '../components/addons';
import Skills from '../components/skills';
import { initialSkillState } from '../constants/skills';
import gsap from 'gsap';
import Loader from '../components/loader';
import Footer from '../components/footer';
import './index.css'
import { ArrowLeftIcon, CopyIcon, DownloadIcon, EyeIcon, CheckIcon, MarkdownIcon } from '@primer/octicons-react';
import SEO from '../components/seo';
import { isGithubUsernameValid } from '../utils/validation';
const IndexPage = () => {
const [prefix, setPrefix] = useState({
title: "Hi 👋, I'm",
currentWork: '🔭 Im currently working on',
currentLearn: '🌱 Im currently learning',
collaborateOn: '👯 Im looking to collaborate on',
helpWith: '🤔 Im looking for help with',
ama: '💬 Ask me about',
contact: '📫 How to reach me',
funFact: '⚡ Fun fact',
portfolio: '👨‍💻 All of my projects are available at',
blog: '📝 I regulary write articles on',
});
const [data, setData] = useState({
title: '',
subtitle: 'A passionate frontend developer from India',
currentWork: '',
currentLearn: '',
collaborateOn: '',
helpWith: '',
ama: '',
contact: '',
funFact: '',
visitorsBadge: false,
githubStats: false,
});
const [link, setLink] = useState({
currentWork: '',
collaborateOn: '',
helpWith: '',
portfolio: '',
blog: '',
});
const [social, setSocial] = useState({
github: '',
dev: '',
linkedin: '',
codepen: '',
stackoverflow: '',
kaggle: '',
codesandbox: '',
fb: '',
instagram: '',
twitter: '',
dribbble: '',
behance: '',
medium: '',
youtube: ''
});
const [skills, setSkills] = useState(initialSkillState)
const [generatePreview, setGeneratePreview] = useState(false);
const [generateMarkdown, setGenerateMarkdown] = useState(false);
const [displayLoader, setDisplayLoader] = useState(false);
const [copyObj, setcopyObj] = useState({
isCopied: false,
copiedText: 'copy-markdown'
});
const [previewMarkdown, setPreviewMarkdown] = useState({
isPreview: false,
buttonText: 'preview'
});
const handleSkillsChange = (field) => {
let change = { ...skills }
change[field] = !change[field];
setSkills(change);
}
const handlePrefixChange = (field, e) => {
let change = { ...prefix }
change[field] = e.target.value;
setPrefix(change);
}
const handleDataChange = (field, e) => {
let change = { ...data }
change[field] = e.target.value;
setData(change);
}
const handleLinkChange = (field, e) => {
let change = { ...link }
change[field] = e.target.value;
setLink(change);
}
const handleSocialChange = (field, e) => {
let change = { ...social }
change[field] = e.target.value.toLowerCase();
setSocial(change);
}
const handleCheckChange = (field) => {
let change = { ...data }
change[field] = !change[field];
setData(change);
}
const generate = () => {
var tl = new gsap.timeline();
tl.to('.generate', {
scale: 0,
duration: 0.5,
ease: 'Linear.easeNone',
});
tl.set('.form', { display: 'none' });
setDisplayLoader(true);
setTimeout(() => {
setDisplayLoader(false);
setGenerateMarkdown(!generateMarkdown);
gsap.fromTo('.markdown-box', {
scale: 0.2,
}, {
scale: 1,
duration: 0.5,
ease: 'Linear.easeNone',
});
}, 3000);
}
const trimDataValues = (item, setItem) => {
const dataObj = { ...item };
Object.keys(dataObj).forEach(k => (typeof dataObj[k] === 'string') ? dataObj[k] = dataObj[k].trim() : null);
setItem(dataObj);
}
const handleGenerate = () => {
trimDataValues(data, setData);
trimDataValues(social, setSocial);
trimDataValues(link, setLink);
if (data.visitorsBadge || data.githubStats) {
if (social.github && isGithubUsernameValid(social.github)) {
generate();
}
} else if (social.github) {
if (isGithubUsernameValid(social.github)) {
generate();
}
} else {
generate();
}
}
const handleGeneratePreview = () => {
setGenerateMarkdown(!generateMarkdown);
setGeneratePreview(!generatePreview);
if (!generatePreview) {
gsap.set('.copy-button, .download-button', {
visibility: 'hidden'
});
setPreviewMarkdown({
isPreview: true,
buttonText: 'markdown'
})
} else {
gsap.set('.copy-button, .download-button', {
visibility: 'visible'
});
gsap.to('.copy-button', {
border: '2px solid #3b3b4f',
duration: 1
});
setPreviewMarkdown({
isPreview: false,
buttonText: 'preview'
})
resetCopyMarkdownButton();
}
}
const resetCopyMarkdownButton = () => {
gsap.set('#copy-markdown', {
color: '#0a0a23',
});
setcopyObj({
isCopied: false,
copiedText: 'copy-markdown'
});
}
const setCopyMarkdownButton = () => {
gsap.set('#copy-markdown', {
color: '#00471b',
});
gsap.fromTo('.copy-button', {
scale: 0.5,
}, {
scale: 1,
ease: 'elastic.in',
border: '2px solid #00471b',
duration: 0.5
});
setcopyObj({
isCopied: true,
copiedText: 'copied'
});
}
const handleCopyToClipboard = () => {
var range = document.createRange();
range.selectNode(document.getElementById("markdown-content"));
window.getSelection().removeAllRanges(); // clear current selection
window.getSelection().addRange(range); // to select text
document.execCommand("copy");
window.getSelection().removeAllRanges();
setCopyMarkdownButton();
}
const handleDownload = () => {
var markdownContent = document.getElementById("markdown-content");
var tempElement = document.createElement('a');
tempElement.setAttribute('href', 'data:text/markdown;charset=utf-8,' + encodeURIComponent(markdownContent.innerText));
tempElement.setAttribute('download', 'README.md');
tempElement.style.display = 'none';
document.body.appendChild(tempElement);
tempElement.click();
document.body.removeChild(tempElement);
}
const handleBackToEdit = () => {
setGeneratePreview(false);
setGenerateMarkdown(false);
gsap.set('.form', {
display: ''
});
gsap.to('.generate', {
scale: 1,
});
resetCopyMarkdownButton();
}
useEffect(() => {
gsap.fromTo(".generate", {
boxShadow: "0 0 0 0px rgba(59, 59, 79, 0.4)"
}, {
boxShadow: "0 0 0 20px rgba(59, 59, 79, 0)",
repeat: -1,
duration: 1
});
});
return (
<>
<SEO title="Github Profile Readme Generator" description="Github Profile Readme Generator" />
<><Header heading="Github Profile Readme Generator" /></>
<div className="form">
<Title data={data} prefix={prefix} handleDataChange={handleDataChange} handlePrefixChange={handlePrefixChange} />
<Subtitle data={data} handleDataChange={handleDataChange} />
<Work prefix={prefix} data={data} link={link} handlePrefixChange={handlePrefixChange} handleLinkChange={handleLinkChange} handleDataChange={handleDataChange} />
<Skills skills={skills} handleSkillsChange={handleSkillsChange} />
<Social social={social} handleSocialChange={handleSocialChange} />
<Addons data={data} handleCheckChange={handleCheckChange} />
<div className="section">
{(data.visitorsBadge || data.githubStats) && !social.github ?
<div className="warning">* Please add github username to use these add-ons</div> : ''}
{social.github && !isGithubUsernameValid(social.github) ?
<div className="warning">* Github username is invalid, please add a valid username</div> : ''}
</div>
<div className="submit">
<div className="button generate" tabIndex="0" role="button" onClick={handleGenerate}>Generate README</div>
</div>
</div>
{displayLoader ? <Loader /> : ''}
{(generateMarkdown || generatePreview) ?
<div className="markdown-section">
<div className="utils">
<div className="back-button" tabIndex="0" role="button" onClick={handleBackToEdit}>
<ArrowLeftIcon size={16} /> <span className="hide-on-mobile"> back to edit</span>
</div>
<div className="copy-button" tabIndex="0" role="button" onClick={handleCopyToClipboard}>
{
copyObj.isCopied === true ?
<CheckIcon size={24} />
:
<CopyIcon size={24} />
}
<span className="hide-on-mobile" id="copy-markdown"> {copyObj.copiedText} </span>
</div>
<div className="download-button" tabIndex="0" role="button" onClick={handleDownload}>
<DownloadIcon size={24} /> <span className="hide-on-mobile" id="download-markdown"> download </span>
</div>
<div className="preview-button" tabIndex="0" role="button" onClick={handleGeneratePreview}>
{previewMarkdown.isPreview ? <MarkdownIcon size={16} /> : <EyeIcon size={16} />} <span className="hide-on-mobile" id="preview-markdown">{previewMarkdown.buttonText}</span>
</div>
</div>
<div className="markdown">
<div className="markdown-box">
{generatePreview ? <MarkdownPreview prefix={prefix} data={data} link={link} social={social} skills={skills} /> : ''}
{generateMarkdown ? <Markdown prefix={prefix} data={data} link={link} social={social} skills={skills} /> : ''}
</div>
</div>
</div>
: ''}
<Footer />
</>
)
}
export default IndexPage