-
-
- {templates.find(x => theme.layout.toLowerCase() === x.key).component()}
-
+
+
+
+ {templates.find(x => theme.layout.toLowerCase() === x.key).component()}
+
+
+
+
diff --git a/src/components/LeftSidebar/tabs/Awards.js b/src/components/LeftSidebar/tabs/Awards.js
index 2b9a61c6..1e584f79 100644
--- a/src/components/LeftSidebar/tabs/Awards.js
+++ b/src/components/LeftSidebar/tabs/Awards.js
@@ -13,7 +13,6 @@ import AddItemButton from '../../../shared/AddItemButton';
import ItemHeading from '../../../shared/ItemHeading';
const AwardsTab = ({ data, onChange }) => {
- const { t } = useTranslation();
const context = useContext(AppContext);
const { dispatch } = context;
@@ -28,7 +27,7 @@ const AwardsTab = ({ data, onChange }) => {
onChange('data.awards.heading', v)}
/>
@@ -62,7 +61,7 @@ const Form = ({ item, onChange, identifier = '' }) => {
onChange(`${identifier}title`, v)}
/>
@@ -70,7 +69,7 @@ const Form = ({ item, onChange, identifier = '' }) => {
onChange(`${identifier}subtitle`, v)}
/>
@@ -78,7 +77,6 @@ const Form = ({ item, onChange, identifier = '' }) => {
onChange('data.certifications.heading', v)}
/>
@@ -62,7 +61,7 @@ const Form = ({ item, onChange, identifier = '' }) => {
onChange(`${identifier}title`, v)}
/>
@@ -70,7 +69,7 @@ const Form = ({ item, onChange, identifier = '' }) => {
onChange(`${identifier}subtitle`, v)}
/>
@@ -78,7 +77,6 @@ const Form = ({ item, onChange, identifier = '' }) => {
onChange('data.education.heading', v)}
/>
@@ -62,7 +61,7 @@ const Form = ({ item, onChange, identifier = '' }) => {
onChange(`${identifier}name`, v)}
/>
@@ -70,7 +69,7 @@ const Form = ({ item, onChange, identifier = '' }) => {
onChange(`${identifier}major`, v)}
/>
@@ -87,7 +86,7 @@ const Form = ({ item, onChange, identifier = '' }) => {
onChange(`${identifier}start`, v)}
/>
@@ -95,7 +94,7 @@ const Form = ({ item, onChange, identifier = '' }) => {
onChange(`${identifier}end`, v)}
/>
@@ -105,7 +104,6 @@ const Form = ({ item, onChange, identifier = '' }) => {
rows="5"
className="mb-6"
label={t('app:item.description.label')}
- placeholder={t('education.description.placeholder')}
value={item.description}
onChange={v => onChange(`${identifier}description`, v)}
/>
diff --git a/src/components/LeftSidebar/tabs/Extras.js b/src/components/LeftSidebar/tabs/Extras.js
index 975baae6..f0e99468 100644
--- a/src/components/LeftSidebar/tabs/Extras.js
+++ b/src/components/LeftSidebar/tabs/Extras.js
@@ -12,7 +12,6 @@ import ItemHeading from '../../../shared/ItemHeading';
import AddItemButton from '../../../shared/AddItemButton';
const ExtrasTab = ({ data, onChange }) => {
- const { t } = useTranslation();
const context = useContext(AppContext);
const { dispatch } = context;
@@ -27,7 +26,7 @@ const ExtrasTab = ({ data, onChange }) => {
onChange('data.extras.heading', v)}
/>
@@ -61,7 +60,7 @@ const Form = ({ item, onChange, identifier = '' }) => {
onChange(`${identifier}key`, v)}
/>
@@ -69,7 +68,7 @@ const Form = ({ item, onChange, identifier = '' }) => {
onChange(`${identifier}value`, v)}
/>
diff --git a/src/components/LeftSidebar/tabs/Languages.js b/src/components/LeftSidebar/tabs/Languages.js
index bb9801d3..a2a58b1f 100644
--- a/src/components/LeftSidebar/tabs/Languages.js
+++ b/src/components/LeftSidebar/tabs/Languages.js
@@ -13,7 +13,6 @@ import AddItemButton from '../../../shared/AddItemButton';
import ItemHeading from '../../../shared/ItemHeading';
const LanguagesTab = ({ data, onChange }) => {
- const { t } = useTranslation('app');
const context = useContext(AppContext);
const { dispatch } = context;
@@ -47,7 +46,7 @@ const LanguagesTab = ({ data, onChange }) => {
onChange('data.languages.heading', v)}
/>
@@ -82,7 +81,7 @@ const Form = ({ item, onChange, identifier = '' }) => {
onChange(`${identifier}key`, v)}
/>
diff --git a/src/components/LeftSidebar/tabs/Objective.js b/src/components/LeftSidebar/tabs/Objective.js
index 88fb3a6d..58f76ae3 100644
--- a/src/components/LeftSidebar/tabs/Objective.js
+++ b/src/components/LeftSidebar/tabs/Objective.js
@@ -6,7 +6,7 @@ import TextField from '../../../shared/TextField';
import Checkbox from '../../../shared/Checkbox';
const ObjectiveTab = ({ data, onChange }) => {
- const { t } = useTranslation(['leftSidebar', 'app']);
+ const { t } = useTranslation('leftSidebar');
return (
@@ -19,7 +19,7 @@ const ObjectiveTab = ({ data, onChange }) => {
onChange('data.objective.heading', v)}
/>
@@ -32,8 +32,8 @@ const ObjectiveTab = ({ data, onChange }) => {
rows="15"
className="mb-4"
label={t('objective.objective.label')}
- placeholder={t('objective.objective.placeholder')}
value={data.objective.body}
+ placeholder="Looking for a challenging role in a reputable organization to utilize my technical, database, and management skills for the growth of the organization as well as to enhance my knowledge about new and emerging trends in the IT sector."
onChange={v => onChange('data.objective.body', v)}
/>
diff --git a/src/components/LeftSidebar/tabs/Profile.js b/src/components/LeftSidebar/tabs/Profile.js
index 3d0565e7..2a05a33d 100644
--- a/src/components/LeftSidebar/tabs/Profile.js
+++ b/src/components/LeftSidebar/tabs/Profile.js
@@ -20,7 +20,7 @@ const ProfileTab = ({ data, onChange }) => {
onChange('data.profile.firstName', v)}
/>
@@ -28,7 +28,7 @@ const ProfileTab = ({ data, onChange }) => {
onChange('data.profile.lastName', v)}
/>
@@ -37,7 +37,7 @@ const ProfileTab = ({ data, onChange }) => {
onChange('data.profile.subtitle', v)}
/>
@@ -47,7 +47,7 @@ const ProfileTab = ({ data, onChange }) => {
onChange('data.profile.address.line1', v)}
/>
@@ -55,7 +55,7 @@ const ProfileTab = ({ data, onChange }) => {
onChange('data.profile.address.line2', v)}
/>
@@ -63,7 +63,7 @@ const ProfileTab = ({ data, onChange }) => {
onChange('data.profile.address.line3', v)}
/>
@@ -81,7 +81,7 @@ const ProfileTab = ({ data, onChange }) => {
onChange('data.profile.website', v)}
/>
@@ -89,7 +89,7 @@ const ProfileTab = ({ data, onChange }) => {
onChange('data.profile.email', v)}
/>
diff --git a/src/components/LeftSidebar/tabs/References.js b/src/components/LeftSidebar/tabs/References.js
index 80e09c33..f369eeb3 100644
--- a/src/components/LeftSidebar/tabs/References.js
+++ b/src/components/LeftSidebar/tabs/References.js
@@ -13,7 +13,6 @@ import ItemHeading from '../../../shared/ItemHeading';
import AddItemButton from '../../../shared/AddItemButton';
const ReferencesTab = ({ data, onChange }) => {
- const { t } = useTranslation();
const context = useContext(AppContext);
const { dispatch } = context;
@@ -47,7 +46,7 @@ const ReferencesTab = ({ data, onChange }) => {
onChange('data.references.heading', v)}
/>
@@ -82,7 +81,7 @@ const Form = ({ item, onChange, identifier = '' }) => {
onChange(`${identifier}name`, v)}
/>
@@ -90,7 +89,7 @@ const Form = ({ item, onChange, identifier = '' }) => {
onChange(`${identifier}position`, v)}
/>
@@ -115,7 +114,6 @@ const Form = ({ item, onChange, identifier = '' }) => {
rows="5"
className="mb-6"
label={t('app:item.description.label')}
- placeholder={t('references.description.placeholder')}
value={item.description}
onChange={v => onChange(`${identifier}description`, v)}
/>
diff --git a/src/components/LeftSidebar/tabs/Skills.js b/src/components/LeftSidebar/tabs/Skills.js
index 95ca1503..06d207aa 100644
--- a/src/components/LeftSidebar/tabs/Skills.js
+++ b/src/components/LeftSidebar/tabs/Skills.js
@@ -1,5 +1,4 @@
import React, { useState, useContext } from 'react';
-import { useTranslation } from 'react-i18next';
import AppContext from '../../../context/AppContext';
import Checkbox from '../../../shared/Checkbox';
@@ -8,7 +7,6 @@ import { addItem, deleteItem } from '../../../utils';
import ItemHeading from '../../../shared/ItemHeading';
const SkillsTab = ({ data, onChange }) => {
- const { t } = useTranslation();
const context = useContext(AppContext);
const { dispatch } = context;
@@ -23,7 +21,7 @@ const SkillsTab = ({ data, onChange }) => {
onChange('data.skills.heading', v)}
/>
@@ -42,12 +40,10 @@ const SkillsTab = ({ data, onChange }) => {
};
const Form = ({ item, onChange }) => {
- const { t } = useTranslation('leftSidebar');
-
return (
onChange(e.target.value)}
type="text"
diff --git a/src/components/LeftSidebar/tabs/Work.js b/src/components/LeftSidebar/tabs/Work.js
index 793cc6b7..5a1f3a2e 100644
--- a/src/components/LeftSidebar/tabs/Work.js
+++ b/src/components/LeftSidebar/tabs/Work.js
@@ -13,7 +13,6 @@ import AddItemButton from '../../../shared/AddItemButton';
import ItemHeading from '../../../shared/ItemHeading';
const WorkTab = ({ data, onChange }) => {
- const { t } = useTranslation();
const context = useContext(AppContext);
const { dispatch } = context;
@@ -25,7 +24,7 @@ const WorkTab = ({ data, onChange }) => {
onChange('data.work.heading', v)}
/>
@@ -59,7 +58,7 @@ const Form = ({ item, onChange, identifier = '' }) => {
onChange(`${identifier}title`, v)}
/>
@@ -67,7 +66,7 @@ const Form = ({ item, onChange, identifier = '' }) => {
onChange(`${identifier}role`, v)}
/>
@@ -76,7 +75,7 @@ const Form = ({ item, onChange, identifier = '' }) => {
onChange(`${identifier}start`, v)}
/>
@@ -84,7 +83,7 @@ const Form = ({ item, onChange, identifier = '' }) => {
onChange(`${identifier}end`, v)}
/>
@@ -94,7 +93,6 @@ const Form = ({ item, onChange, identifier = '' }) => {
rows="5"
className="mb-6"
label={t('app:item.description.label')}
- placeholder={t('work.description.placeholder')}
value={item.description}
onChange={v => onChange(`${identifier}description`, v)}
/>
diff --git a/src/components/RightSidebar/tabs/About.js b/src/components/RightSidebar/tabs/About.js
index c58f063a..3509617e 100644
--- a/src/components/RightSidebar/tabs/About.js
+++ b/src/components/RightSidebar/tabs/About.js
@@ -101,7 +101,7 @@ const AboutTab = () => {
- Reactive Resume is a project by
+ Made with Love by
{
>
Amruth Pillai
- .
{t('about.footer.thanks')}
diff --git a/src/components/RightSidebar/tabs/Actions.js b/src/components/RightSidebar/tabs/Actions.js
index d1e8a767..5fdb69ab 100644
--- a/src/components/RightSidebar/tabs/Actions.js
+++ b/src/components/RightSidebar/tabs/Actions.js
@@ -2,60 +2,17 @@
/* eslint-disable jsx-a11y/anchor-has-content */
/* eslint-disable jsx-a11y/anchor-is-valid */
import React, { useRef, useContext } from 'react';
-import { useTranslation, Trans } from 'react-i18next';
-import html2canvas from 'html2canvas';
-import * as jsPDF from 'jspdf';
+import { useTranslation } from 'react-i18next';
import PageContext from '../../../context/PageContext';
+import { importJson, saveAsPdf } from '../../../utils';
const ActionsTab = ({ data, theme, dispatch }) => {
const pageContext = useContext(PageContext);
- const { pageElement } = pageContext;
+ const { pageRef, panZoomRef } = pageContext;
const { t } = useTranslation('rightSidebar');
const fileInputRef = useRef(null);
- const importJson = event => {
- const fr = new FileReader();
- fr.addEventListener('load', () => {
- const importedObject = JSON.parse(fr.result);
- dispatch({ type: 'import_data', payload: importedObject });
- dispatch({ type: 'save_data' });
- });
- fr.readAsText(event.target.files[0]);
- };
-
- const printAsPdf = () => {
- pageElement.current.style.display = 'table';
- pageElement.current.style.overflow = 'visible';
-
- html2canvas(pageElement.current, {
- scale: 5,
- useCORS: true,
- allowTaint: true,
- }).then(canvas => {
- const image = canvas.toDataURL('image/jpeg', 1.0);
- const doc = new jsPDF('p', 'mm', 'a4');
- const pageWidth = doc.internal.pageSize.getWidth();
- const pageHeight = doc.internal.pageSize.getHeight();
-
- const widthRatio = pageWidth / canvas.width;
- const heightRatio = pageHeight / canvas.height;
- const ratio = widthRatio > heightRatio ? heightRatio : widthRatio;
-
- const canvasWidth = canvas.width * ratio;
- const canvasHeight = canvas.height * ratio;
-
- const marginX = (pageWidth - canvasWidth) / 2;
- const marginY = (pageHeight - canvasHeight) / 2;
-
- pageElement.current.style.display = 'block';
- pageElement.current.style.overflow = 'scroll';
-
- doc.addImage(image, 'JPEG', marginX, marginY, canvasWidth, canvasHeight, null, 'SLOW');
- doc.save(`RxResume_${Date.now()}.pdf`);
- });
- };
-
const exportToJson = () => {
const backupObj = { data, theme };
const dataStr = `data:text/json;charset=utf-8,${encodeURIComponent(JSON.stringify(backupObj))}`;
@@ -86,7 +43,12 @@ const ActionsTab = ({ data, theme, dispatch }) => {
{t('actions.importExport.body')}
-
+
importJson(e, dispatch)}
+ />
@@ -117,39 +79,19 @@ const ActionsTab = ({ data, theme, dispatch }) => {
-
{t('actions.printResume.heading')}
+
{t('actions.downloadResume.heading')}
+
{t('actions.downloadResume.body')}
-
-
- You can click on the button below to generate a PDF instantly. Alternatively, you can
- also use Cmd/Ctrl + P but it would have
- different effects.
-
-
-
-
-
-
- import_export
- {t('actions.printResume.buttons.export')}
-
-
-
-
-
- print
- {t('actions.printResume.buttons.print')}
-
-
-
+
saveAsPdf(pageRef, panZoomRef)}
+ className="mt-4 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium py-2 px-5 rounded"
+ >
+
+ save
+ {t('actions.downloadResume.buttons.saveAsPdf')}
+
+
diff --git a/src/context/PageContext.js b/src/context/PageContext.js
index 8085b6e3..7cd29667 100644
--- a/src/context/PageContext.js
+++ b/src/context/PageContext.js
@@ -4,12 +4,16 @@ const PageContext = React.createContext(null);
const { Provider } = PageContext;
const StateProvider = ({ children }) => {
- const [pageElement, setPageElement] = useState(null);
+ const [panZoomRef, setPanZoomRef] = useState(null);
+ const [pageRef, setPageRef] = useState(null);
+
return (
{children}
diff --git a/src/i18n/source/app/app.json b/src/i18n/source/app/app.json
index 861e3ad5..d491a136 100644
--- a/src/i18n/source/app/app.json
+++ b/src/i18n/source/app/app.json
@@ -1,16 +1,11 @@
{
- "heading": {
- "placeholder": "Heading"
- },
"item": {
"add": "Add {{- heading}}",
"startDate": {
- "label": "Start Date",
- "placeholder": "March 2018"
+ "label": "Start Date"
},
"endDate": {
- "label": "End Date",
- "placeholder": "March 2022"
+ "label": "End Date"
},
"description": {
"label": "Description"
diff --git a/src/i18n/source/index.js b/src/i18n/source/index.js
index 943ca673..d96f4262 100644
--- a/src/i18n/source/index.js
+++ b/src/i18n/source/index.js
@@ -3,7 +3,9 @@ import leftSidebar from './leftSidebar';
import rightSidebar from './rightSidebar';
export default {
- app,
- leftSidebar,
- rightSidebar,
+ en: {
+ app,
+ leftSidebar,
+ rightSidebar,
+ },
};
diff --git a/src/i18n/source/leftSidebar/awards.json b/src/i18n/source/leftSidebar/awards.json
index 4222ec12..4a52c12a 100644
--- a/src/i18n/source/leftSidebar/awards.json
+++ b/src/i18n/source/leftSidebar/awards.json
@@ -1,13 +1,8 @@
{
"title": {
- "label": "Title",
- "placeholder": "Math & Science Olympiad"
+ "label": "Title"
},
"subtitle": {
- "label": "Subtitle",
- "placeholder": "First Place, International Level"
- },
- "description": {
- "placeholder": "You can write about what qualities made you succeed in getting this award."
+ "label": "Subtitle"
}
}
diff --git a/src/i18n/source/leftSidebar/certifications.json b/src/i18n/source/leftSidebar/certifications.json
index 92f9dc16..e6e0effa 100644
--- a/src/i18n/source/leftSidebar/certifications.json
+++ b/src/i18n/source/leftSidebar/certifications.json
@@ -1,13 +1,8 @@
{
"title": {
- "label": "Title",
- "placeholder": "Android Development Nanodegree"
+ "label": "Name"
},
"subtitle": {
- "label": "Subtitle",
- "placeholder": "Udacity"
- },
- "description": {
- "placeholder": "You can write about what you learned from your certification program."
+ "label": "Authority"
}
}
diff --git a/src/i18n/source/leftSidebar/education.json b/src/i18n/source/leftSidebar/education.json
index 231004b2..346748c7 100644
--- a/src/i18n/source/leftSidebar/education.json
+++ b/src/i18n/source/leftSidebar/education.json
@@ -1,16 +1,11 @@
{
"name": {
- "label": "Name",
- "placeholder": "Harvard University"
+ "label": "Name"
},
"major": {
- "label": "Major",
- "placeholder": "Masters in Computer Science"
+ "label": "Major"
},
"grade": {
"label": "Grade"
- },
- "description": {
- "placeholder": "You can write about projects or special credit classes that you took while studying at this school."
}
}
diff --git a/src/i18n/source/leftSidebar/extras.json b/src/i18n/source/leftSidebar/extras.json
index 7afc7c06..59950d61 100644
--- a/src/i18n/source/leftSidebar/extras.json
+++ b/src/i18n/source/leftSidebar/extras.json
@@ -1,10 +1,8 @@
{
"key": {
- "label": "Key",
- "placeholder": "Date of Birth"
+ "label": "Key"
},
"value": {
- "label": "Value",
- "placeholder": "6th August 1995"
+ "label": "Value"
}
}
diff --git a/src/i18n/source/leftSidebar/index.js b/src/i18n/source/leftSidebar/index.js
index a13d6a3e..fea53733 100644
--- a/src/i18n/source/leftSidebar/index.js
+++ b/src/i18n/source/leftSidebar/index.js
@@ -4,7 +4,6 @@ import work from './work.json';
import education from './education.json';
import awards from './awards.json';
import certifications from './certifications.json';
-import skills from './skills.json';
import languages from './languages.json';
import references from './references.json';
import extras from './extras.json';
@@ -16,7 +15,6 @@ export default {
education,
awards,
certifications,
- skills,
languages,
references,
extras,
diff --git a/src/i18n/source/leftSidebar/languages.json b/src/i18n/source/leftSidebar/languages.json
index fc5de101..c0167dd7 100644
--- a/src/i18n/source/leftSidebar/languages.json
+++ b/src/i18n/source/leftSidebar/languages.json
@@ -1,7 +1,6 @@
{
"key": {
- "label": "Key",
- "placeholder": "Dothraki"
+ "label": "Name"
},
"rating": {
"label": "Rating"
diff --git a/src/i18n/source/leftSidebar/objective.json b/src/i18n/source/leftSidebar/objective.json
index 8cb4f70d..32980479 100644
--- a/src/i18n/source/leftSidebar/objective.json
+++ b/src/i18n/source/leftSidebar/objective.json
@@ -1,6 +1,5 @@
{
"objective": {
- "label": "Objective",
- "placeholder": "Looking for a challenging role in a reputable organization to utilize my technical, database, and management skills for the growth of the organization as well as to enhance my knowledge about new and emerging trends in the IT sector."
+ "label": "Objective"
}
}
diff --git a/src/i18n/source/leftSidebar/profile.json b/src/i18n/source/leftSidebar/profile.json
index b7f889c2..6f109ed6 100644
--- a/src/i18n/source/leftSidebar/profile.json
+++ b/src/i18n/source/leftSidebar/profile.json
@@ -3,29 +3,24 @@
"label": "Photo URL"
},
"firstName": {
- "label": "First Name",
- "placeholder": "Jane"
+ "label": "First Name"
},
"lastName": {
- "label": "Last Name",
- "placeholder": "Doe"
+ "label": "Last Name"
},
"subtitle": {
- "label": "Subtitle",
- "placeholder": "Full Stack Web Developer"
+ "label": "Subtitle"
},
"address": {
+ "label": "Address",
"line1": {
- "label": "Address Line 1",
- "placeholder": "Palladium Complex"
+ "label": "Address Line 1"
},
"line2": {
- "label": "Address Line 2",
- "placeholder": "140 E 14th St"
+ "label": "Address Line 2"
},
"line3": {
- "label": "Address Line 3",
- "placeholder": "New York, NY 10003 USA"
+ "label": "Address Line 3"
}
},
"phone": {
diff --git a/src/i18n/source/leftSidebar/references.json b/src/i18n/source/leftSidebar/references.json
index 88241575..f7f2bf83 100644
--- a/src/i18n/source/leftSidebar/references.json
+++ b/src/i18n/source/leftSidebar/references.json
@@ -1,19 +1,14 @@
{
"name": {
- "label": "Name",
- "placeholder": "Richard Hendricks"
+ "label": "Name"
},
"position": {
- "label": "Position",
- "placeholder": "CEO, Pied Piper"
+ "label": "Position"
},
"phone": {
"label": "Phone Number"
},
"email": {
"label": "Email Address"
- },
- "description": {
- "placeholder": "You can write about how you and the reference contact worked together and which projects you were a part of."
}
}
diff --git a/src/i18n/source/leftSidebar/skills.json b/src/i18n/source/leftSidebar/skills.json
deleted file mode 100644
index 5f178d9b..00000000
--- a/src/i18n/source/leftSidebar/skills.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "item": {
- "placeholder": "Cooking"
- }
-}
diff --git a/src/i18n/source/leftSidebar/work.json b/src/i18n/source/leftSidebar/work.json
index 6d115c6e..9859754c 100644
--- a/src/i18n/source/leftSidebar/work.json
+++ b/src/i18n/source/leftSidebar/work.json
@@ -1,13 +1,8 @@
{
"name": {
- "label": "Name",
- "placeholder": "Amazon"
+ "label": "Name"
},
"role": {
- "label": "Role",
- "placeholder": "Front-end Web Developer"
- },
- "description": {
- "placeholder": "You can write about what you specialized in while working at the company and what projects you were a part of."
+ "label": "Role"
}
}
diff --git a/src/i18n/source/rightSidebar/about.json b/src/i18n/source/rightSidebar/about.json
index cac678ad..1bde4c1c 100644
--- a/src/i18n/source/rightSidebar/about.json
+++ b/src/i18n/source/rightSidebar/about.json
@@ -2,7 +2,7 @@
"title": "About",
"documentation": {
"heading": "Documentation",
- "body": "Want to know more about the app? Wouldn't it be nice if there was a guide to setting it up on your local machine? Need information on how to contribute to the project? Look no further, there's comprehensive documentation made just for you.",
+ "body": "Want to know more about the app? Need information on how to contribute to the project? Look no further, there's comprehensive guide made just for you.",
"buttons": {
"documentation": "Documentation"
}
@@ -30,7 +30,7 @@
}
},
"footer": {
- "credit": "Reactive Resume is a project by <1>Amruth Pillai1>.",
+ "credit": "Made with Love by <1>Amruth Pillai1>",
"thanks": "Thank you for using Reactive Resume!"
}
}
diff --git a/src/i18n/source/rightSidebar/actions.json b/src/i18n/source/rightSidebar/actions.json
index b6818714..ae75bbd1 100644
--- a/src/i18n/source/rightSidebar/actions.json
+++ b/src/i18n/source/rightSidebar/actions.json
@@ -9,12 +9,11 @@
"export": "Export"
}
},
- "printResume": {
- "heading": "Print Your Resume",
- "body": "You can click on the button below to generate a PDF instantly. Alternatively, you can also use <1>Cmd/Ctrl + P1> but it would have different effects.",
+ "downloadResume": {
+ "heading": "Download Your Resume",
+ "body": "You can click on the button below to download a PDF version of your resume instantly. For best results, please use the latest version of Google Chrome.",
"buttons": {
- "export": "Export",
- "print": "Print"
+ "saveAsPdf": "Save as PDF"
}
},
"loadDemoData": {
diff --git a/src/i18n/source/rightSidebar/colors.json b/src/i18n/source/rightSidebar/colors.json
index bf4accbf..f7fff7ba 100644
--- a/src/i18n/source/rightSidebar/colors.json
+++ b/src/i18n/source/rightSidebar/colors.json
@@ -2,6 +2,6 @@
"title": "Colors",
"colorOptions": "Color Options",
"primaryColor": "Primary Color",
- "accentColor": "Accent Color",
+ "accentColor": "Secondary Color",
"clipboardCopyAction": "{{color}} has been copied to the clipboard."
}
diff --git a/src/index.css b/src/index.css
index a9361314..c578f62e 100644
--- a/src/index.css
+++ b/src/index.css
@@ -8,6 +8,15 @@
@import url('https://fonts.googleapis.com/css2?family=Titillium+Web:wght@400;600;700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Ubuntu:wght@400;500;700&display=swap');
+* {
+ -ms-overflow-style: none;
+ scrollbar-width: none;
+}
+
+*::-webkit-scrollbar {
+ display: none;
+}
+
html,
body {
height: 100%;
@@ -54,25 +63,21 @@ ul li {
#tabs {
scroll-behavior: smooth;
- scrollbar-width: none;
- -ms-overflow-style: none;
- }
-
- #tabs::-webkit-scrollbar {
- width: 0px;
- height: 0px;
- background: transparent;
}
#page {
width: 21cm;
min-height: 29.7cm;
- max-height: 29.7cm;
- transform: scale(0.8);
- transform-origin: center;
- overflow: scroll;
background-color: white;
}
+
+ #pageController {
+ bottom: 25px;
+ }
+
+ #pageController > div {
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
+ }
}
@page {
diff --git a/src/shared/PageController.js b/src/shared/PageController.js
new file mode 100644
index 00000000..46f8e69a
--- /dev/null
+++ b/src/shared/PageController.js
@@ -0,0 +1,58 @@
+import React, { useContext } from 'react';
+import PageContext from '../context/PageContext';
+import { saveAsPdf } from '../utils';
+
+const PageController = () => {
+ const pageContext = useContext(PageContext);
+ const { pageRef, panZoomRef } = pageContext;
+
+ const zoomIn = () => panZoomRef.current.zoomIn(2);
+ const zoomOut = () => panZoomRef.current.zoomOut(2);
+ const centerReset = () => {
+ panZoomRef.current.autoCenter(1);
+ panZoomRef.current.reset(1);
+ };
+
+ return (
+
+
+
+ zoom_in
+
+
+
+ zoom_out
+
+
+
+ center_focus_strong
+
+
+
|
+
+
saveAsPdf(pageRef, panZoomRef)}
+ >
+ save
+
+
+
|
+
+
+ help_outline
+
+
+
+ );
+};
+
+export default PageController;
diff --git a/src/templates/gengar/Gengar.js b/src/templates/gengar/Gengar.js
index 59961330..dcd0bd1a 100644
--- a/src/templates/gengar/Gengar.js
+++ b/src/templates/gengar/Gengar.js
@@ -117,7 +117,7 @@ const Gengar = () => {
{x.title}
{x.subtitle}
-
+
);
diff --git a/src/templates/glalie/Glalie.js b/src/templates/glalie/Glalie.js
new file mode 100644
index 00000000..98bda52c
--- /dev/null
+++ b/src/templates/glalie/Glalie.js
@@ -0,0 +1,298 @@
+import React, { useContext } from 'react';
+import ReactMarkdown from 'react-markdown';
+
+import AppContext from '../../context/AppContext';
+import { hexToRgb } from '../../utils';
+
+const Glalie = () => {
+ const context = useContext(AppContext);
+ const { state } = context;
+ const { data, theme } = state;
+
+ const { r, g, b } = hexToRgb(theme.colors.accent) || {};
+
+ const Photo = () =>
+ data.profile.photo !== '' && (
+
+ );
+
+ const FullName = () => (
+
+
{data.profile.firstName}
+ {data.profile.lastName}
+
+ );
+
+ const Subtitle = () => (
+ {data.profile.subtitle}
+ );
+
+ const Divider = () => (
+
+ );
+
+ const ContactItem = ({ title, value }) =>
+ value && (
+
+
+ {title}
+
+
{value}
+
+ );
+
+ const ContactInformation = () => (
+
+
+
+ flare
+
+
+
+
+
+
+
+
+
+
+ home
+
+
{data.profile.address.line1}
+
{data.profile.address.line2}
+
{data.profile.address.line3}
+
+
+
+ );
+
+ const Heading = ({ title }) => (
+
+ {title}
+
+ );
+
+ const Objective = () =>
+ data.objective.enable && (
+
+
+
{data.objective.body}
+
+ );
+
+ const WorkItem = x => (
+
+
+
+
{x.title}
+
+ {x.role} / {x.start} - {x.end}
+
+
+
+
+
+ );
+
+ const Work = () =>
+ data.work &&
+ data.work.enable && (
+
+
+ {data.work.items.filter(x => x.enable).map(WorkItem)}
+
+ );
+
+ const EducationItem = x => (
+
+
+
{x.name}
+
{x.major}
+
+ {x.start} - {x.end}
+
+
+
+
+ );
+
+ const Education = () =>
+ data.education &&
+ data.education.enable && (
+
+
+
+ {data.education.items.filter(x => x.enable).map(EducationItem)}
+
+
+ );
+
+ const AwardItem = x => (
+
+
{x.title}
+
{x.subtitle}
+
+
+ );
+
+ const Awards = () =>
+ data.awards &&
+ data.awards.enable && (
+
+
+ {data.awards.items.filter(x => x.enable).map(AwardItem)}
+
+ );
+
+ const CertificationItem = x => (
+
+
{x.title}
+
{x.subtitle}
+
+
+ );
+
+ const Certifications = () =>
+ data.certifications &&
+ data.certifications.enable && (
+
+
+ {data.certifications.items.filter(x => x.enable).map(CertificationItem)}
+
+ );
+
+ const SkillItem = x => (
+
+ {x}
+
+ );
+
+ const Skills = () =>
+ data.skills &&
+ data.skills.enable && (
+
+
+
{data.skills.items.map(SkillItem)}
+
+ );
+
+ const LanguageItem = x => (
+
+
{x.key}
+
+ {Array.from(Array(x.value)).map((_, i) => (
+
+ star
+
+ ))}
+
+
+ );
+
+ const Languages = () =>
+ data.languages &&
+ data.languages.enable && (
+
+
+
{data.languages.items.filter(x => x.enable).map(LanguageItem)}
+
+ );
+
+ const ReferenceItem = x => (
+
+
{x.name}
+ {x.position}
+ {x.phone}
+ {x.email}
+
+
+ );
+
+ const References = () =>
+ data.references &&
+ data.references.enable && (
+
+
+
+ {data.references.items.filter(x => x.enable).map(ReferenceItem)}
+
+
+ );
+
+ const ExtraItem = x => (
+
+ {x.key}
+ {x.value}
+
+ );
+
+ const Extras = () =>
+ data.extras &&
+ data.extras.enable && (
+
+
+
+ {data.extras.items.filter(x => x.enable).map(ExtraItem)}
+
+
+ );
+
+ return (
+
+ );
+};
+
+export default Glalie;
diff --git a/src/templates/glalie/index.js b/src/templates/glalie/index.js
new file mode 100644
index 00000000..10e38686
--- /dev/null
+++ b/src/templates/glalie/index.js
@@ -0,0 +1,5 @@
+import Glalie from './Glalie';
+import image from './preview.png';
+
+export const Image = image;
+export default Glalie;
diff --git a/src/templates/glalie/preview.png b/src/templates/glalie/preview.png
new file mode 100644
index 00000000..cd69f7ed
Binary files /dev/null and b/src/templates/glalie/preview.png differ
diff --git a/src/templates/index.js b/src/templates/index.js
index 5b42cad5..825dc875 100644
--- a/src/templates/index.js
+++ b/src/templates/index.js
@@ -2,6 +2,7 @@ import Onyx, { Image as OnyxPreview } from './onyx';
import Pikachu, { Image as PikachuPreview } from './pikachu';
import Gengar, { Image as GengarPreview } from './gengar';
import Castform, { Image as CastformPreview } from './castform';
+import Glalie, { Image as GlaliePreview } from './glalie';
export default [
{
@@ -28,4 +29,10 @@ export default [
component: Castform,
preview: CastformPreview,
},
+ {
+ key: 'glalie',
+ name: 'Glalie',
+ component: Glalie,
+ preview: GlaliePreview,
+ },
];
diff --git a/src/utils/index.js b/src/utils/index.js
index 52b08076..135ccd85 100644
--- a/src/utils/index.js
+++ b/src/utils/index.js
@@ -1,3 +1,7 @@
+/* eslint-disable new-cap */
+import html2canvas from 'html2canvas';
+import * as jsPDF from 'jspdf';
+
const move = (array, element, delta) => {
const index = array.indexOf(element);
const newIndex = index + delta;
@@ -90,4 +94,58 @@ const moveItemDown = (dispatch, key, value) => {
saveData(dispatch);
};
-export { move, hexToRgb, copyToClipboard, saveData, addItem, deleteItem, moveItemUp, moveItemDown };
+const importJson = (event, dispatch) => {
+ const fr = new FileReader();
+ fr.addEventListener('load', () => {
+ const importedObject = JSON.parse(fr.result);
+ dispatch({ type: 'import_data', payload: importedObject });
+ dispatch({ type: 'save_data' });
+ });
+ fr.readAsText(event.target.files[0]);
+};
+
+const saveAsPdf = (pageRef, panZoomRef) => {
+ panZoomRef.current.autoCenter(1);
+ panZoomRef.current.reset();
+
+ setTimeout(() => {
+ html2canvas(pageRef.current, {
+ scale: 5,
+ useCORS: true,
+ allowTaint: true,
+ }).then(canvas => {
+ const image = canvas.toDataURL('image/jpeg', 1.0);
+ const doc = new jsPDF('p', 'mm', 'a4');
+ const pageWidth = doc.internal.pageSize.getWidth();
+ const pageHeight = doc.internal.pageSize.getHeight();
+
+ const widthRatio = pageWidth / canvas.width;
+ const heightRatio = pageHeight / canvas.height;
+ const ratio = widthRatio > heightRatio ? heightRatio : widthRatio;
+
+ const canvasWidth = canvas.width * ratio;
+ const canvasHeight = canvas.height * ratio;
+
+ const marginX = (pageWidth - canvasWidth) / 2;
+ const marginY = (pageHeight - canvasHeight) / 2;
+
+ panZoomRef.current.autoCenter(0.7);
+
+ doc.addImage(image, 'JPEG', marginX, marginY, canvasWidth, canvasHeight, null, 'SLOW');
+ doc.save(`RxResume_${Date.now()}.pdf`);
+ });
+ }, 250);
+};
+
+export {
+ move,
+ hexToRgb,
+ copyToClipboard,
+ saveData,
+ addItem,
+ deleteItem,
+ moveItemUp,
+ moveItemDown,
+ importJson,
+ saveAsPdf,
+};