"use client"; import * as React from "react"; import List from "@mui/material/List"; import ListItem from "@mui/material/ListItem"; import ListItemText from "@mui/material/ListItemText"; import ListItemIcon from "@mui/material/ListItemIcon"; import Checkbox from "@mui/material/Checkbox"; import IconButton from "@mui/material/Fab"; import Divider from "@mui/material/Divider"; import ChevronLeft from "@mui/icons-material/ChevronLeft"; import ChevronRight from "@mui/icons-material/ChevronRight"; import intersection from "lodash/intersection"; import difference from "lodash/difference"; import Stack from "@mui/material/Stack"; import Paper from "@mui/material/Paper"; import Typography from "@mui/material/Typography"; import ListSubheader from "@mui/material/ListSubheader"; export interface LabelWithId { id: string; label: string; } export interface TransferListProps { allItems: LabelWithId[]; initiallySelectedItems: LabelWithId[]; onChange: () => void; allItemsLabel: string; selectedItemsLabel: string; } interface ItemListProps { items: LabelWithId[]; checkedItems: LabelWithId[]; label: string; handleToggleAll: ( items: LabelWithId[], checkedItems: LabelWithId[], ) => React.MouseEventHandler; handleToggle: (item: LabelWithId) => React.MouseEventHandler; } const ItemList: React.FC = ({ items, checkedItems, label, handleToggle, handleToggleAll, }) => { return ( {label} {`${checkedItems.length}/${items.length} selected`} } > {items.map((item) => { return ( ); })} ); }; const TransferList: React.FC = ({ allItems, initiallySelectedItems, allItemsLabel, selectedItemsLabel, onChange, }) => { // Keep a map for the original order of items const sortMap = React.useMemo(() => { return allItems.reduce<{ [id: string]: number }>( (acc, item, index) => ({ ...acc, [item.id]: index }), {}, ); }, [allItems]); const compareFn = React.useCallback( (a: LabelWithId, b: LabelWithId) => sortMap[a.id] - sortMap[b.id], [sortMap], ); const [checkedList, setCheckedList] = React.useState([]); const [leftList, setLeftList] = React.useState( difference(allItems, initiallySelectedItems), ); const [rightList, setRightList] = React.useState( initiallySelectedItems, ); const leftListChecked = intersection(checkedList, leftList); const rightListChecked = intersection(checkedList, rightList); const handleToggle = React.useCallback( (value: LabelWithId) => () => { const isChecked = checkedList.includes(value); const newCheckedList = isChecked ? difference(checkedList, [value]) : [...checkedList, value]; setCheckedList(newCheckedList); }, [checkedList], ); const handleToggleAll = React.useCallback( (items: LabelWithId[], checkedItems: LabelWithId[]) => () => { if (checkedItems.length === items.length) { setCheckedList(difference(checkedList, checkedItems)); } else { setCheckedList([...checkedList, ...items]); } }, [checkedList], ); const handleCheckedRight = () => { setRightList([...rightList, ...leftListChecked].sort(compareFn)); setLeftList(difference(leftList, leftListChecked).sort(compareFn)); setCheckedList(difference(checkedList, leftListChecked)); }; const handleCheckedLeft = () => { setLeftList([...leftList, ...rightListChecked].sort(compareFn)); setRightList(difference(rightList, rightListChecked).sort(compareFn)); setCheckedList(difference(checkedList, rightListChecked)); }; return ( ); }; export default TransferList;