mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2025-11-10 04:22:27 +10:00
- recreating onyx template
- profile section complete
This commit is contained in:
@ -1,21 +1,16 @@
|
|||||||
import React, { useContext } from "react";
|
import React, { useContext } from "react";
|
||||||
|
import ResumeContext from "../../../contexts/ResumeContext";
|
||||||
import TemplateContext from "../../../contexts/TemplateContext";
|
import TemplateContext from "../../../contexts/TemplateContext";
|
||||||
|
import Onyx from "../../../templates/Onyx";
|
||||||
import styles from "./Artboard.module.css";
|
import styles from "./Artboard.module.css";
|
||||||
|
|
||||||
const Artboard = () => {
|
const Artboard = () => {
|
||||||
const { blocks } = useContext(TemplateContext);
|
const { blocks, colors } = useContext(TemplateContext);
|
||||||
|
const { state } = useContext(ResumeContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div id="artboard" className={styles.container}>
|
||||||
<div className={`grid gap-8 grid-cols-${blocks.length}`}>
|
<Onyx data={state} layout={blocks} colors={colors} />
|
||||||
{blocks.map((block, ind) => (
|
|
||||||
<div key={ind} className="col-span-1">
|
|
||||||
{block.map((x) => (
|
|
||||||
<div key={x.id}>{x.name}</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
.container {
|
.container {
|
||||||
width: 400px;
|
width: 210mm;
|
||||||
height: 600px;
|
height: 297mm;
|
||||||
|
zoom: 0.8;
|
||||||
box-shadow: var(--shadow);
|
box-shadow: var(--shadow);
|
||||||
@apply bg-white;
|
@apply bg-white;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import cx from "classnames";
|
|
||||||
import React, { useContext } from "react";
|
import React, { useContext } from "react";
|
||||||
import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd";
|
import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd";
|
||||||
import TemplateContext from "../../../contexts/TemplateContext";
|
import TemplateContext from "../../../contexts/TemplateContext";
|
||||||
@ -21,21 +20,18 @@ const Layout = () => {
|
|||||||
<DragDropContext onDragEnd={onDragEnd}>
|
<DragDropContext onDragEnd={onDragEnd}>
|
||||||
{blocks.map((el, ind) => (
|
{blocks.map((el, ind) => (
|
||||||
<Droppable key={ind} droppableId={`${ind}`}>
|
<Droppable key={ind} droppableId={`${ind}`}>
|
||||||
{(provided, snapshot) => (
|
{(provided) => (
|
||||||
<div
|
<div
|
||||||
ref={provided.innerRef}
|
ref={provided.innerRef}
|
||||||
className={cx(styles.droppable, {
|
className={styles.droppable}
|
||||||
[styles.draggingOver]: snapshot.isDraggingOver,
|
|
||||||
})}
|
|
||||||
{...provided.droppableProps}
|
{...provided.droppableProps}
|
||||||
>
|
>
|
||||||
<div className="grid gap-3">
|
<div className="grid gap-3">
|
||||||
|
<span className="uppercase font-semibold text-xs">
|
||||||
|
Block {ind + 1}
|
||||||
|
</span>
|
||||||
{el.map((item, index) => (
|
{el.map((item, index) => (
|
||||||
<Draggable
|
<Draggable key={item} draggableId={item} index={index}>
|
||||||
key={item.id}
|
|
||||||
draggableId={item.id}
|
|
||||||
index={index}
|
|
||||||
>
|
|
||||||
{(provided) => (
|
{(provided) => (
|
||||||
<div
|
<div
|
||||||
ref={provided.innerRef}
|
ref={provided.innerRef}
|
||||||
@ -43,7 +39,7 @@ const Layout = () => {
|
|||||||
{...provided.draggableProps}
|
{...provided.draggableProps}
|
||||||
{...provided.dragHandleProps}
|
{...provided.dragHandleProps}
|
||||||
>
|
>
|
||||||
{item.name}
|
{item}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Draggable>
|
</Draggable>
|
||||||
|
|||||||
@ -1,11 +1,7 @@
|
|||||||
.droppable {
|
.droppable {
|
||||||
@apply px-4 py-6 bg-gray-100 col-span-1 rounded;
|
@apply p-6 bg-secondary-light col-span-1 rounded;
|
||||||
}
|
|
||||||
|
|
||||||
.droppable.dragging-over {
|
|
||||||
@apply bg-gray-200;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.draggable {
|
.draggable {
|
||||||
@apply px-4 py-2 font-medium rounded bg-gray-300;
|
@apply px-4 py-2 capitalize font-medium rounded bg-secondary;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,16 +10,34 @@ const Profile = () => {
|
|||||||
<Heading>Profile</Heading>
|
<Heading>Profile</Heading>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className={styles.circle}>
|
<div className={styles.circle}>
|
||||||
<MdFileUpload size="22px" className="text-secondary-dark" />
|
<MdFileUpload size="22px" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Input label="Photograph" className="ml-6" path="profile.photograph" />
|
<Input label="Photograph" className="ml-6" path="profile.photograph" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-8">
|
<div className="grid grid-cols-2 gap-6">
|
||||||
<Input label="First Name" path="profile.firstName" />
|
<Input label="First Name" path="profile.firstName" />
|
||||||
<Input label="Last Name" path="profile.lastName" />
|
<Input label="Last Name" path="profile.lastName" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<Input label="Subtitle" path="profile.subtitle" />
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<Input label="Address Line 1" path="profile.address.line1" />
|
||||||
|
<Input label="Address Line 2" path="profile.address.line2" />
|
||||||
|
|
||||||
|
<div className="grid grid-cols-2 gap-6">
|
||||||
|
<Input label="City" path="profile.address.city" />
|
||||||
|
<Input label="Pincode" path="profile.address.pincode" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<Input label="Phone Number" path="profile.phone" />
|
||||||
|
<Input label="Website" path="profile.website" />
|
||||||
|
<Input label="Email Address" path="profile.email" />
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,5 +2,5 @@
|
|||||||
width: 60px;
|
width: 60px;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
flex: 0 0 60px;
|
flex: 0 0 60px;
|
||||||
@apply flex items-center justify-center bg-secondary rounded-full;
|
@apply flex items-center justify-center bg-secondary text-secondary-dark rounded-full;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ const CreateResume = () => {
|
|||||||
return (
|
return (
|
||||||
<div className={styles.resume}>
|
<div className={styles.resume}>
|
||||||
<div className={styles.backdrop}>
|
<div className={styles.backdrop}>
|
||||||
<MdAdd color="#FFF" size="48" />
|
<MdAdd size="48" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
tabIndex="0"
|
tabIndex="0"
|
||||||
@ -22,7 +22,7 @@ const CreateResume = () => {
|
|||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
onKeyDown={() => {}}
|
onKeyDown={() => {}}
|
||||||
>
|
>
|
||||||
<MdAdd color="#444" size="48" />
|
<MdAdd size="48" />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.meta}>
|
<div className={styles.meta}>
|
||||||
<p>Create New Resume</p>
|
<p>Create New Resume</p>
|
||||||
|
|||||||
@ -5,16 +5,16 @@
|
|||||||
.resume > .backdrop {
|
.resume > .backdrop {
|
||||||
max-width: 184px;
|
max-width: 184px;
|
||||||
height: 260px;
|
height: 260px;
|
||||||
@apply rounded absolute w-full bg-black shadow;
|
@apply rounded absolute w-full bg-black text-white shadow;
|
||||||
@apply absolute text-gray-500 flex justify-center items-center;
|
@apply absolute flex justify-center items-center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.resume > .page {
|
.resume > .page {
|
||||||
max-width: 184px;
|
max-width: 184px;
|
||||||
height: 260px;
|
height: 260px;
|
||||||
@apply rounded absolute w-full bg-inverse;
|
@apply rounded absolute w-full bg-secondary-light;
|
||||||
@apply transition-opacity duration-200 ease-in-out;
|
@apply transition-opacity duration-200 ease-in-out;
|
||||||
@apply cursor-pointer absolute text-gray-500 flex justify-center items-center;
|
@apply cursor-pointer absolute flex justify-center items-center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.resume > .page:hover {
|
.resume > .page:hover {
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.container > label > span {
|
.container > label > span {
|
||||||
@apply mb-1 text-secondary-dark font-medium text-xs uppercase;
|
@apply mb-1 text-secondary-dark font-semibold tracking-wide text-xs uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container > label > input {
|
.container > label > input {
|
||||||
@ -19,7 +19,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.container > label > input:focus {
|
.container > label > input:focus {
|
||||||
@apply outline-none border-secondary-dark;
|
@apply outline-none border-gray-500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container > label > p {
|
.container > label > p {
|
||||||
|
|||||||
@ -2,11 +2,14 @@ import { set } from "lodash";
|
|||||||
import React, { createContext, useReducer } from "react";
|
import React, { createContext, useReducer } from "react";
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
|
id: "dafa3242-f39a-4755-bab3-be3c3ca3d190",
|
||||||
profile: {
|
profile: {
|
||||||
photograph: "",
|
photograph: "",
|
||||||
firstName: "",
|
firstName: "",
|
||||||
lastName: "",
|
lastName: "",
|
||||||
},
|
},
|
||||||
|
createdAt: "",
|
||||||
|
updatedAt: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
const ResumeContext = createContext(initialState);
|
const ResumeContext = createContext(initialState);
|
||||||
@ -16,6 +19,8 @@ const ResumeProvider = ({ children }) => {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case "on_input":
|
case "on_input":
|
||||||
return set({ ...state }, payload.path, payload.value);
|
return set({ ...state }, payload.path, payload.value);
|
||||||
|
case "set_data":
|
||||||
|
return payload;
|
||||||
default:
|
default:
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +1,17 @@
|
|||||||
|
import { flatten } from "lodash";
|
||||||
import React, { createContext, useState } from "react";
|
import React, { createContext, useState } from "react";
|
||||||
|
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
selected: "Pikachu",
|
selected: "Pikachu",
|
||||||
setSelected: () => {},
|
setSelected: () => {},
|
||||||
|
colors: {
|
||||||
|
textColor: "#212121",
|
||||||
|
primaryColor: "#f44336",
|
||||||
|
backgroundColor: "#FFFFFF",
|
||||||
|
},
|
||||||
blocks: [
|
blocks: [
|
||||||
[
|
["profile", "work"],
|
||||||
{ id: "1", name: "Profile" },
|
["education", "skills", "hobbies"],
|
||||||
{ id: "2", name: "Work" },
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{ id: "3", name: "Education" },
|
|
||||||
{ id: "4", name: "Skills" },
|
|
||||||
{ id: "5", name: "Hobbies" },
|
|
||||||
],
|
|
||||||
],
|
],
|
||||||
setBlocks: () => {},
|
setBlocks: () => {},
|
||||||
};
|
};
|
||||||
@ -21,6 +20,7 @@ const TemplateContext = createContext(defaultState);
|
|||||||
|
|
||||||
const TemplateProvider = ({ children }) => {
|
const TemplateProvider = ({ children }) => {
|
||||||
const [selected, setSelected] = useState(defaultState.selected);
|
const [selected, setSelected] = useState(defaultState.selected);
|
||||||
|
const [colors, setColors] = useState(defaultState.colors);
|
||||||
const [blocks, setBlocks] = useState(defaultState.blocks);
|
const [blocks, setBlocks] = useState(defaultState.blocks);
|
||||||
|
|
||||||
const reorder = (list, startIndex, endIndex) => {
|
const reorder = (list, startIndex, endIndex) => {
|
||||||
@ -68,13 +68,28 @@ const TemplateProvider = ({ children }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const setSupportedBlocks = (number) => {
|
||||||
|
if (number === blocks.length) return;
|
||||||
|
|
||||||
|
if (number > blocks.length) {
|
||||||
|
setBlocks([...blocks, []]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (number < blocks.length) {
|
||||||
|
setBlocks([flatten(blocks)]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TemplateContext.Provider
|
<TemplateContext.Provider
|
||||||
value={{
|
value={{
|
||||||
selected,
|
selected,
|
||||||
setSelected,
|
setSelected,
|
||||||
|
colors,
|
||||||
|
setColors,
|
||||||
blocks,
|
blocks,
|
||||||
setBlocks,
|
setBlocks,
|
||||||
|
setSupportedBlocks,
|
||||||
onDragEnd,
|
onDragEnd,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -6,6 +6,7 @@ const COLOR_CONFIG = {
|
|||||||
"--color-primary-dark": "#333",
|
"--color-primary-dark": "#333",
|
||||||
"--color-inverse": "#fff",
|
"--color-inverse": "#fff",
|
||||||
"--color-inverse-dark": "#f5f5f5",
|
"--color-inverse-dark": "#f5f5f5",
|
||||||
|
"--color-secondary-light": "#f7fafc",
|
||||||
"--color-secondary": "#edf2f7",
|
"--color-secondary": "#edf2f7",
|
||||||
"--color-secondary-dark": "#718096",
|
"--color-secondary-dark": "#718096",
|
||||||
},
|
},
|
||||||
@ -14,6 +15,7 @@ const COLOR_CONFIG = {
|
|||||||
"--color-primary-dark": "#eeeeee",
|
"--color-primary-dark": "#eeeeee",
|
||||||
"--color-inverse": "#212121",
|
"--color-inverse": "#212121",
|
||||||
"--color-inverse-dark": "#181818",
|
"--color-inverse-dark": "#181818",
|
||||||
|
"--color-secondary-light": "#2c2c2c",
|
||||||
"--color-secondary": "#444",
|
"--color-secondary": "#444",
|
||||||
"--color-secondary-dark": "#888",
|
"--color-secondary-dark": "#888",
|
||||||
},
|
},
|
||||||
|
|||||||
@ -11,7 +11,7 @@ const Builder = ({ id }) => {
|
|||||||
<div className="col-span-3">
|
<div className="col-span-3">
|
||||||
<LeftSidebar />
|
<LeftSidebar />
|
||||||
</div>
|
</div>
|
||||||
<div className="col-span-5 bg-inverse-dark flex items-center justify-center">
|
<div className="h-screen overflow-scroll col-span-5 bg-inverse-dark grid items-center justify-center">
|
||||||
<Artboard />
|
<Artboard />
|
||||||
</div>
|
</div>
|
||||||
<div className="col-span-3">
|
<div className="col-span-3">
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
--color-primary-dark: #333;
|
--color-primary-dark: #333;
|
||||||
--color-inverse: #fff;
|
--color-inverse: #fff;
|
||||||
--color-inverse-dark: #f5f5f5;
|
--color-inverse-dark: #f5f5f5;
|
||||||
--color-secondary: #edf2f7;
|
--color-secondary-light: #f7fafc;
|
||||||
--color-secondary-dark: #718096;
|
--color-secondary: #e2e8f0;
|
||||||
|
--color-secondary-dark: #a0aec0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,3 +30,11 @@ hr {
|
|||||||
section {
|
section {
|
||||||
@apply grid grid-cols-1 gap-8;
|
@apply grid grid-cols-1 gap-8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#artboard {
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
#artboard hr {
|
||||||
|
border-color: #eee;
|
||||||
|
}
|
||||||
|
|||||||
68
src/templates/Onyx.js
Normal file
68
src/templates/Onyx.js
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import React, { useContext, useEffect } from "react";
|
||||||
|
import { FaGlobeAmericas, FaPhone } from "react-icons/fa";
|
||||||
|
import { MdEmail } from "react-icons/md";
|
||||||
|
import TemplateContext from "../contexts/TemplateContext";
|
||||||
|
|
||||||
|
const Onyx = ({ data, layout, colors }) => {
|
||||||
|
const { setSelected, setSupportedBlocks } = useContext(TemplateContext);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setSelected("Onyx");
|
||||||
|
setSupportedBlocks(1);
|
||||||
|
}, [setSelected, setSupportedBlocks]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="p-8 grid grid-cols-10 gap-4 items-center"
|
||||||
|
style={{
|
||||||
|
color: colors.textColor,
|
||||||
|
backgroundColor: colors.backgroundColor,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className="col-span-2 rounded"
|
||||||
|
src="https://i.imgur.com/Icr472Z.jpg"
|
||||||
|
alt="Photograph"
|
||||||
|
/>
|
||||||
|
<div className="col-span-5">
|
||||||
|
<h2
|
||||||
|
className="text-4xl font-bold"
|
||||||
|
style={{ color: colors.primaryColor }}
|
||||||
|
>
|
||||||
|
Nancy Jackson
|
||||||
|
</h2>
|
||||||
|
<span className="font-medium">Customer Sales Representative</span>
|
||||||
|
|
||||||
|
<div className="mt-5 flex flex-col">
|
||||||
|
<span>3879 Gateway Avenue,</span>
|
||||||
|
<span>Bakersfield,</span>
|
||||||
|
<span>California, USA</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-span-3 grid gap-4">
|
||||||
|
<div className="flex items-center">
|
||||||
|
<FaPhone size="14" style={{ color: colors.primaryColor }} />
|
||||||
|
<span className="ml-4 text-sm font-medium">+1 661-808-4188</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center">
|
||||||
|
<FaGlobeAmericas size="14" style={{ color: colors.primaryColor }} />
|
||||||
|
<span className="ml-4 text-sm font-medium">nancyontheweb.com</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center">
|
||||||
|
<MdEmail size="14" style={{ color: colors.primaryColor }} />
|
||||||
|
<span className="ml-4 text-sm font-medium">
|
||||||
|
nancyjack43@gmail.com
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr className="my-2 col-span-10" />
|
||||||
|
|
||||||
|
{JSON.stringify(layout)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Onyx;
|
||||||
@ -10,6 +10,7 @@ module.exports = {
|
|||||||
"primary-dark": "var(--color-primary-dark)",
|
"primary-dark": "var(--color-primary-dark)",
|
||||||
inverse: "var(--color-inverse)",
|
inverse: "var(--color-inverse)",
|
||||||
"inverse-dark": "var(--color-inverse-dark)",
|
"inverse-dark": "var(--color-inverse-dark)",
|
||||||
|
"secondary-light": "var(--color-secondary-light)",
|
||||||
secondary: "var(--color-secondary)",
|
secondary: "var(--color-secondary)",
|
||||||
"secondary-dark": "var(--color-secondary-dark)",
|
"secondary-dark": "var(--color-secondary-dark)",
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user