mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-07-24 08:54:05 +10:00
added sidebar toggle feature and confirmation prompt before deleting any list-item
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { Element } from 'react-scroll';
|
import { Element } from 'react-scroll';
|
||||||
import React, { Fragment, memo } from 'react';
|
import React, { Fragment, memo, useContext } from 'react';
|
||||||
import * as styles from './LeftSidebar.module.css';
|
import * as styles from './LeftSidebar.module.css';
|
||||||
import Awards from './sections/Awards';
|
import Awards from './sections/Awards';
|
||||||
import Certifications from './sections/Certifications';
|
import Certifications from './sections/Certifications';
|
||||||
@@ -15,6 +15,7 @@ import Skills from './sections/Skills';
|
|||||||
import Social from './sections/Social';
|
import Social from './sections/Social';
|
||||||
import Work from './sections/Work';
|
import Work from './sections/Work';
|
||||||
import sections from '../../../data/leftSections';
|
import sections from '../../../data/leftSections';
|
||||||
|
import SettingsContext from '../../../contexts/SettingsContext';
|
||||||
|
|
||||||
const getComponent = (id) => {
|
const getComponent = (id) => {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
@@ -60,14 +61,17 @@ const SidebarSection = ({ id, event }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const LeftSidebar = () => (
|
const LeftSidebar = () => {
|
||||||
<div className="flex">
|
const { isSideBarOpen } = useContext(SettingsContext);
|
||||||
<LeftNavbar />
|
return (
|
||||||
|
<div className="flex">
|
||||||
<div id="LeftSidebar" className={styles.container}>
|
<LeftNavbar />
|
||||||
{sections.map(SidebarSection)}
|
{isSideBarOpen && (
|
||||||
|
<div id="LeftSidebar" className={styles.container}>
|
||||||
|
{sections.map(SidebarSection)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
);
|
||||||
);
|
};
|
||||||
|
|
||||||
export default memo(LeftSidebar);
|
export default memo(LeftSidebar);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ const ListItem = ({
|
|||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [anchorEl, setAnchorEl] = useState(null);
|
const [anchorEl, setAnchorEl] = useState(null);
|
||||||
|
const [deleteClickCount, setDeleteClickCount] = useState(0);
|
||||||
|
|
||||||
const handleClick = (event) => setAnchorEl(event.currentTarget);
|
const handleClick = (event) => setAnchorEl(event.currentTarget);
|
||||||
const toggleSwitchState = 'isVisible' in data ? data.isVisible : true;
|
const toggleSwitchState = 'isVisible' in data ? data.isVisible : true;
|
||||||
@@ -81,6 +82,14 @@ const ListItem = ({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const checkConfirmationAndDelte = () => {
|
||||||
|
if (deleteClickCount === 1) {
|
||||||
|
handleDelete();
|
||||||
|
} else if (deleteClickCount < 1) {
|
||||||
|
setDeleteClickCount(deleteClickCount + 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Draggable draggableId={data.id} index={index}>
|
<Draggable draggableId={data.id} index={index}>
|
||||||
{(dragProvided) => (
|
{(dragProvided) => (
|
||||||
@@ -126,7 +135,10 @@ const ListItem = ({
|
|||||||
<Menu
|
<Menu
|
||||||
keepMounted
|
keepMounted
|
||||||
anchorEl={anchorEl}
|
anchorEl={anchorEl}
|
||||||
onClose={handleClose}
|
onClose={() => {
|
||||||
|
setDeleteClickCount(0);
|
||||||
|
handleClose();
|
||||||
|
}}
|
||||||
open={Boolean(anchorEl)}
|
open={Boolean(anchorEl)}
|
||||||
>
|
>
|
||||||
<div className="flex items-center space-around">
|
<div className="flex items-center space-around">
|
||||||
@@ -140,9 +152,11 @@ const ListItem = ({
|
|||||||
<MenuItem onClick={handleEdit}>
|
<MenuItem onClick={handleEdit}>
|
||||||
{t('shared.buttons.edit')}
|
{t('shared.buttons.edit')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem onClick={handleDelete}>
|
<MenuItem onClick={checkConfirmationAndDelte}>
|
||||||
<span className="text-red-600 font-medium">
|
<span className="text-red-600 font-medium">
|
||||||
{t('shared.buttons.delete')}
|
{deleteClickCount
|
||||||
|
? t('shared.buttons.confirmation')
|
||||||
|
: t('shared.buttons.delete')}
|
||||||
</span>
|
</span>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|||||||
@@ -1,9 +1,23 @@
|
|||||||
import React, { memo } from 'react';
|
import React, { memo, useContext } from 'react';
|
||||||
|
import { BsBoxArrowRight, BsBoxArrowLeft } from 'react-icons/bs';
|
||||||
import * as styles from './RightNavbar.module.css';
|
import * as styles from './RightNavbar.module.css';
|
||||||
import SectionIcon from '../../shared/SectionIcon';
|
import SectionIcon from '../../shared/SectionIcon';
|
||||||
import SyncIndicator from './SyncIndicator';
|
import SyncIndicator from './SyncIndicator';
|
||||||
import sections from '../../../data/rightSections';
|
import sections from '../../../data/rightSections';
|
||||||
|
import SettingsContext from '../../../contexts/SettingsContext';
|
||||||
|
|
||||||
|
const SideBarToggleIcon = ({ className }) => {
|
||||||
|
const { isSideBarOpen, setSideBarToggle } = useContext(SettingsContext);
|
||||||
|
const ToggleIcon = isSideBarOpen ? BsBoxArrowRight : BsBoxArrowLeft;
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
className={className}
|
||||||
|
onClick={() => setSideBarToggle(!isSideBarOpen)}
|
||||||
|
>
|
||||||
|
<ToggleIcon size="18px" />
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
};
|
||||||
const RightNavbar = () => (
|
const RightNavbar = () => (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<div className="grid grid-cols-1 gap-4 text-primary-500">
|
<div className="grid grid-cols-1 gap-4 text-primary-500">
|
||||||
@@ -16,9 +30,8 @@ const RightNavbar = () => (
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
<SideBarToggleIcon className="mt-auto" />
|
||||||
<hr className="mt-auto my-6" />
|
<hr className=" my-6" />
|
||||||
|
|
||||||
<SyncIndicator />
|
<SyncIndicator />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Element } from 'react-scroll';
|
import { Element } from 'react-scroll';
|
||||||
import React, { Fragment, memo } from 'react';
|
import React, { Fragment, memo, useContext } from 'react';
|
||||||
import * as styles from './RightSidebar.module.css';
|
import * as styles from './RightSidebar.module.css';
|
||||||
import About from './sections/About';
|
import About from './sections/About';
|
||||||
import Actions from './sections/Actions';
|
import Actions from './sections/Actions';
|
||||||
@@ -11,6 +11,7 @@ import RightNavbar from './RightNavbar';
|
|||||||
import Settings from './sections/Settings';
|
import Settings from './sections/Settings';
|
||||||
import Templates from './sections/Templates';
|
import Templates from './sections/Templates';
|
||||||
import sections from '../../../data/rightSections';
|
import sections from '../../../data/rightSections';
|
||||||
|
import SettingsContext from '../../../contexts/SettingsContext';
|
||||||
|
|
||||||
const getComponent = (id) => {
|
const getComponent = (id) => {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
@@ -37,7 +38,6 @@ const getComponent = (id) => {
|
|||||||
|
|
||||||
const SidebarSection = ({ id, event }) => {
|
const SidebarSection = ({ id, event }) => {
|
||||||
const Component = getComponent(id);
|
const Component = getComponent(id);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment key={id}>
|
<Fragment key={id}>
|
||||||
<Element name={id}>
|
<Element name={id}>
|
||||||
@@ -48,14 +48,18 @@ const SidebarSection = ({ id, event }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const RightSidebar = () => (
|
const RightSidebar = () => {
|
||||||
<div className="flex">
|
const { isSideBarOpen } = useContext(SettingsContext);
|
||||||
<div id="RightSidebar" className={styles.container}>
|
return (
|
||||||
{sections.map(SidebarSection)}
|
<div className="flex">
|
||||||
|
{isSideBarOpen && (
|
||||||
|
<div id="RightSidebar" className={styles.container}>
|
||||||
|
{sections.map(SidebarSection)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<RightNavbar />
|
||||||
</div>
|
</div>
|
||||||
|
);
|
||||||
<RightNavbar />
|
};
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default memo(RightSidebar);
|
export default memo(RightSidebar);
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ const defaultState = {
|
|||||||
setTheme: () => {},
|
setTheme: () => {},
|
||||||
language: 'en',
|
language: 'en',
|
||||||
setLanguage: () => {},
|
setLanguage: () => {},
|
||||||
|
isSideBarOpen: true,
|
||||||
|
setSideBarToggle: () => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const SettingsContext = createContext(defaultState);
|
const SettingsContext = createContext(defaultState);
|
||||||
@@ -16,7 +18,9 @@ const SettingsContext = createContext(defaultState);
|
|||||||
const SettingsProvider = ({ children }) => {
|
const SettingsProvider = ({ children }) => {
|
||||||
const [theme, setTheme] = useState(defaultState.theme);
|
const [theme, setTheme] = useState(defaultState.theme);
|
||||||
const [language, setLanguage] = useState(defaultState.theme);
|
const [language, setLanguage] = useState(defaultState.theme);
|
||||||
|
const [isSideBarOpen, setSideBarToggle] = useState(
|
||||||
|
defaultState.isSideBarOpen,
|
||||||
|
);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const prefTheme = localStorage.getItem('theme') || defaultState.theme;
|
const prefTheme = localStorage.getItem('theme') || defaultState.theme;
|
||||||
const prefLanguage =
|
const prefLanguage =
|
||||||
@@ -45,6 +49,8 @@ const SettingsProvider = ({ children }) => {
|
|||||||
setTheme,
|
setTheme,
|
||||||
language,
|
language,
|
||||||
setLanguage,
|
setLanguage,
|
||||||
|
isSideBarOpen,
|
||||||
|
setSideBarToggle,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
@@ -10,12 +10,14 @@ import DatabaseContext from '../../contexts/DatabaseContext';
|
|||||||
import LeftSidebar from '../../components/builder/left/LeftSidebar';
|
import LeftSidebar from '../../components/builder/left/LeftSidebar';
|
||||||
import LoadingScreen from '../../components/router/LoadingScreen';
|
import LoadingScreen from '../../components/router/LoadingScreen';
|
||||||
import RightSidebar from '../../components/builder/right/RightSidebar';
|
import RightSidebar from '../../components/builder/right/RightSidebar';
|
||||||
|
import SettingsContext from '../../contexts/SettingsContext';
|
||||||
|
|
||||||
const Builder = ({ id }) => {
|
const Builder = ({ id }) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const { getResume } = useContext(DatabaseContext);
|
const { getResume } = useContext(DatabaseContext);
|
||||||
|
const { isSideBarOpen } = useContext(SettingsContext);
|
||||||
|
|
||||||
const handleLoadDemoData = () => {
|
const handleLoadDemoData = () => {
|
||||||
dispatch({ type: 'load_demo_data' });
|
dispatch({ type: 'load_demo_data' });
|
||||||
@@ -58,7 +60,7 @@ const Builder = ({ id }) => {
|
|||||||
<div className={styles.left}>
|
<div className={styles.left}>
|
||||||
<LeftSidebar />
|
<LeftSidebar />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.center}>
|
<div className={`${styles.center} ${!isSideBarOpen && 'flex-1'}`}>
|
||||||
<Artboard />
|
<Artboard />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.right}>
|
<div className={styles.right}>
|
||||||
@@ -66,7 +68,7 @@ const Builder = ({ id }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}, [loading]);
|
}, [loading, isSideBarOpen]);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default memo(Builder);
|
export default memo(Builder);
|
||||||
|
|||||||
@@ -3,21 +3,24 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.left {
|
.left {
|
||||||
width: calc(100vw / 4);
|
|
||||||
box-shadow: var(--left-shadow);
|
box-shadow: var(--left-shadow);
|
||||||
|
max-width: calc(100vw / 4);
|
||||||
|
flex-shrink: 1;
|
||||||
|
|
||||||
@apply bg-primary-50 absolute top-0 bottom-0 left-0 z-10;
|
@apply bg-primary-50 absolute top-0 bottom-0 left-0 z-10;
|
||||||
}
|
}
|
||||||
|
|
||||||
.center {
|
.center {
|
||||||
|
flex-shrink: 1;
|
||||||
width: calc(100vw / 2);
|
width: calc(100vw / 2);
|
||||||
|
|
||||||
@apply relative z-0 h-screen overflow-scroll flex flex-col justify-items-center;
|
@apply relative z-0 h-screen overflow-scroll flex flex-col justify-items-center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.right {
|
.right {
|
||||||
width: calc(100vw / 4);
|
max-width: calc(100vw / 4);
|
||||||
box-shadow: var(--right-shadow);
|
box-shadow: var(--right-shadow);
|
||||||
|
flex-shrink: 1;
|
||||||
|
|
||||||
@apply bg-primary-50 absolute top-0 bottom-0 right-0 z-10;
|
@apply bg-primary-50 absolute top-0 bottom-0 right-0 z-10;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,22 @@ body {
|
|||||||
@apply transition-colors duration-200 ease-in-out;
|
@apply transition-colors duration-200 ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
*::-webkit-scrollbar-track {
|
||||||
|
box-shadow: inset 0 0 6px grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
*::-webkit-scrollbar-thumb {
|
||||||
|
background-color: darkgrey;
|
||||||
|
border-radius: 20px;
|
||||||
|
outline: 1px solid slategrey;
|
||||||
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@apply font-semibold;
|
@apply font-semibold;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user