mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2025-11-13 16:22:59 +10:00
🚀 release v3.0.0
This commit is contained in:
100
client/components/shared/Heading.tsx
Normal file
100
client/components/shared/Heading.tsx
Normal file
@ -0,0 +1,100 @@
|
||||
import { Check, Delete, DriveFileRenameOutline, Grade, Visibility, VisibilityOff } from '@mui/icons-material';
|
||||
import { IconButton, TextField, Tooltip } from '@mui/material';
|
||||
import clsx from 'clsx';
|
||||
import get from 'lodash/get';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
|
||||
import sections from '@/config/sections';
|
||||
import { useAppDispatch, useAppSelector } from '@/store/hooks';
|
||||
import { deleteSection, setResumeState } from '@/store/resume/resumeSlice';
|
||||
|
||||
import styles from './Heading.module.scss';
|
||||
|
||||
type Props = {
|
||||
path: string;
|
||||
name?: string;
|
||||
isEditable?: boolean;
|
||||
isHideable?: boolean;
|
||||
isDeletable?: boolean;
|
||||
action?: React.ReactNode;
|
||||
};
|
||||
|
||||
const Heading: React.FC<Props> = ({
|
||||
path,
|
||||
name,
|
||||
isEditable = false,
|
||||
isHideable = false,
|
||||
isDeletable = false,
|
||||
action,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const heading = useAppSelector((state) => get(state.resume, `${path}.name`, name));
|
||||
const visibility = useAppSelector((state) => get(state.resume, `${path}.visible`, true));
|
||||
|
||||
const [editMode, setEditMode] = useState(false);
|
||||
|
||||
const id = useMemo(() => path && path.split('.').at(-1), [path]);
|
||||
|
||||
const icon = sections.find((x) => x.id === id)?.icon || <Grade />;
|
||||
|
||||
const toggleVisibility = () => {
|
||||
dispatch(setResumeState({ path: `${path}.visible`, value: !visibility }));
|
||||
};
|
||||
|
||||
const toggleEditMode = () => setEditMode(!editMode);
|
||||
|
||||
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
dispatch(setResumeState({ path: `${path}.name`, value: event.target.value }));
|
||||
};
|
||||
|
||||
const handleDelete = () => {
|
||||
dispatch(deleteSection({ path }));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className="flex w-full items-center gap-3">
|
||||
<div className="opacity-50">{icon}</div>
|
||||
{editMode ? (
|
||||
<TextField size="small" value={heading} className="w-3/4" onChange={handleChange} />
|
||||
) : (
|
||||
<h1>{heading}</h1>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={clsx(styles.actions, {
|
||||
'!opacity-75': editMode,
|
||||
})}
|
||||
>
|
||||
{isEditable && (
|
||||
<Tooltip title={t<string>('builder.common.tooltip.rename-section')}>
|
||||
<IconButton onClick={toggleEditMode}>{editMode ? <Check /> : <DriveFileRenameOutline />}</IconButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{isHideable && (
|
||||
<Tooltip title={t<string>('builder.common.tooltip.toggle-visibility')}>
|
||||
<IconButton onClick={toggleVisibility}>{visibility ? <Visibility /> : <VisibilityOff />}</IconButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{isDeletable && (
|
||||
<Tooltip title={t<string>('builder.common.tooltip.delete-section')}>
|
||||
<IconButton onClick={handleDelete}>
|
||||
<Delete />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{action}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Heading;
|
||||
Reference in New Issue
Block a user