clearing the slate

This commit is contained in:
Amruth Pillai
2020-07-02 21:23:03 +05:30
parent 58f0cc7f30
commit d2e3227d01
912 changed files with 0 additions and 38944 deletions

View File

@ -1,74 +0,0 @@
/* eslint-disable jsx-a11y/media-has-caption */
import React, { useRef, useEffect, useContext, Suspense } from 'react';
import { useTranslation } from 'react-i18next';
import { PanZoom } from 'react-easy-panzoom';
import AppContext from '../../context/AppContext';
import PageContext from '../../context/PageContext';
import LeftSidebar from '../LeftSidebar/LeftSidebar';
import RightSidebar from '../RightSidebar/RightSidebar';
import templates from '../../templates';
import PageController from '../../shared/PageController';
import PrintDialog from '../../shared/PrintDialog';
import PanZoomAnimation from '../../shared/PanZoomAnimation';
const App = () => {
const pageRef = useRef(null);
const panZoomRef = useRef(null);
const { i18n } = useTranslation();
const context = useContext(AppContext);
const { state, dispatch } = context;
const { theme, settings } = state;
const pageContext = useContext(PageContext);
const { setPageRef, setPanZoomRef } = pageContext;
useEffect(() => {
setPageRef(pageRef);
setPanZoomRef(panZoomRef);
i18n.changeLanguage(settings.language);
const storedState = JSON.parse(localStorage.getItem('state'));
dispatch({ type: 'import_data', payload: storedState });
}, [dispatch, setPageRef, setPanZoomRef, i18n, settings.language]);
return (
<Suspense fallback="Loading...">
<div className="h-screen grid grid-cols-5 items-center">
<LeftSidebar />
<div className="relative z-10 h-screen overflow-hidden col-span-3 flex justify-center items-center">
<PanZoom
ref={panZoomRef}
minZoom="0.4"
autoCenter
autoCenterZoomLevel={0.7}
enableBoundingBox
boundaryRatioVertical={0.8}
boundaryRatioHorizontal={0.8}
style={{ outline: 'none' }}
>
<div id="page" ref={pageRef} className="shadow-2xl break-words">
{templates.find(x => theme.layout.toLowerCase() === x.key).component()}
</div>
</PanZoom>
<PageController />
</div>
<div id="printPage" className="break-words">
{templates.find(x => theme.layout.toLowerCase() === x.key).component()}
</div>
<RightSidebar />
<PanZoomAnimation />
<PrintDialog />
</div>
</Suspense>
);
};
export default App;

View File

@ -1,88 +0,0 @@
import React, { useState, useContext } from 'react';
import AppContext from '../../context/AppContext';
import TabBar from '../../shared/TabBar';
import ProfileTab from './tabs/Profile';
import ObjectiveTab from './tabs/Objective';
import WorkTab from './tabs/Work';
import EducationTab from './tabs/Education';
import AwardsTab from './tabs/Awards';
import CertificationsTab from './tabs/Certifications';
import SkillsTab from './tabs/Skills';
import ExtrasTab from './tabs/Extras';
import LanguagesTab from './tabs/Languages';
import ReferencesTab from './tabs/References';
import HobbiesTab from './tabs/Hobbies';
const LeftSidebar = () => {
const context = useContext(AppContext);
const { state, dispatch } = context;
const { data } = state;
const tabs = [
{ key: 'profile', name: data.profile.heading },
{ key: 'objective', name: data.objective.heading },
{ key: 'work', name: data.work.heading },
{ key: 'education', name: data.education.heading },
{ key: 'awards', name: data.awards.heading },
{ key: 'certifications', name: data.certifications.heading },
{ key: 'skills', name: data.skills.heading },
{ key: 'hobbies', name: data.hobbies.heading },
{ key: 'languages', name: data.languages.heading },
{ key: 'references', name: data.references.heading },
{ key: 'extras', name: data.extras.heading },
];
const [currentTab, setCurrentTab] = useState(tabs[0].key);
const onChange = (key, value) => {
dispatch({
type: 'on_input',
payload: {
key,
value,
},
});
dispatch({ type: 'save_data' });
};
const renderTabs = () => {
switch (currentTab) {
case 'profile':
return <ProfileTab data={data} onChange={onChange} />;
case 'objective':
return <ObjectiveTab data={data} onChange={onChange} />;
case 'work':
return <WorkTab data={data} onChange={onChange} />;
case 'education':
return <EducationTab data={data} onChange={onChange} />;
case 'awards':
return <AwardsTab data={data} onChange={onChange} />;
case 'certifications':
return <CertificationsTab data={data} onChange={onChange} />;
case 'skills':
return <SkillsTab data={data} onChange={onChange} />;
case 'hobbies':
return <HobbiesTab data={data} onChange={onChange} />;
case 'languages':
return <LanguagesTab data={data} onChange={onChange} />;
case 'references':
return <ReferencesTab data={data} onChange={onChange} />;
case 'extras':
return <ExtrasTab data={data} onChange={onChange} />;
default:
return null;
}
};
return (
<div
id="leftSidebar"
className="animated slideInLeft z-10 py-6 h-screen bg-white col-span-1 shadow-2xl overflow-y-scroll"
>
<TabBar tabs={tabs} currentTab={currentTab} setCurrentTab={setCurrentTab} />
<div className="px-6">{renderTabs()}</div>
</div>
);
};
export default LeftSidebar;

View File

@ -1,153 +0,0 @@
import React, { useState, useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { v4 as uuidv4 } from 'uuid';
import set from 'lodash/set';
import TextField from '../../../shared/TextField';
import AppContext from '../../../context/AppContext';
import Checkbox from '../../../shared/Checkbox';
import TextArea from '../../../shared/TextArea';
import { addItem } from '../../../utils';
import ItemActions from '../../../shared/ItemActions';
import AddItemButton from '../../../shared/AddItemButton';
import ItemHeading from '../../../shared/ItemHeading';
const AwardsTab = ({ data, onChange }) => {
const context = useContext(AppContext);
const { dispatch } = context;
return (
<>
<div className="mb-6 grid grid-cols-6 items-center">
<div className="col-span-1">
<Checkbox
checked={data.awards.enable}
onChange={v => onChange('data.awards.enable', v)}
/>
</div>
<div className="col-span-5">
<TextField
placeholder="Heading"
value={data.awards.heading}
onChange={v => onChange('data.awards.heading', v)}
/>
</div>
</div>
<hr className="my-6" />
{data.awards.items.map((x, index) => (
<Item
item={x}
key={x.id}
index={index}
onChange={onChange}
dispatch={dispatch}
first={index === 0}
last={index === data.awards.items.length - 1}
/>
))}
<AddItem heading={data.awards.heading} dispatch={dispatch} />
</>
);
};
const Form = ({ item, onChange, identifier = '' }) => {
const { t } = useTranslation(['leftSidebar', 'app']);
return (
<div>
<TextField
className="mb-6"
label={t('awards.title.label')}
placeholder="Code For Good Hackathon"
value={item.title}
onChange={v => onChange(`${identifier}title`, v)}
/>
<TextField
className="mb-6"
label={t('awards.subtitle.label')}
placeholder="First Place, National Level"
value={item.subtitle}
onChange={v => onChange(`${identifier}subtitle`, v)}
/>
<TextArea
className="mb-6"
label={t('app:item.description.label')}
value={item.description}
onChange={v => onChange(`${identifier}description`, v)}
/>
</div>
);
};
const AddItem = ({ heading, dispatch }) => {
const [isOpen, setOpen] = useState(false);
const [item, setItem] = useState({
id: uuidv4(),
enable: true,
title: '',
subtitle: '',
description: '',
});
const onChange = (key, value) => setItem(set({ ...item }, key, value));
const onSubmit = () => {
if (item.title === '') return;
addItem(dispatch, 'awards', item);
setItem({
id: uuidv4(),
enable: true,
title: '',
subtitle: '',
description: '',
});
setOpen(false);
};
return (
<div className="my-4 border border-gray-200 rounded p-5">
<ItemHeading heading={heading} setOpen={setOpen} isOpen={isOpen} />
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<Form item={item} onChange={onChange} />
<AddItemButton onSubmit={onSubmit} />
</div>
</div>
);
};
const Item = ({ item, index, onChange, dispatch, first, last }) => {
const [isOpen, setOpen] = useState(false);
const identifier = `data.awards.items[${index}].`;
return (
<div className="my-4 border border-gray-200 rounded p-5">
<ItemHeading title={item.title} setOpen={setOpen} isOpen={isOpen} />
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<Form item={item} onChange={onChange} identifier={identifier} />
<ItemActions
dispatch={dispatch}
first={first}
identifier={identifier}
item={item}
last={last}
onChange={onChange}
type="awards"
/>
</div>
</div>
);
};
export default AwardsTab;

View File

@ -1,153 +0,0 @@
import React, { useState, useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { v4 as uuidv4 } from 'uuid';
import set from 'lodash/set';
import TextField from '../../../shared/TextField';
import AppContext from '../../../context/AppContext';
import Checkbox from '../../../shared/Checkbox';
import TextArea from '../../../shared/TextArea';
import { addItem } from '../../../utils';
import ItemActions from '../../../shared/ItemActions';
import ItemHeading from '../../../shared/ItemHeading';
import AddItemButton from '../../../shared/AddItemButton';
const CertificationsTab = ({ data, onChange }) => {
const context = useContext(AppContext);
const { dispatch } = context;
return (
<>
<div className="my-6 grid grid-cols-6 items-center">
<div className="col-span-1">
<Checkbox
checked={data.certifications.enable}
onChange={v => onChange('data.certifications.enable', v)}
/>
</div>
<div className="col-span-5">
<TextField
placeholder="Heading"
value={data.certifications.heading}
onChange={v => onChange('data.certifications.heading', v)}
/>
</div>
</div>
<hr className="my-6" />
{data.certifications.items.map((x, index) => (
<Item
item={x}
key={x.id}
index={index}
onChange={onChange}
dispatch={dispatch}
first={index === 0}
last={index === data.certifications.items.length - 1}
/>
))}
<AddItem heading={data.certifications.heading} dispatch={dispatch} />
</>
);
};
const Form = ({ item, onChange, identifier = '' }) => {
const { t } = useTranslation(['leftSidebar', 'app']);
return (
<div>
<TextField
className="mb-6"
label={t('certifications.title.label')}
placeholder="CS50: Intro to Computer Science"
value={item.title}
onChange={v => onChange(`${identifier}title`, v)}
/>
<TextField
className="mb-6"
label={t('certifications.subtitle.label')}
placeholder="Harvard University"
value={item.subtitle}
onChange={v => onChange(`${identifier}subtitle`, v)}
/>
<TextArea
className="mb-6"
label={t('app:item.description.label')}
value={item.description}
onChange={v => onChange(`${identifier}description`, v)}
/>
</div>
);
};
const AddItem = ({ heading, dispatch }) => {
const [isOpen, setOpen] = useState(false);
const [item, setItem] = useState({
id: uuidv4(),
enable: true,
title: '',
subtitle: '',
description: '',
});
const onChange = (key, value) => setItem(set({ ...item }, key, value));
const onSubmit = () => {
if (item.title === '') return;
addItem(dispatch, 'certifications', item);
setItem({
id: uuidv4(),
enable: true,
title: '',
subtitle: '',
description: '',
});
setOpen(false);
};
return (
<div className="my-4 border border-gray-200 rounded p-5">
<ItemHeading heading={heading} setOpen={setOpen} isOpen={isOpen} />
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<Form item={item} onChange={onChange} />
<AddItemButton onSubmit={onSubmit} />
</div>
</div>
);
};
const Item = ({ item, index, onChange, dispatch, first, last }) => {
const [isOpen, setOpen] = useState(false);
const identifier = `data.certifications.items[${index}].`;
return (
<div className="my-4 border border-gray-200 rounded p-5">
<ItemHeading title={item.title} setOpen={setOpen} isOpen={isOpen} />
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<Form item={item} onChange={onChange} identifier={identifier} />
<ItemActions
dispatch={dispatch}
first={first}
identifier={identifier}
item={item}
last={last}
onChange={onChange}
type="certifications"
/>
</div>
</div>
);
};
export default CertificationsTab;

View File

@ -1,185 +0,0 @@
import React, { useState, useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { v4 as uuidv4 } from 'uuid';
import set from 'lodash/set';
import TextField from '../../../shared/TextField';
import TextArea from '../../../shared/TextArea';
import AppContext from '../../../context/AppContext';
import Checkbox from '../../../shared/Checkbox';
import { addItem } from '../../../utils';
import ItemActions from '../../../shared/ItemActions';
import AddItemButton from '../../../shared/AddItemButton';
import ItemHeading from '../../../shared/ItemHeading';
const EducationTab = ({ data, onChange }) => {
const context = useContext(AppContext);
const { dispatch } = context;
return (
<>
<div className="mb-6 grid grid-cols-6 items-center">
<div className="col-span-1">
<Checkbox
checked={data.education.enable}
onChange={v => onChange('data.education.enable', v)}
/>
</div>
<div className="col-span-5">
<TextField
placeholder="Heading"
value={data.education.heading}
onChange={v => onChange('data.education.heading', v)}
/>
</div>
</div>
<hr className="my-6" />
{data.education.items.map((x, index) => (
<Item
item={x}
key={x.id}
index={index}
onChange={onChange}
dispatch={dispatch}
first={index === 0}
last={index === data.education.items.length - 1}
/>
))}
<AddItem heading={data.education.heading} dispatch={dispatch} />
</>
);
};
const Form = ({ item, onChange, identifier = '' }) => {
const { t } = useTranslation(['leftSidebar', 'app']);
return (
<div>
<TextField
className="mb-6"
label={t('education.name.label')}
placeholder="Harvard University"
value={item.name}
onChange={v => onChange(`${identifier}name`, v)}
/>
<TextField
className="mb-6"
label={t('education.major.label')}
placeholder="Masters in Computer Science"
value={item.major}
onChange={v => onChange(`${identifier}major`, v)}
/>
<TextField
className="mb-6"
label={t('education.grade.label')}
placeholder="7.2 CGPA"
value={item.grade}
onChange={v => onChange(`${identifier}grade`, v)}
/>
<div className="grid grid-cols-2 col-gap-4">
<TextField
className="mb-6"
label={t('app:item.startDate.label')}
placeholder="March 2018"
value={item.start}
onChange={v => onChange(`${identifier}start`, v)}
/>
<TextField
className="mb-6"
label={t('app:item.endDate.label')}
placeholder="June 2022"
value={item.end}
onChange={v => onChange(`${identifier}end`, v)}
/>
</div>
<TextArea
rows="5"
className="mb-6"
label={t('app:item.description.label')}
value={item.description}
onChange={v => onChange(`${identifier}description`, v)}
/>
</div>
);
};
const AddItem = ({ heading, dispatch }) => {
const [isOpen, setOpen] = useState(false);
const [item, setItem] = useState({
id: uuidv4(),
enable: true,
name: '',
major: '',
start: '',
end: '',
grade: '',
description: '',
});
const onChange = (key, value) => setItem(set({ ...item }, key, value));
const onSubmit = () => {
if (item.name === '' || item.major === '') return;
addItem(dispatch, 'education', item);
setItem({
id: uuidv4(),
enable: true,
name: '',
role: '',
start: '',
end: '',
grade: '',
description: '',
});
setOpen(false);
};
return (
<div className="my-4 border border-gray-200 rounded p-5">
<ItemHeading heading={heading} setOpen={setOpen} isOpen={isOpen} />
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<Form item={item} onChange={onChange} />
<AddItemButton onSubmit={onSubmit} />
</div>
</div>
);
};
const Item = ({ item, index, onChange, dispatch, first, last }) => {
const [isOpen, setOpen] = useState(false);
const identifier = `data.education.items[${index}].`;
return (
<div className="my-4 border border-gray-200 rounded p-5">
<ItemHeading title={item.name} setOpen={setOpen} isOpen={isOpen} />
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<Form item={item} onChange={onChange} identifier={identifier} />
<ItemActions
dispatch={dispatch}
first={first}
identifier={identifier}
item={item}
last={last}
onChange={onChange}
type="education"
/>
</div>
</div>
);
};
export default EducationTab;

View File

@ -1,143 +0,0 @@
import React, { useState, useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { v4 as uuidv4 } from 'uuid';
import set from 'lodash/set';
import TextField from '../../../shared/TextField';
import AppContext from '../../../context/AppContext';
import Checkbox from '../../../shared/Checkbox';
import { addItem } from '../../../utils';
import ItemActions from '../../../shared/ItemActions';
import ItemHeading from '../../../shared/ItemHeading';
import AddItemButton from '../../../shared/AddItemButton';
const ExtrasTab = ({ data, onChange }) => {
const context = useContext(AppContext);
const { dispatch } = context;
return (
<>
<div className="mb-6 grid grid-cols-6 items-center">
<div className="col-span-1">
<Checkbox
checked={data.extras.enable}
onChange={v => onChange('data.extras.enable', v)}
/>
</div>
<div className="col-span-5">
<TextField
placeholder="Heading"
value={data.extras.heading}
onChange={v => onChange('data.extras.heading', v)}
/>
</div>
</div>
<hr className="my-6" />
{data.extras.items.map((x, index) => (
<Item
item={x}
key={x.id}
index={index}
onChange={onChange}
dispatch={dispatch}
first={index === 0}
last={index === data.extras.items.length - 1}
/>
))}
<AddItem heading={data.extras.heading} dispatch={dispatch} />
</>
);
};
const Form = ({ item, onChange, identifier = '' }) => {
const { t } = useTranslation('leftSidebar');
return (
<div>
<TextField
className="mb-6"
label={t('extras.key.label')}
placeholder="Date of Birth"
value={item.key}
onChange={v => onChange(`${identifier}key`, v)}
/>
<TextField
className="mb-6"
label={t('extras.value.label')}
placeholder="6th August 1995"
value={item.value}
onChange={v => onChange(`${identifier}value`, v)}
/>
</div>
);
};
const AddItem = ({ heading, dispatch }) => {
const [isOpen, setOpen] = useState(false);
const [item, setItem] = useState({
id: uuidv4(),
enable: true,
key: '',
value: '',
});
const onChange = (key, value) => setItem(items => set({ ...items }, key, value));
const onSubmit = () => {
if (item.key === '' || item.value === '') return;
addItem(dispatch, 'extras', item);
setItem({
id: uuidv4(),
enable: true,
key: '',
value: '',
});
setOpen(false);
};
return (
<div className="my-4 border border-gray-200 rounded p-5">
<ItemHeading heading={heading} setOpen={setOpen} isOpen={isOpen} />
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<Form item={item} onChange={onChange} />
<AddItemButton onSubmit={onSubmit} />
</div>
</div>
);
};
const Item = ({ item, index, onChange, dispatch, first, last }) => {
const [isOpen, setOpen] = useState(false);
const identifier = `data.extras.items[${index}].`;
return (
<div className="my-4 border border-gray-200 rounded p-5">
<ItemHeading title={item.key} setOpen={setOpen} isOpen={isOpen} />
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<Form item={item} onChange={onChange} identifier={identifier} />
<ItemActions
dispatch={dispatch}
first={first}
identifier={identifier}
item={item}
last={last}
onChange={onChange}
type="extras"
/>
</div>
</div>
);
};
export default ExtrasTab;

View File

@ -1,140 +0,0 @@
import React, { useState, useContext } from 'react';
import { v4 as uuidv4 } from 'uuid';
import AppContext from '../../../context/AppContext';
import Checkbox from '../../../shared/Checkbox';
import TextField from '../../../shared/TextField';
import { addItem, deleteItem, moveItemUp, moveItemDown } from '../../../utils';
import ItemHeading from '../../../shared/ItemHeading';
const HobbiesTab = ({ data, onChange }) => {
const context = useContext(AppContext);
const { dispatch } = context;
return (
<>
<div className="my-6 grid grid-cols-6 items-center">
<div className="col-span-1">
<Checkbox
checked={data.hobbies.enable}
onChange={v => onChange('data.hobbies.enable', v)}
/>
</div>
<div className="col-span-5">
<TextField
placeholder="Heading"
value={data.hobbies.heading}
onChange={v => onChange('data.hobbies.heading', v)}
/>
</div>
</div>
<hr className="my-6" />
{data.hobbies.items.map((x, index) => (
<Item item={x} key={index} index={index} onChange={onChange} dispatch={dispatch} />
))}
<AddItem heading={data.hobbies.heading} dispatch={dispatch} />
</>
);
};
const Form = ({ item, onChange }) => {
return (
<input
className="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
placeholder="Beatboxing"
value={item.hobby}
onChange={e => onChange(e.target.value)}
type="text"
/>
);
};
const AddItem = ({ heading, dispatch }) => {
const [isOpen, setOpen] = useState(false);
const [item, setItem] = useState({
id: uuidv4(),
hobby: ''
});
const add = () => {
if (item.hobby === '') return;
addItem(dispatch, 'hobbies', item);
setItem({
id: uuidv4(),
hobby: ''
});
};
return (
<div className="my-4 border border-gray-200 rounded p-5">
<ItemHeading heading={heading} setOpen={setOpen} isOpen={isOpen} />
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<div className="grid grid-cols-4 gap-4">
<div className="col-span-3">
<Form item={item} onChange={v => setItem({...item, hobby: v})} />
</div>
<button
type="button"
onClick={add}
className="col-span-1 bg-gray-600 hover:bg-gray-700 text-sm font-medium rounded"
>
<div className="flex justify-center items-center">
<i className="material-icons font-bold text-white text-lg">add</i>
</div>
</button>
</div>
</div>
</div>
);
};
const Item = ({ item, index, onChange, dispatch }) => {
const identifier = `data.hobbies.items[${index}]`;
return (
<div className="my-4 grid grid-cols-12">
<div className="col-span-9">
<Form item={item} onChange={v => onChange(identifier, v)} />
</div>
<button
type="button"
onClick={() => moveItemUp(dispatch, 'hobbies', item)}
className="col-span-1 text-gray-600 hover:text-red-600 text-sm font-medium"
>
<div className="flex justify-end items-center">
<i className="material-icons font-bold text-lg">arrow_upward</i>
</div>
</button>
<button
type="button"
onClick={() => moveItemDown(dispatch, 'hobbies', item)}
className="col-span-1 text-gray-600 hover:text-red-600 text-sm font-medium"
>
<div className="flex justify-end items-center">
<i className="material-icons font-bold text-lg">arrow_downward</i>
</div>
</button>
<button
type="button"
onClick={() => deleteItem(dispatch, 'hobbies', item)}
className="col-span-1 text-gray-600 hover:text-red-600 text-sm font-medium"
>
<div className="flex justify-end items-center">
<i className="material-icons font-bold text-lg">close</i>
</div>
</button>
</div>
);
};
export default HobbiesTab;

View File

@ -1,182 +0,0 @@
import set from 'lodash/set';
import React, { useContext, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { v4 as uuidv4 } from 'uuid';
import AppContext from '../../../context/AppContext';
import AddItemButton from '../../../shared/AddItemButton';
import Checkbox from '../../../shared/Checkbox';
import Counter from '../../../shared/Counter';
import ItemActions from '../../../shared/ItemActions';
import ItemHeading from '../../../shared/ItemHeading';
import TextField from '../../../shared/TextField';
import { addItem } from '../../../utils';
const LanguagesTab = ({ data, onChange }) => {
const context = useContext(AppContext);
const { dispatch } = context;
useEffect(() => {
if (!('languages' in data)) {
dispatch({
type: 'migrate_section',
payload: {
key: 'languages',
value: {
enable: false,
heading: 'Languages',
items: [],
},
},
});
dispatch({ type: 'save_data' });
}
}, [data, dispatch]);
return (
'languages' in data && (
<>
<div className="mb-6 grid grid-cols-6 items-center">
<div className="col-span-1">
<Checkbox
checked={data.languages.enable}
onChange={v => onChange('data.languages.enable', v)}
/>
</div>
<div className="col-span-5">
<TextField
placeholder="Heading"
value={data.languages.heading}
onChange={v => onChange('data.languages.heading', v)}
/>
</div>
</div>
<hr className="my-6" />
{data.languages.items.map((x, index) => (
<Item
item={x}
key={x.id}
index={index}
onChange={onChange}
dispatch={dispatch}
first={index === 0}
last={index === data.languages.items.length - 1}
/>
))}
<AddItem heading={data.languages.heading} dispatch={dispatch} />
</>
)
);
};
const Form = ({ item, onChange, identifier = '' }) => {
const { t } = useTranslation('leftSidebar');
return (
<div>
<TextField
className="mb-6"
label={t('languages.key.label')}
placeholder="English"
value={item.key}
onChange={v => onChange(`${identifier}key`, v)}
/>
<TextField
className="mb-6"
label={t('languages.level.label')}
placeholder="B1"
value={item.level}
onChange={v => onChange(`${identifier}level`, v)}
/>
<Counter
className="mb-6"
label={t('languages.rating.label')}
value={item.rating}
onDecrement={() =>
item.rating > 1
? onChange(`${identifier}rating`, item.rating - 1)
: onChange(`${identifier}rating`, 0)
}
onIncrement={() =>
item.rating < 5
? onChange(`${identifier}rating`, item.rating + 1)
: onChange(`${identifier}rating`, 0)
}
/>
</div>
);
};
const AddItem = ({ heading, dispatch }) => {
const [isOpen, setOpen] = useState(false);
const [item, setItem] = useState({
id: uuidv4(),
enable: true,
key: '',
value: '',
rating: 1,
});
const onChange = (key, value) => setItem(items => set({ ...items }, key, value));
const onSubmit = () => {
if (item.key === '') return;
addItem(dispatch, 'languages', item);
setItem({
id: uuidv4(),
enable: true,
key: '',
value: '',
rating: 1,
});
setOpen(false);
};
return (
<div className="my-4 border border-gray-200 rounded p-5">
<ItemHeading heading={heading} setOpen={setOpen} isOpen={isOpen} />
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<Form item={item} onChange={onChange} />
<AddItemButton onSubmit={onSubmit} />
</div>
</div>
);
};
const Item = ({ item, index, onChange, dispatch, first, last }) => {
const [isOpen, setOpen] = useState(false);
const identifier = `data.languages.items[${index}].`;
return (
<div className="my-4 border border-gray-200 rounded p-5">
<ItemHeading title={item.key} setOpen={setOpen} isOpen={isOpen} />
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<Form item={item} onChange={onChange} identifier={identifier} />
<ItemActions
dispatch={dispatch}
first={first}
identifier={identifier}
item={item}
last={last}
onChange={onChange}
type="languages"
/>
</div>
</div>
);
};
export default LanguagesTab;

View File

@ -1,43 +0,0 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import TextArea from '../../../shared/TextArea';
import TextField from '../../../shared/TextField';
import Checkbox from '../../../shared/Checkbox';
const ObjectiveTab = ({ data, onChange }) => {
const { t } = useTranslation('leftSidebar');
return (
<div>
<div className="mb-6 grid grid-cols-6 items-center">
<div className="col-span-1">
<Checkbox
checked={data.objective.enable}
onChange={v => onChange('data.objective.enable', v)}
/>
</div>
<div className="col-span-5">
<TextField
placeholder="Heading"
value={data.objective.heading}
onChange={v => onChange('data.objective.heading', v)}
/>
</div>
</div>
<hr className="my-6" />
<TextArea
rows="15"
className="mb-4"
label={t('objective.objective.label')}
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)}
/>
</div>
);
};
export default ObjectiveTab;

View File

@ -1,109 +0,0 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import TextField from '../../../shared/TextField';
const ProfileTab = ({ data, onChange }) => {
const { t } = useTranslation('leftSidebar');
return (
<div>
<TextField
className="mb-6"
placeholder="Heading"
value={data.profile.heading}
onChange={v => onChange('data.profile.heading', v)}
/>
<hr className="my-6" />
<TextField
className="mb-6"
label={t('profile.photoUrl.label')}
placeholder="https://i.imgur.com/..."
value={data.profile.photo}
onChange={v => onChange('data.profile.photo', v)}
/>
<div className="grid grid-cols-2 col-gap-4">
<TextField
className="mb-6"
label={t('profile.firstName.label')}
placeholder="Jane"
value={data.profile.firstName}
onChange={v => onChange('data.profile.firstName', v)}
/>
<TextField
className="mb-6"
label={t('profile.lastName.label')}
placeholder="Doe"
value={data.profile.lastName}
onChange={v => onChange('data.profile.lastName', v)}
/>
</div>
<TextField
className="mb-6"
label={t('profile.subtitle.label')}
placeholder="Full-Stack Web Developer"
value={data.profile.subtitle}
onChange={v => onChange('data.profile.subtitle', v)}
/>
<hr className="my-6" />
<TextField
className="mb-6"
label={t('profile.address.line1.label')}
placeholder="Palladium Complex"
value={data.profile.address.line1}
onChange={v => onChange('data.profile.address.line1', v)}
/>
<TextField
className="mb-6"
label={t('profile.address.line2.label')}
placeholder="140 E 14th St"
value={data.profile.address.line2}
onChange={v => onChange('data.profile.address.line2', v)}
/>
<TextField
className="mb-6"
label={t('profile.address.line3.label')}
placeholder="New York, NY 10003 USA"
value={data.profile.address.line3}
onChange={v => onChange('data.profile.address.line3', v)}
/>
<hr className="my-6" />
<TextField
className="mb-6"
label={t('profile.phone.label')}
placeholder="+1 541 754 3010"
value={data.profile.phone}
onChange={v => onChange('data.profile.phone', v)}
/>
<TextField
className="mb-6"
label={t('profile.website.label')}
placeholder="janedoe.me"
value={data.profile.website}
onChange={v => onChange('data.profile.website', v)}
/>
<TextField
className="mb-6"
label={t('profile.email.label')}
placeholder="jane.doe@example.com"
value={data.profile.email}
onChange={v => onChange('data.profile.email', v)}
/>
</div>
);
};
export default ProfileTab;

View File

@ -1,194 +0,0 @@
import React, { useState, useEffect, useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { v4 as uuidv4 } from 'uuid';
import set from 'lodash/set';
import TextField from '../../../shared/TextField';
import TextArea from '../../../shared/TextArea';
import AppContext from '../../../context/AppContext';
import Checkbox from '../../../shared/Checkbox';
import { addItem } from '../../../utils';
import ItemActions from '../../../shared/ItemActions';
import ItemHeading from '../../../shared/ItemHeading';
import AddItemButton from '../../../shared/AddItemButton';
const ReferencesTab = ({ data, onChange }) => {
const context = useContext(AppContext);
const { dispatch } = context;
useEffect(() => {
if (!('references' in data)) {
dispatch({
type: 'migrate_section',
payload: {
key: 'references',
value: {
enable: false,
heading: 'References',
items: [],
},
},
});
dispatch({ type: 'save_data' });
}
}, [data, dispatch]);
return (
'references' in data && (
<>
<div className="mb-6 grid grid-cols-6 items-center">
<div className="col-span-1">
<Checkbox
checked={data.references.enable}
onChange={v => onChange('data.references.enable', v)}
/>
</div>
<div className="col-span-5">
<TextField
placeholder="Heading"
value={data.references.heading}
onChange={v => onChange('data.references.heading', v)}
/>
</div>
</div>
<hr className="my-6" />
{data.references.items.map((x, index) => (
<Item
item={x}
key={x.id}
index={index}
onChange={onChange}
dispatch={dispatch}
first={index === 0}
last={index === data.references.items.length - 1}
/>
))}
<AddItem heading={data.references.heading} dispatch={dispatch} />
</>
)
);
};
const Form = ({ item, onChange, identifier = '' }) => {
const { t } = useTranslation(['leftSidebar', 'app']);
return (
<div>
<TextField
className="mb-6"
label={t('references.name.label')}
placeholder="Richard Hendricks"
value={item.name}
onChange={v => onChange(`${identifier}name`, v)}
/>
<TextField
className="mb-6"
label={t('references.position.label')}
placeholder="CEO, Pied Piper"
value={item.position}
onChange={v => onChange(`${identifier}position`, v)}
/>
<TextField
className="mb-6"
label={t('references.phone.label')}
placeholder="+1 541 754 3010"
value={item.phone}
onChange={v => onChange(`${identifier}phone`, v)}
/>
<TextField
className="mb-6"
label={t('references.email.label')}
placeholder="richard@piedpiper.com"
value={item.email}
onChange={v => onChange(`${identifier}email`, v)}
/>
<TextArea
rows="5"
className="mb-6"
label={t('app:item.description.label')}
value={item.description}
onChange={v => onChange(`${identifier}description`, v)}
/>
</div>
);
};
const AddItem = ({ heading, dispatch }) => {
const [isOpen, setOpen] = useState(false);
const [item, setItem] = useState({
id: uuidv4(),
enable: true,
name: '',
position: '',
phone: '',
email: '',
description: '',
});
const onChange = (key, value) => setItem(set({ ...item }, key, value));
const onSubmit = () => {
if (item.name === '' || item.position === '') return;
addItem(dispatch, 'references', item);
setItem({
id: uuidv4(),
enable: true,
name: '',
position: '',
phone: '',
email: '',
description: '',
});
setOpen(false);
};
return (
<div className="my-4 border border-gray-200 rounded p-5">
<ItemHeading heading={heading} setOpen={setOpen} isOpen={isOpen} />
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<Form item={item} onChange={onChange} />
<AddItemButton onSubmit={onSubmit} />
</div>
</div>
);
};
const Item = ({ item, index, onChange, dispatch, first, last }) => {
const [isOpen, setOpen] = useState(false);
const identifier = `data.references.items[${index}].`;
return (
<div className="my-4 border border-gray-200 rounded p-5">
<ItemHeading title={item.name} setOpen={setOpen} isOpen={isOpen} />
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<Form item={item} onChange={onChange} identifier={identifier} />
<ItemActions
dispatch={dispatch}
first={first}
identifier={identifier}
item={item}
last={last}
onChange={onChange}
type="references"
/>
</div>
</div>
);
};
export default ReferencesTab;

View File

@ -1,140 +0,0 @@
import React, { useState, useContext } from 'react';
import { v4 as uuidv4 } from 'uuid';
import AppContext from '../../../context/AppContext';
import Checkbox from '../../../shared/Checkbox';
import TextField from '../../../shared/TextField';
import { addItem, deleteItem, moveItemUp, moveItemDown } from '../../../utils';
import ItemHeading from '../../../shared/ItemHeading';
const SkillsTab = ({ data, onChange }) => {
const context = useContext(AppContext);
const { dispatch } = context;
return (
<>
<div className="my-6 grid grid-cols-6 items-center">
<div className="col-span-1">
<Checkbox
checked={data.skills.enable}
onChange={v => onChange('data.skills.enable', v)}
/>
</div>
<div className="col-span-5">
<TextField
placeholder="Heading"
value={data.skills.heading}
onChange={v => onChange('data.skills.heading', v)}
/>
</div>
</div>
<hr className="my-6" />
{data.skills.items.map((x, index) => (
<Item item={x} key={x.id} index={index} onChange={onChange} dispatch={dispatch} />
))}
<AddItem heading={data.skills.heading} dispatch={dispatch} />
</>
);
};
const Form = ({ item, onChange }) => {
return (
<input
className="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
placeholder="Team Building &amp; Training"
value={item.skill}
onChange={e => onChange(e.target.value)}
type="text"
/>
);
};
const AddItem = ({ heading, dispatch }) => {
const [isOpen, setOpen] = useState(false);
const [item, setItem] = useState({
id: uuidv4(),
skill: ''
});
const add = () => {
if (item.skill === '') return;
addItem(dispatch, 'skills', item);
setItem({
id: uuidv4(),
skill: ''
});
};
return (
<div className="my-4 border border-gray-200 rounded p-5">
<ItemHeading heading={heading} setOpen={setOpen} isOpen={isOpen} />
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<div className="grid grid-cols-4 gap-4">
<div className="col-span-3">
<Form item={item} onChange={v => setItem({...item, skill: v})} />
</div>
<button
type="button"
onClick={add}
className="col-span-1 bg-gray-600 hover:bg-gray-700 text-sm font-medium rounded"
>
<div className="flex justify-center items-center">
<i className="material-icons font-bold text-white text-lg">add</i>
</div>
</button>
</div>
</div>
</div>
);
};
const Item = ({ item, index, onChange, dispatch }) => {
const identifier = `data.skills.items[${index}]`;
return (
<div className="my-4 grid grid-cols-12">
<div className="col-span-9">
<Form item={item} onChange={v => onChange(identifier, {...item, skill: v})} />
</div>
<button
type="button"
onClick={() => moveItemUp(dispatch, 'skills', item)}
className="col-span-1 text-gray-600 hover:text-red-600 text-sm font-medium"
>
<div className="flex justify-end items-center">
<i className="material-icons font-bold text-lg">arrow_upward</i>
</div>
</button>
<button
type="button"
onClick={() => moveItemDown(dispatch, 'skills', item)}
className="col-span-1 text-gray-600 hover:text-red-600 text-sm font-medium"
>
<div className="flex justify-end items-center">
<i className="material-icons font-bold text-lg">arrow_downward</i>
</div>
</button>
<button
type="button"
onClick={() => deleteItem(dispatch, 'skills', item)}
className="col-span-1 text-gray-600 hover:text-red-600 text-sm font-medium"
>
<div className="flex justify-end items-center">
<i className="material-icons font-bold text-lg">close</i>
</div>
</button>
</div>
);
};
export default SkillsTab;

View File

@ -1,173 +0,0 @@
import React, { useState, useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { v4 as uuidv4 } from 'uuid';
import set from 'lodash/set';
import TextField from '../../../shared/TextField';
import TextArea from '../../../shared/TextArea';
import AppContext from '../../../context/AppContext';
import Checkbox from '../../../shared/Checkbox';
import { addItem } from '../../../utils';
import ItemActions from '../../../shared/ItemActions';
import AddItemButton from '../../../shared/AddItemButton';
import ItemHeading from '../../../shared/ItemHeading';
const WorkTab = ({ data, onChange }) => {
const context = useContext(AppContext);
const { dispatch } = context;
return (
<>
<div className="mb-6 grid grid-cols-6 items-center">
<div className="col-span-1">
<Checkbox checked={data.work.enable} onChange={v => onChange('data.work.enable', v)} />
</div>
<div className="col-span-5">
<TextField
placeholder="Heading"
value={data.work.heading}
onChange={v => onChange('data.work.heading', v)}
/>
</div>
</div>
<hr className="my-6" />
{data.work.items.map((x, index) => (
<Item
dispatch={dispatch}
first={index === 0}
index={index}
item={x}
key={x.id}
last={index === data.work.items.length - 1}
onChange={onChange}
/>
))}
<AddItem heading={data.work.heading} dispatch={dispatch} />
</>
);
};
const Form = ({ item, onChange, identifier = '' }) => {
const { t } = useTranslation(['leftSidebar', 'app']);
return (
<div>
<TextField
className="mb-6"
label={t('work.name.label')}
placeholder="Amazon"
value={item.title}
onChange={v => onChange(`${identifier}title`, v)}
/>
<TextField
className="mb-6"
label={t('work.role.label')}
placeholder="Full-Stack Web Developer"
value={item.role}
onChange={v => onChange(`${identifier}role`, v)}
/>
<div className="grid grid-cols-2 col-gap-4">
<TextField
className="mb-6"
label={t('app:item.startDate.label')}
placeholder="March 2018"
value={item.start}
onChange={v => onChange(`${identifier}start`, v)}
/>
<TextField
className="mb-6"
label={t('app:item.endDate.label')}
placeholder="June 2022"
value={item.end}
onChange={v => onChange(`${identifier}end`, v)}
/>
</div>
<TextArea
rows="5"
className="mb-6"
label={t('app:item.description.label')}
value={item.description}
onChange={v => onChange(`${identifier}description`, v)}
/>
</div>
);
};
const AddItem = ({ heading, dispatch }) => {
const [isOpen, setOpen] = useState(false);
const [item, setItem] = useState({
id: uuidv4(),
enable: true,
title: '',
role: '',
start: '',
end: '',
description: '',
});
const onChange = (key, value) => setItem(set({ ...item }, key, value));
const onSubmit = () => {
if (item.title === '' || item.role === '') return;
addItem(dispatch, 'work', item);
setItem({
id: uuidv4(),
enable: true,
title: '',
role: '',
start: '',
end: '',
description: '',
});
setOpen(false);
};
return (
<div className="my-4 border border-gray-200 rounded p-5">
<ItemHeading heading={heading} setOpen={setOpen} isOpen={isOpen} />
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<Form item={item} onChange={onChange} />
<AddItemButton onSubmit={onSubmit} />
</div>
</div>
);
};
const Item = ({ item, index, onChange, dispatch, first, last }) => {
const [isOpen, setOpen] = useState(false);
const identifier = `data.work.items[${index}].`;
return (
<div className="my-4 border border-gray-200 rounded p-5">
<ItemHeading title={item.title} setOpen={setOpen} isOpen={isOpen} />
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<Form item={item} onChange={onChange} identifier={identifier} />
<ItemActions
dispatch={dispatch}
first={first}
identifier={identifier}
item={item}
last={last}
onChange={onChange}
type="work"
/>
</div>
</div>
);
};
export default WorkTab;

View File

@ -1,90 +0,0 @@
import React, { useState, useContext } from 'react';
import { useTranslation } from 'react-i18next';
import AppContext from '../../context/AppContext';
import TabBar from '../../shared/TabBar';
import TemplatesTab from './tabs/Templates';
import ColorsTab from './tabs/Colors';
import FontsTab from './tabs/Fonts';
import ActionsTab from './tabs/Actions';
import AboutTab from './tabs/About';
import SettingsTab from './tabs/Settings';
const RightSidebar = () => {
const { t } = useTranslation('rightSidebar');
const context = useContext(AppContext);
const { state, dispatch } = context;
const { data, theme, settings } = state;
const tabs = [
{
key: 'templates',
name: t('templates.title'),
},
{
key: 'colors',
name: t('colors.title'),
},
{
key: 'fonts',
name: t('fonts.title'),
},
{
key: 'actions',
name: t('actions.title'),
},
{
key: 'settings',
name: t('settings.title'),
},
{
key: 'about',
name: t('about.title'),
},
];
const [currentTab, setCurrentTab] = useState(tabs[0].key);
const onChange = (key, value) => {
dispatch({
type: 'on_input',
payload: {
key,
value,
},
});
dispatch({ type: 'save_data' });
};
const renderTabs = () => {
switch (currentTab) {
case tabs[0].key:
return <TemplatesTab theme={theme} onChange={onChange} />;
case tabs[1].key:
return <ColorsTab theme={theme} onChange={onChange} />;
case tabs[2].key:
return <FontsTab theme={theme} onChange={onChange} />;
case tabs[3].key:
return <ActionsTab data={data} theme={theme} dispatch={dispatch} />;
case tabs[4].key:
return <SettingsTab settings={settings} onChange={onChange} />;
case tabs[5].key:
return <AboutTab />;
default:
return null;
}
};
return (
<div
id="rightSidebar"
className="animated slideInRight z-10 py-6 h-screen bg-white col-span-1 shadow-2xl overflow-y-scroll"
>
<TabBar tabs={tabs} currentTab={currentTab} setCurrentTab={setCurrentTab} />
<div className="px-6">{renderTabs()}</div>
</div>
);
};
export default RightSidebar;

View File

@ -1,121 +0,0 @@
import React from 'react';
import { Trans, useTranslation } from 'react-i18next';
const AboutTab = () => {
const { t } = useTranslation('rightSidebar');
return (
<div>
<div className="shadow text-center p-5">
<h6 className="font-bold text-sm mb-2">{t('about.documentation.heading')}</h6>
<div className="text-sm">{t('about.documentation.body')}</div>
<a
target="_blank"
rel="noopener noreferrer"
href="https://docs.rxresu.me/"
className="flex justify-center items-center mt-4 bg-gray-600 hover:bg-gray-700 text-white text-sm font-medium py-2 px-5 rounded"
>
<div className="flex justify-center items-center">
<i className="material-icons mr-2 font-bold text-base">description</i>
<span className="text-sm">{t('about.documentation.buttons.documentation')}</span>
</div>
</a>
</div>
<hr className="my-5" />
<div className="shadow text-center p-5">
<h6 className="font-bold text-sm mb-2">{t('about.bugOrFeatureRequest.heading')}</h6>
<div className="text-sm">{t('about.bugOrFeatureRequest.body')}</div>
<div className="grid grid-cols-1">
<a
target="_blank"
rel="noopener noreferrer"
href="https://github.com/AmruthPillai/Reactive-Resume/issues/new"
className="mt-4 bg-red-600 hover:bg-red-700 text-white text-sm font-medium py-2 px-5 rounded"
>
<div className="flex justify-center items-center">
<i className="material-icons mr-2 font-bold text-base">bug_report</i>
<span className="text-sm">{t('about.bugOrFeatureRequest.buttons.raiseIssue')}</span>
</div>
</a>
<a
target="_blank"
rel="noopener noreferrer"
href="mailto:im.amruth@gmail.com?subject=Feature Request/Reporting a Bug in Reactive Resume: "
className="mt-4 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium py-2 px-5 rounded"
>
<div className="flex justify-center items-center">
<i className="material-icons mr-2 font-bold text-base">email</i>
<span className="text-sm">{t('about.bugOrFeatureRequest.buttons.sendEmail')}</span>
</div>
</a>
</div>
</div>
<hr className="my-5" />
<div className="shadow text-center p-5">
<h6 className="font-bold text-sm mb-2">{t('about.sourceCode.heading')}</h6>
<div className="text-sm">{t('about.sourceCode.body')}</div>
<a
target="_blank"
rel="noopener noreferrer"
href="https://github.com/AmruthPillai/Reactive-Resume"
className="flex justify-center items-center mt-4 bg-green-600 hover:bg-green-700 text-white text-sm font-medium py-2 px-5 rounded"
>
<div className="flex justify-center items-center">
<i className="material-icons mr-2 font-bold text-base">code</i>
<span className="text-sm">{t('about.sourceCode.buttons.githubRepo')}</span>
</div>
</a>
</div>
<hr className="my-5" />
<div className="shadow text-center p-5">
<h6 className="font-bold text-sm mb-2">{t('about.license.heading')}</h6>
<div className="text-sm">{t('about.license.body')}</div>
<a
target="_blank"
rel="noopener noreferrer"
href="https://github.com/AmruthPillai/Reactive-Resume/blob/master/LICENSE"
className="flex justify-center items-center mt-4 bg-gray-600 hover:bg-gray-700 text-white text-sm font-medium py-2 px-5 rounded"
>
<div className="flex justify-center items-center">
<i className="material-icons mr-2 font-bold text-base">gavel</i>
<span className="text-sm">{t('about.license.buttons.mitLicense')}</span>
</div>
</a>
</div>
<div className="mt-5">
<p className="text-xs font-gray-600 text-center">
<Trans t={t} i18nKey="about.footer.credit">
Made with Love by
<a
className="font-bold hover:underline"
href="https://www.amruthpillai.com/"
rel="noopener noreferrer"
target="_blank"
>
Amruth Pillai
</a>
</Trans>
</p>
<p className="text-xs font-gray-600 text-center">{t('about.footer.thanks')}</p>
</div>
</div>
);
};
export default AboutTab;

View File

@ -1,139 +0,0 @@
/* eslint-disable new-cap */
/* eslint-disable jsx-a11y/anchor-has-content */
/* eslint-disable jsx-a11y/anchor-is-valid */
import React, { useRef, useContext } from 'react';
import { useTranslation } from 'react-i18next';
import PageContext from '../../../context/PageContext';
import { importJson } from '../../../utils';
const ActionsTab = ({ data, theme, dispatch }) => {
const pageContext = useContext(PageContext);
const { setPrintDialogOpen } = pageContext;
const { t } = useTranslation('rightSidebar');
const fileInputRef = useRef(null);
const exportToJson = () => {
const backupObj = { data, theme };
const dataStr = `data:text/json;charset=utf-8,${encodeURIComponent(JSON.stringify(backupObj))}`;
const dlAnchor = document.getElementById('downloadAnchor');
dlAnchor.setAttribute('href', dataStr);
dlAnchor.setAttribute('download', `RxResumeBackup_${Date.now()}.json`);
dlAnchor.click();
};
const loadDemoData = () => {
dispatch({ type: 'load_demo_data' });
dispatch({ type: 'save_data' });
};
const resetEverything = () => {
dispatch({ type: 'reset' });
dispatch({ type: 'save_data' });
};
return (
<div>
<div className="shadow text-center text-sm p-5">{t('actions.disclaimer')}</div>
<hr className="my-6" />
<div className="shadow text-center p-5">
<h6 className="font-bold text-sm mb-2">{t('actions.importExport.heading')}</h6>
<p className="text-sm">{t('actions.importExport.body')}</p>
<input
ref={fileInputRef}
type="file"
className="hidden"
onChange={(e) => importJson(e, dispatch)}
/>
<a id="downloadAnchor" className="hidden" />
<div className="mt-4 grid grid-cols-2 col-gap-6">
<button
type="button"
onClick={() => fileInputRef.current.click()}
className="bg-gray-600 hover:bg-gray-700 text-white text-sm font-medium py-2 px-5 rounded"
>
<div className="flex justify-center items-center">
<i className="material-icons mr-2 font-bold text-base">publish</i>
<span className="text-sm">{t('actions.importExport.buttons.import')}</span>
</div>
</button>
<button
type="button"
onClick={exportToJson}
className="bg-gray-600 hover:bg-gray-700 text-white text-sm font-medium py-2 px-5 rounded"
>
<div className="flex justify-center items-center">
<i className="material-icons mr-2 font-bold text-base">get_app</i>
<span className="text-sm">{t('actions.importExport.buttons.export')}</span>
</div>
</button>
</div>
</div>
<hr className="my-6" />
<div className="shadow text-center p-5">
<h6 className="font-bold text-sm mb-2">{t('actions.downloadResume.heading')}</h6>
<div className="text-sm">{t('actions.downloadResume.body')}</div>
<button
type="button"
onClick={() => setPrintDialogOpen(true)}
className="mt-4 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium py-2 px-5 rounded"
>
<div className="flex justify-center items-center">
<i className="material-icons mr-2 font-bold text-base">save</i>
<span className="text-sm">{t('actions.downloadResume.buttons.saveAsPdf')}</span>
</div>
</button>
</div>
<hr className="my-6" />
<div className="shadow text-center p-5">
<h6 className="font-bold text-sm mb-2">{t('actions.loadDemoData.heading')}</h6>
<div className="text-sm">{t('actions.loadDemoData.body')}</div>
<button
type="button"
onClick={loadDemoData}
className="mt-4 bg-green-600 hover:bg-green-700 text-white text-sm font-medium py-2 px-5 rounded"
>
<div className="flex justify-center items-center">
<i className="material-icons mr-2 font-bold text-base">flight_takeoff</i>
<span className="text-sm">{t('actions.loadDemoData.buttons.loadData')}</span>
</div>
</button>
</div>
<hr className="my-6" />
<div className="shadow text-center p-5">
<h6 className="font-bold text-sm mb-2">{t('actions.reset.heading')}</h6>
<div className="text-sm">{t('actions.reset.body')}</div>
<button
type="button"
onClick={resetEverything}
className="mt-4 bg-red-600 hover:bg-red-700 text-white text-sm font-medium py-2 px-5 rounded"
>
<div className="flex justify-center items-center">
<i className="material-icons mr-2 font-bold text-base">refresh</i>
<span className="text-sm">{t('actions.reset.buttons.reset')}</span>
</div>
</button>
</div>
</div>
);
};
export default ActionsTab;

View File

@ -1,95 +0,0 @@
import React from 'react';
import { toast } from 'react-toastify';
import { useTranslation } from 'react-i18next';
import TextField from '../../../shared/TextField';
import { copyToClipboard } from '../../../utils';
const colorOptions = [
'#f44336',
'#E91E63',
'#9C27B0',
'#673AB7',
'#3F51B5',
'#2196F3',
'#03A9F4',
'#00BCD4',
'#009688',
'#4CAF50',
'#8BC34A',
'#CDDC39',
'#FFEB3B',
'#FFC107',
'#FF9800',
'#FF5722',
'#795548',
'#9E9E9E',
'#607D8B',
'#FAFAFA',
'#212121',
'#263238',
];
const ColorsTab = ({ theme, onChange }) => {
const { t } = useTranslation('rightSidebar');
const copyColorToClipboard = color => {
copyToClipboard(color);
toast(t('colors.clipboardCopyAction', { color }), {
bodyClassName: 'text-center text-gray-800 py-2',
});
onChange('theme.colors.accent', color);
};
return (
<div>
<div className="uppercase tracking-wide text-gray-600 text-xs font-semibold mb-4">
{t('colors.colorOptions')}
</div>
<div className="mb-6 grid grid-cols-8 col-gap-2 row-gap-3">
{colorOptions.map(color => (
<div
key={color}
className="cursor-pointer rounded-full border border-gray-200 h-6 w-6 hover:opacity-75"
style={{ backgroundColor: color }}
onClick={() => copyColorToClipboard(color)}
/>
))}
</div>
<hr className="my-6" />
<div className="my-6 grid grid-cols-6 items-end">
<div
className="rounded-full w-8 h-8 mb-2 border-2"
style={{ backgroundColor: theme.colors.primary }}
/>
<div className="col-span-5">
<TextField
label={t('colors.primaryColor')}
placeholder="#FFFFFF"
value={theme.colors.primary}
onChange={v => onChange('theme.colors.primary', v)}
/>
</div>
</div>
<div className="my-6 grid grid-cols-6 items-end">
<div
className="rounded-full w-8 h-8 mb-2 border-2"
style={{ backgroundColor: theme.colors.accent }}
/>
<div className="col-span-5">
<TextField
label={t('colors.accentColor')}
placeholder="#FFFFFF"
value={theme.colors.accent}
onChange={v => onChange('theme.colors.accent', v)}
/>
</div>
</div>
</div>
);
};
export default ColorsTab;

View File

@ -1,51 +0,0 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import TextField from '../../../shared/TextField';
const fontOptions = [
'Lato',
'Montserrat',
'Nunito',
'Open Sans',
'Raleway',
'Rubik',
'Source Sans Pro',
'Titillium Web',
'Ubuntu',
];
const FontsTab = ({ theme, onChange }) => {
const { t } = useTranslation('rightSidebar');
return (
<div className="grid grid-cols-1 gap-6">
{fontOptions.map(x => (
<div
key={x}
style={{ fontFamily: x }}
onClick={() => onChange('theme.font.family', x)}
className={`w-full rounded border py-4 shadow text-xl text-center ${
theme.font.family === x ? 'border-gray-500' : 'border-transparent'
} hover:border-gray-400 cursor-pointer`}
>
{x}
</div>
))}
<div>
<TextField
className="mb-3"
label={t('fonts.fontFamily.label')}
placeholder="Avenir Next"
value={theme.font.family}
onChange={v => onChange('theme.font.family', v)}
/>
<p className="text-gray-800 text-xs">{t('fonts.fontFamily.helpText')}</p>
</div>
</div>
);
};
export default FontsTab;

View File

@ -1,42 +0,0 @@
import React from 'react';
import { useTranslation, Trans } from 'react-i18next';
import { languages } from '../../../i18n';
import Dropdown from '../../../shared/Dropdown';
const SettingsTab = ({ settings, onChange }) => {
const { t } = useTranslation('rightSidebar');
return (
<div>
<Dropdown
label={t('settings.language.label')}
value={settings.language}
onChange={x => onChange('settings.language', x)}
options={languages}
optionItem={x => (
<option key={x.code} value={x.code}>
{x.name}
</option>
)}
/>
<p className="text-gray-800 text-xs">
<Trans t={t} i18nKey="settings.language.helpText">
If you would like to help translate the app into your own language, please refer the
<a
className="text-blue-600 hover:underline"
target="_blank"
rel="noopener noreferrer"
href="https://docs.rxresu.me/translation/"
>
Translation Documentation
</a>
.
</Trans>
</p>
</div>
);
};
export default SettingsTab;

View File

@ -1,26 +0,0 @@
import React from 'react';
import templates from '../../../templates';
const TemplatesTab = ({ theme, onChange }) => {
return (
<div className="grid grid-cols-2 gap-6">
{templates.map(x => (
<div key={x.key} className="text-center" onClick={() => onChange('theme.layout', x.key)}>
<img
className={`rounded cursor-pointer object-cover border shadow hover:shadow-md ${
theme.layout.toLowerCase() === x.key
? 'border-gray-600 hover:border-gray-600'
: 'border-transparent '
} hover:border-gray-500 cursor-pointer`}
src={x.preview}
alt={x.name}
/>
<p className="mt-1 text-sm font-medium">{x.name}</p>
</div>
))}
</div>
);
};
export default TemplatesTab;