Enhance AddTaskModal to support custom due times and update due date handling
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user