mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2025-11-13 16:22:59 +10:00
- implement celebi template
This commit is contained in:
72
package-lock.json
generated
72
package-lock.json
generated
@ -2189,15 +2189,6 @@
|
||||
"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": {
|
||||
"version": "1.1.1",
|
||||
"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",
|
||||
"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": {
|
||||
"version": "0.0.30",
|
||||
"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",
|
||||
"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": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/get-port/-/get-port-3.2.0.tgz",
|
||||
@ -2333,11 +2296,6 @@
|
||||
"@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": {
|
||||
"version": "3.0.3",
|
||||
"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",
|
||||
"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": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/reach__router/-/reach__router-1.3.5.tgz",
|
||||
@ -2416,15 +2364,6 @@
|
||||
"@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": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.0.33.tgz",
|
||||
@ -8138,17 +8077,6 @@
|
||||
"@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": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
"dependencies": {
|
||||
"@material-ui/core": "^4.11.0",
|
||||
"@reach/router": "^1.3.4",
|
||||
"ajv": "^6.12.3",
|
||||
"animate.css": "^4.1.0",
|
||||
"array-move": "^2.2.2",
|
||||
"classnames": "^2.2.6",
|
||||
|
||||
@ -2,6 +2,7 @@ import React, { memo } from 'react';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import { useSelector } from '../../../contexts/ResumeContext';
|
||||
import Castform from '../../../templates/Castform';
|
||||
import Celebi from '../../../templates/Celebi';
|
||||
import Gengar from '../../../templates/Gengar';
|
||||
import Glalie from '../../../templates/Glalie';
|
||||
import Onyx from '../../../templates/Onyx';
|
||||
@ -26,6 +27,7 @@ const Artboard = () => {
|
||||
{template === 'gengar' && <Gengar data={state} />}
|
||||
{template === 'castform' && <Castform data={state} />}
|
||||
{template === 'glalie' && <Glalie data={state} />}
|
||||
{template === 'celebi' && <Celebi data={state} />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import cx from 'classnames';
|
||||
import { graphql, useStaticQuery } from 'gatsby';
|
||||
import GatsbyImage from 'gatsby-image';
|
||||
import React, { memo } from 'react';
|
||||
import { useDispatch, useSelector } from '../../../../contexts/ResumeContext';
|
||||
import templateOptions from '../../../../data/templateOptions';
|
||||
@ -10,6 +12,53 @@ const Templates = () => {
|
||||
const dispatch = useDispatch();
|
||||
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) => {
|
||||
dispatch({
|
||||
type: 'on_input',
|
||||
@ -36,7 +85,13 @@ const Templates = () => {
|
||||
[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>
|
||||
</div>
|
||||
))}
|
||||
|
||||
@ -91,7 +91,13 @@ const ResumeProvider = ({ children }) => {
|
||||
return newState;
|
||||
|
||||
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);
|
||||
return newState;
|
||||
|
||||
|
||||
@ -146,11 +146,15 @@
|
||||
],
|
||||
"castform": [
|
||||
["awards", "certifications", "languages", "hobbies"],
|
||||
["work", "education", "skills", "projects", "references"]
|
||||
["objective", "work", "education", "skills", "projects", "references"]
|
||||
],
|
||||
"glalie": [
|
||||
["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"
|
||||
|
||||
@ -90,11 +90,15 @@
|
||||
],
|
||||
"castform": [
|
||||
["awards", "certifications", "languages", "hobbies"],
|
||||
["work", "education", "skills", "projects", "references"]
|
||||
["objective", "work", "education", "skills", "projects", "references"]
|
||||
],
|
||||
"glalie": [
|
||||
["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": {
|
||||
|
||||
471
src/data/schema/jsonResume.json
Normal file
471
src/data/schema/jsonResume.json
Normal 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"
|
||||
}
|
||||
2755
src/data/schema/reactiveResume.json
Normal file
2755
src/data/schema/reactiveResume.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -2,27 +2,26 @@ const templateOptions = [
|
||||
{
|
||||
id: 'onyx',
|
||||
name: 'Onyx',
|
||||
preview: 'https://source.unsplash.com/random/300x500',
|
||||
},
|
||||
{
|
||||
id: 'pikachu',
|
||||
name: 'Pikachu',
|
||||
preview: 'https://source.unsplash.com/random/301x501',
|
||||
},
|
||||
{
|
||||
id: 'gengar',
|
||||
name: 'Gengar',
|
||||
preview: 'https://source.unsplash.com/random/302x502',
|
||||
},
|
||||
{
|
||||
id: 'castform',
|
||||
name: 'Castform',
|
||||
preview: 'https://source.unsplash.com/random/303x503',
|
||||
},
|
||||
{
|
||||
id: 'glalie',
|
||||
name: 'Glalie',
|
||||
preview: 'https://source.unsplash.com/random/304x504',
|
||||
},
|
||||
{
|
||||
id: 'celebi',
|
||||
name: 'Celebi',
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@ -1,11 +1,15 @@
|
||||
import React, { memo, useContext, useEffect, useState, useRef } from 'react';
|
||||
import { Tooltip } from '@material-ui/core';
|
||||
import ModalContext from '../../contexts/ModalContext';
|
||||
import BaseModal from '../BaseModal';
|
||||
import Ajv from 'ajv';
|
||||
import React, { memo, useContext, useEffect, useRef, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import Button from '../../components/shared/Button';
|
||||
import ModalContext from '../../contexts/ModalContext';
|
||||
import { useDispatch } from '../../contexts/ResumeContext';
|
||||
import reactiveResumeSchema from '../../data/schema/reactiveResume.json';
|
||||
import BaseModal from '../BaseModal';
|
||||
|
||||
const ImportModal = () => {
|
||||
const ajv = new Ajv();
|
||||
const fileInputRef = useRef(null);
|
||||
const [open, setOpen] = useState(false);
|
||||
const dispatch = useDispatch();
|
||||
@ -22,6 +26,11 @@ const ImportModal = () => {
|
||||
const fr = new FileReader();
|
||||
fr.addEventListener('load', () => {
|
||||
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 });
|
||||
setOpen(false);
|
||||
});
|
||||
|
||||
@ -10,6 +10,7 @@ import Glalie from '../../templates/Glalie';
|
||||
import Onyx from '../../templates/Onyx';
|
||||
import Pikachu from '../../templates/Pikachu';
|
||||
import styles from './view.module.css';
|
||||
import Celebi from '../../templates/Celebi';
|
||||
|
||||
const ResumeViewer = ({ id }) => {
|
||||
const [resume, setResume] = useState(null);
|
||||
@ -56,6 +57,7 @@ const ResumeViewer = ({ id }) => {
|
||||
<Castform data={resume} />
|
||||
)}
|
||||
{resume.metadata.template === 'glalie' && <Glalie data={resume} />}
|
||||
{resume.metadata.template === 'celebi' && <Celebi data={resume} />}
|
||||
</div>
|
||||
|
||||
<p className={styles.footer}>
|
||||
|
||||
@ -64,7 +64,7 @@ const Castform = ({ data }) => {
|
||||
>
|
||||
<div className="grid grid-cols-12">
|
||||
<div
|
||||
className="col-span-4 p-5"
|
||||
className="col-span-4 py-8 pr-8 pl-5"
|
||||
style={{
|
||||
color: data.metadata.colors.background,
|
||||
backgroundColor: data.metadata.colors.primary,
|
||||
@ -86,7 +86,7 @@ const Castform = ({ data }) => {
|
||||
})}
|
||||
</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">
|
||||
{layout[1] &&
|
||||
layout[1].map((x) => {
|
||||
|
||||
126
src/templates/Celebi.js
Normal file
126
src/templates/Celebi.js
Normal 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;
|
||||
@ -68,7 +68,7 @@ const Glalie = ({ data }) => {
|
||||
backgroundColor: `rgba(${r}, ${g}, ${b}, 0.1)`,
|
||||
}}
|
||||
>
|
||||
<div className="grid gap-6 p-6">
|
||||
<div className="grid gap-6 text-center p-8">
|
||||
<Profile />
|
||||
<ContactD />
|
||||
|
||||
@ -81,7 +81,7 @@ const Glalie = ({ data }) => {
|
||||
</div>
|
||||
|
||||
<div className="col-span-8">
|
||||
<div className="grid gap-4 p-6">
|
||||
<div className="grid gap-4 p-8">
|
||||
{layout[1] &&
|
||||
layout[1].map((x) => {
|
||||
const Component = Blocks[x];
|
||||
|
||||
@ -32,14 +32,14 @@ const Pikachu = ({ data }) => {
|
||||
<PageContext.Provider value={{ data, heading: HeadingB }}>
|
||||
<div
|
||||
id="page"
|
||||
className="p-6 rounded"
|
||||
className="p-8 rounded"
|
||||
style={{
|
||||
fontFamily: data.metadata.font,
|
||||
color: data.metadata.colors.text,
|
||||
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 && (
|
||||
<div className="self-center col-span-4">
|
||||
<img
|
||||
|
||||
@ -7,7 +7,7 @@ import { safetyCheck } from '../../../utils';
|
||||
const AwardItem = (x) => (
|
||||
<div key={x.id}>
|
||||
<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>
|
||||
<span className="text-xs">{x.awarder}</span>
|
||||
</div>
|
||||
|
||||
@ -7,7 +7,7 @@ import { safetyCheck } from '../../../utils';
|
||||
const CertificationItem = (x) => (
|
||||
<div key={x.id}>
|
||||
<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>
|
||||
<span className="text-xs">{x.issuer}</span>
|
||||
</div>
|
||||
|
||||
@ -18,7 +18,7 @@ const ContactItem = ({ value, label, link }) => {
|
||||
) : null;
|
||||
};
|
||||
|
||||
const ContactC = () => {
|
||||
const ContactD = () => {
|
||||
const { data } = useContext(PageContext);
|
||||
|
||||
return (
|
||||
@ -80,4 +80,4 @@ const ContactC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(ContactC);
|
||||
export default memo(ContactD);
|
||||
|
||||
68
src/templates/blocks/Contact/ContactE.js
Normal file
68
src/templates/blocks/Contact/ContactE.js
Normal 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);
|
||||
@ -6,7 +6,7 @@ import { formatDateRange, safetyCheck } from '../../../utils';
|
||||
const EducationItem = (x) => (
|
||||
<div key={x.id}>
|
||||
<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>
|
||||
<span className="text-xs">
|
||||
<strong>{x.degree}</strong> {x.field}
|
||||
|
||||
11
src/templates/blocks/Heading/HeadingE.js
Normal file
11
src/templates/blocks/Heading/HeadingE.js
Normal 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);
|
||||
23
src/templates/blocks/Languages/LanguagesB.js
Normal file
23
src/templates/blocks/Languages/LanguagesB.js
Normal 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);
|
||||
@ -7,7 +7,7 @@ import { safetyCheck } from '../../../utils';
|
||||
const ProjectItem = (x) => (
|
||||
<div key={x.id}>
|
||||
<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>
|
||||
{x.link && (
|
||||
<a href={x.link} className="text-xs">
|
||||
|
||||
@ -6,7 +6,7 @@ import { formatDateRange, safetyCheck } from '../../../utils';
|
||||
const WorkItem = (x) => (
|
||||
<div key={x.id}>
|
||||
<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>
|
||||
<span className="text-xs">{x.position}</span>
|
||||
</div>
|
||||
|
||||
BIN
static/images/templates/castform.png
Normal file
BIN
static/images/templates/castform.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 151 KiB |
BIN
static/images/templates/celebi.png
Normal file
BIN
static/images/templates/celebi.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 163 KiB |
BIN
static/images/templates/gengar.png
Normal file
BIN
static/images/templates/gengar.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 146 KiB |
BIN
static/images/templates/glalie.png
Normal file
BIN
static/images/templates/glalie.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 150 KiB |
BIN
static/images/templates/onyx.png
Normal file
BIN
static/images/templates/onyx.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 124 KiB |
BIN
static/images/templates/pikachu.png
Normal file
BIN
static/images/templates/pikachu.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 148 KiB |
Reference in New Issue
Block a user