Add useDebounce hook for debouncing input values

Fix parsing
This commit is contained in:
Mo Tarbin 2025-01-16 00:41:04 -05:00
parent aa7f412f14
commit 56f66e9e8f
4 changed files with 92 additions and 20 deletions

19
src/utils/Debounce.jsx Normal file
View 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

View file

@ -300,6 +300,12 @@ const ChoreCard = ({
}
}
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 => {
if (n >= 11 && n <= 13) {
return 'th'
@ -330,7 +336,7 @@ const ChoreCard = ({
} else if (chore.frequencyType === 'yearly') {
return 'Yearly'
} else if (chore.frequencyType === 'days_of_the_week') {
let days = JSON.parse(chore.frequencyMetadata).days
let days = metadata.days
if (days.length > 4) {
const allDays = [
'Sunday',
@ -354,7 +360,7 @@ const ChoreCard = ({
return days.join(', ')
}
} else if (chore.frequencyType === 'day_of_the_month') {
let months = JSON.parse(chore.frequencyMetadata).months
let months = metadata.months
if (months.length > 6) {
const allMonths = [
'January',
@ -385,16 +391,14 @@ const ChoreCard = ({
except ${notSelectedShortMonths.join(', ')}`
return result
} else {
let freqData = JSON.parse(chore.frequencyMetadata)
let freqData = metadata
const months = freqData.months.map(m => moment().month(m).format('MMM'))
return `${chore.frequency}${dayOfMonthSuffix(
chore.frequency,
)} of ${months.join(', ')}`
}
} else if (chore.frequencyType === 'interval') {
return `Every ${chore.frequency} ${
JSON.parse(chore.frequencyMetadata).unit
}`
return `Every ${chore.frequency} ${metadata.unit}`
} else {
return chore.frequencyType
}

View file

@ -19,7 +19,9 @@ import { useContext, useEffect, useRef, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { CSSTransition } from 'react-transition-group'
import { UserContext } from '../../contexts/UserContext'
import useDebounce from '../../utils/Debounce'
import { CreateChore } from '../../utils/Fetcher'
import { useLabels } from '../Labels/LabelQueries'
import LearnMoreButton from './LearnMore'
const VALID_DAYS = {
monday: 'Monday',
@ -69,9 +71,11 @@ const ALL_MONTHS = Object.values(VALID_MONTHS).filter(
)
const TaskInput = ({ autoFocus, onChoreUpdate }) => {
const { data: userLabels, isLoading: userLabelsLoading } = useLabels()
const { userProfile } = useContext(UserContext)
const navigate = useNavigate()
const [taskText, setTaskText] = useState('')
const debounceParsing = useDebounce(taskText, 300)
const [taskTitle, setTaskTitle] = useState('')
const [openModal, setOpenModal] = useState(false)
const textareaRef = useRef(null)
@ -98,6 +102,12 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
}
}, [autoFocus])
useEffect(() => {
if (debounceParsing) {
processText(debounceParsing)
}
}, [debounceParsing])
const handleEnterPressed = e => {
if (e.key === 'Enter') {
createChore()
@ -139,7 +149,28 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
}
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 sentence = inputSentence.toLowerCase()
const result = {
@ -284,8 +315,6 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
.replace('{months}', result.frequencyMetadata.months.join(', ')),
cleanedSentence: inputSentence.replace(match[0], '').trim(),
}
case 'interval:every_other':
case 'interval:2week':
result.frequency = 2
result.frequencyMetadata.unit = 'weeks'
@ -307,6 +336,15 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
.replace('{months}', result.frequencyMetadata.months.join(', ')),
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 }
@ -321,8 +359,10 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
setPriority(0)
return
}
let cleanedSentence = e.target.value
setTaskText(e.target.value)
}
const processText = sentence => {
let cleanedSentence = sentence
const priority = parsePriority(cleanedSentence)
if (priority.result) setPriority(priority.result)
cleanedSentence = priority.cleanedSentence
@ -344,11 +384,24 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
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) {
setOpenModal(true)
}
setTaskText(e.target.value)
setTaskText(sentence)
setTaskTitle(cleanedSentence.trim())
}
@ -504,6 +557,7 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
<FormControl>
<Typography level='body-sm'>Priority</Typography>
<Select
defaultValue={0}
value={priority}
onChange={(e, value) => setPriority(value)}
>
@ -535,9 +589,9 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => {
>
<FormControl>
<Typography level='body-sm'>Assignee</Typography>
<Select value={'0'}>
<Select value={'0'} disabled>
<Option value='0'>Me</Option>
<Option value='1'>Other</Option>
{/* <Option value='1'>Other</Option> */}
</Select>
</FormControl>
<FormControl>

View file

@ -132,12 +132,7 @@ const CalendarView = ({ chores }) => {
mb: 0.4,
py: 1,
px: 1,
// backgroundColor: getAssigneeColor(
// chore.assignedTo,
// userProfile,
// ),
// everything show in one row:
cursor: 'pointer',
}}
>
<CardContent>