Improve MarkChoreComplete, allow complete in past ,etc
This commit is contained in:
parent
df83cc8948
commit
e039b732a8
3 changed files with 228 additions and 92 deletions
|
@ -3,14 +3,19 @@ import {
|
|||
CancelScheduleSend,
|
||||
Check,
|
||||
Checklist,
|
||||
Note,
|
||||
PeopleAlt,
|
||||
Person,
|
||||
} from '@mui/icons-material'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Checkbox,
|
||||
Container,
|
||||
Divider,
|
||||
FormControl,
|
||||
Grid,
|
||||
Input,
|
||||
ListItem,
|
||||
ListItemContent,
|
||||
ListItemDecorator,
|
||||
|
@ -21,7 +26,7 @@ import {
|
|||
} from '@mui/joy'
|
||||
import moment from 'moment'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useParams, useSearchParams } from 'react-router-dom'
|
||||
import { useNavigate, useParams, useSearchParams } from 'react-router-dom'
|
||||
import {
|
||||
GetAllUsers,
|
||||
GetChoreDetailById,
|
||||
|
@ -43,14 +48,16 @@ const ChoreView = () => {
|
|||
const [performers, setPerformers] = useState([])
|
||||
const [infoCards, setInfoCards] = useState([])
|
||||
const { choreId } = useParams()
|
||||
const [note, setNote] = useState(null)
|
||||
|
||||
// query param `complete=true`
|
||||
const Navigate = useNavigate()
|
||||
|
||||
const [searchParams] = useSearchParams()
|
||||
|
||||
const [isPendingCompletion, setIsPendingCompletion] = useState(false)
|
||||
const [timeoutId, setTimeoutId] = useState(null)
|
||||
const [secondsLeftToCancel, setSecondsLeftToCancel] = useState(null)
|
||||
const [completedDate, setCompletedDate] = useState(null)
|
||||
useEffect(() => {
|
||||
Promise.all([
|
||||
GetChoreDetailById(choreId).then(resp => {
|
||||
|
@ -82,7 +89,7 @@ const ChoreView = () => {
|
|||
{
|
||||
icon: <CalendarMonth />,
|
||||
text: 'Due Date',
|
||||
subtext: moment(chore.dueDate).format('MM/DD/YYYY hh:mm A'),
|
||||
subtext: moment(chore.nextDueDate).format('MM/DD/YYYY hh:mm A'),
|
||||
},
|
||||
{
|
||||
icon: <PeopleAlt />,
|
||||
|
@ -119,12 +126,21 @@ const ChoreView = () => {
|
|||
subtext: chore.lastCompletedDate
|
||||
? `${
|
||||
chore.lastCompletedDate &&
|
||||
moment(chore.lastCompletedDate).format('MM/DD/YYYY hh:mm A')
|
||||
}(${
|
||||
performers.find(p => p.id === chore.lastCompletedBy)?.displayName
|
||||
})`
|
||||
moment(chore.lastCompletedDate).fromNow()
|
||||
// moment(chore.lastCompletedDate).format('MM/DD/YYYY hh:mm A'))
|
||||
}(
|
||||
${
|
||||
performers.find(p => p.id === chore.lastCompletedBy)
|
||||
?.displayName
|
||||
}
|
||||
)`
|
||||
: 'Never',
|
||||
},
|
||||
{
|
||||
icon: <Note />,
|
||||
text: 'Recent Note',
|
||||
subtext: chore.notes || '--',
|
||||
},
|
||||
]
|
||||
setInfoCards(cards)
|
||||
}
|
||||
|
@ -143,10 +159,11 @@ const ChoreView = () => {
|
|||
}, 1000)
|
||||
|
||||
const id = setTimeout(() => {
|
||||
MarkChoreComplete(choreId)
|
||||
MarkChoreComplete(choreId, note, completedDate)
|
||||
.then(resp => {
|
||||
if (resp.ok) {
|
||||
return resp.json().then(data => {
|
||||
setNote(null)
|
||||
setChore(data.res)
|
||||
})
|
||||
}
|
||||
|
@ -174,75 +191,130 @@ const ChoreView = () => {
|
|||
}
|
||||
|
||||
return (
|
||||
<Container maxWidth='sm'>
|
||||
<Sheet
|
||||
variant='plain'
|
||||
sx={{
|
||||
borderRadius: 'sm',
|
||||
p: 2,
|
||||
boxShadow: 'md',
|
||||
minHeight: '90vh',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'space-between',
|
||||
}}
|
||||
>
|
||||
<Box>
|
||||
<Typography
|
||||
level='h4'
|
||||
textAlign={'center'}
|
||||
sx={{
|
||||
mt: 2,
|
||||
mb: 4,
|
||||
}}
|
||||
>
|
||||
{chore.name}
|
||||
</Typography>
|
||||
|
||||
<Grid container spacing={1}>
|
||||
{infoCards.map((info, index) => (
|
||||
<Grid key={index} item xs={12} sm={6}>
|
||||
<Sheet
|
||||
sx={{ mb: 1, borderRadius: 'md', p: 1, boxShadow: 'sm' }}
|
||||
>
|
||||
<ListItem>
|
||||
<ListItemDecorator>
|
||||
<IconCard>{info.icon}</IconCard>
|
||||
</ListItemDecorator>
|
||||
<ListItemContent>
|
||||
<Typography level='body1' sx={{ fontWeight: 'md' }}>
|
||||
{info.text}
|
||||
</Typography>
|
||||
<Typography level='body1' color='text.tertiary'>
|
||||
{info.subtext ? info.subtext : '--'}
|
||||
</Typography>
|
||||
</ListItemContent>
|
||||
</ListItem>
|
||||
</Sheet>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</Box>
|
||||
<Box
|
||||
<Container
|
||||
maxWidth='sm'
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
// space between :
|
||||
justifyContent: 'space-between',
|
||||
}}
|
||||
>
|
||||
<Box>
|
||||
<Typography
|
||||
level='h3'
|
||||
textAlign={'center'}
|
||||
sx={{
|
||||
mt: 6,
|
||||
mt: 2,
|
||||
mb: 4,
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
fullWidth
|
||||
size='lg'
|
||||
sx={{
|
||||
height: 50,
|
||||
mb: 2,
|
||||
{chore.name}
|
||||
</Typography>
|
||||
|
||||
<Grid container spacing={1}>
|
||||
{infoCards.map((info, index) => (
|
||||
<Grid key={index} item xs={12} sm={6}>
|
||||
<Sheet sx={{ mb: 1, borderRadius: 'md', p: 1, boxShadow: 'sm' }}>
|
||||
<ListItem>
|
||||
<ListItemDecorator>
|
||||
<IconCard>{info.icon}</IconCard>
|
||||
</ListItemDecorator>
|
||||
<ListItemContent>
|
||||
<Typography level='body1' sx={{ fontWeight: 'md' }}>
|
||||
{info.text}
|
||||
</Typography>
|
||||
<Typography level='body1' color='text.tertiary'>
|
||||
{info.subtext ? info.subtext : '--'}
|
||||
</Typography>
|
||||
</ListItemContent>
|
||||
</ListItem>
|
||||
</Sheet>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</Box>
|
||||
<Divider
|
||||
sx={{
|
||||
my: 2,
|
||||
}}
|
||||
/>
|
||||
|
||||
<Box>
|
||||
<Typography level='title-md'>Additional Notes</Typography>
|
||||
<Input
|
||||
fullWidth
|
||||
multiline
|
||||
label='Additional Notes'
|
||||
placeholder='note or information about the task'
|
||||
value={note || ''}
|
||||
onChange={e => {
|
||||
if (e.target.value.trim() === '') {
|
||||
setNote(null)
|
||||
return
|
||||
}
|
||||
setNote(e.target.value)
|
||||
}}
|
||||
size='md'
|
||||
sx={{
|
||||
my: 1,
|
||||
}}
|
||||
/>
|
||||
<FormControl size='sm' sx={{ width: 400 }}>
|
||||
<Checkbox
|
||||
defaultChecked={completedDate !== null}
|
||||
checked={completedDate !== null}
|
||||
value={completedDate !== null}
|
||||
onChange={e => {
|
||||
if (e.target.checked) {
|
||||
setCompletedDate(
|
||||
moment(new Date()).format('YYYY-MM-DDTHH:00:00'),
|
||||
)
|
||||
} else {
|
||||
setCompletedDate(null)
|
||||
}
|
||||
}}
|
||||
onClick={handleTaskCompletion}
|
||||
disabled={isPendingCompletion}
|
||||
color={isPendingCompletion ? 'danger' : 'success'}
|
||||
startDecorator={<Check />}
|
||||
>
|
||||
<Box>Mark as done</Box>
|
||||
</Button>
|
||||
{/* <Button
|
||||
overlay
|
||||
sx={{
|
||||
my: 1,
|
||||
}}
|
||||
label={<Typography level='body2'>Set completion date</Typography>}
|
||||
/>
|
||||
</FormControl>
|
||||
{completedDate !== null && (
|
||||
<Input
|
||||
sx={{ mt: 1, mb: 1.5, width: 300 }}
|
||||
type='datetime-local'
|
||||
value={completedDate}
|
||||
onChange={e => {
|
||||
setCompletedDate(e.target.value)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{completedDate === null && (
|
||||
// placeholder for the completion date with margin:
|
||||
<Box
|
||||
sx={{
|
||||
height: 56,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Button
|
||||
fullWidth
|
||||
size='lg'
|
||||
sx={{
|
||||
height: 50,
|
||||
mb: 2,
|
||||
}}
|
||||
onClick={handleTaskCompletion}
|
||||
disabled={isPendingCompletion}
|
||||
color={isPendingCompletion ? 'danger' : 'success'}
|
||||
startDecorator={<Check />}
|
||||
>
|
||||
<Box>Mark as done</Box>
|
||||
</Button>
|
||||
{/* <Button
|
||||
sx={{
|
||||
borderRadius: '32px',
|
||||
mt: 1,
|
||||
|
@ -258,8 +330,8 @@ const ChoreView = () => {
|
|||
>
|
||||
<Box>Mark as {isPendingCompletion ? 'completed' : 'done'}</Box>
|
||||
</Button> */}
|
||||
</Box>
|
||||
</Sheet>
|
||||
</Box>
|
||||
|
||||
<Snackbar
|
||||
open={isPendingCompletion}
|
||||
endDecorator={
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue