diff --git a/src/views/ChoreEdit/ChoreEdit.jsx b/src/views/ChoreEdit/ChoreEdit.jsx index f7303b8..8dcf06b 100644 --- a/src/views/ChoreEdit/ChoreEdit.jsx +++ b/src/views/ChoreEdit/ChoreEdit.jsx @@ -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 && ( - + - + Delete diff --git a/src/views/components/AddTaskModal.jsx b/src/views/components/AddTaskModal.jsx index f70abb6..46f109a 100644 --- a/src/views/components/AddTaskModal.jsx +++ b/src/views/components/AddTaskModal.jsx @@ -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 && @@ -870,11 +947,30 @@ const TaskInput = ({ autoFocus, onChoreUpdate, isModalOpen, onClose }) => { Due Date setDueDate(e.target.value)} - sx={{ width: '100%', fontSize: '16px' }} + type='date' + value={dueDateOnly || ''} + onChange={handleDueDateChange} /> + handleUseCustomTimeChange(e.target.checked)} + label='Set a specific time' + sx={{ mt: 1 }} + /> + + {useCustomTime + ? 'Task will be due at the specified time' + : 'Task will be due at the end of the day (11:59 PM)'} + + {useCustomTime && ( + + )} )}