Update Chore view
This commit is contained in:
parent
7a490116b7
commit
93512eb666
3 changed files with 170 additions and 149 deletions
|
@ -73,6 +73,16 @@ const MarkChoreComplete = (id, note, completedDate) => {
|
||||||
body: JSON.stringify(body),
|
body: JSON.stringify(body),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SkipChore = id => {
|
||||||
|
return Fetch(`${API_URL}/chores/${id}/skip`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({}),
|
||||||
|
})
|
||||||
|
}
|
||||||
const CreateChore = chore => {
|
const CreateChore = chore => {
|
||||||
return Fetch(`${API_URL}/chores/`, {
|
return Fetch(`${API_URL}/chores/`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
@ -277,6 +287,7 @@ export {
|
||||||
SaveChore,
|
SaveChore,
|
||||||
SaveThing,
|
SaveThing,
|
||||||
signUp,
|
signUp,
|
||||||
|
SkipChore,
|
||||||
UpdateThingState,
|
UpdateThingState,
|
||||||
UpdateUserDetails,
|
UpdateUserDetails,
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,10 @@ import {
|
||||||
CancelScheduleSend,
|
CancelScheduleSend,
|
||||||
Check,
|
Check,
|
||||||
Checklist,
|
Checklist,
|
||||||
Edit,
|
|
||||||
History,
|
History,
|
||||||
Note,
|
|
||||||
PeopleAlt,
|
PeopleAlt,
|
||||||
Person,
|
Person,
|
||||||
|
SwitchAccessShortcut,
|
||||||
Timelapse,
|
Timelapse,
|
||||||
} from '@mui/icons-material'
|
} from '@mui/icons-material'
|
||||||
import {
|
import {
|
||||||
|
@ -22,7 +21,6 @@ import {
|
||||||
Input,
|
Input,
|
||||||
ListItem,
|
ListItem,
|
||||||
ListItemContent,
|
ListItemContent,
|
||||||
ListItemDecorator,
|
|
||||||
Sheet,
|
Sheet,
|
||||||
Snackbar,
|
Snackbar,
|
||||||
styled,
|
styled,
|
||||||
|
@ -35,15 +33,17 @@ import {
|
||||||
GetAllUsers,
|
GetAllUsers,
|
||||||
GetChoreDetailById,
|
GetChoreDetailById,
|
||||||
MarkChoreComplete,
|
MarkChoreComplete,
|
||||||
|
SkipChore,
|
||||||
} from '../../utils/Fetcher'
|
} from '../../utils/Fetcher'
|
||||||
|
import ConfirmationModal from '../Modals/Inputs/ConfirmationModal'
|
||||||
const IconCard = styled('div')({
|
const IconCard = styled('div')({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
backgroundColor: '#f0f0f0', // Adjust the background color as needed
|
backgroundColor: '#f0f0f0', // Adjust the background color as needed
|
||||||
borderRadius: '50%',
|
borderRadius: '50%',
|
||||||
minWidth: '50px',
|
minWidth: '40px',
|
||||||
height: '50px',
|
height: '40px',
|
||||||
marginRight: '16px',
|
marginRight: '16px',
|
||||||
})
|
})
|
||||||
const ChoreView = () => {
|
const ChoreView = () => {
|
||||||
|
@ -60,6 +60,8 @@ const ChoreView = () => {
|
||||||
const [timeoutId, setTimeoutId] = useState(null)
|
const [timeoutId, setTimeoutId] = useState(null)
|
||||||
const [secondsLeftToCancel, setSecondsLeftToCancel] = useState(null)
|
const [secondsLeftToCancel, setSecondsLeftToCancel] = useState(null)
|
||||||
const [completedDate, setCompletedDate] = useState(null)
|
const [completedDate, setCompletedDate] = useState(null)
|
||||||
|
const [confirmModelConfig, setConfirmModelConfig] = useState({})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Promise.all([
|
Promise.all([
|
||||||
GetChoreDetailById(choreId).then(resp => {
|
GetChoreDetailById(choreId).then(resp => {
|
||||||
|
@ -88,24 +90,21 @@ const ChoreView = () => {
|
||||||
|
|
||||||
const generateInfoCards = chore => {
|
const generateInfoCards = chore => {
|
||||||
const cards = [
|
const cards = [
|
||||||
// {
|
|
||||||
// size: 6,
|
|
||||||
// icon: <CalendarMonth />,
|
|
||||||
// text: 'Due Date',
|
|
||||||
// subtext: moment(chore.nextDueDate).format('MM/DD/YYYY hh:mm A'),
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
size: 6,
|
size: 6,
|
||||||
icon: <PeopleAlt />,
|
icon: <PeopleAlt />,
|
||||||
text: 'Assigned To',
|
text: 'Assigned To',
|
||||||
subtext: performers.find(p => p.id === chore.assignedTo)?.displayName,
|
subtext: performers.find(p => p.id === chore.assignedTo)?.displayName,
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// size: 6,
|
size: 6,
|
||||||
// icon: <Person />,
|
icon: <CalendarMonth />,
|
||||||
// text: 'Created By',
|
text: 'Due Date',
|
||||||
// subtext: performers.find(p => p.id === chore.createdBy)?.displayName,
|
subtext: chore.nextDueDate
|
||||||
// },
|
? moment(chore.nextDueDate).fromNow()
|
||||||
|
: 'N/A',
|
||||||
|
},
|
||||||
|
|
||||||
// {
|
// {
|
||||||
// icon: <TextFields />,
|
// icon: <TextFields />,
|
||||||
// text: 'Frequency',
|
// text: 'Frequency',
|
||||||
|
@ -116,37 +115,40 @@ const ChoreView = () => {
|
||||||
{
|
{
|
||||||
size: 6,
|
size: 6,
|
||||||
icon: <Checklist />,
|
icon: <Checklist />,
|
||||||
text: 'Completed',
|
text: 'Total Completed',
|
||||||
subtext: `${chore.totalCompletedCount} times`,
|
subtext: `${chore.totalCompletedCount} times`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
size: 6,
|
size: 6,
|
||||||
icon: <Timelapse />,
|
icon: <Timelapse />,
|
||||||
text: 'Last time',
|
text: 'Last Completed',
|
||||||
subtext:
|
subtext:
|
||||||
chore.lastCompletedDate &&
|
// chore.lastCompletedDate &&
|
||||||
moment(chore.lastCompletedDate).format('MM/DD/YYYY hh:mm A'),
|
// moment(chore.lastCompletedDate).format('MM/DD/YYYY hh:mm A'),
|
||||||
|
chore.lastCompletedDate && moment(chore.lastCompletedDate).fromNow(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
size: 6,
|
size: 6,
|
||||||
icon: <Person />,
|
icon: <Person />,
|
||||||
text: 'Last',
|
text: 'Last Performer',
|
||||||
subtext: chore.lastCompletedDate
|
subtext: chore.lastCompletedDate
|
||||||
? `${
|
? `${
|
||||||
chore.lastCompletedDate &&
|
|
||||||
moment(chore.lastCompletedDate).fromNow()
|
|
||||||
// moment(chore.lastCompletedDate).format('MM/DD/YYYY hh:mm A'))
|
|
||||||
}(${
|
|
||||||
performers.find(p => p.id === chore.lastCompletedBy)?.displayName
|
performers.find(p => p.id === chore.lastCompletedBy)?.displayName
|
||||||
})`
|
}`
|
||||||
: 'Never',
|
: 'Never',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
size: 12,
|
size: 6,
|
||||||
icon: <Note />,
|
icon: <Person />,
|
||||||
text: 'Recent Note',
|
text: 'Created By',
|
||||||
subtext: chore.notes || '--',
|
subtext: performers.find(p => p.id === chore.createdBy)?.displayName,
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// size: 12,
|
||||||
|
// icon: <Note />,
|
||||||
|
// text: 'Recent Note',
|
||||||
|
// subtext: chore.notes || '--',
|
||||||
|
// },
|
||||||
]
|
]
|
||||||
setInfoCards(cards)
|
setInfoCards(cards)
|
||||||
}
|
}
|
||||||
|
@ -195,7 +197,16 @@ const ChoreView = () => {
|
||||||
|
|
||||||
setTimeoutId(id)
|
setTimeoutId(id)
|
||||||
}
|
}
|
||||||
|
const handleSkippingTask = () => {
|
||||||
|
SkipChore(choreId).then(response => {
|
||||||
|
if (response.ok) {
|
||||||
|
response.json().then(data => {
|
||||||
|
const newChore = data.res
|
||||||
|
setChore(newChore)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<Container
|
<Container
|
||||||
maxWidth='sm'
|
maxWidth='sm'
|
||||||
|
@ -232,69 +243,80 @@ const ChoreView = () => {
|
||||||
</Chip>
|
</Chip>
|
||||||
</Box>
|
</Box>
|
||||||
<Box>
|
<Box>
|
||||||
<Grid container spacing={1}>
|
<Typography level='title-md' sx={{ mb: 1 }}>
|
||||||
{infoCards.map((info, index) => (
|
Details
|
||||||
<Grid key={index} item xs={info.size} sm={info.size}>
|
</Typography>
|
||||||
<Sheet
|
|
||||||
sx={{
|
<Sheet
|
||||||
mb: 1,
|
sx={{
|
||||||
borderRadius: 'lg',
|
mb: 1,
|
||||||
p: 1,
|
borderRadius: 'lg',
|
||||||
boxShadow: 'sm',
|
p: 2,
|
||||||
}}
|
}}
|
||||||
>
|
variant='outlined'
|
||||||
<ListItem>
|
>
|
||||||
<ListItemDecorator>
|
<Grid container spacing={1}>
|
||||||
<IconCard>{info.icon}</IconCard>
|
{infoCards.map((detail, index) => (
|
||||||
</ListItemDecorator>
|
<Grid item xs={4} key={index}>
|
||||||
|
{/* divider between the list items: */}
|
||||||
|
|
||||||
|
<ListItem key={index}>
|
||||||
<ListItemContent>
|
<ListItemContent>
|
||||||
<Typography level='body1' sx={{ fontWeight: 'md' }}>
|
<Typography level='body-xs' sx={{ fontWeight: 'md' }}>
|
||||||
{info.text}
|
{detail.text}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography level='body1' color='text.tertiary'>
|
<Typography level='body-sm' color='text.tertiary'>
|
||||||
{info.subtext ? info.subtext : '--'}
|
{detail.subtext ? detail.subtext : '--'}
|
||||||
</Typography>
|
</Typography>
|
||||||
</ListItemContent>
|
</ListItemContent>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</Sheet>
|
</Grid>
|
||||||
</Grid>
|
))}
|
||||||
))}
|
|
||||||
<Grid item xs={6}>
|
|
||||||
<Button
|
|
||||||
startDecorator={<History />}
|
|
||||||
size='lg'
|
|
||||||
color='success'
|
|
||||||
variant='outlined'
|
|
||||||
fullWidth
|
|
||||||
onClick={() => {
|
|
||||||
navigate(`/chores/${choreId}/history`)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
History
|
|
||||||
</Button>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
</Sheet>
|
||||||
<Button
|
{chore.notes && (
|
||||||
startDecorator={<Edit />}
|
<>
|
||||||
size='lg'
|
<Typography level='title-md' sx={{ mb: 1 }}>
|
||||||
color='success'
|
Previous note:
|
||||||
variant='outlined'
|
</Typography>
|
||||||
fullWidth
|
<Sheet variant='outlined' sx={{ p: 2, borderRadius: 'lg' }}>
|
||||||
onClick={() => {
|
<Typography level='body-md' sx={{ mb: 1 }}>
|
||||||
navigate(`/chores/${choreId}/edit`)
|
{chore.notes || '--'}
|
||||||
}}
|
</Typography>
|
||||||
>
|
</Sheet>
|
||||||
Edit
|
</>
|
||||||
</Button>
|
)}
|
||||||
</Grid>
|
|
||||||
</Grid>
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
gap: 1,
|
||||||
|
alignContent: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
startDecorator={<History />}
|
||||||
|
size='lg'
|
||||||
|
color='success'
|
||||||
|
variant='plain'
|
||||||
|
onClick={() => {
|
||||||
|
navigate(`/chores/${choreId}/history`)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
View History
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
{/* <Divider
|
{/* <Divider
|
||||||
sx={{
|
sx={{
|
||||||
my: 2,
|
my: 2,
|
||||||
}}
|
}}
|
||||||
/> */}
|
/> */}
|
||||||
|
<Typography level='title-md' sx={{ mt: 1 }}>
|
||||||
|
Actions
|
||||||
|
</Typography>
|
||||||
<Card
|
<Card
|
||||||
sx={{
|
sx={{
|
||||||
p: 2,
|
p: 2,
|
||||||
|
@ -319,11 +341,11 @@ const ChoreView = () => {
|
||||||
}}
|
}}
|
||||||
size='md'
|
size='md'
|
||||||
sx={{
|
sx={{
|
||||||
my: 1,
|
mb: 1,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FormControl size='sm' sx={{ width: 400 }}>
|
<FormControl size='sm'>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
defaultChecked={completedDate !== null}
|
defaultChecked={completedDate !== null}
|
||||||
checked={completedDate !== null}
|
checked={completedDate !== null}
|
||||||
|
@ -358,23 +380,9 @@ const ChoreView = () => {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* {completedDate === null && (
|
|
||||||
// placeholder for the completion date with margin:
|
|
||||||
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
height: 56,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)} */}
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
fullWidth
|
fullWidth
|
||||||
size='lg'
|
size='lg'
|
||||||
sx={{
|
|
||||||
height: 50,
|
|
||||||
// mb: 2,
|
|
||||||
}}
|
|
||||||
onClick={handleTaskCompletion}
|
onClick={handleTaskCompletion}
|
||||||
disabled={isPendingCompletion}
|
disabled={isPendingCompletion}
|
||||||
color={isPendingCompletion ? 'danger' : 'success'}
|
color={isPendingCompletion ? 'danger' : 'success'}
|
||||||
|
@ -382,49 +390,57 @@ const ChoreView = () => {
|
||||||
>
|
>
|
||||||
<Box>Mark as done</Box>
|
<Box>Mark as done</Box>
|
||||||
</Button>
|
</Button>
|
||||||
{/* <Button
|
<Button
|
||||||
sx={{
|
fullWidth
|
||||||
borderRadius: '32px',
|
size='lg'
|
||||||
mt: 1,
|
onClick={() => {
|
||||||
height: 50,
|
setConfirmModelConfig({
|
||||||
zIndex: 1,
|
isOpen: true,
|
||||||
}}
|
title: 'Skip Task',
|
||||||
onClick={() => {
|
|
||||||
Navigate('/my/chores')
|
|
||||||
}}
|
|
||||||
color={isPendingCompletion ? 'danger' : 'success'}
|
|
||||||
startDecorator={isPendingCompletion ? <Close /> : <Check />}
|
|
||||||
fullWidth
|
|
||||||
>
|
|
||||||
<Box>Mark as {isPendingCompletion ? 'completed' : 'done'}</Box>
|
|
||||||
</Button> */}
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
<Snackbar
|
message: 'Are you sure you want to skip this task?',
|
||||||
open={isPendingCompletion}
|
|
||||||
endDecorator={
|
confirmText: 'Skip',
|
||||||
<Button
|
cancelText: 'Cancel',
|
||||||
onClick={() => {
|
onClose: confirmed => {
|
||||||
if (timeoutId) {
|
if (confirmed) {
|
||||||
clearTimeout(timeoutId)
|
handleSkippingTask()
|
||||||
setIsPendingCompletion(false)
|
}
|
||||||
setTimeoutId(null)
|
setConfirmModelConfig({})
|
||||||
setSecondsLeftToCancel(null) // Reset or adjust as needed
|
},
|
||||||
}
|
})
|
||||||
}}
|
}}
|
||||||
size='lg'
|
startDecorator={<SwitchAccessShortcut />}
|
||||||
variant='outlined'
|
>
|
||||||
color='danger'
|
<Box>Skip</Box>
|
||||||
startDecorator={<CancelScheduleSend />}
|
</Button>
|
||||||
>
|
<Snackbar
|
||||||
Cancel
|
open={isPendingCompletion}
|
||||||
</Button>
|
endDecorator={
|
||||||
}
|
<Button
|
||||||
>
|
onClick={() => {
|
||||||
<Typography level='body-md' textAlign={'center'}>
|
if (timeoutId) {
|
||||||
Task will be marked as completed in {secondsLeftToCancel} seconds
|
clearTimeout(timeoutId)
|
||||||
</Typography>
|
setIsPendingCompletion(false)
|
||||||
</Snackbar>
|
setTimeoutId(null)
|
||||||
|
setSecondsLeftToCancel(null) // Reset or adjust as needed
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
size='lg'
|
||||||
|
variant='outlined'
|
||||||
|
color='danger'
|
||||||
|
startDecorator={<CancelScheduleSend />}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Typography level='body-md' textAlign={'center'}>
|
||||||
|
Task will be marked as completed in {secondsLeftToCancel} seconds
|
||||||
|
</Typography>
|
||||||
|
</Snackbar>
|
||||||
|
<ConfirmationModal config={confirmModelConfig} />
|
||||||
|
</Card>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ import moment from 'moment'
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
import { API_URL } from '../../Config'
|
import { API_URL } from '../../Config'
|
||||||
import { MarkChoreComplete } from '../../utils/Fetcher'
|
import { MarkChoreComplete, SkipChore } from '../../utils/Fetcher'
|
||||||
import { Fetch } from '../../utils/TokenManager'
|
import { Fetch } from '../../utils/TokenManager'
|
||||||
import ConfirmationModal from '../Modals/Inputs/ConfirmationModal'
|
import ConfirmationModal from '../Modals/Inputs/ConfirmationModal'
|
||||||
import DateModal from '../Modals/Inputs/DateModal'
|
import DateModal from '../Modals/Inputs/DateModal'
|
||||||
|
@ -521,13 +521,7 @@ const ChoreCard = ({
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
Fetch(`${API_URL}/chores/${chore.id}/skip`, {
|
SkipChore(chore.id).then(response => {
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({}),
|
|
||||||
}).then(response => {
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
response.json().then(data => {
|
response.json().then(data => {
|
||||||
const newChore = data.res
|
const newChore = data.res
|
||||||
|
|
Loading…
Add table
Reference in a new issue