implement functionality to hide/show individual items

This commit is contained in:
Amruth Pillai
2020-03-28 22:19:11 +05:30
parent c287d9f289
commit 8a032845cf
16 changed files with 298 additions and 326 deletions

View File

@ -21,6 +21,7 @@
"jsx-a11y/label-has-associated-control": 0, "jsx-a11y/label-has-associated-control": 0,
"react/jsx-filename-extension": 0, "react/jsx-filename-extension": 0,
"react/no-array-index-key": 0, "react/no-array-index-key": 0,
"no-restricted-syntax": 0,
"no-param-reassign": 0, "no-param-reassign": 0,
"react/prop-types": 0, "react/prop-types": 0,
"no-plusplus": 0 "no-plusplus": 0

View File

@ -30,7 +30,9 @@
"role": "Customer Service Representative", "role": "Customer Service Representative",
"start": "Jan 2013", "start": "Jan 2013",
"end": "July 2018", "end": "July 2018",
"description": "- Organized customer information and account data for business planning and customer service purposes.\n- Created excel spreadsheets to track customer data and perform intense reconciliation process.\n- Received 97% positive customer survey results.\n- Speed on calls was 10% above team average. \n**Key Achievement:** Designed and executed an automatized system for following up with customers, increasing customer retention by 22%." "description": "- Organized customer information and account data for business planning and customer service purposes.\n- Created excel spreadsheets to track customer data and perform intense reconciliation process.\n- Received 97% positive customer survey results.\n- Speed on calls was 10% above team average. \n**Key Achievement:** Designed and executed an automatized system for following up with customers, increasing customer retention by 22%.",
"enabled": true,
"enable": true
}, },
{ {
"id": "bd8649f2-42d1-4424-acaf-a02c08c3322c", "id": "bd8649f2-42d1-4424-acaf-a02c08c3322c",
@ -38,7 +40,9 @@
"role": "Customer Service Representative", "role": "Customer Service Representative",
"start": "Oct 2009", "start": "Oct 2009",
"end": "Dec 2012", "end": "Dec 2012",
"description": "- Worked as a full time customer service rep in a high volume call center.\n- Received \"Associate of the Month\" award six times.\n- Chosen as an example for other associates in trainings. \n**Key Achievement:** Received Customer Appreciation bonus in three of four years." "description": "- Worked as a full time customer service rep in a high volume call center.\n- Received \"Associate of the Month\" award six times.\n- Chosen as an example for other associates in trainings. \n**Key Achievement:** Received Customer Appreciation bonus in three of four years.",
"enabled": true,
"enable": true
}, },
{ {
"id": "dde47711-a7a6-424f-9751-73483a0ef4ed", "id": "dde47711-a7a6-424f-9751-73483a0ef4ed",
@ -46,7 +50,9 @@
"role": "Waitress", "role": "Waitress",
"start": "Aug 2005", "start": "Aug 2005",
"end": "Sep 2009", "end": "Sep 2009",
"description": "- Worked passionately in customer service in a high volume restaurant.\n- Completed the FAST customer service training class.\n- Maintained a high tip average thanks to consistent customer satisfaction." "description": "- Worked passionately in customer service in a high volume restaurant.\n- Completed the FAST customer service training class.\n- Maintained a high tip average thanks to consistent customer satisfaction.",
"enabled": true,
"enable": true
} }
] ]
}, },
@ -61,7 +67,9 @@
"start": "Sep 2001", "start": "Sep 2001",
"end": "Aug 2002", "end": "Aug 2002",
"grade": "", "grade": "",
"description": "" "description": "",
"enabled": true,
"enable": true
}, },
{ {
"id": "71a9852f-ed14-4281-bff2-4db9a2275978", "id": "71a9852f-ed14-4281-bff2-4db9a2275978",
@ -70,7 +78,9 @@
"start": "Sep 1997", "start": "Sep 1997",
"end": "Aug 2001", "end": "Aug 2001",
"grade": "", "grade": "",
"description": "" "description": "",
"enabled": true,
"enable": true
} }
] ]
}, },
@ -82,19 +92,22 @@
"id": "121f0976-18cb-4e46-921d-0e156b6bf7fb", "id": "121f0976-18cb-4e46-921d-0e156b6bf7fb",
"title": "Cast Member of a Musical - Oklahoma", "title": "Cast Member of a Musical - Oklahoma",
"subtitle": "Winter, 2007", "subtitle": "Winter, 2007",
"description": "" "description": "",
"enable": true
}, },
{ {
"id": "e5f27346-72ad-4d4f-bab3-726a111e4932", "id": "e5f27346-72ad-4d4f-bab3-726a111e4932",
"title": "Class Representative to ASB", "title": "Class Representative to ASB",
"subtitle": "Fall, 2008", "subtitle": "Fall, 2008",
"description": "" "description": "",
"enable": true
}, },
{ {
"id": "f71ba9bc-8c14-46b5-99dd-e1333e9aceb9", "id": "f71ba9bc-8c14-46b5-99dd-e1333e9aceb9",
"title": "Most Improved - Varsity Soccer", "title": "Most Improved - Varsity Soccer",
"subtitle": "Fall, 2007", "subtitle": "Fall, 2007",
"description": "" "description": "",
"enable": true
} }
] ]
}, },
@ -106,19 +119,22 @@
"id": "e5170d99-b21d-4131-a7dc-26a4670037f5", "id": "e5170d99-b21d-4131-a7dc-26a4670037f5",
"title": "CCNP", "title": "CCNP",
"subtitle": "Cisco Systems", "subtitle": "Cisco Systems",
"description": "" "description": "",
"enable": true
}, },
{ {
"id": "788e4042-9ecb-40c5-849d-7688b4e23888", "id": "788e4042-9ecb-40c5-849d-7688b4e23888",
"title": "VCP6-DCV", "title": "VCP6-DCV",
"subtitle": "VMWare", "subtitle": "VMWare",
"description": "" "description": "",
"enable": true
}, },
{ {
"id": "97a1a8d9-3c03-47fb-93ab-e84f864ffe17", "id": "97a1a8d9-3c03-47fb-93ab-e84f864ffe17",
"title": "DCUCI Exam", "title": "DCUCI Exam",
"subtitle": "", "subtitle": "",
"description": "" "description": "",
"enable": true
} }
] ]
}, },
@ -141,22 +157,26 @@
{ {
"id": "9d34cfcb-c9f0-4d25-ab27-cf81652dd1d0", "id": "9d34cfcb-c9f0-4d25-ab27-cf81652dd1d0",
"key": "English (US)", "key": "English (US)",
"value": 5 "value": 5,
"enable": true
}, },
{ {
"id": "3511a86b-7ea9-44ac-8144-6acc7f3bd54f", "id": "3511a86b-7ea9-44ac-8144-6acc7f3bd54f",
"key": "Spanish", "key": "Spanish",
"value": 4 "value": 4,
"enable": true
}, },
{ {
"id": "d1e17542-f7cc-473a-aa0e-978765907454", "id": "d1e17542-f7cc-473a-aa0e-978765907454",
"key": "French", "key": "French",
"value": 4 "value": 4,
"enable": true
}, },
{ {
"id": "b1e8442a-7059-4c6f-8a9c-415383133b0e", "id": "b1e8442a-7059-4c6f-8a9c-415383133b0e",
"key": "German", "key": "German",
"value": 3 "value": 3,
"enable": true
} }
] ]
}, },
@ -170,7 +190,8 @@
"position": "Head of HR, Carson Logistics", "position": "Head of HR, Carson Logistics",
"phone": "+1 661-808-4188", "phone": "+1 661-808-4188",
"email": "l.beasley@carsonlogistics.com", "email": "l.beasley@carsonlogistics.com",
"description": "" "description": "",
"enable": true
}, },
{ {
"id": "62fd3293-0e93-4242-882b-ae19b7865fef", "id": "62fd3293-0e93-4242-882b-ae19b7865fef",
@ -178,7 +199,8 @@
"position": "Assistant Manager, Bullseye", "position": "Assistant Manager, Bullseye",
"phone": "+1 661-808-4188", "phone": "+1 661-808-4188",
"email": "mikhail@bullseyemart.nyc", "email": "mikhail@bullseyemart.nyc",
"description": "" "description": "",
"enable": true
}, },
{ {
"id": "eaab2e32-8591-497c-8676-d122cf3a4798", "id": "eaab2e32-8591-497c-8676-d122cf3a4798",
@ -186,7 +208,8 @@
"position": "CEO , DownToPlay", "position": "CEO , DownToPlay",
"phone": "+1 661-808-4188", "phone": "+1 661-808-4188",
"email": "k.rose@downtoplay.xyz", "email": "k.rose@downtoplay.xyz",
"description": "" "description": "",
"enable": true
} }
] ]
}, },
@ -197,28 +220,45 @@
{ {
"id": "3834a270-2c01-4105-b670-80863c955347", "id": "3834a270-2c01-4105-b670-80863c955347",
"key": "Skype", "key": "Skype",
"value": "@NancyJack5436" "value": "@NancyJack5436",
"enable": true
}, },
{ {
"id": "b0c4fd85-cfda-421e-bd31-008b9aad1dfe", "id": "b0c4fd85-cfda-421e-bd31-008b9aad1dfe",
"key": "Hometown", "key": "Hometown",
"value": "New Jersey, NY" "value": "New Jersey, NY",
"enable": true
}, },
{ {
"id": "7f0a4971-9770-4ca7-b135-2b0ccd867879", "id": "7f0a4971-9770-4ca7-b135-2b0ccd867879",
"key": "Hobbies", "key": "Hobbies",
"value": "Playing Soccer & Guitar" "value": "Playing Soccer & Guitar",
"enable": true
}, },
{ {
"id": "e17552a2-e7e9-4605-8145-795e2b62c30e", "id": "e17552a2-e7e9-4605-8145-795e2b62c30e",
"key": "Valid Work Visas", "key": "Valid Work Visas",
"value": "US, UK, EU" "value": "US, UK, EU",
"enable": true
}
]
},
"data": {
"languages": {
"items": [
null,
null,
null,
null,
{
"items": []
} }
] ]
} }
}
}, },
"theme": { "theme": {
"layout": "Pikachu", "layout": "Gengar",
"font": { "font": {
"family": "Montserrat" "family": "Montserrat"
}, },

View File

@ -7,6 +7,7 @@ import AppContext from '../../../context/AppContext';
import Checkbox from '../../../shared/Checkbox'; import Checkbox from '../../../shared/Checkbox';
import TextArea from '../../../shared/TextArea'; import TextArea from '../../../shared/TextArea';
import { addItem, deleteItem, moveItemUp, moveItemDown } from '../../../utils'; import { addItem, deleteItem, moveItemUp, moveItemDown } from '../../../utils';
import ItemActions from '../../../shared/ItemActions';
const AwardsTab = ({ data, onChange }) => { const AwardsTab = ({ data, onChange }) => {
const context = useContext(AppContext); const context = useContext(AppContext);
@ -53,6 +54,7 @@ const AddItem = ({ dispatch }) => {
const [isOpen, setOpen] = useState(false); const [isOpen, setOpen] = useState(false);
const [item, setItem] = useState({ const [item, setItem] = useState({
id: uuidv4(), id: uuidv4(),
enable: true,
title: '', title: '',
subtitle: '', subtitle: '',
description: '', description: '',
@ -67,6 +69,7 @@ const AddItem = ({ dispatch }) => {
setItem({ setItem({
id: uuidv4(), id: uuidv4(),
enable: true,
title: '', title: '',
subtitle: '', subtitle: '',
description: '', description: '',
@ -162,44 +165,18 @@ const Item = ({ item, index, onChange, dispatch, first, last }) => {
onChange={v => onChange(`${identifier}.description`, v)} onChange={v => onChange(`${identifier}.description`, v)}
/> />
<div className="flex justify-between"> <ItemActions
<button item={item}
type="button" onChange={onChange}
onClick={() => deleteItem(dispatch, 'awards', item)} type="awards"
className="bg-red-600 hover:bg-red-700 text-white text-sm font-medium py-2 px-5 rounded" identifier={identifier}
> dispatch={dispatch}
<div className="flex items-center"> deleteItem={deleteItem}
<i className="material-icons mr-2 font-bold text-base">delete</i> first={first}
<span className="text-sm">Delete</span> moveItemUp={moveItemUp}
</div> last={last}
</button> moveItemDown={moveItemDown}
/>
<div className="flex">
{!first && (
<button
type="button"
onClick={() => moveItemUp(dispatch, 'awards', item)}
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(dispatch, 'awards', item)}
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>
</div> </div>
); );

View File

@ -7,6 +7,7 @@ import AppContext from '../../../context/AppContext';
import Checkbox from '../../../shared/Checkbox'; import Checkbox from '../../../shared/Checkbox';
import TextArea from '../../../shared/TextArea'; import TextArea from '../../../shared/TextArea';
import { addItem, deleteItem, moveItemUp, moveItemDown } from '../../../utils'; import { addItem, deleteItem, moveItemUp, moveItemDown } from '../../../utils';
import ItemActions from '../../../shared/ItemActions';
const CertificationsTab = ({ data, onChange }) => { const CertificationsTab = ({ data, onChange }) => {
const context = useContext(AppContext); const context = useContext(AppContext);
@ -53,6 +54,7 @@ const AddItem = ({ dispatch }) => {
const [isOpen, setOpen] = useState(false); const [isOpen, setOpen] = useState(false);
const [item, setItem] = useState({ const [item, setItem] = useState({
id: uuidv4(), id: uuidv4(),
enable: true,
title: '', title: '',
subtitle: '', subtitle: '',
description: '', description: '',
@ -67,6 +69,7 @@ const AddItem = ({ dispatch }) => {
setItem({ setItem({
id: uuidv4(), id: uuidv4(),
enable: true,
title: '', title: '',
subtitle: '', subtitle: '',
description: '', description: '',
@ -162,44 +165,18 @@ const Item = ({ item, index, onChange, dispatch, first, last }) => {
onChange={v => onChange(`${identifier}.description`, v)} onChange={v => onChange(`${identifier}.description`, v)}
/> />
<div className="flex justify-between"> <ItemActions
<button item={item}
type="button" onChange={onChange}
onClick={() => deleteItem(dispatch, 'certifications', item)} type="certifications"
className="bg-red-600 hover:bg-red-700 text-white text-sm font-medium py-2 px-5 rounded" identifier={identifier}
> dispatch={dispatch}
<div className="flex items-center"> deleteItem={deleteItem}
<i className="material-icons mr-2 font-bold text-base">delete</i> first={first}
<span className="text-sm">Delete</span> moveItemUp={moveItemUp}
</div> last={last}
</button> moveItemDown={moveItemDown}
/>
<div className="flex">
{!first && (
<button
type="button"
onClick={() => moveItemUp(dispatch, 'certifications', item)}
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(dispatch, 'certifications', item)}
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>
</div> </div>
); );

View File

@ -7,6 +7,7 @@ import TextArea from '../../../shared/TextArea';
import AppContext from '../../../context/AppContext'; import AppContext from '../../../context/AppContext';
import Checkbox from '../../../shared/Checkbox'; import Checkbox from '../../../shared/Checkbox';
import { addItem, deleteItem, moveItemUp, moveItemDown } from '../../../utils'; import { addItem, deleteItem, moveItemUp, moveItemDown } from '../../../utils';
import ItemActions from '../../../shared/ItemActions';
const EducationTab = ({ data, onChange }) => { const EducationTab = ({ data, onChange }) => {
const context = useContext(AppContext); const context = useContext(AppContext);
@ -53,6 +54,7 @@ const AddItem = ({ dispatch }) => {
const [isOpen, setOpen] = useState(false); const [isOpen, setOpen] = useState(false);
const [item, setItem] = useState({ const [item, setItem] = useState({
id: uuidv4(), id: uuidv4(),
enable: true,
name: '', name: '',
major: '', major: '',
start: '', start: '',
@ -70,6 +72,7 @@ const AddItem = ({ dispatch }) => {
setItem({ setItem({
id: uuidv4(), id: uuidv4(),
enable: true,
title: '', title: '',
role: '', role: '',
start: '', start: '',
@ -224,44 +227,18 @@ const Item = ({ item, index, onChange, dispatch, first, last }) => {
onChange={v => onChange(`${identifier}.description`, v)} onChange={v => onChange(`${identifier}.description`, v)}
/> />
<div className="flex justify-between"> <ItemActions
<button item={item}
type="button" onChange={onChange}
onClick={() => deleteItem(dispatch, 'education', item)} type="education"
className="bg-red-600 hover:bg-red-700 text-white text-sm font-medium py-2 px-5 rounded" identifier={identifier}
> dispatch={dispatch}
<div className="flex items-center"> deleteItem={deleteItem}
<i className="material-icons mr-2 font-bold text-base">delete</i> first={first}
<span className="text-sm">Delete</span> moveItemUp={moveItemUp}
</div> last={last}
</button> moveItemDown={moveItemDown}
/>
<div className="flex">
{!first && (
<button
type="button"
onClick={() => moveItemUp(dispatch, 'education', item)}
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(dispatch, 'education', item)}
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>
</div> </div>
); );

View File

@ -6,6 +6,7 @@ import TextField from '../../../shared/TextField';
import AppContext from '../../../context/AppContext'; import AppContext from '../../../context/AppContext';
import Checkbox from '../../../shared/Checkbox'; import Checkbox from '../../../shared/Checkbox';
import { addItem, deleteItem, moveItemUp, moveItemDown } from '../../../utils'; import { addItem, deleteItem, moveItemUp, moveItemDown } from '../../../utils';
import ItemActions from '../../../shared/ItemActions';
const ExtrasTab = ({ data, onChange }) => { const ExtrasTab = ({ data, onChange }) => {
const context = useContext(AppContext); const context = useContext(AppContext);
@ -52,6 +53,7 @@ const AddItem = ({ dispatch }) => {
const [isOpen, setOpen] = useState(false); const [isOpen, setOpen] = useState(false);
const [item, setItem] = useState({ const [item, setItem] = useState({
id: uuidv4(), id: uuidv4(),
enable: true,
key: '', key: '',
value: '', value: '',
}); });
@ -65,6 +67,7 @@ const AddItem = ({ dispatch }) => {
setItem({ setItem({
id: uuidv4(), id: uuidv4(),
enable: true,
key: '', key: '',
value: '', value: '',
}); });
@ -145,44 +148,18 @@ const Item = ({ item, index, onChange, dispatch, first, last }) => {
onChange={v => onChange(`${identifier}.value`, v)} onChange={v => onChange(`${identifier}.value`, v)}
/> />
<div className="mt-6 flex justify-between"> <ItemActions
<button item={item}
type="button" onChange={onChange}
onClick={() => deleteItem(dispatch, 'extras', item)} type="extras"
className="bg-red-600 hover:bg-red-700 text-white text-sm font-medium py-2 px-5 rounded" identifier={identifier}
> dispatch={dispatch}
<div className="flex items-center"> deleteItem={deleteItem}
<i className="material-icons mr-2 font-bold text-base">delete</i> first={first}
<span className="text-sm">Delete</span> moveItemUp={moveItemUp}
</div> last={last}
</button> moveItemDown={moveItemDown}
/>
<div className="flex">
{!first && (
<button
type="button"
onClick={() => moveItemUp(dispatch, 'extras', item)}
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(dispatch, 'extras', item)}
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>
</div> </div>
); );

View File

@ -7,6 +7,7 @@ import AppContext from '../../../context/AppContext';
import Checkbox from '../../../shared/Checkbox'; import Checkbox from '../../../shared/Checkbox';
import Counter from '../../../shared/Counter'; import Counter from '../../../shared/Counter';
import { addItem, deleteItem, moveItemUp, moveItemDown } from '../../../utils'; import { addItem, deleteItem, moveItemUp, moveItemDown } from '../../../utils';
import ItemActions from '../../../shared/ItemActions';
const LanguagesTab = ({ data, onChange }) => { const LanguagesTab = ({ data, onChange }) => {
const context = useContext(AppContext); const context = useContext(AppContext);
@ -73,6 +74,7 @@ const AddItem = ({ dispatch }) => {
const [isOpen, setOpen] = useState(false); const [isOpen, setOpen] = useState(false);
const [item, setItem] = useState({ const [item, setItem] = useState({
id: uuidv4(), id: uuidv4(),
enable: true,
key: '', key: '',
value: 1, value: 1,
}); });
@ -86,6 +88,7 @@ const AddItem = ({ dispatch }) => {
setItem({ setItem({
id: uuidv4(), id: uuidv4(),
enable: true,
key: '', key: '',
value: 1, value: 1,
}); });
@ -166,44 +169,18 @@ const Item = ({ item, index, onChange, dispatch, first, last }) => {
onIncrement={() => item.value < 5 && onChange(`${identifier}.value`, item.value + 1)} onIncrement={() => item.value < 5 && onChange(`${identifier}.value`, item.value + 1)}
/> />
<div className="mt-6 flex justify-between"> <ItemActions
<button item={item}
type="button" onChange={onChange}
onClick={() => deleteItem(dispatch, 'languages', item)} type="languages"
className="bg-red-600 hover:bg-red-700 text-white text-sm font-medium py-2 px-5 rounded" identifier={identifier}
> dispatch={dispatch}
<div className="flex items-center"> deleteItem={deleteItem}
<i className="material-icons mr-2 font-bold text-base">delete</i> first={first}
<span className="text-sm">Delete</span> moveItemUp={moveItemUp}
</div> last={last}
</button> moveItemDown={moveItemDown}
/>
<div className="flex">
{!first && (
<button
type="button"
onClick={() => moveItemUp(dispatch, 'languages', item)}
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(dispatch, 'languages', item)}
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>
</div> </div>
); );

View File

@ -7,6 +7,7 @@ import TextArea from '../../../shared/TextArea';
import AppContext from '../../../context/AppContext'; import AppContext from '../../../context/AppContext';
import Checkbox from '../../../shared/Checkbox'; import Checkbox from '../../../shared/Checkbox';
import { addItem, deleteItem, moveItemUp, moveItemDown } from '../../../utils'; import { addItem, deleteItem, moveItemUp, moveItemDown } from '../../../utils';
import ItemActions from '../../../shared/ItemActions';
const ReferencesTab = ({ data, onChange }) => { const ReferencesTab = ({ data, onChange }) => {
const context = useContext(AppContext); const context = useContext(AppContext);
@ -73,6 +74,7 @@ const AddItem = ({ dispatch }) => {
const [isOpen, setOpen] = useState(false); const [isOpen, setOpen] = useState(false);
const [item, setItem] = useState({ const [item, setItem] = useState({
id: uuidv4(), id: uuidv4(),
enable: true,
name: '', name: '',
position: '', position: '',
phone: '', phone: '',
@ -89,6 +91,7 @@ const AddItem = ({ dispatch }) => {
setItem({ setItem({
id: uuidv4(), id: uuidv4(),
enable: true,
name: '', name: '',
position: '', position: '',
phone: '', phone: '',
@ -222,44 +225,18 @@ const Item = ({ item, index, onChange, dispatch, first, last }) => {
onChange={v => onChange(`${identifier}.description`, v)} onChange={v => onChange(`${identifier}.description`, v)}
/> />
<div className="flex justify-between"> <ItemActions
<button item={item}
type="button" onChange={onChange}
onClick={() => deleteItem(dispatch, 'references', item)} type="references"
className="bg-red-600 hover:bg-red-700 text-white text-sm font-medium py-2 px-5 rounded" identifier={identifier}
> dispatch={dispatch}
<div className="flex items-center"> deleteItem={deleteItem}
<i className="material-icons mr-2 font-bold text-base">delete</i> first={first}
<span className="text-sm">Delete</span> moveItemUp={moveItemUp}
</div> last={last}
</button> moveItemDown={moveItemDown}
/>
<div className="flex">
{!first && (
<button
type="button"
onClick={() => moveItemUp(dispatch, 'references', item)}
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(dispatch, 'references', item)}
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>
</div> </div>
); );

View File

@ -7,6 +7,7 @@ import TextArea from '../../../shared/TextArea';
import AppContext from '../../../context/AppContext'; import AppContext from '../../../context/AppContext';
import Checkbox from '../../../shared/Checkbox'; import Checkbox from '../../../shared/Checkbox';
import { addItem, deleteItem, moveItemUp, moveItemDown } from '../../../utils'; import { addItem, deleteItem, moveItemUp, moveItemDown } from '../../../utils';
import ItemActions from '../../../shared/ItemActions';
const WorkTab = ({ data, onChange }) => { const WorkTab = ({ data, onChange }) => {
const context = useContext(AppContext); const context = useContext(AppContext);
@ -50,6 +51,7 @@ const AddItem = ({ dispatch }) => {
const [isOpen, setOpen] = useState(false); const [isOpen, setOpen] = useState(false);
const [item, setItem] = useState({ const [item, setItem] = useState({
id: uuidv4(), id: uuidv4(),
enable: true,
title: '', title: '',
role: '', role: '',
start: '', start: '',
@ -66,6 +68,7 @@ const AddItem = ({ dispatch }) => {
setItem({ setItem({
id: uuidv4(), id: uuidv4(),
enable: true,
title: '', title: '',
role: '', role: '',
start: '', start: '',
@ -155,7 +158,7 @@ const Item = ({ item, index, onChange, dispatch, first, last }) => {
className="flex justify-between items-center cursor-pointer" className="flex justify-between items-center cursor-pointer"
onClick={() => setOpen(!isOpen)} onClick={() => setOpen(!isOpen)}
> >
<h6 className="text-sm font-medium">{item.title}</h6> <h6 className="ml-2 text-sm font-medium">{item.title}</h6>
<i className="material-icons">{isOpen ? 'expand_less' : 'expand_more'}</i> <i className="material-icons">{isOpen ? 'expand_less' : 'expand_more'}</i>
</div> </div>
@ -203,44 +206,18 @@ const Item = ({ item, index, onChange, dispatch, first, last }) => {
onChange={v => onChange(`${identifier}.description`, v)} onChange={v => onChange(`${identifier}.description`, v)}
/> />
<div className="flex justify-between"> <ItemActions
<button item={item}
type="button" onChange={onChange}
onClick={() => deleteItem(dispatch, 'work', item)} type="work"
className="bg-red-600 hover:bg-red-700 text-white text-sm font-medium py-2 px-5 rounded" identifier={identifier}
> dispatch={dispatch}
<div className="flex items-center"> deleteItem={deleteItem}
<i className="material-icons mr-2 font-bold text-base">delete</i> first={first}
<span className="text-sm">Delete</span> moveItemUp={moveItemUp}
</div> last={last}
</button> moveItemDown={moveItemDown}
/>
<div className="flex">
{!first && (
<button
type="button"
onClick={() => moveItemUp(dispatch, 'work', item)}
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(dispatch, 'work', item)}
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>
</div> </div>
); );

View File

@ -113,8 +113,8 @@ const reducer = (state, { type, payload }) => {
case 'import_data': case 'import_data':
if (payload === null) return initialState; if (payload === null) return initialState;
for(const section of Object.keys(initialState.data)){ for (const section of Object.keys(initialState.data)) {
if(!(section in payload.data)){ if (!(section in payload.data)) {
payload.data[section] = initialState.data[section]; payload.data[section] = initialState.data[section];
} }
} }

View File

@ -1,16 +1,20 @@
import React from 'react'; import React from 'react';
const Checkbox = ({ checked, onChange }) => { const Checkbox = ({ checked, onChange, icon = 'check', size = '2rem' }) => {
return ( return (
<div className="bg-white border-2 rounded border-gray-400 hover:border-gray-500 w-8 h-8 flex flex-shrink-0 justify-center items-center mr-2 focus-within:border-blue-500 cursor-pointer"> <div
className="bg-white border-2 rounded border-gray-400 hover:border-gray-500 flex flex-shrink-0 justify-center items-center mr-2 focus-within:border-blue-500 cursor-pointer"
style={{ width: size, height: size }}
>
<input <input
type="checkbox" type="checkbox"
className="w-8 h-8 opacity-0 absolute cursor-pointer" style={{ width: size, height: size }}
className="opacity-0 absolute cursor-pointer"
checked={checked} checked={checked}
onChange={e => onChange(e.target.checked)} onChange={e => onChange(e.target.checked)}
/> />
<i className="material-icons fill-current hidden text-lg font-bold text-gray-800 cursor-pointer"> <i className="material-icons fill-current hidden text-sm font-bold text-gray-800 cursor-pointer">
check {icon}
</i> </i>
</div> </div>
); );

68
src/shared/ItemActions.js Normal file
View File

@ -0,0 +1,68 @@
import React from 'react';
import Checkbox from './Checkbox';
const ItemActions = ({
item,
onChange,
type,
identifier,
dispatch,
deleteItem,
first,
moveItemUp,
last,
moveItemDown,
}) => {
return (
<div className="flex justify-between">
<div className="flex items-center">
<Checkbox
size="2.25rem"
checked={item.enable}
onChange={v => {
onChange(`${identifier}.enable`, v);
}}
/>
<button
type="button"
onClick={() => deleteItem(dispatch, type, item)}
className="ml-2 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>
<div className="flex">
{!first && (
<button
type="button"
onClick={() => moveItemUp(dispatch, type, item)}
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(dispatch, type, item)}
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>
);
};
export default ItemActions;

View File

@ -116,7 +116,7 @@ const Castform = () => {
data.work.enable && ( data.work.enable && (
<div> <div>
<Heading light title={data.work.heading} /> <Heading light title={data.work.heading} />
{data.work.items.map(WorkItem)} {data.work.items.filter(x => x.enable).map(WorkItem)}
</div> </div>
); );
@ -136,7 +136,7 @@ const Castform = () => {
<div> <div>
<Heading light title={data.references.heading} /> <Heading light title={data.references.heading} />
<div className="grid grid-cols-2 gap-6 px-5"> <div className="grid grid-cols-2 gap-6 px-5">
{data.references.items.map(ReferenceItem)} {data.references.items.filter(x => x.enable).map(ReferenceItem)}
</div> </div>
</div> </div>
); );
@ -167,7 +167,9 @@ const Castform = () => {
data.languages.enable && ( data.languages.enable && (
<div> <div>
<Heading title={data.languages.heading} /> <Heading title={data.languages.heading} />
<div className="px-5 mb-6">{data.languages.items.map(LanguageItem)}</div> <div className="px-5 mb-6">
{data.languages.items.filter(x => x.enable).map(LanguageItem)}
</div>
</div> </div>
); );
@ -194,7 +196,7 @@ const Castform = () => {
data.education.enable && ( data.education.enable && (
<div> <div>
<Heading light title={data.education.heading} /> <Heading light title={data.education.heading} />
{data.education.items.map(EducationItem)} {data.education.items.filter(x => x.enable).map(EducationItem)}
</div> </div>
); );
@ -211,7 +213,7 @@ const Castform = () => {
data.awards.enable && ( data.awards.enable && (
<div> <div>
<Heading light title={data.awards.heading} /> <Heading light title={data.awards.heading} />
{data.awards.items.map(AwardItem)} {data.awards.items.filter(x => x.enable).map(AwardItem)}
</div> </div>
); );
@ -228,7 +230,7 @@ const Castform = () => {
data.certifications.enable && ( data.certifications.enable && (
<div> <div>
<Heading title={data.certifications.heading} /> <Heading title={data.certifications.heading} />
{data.certifications.items.map(CertificationItem)} {data.certifications.items.filter(x => x.enable).map(CertificationItem)}
</div> </div>
); );
@ -244,7 +246,7 @@ const Castform = () => {
data.extras.enable && ( data.extras.enable && (
<div> <div>
<Heading title={data.extras.heading} /> <Heading title={data.extras.heading} />
{data.extras.items.map(ExtraItem)} {data.extras.items.filter(x => x.enable).map(ExtraItem)}
</div> </div>
); );

View File

@ -109,7 +109,7 @@ const Gengar = () => {
data.education.enable && ( data.education.enable && (
<div className="mb-6"> <div className="mb-6">
<Heading title={data.education.heading} /> <Heading title={data.education.heading} />
{data.education.items.map(EducationItem)} {data.education.items.filter(x => x.enable).map(EducationItem)}
</div> </div>
); );
@ -126,7 +126,7 @@ const Gengar = () => {
data.certifications.enable && ( data.certifications.enable && (
<div className="mb-6"> <div className="mb-6">
<Heading title={data.certifications.heading} /> <Heading title={data.certifications.heading} />
{data.certifications.items.map(CertificationItem)} {data.certifications.items.filter(x => x.enable).map(CertificationItem)}
</div> </div>
); );
@ -143,7 +143,7 @@ const Gengar = () => {
data.awards.enable && ( data.awards.enable && (
<div className="mb-6"> <div className="mb-6">
<Heading title={data.awards.heading} /> <Heading title={data.awards.heading} />
{data.awards.items.map(AwardItem)} {data.awards.items.filter(x => x.enable).map(AwardItem)}
</div> </div>
); );
@ -162,7 +162,9 @@ const Gengar = () => {
data.references.enable && ( data.references.enable && (
<div> <div>
<Heading title={data.references.heading} /> <Heading title={data.references.heading} />
<div className="grid grid-cols-2 gap-6">{data.references.items.map(ReferenceItem)}</div> <div className="grid grid-cols-2 gap-6">
{data.references.items.filter(x => x.enable).map(ReferenceItem)}
</div>
</div> </div>
); );
@ -186,7 +188,7 @@ const Gengar = () => {
data.work.enable && ( data.work.enable && (
<div className="mb-6"> <div className="mb-6">
<Heading title={data.work.heading} /> <Heading title={data.work.heading} />
{data.work.items.map(WorkItem)} {data.work.items.filter(x => x.enable).map(WorkItem)}
</div> </div>
); );
@ -208,7 +210,7 @@ const Gengar = () => {
data.languages.enable && ( data.languages.enable && (
<div> <div>
<Heading title={data.languages.heading} /> <Heading title={data.languages.heading} />
<div className="mb-6">{data.languages.items.map(LanguageItem)}</div> <div className="mb-6">{data.languages.items.filter(x => x.enable).map(LanguageItem)}</div>
</div> </div>
); );
@ -224,7 +226,9 @@ const Gengar = () => {
data.extras.enable && ( data.extras.enable && (
<div> <div>
<Heading title={data.extras.heading} /> <Heading title={data.extras.heading} />
<div className="grid grid-cols-2">{data.extras.items.map(ExtraItem)}</div> <div className="grid grid-cols-2">
{data.extras.items.filter(x => x.enable).map(ExtraItem)}
</div>
</div> </div>
); );

View File

@ -80,7 +80,7 @@ const Onyx = () => {
data.work.enable && ( data.work.enable && (
<div> <div>
<Heading title={data.work.heading} /> <Heading title={data.work.heading} />
{data.work.items.map(WorkItem)} {data.work.items.filter(x => x.enable).map(WorkItem)}
</div> </div>
); );
@ -107,7 +107,7 @@ const Onyx = () => {
data.education.enable && ( data.education.enable && (
<div> <div>
<Heading title={data.education.heading} /> <Heading title={data.education.heading} />
{data.education.items.map(EducationItem)} {data.education.items.filter(x => x.enable).map(EducationItem)}
</div> </div>
); );
@ -124,7 +124,7 @@ const Onyx = () => {
data.awards.enable && ( data.awards.enable && (
<div> <div>
<Heading title={data.awards.heading} /> <Heading title={data.awards.heading} />
{data.awards.items.map(AwardItem)} {data.awards.items.filter(x => x.enable).map(AwardItem)}
</div> </div>
); );
@ -141,7 +141,7 @@ const Onyx = () => {
data.certifications.enable && ( data.certifications.enable && (
<div> <div>
<Heading title={data.certifications.heading} /> <Heading title={data.certifications.heading} />
{data.certifications.items.map(CertificationItem)} {data.certifications.items.filter(x => x.enable).map(CertificationItem)}
</div> </div>
); );
@ -185,7 +185,7 @@ const Onyx = () => {
data.languages.enable && ( data.languages.enable && (
<div> <div>
<Heading title={data.languages.heading} /> <Heading title={data.languages.heading} />
<div className="w-3/4">{data.languages.items.map(LanguageItem)}</div> <div className="w-3/4">{data.languages.items.filter(x => x.enable).map(LanguageItem)}</div>
</div> </div>
); );
@ -204,7 +204,9 @@ const Onyx = () => {
data.references.enable && ( data.references.enable && (
<div> <div>
<Heading title={data.references.heading} /> <Heading title={data.references.heading} />
<div className="grid grid-cols-3 gap-6">{data.references.items.map(ReferenceItem)}</div> <div className="grid grid-cols-3 gap-6">
{data.references.items.filter(x => x.enable).map(ReferenceItem)}
</div>
</div> </div>
); );
@ -221,7 +223,7 @@ const Onyx = () => {
<div> <div>
<Heading title={data.extras.heading} /> <Heading title={data.extras.heading} />
<table className="w-2/3 table-auto"> <table className="w-2/3 table-auto">
<tbody>{data.extras.items.map(ExtraItem)}</tbody> <tbody>{data.extras.items.filter(x => x.enable).map(ExtraItem)}</tbody>
</table> </table>
</div> </div>
); );

View File

@ -91,7 +91,9 @@ const Pikachu = () => {
data.references.enable && ( data.references.enable && (
<div> <div>
<Heading title={data.references.heading} /> <Heading title={data.references.heading} />
<div className="grid grid-cols-2 gap-6">{data.references.items.map(ReferenceItem)}</div> <div className="grid grid-cols-2 gap-6">
{data.references.items.filter(x => x.enable).map(ReferenceItem)}
</div>
</div> </div>
); );
@ -113,7 +115,7 @@ const Pikachu = () => {
data.languages.enable && ( data.languages.enable && (
<div> <div>
<Heading title={data.languages.heading} /> <Heading title={data.languages.heading} />
<div className="mb-6">{data.languages.items.map(LanguageItem)}</div> <div className="mb-6">{data.languages.items.filter(x => x.enable).map(LanguageItem)}</div>
</div> </div>
); );
@ -129,7 +131,9 @@ const Pikachu = () => {
data.extras.enable && ( data.extras.enable && (
<div> <div>
<Heading title={data.extras.heading} /> <Heading title={data.extras.heading} />
<div className="flex flex-col mb-6">{data.extras.items.map(ExtraItem)}</div> <div className="flex flex-col mb-6">
{data.extras.items.filter(x => x.enable).map(ExtraItem)}
</div>
</div> </div>
); );
@ -153,7 +157,9 @@ const Pikachu = () => {
data.work.enable && ( data.work.enable && (
<div> <div>
<Heading title={data.work.heading} /> <Heading title={data.work.heading} />
<div className="flex flex-col mb-4">{data.work.items.map(WorkItem)}</div> <div className="flex flex-col mb-4">
{data.work.items.filter(x => x.enable).map(WorkItem)}
</div>
</div> </div>
); );
@ -182,7 +188,9 @@ const Pikachu = () => {
data.education.enable && ( data.education.enable && (
<div> <div>
<Heading title={data.education.heading} /> <Heading title={data.education.heading} />
<div className="flex flex-col mb-4">{data.education.items.map(EducationItem)}</div> <div className="flex flex-col mb-4">
{data.education.items.filter(x => x.enable).map(EducationItem)}
</div>
</div> </div>
); );
@ -199,7 +207,9 @@ const Pikachu = () => {
data.awards.enable && ( data.awards.enable && (
<div> <div>
<Heading title={data.awards.heading} /> <Heading title={data.awards.heading} />
<div className="flex flex-col mb-2">{data.awards.items.map(AwardItem)}</div> <div className="flex flex-col mb-2">
{data.awards.items.filter(x => x.enable).map(AwardItem)}
</div>
</div> </div>
); );
@ -216,7 +226,9 @@ const Pikachu = () => {
data.certifications.enable && ( data.certifications.enable && (
<div> <div>
<Heading title={data.certifications.heading} /> <Heading title={data.certifications.heading} />
<div className="flex flex-col mb-2">{data.certifications.items.map(CertificationItem)}</div> <div className="flex flex-col mb-2">
{data.certifications.items.filter(x => x.enable).map(CertificationItem)}
</div>
</div> </div>
); );