- refactor sections

- combine resume and metadata contexts
This commit is contained in:
Amruth Pillai
2020-07-09 19:18:04 +05:30
parent c00d7a9eef
commit 3b252476c4
41 changed files with 309 additions and 235 deletions

View File

@ -7,7 +7,7 @@ import SyncIndicator from './SyncIndicator';
const RightNavbar = () => {
return (
<div className={styles.container}>
<div className="grid grid-cols-1 gap-6 text-secondary-dark">
<div className="grid grid-cols-1 gap-4 text-secondary-dark">
{sections.map((x) => (
<SectionIcon
key={x.id}

View File

@ -1,12 +1,15 @@
import React, { Fragment, memo } from 'react';
import { Element } from 'react-scroll';
import sections from '../../../data/rightSections';
import Layout from '../sections/Layout';
import RightNavbar from './RightNavbar';
import styles from './RightSidebar.module.css';
import Layout from './sections/Layout';
import Templates from './sections/Templates';
const getComponent = (id) => {
switch (id) {
case 'templates':
return Templates;
case 'layout':
return Layout;
default:

View File

@ -4,7 +4,7 @@
-ms-overflow-style: none;
scrollbar-width: none;
@apply w-full h-screen overflow-scroll p-8;
@apply grid gap-6;
@apply grid gap-8;
}
.container::-webkit-scrollbar {

View File

@ -0,0 +1,47 @@
import React, { memo } from 'react';
import { useDispatch } from '../../../../contexts/ResumeContext';
import Heading from '../../../shared/Heading';
import Input from '../../../shared/Input';
const Colors = () => {
const dispatch = useDispatch();
const handleClick = (value) => {
dispatch({
type: 'on_input',
payload: {
path: 'metadata.colors.primary',
value,
},
});
};
return (
<section>
<Heading>Colors</Heading>
<Input
name="primary"
label="Primary Color"
placeholder="#FF4081"
path="metadata.colors.primary"
/>
<Input
name="text"
label="Text Color"
placeholder="#444444"
path="metadata.colors.text"
/>
<Input
name="background"
label="Background Color"
placeholder="#FFFFFF"
path="metadata.colors.background"
/>
</section>
);
};
export default memo(Colors);

View File

@ -0,0 +1,100 @@
import React, { memo } from 'react';
import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd';
import { useDispatch, useSelector } from '../../../../contexts/ResumeContext';
import { move, reorder } from '../../../../utils';
import Heading from '../../../shared/Heading';
import styles from './Layout.module.css';
const Layout = () => {
const blocks = useSelector('metadata.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: 'on_input',
payload: {
path: 'metadata.layout',
value: newState,
},
});
} else {
const newResult = move(blocks[sInd], blocks[dInd], source, destination);
const newState = [...blocks];
newState[sInd] = newResult[sInd];
newState[dInd] = newResult[dInd];
dispatch({
type: 'on_input',
payload: {
path: 'layout',
value: newState,
},
});
}
};
return (
<section>
<Heading>Layout</Heading>
<p>
This template supports {blocks.length} blocks. You can re-order or move
sections by dragging/dropping the section names across lists.
</p>
<div className={`grid gap-8 grid-cols-${blocks.length}`}>
<DragDropContext onDragEnd={onDragEnd}>
{blocks.map((el, ind) => (
<Droppable key={ind} droppableId={`${ind}`}>
{(dropProvided) => (
<div
ref={dropProvided.innerRef}
className={styles.droppable}
{...dropProvided.droppableProps}
>
<div className="grid gap-3">
<span className="uppercase font-semibold text-xs">
Block {ind + 1}
</span>
{el.map((item, index) => (
<Draggable
key={item.id}
index={index}
draggableId={item.id}
>
{(dragProvided) => (
<div
ref={dragProvided.innerRef}
className={styles.draggable}
{...dragProvided.draggableProps}
{...dragProvided.dragHandleProps}
>
{item.name}
</div>
)}
</Draggable>
))}
</div>
{dropProvided.placeholder}
</div>
)}
</Droppable>
))}
</DragDropContext>
</div>
</section>
);
};
export default memo(Layout);

View File

@ -0,0 +1,7 @@
.droppable {
@apply p-6 bg-secondary-light col-span-1 rounded;
}
.draggable {
@apply px-4 py-2 capitalize font-medium rounded bg-secondary;
}

View File

@ -0,0 +1,48 @@
import cx from 'classnames';
import React, { memo } from 'react';
import { useDispatch, useSelector } from '../../../../contexts/ResumeContext';
import templates from '../../../../data/templates';
import { handleKeyUp } from '../../../../utils';
import Heading from '../../../shared/Heading';
import styles from './Templates.module.css';
const Templates = () => {
const dispatch = useDispatch();
const template = useSelector('metadata.template');
const handleClick = (value) => {
dispatch({
type: 'on_input',
payload: {
path: 'metadata.template',
value,
},
});
};
return (
<section>
<Heading>Templates</Heading>
<div className="grid grid-cols-2 gap-8">
{templates.map((x) => (
<div
key={x.id}
tabIndex="0"
role="button"
onKeyUp={(e) => handleKeyUp(e, () => handleClick(x.id))}
onClick={() => handleClick(x.id)}
className={cx(styles.template, {
[styles.selected]: template === x.id,
})}
>
<img loading="lazy" height="240px" src={x.preview} alt={x.name} />
<span>{x.name}</span>
</div>
))}
</div>
</section>
);
};
export default memo(Templates);

View File

@ -0,0 +1,26 @@
.template {
@apply w-full rounded flex flex-col items-center;
}
.template:focus {
@apply outline-none;
}
.template img {
height: 240px;
@apply w-full object-cover border-2 border-transparent rounded;
@apply transition-opacity duration-200 ease-in-out;
}
.template.selected img {
@apply border-2 border-primary;
}
.template:hover img {
@apply cursor-pointer opacity-75;
@apply transition-opacity duration-200 ease-in-out;
}
.template span {
@apply mt-1 text-center text-sm font-semibold;
}