mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2025-11-13 00:03:27 +10:00
🚀 release v3.0.0
This commit is contained in:
95
client/components/shared/List.tsx
Normal file
95
client/components/shared/List.tsx
Normal file
@ -0,0 +1,95 @@
|
||||
import { ListItem as ListItemType } from '@reactive-resume/schema';
|
||||
import clsx from 'clsx';
|
||||
import get from 'lodash/get';
|
||||
import isArray from 'lodash/isArray';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import isFunction from 'lodash/isFunction';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useCallback } from 'react';
|
||||
import { DndProvider } from 'react-dnd';
|
||||
import { HTML5Backend } from 'react-dnd-html5-backend';
|
||||
|
||||
import { useAppDispatch, useAppSelector } from '@/store/hooks';
|
||||
import { deleteItem, setResumeState } from '@/store/resume/resumeSlice';
|
||||
|
||||
import styles from './List.module.scss';
|
||||
import ListItem from './ListItem';
|
||||
|
||||
type Props = {
|
||||
path: string;
|
||||
titleKey?: string;
|
||||
subtitleKey?: string;
|
||||
onEdit?: (item: ListItemType) => void;
|
||||
onDuplicate?: (item: ListItemType) => void;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
const List: React.FC<Props> = ({
|
||||
path,
|
||||
titleKey = 'title',
|
||||
subtitleKey = 'subtitle',
|
||||
onEdit,
|
||||
onDuplicate,
|
||||
className,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const list: Array<ListItemType> = useAppSelector((state) => get(state.resume, path, []));
|
||||
|
||||
const handleEdit = (item: ListItemType) => {
|
||||
isFunction(onEdit) && onEdit(item);
|
||||
};
|
||||
|
||||
const handleDuplicate = (item: ListItemType) => {
|
||||
isFunction(onDuplicate) && onDuplicate(item);
|
||||
};
|
||||
|
||||
const handleDelete = (item: ListItemType) => {
|
||||
dispatch(deleteItem({ path, value: item }));
|
||||
};
|
||||
|
||||
const handleMove = useCallback(
|
||||
(dragIndex: number, hoverIndex: number) => {
|
||||
const dragItem = list[dragIndex];
|
||||
const newList = [...list];
|
||||
|
||||
newList.splice(dragIndex, 1);
|
||||
newList.splice(hoverIndex, 0, dragItem);
|
||||
|
||||
dispatch(setResumeState({ path, value: newList }));
|
||||
},
|
||||
[list, dispatch, path]
|
||||
);
|
||||
|
||||
return (
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
<div className={clsx(styles.container, className)}>
|
||||
{isEmpty(list) && <div className={styles.empty}>{t('builder.common.list.empty-text')}</div>}
|
||||
|
||||
{list.map((item, index) => {
|
||||
const title = get(item, titleKey, '');
|
||||
const subtitleObj = get(item, subtitleKey);
|
||||
const subtitle: string = isArray(subtitleObj) ? subtitleObj.join(', ') : subtitleObj;
|
||||
|
||||
return (
|
||||
<ListItem
|
||||
key={item.id}
|
||||
item={item}
|
||||
index={index}
|
||||
title={title}
|
||||
subtitle={subtitle}
|
||||
onMove={handleMove}
|
||||
onEdit={handleEdit}
|
||||
onDelete={handleDelete}
|
||||
onDuplicate={handleDuplicate}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</DndProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default List;
|
||||
Reference in New Issue
Block a user