aboutsummaryrefslogtreecommitdiffstats
path: root/src/views/ChoreEdit
diff options
context:
space:
mode:
authorLibravatar Mo Tarbin <mhed.t91@gmail.com>2024-07-16 19:37:59 -0400
committerLibravatar Mo Tarbin <mhed.t91@gmail.com>2024-07-16 19:37:59 -0400
commit8e42e59a80fbb4009e6d871d998793ffa597802a (patch)
tree36278fab2f16b148b86b2760dfb19d8e138e1d4d /src/views/ChoreEdit
parentc684bdb9ece99935c4c5f3a3eb81787cc2a0ef19 (diff)
parent7f4e5928492a71135f6817874461c80a0ecc155c (diff)
downloaddonetick-frontend-8e42e59a80fbb4009e6d871d998793ffa597802a.tar.gz
donetick-frontend-8e42e59a80fbb4009e6d871d998793ffa597802a.tar.bz2
donetick-frontend-8e42e59a80fbb4009e6d871d998793ffa597802a.zip
Merge branch 'dev'
Diffstat (limited to '')
-rw-r--r--src/views/ChoreEdit/ChoreView.jsx387
-rw-r--r--src/views/ChoreEdit/RepeatSection.jsx2
2 files changed, 263 insertions, 126 deletions
diff --git a/src/views/ChoreEdit/ChoreView.jsx b/src/views/ChoreEdit/ChoreView.jsx
index df45aa7..172ad9b 100644
--- a/src/views/ChoreEdit/ChoreView.jsx
+++ b/src/views/ChoreEdit/ChoreView.jsx
@@ -3,48 +3,53 @@ import {
CancelScheduleSend,
Check,
Checklist,
- Note,
+ History,
PeopleAlt,
Person,
+ SwitchAccessShortcut,
+ Timelapse,
} from '@mui/icons-material'
import {
Box,
Button,
Card,
Checkbox,
+ Chip,
Container,
FormControl,
Grid,
Input,
ListItem,
ListItemContent,
- ListItemDecorator,
Sheet,
Snackbar,
styled,
Typography,
} from '@mui/joy'
+import { Divider } from '@mui/material'
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,
MarkChoreComplete,
+ SkipChore,
} from '../../utils/Fetcher'
+import ConfirmationModal from '../Modals/Inputs/ConfirmationModal'
const IconCard = styled('div')({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#f0f0f0', // Adjust the background color as needed
borderRadius: '50%',
- minWidth: '50px',
- height: '50px',
+ minWidth: '40px',
+ height: '40px',
marginRight: '16px',
})
const ChoreView = () => {
const [chore, setChore] = useState({})
-
+ const navigate = useNavigate()
const [performers, setPerformers] = useState([])
const [infoCards, setInfoCards] = useState([])
const { choreId } = useParams()
@@ -56,6 +61,8 @@ const ChoreView = () => {
const [timeoutId, setTimeoutId] = useState(null)
const [secondsLeftToCancel, setSecondsLeftToCancel] = useState(null)
const [completedDate, setCompletedDate] = useState(null)
+ const [confirmModelConfig, setConfirmModelConfig] = useState({})
+
useEffect(() => {
Promise.all([
GetChoreDetailById(choreId).then(resp => {
@@ -85,20 +92,20 @@ const ChoreView = () => {
const generateInfoCards = chore => {
const cards = [
{
- icon: <CalendarMonth />,
- text: 'Due Date',
- subtext: moment(chore.nextDueDate).format('MM/DD/YYYY hh:mm A'),
- },
- {
+ size: 6,
icon: <PeopleAlt />,
text: 'Assigned To',
subtext: performers.find(p => p.id === chore.assignedTo)?.displayName,
},
{
- icon: <Person />,
- text: 'Created By',
- subtext: performers.find(p => p.id === chore.createdBy)?.displayName,
+ size: 6,
+ icon: <CalendarMonth />,
+ text: 'Due Date',
+ subtext: chore.nextDueDate
+ ? moment(chore.nextDueDate).fromNow()
+ : 'N/A',
},
+
// {
// icon: <TextFields />,
// text: 'Frequency',
@@ -107,35 +114,42 @@ const ChoreView = () => {
// chore.frequencyType.slice(1),
// },
{
+ size: 6,
icon: <Checklist />,
text: 'Total Completed',
- subtext: `${chore.totalCompletedCount}`,
+ subtext: `${chore.totalCompletedCount} times`,
},
- // {
- // icon: <Timelapse />,
- // text: 'Last Completed',
- // subtext:
- // chore.lastCompletedDate &&
- // moment(chore.lastCompletedDate).format('MM/DD/YYYY hh:mm A'),
- // },
{
- icon: <Person />,
+ size: 6,
+ icon: <Timelapse />,
text: 'Last Completed',
+ subtext:
+ // chore.lastCompletedDate &&
+ // moment(chore.lastCompletedDate).format('MM/DD/YYYY hh:mm A'),
+ chore.lastCompletedDate && moment(chore.lastCompletedDate).fromNow(),
+ },
+ {
+ size: 6,
+ icon: <Person />,
+ text: 'Last Performer',
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
- })`
- : 'Never',
+ }`
+ : '--',
},
{
- icon: <Note />,
- text: 'Recent Note',
- subtext: chore.notes || '--',
+ size: 6,
+ icon: <Person />,
+ text: 'Created By',
+ subtext: performers.find(p => p.id === chore.createdBy)?.displayName,
},
+ // {
+ // size: 12,
+ // icon: <Note />,
+ // text: 'Recent Note',
+ // subtext: chore.notes || '--',
+ // },
]
setInfoCards(cards)
}
@@ -184,7 +198,16 @@ const ChoreView = () => {
setTimeoutId(id)
}
-
+ const handleSkippingTask = () => {
+ SkipChore(choreId).then(response => {
+ if (response.ok) {
+ response.json().then(data => {
+ const newChore = data.res
+ setChore(newChore)
+ })
+ }
+ })
+ }
return (
<Container
maxWidth='sm'
@@ -195,46 +218,88 @@ const ChoreView = () => {
justifyContent: 'space-between',
}}
>
- <Box>
+ <Box
+ sx={{
+ display: 'flex',
+ flexDirection: 'column',
+ justifyContent: 'center',
+ alignItems: 'center',
+ textAlign: 'center',
+ }}
+ >
<Typography
level='h3'
- textAlign={'center'}
+ // textAlign={'center'}
sx={{
- mt: 2,
- mb: 4,
+ mt: 1,
+ mb: 0.5,
}}
>
{chore.name}
</Typography>
+ <Chip startDecorator={<CalendarMonth />} size='lg' sx={{ mb: 4 }}>
+ {chore.nextDueDate
+ ? `Due at ${moment(chore.nextDueDate).format('MM/DD/YYYY hh:mm A')}`
+ : 'N/A'}
+ </Chip>
+ </Box>
+ <Box>
+ <Typography level='title-md' sx={{ mb: 0.5 }}>
+ Details
+ </Typography>
+
+ <Sheet
+ sx={{
+ mb: 1,
+ borderRadius: 'lg',
+ p: 2,
+ }}
+ variant='outlined'
+ >
+ <Grid container spacing={1}>
+ {infoCards.map((detail, index) => (
+ <Grid item xs={4} key={index}>
+ {/* divider between the list items: */}
- <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>
+ <ListItem key={index}>
<ListItemContent>
- <Typography level='body1' sx={{ fontWeight: 'md' }}>
- {info.text}
- </Typography>
- <Typography level='body1' color='text.tertiary'>
- {info.subtext ? info.subtext : '--'}
+ <Typography level='body-xs' sx={{ fontWeight: 'md' }}>
+ {detail.text}
</Typography>
+ <Chip
+ color='primary'
+ size='md'
+ startDecorator={detail.icon}
+ >
+ {detail.subtext ? detail.subtext : '--'}
+ </Chip>
</ListItemContent>
</ListItem>
- </Sheet>
- </Grid>
- ))}
- </Grid>
+ </Grid>
+ ))}
+ </Grid>
+ </Sheet>
+ {chore.notes && (
+ <>
+ <Typography level='title-md' sx={{ mb: 1 }}>
+ Previous note:
+ </Typography>
+ <Sheet variant='outlined' sx={{ p: 2, borderRadius: 'lg' }}>
+ <Typography level='body-md' sx={{ mb: 1 }}>
+ {chore.notes || '--'}
+ </Typography>
+ </Sheet>
+ </>
+ )}
</Box>
{/* <Divider
sx={{
my: 2,
}}
/> */}
-
+ <Typography level='title-md' sx={{ mt: 1 }}>
+ Actions
+ </Typography>
<Card
sx={{
p: 2,
@@ -243,27 +308,65 @@ const ChoreView = () => {
mt: 2,
}}
>
- <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
+ <Typography level='body-md' sx={{ mb: 1 }}>
+ Complete the task
+ </Typography>
+
+ <FormControl size='sm'>
+ <Checkbox
+ defaultChecked={note !== null}
+ checked={note !== null}
+ value={note !== null}
+ size='lg'
+ onChange={e => {
+ if (e.target.checked) {
+ setNote('')
+ } else {
+ setNote(null)
+ }
+ }}
+ overlay
+ sx={
+ {
+ // my: 1,
+ }
}
- setNote(e.target.value)
- }}
- size='md'
- sx={{
- my: 1,
- }}
- />
+ label={
+ <Typography
+ level='body-sm'
+ sx={{
+ // center vertically
+ display: 'flex',
+ alignItems: 'center',
+ }}
+ >
+ Add Additional Notes
+ </Typography>
+ }
+ />
+ </FormControl>
+ {note !== null && (
+ <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={{
+ mb: 1,
+ }}
+ />
+ )}
- <FormControl size='sm' sx={{ width: 400 }}>
+ <FormControl size='sm'>
<Checkbox
defaultChecked={completedDate !== null}
checked={completedDate !== null}
@@ -279,10 +382,23 @@ const ChoreView = () => {
}
}}
overlay
- sx={{
- my: 1,
- }}
- label={<Typography level='body2'>Set completion date</Typography>}
+ sx={
+ {
+ // my: 1,
+ }
+ }
+ label={
+ <Typography
+ level='body-sm'
+ sx={{
+ // center vertically
+ display: 'flex',
+ alignItems: 'center',
+ }}
+ >
+ Specify completion date
+ </Typography>
+ }
/>
</FormControl>
{completedDate !== null && (
@@ -295,22 +411,10 @@ const ChoreView = () => {
}}
/>
)}
- {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'}
@@ -318,49 +422,82 @@ const ChoreView = () => {
>
<Box>Mark as done</Box>
</Button>
- {/* <Button
- sx={{
- borderRadius: '32px',
- mt: 1,
- height: 50,
- zIndex: 1,
- }}
- onClick={() => {
- Navigate('/my/chores')
- }}
- color={isPendingCompletion ? 'danger' : 'success'}
- startDecorator={isPendingCompletion ? <Close /> : <Check />}
- fullWidth
- >
- <Box>Mark as {isPendingCompletion ? 'completed' : 'done'}</Box>
- </Button> */}
- </Card>
+ <Divider sx={{ my: 0.5 }}>or</Divider>
- <Snackbar
- open={isPendingCompletion}
- endDecorator={
+ <Box
+ sx={{
+ display: 'flex',
+ flexDirection: 'row',
+ gap: 1,
+ alignContent: 'center',
+ justifyContent: 'center',
+ }}
+ >
<Button
+ fullWidth
+ size='lg'
onClick={() => {
- if (timeoutId) {
- clearTimeout(timeoutId)
- setIsPendingCompletion(false)
- setTimeoutId(null)
- setSecondsLeftToCancel(null) // Reset or adjust as needed
- }
+ setConfirmModelConfig({
+ isOpen: true,
+ title: 'Skip Task',
+
+ message: 'Are you sure you want to skip this task?',
+
+ confirmText: 'Skip',
+ cancelText: 'Cancel',
+ onClose: confirmed => {
+ if (confirmed) {
+ handleSkippingTask()
+ }
+ setConfirmModelConfig({})
+ },
+ })
}}
+ startDecorator={<SwitchAccessShortcut />}
+ >
+ <Box>Skip</Box>
+ </Button>
+ <Button
+ startDecorator={<History />}
size='lg'
+ color='primary'
variant='outlined'
- color='danger'
- startDecorator={<CancelScheduleSend />}
+ fullWidth
+ onClick={() => {
+ navigate(`/chores/${choreId}/history`)
+ }}
>
- Cancel
+ History
</Button>
- }
- >
- <Typography level='body-md' textAlign={'center'}>
- Task will be marked as completed in {secondsLeftToCancel} seconds
- </Typography>
- </Snackbar>
+ </Box>
+
+ <Snackbar
+ open={isPendingCompletion}
+ endDecorator={
+ <Button
+ onClick={() => {
+ if (timeoutId) {
+ clearTimeout(timeoutId)
+ setIsPendingCompletion(false)
+ 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>
)
}
diff --git a/src/views/ChoreEdit/RepeatSection.jsx b/src/views/ChoreEdit/RepeatSection.jsx
index 99f196f..bdf6738 100644
--- a/src/views/ChoreEdit/RepeatSection.jsx
+++ b/src/views/ChoreEdit/RepeatSection.jsx
@@ -509,7 +509,7 @@ const RepeatSection = ({
}}
>
Is this something that should be done when a thing state changes?{' '}
- {!isPlusAccount(userProfile) && (
+ {userProfile && !isPlusAccount(userProfile) && (
<Chip variant='soft' color='warning'>
Not available in Basic Plan
</Chip>