initial commit, completed 40% of first milestone

This commit is contained in:
Amruth Pillai
2020-03-25 02:52:24 +05:30
parent dfeb67cda9
commit 25a6740c24
36 changed files with 55170 additions and 154 deletions

25
src/components/App/App.js Normal file
View File

@ -0,0 +1,25 @@
/* eslint-disable no-unused-vars */
import React from 'react';
import Onyx from '../../templates/onyx/Onyx';
import LeftSidebar from '../LeftSidebar/LeftSidebar';
const App = () => {
return (
<div className="grid grid-cols-5 items-center">
<LeftSidebar />
<div className="col-span-3">
<div id="page" className="p-12 my-auto mx-auto shadow-2xl">
<Onyx />
</div>
</div>
<div id="rightSidebar" className="h-screen bg-white col-span-1 shadow-2xl overflow-scroll">
This is the right sidebar
</div>
</div>
);
};
export default App;

View File

@ -0,0 +1,76 @@
import React, { useState, useEffect, useContext } from 'react';
import TabBar from '../../shared/TabBar';
import ProfileTab from './tabs/Profile';
import ObjectiveTab from './tabs/Objective';
import WorkTab from './tabs/Work';
import AppContext from '../../context/AppContext';
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';
const tabs = [
'Profile',
'Objective',
'Work Experience',
'Education',
'Awards',
'Certifications',
'Skills',
'Extras',
];
const LeftSidebar = () => {
const context = useContext(AppContext);
const { state, dispatch } = context;
const { data } = state;
const [currentTab, setCurrentTab] = useState('Extras');
const onChange = (key, value) => {
dispatch({
type: 'on_input',
payload: {
key,
value,
},
});
};
useEffect(() => {
dispatch({ type: 'populate_starter' });
}, [dispatch]);
const renderTabs = () => {
switch (currentTab) {
case 'Profile':
return <ProfileTab data={data} onChange={onChange} />;
case 'Objective':
return <ObjectiveTab data={data} onChange={onChange} />;
case 'Work Experience':
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 'Extras':
return <ExtrasTab data={data} onChange={onChange} />;
default:
return null;
}
};
return (
<div id="leftSidebar" className="h-screen bg-white col-span-1 shadow-2xl overflow-y-scroll">
<TabBar tabs={tabs} currentTab={currentTab} setCurrentTab={setCurrentTab} />
<div className="px-6 pb-6">{renderTabs()}</div>
</div>
);
};
export default LeftSidebar;

View File

@ -0,0 +1,197 @@
import React, { useState, useContext } from 'react';
import { v4 as uuidv4 } from 'uuid';
import set from 'lodash/set';
import TextField from '../../../shared/TextField';
import AppContext from '../../../context/AppContext';
const AwardsTab = ({ data, onChange }) => {
const context = useContext(AppContext);
const { dispatch } = context;
return (
<>
{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 dispatch={dispatch} />
</>
);
};
const AddItem = ({ dispatch }) => {
const [isOpen, setOpen] = useState(false);
const [item, setItem] = useState({
id: uuidv4(),
title: '',
subtitle: '',
});
const onChange = (key, value) => setItem(set({ ...item }, key, value));
const addItem = () => {
dispatch({
type: 'add_item',
payload: {
key: 'awards',
value: item,
},
});
setItem({
id: uuidv4(),
title: '',
subtitle: '',
});
setOpen(false);
};
return (
<div className="border border-gray-200 rounded p-5">
<div
className="flex justify-between items-center cursor-pointer"
onClick={() => setOpen(!isOpen)}
>
<h6 className="text-sm font-medium">Add Award</h6>
<i className="material-icons">{isOpen ? 'expand_less' : 'expand_more'}</i>
</div>
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<TextField
label="Title"
placeholder="Math &amp; Science Olympiad"
value={item.title}
onChange={v => onChange('title', v)}
/>
<TextField
label="Subtitle"
placeholder="First Place, International Level"
value={item.subtitle}
onChange={v => onChange('subtitle', v)}
/>
<button
type="button"
onClick={addItem}
className="mt-4 bg-gray-600 hover:bg-gray-700 text-white text-sm font-medium py-2 px-5 rounded"
>
<div className="flex items-center">
<i className="material-icons mr-2 font-bold text-base">add</i>
<span className="text-sm">Add</span>
</div>
</button>
</div>
</div>
);
};
const Item = ({ item, index, onChange, dispatch, first, last }) => {
const [isOpen, setOpen] = useState(false);
const identifier = `data.awards.items[${index}]`;
const deleteItem = () =>
dispatch({
type: 'delete_item',
payload: {
key: 'awards',
value: item,
},
});
const moveItemUp = () =>
dispatch({
type: 'move_item_up',
payload: {
key: 'awards',
value: item,
},
});
const moveItemDown = () =>
dispatch({
type: 'move_item_down',
payload: {
key: 'awards',
value: item,
},
});
return (
<div className="my-4 border border-gray-200 rounded p-5">
<div
className="flex justify-between items-center cursor-pointer"
onClick={() => setOpen(!isOpen)}
>
<h6 className="text-sm font-medium">{item.title}</h6>
<i className="material-icons">{isOpen ? 'expand_less' : 'expand_more'}</i>
</div>
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<TextField
label="Title"
placeholder="Math &amp; Science Olympiad"
value={item.title}
onChange={v => onChange(`${identifier}.title`, v)}
/>
<TextField
label="Subtitle"
placeholder="First Place, International Level"
value={item.subtitle}
onChange={v => onChange(`${identifier}.subtitle`, v)}
/>
<div className="mt-6 flex justify-between">
<button
type="button"
onClick={deleteItem}
className="bg-red-600 hover:bg-red-700 text-white text-sm font-medium py-2 px-5 rounded"
>
<div className="flex items-center">
<i className="material-icons mr-2 font-bold text-base">delete</i>
<span className="text-sm">Delete</span>
</div>
</button>
<div className="flex">
{!first && (
<button
type="button"
onClick={moveItemUp}
className="bg-gray-600 hover:bg-gray-700 text-white text-sm font-medium py-2 px-4 rounded mr-2"
>
<div className="flex items-center">
<i className="material-icons font-bold text-base">arrow_upward</i>
</div>
</button>
)}
{!last && (
<button
type="button"
onClick={moveItemDown}
className="bg-gray-600 hover:bg-gray-700 text-white text-sm font-medium py-2 px-4 rounded"
>
<div className="flex items-center">
<i className="material-icons font-bold text-base">arrow_downward</i>
</div>
</button>
)}
</div>
</div>
</div>
</div>
);
};
export default AwardsTab;

View File

@ -0,0 +1,197 @@
import React, { useState, useContext } from 'react';
import { v4 as uuidv4 } from 'uuid';
import set from 'lodash/set';
import TextField from '../../../shared/TextField';
import AppContext from '../../../context/AppContext';
const CertificationsTab = ({ data, onChange }) => {
const context = useContext(AppContext);
const { dispatch } = context;
return (
<>
{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 dispatch={dispatch} />
</>
);
};
const AddItem = ({ dispatch }) => {
const [isOpen, setOpen] = useState(false);
const [item, setItem] = useState({
id: uuidv4(),
title: '',
subtitle: '',
});
const onChange = (key, value) => setItem(set({ ...item }, key, value));
const addItem = () => {
dispatch({
type: 'add_item',
payload: {
key: 'certifications',
value: item,
},
});
setItem({
id: uuidv4(),
title: '',
subtitle: '',
});
setOpen(false);
};
return (
<div className="border border-gray-200 rounded p-5">
<div
className="flex justify-between items-center cursor-pointer"
onClick={() => setOpen(!isOpen)}
>
<h6 className="text-sm font-medium">Add Certification</h6>
<i className="material-icons">{isOpen ? 'expand_less' : 'expand_more'}</i>
</div>
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<TextField
label="Title"
placeholder="Android Development Nanodegree"
value={item.title}
onChange={v => onChange('title', v)}
/>
<TextField
label="Subtitle"
placeholder="Udacity"
value={item.subtitle}
onChange={v => onChange('subtitle', v)}
/>
<button
type="button"
onClick={addItem}
className="mt-4 bg-gray-600 hover:bg-gray-700 text-white text-sm font-medium py-2 px-5 rounded"
>
<div className="flex items-center">
<i className="material-icons mr-2 font-bold text-base">add</i>
<span className="text-sm">Add</span>
</div>
</button>
</div>
</div>
);
};
const Item = ({ item, index, onChange, dispatch, first, last }) => {
const [isOpen, setOpen] = useState(false);
const identifier = `data.certifications.items[${index}]`;
const deleteItem = () =>
dispatch({
type: 'delete_item',
payload: {
key: 'certifications',
value: item,
},
});
const moveItemUp = () =>
dispatch({
type: 'move_item_up',
payload: {
key: 'certifications',
value: item,
},
});
const moveItemDown = () =>
dispatch({
type: 'move_item_down',
payload: {
key: 'certifications',
value: item,
},
});
return (
<div className="my-4 border border-gray-200 rounded p-5">
<div
className="flex justify-between items-center cursor-pointer"
onClick={() => setOpen(!isOpen)}
>
<h6 className="text-sm font-medium">{item.title}</h6>
<i className="material-icons">{isOpen ? 'expand_less' : 'expand_more'}</i>
</div>
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<TextField
label="Title"
placeholder="Android Development Nanodegree"
value={item.title}
onChange={v => onChange(`${identifier}.title`, v)}
/>
<TextField
label="Subtitle"
placeholder="Udacity"
value={item.subtitle}
onChange={v => onChange(`${identifier}.subtitle`, v)}
/>
<div className="mt-6 flex justify-between">
<button
type="button"
onClick={deleteItem}
className="bg-red-600 hover:bg-red-700 text-white text-sm font-medium py-2 px-5 rounded"
>
<div className="flex items-center">
<i className="material-icons mr-2 font-bold text-base">delete</i>
<span className="text-sm">Delete</span>
</div>
</button>
<div className="flex">
{!first && (
<button
type="button"
onClick={moveItemUp}
className="bg-gray-600 hover:bg-gray-700 text-white text-sm font-medium py-2 px-4 rounded mr-2"
>
<div className="flex items-center">
<i className="material-icons font-bold text-base">arrow_upward</i>
</div>
</button>
)}
{!last && (
<button
type="button"
onClick={moveItemDown}
className="bg-gray-600 hover:bg-gray-700 text-white text-sm font-medium py-2 px-4 rounded"
>
<div className="flex items-center">
<i className="material-icons font-bold text-base">arrow_downward</i>
</div>
</button>
)}
</div>
</div>
</div>
</div>
);
};
export default CertificationsTab;

View File

@ -0,0 +1,268 @@
import React, { useState, useContext } from 'react';
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';
const EducationTab = ({ data, onChange }) => {
const context = useContext(AppContext);
const { dispatch } = context;
return (
<>
{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 dispatch={dispatch} />
</>
);
};
const AddItem = ({ dispatch }) => {
const [isOpen, setOpen] = useState(false);
const [item, setItem] = useState({
id: uuidv4(),
name: '',
major: '',
start: '',
end: '',
grade: '',
description: '',
});
const onChange = (key, value) => setItem(set({ ...item }, key, value));
const addItem = () => {
dispatch({
type: 'add_item',
payload: {
key: 'education',
value: item,
},
});
setItem({
id: uuidv4(),
title: '',
role: '',
start: '',
end: '',
grade: '',
description: '',
});
setOpen(false);
};
return (
<div className="border border-gray-200 rounded p-5">
<div
className="flex justify-between items-center cursor-pointer"
onClick={() => setOpen(!isOpen)}
>
<h6 className="text-sm font-medium">Add Education</h6>
<i className="material-icons">{isOpen ? 'expand_less' : 'expand_more'}</i>
</div>
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<TextField
label="Name"
placeholder="Harvard University"
value={item.name}
onChange={v => onChange('name', v)}
/>
<TextField
label="Major"
placeholder="Masters in Computer Science"
value={item.major}
onChange={v => onChange('major', v)}
/>
<TextField
label="Grade"
placeholder="7.2 CGPA"
value={item.grade}
onChange={v => onChange('grade', v)}
/>
<div className="grid grid-cols-2 col-gap-4">
<TextField
label="Start Date"
placeholder="March 2018"
value={item.start}
onChange={v => onChange('start', v)}
/>
<TextField
label="End Date"
placeholder="May 2020"
value={item.end}
onChange={v => onChange('end', v)}
/>
</div>
<TextArea
rows="5"
label="Description"
placeholder="You can write about projects or special credit classes that you took while studying at this school."
value={item.description}
onChange={v => onChange('description', v)}
/>
<button
type="button"
onClick={addItem}
className="mt-4 bg-gray-600 hover:bg-gray-700 text-white text-sm font-medium py-2 px-5 rounded"
>
<div className="flex items-center">
<i className="material-icons mr-2 font-bold text-base">add</i>
<span className="text-sm">Add</span>
</div>
</button>
</div>
</div>
);
};
const Item = ({ item, index, onChange, dispatch, first, last }) => {
const [isOpen, setOpen] = useState(false);
const identifier = `data.education.items[${index}]`;
const deleteItem = () =>
dispatch({
type: 'delete_item',
payload: {
key: 'education',
value: item,
},
});
const moveItemUp = () =>
dispatch({
type: 'move_item_up',
payload: {
key: 'education',
value: item,
},
});
const moveItemDown = () =>
dispatch({
type: 'move_item_down',
payload: {
key: 'education',
value: item,
},
});
return (
<div className="my-4 border border-gray-200 rounded p-5">
<div
className="flex justify-between items-center cursor-pointer"
onClick={() => setOpen(!isOpen)}
>
<h6 className="text-sm font-medium">{item.name}</h6>
<i className="material-icons">{isOpen ? 'expand_less' : 'expand_more'}</i>
</div>
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<TextField
label="Name"
placeholder="Harvard University"
value={item.name}
onChange={v => onChange(`${identifier}.name`, v)}
/>
<TextField
label="Major"
placeholder="Masters in Computer Science"
value={item.major}
onChange={v => onChange(`${identifier}.major`, v)}
/>
<TextField
label="Grade"
placeholder="7.2 CGPA"
value={item.grade}
onChange={v => onChange(`${identifier}.grade`, v)}
/>
<div className="grid grid-cols-2 col-gap-4">
<TextField
label="Start Date"
placeholder="March 2018"
value={item.start}
onChange={v => onChange(`${identifier}.start`, v)}
/>
<TextField
label="End Date"
placeholder="May 2020"
value={item.end}
onChange={v => onChange(`${identifier}.end`, v)}
/>
</div>
<TextArea
rows="5"
label="Description"
placeholder="You can write about projects or special credit classes that you took while studying at this school."
value={item.description}
onChange={v => onChange(`${identifier}.description`, v)}
/>
<div className="mt-6 flex justify-between">
<button
type="button"
onClick={deleteItem}
className="bg-red-600 hover:bg-red-700 text-white text-sm font-medium py-2 px-5 rounded"
>
<div className="flex items-center">
<i className="material-icons mr-2 font-bold text-base">delete</i>
<span className="text-sm">Delete</span>
</div>
</button>
<div className="flex">
{!first && (
<button
type="button"
onClick={moveItemUp}
className="bg-gray-600 hover:bg-gray-700 text-white text-sm font-medium py-2 px-4 rounded mr-2"
>
<div className="flex items-center">
<i className="material-icons font-bold text-base">arrow_upward</i>
</div>
</button>
)}
{!last && (
<button
type="button"
onClick={moveItemDown}
className="bg-gray-600 hover:bg-gray-700 text-white text-sm font-medium py-2 px-4 rounded"
>
<div className="flex items-center">
<i className="material-icons font-bold text-base">arrow_downward</i>
</div>
</button>
)}
</div>
</div>
</div>
</div>
);
};
export default EducationTab;

View File

@ -0,0 +1,197 @@
import React, { useState, useContext } from 'react';
import { v4 as uuidv4 } from 'uuid';
import set from 'lodash/set';
import TextField from '../../../shared/TextField';
import AppContext from '../../../context/AppContext';
const ExtrasTab = ({ data, onChange }) => {
const context = useContext(AppContext);
const { dispatch } = context;
return (
<>
{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 dispatch={dispatch} />
</>
);
};
const AddItem = ({ dispatch }) => {
const [isOpen, setOpen] = useState(false);
const [item, setItem] = useState({
id: uuidv4(),
key: '',
value: '',
});
const onChange = (key, value) => setItem(items => set({ ...items }, key, value));
const addItem = () => {
dispatch({
type: 'add_item',
payload: {
key: 'extras',
value: item,
},
});
setItem({
id: uuidv4(),
key: '',
value: '',
});
setOpen(false);
};
return (
<div className="border border-gray-200 rounded p-5">
<div
className="flex justify-between items-center cursor-pointer"
onClick={() => setOpen(!isOpen)}
>
<h6 className="text-sm font-medium">Add Item</h6>
<i className="material-icons">{isOpen ? 'expand_less' : 'expand_more'}</i>
</div>
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<TextField
label="Key"
placeholder="Date of Birth"
value={item.key}
onChange={v => onChange('key', v)}
/>
<TextField
label="Value"
placeholder="6th August 1995"
value={item.value}
onChange={v => onChange('value', v)}
/>
<button
type="button"
onClick={addItem}
className="mt-4 bg-gray-600 hover:bg-gray-700 text-white text-sm font-medium py-2 px-5 rounded"
>
<div className="flex items-center">
<i className="material-icons mr-2 font-bold text-base">add</i>
<span className="text-sm">Add</span>
</div>
</button>
</div>
</div>
);
};
const Item = ({ item, index, onChange, dispatch, first, last }) => {
const [isOpen, setOpen] = useState(false);
const identifier = `data.extras.items[${index}]`;
const deleteItem = () =>
dispatch({
type: 'delete_item',
payload: {
key: 'extras',
value: item,
},
});
const moveItemUp = () =>
dispatch({
type: 'move_item_up',
payload: {
key: 'extras',
value: item,
},
});
const moveItemDown = () =>
dispatch({
type: 'move_item_down',
payload: {
key: 'extras',
value: item,
},
});
return (
<div className="my-4 border border-gray-200 rounded p-5">
<div
className="flex justify-between items-center cursor-pointer"
onClick={() => setOpen(!isOpen)}
>
<h6 className="text-sm font-medium">{item.key}</h6>
<i className="material-icons">{isOpen ? 'expand_less' : 'expand_more'}</i>
</div>
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<TextField
label="Key"
placeholder="Date of Birth"
value={item.key}
onChange={v => onChange(`${identifier}.key`, v)}
/>
<TextField
label="Value"
placeholder="6th August 1995"
value={item.value}
onChange={v => onChange(`${identifier}.value`, v)}
/>
<div className="mt-6 flex justify-between">
<button
type="button"
onClick={deleteItem}
className="bg-red-600 hover:bg-red-700 text-white text-sm font-medium py-2 px-5 rounded"
>
<div className="flex items-center">
<i className="material-icons mr-2 font-bold text-base">delete</i>
<span className="text-sm">Delete</span>
</div>
</button>
<div className="flex">
{!first && (
<button
type="button"
onClick={moveItemUp}
className="bg-gray-600 hover:bg-gray-700 text-white text-sm font-medium py-2 px-4 rounded mr-2"
>
<div className="flex items-center">
<i className="material-icons font-bold text-base">arrow_upward</i>
</div>
</button>
)}
{!last && (
<button
type="button"
onClick={moveItemDown}
className="bg-gray-600 hover:bg-gray-700 text-white text-sm font-medium py-2 px-4 rounded"
>
<div className="flex items-center">
<i className="material-icons font-bold text-base">arrow_downward</i>
</div>
</button>
)}
</div>
</div>
</div>
</div>
);
};
export default ExtrasTab;

View File

@ -0,0 +1,18 @@
import React from 'react';
import TextArea from '../../../shared/TextArea';
const ObjectiveTab = ({ data, onChange }) => {
return (
<div>
<TextArea
rows="15"
label="Objective"
placeholder="Looking for a challenging role in a reputable organization to utilize my technical, database, and management skills for the growth of the organization as well as to enhance my knowledge about new and emerging trends in the IT sector."
value={data.objective.body}
onChange={v => onChange('data.objective.body', v)}
/>
</div>
);
};
export default ObjectiveTab;

View File

@ -0,0 +1,83 @@
import React from 'react';
import TextField from '../../../shared/TextField';
const ProfileTab = ({ data, onChange }) => (
<div>
<TextField
label="Photo URL"
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
label="First Name"
placeholder="Jane"
value={data.profile.firstName}
onChange={v => onChange('data.profile.firstName', v)}
/>
<TextField
label="Last Name"
placeholder="Doe"
value={data.profile.lastName}
onChange={v => onChange('data.profile.lastName', v)}
/>
</div>
<TextField
label="Subtitle"
placeholder="Full Stack Web Developer"
value={data.profile.subtitle}
onChange={v => onChange('data.profile.subtitle', v)}
/>
<hr className="my-6" />
<TextField
label="Address Line 1"
placeholder="Palladium Complex"
value={data.profile.address.line1}
onChange={v => onChange('data.profile.address.line1', v)}
/>
<TextField
label="Address Line 2"
placeholder="140 E 14th St"
value={data.profile.address.line2}
onChange={v => onChange('data.profile.address.line2', v)}
/>
<TextField
label="Address Line 3"
placeholder="New York, NY 10003 USA"
value={data.profile.address.line3}
onChange={v => onChange('data.profile.address.line3', v)}
/>
<hr className="my-6" />
<TextField
label="Phone Number"
placeholder="+1 541 754 3010"
value={data.profile.phone}
onChange={v => onChange('data.profile.phone', v)}
/>
<TextField
label="Website"
placeholder="google.com"
value={data.profile.website}
onChange={v => onChange('data.profile.website', v)}
/>
<TextField
label="Email Address"
placeholder="john.doe@example.com"
value={data.profile.email}
onChange={v => onChange('data.profile.email', v)}
/>
</div>
);
export default ProfileTab;

View File

@ -0,0 +1,110 @@
import React, { useState, useContext } from 'react';
import AppContext from '../../../context/AppContext';
const SkillsTab = ({ data, onChange }) => {
const context = useContext(AppContext);
const { dispatch } = context;
return (
<>
{data.skills.items.map((x, index) => (
<Item item={x} key={x} index={index} onChange={onChange} dispatch={dispatch} />
))}
<AddItem dispatch={dispatch} />
</>
);
};
const AddItem = ({ dispatch }) => {
const [isOpen, setOpen] = useState(false);
const [item, setItem] = useState('');
const addItem = () => {
dispatch({
type: 'add_item',
payload: {
key: 'skills',
value: item,
},
});
setItem('');
setOpen(false);
};
return (
<div className="mt-4 border border-gray-200 rounded p-5">
<div
className="flex justify-between items-center cursor-pointer"
onClick={() => setOpen(!isOpen)}
>
<h6 className="text-sm font-medium">Add Skill</h6>
<i className="material-icons">{isOpen ? 'expand_less' : 'expand_more'}</i>
</div>
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<div className="mt-4 grid grid-cols-4 col-gap-4">
<div className="col-span-3">
<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="Cooking"
value={item}
onChange={e => setItem(e.target.value)}
type="text"
/>
</div>
<button
type="button"
onClick={addItem}
className="col-span-1 bg-gray-600 hover:bg-gray-700 text-white text-sm font-medium rounded"
>
<div className="flex justify-center items-center">
<i className="material-icons font-bold text-lg">add</i>
</div>
</button>
</div>
</div>
</div>
);
};
const Item = ({ item, index, onChange, dispatch }) => {
const identifier = `data.skills.items[${index}]`;
const deleteItem = () =>
dispatch({
type: 'delete_item',
payload: {
key: 'skills',
value: item,
},
});
return (
<div className="mt-4 grid grid-cols-6">
<div className="col-span-5">
<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="Cooking"
value={item}
onChange={e => onChange(`${identifier}`, e.target.value)}
type="text"
/>
</div>
<button
type="button"
onClick={deleteItem}
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 pr-4">close</i>
</div>
</button>
</div>
);
};
export default SkillsTab;

View File

@ -0,0 +1,252 @@
import React, { useState, useContext } from 'react';
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';
const WorkTab = ({ data, onChange }) => {
const context = useContext(AppContext);
const { dispatch } = context;
return (
<>
{data.work.items.map((x, index) => (
<Item
item={x}
key={x.id}
index={index}
onChange={onChange}
dispatch={dispatch}
first={index === 0}
last={index === data.work.items.length - 1}
/>
))}
<AddItem dispatch={dispatch} />
</>
);
};
const AddItem = ({ dispatch }) => {
const [isOpen, setOpen] = useState(false);
const [item, setItem] = useState({
id: uuidv4(),
title: '',
role: '',
start: '',
end: '',
description: '',
});
const onChange = (key, value) => setItem(set({ ...item }, key, value));
const addItem = () => {
dispatch({
type: 'add_item',
payload: {
key: 'work',
value: item,
},
});
setItem({
id: uuidv4(),
title: '',
role: '',
start: '',
end: '',
description: '',
});
setOpen(false);
};
return (
<div className="border border-gray-200 rounded p-5">
<div
className="flex justify-between items-center cursor-pointer"
onClick={() => setOpen(!isOpen)}
>
<h6 className="text-sm font-medium">Add Work Experience</h6>
<i className="material-icons">{isOpen ? 'expand_less' : 'expand_more'}</i>
</div>
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<TextField
label="Name"
placeholder="Amazon US"
value={item.title}
onChange={v => onChange('title', v)}
/>
<TextField
label="Role"
placeholder="Frontend Web Developer"
value={item.role}
onChange={v => onChange('role', v)}
/>
<div className="grid grid-cols-2 col-gap-4">
<TextField
label="Start Date"
placeholder="March 2018"
value={item.start}
onChange={v => onChange('start', v)}
/>
<TextField
label="End Date"
placeholder="current"
value={item.end}
onChange={v => onChange('end', v)}
/>
</div>
<TextArea
rows="5"
label="Description"
placeholder="You can write about what you specialized in while working at the company and what projects you were a part of."
value={item.description}
onChange={v => onChange('description', v)}
/>
<button
type="button"
onClick={addItem}
className="mt-4 bg-gray-600 hover:bg-gray-700 text-white text-sm font-medium py-2 px-5 rounded"
>
<div className="flex items-center">
<i className="material-icons mr-2 font-bold text-base">add</i>
<span className="text-sm">Add</span>
</div>
</button>
</div>
</div>
);
};
const Item = ({ item, index, onChange, dispatch, first, last }) => {
const [isOpen, setOpen] = useState(false);
const identifier = `data.work.items[${index}]`;
const deleteItem = () =>
dispatch({
type: 'delete_item',
payload: {
key: 'work',
value: item,
},
});
const moveItemUp = () =>
dispatch({
type: 'move_item_up',
payload: {
key: 'work',
value: item,
},
});
const moveItemDown = () =>
dispatch({
type: 'move_item_down',
payload: {
key: 'work',
value: item,
},
});
return (
<div className="my-4 border border-gray-200 rounded p-5">
<div
className="flex justify-between items-center cursor-pointer"
onClick={() => setOpen(!isOpen)}
>
<h6 className="text-sm font-medium">{item.title}</h6>
<i className="material-icons">{isOpen ? 'expand_less' : 'expand_more'}</i>
</div>
<div className={`mt-6 ${isOpen ? 'block' : 'hidden'}`}>
<TextField
label="Name"
placeholder="Amazon US"
value={item.title}
onChange={v => onChange(`${identifier}.title`, v)}
/>
<TextField
label="Role"
placeholder="Frontend Web Developer"
value={item.role}
onChange={v => onChange(`${identifier}.role`, v)}
/>
<div className="grid grid-cols-2 col-gap-4">
<TextField
label="Start Date"
placeholder="March 2018"
value={item.start}
onChange={v => onChange(`${identifier}.start`, v)}
/>
<TextField
label="End Date"
placeholder="current"
value={item.end}
onChange={v => onChange(`${identifier}.end`, v)}
/>
</div>
<TextArea
rows="5"
label="Description"
placeholder="You can write about what you specialized in while working at the company and what projects you were a part of."
value={item.description}
onChange={v => onChange(`${identifier}.description`, v)}
/>
<div className="mt-6 flex justify-between">
<button
type="button"
onClick={deleteItem}
className="bg-red-600 hover:bg-red-700 text-white text-sm font-medium py-2 px-5 rounded"
>
<div className="flex items-center">
<i className="material-icons mr-2 font-bold text-base">delete</i>
<span className="text-sm">Delete</span>
</div>
</button>
<div className="flex">
{!first && (
<button
type="button"
onClick={moveItemUp}
className="bg-gray-600 hover:bg-gray-700 text-white text-sm font-medium py-2 px-4 rounded mr-2"
>
<div className="flex items-center">
<i className="material-icons font-bold text-base">arrow_upward</i>
</div>
</button>
)}
{!last && (
<button
type="button"
onClick={moveItemDown}
className="bg-gray-600 hover:bg-gray-700 text-white text-sm font-medium py-2 px-4 rounded"
>
<div className="flex items-center">
<i className="material-icons font-bold text-base">arrow_downward</i>
</div>
</button>
)}
</div>
</div>
</div>
</div>
);
};
export default WorkTab;