Add Support for Priority

This commit is contained in:
Mo Tarbin 2024-11-03 22:37:21 -05:00
parent 240633177c
commit 6b0d2fe9cd
6 changed files with 233 additions and 100 deletions

View file

@ -108,13 +108,20 @@ const DeleteChore = id => {
}
const SaveChore = chore => {
console.log('chore', chore)
return Fetch(`${API_URL}/chores/`, {
method: 'PUT',
headers: HEADERS(),
body: JSON.stringify(chore),
})
}
const UpdateChorePriority = (id, priority) => {
return Fetch(`${API_URL}/chores/${id}/priority `, {
method: 'PUT',
headers: HEADERS(),
body: JSON.stringify({ priority: priority }),
})
}
const GetChoreHistory = choreId => {
return Fetch(`${API_URL}/chores/${choreId}/history`, {
method: 'GET',
@ -312,8 +319,9 @@ export {
SaveThing,
signUp,
SkipChore,
UpdateChoreAssignee,
UpdateChoreHistory,
UpdateChorePriority,
UpdateThingState,
UpdateUserDetails,
UpdateChoreAssignee,
}

31
src/utils/Priorities.jsx Normal file
View file

@ -0,0 +1,31 @@
import {
HorizontalRule,
KeyboardControlKey,
KeyboardDoubleArrowUp,
PriorityHigh,
} from '@mui/icons-material'
const Priorities = [
{
name: 'P4',
value: 4,
icon: <HorizontalRule />,
},
{
name: 'P3 ',
value: 3,
icon: <KeyboardControlKey />,
},
{
name: 'P2',
value: 2,
icon: <KeyboardDoubleArrowUp />,
},
{
name: 'P1',
value: 1,
icon: <PriorityHigh />,
},
]
export default Priorities

View file

@ -630,10 +630,11 @@ const ChoreEdit = () => {
description: 'before a task is due in few hours',
id: 'predue',
},
{
title: 'Overdue',
description: 'A notification when a task is overdue',
},
// {
// title: 'Overdue',
// description: 'A notification when a task is overdue',
// id: 'overdue',
// },
{
title: 'Nagging',
description: 'Daily reminders until the task is completed',

View file

@ -5,6 +5,7 @@ import {
Checklist,
Edit,
History,
LowPriority,
PeopleAlt,
Person,
SwitchAccessShortcut,
@ -17,11 +18,15 @@ import {
Checkbox,
Chip,
Container,
Dropdown,
FormControl,
Grid,
Input,
ListItem,
ListItemContent,
Menu,
MenuButton,
MenuItem,
Sheet,
Snackbar,
styled,
@ -36,7 +41,9 @@ import {
GetChoreDetailById,
MarkChoreComplete,
SkipChore,
UpdateChorePriority,
} from '../../utils/Fetcher'
import Priorities from '../../utils/Priorities'
import ConfirmationModal from '../Modals/Inputs/ConfirmationModal'
const IconCard = styled('div')({
display: 'flex',
@ -48,6 +55,7 @@ const IconCard = styled('div')({
height: '40px',
marginRight: '16px',
})
const ChoreView = () => {
const [chore, setChore] = useState({})
const navigate = useNavigate()
@ -63,13 +71,17 @@ const ChoreView = () => {
const [secondsLeftToCancel, setSecondsLeftToCancel] = useState(null)
const [completedDate, setCompletedDate] = useState(null)
const [confirmModelConfig, setConfirmModelConfig] = useState({})
const [chorePriority, setChorePriority] = useState(null)
useEffect(() => {
Promise.all([
GetChoreDetailById(choreId).then(resp => {
if (resp.ok) {
return resp.json().then(data => {
setChore(data.res)
setChorePriority(
Priorities.find(p => p.value === data.res.priority),
)
document.title = 'Donetick: ' + data.res.name
})
}
}),
@ -89,7 +101,14 @@ const ChoreView = () => {
generateInfoCards(chore)
}
}, [chore, performers])
const handleUpdatePriority = priority => {
if (priority.value === 0) {
setChorePriority(null)
} else {
setChorePriority(priority)
}
UpdateChorePriority(choreId, priority.value)
}
const generateInfoCards = chore => {
const cards = [
{
@ -217,6 +236,8 @@ const ChoreView = () => {
flexDirection: 'column',
// space between :
justifyContent: 'space-between',
// max height of the container:
maxHeight: 'calc(100vh - 500px)',
}}
>
<Box
@ -238,17 +259,13 @@ const ChoreView = () => {
>
{chore.name}
</Typography>
<Chip startDecorator={<CalendarMonth />} size='lg' sx={{ mb: 4 }}>
<Chip startDecorator={<CalendarMonth />} size='md' sx={{ mb: 1 }}>
{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,
@ -280,6 +297,101 @@ const ChoreView = () => {
))}
</Grid>
</Sheet>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
gap: 1,
alignContent: 'center',
justifyContent: 'center',
mb: 1,
}}
>
<Dropdown>
<MenuButton
color={
chorePriority?.name === 'P1'
? 'danger'
: chorePriority?.name === 'P2'
? 'warning'
: 'neutral'
}
sx={{
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
p: 1,
}}
fullWidth
>
{chorePriority ? chorePriority.icon : <LowPriority />}
{chorePriority ? chorePriority.name : 'No Priority'}
</MenuButton>
<Menu>
{Priorities.map((priority, index) => (
<MenuItem
key={index}
onClick={() => {
handleUpdatePriority(priority)
}}
>
{priority.name}
</MenuItem>
))}
<Divider />
<MenuItem
onClick={() => {
handleUpdatePriority({
name: 'No Priority',
value: 0,
})
setChorePriority(null)
}}
>
No Priority
</MenuItem>
</Menu>
</Dropdown>
<Button
size='sm'
color='neutral'
variant='outlined'
fullWidth
onClick={() => {
navigate(`/chores/${choreId}/history`)
}}
sx={{
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
p: 1,
}}
>
<History />
History
</Button>
<Button
size='sm'
color='neutral'
variant='outlined'
fullWidth
sx={{
// top right of the card:
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
p: 1,
}}
onClick={() => {
navigate(`/chores/${choreId}/edit`)
}}
>
<Edit />
Edit
</Button>
</Box>
{chore.notes && (
<>
<Typography level='title-md' sx={{ mb: 1 }}>
@ -298,9 +410,7 @@ const ChoreView = () => {
my: 2,
}}
/> */}
<Typography level='title-md' sx={{ mt: 1 }}>
Actions
</Typography>
<Card
sx={{
p: 2,
@ -412,6 +522,7 @@ const ChoreView = () => {
}}
/>
)}
<Box
sx={{
display: 'flex',
@ -428,11 +539,9 @@ const ChoreView = () => {
disabled={isPendingCompletion}
color={isPendingCompletion ? 'danger' : 'success'}
startDecorator={<Check />}
sx={
{
sx={{
flex: 4,
}
}
}}
>
<Box>Mark as done</Box>
</Button>
@ -458,53 +567,14 @@ const ChoreView = () => {
})
}}
startDecorator={<SwitchAccessShortcut />}
sx={
{
sx={{
flex: 1,
}
}
}}
>
<Box>Skip</Box>
</Button>
</Box>
<Divider sx={{ my: 0.5 }}>More</Divider>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
gap: 1,
alignContent: 'center',
justifyContent: 'center',
}}
>
<Button
startDecorator={<History />}
size='lg'
color='primary'
variant='outlined'
fullWidth
onClick={() => {
navigate(`/chores/${choreId}/history`)
}}
>
History
</Button>
<Button
startDecorator={<Edit />}
size='lg'
color='primary'
variant='outlined'
fullWidth
onClick={() => {
navigate(`/chores/${choreId}/edit`)
}}
>
Edit
</Button>
</Box>
<Snackbar
open={isPendingCompletion}
endDecorator={

View file

@ -3,6 +3,8 @@ import {
Check,
Delete,
Edit,
HorizontalRule,
KeyboardControlKey,
KeyboardDoubleArrowUp,
LocalOffer,
ManageSearch,
@ -10,6 +12,7 @@ import {
MoreVert,
Nfc,
NoteAdd,
PriorityHigh,
RecordVoiceOver,
Repeat,
Report,
@ -38,6 +41,7 @@ import moment from 'moment'
import React, { useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import { API_URL } from '../../Config'
import { UserContext } from '../../contexts/UserContext'
import {
MarkChoreComplete,
SkipChore,
@ -76,14 +80,7 @@ const ChoreCard = ({
const [isPendingCompletion, setIsPendingCompletion] = React.useState(false)
const [secondsLeftToCancel, setSecondsLeftToCancel] = React.useState(null)
const [timeoutId, setTimeoutId] = React.useState(null)
// useEffect(() => {
// GetAllUsers()
// .then(response => response.json())
// .then(data => {
// setPerformers(data.res)
// })
// }, [])
const { userProfile } = React.useContext(UserContext)
useEffect(() => {
document.addEventListener('mousedown', handleMenuOutsideClick)
return () => {
@ -282,7 +279,18 @@ const ChoreCard = ({
return <LocalOffer />
}
}
const getPriorityIcon = priority => {
switch (Number(priority)) {
case 1:
return <PriorityHigh />
case 2:
return <KeyboardDoubleArrowUp />
case 3:
return <KeyboardControlKey />
default:
return <HorizontalRule />
}
}
const getRecurrentChipText = chore => {
const dayOfMonthSuffix = n => {
if (n >= 11 && n <= 13) {
@ -438,6 +446,7 @@ const ChoreCard = ({
</Avatar>
<Box display='flex' flexDirection='column'>
<Typography level='title-md'>{getName(chore.name)}</Typography>
{chore.assignedTo !== userProfile.id && (
<Typography level='body-md' color='text.disabled'>
Assigned to{' '}
<Chip variant='outlined'>
@ -447,7 +456,27 @@ const ChoreCard = ({
}
</Chip>
</Typography>
)}
<Box>
{chore.priority > 0 && (
<Chip
sx={{
position: 'relative',
mr: 0.5,
top: 2,
zIndex: 1,
}}
color={
chore.priority === 1
? 'danger'
: chore.priority === 2
? 'warning'
: 'neutral'
}
>
P{chore.priority}
</Chip>
)}
{chore.labels?.split(',').map((label, index) => (
<Chip
variant='solid'

View file

@ -66,12 +66,6 @@ const MyChores = () => {
return aDueDate - bDueDate // Sort ascending by due date
}
const handleSelectedFilter = selected => {
setFilteredChores(FILTERS[selected](chores))
setSelectedFilter(selected)
}
useEffect(() => {
if (userProfile === null) {
GetUserProfile()