Improve the flow for archive screen. Fix https://github.com/donetick/frontend/issues/41
This commit is contained in:
@@ -443,6 +443,8 @@ const ArchivedTasks = () => {
|
||||
onChoreRemove={handleChoreDeleted}
|
||||
performers={performers}
|
||||
viewOnly={false}
|
||||
showActions={false}
|
||||
// onAction={handleChoreAction}
|
||||
// Multi-select props
|
||||
isMultiSelectMode={isMultiSelectMode}
|
||||
isSelected={selectedChores.has(chore.id)}
|
||||
|
||||
@@ -40,6 +40,7 @@ const ChoreCard = ({
|
||||
performers,
|
||||
sx,
|
||||
viewOnly,
|
||||
showActions = true,
|
||||
onChipClick,
|
||||
onAction,
|
||||
// Multi-select props
|
||||
@@ -862,44 +863,45 @@ const ChoreCard = ({
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
display='flex'
|
||||
justifyContent='flex-end'
|
||||
alignItems='flex-end'
|
||||
>
|
||||
{/* <ButtonGroup> */}
|
||||
{chore.status === 3 ? (
|
||||
// Pending approval: Show approve/reject for admins/managers/owners, grayed out for others
|
||||
canApproveReject() ? (
|
||||
<Box sx={{ display: 'flex', gap: 0.5 }}>
|
||||
<IconButton
|
||||
variant='soft'
|
||||
color='success'
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
onAction('approve', chore)
|
||||
}}
|
||||
sx={{
|
||||
borderRadius: '50%',
|
||||
minWidth: 50,
|
||||
height: 50,
|
||||
zIndex: 1,
|
||||
transition: 'all 0.2s ease',
|
||||
'&:hover': {
|
||||
transform: 'scale(1.05)',
|
||||
},
|
||||
'&:active': {
|
||||
transform: 'scale(0.95)',
|
||||
},
|
||||
'&:disabled': {
|
||||
opacity: 0.5,
|
||||
transform: 'none',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ThumbUp sx={{ fontSize: 18 }} />
|
||||
</IconButton>
|
||||
{/* <IconButton
|
||||
{showActions && (
|
||||
<Box
|
||||
display='flex'
|
||||
justifyContent='flex-end'
|
||||
alignItems='flex-end'
|
||||
>
|
||||
{/* <ButtonGroup> */}
|
||||
{chore.status === 3 ? (
|
||||
// Pending approval: Show approve/reject for admins/managers/owners, grayed out for others
|
||||
canApproveReject() ? (
|
||||
<Box sx={{ display: 'flex', gap: 0.5 }}>
|
||||
<IconButton
|
||||
variant='soft'
|
||||
color='success'
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
onAction('approve', chore)
|
||||
}}
|
||||
sx={{
|
||||
borderRadius: '50%',
|
||||
minWidth: 50,
|
||||
height: 50,
|
||||
zIndex: 1,
|
||||
transition: 'all 0.2s ease',
|
||||
'&:hover': {
|
||||
transform: 'scale(1.05)',
|
||||
},
|
||||
'&:active': {
|
||||
transform: 'scale(0.95)',
|
||||
},
|
||||
'&:disabled': {
|
||||
opacity: 0.5,
|
||||
transform: 'none',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ThumbUp sx={{ fontSize: 18 }} />
|
||||
</IconButton>
|
||||
{/* <IconButton
|
||||
variant='soft'
|
||||
color='danger'
|
||||
onClick={e => {
|
||||
@@ -922,97 +924,100 @@ const ChoreCard = ({
|
||||
>
|
||||
<ThumbDown sx={{ fontSize: 18 }} />
|
||||
</IconButton> */}
|
||||
</Box>
|
||||
</Box>
|
||||
) : (
|
||||
<IconButton
|
||||
variant='soft'
|
||||
color='neutral'
|
||||
disabled={true}
|
||||
sx={{
|
||||
borderRadius: '50%',
|
||||
minWidth: 50,
|
||||
height: 50,
|
||||
zIndex: 1,
|
||||
opacity: 0.5,
|
||||
}}
|
||||
>
|
||||
<HourglassEmpty />
|
||||
</IconButton>
|
||||
)
|
||||
) : (
|
||||
<IconButton
|
||||
variant='soft'
|
||||
color='neutral'
|
||||
disabled={true}
|
||||
variant={chore.status === 0 ? 'solid' : 'soft'}
|
||||
color={chore.status === 0 ? 'success' : 'warning'}
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
switch (chore.status) {
|
||||
case 0: // Not started
|
||||
onAction('complete', chore)
|
||||
break
|
||||
case 1: // In progress
|
||||
onAction('pause', chore)
|
||||
break
|
||||
case 2: // Paused
|
||||
onAction('start', chore)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}}
|
||||
disabled={notInCompletionWindow(chore)}
|
||||
sx={{
|
||||
borderRadius: '50%',
|
||||
minWidth: 50,
|
||||
height: 50,
|
||||
zIndex: 1,
|
||||
opacity: 0.5,
|
||||
transition: 'all 0.2s ease',
|
||||
'&:hover': {
|
||||
transform: 'scale(1.05)',
|
||||
},
|
||||
'&:active': {
|
||||
transform: 'scale(0.95)',
|
||||
},
|
||||
'&:disabled': {
|
||||
opacity: 0.5,
|
||||
transform: 'none',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<HourglassEmpty />
|
||||
<div className='relative grid place-items-center'>
|
||||
{chore.status === 0 ? (
|
||||
<Check />
|
||||
) : chore.status === 1 ? (
|
||||
<Pause />
|
||||
) : (
|
||||
<PlayArrow />
|
||||
)}
|
||||
</div>
|
||||
</IconButton>
|
||||
)
|
||||
) : (
|
||||
<IconButton
|
||||
variant={chore.status === 0 ? 'solid' : 'soft'}
|
||||
color={chore.status === 0 ? 'success' : 'warning'}
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
switch (chore.status) {
|
||||
case 0: // Not started
|
||||
onAction('complete', chore)
|
||||
break
|
||||
case 1: // In progress
|
||||
onAction('pause', chore)
|
||||
break
|
||||
case 2: // Paused
|
||||
onAction('start', chore)
|
||||
break
|
||||
default:
|
||||
break
|
||||
)}
|
||||
<ChoreActionMenu
|
||||
chore={chore}
|
||||
onCompleteWithNote={() =>
|
||||
onAction('completeWithNote', chore)
|
||||
}
|
||||
onCompleteWithPastDate={() =>
|
||||
onAction('completeWithPastDate', chore)
|
||||
}
|
||||
onAction={(type, chore, extraData) =>
|
||||
onAction(type, chore, extraData)
|
||||
}
|
||||
onChangeAssignee={() => onAction('changeAssignee', chore)}
|
||||
onChangeDueDate={() => onAction('changeDueDate', chore)}
|
||||
onWriteNFC={() => onAction('writeNFC', chore)}
|
||||
onNudge={() => onAction('nudge', chore)}
|
||||
onDelete={() => onAction('delete', chore)}
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onOpen={() => {
|
||||
// Clear any pending hide timer when menu opens
|
||||
if (hoverTimer) {
|
||||
clearTimeout(hoverTimer)
|
||||
setHoverTimer(null)
|
||||
}
|
||||
}}
|
||||
disabled={notInCompletionWindow(chore)}
|
||||
sx={{
|
||||
borderRadius: '50%',
|
||||
minWidth: 50,
|
||||
height: 50,
|
||||
zIndex: 1,
|
||||
transition: 'all 0.2s ease',
|
||||
'&:hover': {
|
||||
transform: 'scale(1.05)',
|
||||
},
|
||||
'&:active': {
|
||||
transform: 'scale(0.95)',
|
||||
},
|
||||
'&:disabled': {
|
||||
opacity: 0.5,
|
||||
transform: 'none',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<div className='relative grid place-items-center'>
|
||||
{chore.status === 0 ? (
|
||||
<Check />
|
||||
) : chore.status === 1 ? (
|
||||
<Pause />
|
||||
) : (
|
||||
<PlayArrow />
|
||||
)}
|
||||
</div>
|
||||
</IconButton>
|
||||
)}
|
||||
<ChoreActionMenu
|
||||
chore={chore}
|
||||
onCompleteWithNote={() => onAction('completeWithNote', chore)}
|
||||
onCompleteWithPastDate={() =>
|
||||
onAction('completeWithPastDate', chore)
|
||||
}
|
||||
onAction={(type, chore, extraData) =>
|
||||
onAction(type, chore, extraData)
|
||||
}
|
||||
onChangeAssignee={() => onAction('changeAssignee', chore)}
|
||||
onChangeDueDate={() => onAction('changeDueDate', chore)}
|
||||
onWriteNFC={() => onAction('writeNFC', chore)}
|
||||
onNudge={() => onAction('nudge', chore)}
|
||||
onDelete={() => onAction('delete', chore)}
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onOpen={() => {
|
||||
// Clear any pending hide timer when menu opens
|
||||
if (hoverTimer) {
|
||||
clearTimeout(hoverTimer)
|
||||
setHoverTimer(null)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Card>
|
||||
|
||||
@@ -32,6 +32,7 @@ const CompactChoreCard = ({
|
||||
performers,
|
||||
sx,
|
||||
viewOnly,
|
||||
showActions = true,
|
||||
onChipClick,
|
||||
onAction,
|
||||
// Multi-select props
|
||||
@@ -708,53 +709,54 @@ const CompactChoreCard = ({
|
||||
}}
|
||||
>
|
||||
{/* Complete Button */}
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
transition:
|
||||
'opacity 0.3s ease-in-out, transform 0.3s ease-in-out',
|
||||
opacity: isMultiSelectMode ? 0 : 1,
|
||||
transform: isMultiSelectMode
|
||||
? 'scale(0.8) rotate(45deg)'
|
||||
: 'scale(1) rotate(0deg)',
|
||||
pointerEvents: isMultiSelectMode ? 'none' : 'auto',
|
||||
}}
|
||||
>
|
||||
{chore.status === 3 ? (
|
||||
// Pending approval: Show approve/reject for admins/managers/owners, grayed out for others
|
||||
canApproveReject() ? (
|
||||
<Box sx={{ display: 'flex', gap: 0.25 }}>
|
||||
<IconButton
|
||||
variant='soft'
|
||||
color='success'
|
||||
size='sm'
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
onAction('approve', chore)
|
||||
}}
|
||||
sx={{
|
||||
width: 24,
|
||||
height: 24,
|
||||
borderRadius: '50%',
|
||||
transition: 'all 0.2s ease',
|
||||
'&:hover': {
|
||||
transform: 'scale(1.05)',
|
||||
},
|
||||
'&:active': {
|
||||
transform: 'scale(0.95)',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ThumbUp sx={{ fontSize: 12 }} />
|
||||
</IconButton>
|
||||
{/* <IconButton
|
||||
{showActions && (
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
transition:
|
||||
'opacity 0.3s ease-in-out, transform 0.3s ease-in-out',
|
||||
opacity: isMultiSelectMode ? 0 : 1,
|
||||
transform: isMultiSelectMode
|
||||
? 'scale(0.8) rotate(45deg)'
|
||||
: 'scale(1) rotate(0deg)',
|
||||
pointerEvents: isMultiSelectMode ? 'none' : 'auto',
|
||||
}}
|
||||
>
|
||||
{chore.status === 3 ? (
|
||||
// Pending approval: Show approve/reject for admins/managers/owners, grayed out for others
|
||||
canApproveReject() ? (
|
||||
<Box sx={{ display: 'flex', gap: 0.25 }}>
|
||||
<IconButton
|
||||
variant='soft'
|
||||
color='success'
|
||||
size='sm'
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
onAction('approve', chore)
|
||||
}}
|
||||
sx={{
|
||||
width: 24,
|
||||
height: 24,
|
||||
borderRadius: '50%',
|
||||
transition: 'all 0.2s ease',
|
||||
'&:hover': {
|
||||
transform: 'scale(1.05)',
|
||||
},
|
||||
'&:active': {
|
||||
transform: 'scale(0.95)',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ThumbUp sx={{ fontSize: 12 }} />
|
||||
</IconButton>
|
||||
{/* <IconButton
|
||||
variant='soft'
|
||||
color='danger'
|
||||
size='sm'
|
||||
@@ -777,68 +779,68 @@ const CompactChoreCard = ({
|
||||
>
|
||||
<ThumbDown sx={{ fontSize: 12 }} />
|
||||
</IconButton> */}
|
||||
</Box>
|
||||
</Box>
|
||||
) : (
|
||||
<IconButton
|
||||
variant='soft'
|
||||
color='neutral'
|
||||
size='sm'
|
||||
disabled={true}
|
||||
sx={{
|
||||
width: 32,
|
||||
height: 32,
|
||||
borderRadius: '50%',
|
||||
opacity: 0.5,
|
||||
}}
|
||||
>
|
||||
<HourglassEmpty sx={{ fontSize: 16 }} />
|
||||
</IconButton>
|
||||
)
|
||||
) : (
|
||||
<IconButton
|
||||
variant='soft'
|
||||
color='neutral'
|
||||
color={chore.status === 0 ? 'success' : 'warning'}
|
||||
size='sm'
|
||||
disabled={true}
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
if (chore.status === 0) {
|
||||
onAction('complete', chore)
|
||||
} else if (chore.status === 1) {
|
||||
onAction('pause', chore)
|
||||
} else {
|
||||
onAction('start', chore)
|
||||
}
|
||||
}}
|
||||
disabled={notInCompletionWindow(chore)}
|
||||
sx={{
|
||||
width: 32,
|
||||
height: 32,
|
||||
borderRadius: '50%',
|
||||
opacity: 0.5,
|
||||
transition: 'all 0.2s ease',
|
||||
'&:hover': {
|
||||
transform: 'scale(1.05)',
|
||||
},
|
||||
|
||||
'&:active': {
|
||||
transform: 'scale(0.95)',
|
||||
},
|
||||
'&:disabled': {
|
||||
opacity: 0.5,
|
||||
transform: 'none',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<HourglassEmpty sx={{ fontSize: 16 }} />
|
||||
{chore.status === 0 ? (
|
||||
<Check sx={{ fontSize: 16 }} />
|
||||
) : chore.status === 1 ? (
|
||||
<Pause sx={{ fontSize: 16 }} />
|
||||
) : (
|
||||
<PlayArrow sx={{ fontSize: 16 }} />
|
||||
)}
|
||||
</IconButton>
|
||||
)
|
||||
) : (
|
||||
<IconButton
|
||||
variant='soft'
|
||||
color={chore.status === 0 ? 'success' : 'warning'}
|
||||
size='sm'
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
if (chore.status === 0) {
|
||||
onAction('complete', chore)
|
||||
} else if (chore.status === 1) {
|
||||
onAction('pause', chore)
|
||||
} else {
|
||||
onAction('start', chore)
|
||||
}
|
||||
}}
|
||||
disabled={notInCompletionWindow(chore)}
|
||||
sx={{
|
||||
width: 32,
|
||||
height: 32,
|
||||
borderRadius: '50%',
|
||||
transition: 'all 0.2s ease',
|
||||
'&:hover': {
|
||||
transform: 'scale(1.05)',
|
||||
},
|
||||
|
||||
'&:active': {
|
||||
transform: 'scale(0.95)',
|
||||
},
|
||||
'&:disabled': {
|
||||
opacity: 0.5,
|
||||
transform: 'none',
|
||||
},
|
||||
}}
|
||||
>
|
||||
{chore.status === 0 ? (
|
||||
<Check sx={{ fontSize: 16 }} />
|
||||
) : chore.status === 1 ? (
|
||||
<Pause sx={{ fontSize: 16 }} />
|
||||
) : (
|
||||
<PlayArrow sx={{ fontSize: 16 }} />
|
||||
)}
|
||||
</IconButton>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
{/* Multi-select Checkbox */}
|
||||
<Box
|
||||
sx={{
|
||||
@@ -1015,35 +1017,37 @@ const CompactChoreCard = ({
|
||||
pointerEvents: isMultiSelectMode ? 'none' : 'auto',
|
||||
}}
|
||||
>
|
||||
<ChoreActionMenu
|
||||
variant='plain'
|
||||
chore={chore}
|
||||
onAction={onAction}
|
||||
onCompleteWithNote={() => onAction('completeWithNote', chore)}
|
||||
onCompleteWithPastDate={() =>
|
||||
onAction('completeWithPastDate', chore)
|
||||
}
|
||||
onChangeAssignee={() => onAction('changeAssignee', chore)}
|
||||
onChangeDueDate={() => onAction('changeDueDate', chore)}
|
||||
onWriteNFC={() => onAction('writeNFC', chore)}
|
||||
onNudge={() => onAction('nudge', chore)}
|
||||
onDelete={() => onAction('delete', chore)}
|
||||
onMouseEnter={handleMouseEnter}
|
||||
// onMouseLeave={handleMouseLeave}
|
||||
sx={{
|
||||
width: 32,
|
||||
height: 32,
|
||||
color: 'text.tertiary',
|
||||
flexShrink: 0,
|
||||
'&:hover': {
|
||||
color: 'text.secondary',
|
||||
bgcolor: 'background.level1',
|
||||
},
|
||||
}}
|
||||
onOpen={() => {
|
||||
handleMouseLeave()
|
||||
}}
|
||||
/>
|
||||
{showActions && (
|
||||
<ChoreActionMenu
|
||||
variant='plain'
|
||||
chore={chore}
|
||||
onAction={onAction}
|
||||
onCompleteWithNote={() => onAction('completeWithNote', chore)}
|
||||
onCompleteWithPastDate={() =>
|
||||
onAction('completeWithPastDate', chore)
|
||||
}
|
||||
onChangeAssignee={() => onAction('changeAssignee', chore)}
|
||||
onChangeDueDate={() => onAction('changeDueDate', chore)}
|
||||
onWriteNFC={() => onAction('writeNFC', chore)}
|
||||
onNudge={() => onAction('nudge', chore)}
|
||||
onDelete={() => onAction('delete', chore)}
|
||||
onMouseEnter={handleMouseEnter}
|
||||
// onMouseLeave={handleMouseLeave}
|
||||
sx={{
|
||||
width: 32,
|
||||
height: 32,
|
||||
color: 'text.tertiary',
|
||||
flexShrink: 0,
|
||||
'&:hover': {
|
||||
color: 'text.secondary',
|
||||
bgcolor: 'background.level1',
|
||||
},
|
||||
}}
|
||||
onOpen={() => {
|
||||
handleMouseLeave()
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
Reference in New Issue
Block a user