ShiftSync/web/components/common/TransferBox/TransferBox.jsx

254 lines
7.4 KiB
React
Raw Normal View History

2025-06-03 22:52:40 +00:00
import React, { useState } from 'react';
import styled from '@emotion/styled';
import CheckIcon from '@mui/icons-material/Check';
import DoNotDisturbIcon from '@mui/icons-material/DoNotDisturb';
import KeyboardArrowLeftIcon from '@mui/icons-material/KeyboardArrowLeft';
import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
2025-06-04 06:29:10 +00:00
const OuterShell = styled('div')`
display: flex;
flex-direction: row;
width: 100%;
justify-content: space-around;
`;
const TransferShell = styled('div')`
display: flex;
flex-direction: column;
width: 100%;
align-items: center;
padding: 5px;
`;
const TransferButtonShell = styled('div')`
display: flex;
flex-direction: column;
width: 25%;
align-items: center;
justify-content: center;
`;
const TransferHeader = styled('div')`
padding-bottom: 10px;
`;
const TransferOuterBox = styled('div')`
display: flex;
width: 200px;
height: 250px;
border: 1px solid black;
border-radius: 5px;
background-color: #E8E8E8;
`;
const TransferInnerBox = styled('div')`
display: flex;
flex-direction: column;
padding: 5px;
`;
const TransferBoxItem = styled('div')`
display: flex;
align-items: center;
width: 188px;
padding: 2px 4px;
background-color: ${({ isSelected }) => (isSelected ? '#D3D3D3' : 'transparent')};
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
color: ${({ disabled }) => (disabled ? '#999' : 'inherit')};
border-radius: 4px;
overflow: hidden;
user-select: ${({ disabled }) => (disabled ? 'none' : 'auto')};
opacity: ${({ disabled }) => (disabled ? 0.5 : 1)};
`;
const TransferBoxLabel = styled('span')`
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex: 1;
min-width: 0;
`;
2025-06-03 22:52:40 +00:00
const CenterButton = styled('div')`
display: flex;
justify-content: center;
align-items: center;
width: 30px;
height: 30px;
border: 1px solid black;
border-radius: 5px;
margin: 5px;
cursor: ${({ buttonEnabled }) => (buttonEnabled ? 'pointer' : 'not-allowed')};
transition: background-color 0.3s ease, color 0.3s ease;
opacity: ${({ buttonEnabled }) => (buttonEnabled ? 1 : 0.5)};
${({ color, buttonEnabled }) => buttonEnabled && color && `
&:hover {
background-color: ${color};
color: white;
}
`}
`;
2025-06-04 06:29:10 +00:00
const sortByLastThenFirst = (arr) => {
return [...arr].sort((a, b) => {
const [aLast, aFirst] = a.value.split(',').map(s => s.trim());
const [bLast, bFirst] = b.value.split(',').map(s => s.trim());
if (aLast < bLast) return -1;
if (aLast > bLast) return 1;
if (aFirst < bFirst) return -1;
if (aFirst > bFirst) return 1;
return 0;
});
};
export const TransferBox = ({ fields, leftGroup, rightGroup, onSave, user={} }) => {
2025-06-03 22:52:40 +00:00
const {
id,
exclusionList,
oldListLabel,
newListLabel
} = fields;
const [itemSelected, setItemSelected] = useState({});
2025-06-04 06:29:10 +00:00
const [leftItems, setLeftItems] = useState(sortByLastThenFirst(leftGroup || []));
const [rightItems, setRightItems] = useState(sortByLastThenFirst(rightGroup || []));
const handleItemClick = (item, side) => {
setItemSelected({ ...item, from: side });
};
const arraysEqual = (a, b) => {
if (a.length !== b.length) return false;
const aIds = a.map(i => i.id).sort();
const bIds = b.map(i => i.id).sort();
return JSON.stringify(aIds) === JSON.stringify(bIds);
};
const isLeftArrowEnabled = itemSelected?.from === 'right';
const isRightArrowEnabled = itemSelected?.from === 'left';
const hasChanges = !arraysEqual(leftItems, leftGroup) || !arraysEqual(rightItems, rightGroup);
2025-06-03 22:52:40 +00:00
return (
2025-06-04 06:29:10 +00:00
<OuterShell>
<TransferShell>
<TransferHeader>
2025-06-03 22:52:40 +00:00
<h2>{oldListLabel}</h2>
2025-06-04 06:29:10 +00:00
</TransferHeader>
<TransferOuterBox>
<TransferInnerBox>
{leftItems?.filter(leftItem => !rightItems.some(rightItem => rightItem.id === leftItem.id))?.map((j) => {
const isUser = user?.id === j?.id;
const isSelected = itemSelected?.id === j?.id && itemSelected?.from === 'left' && !isUser;
2025-06-03 22:52:40 +00:00
return (
2025-06-04 06:29:10 +00:00
<TransferBoxItem
key={j?.id}
isSelected={isSelected}
disabled={isUser}
onClick={() => {
if (isUser) return;
handleItemClick(j, 'left');
2025-06-03 22:52:40 +00:00
}}
title={j?.value}
>
2025-06-04 06:29:10 +00:00
<TransferBoxLabel>
{j?.value}
</TransferBoxLabel>
</TransferBoxItem>
2025-06-03 22:52:40 +00:00
)
})}
2025-06-04 06:29:10 +00:00
</TransferInnerBox>
</TransferOuterBox>
</TransferShell>
<TransferButtonShell>
2025-06-03 22:52:40 +00:00
<CenterButton
2025-06-04 06:29:10 +00:00
onClick={() => {
if (!itemSelected) return;
if (itemSelected.from === 'left') {
setLeftItems(prev => prev.filter(item => item.id !== itemSelected.id));
setRightItems(prev => sortByLastThenFirst([
...rightItems.filter(item => item.id !== itemSelected.id),
itemSelected
]));
}
setItemSelected({});
}}
2025-06-03 22:52:40 +00:00
color='#A8A8A8'
2025-06-04 06:29:10 +00:00
buttonEnabled={isRightArrowEnabled}
2025-06-03 22:52:40 +00:00
>
<KeyboardArrowRightIcon />
</CenterButton>
<CenterButton
2025-06-04 06:29:10 +00:00
onClick={() => {
setLeftItems(sortByLastThenFirst(leftGroup));
setRightItems(sortByLastThenFirst(rightGroup));
setItemSelected({});
}}
2025-06-03 22:52:40 +00:00
color='#FF6666'
2025-06-04 06:29:10 +00:00
buttonEnabled={hasChanges}
2025-06-03 22:52:40 +00:00
>
<DoNotDisturbIcon />
</CenterButton>
<CenterButton
2025-06-04 06:29:10 +00:00
onClick={() => {
2025-06-23 21:55:42 +00:00
onSave(rightItems?.map((item) => { return item?.id }));
setItemSelected({});
2025-06-04 06:29:10 +00:00
}}
2025-06-03 22:52:40 +00:00
color='#00B33C'
2025-06-04 06:29:10 +00:00
buttonEnabled={hasChanges}
2025-06-03 22:52:40 +00:00
>
<CheckIcon />
</CenterButton>
<CenterButton
2025-06-04 06:29:10 +00:00
onClick={() => {
if (!itemSelected) return;
if (itemSelected.from === 'right') {
setRightItems(prev => prev.filter(item => item.id !== itemSelected.id));
setLeftItems(prev => sortByLastThenFirst([
...leftItems.filter(item => item.id !== itemSelected.id),
itemSelected
]));
}
setItemSelected({});
}}
2025-06-03 22:52:40 +00:00
color='#A8A8A8'
2025-06-04 06:29:10 +00:00
buttonEnabled={isLeftArrowEnabled}
2025-06-03 22:52:40 +00:00
>
<KeyboardArrowLeftIcon />
</CenterButton>
2025-06-04 06:29:10 +00:00
</TransferButtonShell>
<TransferShell>
<TransferHeader>
2025-06-03 22:52:40 +00:00
<h2>{newListLabel}</h2>
2025-06-04 06:29:10 +00:00
</TransferHeader>
<TransferOuterBox>
<TransferInnerBox>
{rightItems?.map((j) => {
const isUser = user?.id === j?.id;
const isSelected = itemSelected?.id === j?.id && itemSelected?.from === 'right' && !isUser;
2025-06-03 22:52:40 +00:00
return (
2025-06-04 06:29:10 +00:00
<TransferBoxItem
key={j?.id}
isSelected={isSelected}
disabled={isUser}
onClick={() => {
if (isUser) return;
handleItemClick(j, 'right');
2025-06-03 22:52:40 +00:00
}}
title={j?.value}
>
2025-06-04 06:29:10 +00:00
<TransferBoxLabel>
{j?.value}
</TransferBoxLabel>
</TransferBoxItem>
2025-06-03 22:52:40 +00:00
)
})}
2025-06-04 06:29:10 +00:00
</TransferInnerBox>
</TransferOuterBox>
</TransferShell>
</OuterShell>
2025-06-03 22:52:40 +00:00
);
}