mirror of
https://github.com/zebrajr/Reactive-Resume.git
synced 2025-12-06 12:20:18 +01:00
- memoize all components
- implement metadata context
This commit is contained in:
parent
9e98da038c
commit
3aaef5f730
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"semi": true,
|
"semi": true,
|
||||||
"trailingComma": "all",
|
"singleQuote": true,
|
||||||
"singleQuote": true
|
"trailingComma": "all"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
|
|
@ -4,8 +4,10 @@
|
||||||
},
|
},
|
||||||
"[javascriptreact]": {
|
"[javascriptreact]": {
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.organizeImports": true,
|
"source.organizeImports": true
|
||||||
"source.fixAll": true
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.fixAll": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,10 @@ import 'firebase/database';
|
||||||
import 'firebase/storage';
|
import 'firebase/storage';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { DatabaseProvider } from './src/contexts/DatabaseContext';
|
import { DatabaseProvider } from './src/contexts/DatabaseContext';
|
||||||
|
import { MetadataProvider } from './src/contexts/MetadataContext';
|
||||||
import { ModalProvider } from './src/contexts/ModalContext';
|
import { ModalProvider } from './src/contexts/ModalContext';
|
||||||
import { ResumeProvider } from './src/contexts/ResumeContext';
|
import { ResumeProvider } from './src/contexts/ResumeContext';
|
||||||
import { StorageProvider } from './src/contexts/StorageContext';
|
import { StorageProvider } from './src/contexts/StorageContext';
|
||||||
import { TemplateProvider } from './src/contexts/TemplateContext';
|
|
||||||
import { ThemeProvider } from './src/contexts/ThemeContext';
|
import { ThemeProvider } from './src/contexts/ThemeContext';
|
||||||
import { UserProvider } from './src/contexts/UserContext';
|
import { UserProvider } from './src/contexts/UserContext';
|
||||||
import './src/styles/colors.css';
|
import './src/styles/colors.css';
|
||||||
|
|
@ -32,9 +32,9 @@ export const wrapRootElement = ({ element }) => (
|
||||||
<UserProvider>
|
<UserProvider>
|
||||||
<DatabaseProvider>
|
<DatabaseProvider>
|
||||||
<ResumeProvider>
|
<ResumeProvider>
|
||||||
<StorageProvider>
|
<MetadataProvider>
|
||||||
<TemplateProvider>{element}</TemplateProvider>
|
<StorageProvider>{element}</StorageProvider>
|
||||||
</StorageProvider>
|
</MetadataProvider>
|
||||||
</ResumeProvider>
|
</ResumeProvider>
|
||||||
</DatabaseProvider>
|
</DatabaseProvider>
|
||||||
</UserProvider>
|
</UserProvider>
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
import React, { useContext } from 'react';
|
import React, { memo } from 'react';
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
import { useSelector } from '../../../contexts/ResumeContext';
|
import { useSelector as useMetadataSelector } from '../../../contexts/MetadataContext';
|
||||||
import TemplateContext from '../../../contexts/TemplateContext';
|
import { useSelector as useResumeSelector } from '../../../contexts/ResumeContext';
|
||||||
import Onyx from '../../../templates/Onyx';
|
import Onyx from '../../../templates/Onyx';
|
||||||
import styles from './Artboard.module.css';
|
import styles from './Artboard.module.css';
|
||||||
|
|
||||||
const Artboard = () => {
|
const Artboard = () => {
|
||||||
const { selected, blocks, colors } = useContext(TemplateContext);
|
const { template, layout, colors } = useMetadataSelector((store) => store);
|
||||||
const state = useSelector((store) => store);
|
const state = useResumeSelector((store) => store);
|
||||||
const { id, name } = state;
|
const { id, name } = state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -18,12 +18,12 @@ const Artboard = () => {
|
||||||
</Helmet>
|
</Helmet>
|
||||||
|
|
||||||
<div id="artboard" className={styles.container}>
|
<div id="artboard" className={styles.container}>
|
||||||
{selected === 'Onyx' && (
|
{template === 'Onyx' && (
|
||||||
<Onyx data={state} layout={blocks} colors={colors} />
|
<Onyx data={state} layout={layout} colors={colors} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Artboard;
|
export default memo(Artboard);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Link } from 'gatsby';
|
import { Link } from 'gatsby';
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import sections from '../../../data/leftSections';
|
import sections from '../../../data/leftSections';
|
||||||
import Avatar from '../../shared/Avatar';
|
import Avatar from '../../shared/Avatar';
|
||||||
import Logo from '../../shared/Logo';
|
import Logo from '../../shared/Logo';
|
||||||
|
|
@ -26,4 +26,4 @@ const LeftNavbar = () => (
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default LeftNavbar;
|
export default memo(LeftNavbar);
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,70 @@
|
||||||
import React from 'react';
|
import React, { Fragment, memo } from 'react';
|
||||||
import { Element } from 'react-scroll';
|
import { Element } from 'react-scroll';
|
||||||
import sections from '../../../data/leftSections';
|
import sections from '../../../data/leftSections';
|
||||||
|
import Awards from '../sections/Awards';
|
||||||
|
import Certifications from '../sections/Certifications';
|
||||||
|
import Education from '../sections/Education';
|
||||||
|
import Hobbies from '../sections/Hobbies';
|
||||||
|
import Languages from '../sections/Languages';
|
||||||
|
import Objective from '../sections/Objective';
|
||||||
|
import Profile from '../sections/Profile';
|
||||||
|
import References from '../sections/References';
|
||||||
|
import Skills from '../sections/Skills';
|
||||||
|
import Social from '../sections/Social';
|
||||||
|
import Work from '../sections/Work';
|
||||||
import LeftNavbar from './LeftNavbar';
|
import LeftNavbar from './LeftNavbar';
|
||||||
import styles from './LeftSidebar.module.css';
|
import styles from './LeftSidebar.module.css';
|
||||||
|
|
||||||
const LeftSidebar = () => (
|
const getComponent = (id) => {
|
||||||
<div className="flex">
|
switch (id) {
|
||||||
<LeftNavbar />
|
case 'profile':
|
||||||
|
return Profile;
|
||||||
|
case 'social':
|
||||||
|
return Social;
|
||||||
|
case 'objective':
|
||||||
|
return Objective;
|
||||||
|
case 'work':
|
||||||
|
return Work;
|
||||||
|
case 'education':
|
||||||
|
return Education;
|
||||||
|
case 'awards':
|
||||||
|
return Awards;
|
||||||
|
case 'certifications':
|
||||||
|
return Certifications;
|
||||||
|
case 'skills':
|
||||||
|
return Skills;
|
||||||
|
case 'hobbies':
|
||||||
|
return Hobbies;
|
||||||
|
case 'languages':
|
||||||
|
return Languages;
|
||||||
|
case 'references':
|
||||||
|
return References;
|
||||||
|
default:
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
<div id="LeftSidebar" className={styles.container}>
|
const LeftSidebar = () => {
|
||||||
{sections.map(({ id, name, event, component: Component }) => (
|
return (
|
||||||
<Element key={id} name={id}>
|
<div className="flex">
|
||||||
<Component id={id} name={name} event={event} />
|
<LeftNavbar />
|
||||||
<hr />
|
|
||||||
</Element>
|
<div id="LeftSidebar" className={styles.container}>
|
||||||
))}
|
{sections.map(({ id, name, event }) => {
|
||||||
|
const Component = getComponent(id);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Fragment key={id}>
|
||||||
|
<Element name={id}>
|
||||||
|
<Component id={id} name={name} event={event} />
|
||||||
|
</Element>
|
||||||
|
<hr />
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
);
|
||||||
);
|
};
|
||||||
|
|
||||||
export default LeftSidebar;
|
export default memo(LeftSidebar);
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
-ms-overflow-style: none;
|
-ms-overflow-style: none;
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
@apply w-full h-screen overflow-scroll p-8;
|
@apply w-full h-screen overflow-scroll p-8;
|
||||||
@apply grid gap-6;
|
@apply grid gap-8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container::-webkit-scrollbar {
|
.container::-webkit-scrollbar {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
|
|
||||||
const EmptyList = () => (
|
const EmptyList = () => (
|
||||||
<div className="py-6 opacity-75 text-center">This list is empty.</div>
|
<div className="py-6 opacity-75 text-center">This list is empty.</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default EmptyList;
|
export default memo(EmptyList);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { get, isEmpty } from 'lodash';
|
import { get, isEmpty } from 'lodash';
|
||||||
import React, { useContext } from 'react';
|
import React, { memo, useContext } from 'react';
|
||||||
import { MdAdd } from 'react-icons/md';
|
import { MdAdd } from 'react-icons/md';
|
||||||
import ModalContext from '../../../contexts/ModalContext';
|
import ModalContext from '../../../contexts/ModalContext';
|
||||||
import { useSelector } from '../../../contexts/ResumeContext';
|
import { useSelector } from '../../../contexts/ResumeContext';
|
||||||
|
|
@ -64,4 +64,4 @@ const List = ({
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default List;
|
export default memo(List);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Menu, MenuItem } from '@material-ui/core';
|
import { Menu, MenuItem } from '@material-ui/core';
|
||||||
import React, { useState } from 'react';
|
import React, { memo, useState } from 'react';
|
||||||
import { IoIosArrowDown, IoIosArrowUp } from 'react-icons/io';
|
import { IoIosArrowDown, IoIosArrowUp } from 'react-icons/io';
|
||||||
import { MdMoreVert } from 'react-icons/md';
|
import { MdMoreVert } from 'react-icons/md';
|
||||||
import { useDispatch } from '../../../contexts/ResumeContext';
|
import { useDispatch } from '../../../contexts/ResumeContext';
|
||||||
|
|
@ -108,4 +108,4 @@ const ListItem = ({
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ListItem;
|
export default memo(ListItem);
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import { MdPerson } from 'react-icons/md';
|
import sections from '../../../data/rightSections';
|
||||||
|
import SectionIcon from '../../shared/SectionIcon';
|
||||||
import styles from './RightNavbar.module.css';
|
import styles from './RightNavbar.module.css';
|
||||||
import SyncIndicator from './SyncIndicator';
|
import SyncIndicator from './SyncIndicator';
|
||||||
|
|
||||||
const RightNavbar = () => {
|
const RightNavbar = () => {
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<div className="grid grid-cols-1 gap-6">
|
<div className="grid grid-cols-1 gap-8">
|
||||||
<MdPerson
|
{sections.map((x) => (
|
||||||
className="text-secondary-dark hover:text-primary"
|
<SectionIcon key={x.id} section={x} containerId="RightSidebar" />
|
||||||
size="20px"
|
))}
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr className="mt-auto my-6" />
|
<hr className="mt-auto my-6" />
|
||||||
|
|
@ -20,4 +20,4 @@ const RightNavbar = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default RightNavbar;
|
export default memo(RightNavbar);
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,35 @@
|
||||||
import React from 'react';
|
import React, { Fragment, memo } from 'react';
|
||||||
|
import { Element } from 'react-scroll';
|
||||||
|
import sections from '../../../data/rightSections';
|
||||||
import Layout from '../sections/Layout';
|
import Layout from '../sections/Layout';
|
||||||
import RightNavbar from './RightNavbar';
|
import RightNavbar from './RightNavbar';
|
||||||
import styles from './RightSidebar.module.css';
|
import styles from './RightSidebar.module.css';
|
||||||
|
|
||||||
|
const getComponent = (id) => {
|
||||||
|
switch (id) {
|
||||||
|
case 'layout':
|
||||||
|
return Layout;
|
||||||
|
default:
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const RightSidebar = () => {
|
const RightSidebar = () => {
|
||||||
return (
|
return (
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<div className={styles.container}>
|
<div id="RightSidebar" className={styles.container}>
|
||||||
<Layout />
|
{sections.map(({ id, name, event }) => {
|
||||||
<hr />
|
const Component = getComponent(id);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Fragment key={id}>
|
||||||
|
<Element name={id}>
|
||||||
|
<Component id={id} name={name} event={event} />
|
||||||
|
</Element>
|
||||||
|
<hr />
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<RightNavbar />
|
<RightNavbar />
|
||||||
|
|
@ -16,4 +37,4 @@ const RightSidebar = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default RightSidebar;
|
export default memo(RightSidebar);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
import React, { useContext } from 'react';
|
import React, { memo, useContext } from 'react';
|
||||||
import { MdSync, MdSyncDisabled } from 'react-icons/md';
|
import { MdSync, MdSyncDisabled } from 'react-icons/md';
|
||||||
import DatabaseContext from '../../../contexts/DatabaseContext';
|
import DatabaseContext from '../../../contexts/DatabaseContext';
|
||||||
|
|
||||||
|
|
@ -17,4 +17,4 @@ const SyncIndicator = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SyncIndicator;
|
export default memo(SyncIndicator);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import Heading from '../../shared/Heading';
|
import Heading from '../../shared/Heading';
|
||||||
import List from '../lists/List';
|
import List from '../lists/List';
|
||||||
|
|
||||||
|
|
@ -20,4 +20,4 @@ const Awards = ({ id, name, event }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Awards;
|
export default memo(Awards);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import Heading from '../../shared/Heading';
|
import Heading from '../../shared/Heading';
|
||||||
import List from '../lists/List';
|
import List from '../lists/List';
|
||||||
|
|
||||||
|
|
@ -20,4 +20,4 @@ const Certifications = ({ id, name, event }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Certifications;
|
export default memo(Certifications);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import Heading from '../../shared/Heading';
|
import Heading from '../../shared/Heading';
|
||||||
import List from '../lists/List';
|
import List from '../lists/List';
|
||||||
|
|
||||||
|
|
@ -20,4 +20,4 @@ const Education = ({ id, name, event }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Education;
|
export default memo(Education);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import Heading from '../../shared/Heading';
|
import Heading from '../../shared/Heading';
|
||||||
import List from '../lists/List';
|
import List from '../lists/List';
|
||||||
|
|
||||||
|
|
@ -14,4 +14,4 @@ const Hobbies = ({ id, name, event }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Hobbies;
|
export default memo(Hobbies);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import Heading from '../../shared/Heading';
|
import Heading from '../../shared/Heading';
|
||||||
import List from '../lists/List';
|
import List from '../lists/List';
|
||||||
|
|
||||||
|
|
@ -14,4 +14,4 @@ const Languages = ({ id, name, event }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Languages;
|
export default memo(Languages);
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,36 @@
|
||||||
import React, { useContext } from 'react';
|
import React, { memo } from 'react';
|
||||||
import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd';
|
import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd';
|
||||||
import TemplateContext from '../../../contexts/TemplateContext';
|
import { useDispatch, useSelector } from '../../../contexts/MetadataContext';
|
||||||
|
import { move, reorder } from '../../../utils';
|
||||||
import Heading from '../../shared/Heading';
|
import Heading from '../../shared/Heading';
|
||||||
import styles from './Layout.module.css';
|
import styles from './Layout.module.css';
|
||||||
|
|
||||||
const Layout = () => {
|
const Layout = () => {
|
||||||
const { blocks, onDragEnd } = useContext(TemplateContext);
|
const blocks = useSelector((state) => state.layout);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const onDragEnd = (result) => {
|
||||||
|
const { source, destination } = result;
|
||||||
|
|
||||||
|
if (!destination) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const sInd = +source.droppableId;
|
||||||
|
const dInd = +destination.droppableId;
|
||||||
|
|
||||||
|
if (sInd === dInd) {
|
||||||
|
const items = reorder(blocks[sInd], source.index, destination.index);
|
||||||
|
const newState = [...blocks];
|
||||||
|
newState[sInd] = items;
|
||||||
|
dispatch({ type: 'set_layout', payload: newState });
|
||||||
|
} else {
|
||||||
|
const newResult = move(blocks[sInd], blocks[dInd], source, destination);
|
||||||
|
const newState = [...blocks];
|
||||||
|
newState[sInd] = newResult[sInd];
|
||||||
|
newState[dInd] = newResult[dInd];
|
||||||
|
dispatch({ type: 'set_layout', payload: newState });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
|
|
@ -60,4 +85,4 @@ const Layout = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Layout;
|
export default memo(Layout);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import Heading from '../../shared/Heading';
|
import Heading from '../../shared/Heading';
|
||||||
import Input from '../../shared/Input';
|
import Input from '../../shared/Input';
|
||||||
|
|
||||||
|
|
@ -12,4 +12,4 @@ const Objective = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Objective;
|
export default memo(Objective);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import Heading from '../../shared/Heading';
|
import Heading from '../../shared/Heading';
|
||||||
import Input from '../../shared/Input';
|
import Input from '../../shared/Input';
|
||||||
import PhotoUpload from '../../shared/PhotoUpload';
|
import PhotoUpload from '../../shared/PhotoUpload';
|
||||||
|
|
@ -44,4 +44,4 @@ const Profile = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Profile;
|
export default memo(Profile);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import Heading from '../../shared/Heading';
|
import Heading from '../../shared/Heading';
|
||||||
import List from '../lists/List';
|
import List from '../lists/List';
|
||||||
|
|
||||||
|
|
@ -20,4 +20,4 @@ const References = ({ id, name, event }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default References;
|
export default memo(References);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import Heading from '../../shared/Heading';
|
import Heading from '../../shared/Heading';
|
||||||
import List from '../lists/List';
|
import List from '../lists/List';
|
||||||
|
|
||||||
|
|
@ -14,4 +14,4 @@ const Skills = ({ id, name, event }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Skills;
|
export default memo(Skills);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import Heading from '../../shared/Heading';
|
import Heading from '../../shared/Heading';
|
||||||
import List from '../lists/List';
|
import List from '../lists/List';
|
||||||
|
|
||||||
|
|
@ -19,4 +19,4 @@ const Social = ({ id, name, event }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Social;
|
export default memo(Social);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import Heading from '../../shared/Heading';
|
import Heading from '../../shared/Heading';
|
||||||
import List from '../lists/List';
|
import List from '../lists/List';
|
||||||
|
|
||||||
|
|
@ -20,4 +20,4 @@ const Work = ({ id, name, event }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Work;
|
export default memo(Work);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useContext } from 'react';
|
import React, { memo, useContext } from 'react';
|
||||||
import { MdAdd } from 'react-icons/md';
|
import { MdAdd } from 'react-icons/md';
|
||||||
import ModalContext from '../../contexts/ModalContext';
|
import ModalContext from '../../contexts/ModalContext';
|
||||||
import { handleKeyUp } from '../../utils';
|
import { handleKeyUp } from '../../utils';
|
||||||
|
|
@ -30,4 +30,4 @@ const CreateResume = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CreateResume;
|
export default memo(CreateResume);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { Menu, MenuItem } from '@material-ui/core';
|
import { Menu, MenuItem } from '@material-ui/core';
|
||||||
import { navigate } from 'gatsby';
|
import { navigate } from 'gatsby';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import React, { useContext, useState } from 'react';
|
import React, { memo, useContext, useState } from 'react';
|
||||||
import { MdMoreHoriz, MdOpenInNew } from 'react-icons/md';
|
import { MdMoreHoriz, MdOpenInNew } from 'react-icons/md';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import DatabaseContext from '../../contexts/DatabaseContext';
|
import DatabaseContext from '../../contexts/DatabaseContext';
|
||||||
|
|
@ -78,4 +78,4 @@ const ResumePreview = ({ resume }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ResumePreview;
|
export default memo(ResumePreview);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Link, navigate } from 'gatsby';
|
import { Link, navigate } from 'gatsby';
|
||||||
import React, { useContext } from 'react';
|
import React, { memo, useContext } from 'react';
|
||||||
import UserContext from '../../contexts/UserContext';
|
import UserContext from '../../contexts/UserContext';
|
||||||
import Avatar from '../shared/Avatar';
|
import Avatar from '../shared/Avatar';
|
||||||
import Logo from '../shared/Logo';
|
import Logo from '../shared/Logo';
|
||||||
|
|
@ -35,4 +35,4 @@ const TopNavbar = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TopNavbar;
|
export default memo(TopNavbar);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { navigate } from 'gatsby';
|
import { navigate } from 'gatsby';
|
||||||
import React, { useContext } from 'react';
|
import React, { memo, useContext } from 'react';
|
||||||
import { FaGithub } from 'react-icons/fa';
|
import { FaGithub } from 'react-icons/fa';
|
||||||
import ModalContext from '../../contexts/ModalContext';
|
import ModalContext from '../../contexts/ModalContext';
|
||||||
import ThemeContext from '../../contexts/ThemeContext';
|
import ThemeContext from '../../contexts/ThemeContext';
|
||||||
|
|
@ -49,4 +49,4 @@ const Hero = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Hero;
|
export default memo(Hero);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Fade, Modal } from '@material-ui/core';
|
import { Fade, Modal } from '@material-ui/core';
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import { getRandomTip } from '../../data/tips';
|
import { getRandomTip } from '../../data/tips';
|
||||||
import Logo from '../shared/Logo';
|
import Logo from '../shared/Logo';
|
||||||
|
|
||||||
|
|
@ -18,4 +18,4 @@ const LoadingScreen = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LoadingScreen;
|
export default memo(LoadingScreen);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { navigate } from 'gatsby';
|
import { navigate } from 'gatsby';
|
||||||
import React, { useContext } from 'react';
|
import React, { memo, useContext } from 'react';
|
||||||
import UserContext from '../../contexts/UserContext';
|
import UserContext from '../../contexts/UserContext';
|
||||||
import LoadingScreen from './LoadingScreen';
|
import LoadingScreen from './LoadingScreen';
|
||||||
|
|
||||||
|
|
@ -18,4 +18,4 @@ const PrivateRoute = ({ component: Component, location, ...props }) => {
|
||||||
return <Component user={user} {...props} />;
|
return <Component user={user} {...props} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PrivateRoute;
|
export default memo(PrivateRoute);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
import { toUrl } from 'gatsby-source-gravatar';
|
import { toUrl } from 'gatsby-source-gravatar';
|
||||||
import React, { useContext, useMemo } from 'react';
|
import React, { memo, useContext, useMemo } from 'react';
|
||||||
import UserContext from '../../contexts/UserContext';
|
import UserContext from '../../contexts/UserContext';
|
||||||
import styles from './Avatar.module.css';
|
import styles from './Avatar.module.css';
|
||||||
|
|
||||||
|
|
@ -18,4 +18,4 @@ const Avatar = ({ className }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Avatar;
|
export default memo(Avatar);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import { handleKeyUp } from '../../utils';
|
import { handleKeyUp } from '../../utils';
|
||||||
import styles from './Button.module.css';
|
import styles from './Button.module.css';
|
||||||
|
|
||||||
|
|
@ -21,4 +21,4 @@ const Button = ({ icon, title, onClick, outline, className, isLoading }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Button;
|
export default memo(Button);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
|
|
||||||
const Heading = ({ children }) => {
|
const Heading = ({ children }) => {
|
||||||
return <h2 className="text-4xl">{children}</h2>;
|
return <h2 className="text-4xl">{children}</h2>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Heading;
|
export default memo(Heading);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
import { get, isFunction } from 'lodash';
|
import { get, isFunction } from 'lodash';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { memo, useEffect, useState } from 'react';
|
||||||
import { FaAngleDown } from 'react-icons/fa';
|
import { FaAngleDown } from 'react-icons/fa';
|
||||||
import { MdClose } from 'react-icons/md';
|
import { MdClose } from 'react-icons/md';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
@ -133,4 +133,4 @@ const Input = ({
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Input;
|
export default memo(Input);
|
||||||
|
|
|
||||||
51
src/components/shared/InputArray.js
Normal file
51
src/components/shared/InputArray.js
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { Field } from 'formik';
|
||||||
|
import React, { memo } from 'react';
|
||||||
|
import { MdAdd } from 'react-icons/md';
|
||||||
|
import { getFieldProps, handleKeyUp } from '../../utils';
|
||||||
|
import Input from './Input';
|
||||||
|
|
||||||
|
const InputArray = ({ formik, schema, helpers, label, path, placeholder }) => {
|
||||||
|
const handleClickAdd = () => {
|
||||||
|
formik.values.temp && helpers.push(formik.values.temp);
|
||||||
|
formik.setFieldValue('temp', '');
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="col-span-2">
|
||||||
|
<label>
|
||||||
|
<span>{label}</span>
|
||||||
|
|
||||||
|
{formik.values[path] &&
|
||||||
|
formik.values[path].map((x, i) => (
|
||||||
|
<Field key={i} name={`${path}.${i}`}>
|
||||||
|
{({ field, meta }) => (
|
||||||
|
<Input
|
||||||
|
className="my-1"
|
||||||
|
showDeleteItemButton
|
||||||
|
onDeleteItem={() => helpers.remove(i)}
|
||||||
|
{...field}
|
||||||
|
{...meta}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Field>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<div className="flex items-center">
|
||||||
|
<Input
|
||||||
|
placeholder={placeholder}
|
||||||
|
{...getFieldProps(formik, schema, 'temp')}
|
||||||
|
/>
|
||||||
|
<MdAdd
|
||||||
|
size="18px"
|
||||||
|
tabIndex="0"
|
||||||
|
className="mx-4 cursor-pointer opacity-50 hover:opacity-75"
|
||||||
|
onKeyUp={(e) => handleKeyUp(e, handleClickAdd)}
|
||||||
|
onClick={handleClickAdd}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(InputArray);
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
import { graphql, useStaticQuery } from 'gatsby';
|
import { graphql, useStaticQuery } from 'gatsby';
|
||||||
import GatsbyImage from 'gatsby-image';
|
import GatsbyImage from 'gatsby-image';
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import styles from './Logo.module.css';
|
import styles from './Logo.module.css';
|
||||||
|
|
||||||
const Logo = ({ size = '256px', className }) => {
|
const Logo = ({ size = '256px', className }) => {
|
||||||
|
|
@ -27,4 +27,4 @@ const Logo = ({ size = '256px', className }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Logo;
|
export default memo(Logo);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useContext, useRef } from 'react';
|
import React, { memo, useContext, useRef } from 'react';
|
||||||
import { MdFileUpload } from 'react-icons/md';
|
import { MdFileUpload } from 'react-icons/md';
|
||||||
import StorageContext from '../../contexts/StorageContext';
|
import StorageContext from '../../contexts/StorageContext';
|
||||||
import { handleKeyUp } from '../../utils';
|
import { handleKeyUp } from '../../utils';
|
||||||
|
|
@ -47,4 +47,4 @@ const PhotoUpload = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PhotoUpload;
|
export default memo(PhotoUpload);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Tooltip } from '@material-ui/core';
|
import { Tooltip } from '@material-ui/core';
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import { scroller } from 'react-scroll';
|
import { scroller } from 'react-scroll';
|
||||||
import { handleKeyUp } from '../../utils';
|
import { handleKeyUp } from '../../utils';
|
||||||
|
|
||||||
|
|
@ -30,4 +30,4 @@ const SectionIcon = ({ section, containerId, placement = 'right' }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SectionIcon;
|
export default memo(SectionIcon);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useEffect } from 'react';
|
import React, { memo, useEffect } from 'react';
|
||||||
import { Slide, toast } from 'react-toastify';
|
import { Slide, toast } from 'react-toastify';
|
||||||
import ModalRegistrar from '../../modals/ModalRegistrar';
|
import ModalRegistrar from '../../modals/ModalRegistrar';
|
||||||
|
|
||||||
|
|
@ -23,4 +23,4 @@ const Wrapper = ({ children }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Wrapper;
|
export default memo(Wrapper);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,16 @@
|
||||||
import firebase from 'gatsby-plugin-firebase';
|
import firebase from 'gatsby-plugin-firebase';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
import React, { createContext, useContext, useEffect, useState } from 'react';
|
import React, {
|
||||||
|
createContext,
|
||||||
|
memo,
|
||||||
|
useContext,
|
||||||
|
useEffect,
|
||||||
|
useState,
|
||||||
|
} from 'react';
|
||||||
import UserContext from './UserContext';
|
import UserContext from './UserContext';
|
||||||
|
|
||||||
|
const DEBOUNCE_WAIT_TIME = 4000;
|
||||||
|
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
isOffline: false,
|
isOffline: false,
|
||||||
isUpdating: false,
|
isUpdating: false,
|
||||||
|
|
@ -10,7 +18,8 @@ const defaultState = {
|
||||||
getResumes: async () => {},
|
getResumes: async () => {},
|
||||||
createResume: () => {},
|
createResume: () => {},
|
||||||
updateResume: async () => {},
|
updateResume: async () => {},
|
||||||
debouncedUpdate: async () => {},
|
debouncedUpdateResume: async () => {},
|
||||||
|
debouncedUpdateMetadata: async () => {},
|
||||||
deleteResume: () => {},
|
deleteResume: () => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -77,7 +86,23 @@ const DatabaseProvider = ({ children }) => {
|
||||||
setUpdating(false);
|
setUpdating(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const debouncedUpdate = debounce(updateResume, 2000);
|
const debouncedUpdateResume = debounce(updateResume, DEBOUNCE_WAIT_TIME);
|
||||||
|
|
||||||
|
const updateMetadata = async (resumeId, metadata) => {
|
||||||
|
setUpdating(true);
|
||||||
|
|
||||||
|
await firebase
|
||||||
|
.database()
|
||||||
|
.ref(`users/${user.uid}/resumes/${resumeId}`)
|
||||||
|
.update({
|
||||||
|
metadata,
|
||||||
|
updatedAt: firebase.database.ServerValue.TIMESTAMP,
|
||||||
|
});
|
||||||
|
|
||||||
|
setUpdating(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const debouncedUpdateMetadata = debounce(updateMetadata, DEBOUNCE_WAIT_TIME);
|
||||||
|
|
||||||
const deleteResume = (id) => {
|
const deleteResume = (id) => {
|
||||||
firebase.database().ref(`users/${user.uid}/resumes/${id}`).remove();
|
firebase.database().ref(`users/${user.uid}/resumes/${id}`).remove();
|
||||||
|
|
@ -91,7 +116,8 @@ const DatabaseProvider = ({ children }) => {
|
||||||
getResume,
|
getResume,
|
||||||
createResume,
|
createResume,
|
||||||
updateResume,
|
updateResume,
|
||||||
debouncedUpdate,
|
debouncedUpdateResume,
|
||||||
|
debouncedUpdateMetadata,
|
||||||
deleteResume,
|
deleteResume,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
@ -102,4 +128,6 @@ const DatabaseProvider = ({ children }) => {
|
||||||
|
|
||||||
export default DatabaseContext;
|
export default DatabaseContext;
|
||||||
|
|
||||||
export { DatabaseProvider };
|
const memoizedProvider = memo(DatabaseProvider);
|
||||||
|
|
||||||
|
export { memoizedProvider as DatabaseProvider };
|
||||||
|
|
|
||||||
70
src/contexts/MetadataContext.js
Normal file
70
src/contexts/MetadataContext.js
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
import { clone, setWith } from 'lodash';
|
||||||
|
import React, {
|
||||||
|
createContext,
|
||||||
|
memo,
|
||||||
|
useCallback,
|
||||||
|
useContext,
|
||||||
|
useReducer,
|
||||||
|
} from 'react';
|
||||||
|
import leftSections from '../data/leftSections';
|
||||||
|
import DatabaseContext from './DatabaseContext';
|
||||||
|
import { useSelector as useResumeSelector } from './ResumeContext';
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
template: 'Onyx',
|
||||||
|
font: 'Montserrat',
|
||||||
|
layout: [leftSections.map(({ id, name }) => ({ id, name }))],
|
||||||
|
colors: {
|
||||||
|
textColor: '#444444',
|
||||||
|
primaryColor: '#5875DB',
|
||||||
|
backgroundColor: '#FFFFFF',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const MetadataContext = createContext({});
|
||||||
|
|
||||||
|
const MetadataProvider = ({ children }) => {
|
||||||
|
const id = useResumeSelector((state) => state.id);
|
||||||
|
const { debouncedUpdateMetadata } = useContext(DatabaseContext);
|
||||||
|
|
||||||
|
const memoizedReducer = useCallback(
|
||||||
|
(state, { type, payload }) => {
|
||||||
|
let newState;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'set_layout':
|
||||||
|
newState = setWith(clone(state), 'layout', payload, clone);
|
||||||
|
debouncedUpdateMetadata(id, newState);
|
||||||
|
return newState;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[id, debouncedUpdateMetadata],
|
||||||
|
);
|
||||||
|
|
||||||
|
const [state, dispatch] = useReducer(memoizedReducer, initialState);
|
||||||
|
|
||||||
|
const selectValue = (callback) => callback(state);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MetadataContext.Provider value={{ selectValue, dispatch }}>
|
||||||
|
{children}
|
||||||
|
</MetadataContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const useSelector = (callback) => {
|
||||||
|
const { selectValue } = useContext(MetadataContext);
|
||||||
|
return selectValue(callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
const useDispatch = () => {
|
||||||
|
const { dispatch } = useContext(MetadataContext);
|
||||||
|
return dispatch;
|
||||||
|
};
|
||||||
|
|
||||||
|
const memoizedProvider = memo(MetadataProvider);
|
||||||
|
|
||||||
|
export { memoizedProvider as MetadataProvider, useSelector, useDispatch };
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { createNanoEvents } from 'nanoevents';
|
import { createNanoEvents } from 'nanoevents';
|
||||||
import React, { createContext } from 'react';
|
import React, { createContext, memo } from 'react';
|
||||||
import ModalEvents from '../constants/ModalEvents';
|
import ModalEvents from '../constants/ModalEvents';
|
||||||
|
|
||||||
const emitter = createNanoEvents();
|
const emitter = createNanoEvents();
|
||||||
|
|
@ -18,4 +18,6 @@ const ModalProvider = ({ children }) => {
|
||||||
|
|
||||||
export default ModalContext;
|
export default ModalContext;
|
||||||
|
|
||||||
export { ModalProvider };
|
const memoizedProvider = memo(ModalProvider);
|
||||||
|
|
||||||
|
export { memoizedProvider as ModalProvider };
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import arrayMove from 'array-move';
|
||||||
import { clone, findIndex, get, setWith } from 'lodash';
|
import { clone, findIndex, get, setWith } from 'lodash';
|
||||||
import React, {
|
import React, {
|
||||||
createContext,
|
createContext,
|
||||||
|
memo,
|
||||||
useCallback,
|
useCallback,
|
||||||
useContext,
|
useContext,
|
||||||
useReducer,
|
useReducer,
|
||||||
|
|
@ -10,10 +11,10 @@ import DatabaseContext from './DatabaseContext';
|
||||||
|
|
||||||
const initialState = {};
|
const initialState = {};
|
||||||
|
|
||||||
const ResumeContext = createContext(initialState);
|
const ResumeContext = createContext({});
|
||||||
|
|
||||||
const ResumeProvider = ({ children }) => {
|
const ResumeProvider = ({ children }) => {
|
||||||
const { debouncedUpdate } = useContext(DatabaseContext);
|
const { debouncedUpdateResume } = useContext(DatabaseContext);
|
||||||
|
|
||||||
const memoizedReducer = useCallback(
|
const memoizedReducer = useCallback(
|
||||||
(state, { type, payload }) => {
|
(state, { type, payload }) => {
|
||||||
|
|
@ -31,7 +32,7 @@ const ResumeProvider = ({ children }) => {
|
||||||
[...items, payload.value],
|
[...items, payload.value],
|
||||||
clone,
|
clone,
|
||||||
);
|
);
|
||||||
debouncedUpdate(newState);
|
debouncedUpdateResume(newState);
|
||||||
return newState;
|
return newState;
|
||||||
|
|
||||||
case 'on_edit_item':
|
case 'on_edit_item':
|
||||||
|
|
@ -44,7 +45,7 @@ const ResumeProvider = ({ children }) => {
|
||||||
payload.value,
|
payload.value,
|
||||||
clone,
|
clone,
|
||||||
);
|
);
|
||||||
debouncedUpdate(newState);
|
debouncedUpdateResume(newState);
|
||||||
return newState;
|
return newState;
|
||||||
|
|
||||||
case 'on_delete_item':
|
case 'on_delete_item':
|
||||||
|
|
@ -52,7 +53,7 @@ const ResumeProvider = ({ children }) => {
|
||||||
index = findIndex(items, ['id', payload.value.id]);
|
index = findIndex(items, ['id', payload.value.id]);
|
||||||
items.splice(index, 1);
|
items.splice(index, 1);
|
||||||
newState = setWith(clone(state), payload.path, items, clone);
|
newState = setWith(clone(state), payload.path, items, clone);
|
||||||
debouncedUpdate(newState);
|
debouncedUpdateResume(newState);
|
||||||
return newState;
|
return newState;
|
||||||
|
|
||||||
case 'on_move_item_up':
|
case 'on_move_item_up':
|
||||||
|
|
@ -60,7 +61,7 @@ const ResumeProvider = ({ children }) => {
|
||||||
index = findIndex(items, ['id', payload.value.id]);
|
index = findIndex(items, ['id', payload.value.id]);
|
||||||
items = arrayMove(items, index, index - 1);
|
items = arrayMove(items, index, index - 1);
|
||||||
newState = setWith(clone(state), payload.path, items, clone);
|
newState = setWith(clone(state), payload.path, items, clone);
|
||||||
debouncedUpdate(newState);
|
debouncedUpdateResume(newState);
|
||||||
return newState;
|
return newState;
|
||||||
|
|
||||||
case 'on_move_item_down':
|
case 'on_move_item_down':
|
||||||
|
|
@ -68,12 +69,12 @@ const ResumeProvider = ({ children }) => {
|
||||||
index = findIndex(items, ['id', payload.value.id]);
|
index = findIndex(items, ['id', payload.value.id]);
|
||||||
items = arrayMove(items, index, index + 1);
|
items = arrayMove(items, index, index + 1);
|
||||||
newState = setWith(clone(state), payload.path, items, clone);
|
newState = setWith(clone(state), payload.path, items, clone);
|
||||||
debouncedUpdate(newState);
|
debouncedUpdateResume(newState);
|
||||||
return newState;
|
return newState;
|
||||||
|
|
||||||
case 'on_input':
|
case 'on_input':
|
||||||
newState = setWith(clone(state), payload.path, payload.value, clone);
|
newState = setWith(clone(state), payload.path, payload.value, clone);
|
||||||
debouncedUpdate(newState);
|
debouncedUpdateResume(newState);
|
||||||
return newState;
|
return newState;
|
||||||
|
|
||||||
case 'set_data':
|
case 'set_data':
|
||||||
|
|
@ -83,7 +84,7 @@ const ResumeProvider = ({ children }) => {
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[debouncedUpdate],
|
[debouncedUpdateResume],
|
||||||
);
|
);
|
||||||
|
|
||||||
const [state, dispatch] = useReducer(memoizedReducer, initialState);
|
const [state, dispatch] = useReducer(memoizedReducer, initialState);
|
||||||
|
|
@ -107,4 +108,6 @@ const useDispatch = () => {
|
||||||
return dispatch;
|
return dispatch;
|
||||||
};
|
};
|
||||||
|
|
||||||
export { ResumeProvider, useSelector, useDispatch };
|
const memoizedProvider = memo(ResumeProvider);
|
||||||
|
|
||||||
|
export { memoizedProvider as ResumeProvider, useSelector, useDispatch };
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import firebase from 'gatsby-plugin-firebase';
|
import firebase from 'gatsby-plugin-firebase';
|
||||||
import React, { createContext, useContext, useRef } from 'react';
|
import React, { createContext, memo, useContext, useRef } from 'react';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import { isFileImage } from '../utils';
|
import { isFileImage } from '../utils';
|
||||||
import { useDispatch, useSelector } from './ResumeContext';
|
import { useDispatch, useSelector } from './ResumeContext';
|
||||||
|
|
@ -84,4 +84,6 @@ const StorageProvider = ({ children }) => {
|
||||||
|
|
||||||
export default StorageContext;
|
export default StorageContext;
|
||||||
|
|
||||||
export { StorageProvider };
|
const memoizedProvider = memo(StorageProvider);
|
||||||
|
|
||||||
|
export { memoizedProvider as StorageProvider };
|
||||||
|
|
|
||||||
|
|
@ -1,111 +0,0 @@
|
||||||
import { flatten } from 'lodash';
|
|
||||||
import React, { createContext, useState } from 'react';
|
|
||||||
import leftSections from '../data/leftSections';
|
|
||||||
|
|
||||||
const defaultState = {
|
|
||||||
selected: 'Onyx',
|
|
||||||
setSelected: () => {},
|
|
||||||
colors: {
|
|
||||||
textColor: '#212121',
|
|
||||||
primaryColor: '#f44336',
|
|
||||||
backgroundColor: '#FFFFFF',
|
|
||||||
},
|
|
||||||
blocks: [leftSections],
|
|
||||||
setBlocks: () => {},
|
|
||||||
setFixedBlocks: () => {},
|
|
||||||
setSupportedBlocks: () => {},
|
|
||||||
};
|
|
||||||
|
|
||||||
const TemplateContext = createContext(defaultState);
|
|
||||||
|
|
||||||
const TemplateProvider = ({ children }) => {
|
|
||||||
const [selected, setSelected] = useState(defaultState.selected);
|
|
||||||
const [colors, setColors] = useState(defaultState.colors);
|
|
||||||
const [blocks, setBlocks] = useState(defaultState.blocks);
|
|
||||||
|
|
||||||
const reorder = (list, startIndex, endIndex) => {
|
|
||||||
const result = Array.from(list);
|
|
||||||
const [removed] = result.splice(startIndex, 1);
|
|
||||||
result.splice(endIndex, 0, removed);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
const move = (source, destination, droppableSource, droppableDestination) => {
|
|
||||||
const sourceClone = Array.from(source);
|
|
||||||
const destClone = Array.from(destination);
|
|
||||||
const [removed] = sourceClone.splice(droppableSource.index, 1);
|
|
||||||
|
|
||||||
destClone.splice(droppableDestination.index, 0, removed);
|
|
||||||
|
|
||||||
const result = {};
|
|
||||||
result[droppableSource.droppableId] = sourceClone;
|
|
||||||
result[droppableDestination.droppableId] = destClone;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
const onDragEnd = (result) => {
|
|
||||||
const { source, destination } = result;
|
|
||||||
|
|
||||||
if (!destination) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const sInd = +source.droppableId;
|
|
||||||
const dInd = +destination.droppableId;
|
|
||||||
|
|
||||||
if (sInd === dInd) {
|
|
||||||
const items = reorder(blocks[sInd], source.index, destination.index);
|
|
||||||
const newState = [...blocks];
|
|
||||||
newState[sInd] = items;
|
|
||||||
setBlocks(newState);
|
|
||||||
} else {
|
|
||||||
const newResult = move(blocks[sInd], blocks[dInd], source, destination);
|
|
||||||
const newState = [...blocks];
|
|
||||||
newState[sInd] = newResult[sInd];
|
|
||||||
newState[dInd] = newResult[dInd];
|
|
||||||
setBlocks(newState);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const setFixedBlocks = (fixedBlocks) => {
|
|
||||||
const newBlocks = blocks.map((x) =>
|
|
||||||
x.filter((y) => !fixedBlocks.includes(y)),
|
|
||||||
);
|
|
||||||
setBlocks(newBlocks);
|
|
||||||
};
|
|
||||||
|
|
||||||
const setSupportedBlocks = (number) => {
|
|
||||||
if (number === blocks.length) return;
|
|
||||||
|
|
||||||
if (number > blocks.length) {
|
|
||||||
setBlocks([...blocks, []]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (number < blocks.length) {
|
|
||||||
setBlocks([flatten(blocks)]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TemplateContext.Provider
|
|
||||||
value={{
|
|
||||||
colors,
|
|
||||||
blocks,
|
|
||||||
selected,
|
|
||||||
setColors,
|
|
||||||
setBlocks,
|
|
||||||
onDragEnd,
|
|
||||||
setSelected,
|
|
||||||
setFixedBlocks,
|
|
||||||
setSupportedBlocks,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</TemplateContext.Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default TemplateContext;
|
|
||||||
|
|
||||||
export { TemplateProvider };
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { createContext, useEffect, useState } from 'react';
|
import React, { createContext, memo, useEffect, useState } from 'react';
|
||||||
|
|
||||||
const COLOR_CONFIG = {
|
const COLOR_CONFIG = {
|
||||||
light: {
|
light: {
|
||||||
|
|
@ -62,4 +62,6 @@ const ThemeProvider = ({ children }) => {
|
||||||
|
|
||||||
export default ThemeContext;
|
export default ThemeContext;
|
||||||
|
|
||||||
export { ThemeProvider };
|
const memoizedProvider = memo(ThemeProvider);
|
||||||
|
|
||||||
|
export { memoizedProvider as ThemeProvider };
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import firebase from 'gatsby-plugin-firebase';
|
import firebase from 'gatsby-plugin-firebase';
|
||||||
import { pick } from 'lodash';
|
import { pick } from 'lodash';
|
||||||
import React, { createContext, useEffect, useState } from 'react';
|
import React, { createContext, memo, useEffect, useState } from 'react';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import useAuthState from '../hooks/useAuthState';
|
import useAuthState from '../hooks/useAuthState';
|
||||||
|
|
||||||
|
|
@ -77,4 +77,6 @@ const UserProvider = ({ children }) => {
|
||||||
|
|
||||||
export default UserContext;
|
export default UserContext;
|
||||||
|
|
||||||
export { UserProvider };
|
const memoizedProvider = memo(UserProvider);
|
||||||
|
|
||||||
|
export { memoizedProvider as UserProvider };
|
||||||
|
|
|
||||||
|
|
@ -7,17 +7,6 @@ import {
|
||||||
IoMdDocument,
|
IoMdDocument,
|
||||||
} from 'react-icons/io';
|
} from 'react-icons/io';
|
||||||
import { MdPerson, MdSchool, MdTranslate } from 'react-icons/md';
|
import { MdPerson, MdSchool, MdTranslate } from 'react-icons/md';
|
||||||
import Awards from '../components/builder/sections/Awards';
|
|
||||||
import Certifications from '../components/builder/sections/Certifications';
|
|
||||||
import Education from '../components/builder/sections/Education';
|
|
||||||
import Hobbies from '../components/builder/sections/Hobbies';
|
|
||||||
import Languages from '../components/builder/sections/Languages';
|
|
||||||
import Objective from '../components/builder/sections/Objective';
|
|
||||||
import Profile from '../components/builder/sections/Profile';
|
|
||||||
import References from '../components/builder/sections/References';
|
|
||||||
import Skills from '../components/builder/sections/Skills';
|
|
||||||
import Social from '../components/builder/sections/Social';
|
|
||||||
import Work from '../components/builder/sections/Work';
|
|
||||||
import ModalEvents from '../constants/ModalEvents';
|
import ModalEvents from '../constants/ModalEvents';
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
|
|
@ -25,75 +14,64 @@ export default [
|
||||||
id: 'profile',
|
id: 'profile',
|
||||||
name: 'Profile',
|
name: 'Profile',
|
||||||
icon: MdPerson,
|
icon: MdPerson,
|
||||||
component: Profile,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'social',
|
id: 'social',
|
||||||
name: 'Social Network',
|
name: 'Social Network',
|
||||||
icon: AiOutlineTwitter,
|
icon: AiOutlineTwitter,
|
||||||
component: Social,
|
|
||||||
event: ModalEvents.SOCIAL_MODAL,
|
event: ModalEvents.SOCIAL_MODAL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'objective',
|
id: 'objective',
|
||||||
name: 'Objective',
|
name: 'Objective',
|
||||||
icon: IoMdDocument,
|
icon: IoMdDocument,
|
||||||
component: Objective,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'work',
|
id: 'work',
|
||||||
name: 'Work Experience',
|
name: 'Work Experience',
|
||||||
icon: IoMdBriefcase,
|
icon: IoMdBriefcase,
|
||||||
component: Work,
|
|
||||||
event: ModalEvents.WORK_MODAL,
|
event: ModalEvents.WORK_MODAL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'education',
|
id: 'education',
|
||||||
name: 'Education',
|
name: 'Education',
|
||||||
icon: MdSchool,
|
icon: MdSchool,
|
||||||
component: Education,
|
|
||||||
event: ModalEvents.EDUCATION_MODAL,
|
event: ModalEvents.EDUCATION_MODAL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'awards',
|
id: 'awards',
|
||||||
name: 'Awards',
|
name: 'Awards',
|
||||||
icon: FaAward,
|
icon: FaAward,
|
||||||
component: Awards,
|
|
||||||
event: ModalEvents.AWARD_MODAL,
|
event: ModalEvents.AWARD_MODAL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'certifications',
|
id: 'certifications',
|
||||||
name: 'Certifications',
|
name: 'Certifications',
|
||||||
icon: AiFillSafetyCertificate,
|
icon: AiFillSafetyCertificate,
|
||||||
component: Certifications,
|
|
||||||
event: ModalEvents.CERTIFICATION_MODAL,
|
event: ModalEvents.CERTIFICATION_MODAL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'skills',
|
id: 'skills',
|
||||||
name: 'Skills',
|
name: 'Skills',
|
||||||
icon: BsTools,
|
icon: BsTools,
|
||||||
component: Skills,
|
|
||||||
event: ModalEvents.SKILL_MODAL,
|
event: ModalEvents.SKILL_MODAL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'hobbies',
|
id: 'hobbies',
|
||||||
name: 'Hobbies',
|
name: 'Hobbies',
|
||||||
icon: IoLogoGameControllerB,
|
icon: IoLogoGameControllerB,
|
||||||
component: Hobbies,
|
|
||||||
event: ModalEvents.HOBBY_MODAL,
|
event: ModalEvents.HOBBY_MODAL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'languages',
|
id: 'languages',
|
||||||
name: 'Languages',
|
name: 'Languages',
|
||||||
icon: MdTranslate,
|
icon: MdTranslate,
|
||||||
component: Languages,
|
|
||||||
event: ModalEvents.LANGUAGE_MODAL,
|
event: ModalEvents.LANGUAGE_MODAL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'references',
|
id: 'references',
|
||||||
name: 'References',
|
name: 'References',
|
||||||
icon: FaUserFriends,
|
icon: FaUserFriends,
|
||||||
component: References,
|
|
||||||
event: ModalEvents.REFERENCE_MODAL,
|
event: ModalEvents.REFERENCE_MODAL,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
9
src/data/rightSections.js
Normal file
9
src/data/rightSections.js
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { MdDashboard } from 'react-icons/md';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
id: 'layout',
|
||||||
|
name: 'Layout',
|
||||||
|
icon: MdDashboard,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { navigate } from 'gatsby';
|
import { navigate } from 'gatsby';
|
||||||
import React, { useContext, useEffect, useState } from 'react';
|
import React, { memo, useContext, useEffect, useState } from 'react';
|
||||||
import Button from '../components/shared/Button';
|
import Button from '../components/shared/Button';
|
||||||
import ModalContext from '../contexts/ModalContext';
|
import ModalContext from '../contexts/ModalContext';
|
||||||
import UserContext from '../contexts/UserContext';
|
import UserContext from '../contexts/UserContext';
|
||||||
|
|
@ -63,4 +63,4 @@ const AuthModal = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AuthModal;
|
export default memo(AuthModal);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import Backdrop from '@material-ui/core/Backdrop';
|
||||||
import Fade from '@material-ui/core/Fade';
|
import Fade from '@material-ui/core/Fade';
|
||||||
import Modal from '@material-ui/core/Modal';
|
import Modal from '@material-ui/core/Modal';
|
||||||
import { isFunction } from 'lodash';
|
import { isFunction } from 'lodash';
|
||||||
import React, { forwardRef, useImperativeHandle } from 'react';
|
import React, { forwardRef, memo, useImperativeHandle } from 'react';
|
||||||
import { MdClose } from 'react-icons/md';
|
import { MdClose } from 'react-icons/md';
|
||||||
import Button from '../components/shared/Button';
|
import Button from '../components/shared/Button';
|
||||||
import { handleKeyUp } from '../utils';
|
import { handleKeyUp } from '../utils';
|
||||||
|
|
@ -61,4 +61,4 @@ const BaseModal = forwardRef(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
export default BaseModal;
|
export default memo(BaseModal);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { useFormikContext } from 'formik';
|
import { useFormikContext } from 'formik';
|
||||||
import { isEmpty, isFunction } from 'lodash';
|
import { isEmpty, isFunction } from 'lodash';
|
||||||
import React, { useContext, useEffect, useRef, useState } from 'react';
|
import React, { memo, useContext, useEffect, useRef, useState } from 'react';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import Button from '../components/shared/Button';
|
import Button from '../components/shared/Button';
|
||||||
import ModalContext from '../contexts/ModalContext';
|
import ModalContext from '../contexts/ModalContext';
|
||||||
|
|
@ -101,4 +101,4 @@ const DataModal = ({
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DataModal;
|
export default memo(DataModal);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import AuthModal from './AuthModal';
|
import AuthModal from './AuthModal';
|
||||||
import ResumeModal from './ResumeModal';
|
import ResumeModal from './ResumeModal';
|
||||||
import AwardModal from './sections/AwardModal';
|
import AwardModal from './sections/AwardModal';
|
||||||
|
|
@ -29,4 +29,4 @@ const ModalRegistrar = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ModalRegistrar;
|
export default memo(ModalRegistrar);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Formik } from 'formik';
|
import { Formik } from 'formik';
|
||||||
import React, { useContext } from 'react';
|
import React, { memo, useContext } from 'react';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import Input from '../components/shared/Input';
|
import Input from '../components/shared/Input';
|
||||||
import ModalEvents from '../constants/ModalEvents';
|
import ModalEvents from '../constants/ModalEvents';
|
||||||
|
|
@ -56,4 +56,4 @@ const ResumeModal = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ResumeModal;
|
export default memo(ResumeModal);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Formik } from 'formik';
|
import { Formik } from 'formik';
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import Input from '../../components/shared/Input';
|
import Input from '../../components/shared/Input';
|
||||||
import ModalEvents from '../../constants/ModalEvents';
|
import ModalEvents from '../../constants/ModalEvents';
|
||||||
|
|
@ -66,4 +66,4 @@ const AwardModal = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AwardModal;
|
export default memo(AwardModal);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Formik } from 'formik';
|
import { Formik } from 'formik';
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import Input from '../../components/shared/Input';
|
import Input from '../../components/shared/Input';
|
||||||
import ModalEvents from '../../constants/ModalEvents';
|
import ModalEvents from '../../constants/ModalEvents';
|
||||||
|
|
@ -66,4 +66,4 @@ const CertificateModal = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CertificateModal;
|
export default memo(CertificateModal);
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { Field, FieldArray, Formik } from 'formik';
|
import { FieldArray, Formik } from 'formik';
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import { MdAdd } from 'react-icons/md';
|
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import Input from '../../components/shared/Input';
|
import Input from '../../components/shared/Input';
|
||||||
|
import InputArray from '../../components/shared/InputArray';
|
||||||
import ModalEvents from '../../constants/ModalEvents';
|
import ModalEvents from '../../constants/ModalEvents';
|
||||||
import { getFieldProps, handleKeyUp } from '../../utils';
|
import { getFieldProps } from '../../utils';
|
||||||
import DataModal from '../DataModal';
|
import DataModal from '../DataModal';
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
|
|
@ -90,49 +90,16 @@ const EducationModal = () => {
|
||||||
|
|
||||||
<FieldArray
|
<FieldArray
|
||||||
name="courses"
|
name="courses"
|
||||||
render={(arrayHelpers) => {
|
render={(helpers) => (
|
||||||
const handleClickAdd = () => {
|
<InputArray
|
||||||
formik.values.temp && arrayHelpers.push(formik.values.temp);
|
formik={formik}
|
||||||
formik.setFieldValue('temp', '');
|
schema={schema}
|
||||||
};
|
helpers={helpers}
|
||||||
|
label="Courses"
|
||||||
return (
|
path="courses"
|
||||||
<div className="col-span-2">
|
placeholder="Data Structures & Algortihms"
|
||||||
<label>
|
/>
|
||||||
<span>Courses</span>
|
)}
|
||||||
|
|
||||||
{formik.values.courses &&
|
|
||||||
formik.values.courses.map((x, i) => (
|
|
||||||
<Field key={x} name={`courses.${i}`}>
|
|
||||||
{({ field, meta }) => (
|
|
||||||
<Input
|
|
||||||
className="my-1"
|
|
||||||
showDeleteItemButton
|
|
||||||
onDeleteItem={() => arrayHelpers.remove(i)}
|
|
||||||
{...field}
|
|
||||||
{...meta}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Field>
|
|
||||||
))}
|
|
||||||
|
|
||||||
<div className="flex items-center">
|
|
||||||
<Input
|
|
||||||
placeholder="Algorithms & Data Structures"
|
|
||||||
{...getFieldProps(formik, schema, 'temp')}
|
|
||||||
/>
|
|
||||||
<MdAdd
|
|
||||||
size="18px"
|
|
||||||
tabIndex="0"
|
|
||||||
className="mx-4 cursor-pointer opacity-50 hover:opacity-75"
|
|
||||||
onKeyUp={(e) => handleKeyUp(e, handleClickAdd)}
|
|
||||||
onClick={handleClickAdd}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</DataModal>
|
</DataModal>
|
||||||
|
|
@ -141,4 +108,4 @@ const EducationModal = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default EducationModal;
|
export default memo(EducationModal);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Formik } from 'formik';
|
import { Formik } from 'formik';
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import Input from '../../components/shared/Input';
|
import Input from '../../components/shared/Input';
|
||||||
import ModalEvents from '../../constants/ModalEvents';
|
import ModalEvents from '../../constants/ModalEvents';
|
||||||
|
|
@ -41,4 +41,4 @@ const HobbyModal = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default HobbyModal;
|
export default memo(HobbyModal);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Formik } from 'formik';
|
import { Formik } from 'formik';
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import Input from '../../components/shared/Input';
|
import Input from '../../components/shared/Input';
|
||||||
import ModalEvents from '../../constants/ModalEvents';
|
import ModalEvents from '../../constants/ModalEvents';
|
||||||
|
|
@ -48,4 +48,4 @@ const LanguageModal = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LanguageModal;
|
export default memo(LanguageModal);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Formik } from 'formik';
|
import { Formik } from 'formik';
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import Input from '../../components/shared/Input';
|
import Input from '../../components/shared/Input';
|
||||||
import ModalEvents from '../../constants/ModalEvents';
|
import ModalEvents from '../../constants/ModalEvents';
|
||||||
|
|
@ -73,4 +73,4 @@ const ReferenceModal = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ReferenceModal;
|
export default memo(ReferenceModal);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Formik } from 'formik';
|
import { Formik } from 'formik';
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import Input from '../../components/shared/Input';
|
import Input from '../../components/shared/Input';
|
||||||
import ModalEvents from '../../constants/ModalEvents';
|
import ModalEvents from '../../constants/ModalEvents';
|
||||||
|
|
@ -59,4 +59,4 @@ const SkillModal = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SkillModal;
|
export default memo(SkillModal);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Formik } from 'formik';
|
import { Formik } from 'formik';
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import Input from '../../components/shared/Input';
|
import Input from '../../components/shared/Input';
|
||||||
import ModalEvents from '../../constants/ModalEvents';
|
import ModalEvents from '../../constants/ModalEvents';
|
||||||
|
|
@ -62,4 +62,4 @@ const SocialModal = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SocialModal;
|
export default memo(SocialModal);
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { Field, FieldArray, Formik } from 'formik';
|
import { FieldArray, Formik } from 'formik';
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import { MdAdd } from 'react-icons/md';
|
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import Input from '../../components/shared/Input';
|
import Input from '../../components/shared/Input';
|
||||||
|
import InputArray from '../../components/shared/InputArray';
|
||||||
import ModalEvents from '../../constants/ModalEvents';
|
import ModalEvents from '../../constants/ModalEvents';
|
||||||
import { getFieldProps, handleKeyUp } from '../../utils';
|
import { getFieldProps } from '../../utils';
|
||||||
import DataModal from '../DataModal';
|
import DataModal from '../DataModal';
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
|
|
@ -92,49 +92,16 @@ const WorkModal = () => {
|
||||||
|
|
||||||
<FieldArray
|
<FieldArray
|
||||||
name="highlights"
|
name="highlights"
|
||||||
render={(arrayHelpers) => {
|
render={(helpers) => (
|
||||||
const handleClickAdd = () => {
|
<InputArray
|
||||||
formik.values.temp && arrayHelpers.push(formik.values.temp);
|
formik={formik}
|
||||||
formik.setFieldValue('temp', '');
|
schema={schema}
|
||||||
};
|
helpers={helpers}
|
||||||
|
label="Highlights"
|
||||||
return (
|
path="highlights"
|
||||||
<div className="col-span-2">
|
placeholder="Worked passionately in customer service in a high volume restaurant."
|
||||||
<label>
|
/>
|
||||||
<span>Highlights</span>
|
)}
|
||||||
|
|
||||||
{formik.values.highlights &&
|
|
||||||
formik.values.highlights.map((x, i) => (
|
|
||||||
<Field key={x} name={`highlights.${i}`}>
|
|
||||||
{({ field, meta }) => (
|
|
||||||
<Input
|
|
||||||
className="my-1"
|
|
||||||
showDeleteItemButton
|
|
||||||
onDeleteItem={() => arrayHelpers.remove(i)}
|
|
||||||
{...field}
|
|
||||||
{...meta}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Field>
|
|
||||||
))}
|
|
||||||
|
|
||||||
<div className="flex items-center">
|
|
||||||
<Input
|
|
||||||
placeholder="Worked passionately in customer service in a high volume restaurant."
|
|
||||||
{...getFieldProps(formik, schema, 'temp')}
|
|
||||||
/>
|
|
||||||
<MdAdd
|
|
||||||
size="18px"
|
|
||||||
tabIndex="0"
|
|
||||||
className="mx-4 cursor-pointer opacity-50 hover:opacity-75"
|
|
||||||
onKeyUp={(e) => handleKeyUp(e, handleClickAdd)}
|
|
||||||
onClick={handleClickAdd}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</DataModal>
|
</DataModal>
|
||||||
|
|
@ -143,4 +110,4 @@ const WorkModal = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default WorkModal;
|
export default memo(WorkModal);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { navigate } from 'gatsby';
|
import { navigate } from 'gatsby';
|
||||||
import { useEffect } from 'react';
|
import { memo, useEffect } from 'react';
|
||||||
|
|
||||||
const NotFound = () => {
|
const NotFound = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -9,4 +9,4 @@ const NotFound = () => {
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default NotFound;
|
export default memo(NotFound);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Redirect, Router } from '@reach/router';
|
import { Redirect, Router } from '@reach/router';
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import PrivateRoute from '../components/router/PrivateRoute';
|
import PrivateRoute from '../components/router/PrivateRoute';
|
||||||
import Wrapper from '../components/shared/Wrapper';
|
import Wrapper from '../components/shared/Wrapper';
|
||||||
import NotFound from './404';
|
import NotFound from './404';
|
||||||
|
|
@ -16,4 +16,4 @@ const App = () => (
|
||||||
</Router>
|
</Router>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
);
|
);
|
||||||
export default App;
|
export default memo(App);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { navigate } from 'gatsby';
|
import { navigate } from 'gatsby';
|
||||||
import React, { useContext, useEffect, useMemo, useState } from 'react';
|
import React, { memo, useContext, useEffect, useMemo, useState } from 'react';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import Artboard from '../../components/builder/center/Artboard';
|
import Artboard from '../../components/builder/center/Artboard';
|
||||||
import LeftSidebar from '../../components/builder/left/LeftSidebar';
|
import LeftSidebar from '../../components/builder/left/LeftSidebar';
|
||||||
|
|
@ -51,4 +51,4 @@ const Builder = ({ id }) => {
|
||||||
}, [loading]);
|
}, [loading]);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Builder;
|
export default memo(Builder);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import firebase from 'gatsby-plugin-firebase';
|
import firebase from 'gatsby-plugin-firebase';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { memo, useEffect, useState } from 'react';
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
import CreateResume from '../../components/dashboard/CreateResume';
|
import CreateResume from '../../components/dashboard/CreateResume';
|
||||||
import ResumePreview from '../../components/dashboard/ResumePreview';
|
import ResumePreview from '../../components/dashboard/ResumePreview';
|
||||||
|
|
@ -58,4 +58,4 @@ const Dashboard = ({ user }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Dashboard;
|
export default memo(Dashboard);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
import Hero from '../components/landing/Hero';
|
import Hero from '../components/landing/Hero';
|
||||||
import Wrapper from '../components/shared/Wrapper';
|
import Wrapper from '../components/shared/Wrapper';
|
||||||
|
|
@ -68,4 +68,4 @@ const Feature = ({ title, children }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Home;
|
export default memo(Home);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import React, { memo } from 'react';
|
||||||
import { FaGlobeAmericas, FaPhone } from 'react-icons/fa';
|
import { FaGlobeAmericas, FaPhone } from 'react-icons/fa';
|
||||||
import { MdEmail } from 'react-icons/md';
|
import { MdEmail } from 'react-icons/md';
|
||||||
|
|
||||||
|
|
@ -57,4 +57,4 @@ const Onyx = ({ data, layout, colors }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Onyx;
|
export default memo(Onyx);
|
||||||
|
|
|
||||||
|
|
@ -31,3 +31,30 @@ export const getFieldProps = (formik, schema, name) => ({
|
||||||
isRequired: get(schema, `fields.${name}._exclusive.required`),
|
isRequired: get(schema, `fields.${name}._exclusive.required`),
|
||||||
...formik.getFieldProps(name),
|
...formik.getFieldProps(name),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const reorder = (list, startIndex, endIndex) => {
|
||||||
|
const result = Array.from(list);
|
||||||
|
const [removed] = result.splice(startIndex, 1);
|
||||||
|
result.splice(endIndex, 0, removed);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const move = (
|
||||||
|
source,
|
||||||
|
destination,
|
||||||
|
droppableSource,
|
||||||
|
droppableDestination,
|
||||||
|
) => {
|
||||||
|
const sourceClone = Array.from(source);
|
||||||
|
const destClone = Array.from(destination);
|
||||||
|
const [removed] = sourceClone.splice(droppableSource.index, 1);
|
||||||
|
|
||||||
|
destClone.splice(droppableDestination.index, 0, removed);
|
||||||
|
|
||||||
|
const result = {};
|
||||||
|
result[droppableSource.droppableId] = sourceClone;
|
||||||
|
result[droppableDestination.droppableId] = destClone;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user