- implement celebi template

This commit is contained in:
Amruth Pillai
2020-07-13 09:46:55 +05:30
parent 7b2094a543
commit 55fd1d4bdc
31 changed files with 3563 additions and 99 deletions

72
package-lock.json generated
View File

@ -2189,15 +2189,6 @@
"defer-to-connect": "^1.0.1" "defer-to-connect": "^1.0.1"
} }
}, },
"@types/body-parser": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz",
"integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==",
"requires": {
"@types/connect": "*",
"@types/node": "*"
}
},
"@types/color-name": { "@types/color-name": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
@ -2213,14 +2204,6 @@
"resolved": "https://registry.npmjs.org/@types/configstore/-/configstore-2.1.1.tgz", "resolved": "https://registry.npmjs.org/@types/configstore/-/configstore-2.1.1.tgz",
"integrity": "sha1-zR6FU2M60xhcPy8jns/10mQ+krY=" "integrity": "sha1-zR6FU2M60xhcPy8jns/10mQ+krY="
}, },
"@types/connect": {
"version": "3.4.33",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz",
"integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==",
"requires": {
"@types/node": "*"
}
},
"@types/debug": { "@types/debug": {
"version": "0.0.30", "version": "0.0.30",
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-0.0.30.tgz", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-0.0.30.tgz",
@ -2236,26 +2219,6 @@
"resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
"integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==" "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g=="
}, },
"@types/express": {
"version": "4.17.3",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.3.tgz",
"integrity": "sha512-I8cGRJj3pyOLs/HndoP+25vOqhqWkAZsWMEmq1qXy/b/M3ppufecUwaK2/TVDVxcV61/iSdhykUjQQ2DLSrTdg==",
"requires": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "*",
"@types/serve-static": "*"
}
},
"@types/express-serve-static-core": {
"version": "4.17.8",
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.8.tgz",
"integrity": "sha512-1SJZ+R3Q/7mLkOD9ewCBDYD2k0WyZQtWYqF/2VvoNN2/uhI49J9CDN4OAm+wGMA0DbArA4ef27xl4+JwMtGggw==",
"requires": {
"@types/node": "*",
"@types/qs": "*",
"@types/range-parser": "*"
}
},
"@types/get-port": { "@types/get-port": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/@types/get-port/-/get-port-3.2.0.tgz", "resolved": "https://registry.npmjs.org/@types/get-port/-/get-port-3.2.0.tgz",
@ -2333,11 +2296,6 @@
"@types/unist": "*" "@types/unist": "*"
} }
}, },
"@types/mime": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.2.tgz",
"integrity": "sha512-4kPlzbljFcsttWEq6aBW0OZe6BDajAmyvr2xknBG92tejQnvdGtT9+kXSZ580DqpxY9qG2xeQVF9Dq0ymUTo5Q=="
},
"@types/minimatch": { "@types/minimatch": {
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
@ -2371,16 +2329,6 @@
"resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz",
"integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==" "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug=="
}, },
"@types/qs": {
"version": "6.9.3",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.3.tgz",
"integrity": "sha512-7s9EQWupR1fTc2pSMtXRQ9w9gLOcrJn+h7HOXw4evxyvVqMi4f+q7d2tnFe3ng3SNHjtK+0EzGMGFUQX4/AQRA=="
},
"@types/range-parser": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
"integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA=="
},
"@types/reach__router": { "@types/reach__router": {
"version": "1.3.5", "version": "1.3.5",
"resolved": "https://registry.npmjs.org/@types/reach__router/-/reach__router-1.3.5.tgz", "resolved": "https://registry.npmjs.org/@types/reach__router/-/reach__router-1.3.5.tgz",
@ -2416,15 +2364,6 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"@types/serve-static": {
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.4.tgz",
"integrity": "sha512-jTDt0o/YbpNwZbQmE/+2e+lfjJEJJR0I3OFaKQKPWkASkCoW3i6fsUnqudSMcNAfbtmADGu8f4MV4q+GqULmug==",
"requires": {
"@types/express-serve-static-core": "*",
"@types/mime": "*"
}
},
"@types/tmp": { "@types/tmp": {
"version": "0.0.33", "version": "0.0.33",
"resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.0.33.tgz", "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.0.33.tgz",
@ -8138,17 +8077,6 @@
"@firebase/util": "0.2.50" "@firebase/util": "0.2.50"
} }
}, },
"firebase-functions": {
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-3.7.0.tgz",
"integrity": "sha512-+ROj2Gs2/KyM+T8jYo7AKaHynFsN49sXbgZMll3zuGa9/8oiDsXp9e1Iy2JMkFmSZg67jeYw5Ue2OSpz0XiqFQ==",
"requires": {
"@types/express": "4.17.3",
"cors": "^2.8.5",
"express": "^4.17.1",
"lodash": "^4.17.14"
}
},
"flat-cache": { "flat-cache": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",

View File

@ -18,6 +18,7 @@
"dependencies": { "dependencies": {
"@material-ui/core": "^4.11.0", "@material-ui/core": "^4.11.0",
"@reach/router": "^1.3.4", "@reach/router": "^1.3.4",
"ajv": "^6.12.3",
"animate.css": "^4.1.0", "animate.css": "^4.1.0",
"array-move": "^2.2.2", "array-move": "^2.2.2",
"classnames": "^2.2.6", "classnames": "^2.2.6",

View File

@ -2,6 +2,7 @@ import React, { memo } from 'react';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { useSelector } from '../../../contexts/ResumeContext'; import { useSelector } from '../../../contexts/ResumeContext';
import Castform from '../../../templates/Castform'; import Castform from '../../../templates/Castform';
import Celebi from '../../../templates/Celebi';
import Gengar from '../../../templates/Gengar'; import Gengar from '../../../templates/Gengar';
import Glalie from '../../../templates/Glalie'; import Glalie from '../../../templates/Glalie';
import Onyx from '../../../templates/Onyx'; import Onyx from '../../../templates/Onyx';
@ -26,6 +27,7 @@ const Artboard = () => {
{template === 'gengar' && <Gengar data={state} />} {template === 'gengar' && <Gengar data={state} />}
{template === 'castform' && <Castform data={state} />} {template === 'castform' && <Castform data={state} />}
{template === 'glalie' && <Glalie data={state} />} {template === 'glalie' && <Glalie data={state} />}
{template === 'celebi' && <Celebi data={state} />}
</div> </div>
</div> </div>
); );

View File

@ -1,4 +1,6 @@
import cx from 'classnames'; import cx from 'classnames';
import { graphql, useStaticQuery } from 'gatsby';
import GatsbyImage from 'gatsby-image';
import React, { memo } from 'react'; import React, { memo } from 'react';
import { useDispatch, useSelector } from '../../../../contexts/ResumeContext'; import { useDispatch, useSelector } from '../../../../contexts/ResumeContext';
import templateOptions from '../../../../data/templateOptions'; import templateOptions from '../../../../data/templateOptions';
@ -10,6 +12,53 @@ const Templates = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const template = useSelector('metadata.template'); const template = useSelector('metadata.template');
const previews = useStaticQuery(graphql`
query {
onyx: file(relativePath: { eq: "templates/onyx.png" }) {
childImageSharp {
fluid(maxHeight: 400) {
...GatsbyImageSharpFluid
}
}
}
pikachu: file(relativePath: { eq: "templates/pikachu.png" }) {
childImageSharp {
fluid(maxHeight: 400) {
...GatsbyImageSharpFluid
}
}
}
gengar: file(relativePath: { eq: "templates/gengar.png" }) {
childImageSharp {
fluid(maxHeight: 400) {
...GatsbyImageSharpFluid
}
}
}
castform: file(relativePath: { eq: "templates/castform.png" }) {
childImageSharp {
fluid(maxHeight: 400) {
...GatsbyImageSharpFluid
}
}
}
glalie: file(relativePath: { eq: "templates/glalie.png" }) {
childImageSharp {
fluid(maxHeight: 400) {
...GatsbyImageSharpFluid
}
}
}
celebi: file(relativePath: { eq: "templates/celebi.png" }) {
childImageSharp {
fluid(maxHeight: 400) {
...GatsbyImageSharpFluid
}
}
}
}
`);
const handleClick = (value) => { const handleClick = (value) => {
dispatch({ dispatch({
type: 'on_input', type: 'on_input',
@ -36,7 +85,13 @@ const Templates = () => {
[styles.selected]: template === x.id, [styles.selected]: template === x.id,
})} })}
> >
<img loading="lazy" height="240px" src={x.preview} alt={x.name} /> <GatsbyImage
alt={x.name}
loading="eager"
className="w-full"
style={{ height: '225px' }}
fluid={previews[x.id].childImageSharp.fluid}
/>
<span>{x.name}</span> <span>{x.name}</span>
</div> </div>
))} ))}

View File

@ -91,7 +91,13 @@ const ResumeProvider = ({ children }) => {
return newState; return newState;
case 'on_import': case 'on_import':
newState = { id: state.id, ...payload }; temp = clone(state);
newState = payload;
newState.id = temp.id;
newState.user = temp.user;
newState.name = temp.name;
newState.createdAt = temp.createdAt;
newState.updatedAt = temp.updatedAt;
debouncedUpdateResume(newState); debouncedUpdateResume(newState);
return newState; return newState;

View File

@ -146,11 +146,15 @@
], ],
"castform": [ "castform": [
["awards", "certifications", "languages", "hobbies"], ["awards", "certifications", "languages", "hobbies"],
["work", "education", "skills", "projects", "references"] ["objective", "work", "education", "skills", "projects", "references"]
], ],
"glalie": [ "glalie": [
["awards", "certifications", "hobbies"], ["awards", "certifications", "hobbies"],
["work", "education", "skills", "projects", "languages", "references"] ["objective", "work", "education", "skills", "projects", "languages", "references"]
],
"celebi": [
["awards", "certifications", "languages", "hobbies"],
["objective", "work", "education", "skills", "projects", "references"]
] ]
}, },
"template": "pikachu" "template": "pikachu"

View File

@ -90,11 +90,15 @@
], ],
"castform": [ "castform": [
["awards", "certifications", "languages", "hobbies"], ["awards", "certifications", "languages", "hobbies"],
["work", "education", "skills", "projects", "references"] ["objective", "work", "education", "skills", "projects", "references"]
], ],
"glalie": [ "glalie": [
["awards", "certifications", "hobbies"], ["awards", "certifications", "hobbies"],
["work", "education", "skills", "projects", "languages", "references"] ["objective", "work", "education", "skills", "projects", "languages", "references"]
],
"celebi": [
["awards", "certifications", "languages", "hobbies"],
["objective", "work", "education", "skills", "projects", "references"]
] ]
}, },
"colors": { "colors": {

View File

@ -0,0 +1,471 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"additionalProperties": false,
"definitions": {
"iso8601": {
"type": "string",
"description": "e.g. 2014-06-29",
"pattern": "^([1-2][0-9]{3}-[0-1][0-9]-[0-3][0-9]|[1-2][0-9]{3}-[0-1][0-9]|[1-2][0-9]{3})$"
}
},
"properties": {
"$schema": {
"type": "string",
"description": "link to the version of the schema that can validate the resume",
"format": "uri"
},
"basics": {
"type": "object",
"additionalProperties": true,
"properties": {
"name": {
"type": "string"
},
"label": {
"type": "string",
"description": "e.g. Web Developer"
},
"image": {
"type": "string",
"description": "URL (as per RFC 3986) to a image in JPEG or PNG format"
},
"email": {
"type": "string",
"description": "e.g. thomas@gmail.com",
"format": "email"
},
"phone": {
"type": "string",
"description": "Phone numbers are stored as strings so use any format you like, e.g. 712-117-2923"
},
"url": {
"type": "string",
"description": "URL (as per RFC 3986) to your website, e.g. personal homepage",
"format": "uri"
},
"summary": {
"type": "string",
"description": "Write a short 2-3 sentence biography about yourself"
},
"location": {
"type": "object",
"additionalProperties": true,
"properties": {
"address": {
"type": "string",
"description": "To add multiple address lines, use \n. For example, 1234 Glücklichkeit Straße\nHinterhaus 5. Etage li."
},
"postalCode": {
"type": "string"
},
"city": {
"type": "string"
},
"countryCode": {
"type": "string",
"description": "code as per ISO-3166-1 ALPHA-2, e.g. US, AU, IN"
},
"region": {
"type": "string",
"description": "The general region where you live. Can be a US state, or a province, for instance."
}
}
},
"profiles": {
"type": "array",
"description": "Specify any number of social networks that you participate in",
"additionalItems": false,
"items": {
"type": "object",
"additionalProperties": true,
"properties": {
"network": {
"type": "string",
"description": "e.g. Facebook or Twitter"
},
"username": {
"type": "string",
"description": "e.g. neutralthoughts"
},
"url": {
"type": "string",
"description": "e.g. http://twitter.example.com/neutralthoughts",
"format": "uri"
}
}
}
}
}
},
"work": {
"type": "array",
"additionalItems": false,
"items": {
"type": "object",
"additionalProperties": true,
"properties": {
"name": {
"type": "string",
"description": "e.g. Facebook"
},
"location": {
"type": "string",
"description": "e.g. Menlo Park, CA"
},
"description": {
"type": "string",
"description": "e.g. Social Media Company"
},
"position": {
"type": "string",
"description": "e.g. Software Engineer"
},
"url": {
"type": "string",
"description": "e.g. http://facebook.example.com",
"format": "uri"
},
"startDate": {
"$ref": "#/definitions/iso8601"
},
"endDate": {
"$ref": "#/definitions/iso8601"
},
"summary": {
"type": "string",
"description": "Give an overview of your responsibilities at the company"
},
"highlights": {
"type": "array",
"description": "Specify multiple accomplishments",
"additionalItems": false,
"items": {
"type": "string",
"description": "e.g. Increased profits by 20% from 2011-2012 through viral advertising"
}
}
}
}
},
"volunteer": {
"type": "array",
"additionalItems": false,
"items": {
"type": "object",
"additionalProperties": true,
"properties": {
"organization": {
"type": "string",
"description": "e.g. Facebook"
},
"position": {
"type": "string",
"description": "e.g. Software Engineer"
},
"url": {
"type": "string",
"description": "e.g. http://facebook.example.com",
"format": "uri"
},
"startDate": {
"$ref": "#/definitions/iso8601"
},
"endDate": {
"$ref": "#/definitions/iso8601"
},
"summary": {
"type": "string",
"description": "Give an overview of your responsibilities at the company"
},
"highlights": {
"type": "array",
"description": "Specify accomplishments and achievements",
"additionalItems": false,
"items": {
"type": "string",
"description": "e.g. Increased profits by 20% from 2011-2012 through viral advertising"
}
}
}
}
},
"education": {
"type": "array",
"additionalItems": false,
"items": {
"type": "object",
"additionalProperties": true,
"properties": {
"institution": {
"type": "string",
"description": "e.g. Massachusetts Institute of Technology"
},
"url": {
"type": "string",
"description": "e.g. http://facebook.example.com",
"format": "uri"
},
"area": {
"type": "string",
"description": "e.g. Arts"
},
"studyType": {
"type": "string",
"description": "e.g. Bachelor"
},
"startDate": {
"$ref": "#/definitions/iso8601"
},
"endDate": {
"$ref": "#/definitions/iso8601"
},
"gpa": {
"type": "string",
"description": "grade point average, e.g. 3.67/4.0"
},
"courses": {
"type": "array",
"description": "List notable courses/subjects",
"additionalItems": false,
"items": {
"type": "string",
"description": "e.g. H1302 - Introduction to American history"
}
}
}
}
},
"awards": {
"type": "array",
"description": "Specify any awards you have received throughout your professional career",
"additionalItems": false,
"items": {
"type": "object",
"additionalProperties": true,
"properties": {
"title": {
"type": "string",
"description": "e.g. One of the 100 greatest minds of the century"
},
"date": {
"$ref": "#/definitions/iso8601"
},
"awarder": {
"type": "string",
"description": "e.g. Time Magazine"
},
"summary": {
"type": "string",
"description": "e.g. Received for my work with Quantum Physics"
}
}
}
},
"publications": {
"type": "array",
"description": "Specify your publications through your career",
"additionalItems": false,
"items": {
"type": "object",
"additionalProperties": true,
"properties": {
"name": {
"type": "string",
"description": "e.g. The World Wide Web"
},
"publisher": {
"type": "string",
"description": "e.g. IEEE, Computer Magazine"
},
"releaseDate": {
"$ref": "#/definitions/iso8601"
},
"url": {
"type": "string",
"description": "e.g. http://www.computer.org.example.com/csdl/mags/co/1996/10/rx069-abs.html",
"format": "uri"
},
"summary": {
"type": "string",
"description": "Short summary of publication. e.g. Discussion of the World Wide Web, HTTP, HTML."
}
}
}
},
"skills": {
"type": "array",
"description": "List out your professional skill-set",
"additionalItems": false,
"items": {
"type": "object",
"additionalProperties": true,
"properties": {
"name": {
"type": "string",
"description": "e.g. Web Development"
},
"level": {
"type": "string",
"description": "e.g. Master"
},
"keywords": {
"type": "array",
"description": "List some keywords pertaining to this skill",
"additionalItems": false,
"items": {
"type": "string",
"description": "e.g. HTML"
}
}
}
}
},
"languages": {
"type": "array",
"description": "List any other languages you speak",
"additionalItems": false,
"items": {
"type": "object",
"additionalProperties": true,
"properties": {
"language": {
"type": "string",
"description": "e.g. English, Spanish"
},
"fluency": {
"type": "string",
"description": "e.g. Fluent, Beginner"
}
}
}
},
"interests": {
"type": "array",
"additionalItems": false,
"items": {
"type": "object",
"additionalProperties": true,
"properties": {
"name": {
"type": "string",
"description": "e.g. Philosophy"
},
"keywords": {
"type": "array",
"additionalItems": false,
"items": {
"type": "string",
"description": "e.g. Friedrich Nietzsche"
}
}
}
}
},
"references": {
"type": "array",
"description": "List references you have received",
"additionalItems": false,
"items": {
"type": "object",
"additionalProperties": true,
"properties": {
"name": {
"type": "string",
"description": "e.g. Timothy Cook"
},
"reference": {
"type": "string",
"description": "e.g. Joe blogs was a great employee, who turned up to work at least once a week. He exceeded my expectations when it came to doing nothing."
}
}
}
},
"projects": {
"type": "array",
"description": "Specify career projects",
"additionalItems": false,
"items": {
"type": "object",
"additionalProperties": true,
"properties": {
"name": {
"type": "string",
"description": "e.g. The World Wide Web"
},
"description": {
"type": "string",
"description": "Short summary of project. e.g. Collated works of 2017."
},
"highlights": {
"type": "array",
"description": "Specify multiple features",
"additionalItems": false,
"items": {
"type": "string",
"description": "e.g. Directs you close but not quite there"
}
},
"keywords": {
"type": "array",
"description": "Specify special elements involved",
"additionalItems": false,
"items": {
"type": "string",
"description": "e.g. AngularJS"
}
},
"startDate": {
"$ref": "#/definitions/iso8601"
},
"endDate": {
"$ref": "#/definitions/iso8601"
},
"url": {
"type": "string",
"format": "uri",
"description": "e.g. http://www.computer.org/csdl/mags/co/1996/10/rx069-abs.html"
},
"roles": {
"type": "array",
"description": "Specify your role on this project or in company",
"additionalItems": false,
"items": {
"type": "string",
"description": "e.g. Team Lead, Speaker, Writer"
}
},
"entity": {
"type": "string",
"description": "Specify the relevant company/entity affiliations e.g. 'greenpeace', 'corporationXYZ'"
},
"type": {
"type": "string",
"description": " e.g. 'volunteering', 'presentation', 'talk', 'application', 'conference'"
}
}
}
},
"meta": {
"type": "object",
"description": "The schema version and any other tooling configuration lives here",
"additionalProperties": true,
"properties": {
"canonical": {
"type": "string",
"description": "URL (as per RFC 3986) to latest version of this document",
"format": "uri"
},
"version": {
"type": "string",
"description": "A version field which follows semver - e.g. v1.0.0"
},
"lastModified": {
"type": "string",
"description": "Using ISO 8601 with YYYY-MM-DDThh:mm:ss"
}
}
}
},
"title": "Resume Schema",
"type": "object"
}

File diff suppressed because it is too large Load Diff

View File

@ -2,27 +2,26 @@ const templateOptions = [
{ {
id: 'onyx', id: 'onyx',
name: 'Onyx', name: 'Onyx',
preview: 'https://source.unsplash.com/random/300x500',
}, },
{ {
id: 'pikachu', id: 'pikachu',
name: 'Pikachu', name: 'Pikachu',
preview: 'https://source.unsplash.com/random/301x501',
}, },
{ {
id: 'gengar', id: 'gengar',
name: 'Gengar', name: 'Gengar',
preview: 'https://source.unsplash.com/random/302x502',
}, },
{ {
id: 'castform', id: 'castform',
name: 'Castform', name: 'Castform',
preview: 'https://source.unsplash.com/random/303x503',
}, },
{ {
id: 'glalie', id: 'glalie',
name: 'Glalie', name: 'Glalie',
preview: 'https://source.unsplash.com/random/304x504', },
{
id: 'celebi',
name: 'Celebi',
}, },
]; ];

View File

@ -1,11 +1,15 @@
import React, { memo, useContext, useEffect, useState, useRef } from 'react';
import { Tooltip } from '@material-ui/core'; import { Tooltip } from '@material-ui/core';
import ModalContext from '../../contexts/ModalContext'; import Ajv from 'ajv';
import BaseModal from '../BaseModal'; import React, { memo, useContext, useEffect, useRef, useState } from 'react';
import { toast } from 'react-toastify';
import Button from '../../components/shared/Button'; import Button from '../../components/shared/Button';
import ModalContext from '../../contexts/ModalContext';
import { useDispatch } from '../../contexts/ResumeContext'; import { useDispatch } from '../../contexts/ResumeContext';
import reactiveResumeSchema from '../../data/schema/reactiveResume.json';
import BaseModal from '../BaseModal';
const ImportModal = () => { const ImportModal = () => {
const ajv = new Ajv();
const fileInputRef = useRef(null); const fileInputRef = useRef(null);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const dispatch = useDispatch(); const dispatch = useDispatch();
@ -22,6 +26,11 @@ const ImportModal = () => {
const fr = new FileReader(); const fr = new FileReader();
fr.addEventListener('load', () => { fr.addEventListener('load', () => {
const payload = JSON.parse(fr.result); const payload = JSON.parse(fr.result);
const valid = ajv.validate(reactiveResumeSchema, payload);
if (!valid) {
ajv.errors.forEach((x) => toast.error(`Invalid Data: ${x.message}`));
return;
}
dispatch({ type: 'on_import', payload }); dispatch({ type: 'on_import', payload });
setOpen(false); setOpen(false);
}); });

View File

@ -10,6 +10,7 @@ import Glalie from '../../templates/Glalie';
import Onyx from '../../templates/Onyx'; import Onyx from '../../templates/Onyx';
import Pikachu from '../../templates/Pikachu'; import Pikachu from '../../templates/Pikachu';
import styles from './view.module.css'; import styles from './view.module.css';
import Celebi from '../../templates/Celebi';
const ResumeViewer = ({ id }) => { const ResumeViewer = ({ id }) => {
const [resume, setResume] = useState(null); const [resume, setResume] = useState(null);
@ -56,6 +57,7 @@ const ResumeViewer = ({ id }) => {
<Castform data={resume} /> <Castform data={resume} />
)} )}
{resume.metadata.template === 'glalie' && <Glalie data={resume} />} {resume.metadata.template === 'glalie' && <Glalie data={resume} />}
{resume.metadata.template === 'celebi' && <Celebi data={resume} />}
</div> </div>
<p className={styles.footer}> <p className={styles.footer}>

View File

@ -64,7 +64,7 @@ const Castform = ({ data }) => {
> >
<div className="grid grid-cols-12"> <div className="grid grid-cols-12">
<div <div
className="col-span-4 p-5" className="col-span-4 py-8 pr-8 pl-5"
style={{ style={{
color: data.metadata.colors.background, color: data.metadata.colors.background,
backgroundColor: data.metadata.colors.primary, backgroundColor: data.metadata.colors.primary,
@ -86,7 +86,7 @@ const Castform = ({ data }) => {
})} })}
</div> </div>
</div> </div>
<div className="col-span-8 p-5"> <div className="col-span-8 py-8 pr-8 pl-5">
<div className="grid gap-4"> <div className="grid gap-4">
{layout[1] && {layout[1] &&
layout[1].map((x) => { layout[1].map((x) => {

126
src/templates/Celebi.js Normal file
View File

@ -0,0 +1,126 @@
import React from 'react';
import PageContext from '../contexts/PageContext';
import { hexToRgb } from '../utils';
import AwardsA from './blocks/Awards/AwardsA';
import CertificationsA from './blocks/Certifications/CertificationsA';
import ContactE from './blocks/Contact/ContactE';
import EducationA from './blocks/Education/EducationA';
import HeadingE from './blocks/Heading/HeadingE';
import HobbiesA from './blocks/Hobbies/HobbiesA';
import LanguagesB from './blocks/Languages/LanguagesB';
import ObjectiveA from './blocks/Objective/ObjectiveA';
import ProjectsA from './blocks/Projects/ProjectsA';
import ReferencesA from './blocks/References/ReferencesA';
import SkillsA from './blocks/Skills/SkillsA';
import WorkA from './blocks/Work/WorkA';
const Blocks = {
objective: ObjectiveA,
work: WorkA,
education: EducationA,
projects: ProjectsA,
awards: AwardsA,
certifications: CertificationsA,
skills: SkillsA,
hobbies: HobbiesA,
languages: LanguagesB,
references: ReferencesA,
};
const Celebi = ({ data }) => {
const layout = data.metadata.layout.celebi;
const { r, g, b } = hexToRgb(data.metadata.colors.primary) || {};
const styles = {
header: {
position: 'absolute',
left: 0,
right: 0,
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
color: data.metadata.colors.background,
backgroundColor: data.metadata.colors.text,
height: '160px',
paddingLeft: '275px',
},
leftSection: {
backgroundColor: `rgba(${r}, ${g}, ${b}, 0.1)`,
},
rightSection: {
top: '160px',
},
};
const Photo = () =>
data.profile.photograph !== '' && (
<div className="relative z-40">
<img
className="w-full object-cover object-center"
src={data.profile.photograph}
alt={data.profile.firstName}
style={{
height: '160px',
}}
/>
</div>
);
const Profile = () => (
<div style={styles.header}>
<h1
className="tracking-wide uppercase font-bold"
style={{ fontSize: '2.75em' }}
>
{data.profile.firstName} {data.profile.lastName}
</h1>
<h6 className="text-lg tracking-wider uppercase">
{data.profile.subtitle}
</h6>
</div>
);
return (
<PageContext.Provider value={{ data, heading: HeadingE }}>
<div
id="page"
className="relative rounded"
style={{
fontFamily: data.metadata.font,
color: data.metadata.colors.text,
backgroundColor: data.metadata.colors.background,
}}
>
<div className="grid grid-cols-12 gap-8">
<div className="col-span-4 ml-8" style={styles.leftSection}>
<Photo />
<div className="text-center grid gap-4 mt-4 mb-8 mx-6">
<ContactE />
{layout[0] &&
layout[0].map((x) => {
const Component = Blocks[x];
return Component && <Component key={x} />;
})}
</div>
</div>
<div className="col-span-8">
<Profile />
<div className="relative" style={styles.rightSection}>
<div className="grid gap-4 mt-4 mb-8 mr-8">
{layout[1] &&
layout[1].map((x) => {
const Component = Blocks[x];
return Component && <Component key={x} />;
})}
</div>
</div>
</div>
</div>
</div>
</PageContext.Provider>
);
};
export default Celebi;

View File

@ -68,7 +68,7 @@ const Glalie = ({ data }) => {
backgroundColor: `rgba(${r}, ${g}, ${b}, 0.1)`, backgroundColor: `rgba(${r}, ${g}, ${b}, 0.1)`,
}} }}
> >
<div className="grid gap-6 p-6"> <div className="grid gap-6 text-center p-8">
<Profile /> <Profile />
<ContactD /> <ContactD />
@ -81,7 +81,7 @@ const Glalie = ({ data }) => {
</div> </div>
<div className="col-span-8"> <div className="col-span-8">
<div className="grid gap-4 p-6"> <div className="grid gap-4 p-8">
{layout[1] && {layout[1] &&
layout[1].map((x) => { layout[1].map((x) => {
const Component = Blocks[x]; const Component = Blocks[x];

View File

@ -32,14 +32,14 @@ const Pikachu = ({ data }) => {
<PageContext.Provider value={{ data, heading: HeadingB }}> <PageContext.Provider value={{ data, heading: HeadingB }}>
<div <div
id="page" id="page"
className="p-6 rounded" className="p-8 rounded"
style={{ style={{
fontFamily: data.metadata.font, fontFamily: data.metadata.font,
color: data.metadata.colors.text, color: data.metadata.colors.text,
backgroundColor: data.metadata.colors.background, backgroundColor: data.metadata.colors.background,
}} }}
> >
<div className="grid grid-cols-12 col-gap-6 row-gap-8"> <div className="grid grid-cols-12 gap-8">
{data.profile.photograph && ( {data.profile.photograph && (
<div className="self-center col-span-4"> <div className="self-center col-span-4">
<img <img

View File

@ -7,7 +7,7 @@ import { safetyCheck } from '../../../utils';
const AwardItem = (x) => ( const AwardItem = (x) => (
<div key={x.id}> <div key={x.id}>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<div className="flex flex-col"> <div className="flex flex-col text-left mr-2">
<h6 className="font-semibold">{x.title}</h6> <h6 className="font-semibold">{x.title}</h6>
<span className="text-xs">{x.awarder}</span> <span className="text-xs">{x.awarder}</span>
</div> </div>

View File

@ -7,7 +7,7 @@ import { safetyCheck } from '../../../utils';
const CertificationItem = (x) => ( const CertificationItem = (x) => (
<div key={x.id}> <div key={x.id}>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<div className="flex flex-col"> <div className="flex flex-col text-left mr-2">
<h6 className="font-semibold">{x.title}</h6> <h6 className="font-semibold">{x.title}</h6>
<span className="text-xs">{x.issuer}</span> <span className="text-xs">{x.issuer}</span>
</div> </div>

View File

@ -18,7 +18,7 @@ const ContactItem = ({ value, label, link }) => {
) : null; ) : null;
}; };
const ContactC = () => { const ContactD = () => {
const { data } = useContext(PageContext); const { data } = useContext(PageContext);
return ( return (
@ -80,4 +80,4 @@ const ContactC = () => {
); );
}; };
export default memo(ContactC); export default memo(ContactD);

View File

@ -0,0 +1,68 @@
import React, { memo, useContext } from 'react';
import PageContext from '../../../contexts/PageContext';
import { safetyCheck } from '../../../utils';
const ContactItem = ({ value, label, link }) => {
return value ? (
<div className="flex flex-col">
<h6 className="capitalize font-semibold">{label}</h6>
{link ? (
<a href={link} target="_blank" rel="noopener noreferrer">
<span className="font-medium break-all">{value}</span>
</a>
) : (
<span className="font-medium break-all">{value}</span>
)}
</div>
) : null;
};
const ContactE = () => {
const { data, heading: Heading } = useContext(PageContext);
return (
<div>
<Heading>Profile</Heading>
<div className="relative w-full grid gap-2 text-xs">
<div>
<h6 className="capitalize font-semibold">Address</h6>
<div className="flex flex-col text-xs">
<span>{data.profile.address.line1}</span>
<span>{data.profile.address.line2}</span>
<span>
{data.profile.address.city} {data.profile.address.pincode}
</span>
</div>
</div>
<ContactItem
label="phone"
value={data.profile.phone}
link={`tel:${data.profile.phone}`}
/>
<ContactItem
label="website"
value={data.profile.website}
link={`http://${data.profile.website}`}
/>
<ContactItem
label="email"
value={data.profile.email}
link={`mailto:${data.profile.email}`}
/>
{safetyCheck(data.social) &&
data.social.items.map((x) => (
<ContactItem
key={x.id}
value={x.username}
label={x.network}
link={x.url}
/>
))}
</div>
</div>
);
};
export default memo(ContactE);

View File

@ -6,7 +6,7 @@ import { formatDateRange, safetyCheck } from '../../../utils';
const EducationItem = (x) => ( const EducationItem = (x) => (
<div key={x.id}> <div key={x.id}>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<div className="flex flex-col"> <div className="flex flex-col text-left mr-2">
<h6 className="font-semibold">{x.institution}</h6> <h6 className="font-semibold">{x.institution}</h6>
<span className="text-xs"> <span className="text-xs">
<strong>{x.degree}</strong> {x.field} <strong>{x.degree}</strong> {x.field}

View File

@ -0,0 +1,11 @@
import React, { memo } from 'react';
const HeadingC = ({ children }) => {
return (
<h6 className="my-2 text-md uppercase font-semibold tracking-wider pb-1 border-b-2 border-gray-800">
{children}
</h6>
);
};
export default memo(HeadingC);

View File

@ -0,0 +1,23 @@
import React, { memo, useContext } from 'react';
import PageContext from '../../../contexts/PageContext';
import { safetyCheck } from '../../../utils';
const LanguageItem = (x) => (
<div key={x.id} className="flex flex-col">
<h6 className="font-semibold">{x.name}</h6>
<span className="text-xs">{x.fluency}</span>
</div>
);
const LanguagesB = () => {
const { data, heading: Heading } = useContext(PageContext);
return safetyCheck(data.languages) ? (
<div>
<Heading>{data.languages.heading}</Heading>
<div className="grid gap-2">{data.languages.items.map(LanguageItem)}</div>
</div>
) : null;
};
export default memo(LanguagesB);

View File

@ -7,7 +7,7 @@ import { safetyCheck } from '../../../utils';
const ProjectItem = (x) => ( const ProjectItem = (x) => (
<div key={x.id}> <div key={x.id}>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<div className="flex flex-col"> <div className="flex flex-col text-left mr-2">
<h6 className="font-semibold">{x.title}</h6> <h6 className="font-semibold">{x.title}</h6>
{x.link && ( {x.link && (
<a href={x.link} className="text-xs"> <a href={x.link} className="text-xs">

View File

@ -6,7 +6,7 @@ import { formatDateRange, safetyCheck } from '../../../utils';
const WorkItem = (x) => ( const WorkItem = (x) => (
<div key={x.id}> <div key={x.id}>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<div className="flex flex-col"> <div className="flex flex-col text-left mr-2">
<h6 className="font-semibold">{x.company}</h6> <h6 className="font-semibold">{x.company}</h6>
<span className="text-xs">{x.position}</span> <span className="text-xs">{x.position}</span>
</div> </div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB