- implementing hobby, language and reference sections

- dynamic template selection
This commit is contained in:
Amruth Pillai
2020-07-09 10:41:16 +05:30
parent 9045e2983d
commit 9e98da038c
38 changed files with 470 additions and 187 deletions

View File

@ -6,8 +6,8 @@ import Onyx from '../../../templates/Onyx';
import styles from './Artboard.module.css';
const Artboard = () => {
const { blocks, colors } = useContext(TemplateContext);
const state = useSelector((s) => s);
const { selected, blocks, colors } = useContext(TemplateContext);
const state = useSelector((store) => store);
const { id, name } = state;
return (
@ -18,7 +18,9 @@ const Artboard = () => {
</Helmet>
<div id="artboard" className={styles.container}>
<Onyx data={state} layout={blocks} colors={colors} />
{selected === 'Onyx' && (
<Onyx data={state} layout={blocks} colors={colors} />
)}
</div>
</div>
);

View File

@ -16,7 +16,7 @@ const LeftNavbar = () => (
<div className="grid grid-cols-1 gap-8">
{sections.map((x) => (
<SectionIcon key={x.id} section={x} />
<SectionIcon key={x.id} section={x} containerId="LeftSidebar" />
))}
</div>

View File

@ -1,4 +1,5 @@
import React, { Fragment } from 'react';
import React from 'react';
import { Element } from 'react-scroll';
import sections from '../../../data/leftSections';
import LeftNavbar from './LeftNavbar';
import styles from './LeftSidebar.module.css';
@ -7,12 +8,12 @@ const LeftSidebar = () => (
<div className="flex">
<LeftNavbar />
<div className={styles.container}>
<div id="LeftSidebar" className={styles.container}>
{sections.map(({ id, name, event, component: Component }) => (
<Fragment key={id}>
<Element key={id} name={id}>
<Component id={id} name={name} event={event} />
<hr />
</Fragment>
</Element>
))}
</div>
</div>

View File

@ -1,9 +1,9 @@
import { get, isEmpty } from 'lodash';
import moment from 'moment';
import React, { useContext } from 'react';
import { MdAdd } from 'react-icons/md';
import ModalContext from '../../../contexts/ModalContext';
import { useSelector } from '../../../contexts/ResumeContext';
import { formatDateRange } from '../../../utils';
import Button from '../../shared/Button';
import EmptyList from './EmptyList';
import styles from './List.module.css';
@ -17,6 +17,7 @@ const List = ({
subtitlePath,
text,
textPath,
hasDate,
event,
}) => {
const items = useSelector((state) => get(state, path, []));
@ -26,13 +27,6 @@ const List = ({
const handleEdit = (data) => emitter.emit(event, data);
const formatDateRange = (x) =>
`${moment(x.startDate).format('MMMM Y')}${
moment(x.endDate).isValid()
? moment(x.endDate).format('MMMM Y')
: 'Present'
}`;
return (
<div className="flex flex-col">
<div className={styles.list}>
@ -46,10 +40,11 @@ const List = ({
path={path}
title={title || get(x, titlePath, '')}
subtitle={
subtitle || get(x, subtitlePath, '') || formatDateRange(x)
subtitle ||
get(x, subtitlePath, '') ||
(hasDate && formatDateRange(x))
}
text={text || get(x, textPath, '')}
className={styles.listItem}
onEdit={() => handleEdit(x)}
isFirst={i === 0}
isLast={i === items.length - 1}

View File

@ -1,21 +1,3 @@
.list {
@apply flex flex-col border border-secondary rounded;
}
.list-item {
@apply flex items-center justify-between border-t border-secondary px-8 py-5;
}
.list-item:first-child {
@apply border-t-0;
}
.menu {
@apply opacity-0;
@apply transition-opacity duration-200 ease-in-out;
}
.list-item:hover .menu {
@apply opacity-100;
@apply transition-opacity duration-200 ease-in-out;
}

View File

@ -64,7 +64,7 @@ const ListItem = ({
};
return (
<div className={styles.container}>
<div className={styles.listItem}>
<div className="grid">
<span className="font-medium truncate">{title}</span>

View File

@ -1,8 +1,8 @@
.container {
.listItem {
@apply flex items-center justify-between border-t border-secondary px-6 py-5;
}
.container:first-child {
.listItem:first-child {
@apply border-t-0;
}
@ -11,7 +11,7 @@
@apply transition-opacity duration-200 ease-in-out;
}
.container:hover .menu {
.listItem:hover .menu {
@apply opacity-100;
@apply transition-opacity duration-200 ease-in-out;
}

View File

@ -10,6 +10,7 @@ const Education = ({ id, name, event }) => {
<Heading>{name}</Heading>
<List
hasDate
path={path}
event={event}
titlePath="institution"

View File

@ -0,0 +1,17 @@
import React from 'react';
import Heading from '../../shared/Heading';
import List from '../lists/List';
const Hobbies = ({ id, name, event }) => {
const path = `${id}.items`;
return (
<section>
<Heading>{name}</Heading>
<List path={path} event={event} titlePath="name" />
</section>
);
};
export default Hobbies;

View File

@ -0,0 +1,17 @@
import React from 'react';
import Heading from '../../shared/Heading';
import List from '../lists/List';
const Languages = ({ id, name, event }) => {
const path = `${id}.items`;
return (
<section>
<Heading>{name}</Heading>
<List path={path} event={event} titlePath="name" subtitlePath="fluency" />
</section>
);
};
export default Languages;

View File

@ -0,0 +1,23 @@
import React from 'react';
import Heading from '../../shared/Heading';
import List from '../lists/List';
const References = ({ id, name, event }) => {
const path = `${id}.items`;
return (
<section>
<Heading>{name}</Heading>
<List
path={path}
event={event}
titlePath="name"
subtitlePath="position"
textPath="summary"
/>
</section>
);
};
export default References;

View File

@ -9,7 +9,13 @@ const Work = ({ id, name, event }) => {
<section>
<Heading>{name}</Heading>
<List path={path} event={event} titlePath="company" textPath="summary" />
<List
hasDate
path={path}
event={event}
titlePath="company"
textPath="summary"
/>
</section>
);
};

View File

@ -1,7 +1,7 @@
import React, { useContext } from 'react';
import { MdAdd } from 'react-icons/md';
import ModalContext from '../../contexts/ModalContext';
import { handleKeyDown } from '../../utils';
import { handleKeyUp } from '../../utils';
import styles from './CreateResume.module.css';
const CreateResume = () => {
@ -19,7 +19,7 @@ const CreateResume = () => {
role="button"
className={styles.page}
onClick={handleClick}
onKeyDown={(e) => handleKeyDown(e, handleClick)}
onKeyUp={(e) => handleKeyUp(e, handleClick)}
>
<MdAdd size="48" />
</div>

View File

@ -1,6 +1,6 @@
import classNames from 'classnames';
import React from 'react';
import { handleKeyDown } from '../../utils';
import { handleKeyUp } from '../../utils';
import styles from './Button.module.css';
const Button = ({ icon, title, onClick, outline, className, isLoading }) => {
@ -12,7 +12,7 @@ const Button = ({ icon, title, onClick, outline, className, isLoading }) => {
return (
<button
className={classes}
onKeyDown={(e) => handleKeyDown(e, onClick)}
onKeyUp={(e) => handleKeyUp(e, onClick)}
onClick={isLoading ? undefined : onClick}
>
{icon && <Icon size="14" className="mr-2" />}

View File

@ -1,10 +1,11 @@
import cx from 'classnames';
import { get, isFunction } from 'lodash';
import React from 'react';
import React, { useEffect, useState } from 'react';
import { FaAngleDown } from 'react-icons/fa';
import { MdClose } from 'react-icons/md';
import { v4 as uuidv4 } from 'uuid';
import { useDispatch, useSelector } from '../../contexts/ResumeContext';
import { handleKeyDown } from '../../utils';
import { handleKeyUp } from '../../utils';
import styles from './Input.module.css';
const Input = ({
@ -14,8 +15,8 @@ const Input = ({
error,
value,
onBlur,
options,
touched,
checked,
onChange,
className,
isRequired,
@ -24,11 +25,15 @@ const Input = ({
showDeleteItemButton,
type = 'text',
}) => {
const uuid = uuidv4();
const [uuid, setUuid] = useState(null);
const stateValue = useSelector((state) => get(state, path));
const dispatch = useDispatch();
value = value || stateValue;
useEffect(() => {
setUuid(uuidv4());
}, []);
value = isFunction(onChange) ? value : stateValue;
onChange = isFunction(onChange)
? onChange
: (e) => {
@ -51,7 +56,7 @@ const Input = ({
)}
</span>
{type === 'text' && (
{(type === 'text' || type === 'date') && (
<div className="relative grid items-center">
<input
id={uuid}
@ -59,7 +64,6 @@ const Input = ({
type={type}
value={value}
onBlur={onBlur}
checked={checked}
onChange={onChange}
placeholder={placeholder}
/>
@ -69,7 +73,7 @@ const Input = ({
size="16px"
tabIndex="0"
onClick={onDeleteItem}
onKeyDown={(e) => handleKeyDown(e, onDeleteItem)}
onKeyUp={(e) => handleKeyUp(e, onDeleteItem)}
className="absolute right-0 cursor-pointer opacity-50 hover:opacity-75 mx-4"
/>
)}
@ -82,10 +86,8 @@ const Input = ({
id={uuid}
rows="4"
name={name}
type={type}
value={value}
onBlur={onBlur}
checked={checked}
onChange={onChange}
placeholder={placeholder}
/>
@ -104,6 +106,27 @@ const Input = ({
</div>
)}
{type === 'dropdown' && (
<div className="relative grid items-center">
<select
id={uuid}
name={name}
value={value}
onBlur={onBlur}
onChange={onChange}
>
{options.map((x) => (
<option key={x}>{x}</option>
))}
</select>
<FaAngleDown
size="16px"
className="absolute right-0 opacity-50 hover:opacity-75 mx-4"
/>
</div>
)}
{error && touched && <p>{error}</p>}
</label>
</div>

View File

@ -3,17 +3,20 @@
}
.container label input,
.container label textarea {
@apply py-3 px-4 rounded bg-secondary text-primary border border-secondary;
.container label textarea,
.container label select {
@apply py-3 px-4 rounded bg-secondary text-primary border border-secondary appearance-none;
}
.container label input::placeholder,
.container label textarea::placeholder {
.container label textarea::placeholder,
.container label select::placeholder {
@apply text-primary opacity-50;
}
.container label input:focus,
.container label textarea:focus {
.container label textarea:focus,
.container label select:focus {
@apply outline-none border-gray-500;
}

View File

@ -1,7 +1,7 @@
import React, { useContext, useRef } from 'react';
import { MdFileUpload } from 'react-icons/md';
import StorageContext from '../../contexts/StorageContext';
import { handleKeyDown } from '../../utils';
import { handleKeyUp } from '../../utils';
import Input from './Input';
import styles from './PhotoUpload.module.css';
@ -25,7 +25,7 @@ const PhotoUpload = () => {
tabIndex="0"
className={styles.circle}
onClick={handleIconClick}
onKeyDown={(e) => handleKeyDown(e, handleIconClick)}
onKeyUp={(e) => handleKeyUp(e, handleIconClick)}
>
<MdFileUpload size="22px" />
<input

View File

@ -1,13 +1,30 @@
import { Tooltip } from '@material-ui/core';
import React from 'react';
import { scroller } from 'react-scroll';
import { handleKeyUp } from '../../utils';
const SectionIcon = ({ section, placement = 'right' }) => {
const { icon: Icon, name } = section;
const SectionIcon = ({ section, containerId, placement = 'right' }) => {
const { id, name, icon: Icon } = section;
const handleClick = () => {
scroller.scrollTo(id, {
duration: 500,
smooth: true,
containerId,
offset: -10,
});
};
return (
<Tooltip title={name} placement={placement} arrow>
<div className="cursor-pointer">
<Icon className="text-secondary-dark hover:text-primary" size="20px" />
<div
tabIndex="0"
role="button"
className="cursor-pointer focus:outline-none"
onKeyUp={(e) => handleKeyUp(e, handleClick)}
onClick={handleClick}
>
<Icon className="text-secondary-dark hover:text-primary" size="16px" />
</div>
</Tooltip>
);