Add more functionality to TransferBox
This commit is contained in:
parent
fe13b651ed
commit
892134d63b
3 changed files with 213 additions and 89 deletions
|
|
@ -5,6 +5,70 @@ import DoNotDisturbIcon from '@mui/icons-material/DoNotDisturb';
|
|||
import KeyboardArrowLeftIcon from '@mui/icons-material/KeyboardArrowLeft';
|
||||
import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
|
||||
|
||||
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;
|
||||
`;
|
||||
|
||||
const CenterButton = styled('div')`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
|
@ -26,7 +90,21 @@ const CenterButton = styled('div')`
|
|||
`}
|
||||
`;
|
||||
|
||||
export const TransferBox = ({ fields, leftGroup, rightGroup }) => {
|
||||
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={} }) => {
|
||||
const {
|
||||
id,
|
||||
exclusionList,
|
||||
|
|
@ -35,104 +113,141 @@ export const TransferBox = ({ fields, leftGroup, rightGroup }) => {
|
|||
} = fields;
|
||||
|
||||
const [itemSelected, setItemSelected] = useState({});
|
||||
const [containsSelection, setContainsSelection] = useState([]);
|
||||
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);
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex', flexDirection: 'row', width: '100%', justifyContent: 'space-around' }}>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', width: '100%', alignItems: 'center', padding: '5px' }}>
|
||||
<div style={{ paddingBottom: '10px' }}>
|
||||
<OuterShell>
|
||||
<TransferShell>
|
||||
<TransferHeader>
|
||||
<h2>{oldListLabel}</h2>
|
||||
</div>
|
||||
<div style={{ display: 'flex', width: '200px', height: '250px', border: '1px solid black', borderRadius: '5px', backgroundColor: '#E8E8E8' }}>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
padding: '5px',
|
||||
}}
|
||||
>
|
||||
{leftGroup?.map((j, index) => {
|
||||
</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;
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
style={{
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
width: '80%',
|
||||
padding: '2px',
|
||||
<TransferBoxItem
|
||||
key={j?.id}
|
||||
isSelected={isSelected}
|
||||
disabled={isUser}
|
||||
onClick={() => {
|
||||
if (isUser) return;
|
||||
handleItemClick(j, 'left');
|
||||
}}
|
||||
title={j?.value}
|
||||
>
|
||||
<span>{j?.value}</span>
|
||||
</div>
|
||||
<TransferBoxLabel>
|
||||
{j?.value}
|
||||
</TransferBoxLabel>
|
||||
</TransferBoxItem>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', width: '25%', alignItems: 'center', justifyContent: 'center' }}>
|
||||
</TransferInnerBox>
|
||||
</TransferOuterBox>
|
||||
</TransferShell>
|
||||
<TransferButtonShell>
|
||||
<CenterButton
|
||||
onClick={() => { console.log('clicked Right') }}
|
||||
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({});
|
||||
}}
|
||||
color='#A8A8A8'
|
||||
buttonEnabled={itemSelected?.id}
|
||||
buttonEnabled={isRightArrowEnabled}
|
||||
>
|
||||
<KeyboardArrowRightIcon />
|
||||
</CenterButton>
|
||||
<CenterButton
|
||||
onClick={() => { console.log('clicked Clear') }}
|
||||
onClick={() => {
|
||||
setLeftItems(sortByLastThenFirst(leftGroup));
|
||||
setRightItems(sortByLastThenFirst(rightGroup));
|
||||
setItemSelected({});
|
||||
}}
|
||||
color='#FF6666'
|
||||
buttonEnabled={containsSelection?.length > 0}
|
||||
buttonEnabled={hasChanges}
|
||||
>
|
||||
<DoNotDisturbIcon />
|
||||
</CenterButton>
|
||||
<CenterButton
|
||||
onClick={() => { console.log('clicked Save') }}
|
||||
onClick={() => {
|
||||
return onSave(rightItems?.map((item) => { return item?.id }))
|
||||
}}
|
||||
color='#00B33C'
|
||||
buttonEnabled={containsSelection?.length > 0}
|
||||
buttonEnabled={hasChanges}
|
||||
>
|
||||
<CheckIcon />
|
||||
</CenterButton>
|
||||
<CenterButton
|
||||
onClick={() => { console.log('clicked Left') }}
|
||||
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({});
|
||||
}}
|
||||
color='#A8A8A8'
|
||||
buttonEnabled={itemSelected?.id}
|
||||
buttonEnabled={isLeftArrowEnabled}
|
||||
>
|
||||
<KeyboardArrowLeftIcon />
|
||||
</CenterButton>
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', width: '100%', alignItems: 'center', padding: '5px' }}>
|
||||
<div style={{ paddingBottom: '10px' }}>
|
||||
</TransferButtonShell>
|
||||
<TransferShell>
|
||||
<TransferHeader>
|
||||
<h2>{newListLabel}</h2>
|
||||
</div>
|
||||
<div style={{ display: 'flex', width: '200px', height: '250px', border: '1px solid black', borderRadius: '5px', backgroundColor: '#E8E8E8' }}>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
padding: '5px',
|
||||
}}
|
||||
>
|
||||
{rightGroup?.map((j, index) => {
|
||||
</TransferHeader>
|
||||
<TransferOuterBox>
|
||||
<TransferInnerBox>
|
||||
{rightItems?.map((j) => {
|
||||
const isUser = user?.id === j?.id;
|
||||
const isSelected = itemSelected?.id === j?.id && itemSelected?.from === 'right' && !isUser;
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
style={{
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
width: '80%',
|
||||
padding: '2px',
|
||||
<TransferBoxItem
|
||||
key={j?.id}
|
||||
isSelected={isSelected}
|
||||
disabled={isUser}
|
||||
onClick={() => {
|
||||
if (isUser) return;
|
||||
handleItemClick(j, 'right');
|
||||
}}
|
||||
title={j?.value}
|
||||
>
|
||||
<span>{j?.value}</span>
|
||||
</div>
|
||||
<TransferBoxLabel>
|
||||
{j?.value}
|
||||
</TransferBoxLabel>
|
||||
</TransferBoxItem>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</TransferInnerBox>
|
||||
</TransferOuterBox>
|
||||
</TransferShell>
|
||||
</OuterShell>
|
||||
);
|
||||
}
|
||||
|
|
@ -285,8 +285,22 @@ export const Settings = () => {
|
|||
}, [pageValue?.id, windowWidth, window.innerHeight]);
|
||||
|
||||
useEffect(() => {
|
||||
setPageValue(settingsFields?.filter((field) => field?.tab === tabValue?.value)[0]);
|
||||
}, [tabValue]);
|
||||
const filteredFields = settingsFields?.filter((field) => {
|
||||
const hasAccess =
|
||||
(field?.accessRequired === 'administrator' && isAdministrator) ||
|
||||
(field?.accessRequired === 'manager' && isManager) ||
|
||||
(field?.accessRequired === 'scheduler' && isScheduler) ||
|
||||
(!field?.accessRequired || field?.accessRequired === 'user');
|
||||
|
||||
return field?.tab === tabValue?.value && hasAccess;
|
||||
});
|
||||
|
||||
if (filteredFields.length > 0) {
|
||||
setPageValue(filteredFields[0]);
|
||||
} else {
|
||||
setPageValue(null);
|
||||
}
|
||||
}, [tabValue, isAdministrator, isManager, isScheduler]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
|
@ -433,9 +447,11 @@ export const Settings = () => {
|
|||
} else if (field?.type === 'transfer') {
|
||||
fieldType = <TransferBox
|
||||
style={{ display: 'flex', flexDirection: 'row' }}
|
||||
user={user}
|
||||
fields={field}
|
||||
leftGroup={department[field?.origList]}
|
||||
rightGroup={department[field?.id]}
|
||||
onSave={(t) => console.log(t)}
|
||||
/>
|
||||
}
|
||||
return field?.type !== 'header' && (
|
||||
|
|
|
|||
|
|
@ -85,22 +85,22 @@ export const settingsFields = [
|
|||
title: 'Roles',
|
||||
tab: 'department',
|
||||
cards: [
|
||||
{
|
||||
id: 'companyAdmins',
|
||||
label: 'Company Administrators',
|
||||
fields: [
|
||||
{
|
||||
id: 'administrators',
|
||||
type: 'transfer',
|
||||
exclusionList: [],
|
||||
origList: 'users',
|
||||
oldListLabel: 'Users',
|
||||
newListLabel: 'Administrators'
|
||||
},
|
||||
],
|
||||
accessRequired: 'administrator',
|
||||
removeEdit: true
|
||||
},
|
||||
// Need to decide if Admins should be able to Add other Admins
|
||||
// {
|
||||
// id: 'companyAdmins',
|
||||
// label: 'Company Administrators',
|
||||
// fields: [
|
||||
// {
|
||||
// id: 'administrators',
|
||||
// type: 'transfer',
|
||||
// origList: 'users',
|
||||
// oldListLabel: 'Users',
|
||||
// newListLabel: 'Administrators'
|
||||
// },
|
||||
// ],
|
||||
// accessRequired: 'administrator',
|
||||
// removeEdit: true
|
||||
// },
|
||||
{
|
||||
id: 'companyMgrs',
|
||||
label: 'Company Managers',
|
||||
|
|
@ -108,9 +108,6 @@ export const settingsFields = [
|
|||
{
|
||||
id: 'managers',
|
||||
type: 'transfer',
|
||||
exclusionList: [
|
||||
'administrators'
|
||||
],
|
||||
origList: 'users',
|
||||
oldListLabel: 'Users',
|
||||
newListLabel: 'Managers'
|
||||
|
|
@ -126,10 +123,6 @@ export const settingsFields = [
|
|||
{
|
||||
id: 'schedulers',
|
||||
type: 'transfer',
|
||||
exclusionList: [
|
||||
'administrators',
|
||||
'managers'
|
||||
],
|
||||
origList: 'users',
|
||||
oldListLabel: 'Users',
|
||||
newListLabel: 'Schedulers'
|
||||
|
|
|
|||
Loading…
Reference in a new issue