Add Debounce, Add Description, fix TaskModal issue with every_other
This commit is contained in:
commit
dfa5763605
9 changed files with 178 additions and 33 deletions
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "donetick",
|
"name": "donetick",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.1.90",
|
"version": "0.1.91",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"*.{js,jsx,ts,tsx}": [
|
"*.{js,jsx,ts,tsx}": [
|
||||||
|
|
19
src/utils/Debounce.jsx
Normal file
19
src/utils/Debounce.jsx
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
|
function useDebounce(value, delay) {
|
||||||
|
const [debouncedValue, setDebouncedValue] = useState(value)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = setTimeout(() => {
|
||||||
|
setDebouncedValue(value)
|
||||||
|
}, delay)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearTimeout(handler)
|
||||||
|
}
|
||||||
|
}, [value, delay])
|
||||||
|
|
||||||
|
return debouncedValue
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useDebounce
|
|
@ -22,6 +22,7 @@ import {
|
||||||
Snackbar,
|
Snackbar,
|
||||||
Stack,
|
Stack,
|
||||||
Switch,
|
Switch,
|
||||||
|
Textarea,
|
||||||
Typography,
|
Typography,
|
||||||
} from '@mui/joy'
|
} from '@mui/joy'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
|
@ -61,6 +62,7 @@ const ChoreEdit = () => {
|
||||||
const [userHistory, setUserHistory] = useState({})
|
const [userHistory, setUserHistory] = useState({})
|
||||||
const { choreId } = useParams()
|
const { choreId } = useParams()
|
||||||
const [name, setName] = useState('')
|
const [name, setName] = useState('')
|
||||||
|
const [description, setDescription] = useState('')
|
||||||
const [confirmModelConfig, setConfirmModelConfig] = useState({})
|
const [confirmModelConfig, setConfirmModelConfig] = useState({})
|
||||||
const [assignees, setAssignees] = useState([])
|
const [assignees, setAssignees] = useState([])
|
||||||
const [performers, setPerformers] = useState([])
|
const [performers, setPerformers] = useState([])
|
||||||
|
@ -186,6 +188,7 @@ const ChoreEdit = () => {
|
||||||
const chore = {
|
const chore = {
|
||||||
id: Number(choreId),
|
id: Number(choreId),
|
||||||
name: name,
|
name: name,
|
||||||
|
description: description,
|
||||||
assignees: assignees,
|
assignees: assignees,
|
||||||
dueDate: dueDate ? new Date(dueDate).toISOString() : null,
|
dueDate: dueDate ? new Date(dueDate).toISOString() : null,
|
||||||
frequencyType: frequencyType,
|
frequencyType: frequencyType,
|
||||||
|
@ -241,6 +244,7 @@ const ChoreEdit = () => {
|
||||||
.then(data => {
|
.then(data => {
|
||||||
setChore(data.res)
|
setChore(data.res)
|
||||||
setName(data.res.name ? data.res.name : '')
|
setName(data.res.name ? data.res.name : '')
|
||||||
|
setDescription(data.res.description ? data.res.description : '')
|
||||||
setAssignees(data.res.assignees ? data.res.assignees : [])
|
setAssignees(data.res.assignees ? data.res.assignees : [])
|
||||||
setAssignedTo(data.res.assignedTo)
|
setAssignedTo(data.res.assignedTo)
|
||||||
setFrequencyType(
|
setFrequencyType(
|
||||||
|
@ -379,11 +383,22 @@ const ChoreEdit = () => {
|
||||||
<Box>
|
<Box>
|
||||||
<FormControl error={errors.name}>
|
<FormControl error={errors.name}>
|
||||||
<Typography level='h4'>Title :</Typography>
|
<Typography level='h4'>Title :</Typography>
|
||||||
<Typography level='h5'>What is this chore about?</Typography>
|
<Typography level='h5'> What is the name of this chore?</Typography>
|
||||||
<Input value={name} onChange={e => setName(e.target.value)} />
|
<Input value={name} onChange={e => setName(e.target.value)} />
|
||||||
<FormHelperText error>{errors.name}</FormHelperText>
|
<FormHelperText error>{errors.name}</FormHelperText>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</Box>
|
</Box>
|
||||||
|
<Box mt={2}>
|
||||||
|
<FormControl error={errors.description}>
|
||||||
|
<Typography level='h4'>Details:</Typography>
|
||||||
|
<Typography level='h5'>What is this chore about?</Typography>
|
||||||
|
<Textarea
|
||||||
|
value={description}
|
||||||
|
onChange={e => setDescription(e.target.value)}
|
||||||
|
/>
|
||||||
|
<FormHelperText error>{errors.name}</FormHelperText>
|
||||||
|
</FormControl>
|
||||||
|
</Box>
|
||||||
<Box mt={2}>
|
<Box mt={2}>
|
||||||
<Typography level='h4'>Assignees :</Typography>
|
<Typography level='h4'>Assignees :</Typography>
|
||||||
<Typography level='h5'>Who can do this chore?</Typography>
|
<Typography level='h5'>Who can do this chore?</Typography>
|
||||||
|
|
|
@ -3,9 +3,11 @@ import {
|
||||||
CancelScheduleSend,
|
CancelScheduleSend,
|
||||||
Check,
|
Check,
|
||||||
Checklist,
|
Checklist,
|
||||||
|
CloseFullscreen,
|
||||||
Edit,
|
Edit,
|
||||||
History,
|
History,
|
||||||
LowPriority,
|
LowPriority,
|
||||||
|
OpenInFull,
|
||||||
PeopleAlt,
|
PeopleAlt,
|
||||||
Person,
|
Person,
|
||||||
SwitchAccessShortcut,
|
SwitchAccessShortcut,
|
||||||
|
@ -21,6 +23,7 @@ import {
|
||||||
Dropdown,
|
Dropdown,
|
||||||
FormControl,
|
FormControl,
|
||||||
Grid,
|
Grid,
|
||||||
|
IconButton,
|
||||||
Input,
|
Input,
|
||||||
ListItem,
|
ListItem,
|
||||||
ListItemContent,
|
ListItemContent,
|
||||||
|
@ -74,6 +77,7 @@ const ChoreView = () => {
|
||||||
const [completedDate, setCompletedDate] = useState(null)
|
const [completedDate, setCompletedDate] = useState(null)
|
||||||
const [confirmModelConfig, setConfirmModelConfig] = useState({})
|
const [confirmModelConfig, setConfirmModelConfig] = useState({})
|
||||||
const [chorePriority, setChorePriority] = useState(null)
|
const [chorePriority, setChorePriority] = useState(null)
|
||||||
|
const [isDescriptionOpen, setIsDescriptionOpen] = useState(false)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Promise.all([
|
Promise.all([
|
||||||
GetChoreDetailById(choreId).then(resp => {
|
GetChoreDetailById(choreId).then(resp => {
|
||||||
|
@ -420,6 +424,47 @@ const ChoreView = () => {
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
{chore.description && (
|
||||||
|
<>
|
||||||
|
<Typography level='title-md' sx={{ mb: 1 }}>
|
||||||
|
Description :
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Sheet
|
||||||
|
variant='outlined'
|
||||||
|
sx={{
|
||||||
|
p: 2,
|
||||||
|
borderRadius: 'lg',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconButton
|
||||||
|
variant='plain'
|
||||||
|
onClick={() => {
|
||||||
|
setIsDescriptionOpen(!isDescriptionOpen)
|
||||||
|
}}
|
||||||
|
size='sm'
|
||||||
|
sx={{
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: 5,
|
||||||
|
right: 5,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isDescriptionOpen ? <CloseFullscreen /> : <OpenInFull />}
|
||||||
|
</IconButton>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
maxHeight: isDescriptionOpen ? 'none' : '100px',
|
||||||
|
overflowY: 'auto',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography level='body-md' sx={{ mb: 1 }}>
|
||||||
|
{chore.description || '--'}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
</Sheet>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
{chore.notes && (
|
{chore.notes && (
|
||||||
<>
|
<>
|
||||||
<Typography level='title-md' sx={{ mb: 1 }}>
|
<Typography level='title-md' sx={{ mb: 1 }}>
|
||||||
|
|
|
@ -300,6 +300,12 @@ const ChoreCard = ({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const getRecurrentChipText = chore => {
|
const getRecurrentChipText = chore => {
|
||||||
|
// if chore.frequencyMetadata is type string then parse it otherwise assigned to the metadata:
|
||||||
|
const metadata =
|
||||||
|
typeof chore.frequencyMetadata === 'string'
|
||||||
|
? JSON.parse(chore.frequencyMetadata)
|
||||||
|
: chore.frequencyMetadata
|
||||||
|
|
||||||
const dayOfMonthSuffix = n => {
|
const dayOfMonthSuffix = n => {
|
||||||
if (n >= 11 && n <= 13) {
|
if (n >= 11 && n <= 13) {
|
||||||
return 'th'
|
return 'th'
|
||||||
|
@ -330,7 +336,7 @@ const ChoreCard = ({
|
||||||
} else if (chore.frequencyType === 'yearly') {
|
} else if (chore.frequencyType === 'yearly') {
|
||||||
return 'Yearly'
|
return 'Yearly'
|
||||||
} else if (chore.frequencyType === 'days_of_the_week') {
|
} else if (chore.frequencyType === 'days_of_the_week') {
|
||||||
let days = JSON.parse(chore.frequencyMetadata).days
|
let days = metadata.days
|
||||||
if (days.length > 4) {
|
if (days.length > 4) {
|
||||||
const allDays = [
|
const allDays = [
|
||||||
'Sunday',
|
'Sunday',
|
||||||
|
@ -354,7 +360,7 @@ const ChoreCard = ({
|
||||||
return days.join(', ')
|
return days.join(', ')
|
||||||
}
|
}
|
||||||
} else if (chore.frequencyType === 'day_of_the_month') {
|
} else if (chore.frequencyType === 'day_of_the_month') {
|
||||||
let months = JSON.parse(chore.frequencyMetadata).months
|
let months = metadata.months
|
||||||
if (months.length > 6) {
|
if (months.length > 6) {
|
||||||
const allMonths = [
|
const allMonths = [
|
||||||
'January',
|
'January',
|
||||||
|
@ -385,16 +391,14 @@ const ChoreCard = ({
|
||||||
except ${notSelectedShortMonths.join(', ')}`
|
except ${notSelectedShortMonths.join(', ')}`
|
||||||
return result
|
return result
|
||||||
} else {
|
} else {
|
||||||
let freqData = JSON.parse(chore.frequencyMetadata)
|
let freqData = metadata
|
||||||
const months = freqData.months.map(m => moment().month(m).format('MMM'))
|
const months = freqData.months.map(m => moment().month(m).format('MMM'))
|
||||||
return `${chore.frequency}${dayOfMonthSuffix(
|
return `${chore.frequency}${dayOfMonthSuffix(
|
||||||
chore.frequency,
|
chore.frequency,
|
||||||
)} of ${months.join(', ')}`
|
)} of ${months.join(', ')}`
|
||||||
}
|
}
|
||||||
} else if (chore.frequencyType === 'interval') {
|
} else if (chore.frequencyType === 'interval') {
|
||||||
return `Every ${chore.frequency} ${
|
return `Every ${chore.frequency} ${metadata.unit}`
|
||||||
JSON.parse(chore.frequencyMetadata).unit
|
|
||||||
}`
|
|
||||||
} else {
|
} else {
|
||||||
return chore.frequencyType
|
return chore.frequencyType
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { getTextColorFromBackgroundColor } from '../../utils/Colors.jsx'
|
||||||
|
|
||||||
const IconButtonWithMenu = ({
|
const IconButtonWithMenu = ({
|
||||||
label,
|
label,
|
||||||
key,
|
k,
|
||||||
icon,
|
icon,
|
||||||
options,
|
options,
|
||||||
onItemSelect,
|
onItemSelect,
|
||||||
|
@ -72,14 +72,14 @@ const IconButtonWithMenu = ({
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Menu
|
<Menu
|
||||||
key={key}
|
key={k}
|
||||||
ref={menuRef}
|
ref={menuRef}
|
||||||
anchorEl={anchorEl}
|
anchorEl={anchorEl}
|
||||||
open={Boolean(anchorEl)}
|
open={Boolean(anchorEl)}
|
||||||
onClose={handleMenuClose}
|
onClose={handleMenuClose}
|
||||||
>
|
>
|
||||||
{title && (
|
{title && (
|
||||||
<MenuItem key={`${key}-title`} disabled>
|
<MenuItem key={`${k}-title`} disabled>
|
||||||
<Typography level='body-sm' sx={{ fontWeight: 'bold' }}>
|
<Typography level='body-sm' sx={{ fontWeight: 'bold' }}>
|
||||||
{title}
|
{title}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
@ -87,7 +87,7 @@ const IconButtonWithMenu = ({
|
||||||
)}
|
)}
|
||||||
{options?.map(item => (
|
{options?.map(item => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={`${key}-${item?.id}`}
|
key={`${k}-${item?.id}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onItemSelect(item)
|
onItemSelect(item)
|
||||||
setSelectedItem?.selectedItem(item.name)
|
setSelectedItem?.selectedItem(item.name)
|
||||||
|
|
|
@ -420,11 +420,7 @@ const MyChores = () => {
|
||||||
setActiveTextField('search')
|
setActiveTextField('search')
|
||||||
setSearchInputFocus(searchInputFocus + 1)
|
setSearchInputFocus(searchInputFocus + 1)
|
||||||
|
|
||||||
searchInputRef.current.focus()
|
searchInputRef?.current?.focus()
|
||||||
searchInputRef.current.selectionStart =
|
|
||||||
searchInputRef.current.value?.length
|
|
||||||
searchInputRef.current.selectionEnd =
|
|
||||||
searchInputRef.current.value?.length
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Search />
|
<Search />
|
||||||
|
@ -434,6 +430,7 @@ const MyChores = () => {
|
||||||
|
|
||||||
<IconButtonWithMenu
|
<IconButtonWithMenu
|
||||||
title='Group by'
|
title='Group by'
|
||||||
|
k={'icon-menu-group-by'}
|
||||||
icon={<Sort />}
|
icon={<Sort />}
|
||||||
options={[
|
options={[
|
||||||
{ name: 'Due Date', value: 'due_date' },
|
{ name: 'Due Date', value: 'due_date' },
|
||||||
|
@ -456,7 +453,7 @@ const MyChores = () => {
|
||||||
<div className='grid flex-1 grid-cols-3 gap-4'>
|
<div className='grid flex-1 grid-cols-3 gap-4'>
|
||||||
<IconButtonWithMenu
|
<IconButtonWithMenu
|
||||||
label={' Priority'}
|
label={' Priority'}
|
||||||
key={'icon-menu-labels-filter'}
|
k={'icon-menu-priority-filter'}
|
||||||
icon={<PriorityHigh />}
|
icon={<PriorityHigh />}
|
||||||
options={Priorities}
|
options={Priorities}
|
||||||
selectedItem={selectedFilter}
|
selectedItem={selectedFilter}
|
||||||
|
@ -468,7 +465,7 @@ const MyChores = () => {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<IconButtonWithMenu
|
<IconButtonWithMenu
|
||||||
key={'icon-menu-labels-filter'}
|
k={'icon-menu-labels-filter'}
|
||||||
label={' Labels'}
|
label={' Labels'}
|
||||||
icon={<Style />}
|
icon={<Style />}
|
||||||
options={userLabels}
|
options={userLabels}
|
||||||
|
|
|
@ -19,7 +19,9 @@ import { useContext, useEffect, useRef, useState } from 'react'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
import { CSSTransition } from 'react-transition-group'
|
import { CSSTransition } from 'react-transition-group'
|
||||||
import { UserContext } from '../../contexts/UserContext'
|
import { UserContext } from '../../contexts/UserContext'
|
||||||
|
import useDebounce from '../../utils/Debounce'
|
||||||
import { CreateChore } from '../../utils/Fetcher'
|
import { CreateChore } from '../../utils/Fetcher'
|
||||||
|
import { useLabels } from '../Labels/LabelQueries'
|
||||||
import LearnMoreButton from './LearnMore'
|
import LearnMoreButton from './LearnMore'
|
||||||
const VALID_DAYS = {
|
const VALID_DAYS = {
|
||||||
monday: 'Monday',
|
monday: 'Monday',
|
||||||
|
@ -69,9 +71,11 @@ const ALL_MONTHS = Object.values(VALID_MONTHS).filter(
|
||||||
)
|
)
|
||||||
|
|
||||||
const TaskInput = ({ autoFocus, onChoreUpdate }) => {
|
const TaskInput = ({ autoFocus, onChoreUpdate }) => {
|
||||||
|
const { data: userLabels, isLoading: userLabelsLoading } = useLabels()
|
||||||
const { userProfile } = useContext(UserContext)
|
const { userProfile } = useContext(UserContext)
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const [taskText, setTaskText] = useState('')
|
const [taskText, setTaskText] = useState('')
|
||||||
|
const debounceParsing = useDebounce(taskText, 300)
|
||||||
const [taskTitle, setTaskTitle] = useState('')
|
const [taskTitle, setTaskTitle] = useState('')
|
||||||
const [openModal, setOpenModal] = useState(false)
|
const [openModal, setOpenModal] = useState(false)
|
||||||
const textareaRef = useRef(null)
|
const textareaRef = useRef(null)
|
||||||
|
@ -98,6 +102,12 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
|
||||||
}
|
}
|
||||||
}, [autoFocus])
|
}, [autoFocus])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (debounceParsing) {
|
||||||
|
processText(debounceParsing)
|
||||||
|
}
|
||||||
|
}, [debounceParsing])
|
||||||
|
|
||||||
const handleEnterPressed = e => {
|
const handleEnterPressed = e => {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Enter') {
|
||||||
createChore()
|
createChore()
|
||||||
|
@ -139,7 +149,28 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
|
||||||
}
|
}
|
||||||
return { result: 0, cleanedSentence: inputSentence }
|
return { result: 0, cleanedSentence: inputSentence }
|
||||||
}
|
}
|
||||||
|
const parseLabels = inputSentence => {
|
||||||
|
let sentence = inputSentence.toLowerCase()
|
||||||
|
const currentLabels = []
|
||||||
|
// label will always be prefixed #:
|
||||||
|
for (const label of userLabels) {
|
||||||
|
if (sentence.includes(`#${label.name.toLowerCase()}`)) {
|
||||||
|
currentLabels.push(label)
|
||||||
|
sentence = sentence.replace(`#${label.name.toLowerCase()}`, '')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currentLabels.length > 0) {
|
||||||
|
return {
|
||||||
|
result: currentLabels,
|
||||||
|
cleanedSentence: sentence,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { result: null, cleanedSentence: sentence }
|
||||||
|
}
|
||||||
|
const parseAssignee = inputSentence => {
|
||||||
|
let sentence = inputSentence.toLowerCase()
|
||||||
|
const assigneeMap = {}
|
||||||
|
}
|
||||||
const parseRepeatV2 = inputSentence => {
|
const parseRepeatV2 = inputSentence => {
|
||||||
const sentence = inputSentence.toLowerCase()
|
const sentence = inputSentence.toLowerCase()
|
||||||
const result = {
|
const result = {
|
||||||
|
@ -164,6 +195,11 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
|
||||||
regex: /(every day|daily)$/i,
|
regex: /(every day|daily)$/i,
|
||||||
name: 'Every day',
|
name: 'Every day',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
frequencyType: 'daily:time',
|
||||||
|
regex: /every (morning|noon|afternoon|evening|night)$/i,
|
||||||
|
name: 'Every {time} daily',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
frequencyType: 'weekly',
|
frequencyType: 'weekly',
|
||||||
regex: /(every week|weekly)$/i,
|
regex: /(every week|weekly)$/i,
|
||||||
|
@ -284,8 +320,6 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
|
||||||
.replace('{months}', result.frequencyMetadata.months.join(', ')),
|
.replace('{months}', result.frequencyMetadata.months.join(', ')),
|
||||||
cleanedSentence: inputSentence.replace(match[0], '').trim(),
|
cleanedSentence: inputSentence.replace(match[0], '').trim(),
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'interval:every_other':
|
|
||||||
case 'interval:2week':
|
case 'interval:2week':
|
||||||
result.frequency = 2
|
result.frequency = 2
|
||||||
result.frequencyMetadata.unit = 'weeks'
|
result.frequencyMetadata.unit = 'weeks'
|
||||||
|
@ -295,6 +329,17 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
|
||||||
name: pattern.name,
|
name: pattern.name,
|
||||||
cleanedSentence: inputSentence.replace(match[0], '').trim(),
|
cleanedSentence: inputSentence.replace(match[0], '').trim(),
|
||||||
}
|
}
|
||||||
|
case 'daily:time':
|
||||||
|
result.frequency = 1
|
||||||
|
result.frequencyMetadata.unit = 'days'
|
||||||
|
result.frequencyType = 'daily'
|
||||||
|
return {
|
||||||
|
result,
|
||||||
|
name: pattern.name.replace('{time}', match[1]),
|
||||||
|
// replace every x with ''
|
||||||
|
|
||||||
|
cleanedSentence: inputSentence.replace(match[0], '').trim(),
|
||||||
|
}
|
||||||
|
|
||||||
case 'day_of_the_month:every':
|
case 'day_of_the_month:every':
|
||||||
result.frequency = parseInt(match[1], 10)
|
result.frequency = parseInt(match[1], 10)
|
||||||
|
@ -307,6 +352,15 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
|
||||||
.replace('{months}', result.frequencyMetadata.months.join(', ')),
|
.replace('{months}', result.frequencyMetadata.months.join(', ')),
|
||||||
cleanedSentence: inputSentence.replace(match[0], '').trim(),
|
cleanedSentence: inputSentence.replace(match[0], '').trim(),
|
||||||
}
|
}
|
||||||
|
case 'interval:every_other':
|
||||||
|
result.frequency = 2
|
||||||
|
result.frequencyMetadata.unit = match[1]
|
||||||
|
result.frequencyType = 'interval'
|
||||||
|
return {
|
||||||
|
result,
|
||||||
|
name: pattern.name.replace('{unit}', result.frequencyMetadata.unit),
|
||||||
|
cleanedSentence: inputSentence.replace(match[0], '').trim(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { result: null, name: null, cleanedSentence: inputSentence }
|
return { result: null, name: null, cleanedSentence: inputSentence }
|
||||||
|
@ -321,8 +375,10 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
|
||||||
setPriority(0)
|
setPriority(0)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
setTaskText(e.target.value)
|
||||||
let cleanedSentence = e.target.value
|
}
|
||||||
|
const processText = sentence => {
|
||||||
|
let cleanedSentence = sentence
|
||||||
const priority = parsePriority(cleanedSentence)
|
const priority = parsePriority(cleanedSentence)
|
||||||
if (priority.result) setPriority(priority.result)
|
if (priority.result) setPriority(priority.result)
|
||||||
cleanedSentence = priority.cleanedSentence
|
cleanedSentence = priority.cleanedSentence
|
||||||
|
@ -344,11 +400,24 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
|
||||||
cleanedSentence = cleanedSentence.replace(parsedDueDate[0].text, '')
|
cleanedSentence = cleanedSentence.replace(parsedDueDate[0].text, '')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (repeat.result) {
|
||||||
|
// if repeat has result the cleaned sentence will remove the date related info which mean
|
||||||
|
// we need to reparse the date again to get the correct due date:
|
||||||
|
const parsedDueDate = chrono.parse(sentence, new Date(), {
|
||||||
|
forwardDate: true,
|
||||||
|
})
|
||||||
|
if (parsedDueDate[0]?.index > -1) {
|
||||||
|
setDueDate(
|
||||||
|
moment(parsedDueDate[0].start.date()).format('YYYY-MM-DDTHH:mm:ss'),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (priority.result || parsedDueDate[0]?.index > -1 || repeat.result) {
|
if (priority.result || parsedDueDate[0]?.index > -1 || repeat.result) {
|
||||||
setOpenModal(true)
|
setOpenModal(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
setTaskText(e.target.value)
|
setTaskText(sentence)
|
||||||
setTaskTitle(cleanedSentence.trim())
|
setTaskTitle(cleanedSentence.trim())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -504,6 +573,7 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Typography level='body-sm'>Priority</Typography>
|
<Typography level='body-sm'>Priority</Typography>
|
||||||
<Select
|
<Select
|
||||||
|
defaultValue={0}
|
||||||
value={priority}
|
value={priority}
|
||||||
onChange={(e, value) => setPriority(value)}
|
onChange={(e, value) => setPriority(value)}
|
||||||
>
|
>
|
||||||
|
@ -535,9 +605,9 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
|
||||||
>
|
>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Typography level='body-sm'>Assignee</Typography>
|
<Typography level='body-sm'>Assignee</Typography>
|
||||||
<Select value={'0'}>
|
<Select value={'0'} disabled>
|
||||||
<Option value='0'>Me</Option>
|
<Option value='0'>Me</Option>
|
||||||
<Option value='1'>Other</Option>
|
{/* <Option value='1'>Other</Option> */}
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
|
|
|
@ -132,12 +132,7 @@ const CalendarView = ({ chores }) => {
|
||||||
mb: 0.4,
|
mb: 0.4,
|
||||||
py: 1,
|
py: 1,
|
||||||
px: 1,
|
px: 1,
|
||||||
|
cursor: 'pointer',
|
||||||
// backgroundColor: getAssigneeColor(
|
|
||||||
// chore.assignedTo,
|
|
||||||
// userProfile,
|
|
||||||
// ),
|
|
||||||
// everything show in one row:
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
|
|
Loading…
Add table
Reference in a new issue