Enhance AddTaskModal to support custom due times and update due date handling

This commit is contained in:
Mo Tarbin
2026-04-05 18:44:41 -04:00
parent 083680b563
commit e0f00fd4f5
2 changed files with 122 additions and 21 deletions

View File

@@ -296,7 +296,7 @@ const ChoreEdit = () => {
if (dueDateOnly) {
const combinedDateTime = moment(`${dueDateOnly}T${defaultTime}`).format(
'YYYY-MM-DDTHH:mm:00',
'YYYY-MM-DDTHH:mm:59',
)
setDueDate(combinedDateTime)
@@ -314,7 +314,7 @@ const ChoreEdit = () => {
if (dueDateOnly) {
const endOfDay = moment(dueDateOnly)
.endOf('day')
.format('YYYY-MM-DDTHH:mm:00')
.format('YYYY-MM-DDTHH:mm:ss')
setDueDate(endOfDay)
}
}
@@ -563,7 +563,7 @@ const ChoreEdit = () => {
const today = moment(new Date()).format('YYYY-MM-DD')
setDueDateOnly(today)
// Default to end of day
setDueDate(moment(today).endOf('day').format('YYYY-MM-DDTHH:mm:00'))
setDueDate(moment(today).endOf('day').format('YYYY-MM-DDTHH:mm:59'))
setUseCustomTime(false)
setDueTime(null)
}
@@ -1112,7 +1112,7 @@ const ChoreEdit = () => {
const today = moment(new Date()).format('YYYY-MM-DD')
setDueDateOnly(today)
setDueDate(
moment(today).endOf('day').format('YYYY-MM-DDTHH:mm:00'),
moment(today).endOf('day').format('YYYY-MM-DDTHH:mm:59'),
)
setUseCustomTime(false)
setDueTime(null)
@@ -1644,7 +1644,10 @@ const ChoreEdit = () => {
>
{choreId > 0 && (
<Dropdown>
<ButtonGroup variant='outlined' color={isActive ? 'danger' : 'neutral'}>
<ButtonGroup
variant='outlined'
color={isActive ? 'danger' : 'neutral'}
>
<Button
onClick={() => {
isActive
@@ -1656,16 +1659,18 @@ const ChoreEdit = () => {
</Button>
<MenuButton
slots={{ root: IconButton }}
slotProps={{ root: { variant: 'outlined', color: isActive ? 'danger' : 'neutral' } }}
slotProps={{
root: {
variant: 'outlined',
color: isActive ? 'danger' : 'neutral',
},
}}
>
<ArrowDropDown />
</MenuButton>
</ButtonGroup>
<Menu placement='top-end'>
<MenuItem
color='danger'
onClick={handleDelete}
>
<MenuItem color='danger' onClick={handleDelete}>
Delete
</MenuItem>
</Menu>

View File

@@ -1,5 +1,14 @@
import { Add, EditNotifications } from '@mui/icons-material'
import { Box, Button, Input, Option, Select, Typography } from '@mui/joy'
import {
Box,
Button,
Checkbox,
FormHelperText,
Input,
Option,
Select,
Typography,
} from '@mui/joy'
import { FormControl } from '@mui/material'
import * as chrono from 'chrono-node'
import moment from 'moment'
@@ -92,6 +101,9 @@ const TaskInput = ({ autoFocus, onChoreUpdate, isModalOpen, onClose }) => {
const [hasNotifications, setHasNotifications] = useState(false)
const [hasDeadline, setHasDeadline] = useState(false)
const [deadlineOffset, setDeadlineOffset] = useState(-1)
const [dueDateOnly, setDueDateOnly] = useState(null)
const [dueTime, setDueTime] = useState(null)
const [useCustomTime, setUseCustomTime] = useState(false)
const [showKeyboardShortcuts, setShowKeyboardShortcuts] = useState(false)
const [projectId, setProjectId] = useState(getInitialProject())
@@ -135,7 +147,11 @@ const TaskInput = ({ autoFocus, onChoreUpdate, isModalOpen, onClose }) => {
!dueDate
) {
// add due date:
setDueDate(moment().add(1, 'day').format('YYYY-MM-DDTHH:00:00'))
const tomorrow = moment().add(1, 'day')
setDueDateOnly(tomorrow.format('YYYY-MM-DD'))
setDueDate(tomorrow.endOf('day').format('YYYY-MM-DDTHH:mm:59'))
setUseCustomTime(false)
setDueTime(null)
setShowKeyboardShortcuts(false)
}
// Enter key to create task
@@ -379,9 +395,24 @@ const TaskInput = ({ autoFocus, onChoreUpdate, isModalOpen, onClose }) => {
setFrequencyHumanReadable(repeat.name)
}
const syncDueDateStates = parsedDate => {
const m = moment(parsedDate)
const dateOnly = m.format('YYYY-MM-DD')
const timeOnly = m.format('HH:mm')
setDueDateOnly(dateOnly)
setDueDate(m.format('YYYY-MM-DDTHH:mm:ss'))
if (timeOnly !== '23:59') {
setUseCustomTime(true)
setDueTime(timeOnly)
} else {
setUseCustomTime(false)
setDueTime(null)
}
}
let dueDateHighlight = null
if (dueDateParsed.result) {
setDueDate(moment(dueDateParsed.result).format('YYYY-MM-DDTHH:mm:ss'))
syncDueDateStates(dueDateParsed.result)
dueDateHighlight = dueDateParsed.highlight[0]
}
@@ -390,9 +421,7 @@ const TaskInput = ({ autoFocus, onChoreUpdate, isModalOpen, onClose }) => {
// we need to reparse the date again to get the correct due date:
const dueDateParsedAgain = parseDueDate(sentence, chrono)
if (dueDateParsedAgain.result) {
setDueDate(
moment(dueDateParsedAgain.result).format('YYYY-MM-DDTHH:mm:ss'),
)
syncDueDateStates(dueDateParsedAgain.result)
}
}
@@ -472,6 +501,47 @@ const TaskInput = ({ autoFocus, onChoreUpdate, isModalOpen, onClose }) => {
processText,
])
const handleDueDateChange = e => {
const dateValue = e.target.value
setDueDateOnly(dateValue)
if (useCustomTime && dueTime) {
setDueDate(
moment(`${dateValue}T${dueTime}`).format('YYYY-MM-DDTHH:mm:00'),
)
} else {
setDueDate(moment(dateValue).endOf('day').format('YYYY-MM-DDTHH:mm:ss'))
}
}
const handleDueTimeChange = e => {
const timeValue = e.target.value
setDueTime(timeValue)
if (dueDateOnly) {
setDueDate(
moment(`${dueDateOnly}T${timeValue}`).format('YYYY-MM-DDTHH:mm:00'),
)
}
}
const handleUseCustomTimeChange = checked => {
setUseCustomTime(checked)
if (checked) {
const defaultTime = dueTime || '18:00'
setDueTime(defaultTime)
if (dueDateOnly) {
setDueDate(
moment(`${dueDateOnly}T${defaultTime}`).format('YYYY-MM-DDTHH:mm:00'),
)
}
} else {
if (dueDateOnly) {
setDueDate(
moment(dueDateOnly).endOf('day').format('YYYY-MM-DDTHH:mm:ss'),
)
}
}
}
const handleEnterPressed = () => {
createChore()
}
@@ -495,6 +565,9 @@ const TaskInput = ({ autoFocus, onChoreUpdate, isModalOpen, onClose }) => {
setProjectId(getInitialProject())
setHasDeadline(false)
setDeadlineOffset(-1)
setDueDateOnly(null)
setDueTime(null)
setUseCustomTime(false)
}
const createChore = () => {
@@ -780,7 +853,11 @@ const TaskInput = ({ autoFocus, onChoreUpdate, isModalOpen, onClose }) => {
variant='plain'
size='sm'
onClick={() => {
setDueDate(moment().add(1, 'day').format('YYYY-MM-DDTHH:00:00'))
const tomorrow = moment().add(1, 'day')
setDueDateOnly(tomorrow.format('YYYY-MM-DD'))
setDueDate(tomorrow.endOf('day').format('YYYY-MM-DDTHH:mm:ss'))
setUseCustomTime(false)
setDueTime(null)
}}
endDecorator={
showKeyboardShortcuts && <KeyboardShortcutHint shortcut='B' />
@@ -870,11 +947,30 @@ const TaskInput = ({ autoFocus, onChoreUpdate, isModalOpen, onClose }) => {
<FormControl>
<Typography level='body-sm'>Due Date</Typography>
<Input
type='datetime-local'
value={dueDate}
onChange={e => setDueDate(e.target.value)}
sx={{ width: '100%', fontSize: '16px' }}
type='date'
value={dueDateOnly || ''}
onChange={handleDueDateChange}
/>
<Checkbox
size='sm'
checked={useCustomTime}
onChange={e => handleUseCustomTimeChange(e.target.checked)}
label='Set a specific time'
sx={{ mt: 1 }}
/>
<FormHelperText>
{useCustomTime
? 'Task will be due at the specified time'
: 'Task will be due at the end of the day (11:59 PM)'}
</FormHelperText>
{useCustomTime && (
<Input
type='time'
value={dueTime || '18:00'}
onChange={handleDueTimeChange}
sx={{ maxWidth: 200, mt: 1 }}
/>
)}
</FormControl>
)}
</Box>