diff --git a/src/views/Chores/IconButtonWithMenu.jsx b/src/views/Chores/IconButtonWithMenu.jsx index bd7db7c..2ad1706 100644 --- a/src/views/Chores/IconButtonWithMenu.jsx +++ b/src/views/Chores/IconButtonWithMenu.jsx @@ -1,9 +1,10 @@ -import { Chip, Menu, MenuItem, Typography } from '@mui/joy' +import { Button, Chip, Menu, MenuItem, Typography } from '@mui/joy' import IconButton from '@mui/joy/IconButton' import React, { useEffect, useRef, useState } from 'react' import { getTextColorFromBackgroundColor } from '../../utils/Colors.jsx' const IconButtonWithMenu = ({ + label, key, icon, options, @@ -39,18 +40,36 @@ const IconButtonWithMenu = ({ return ( <> - - {icon} - + {!label && ( + + {icon} + {label ? label : null} + + )} + {label && ( + + )} { /> )} {activeTextField != 'task' && ( - + + )} {activeTextField != 'search' && ( - + + )} - } - title='Filter by Priority' - options={Priorities} - selectedItem={selectedFilter} - onItemSelect={selected => { - handleLabelFiltering({ priority: selected.value }) - }} - mouseClickHandler={handleMenuOutsideClick} - isActive={selectedFilter.startsWith('Priority: ')} - /> - } - // TODO : this need simplification we want to display both user labels and chore labels - // that why we are merging them here. - // we also filter out the labels that user created as those will be part of user labels - title='Filter by Label' - options={[ - ...userLabels, - ...chores - .map(c => c.labelsV2) - .flat() - .filter(l => l.created_by !== userProfile.id) - .map(l => { - // if user created it don't show it: - return { - ...l, - name: l.name + ' (Shared Label)', - } - }), - ]} - selectedItem={selectedFilter} - onItemSelect={selected => { - handleLabelFiltering({ label: selected }) - }} - isActive={selectedFilter.startsWith('Label: ')} - mouseClickHandler={handleMenuOutsideClick} - useChips - /> - - - - - - {Object.keys(FILTERS).map((filter, index) => ( - { - const filterFunction = FILTERS[filter] - const filteredChores = - filterFunction.length === 2 - ? filterFunction(chores, userProfile.id) - : filterFunction(chores) - setFilteredChores(filteredChores) - setSelectedFilter(filter) - handleFilterMenuClose() - }} - > - {filter} - - {FILTERS[filter].length === 2 - ? FILTERS[filter](chores, userProfile.id).length - : FILTERS[filter](chores).length} - - - ))} - {selectedFilter.startsWith('Label: ') || - (selectedFilter.startsWith('Priority: ') && ( - { - setFilteredChores(chores) - setSelectedFilter('All') - }} - > - Cancel All Filters - - ))} - - - + } @@ -561,6 +451,113 @@ const MyChores = () => { mouseClickHandler={handleMenuOutsideClick} /> + {activeTextField === 'search' && ( +
+
+ } + options={Priorities} + selectedItem={selectedFilter} + onItemSelect={selected => { + handleLabelFiltering({ priority: selected.value }) + }} + mouseClickHandler={handleMenuOutsideClick} + isActive={selectedFilter.startsWith('Priority: ')} + /> + + } + options={userLabels} + selectedItem={selectedFilter} + onItemSelect={selected => { + handleLabelFiltering({ label: selected }) + }} + isActive={selectedFilter.startsWith('Label: ')} + mouseClickHandler={handleMenuOutsideClick} + useChips + /> + + + + + + {Object.keys(FILTERS).map((filter, index) => ( + { + const filterFunction = FILTERS[filter] + const filteredChores = + filterFunction.length === 2 + ? filterFunction(chores, userProfile.id) + : filterFunction(chores) + setFilteredChores(filteredChores) + setSelectedFilter(filter) + handleFilterMenuClose() + }} + > + {filter} + + {FILTERS[filter].length === 2 + ? FILTERS[filter](chores, userProfile.id).length + : FILTERS[filter](chores).length} + + + ))} + + {selectedFilter.startsWith('Label: ') || + (selectedFilter.startsWith('Priority: ') && ( + { + setFilteredChores(chores) + setSelectedFilter('All') + }} + > + Cancel All Filters + + ))} + + +
+
+ )} {selectedFilter !== 'All' && ( { { frequencyType: 'days_of_the_week', regex: /every ([\w, ]+(?:day)?(?:, [\w, ]+(?:day)?)*)$/i, - name: 'Every {days} of the week', + name: 'Every {days}', }, { frequencyType: 'day_of_the_month', @@ -314,7 +315,6 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => { const handleTextChange = e => { if (!e.target.value) { setTaskText('') - setOpenModal(false) setDueDate(null) setFrequency(null) setFrequencyHumanReadable(null) @@ -327,6 +327,13 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => { if (priority.result) setPriority(priority.result) cleanedSentence = priority.cleanedSentence + const repeat = parseRepeatV2(cleanedSentence) + if (repeat.result) { + setFrequency(repeat.result) + setFrequencyHumanReadable(repeat.name) + cleanedSentence = repeat.cleanedSentence + } + const parsedDueDate = chrono.parse(cleanedSentence, new Date(), { forwardDate: true, }) @@ -337,13 +344,6 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => { cleanedSentence = cleanedSentence.replace(parsedDueDate[0].text, '') } - const repeat = parseRepeatV2(cleanedSentence) - if (repeat.result) { - setFrequency(repeat.result) - setFrequencyHumanReadable(repeat.name) - cleanedSentence = repeat.cleanedSentence - } - if (priority.result || parsedDueDate[0]?.index > -1 || repeat.result) { setOpenModal(true) } @@ -425,7 +425,7 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => { */} Create new task - Experimental + Experimental Feature Task in a sentence: @@ -438,13 +438,54 @@ const TaskInput = ({ autoFocus, onChoreUpdate }) => { placeholder='Type your full text here...' sx={{ width: '100%', fontSize: '16px' }} /> + + + This feature lets you create a task simply by typing a + sentence. It attempt parses the sentence to identify the + task's due date, priority, and frequency. + + + + Examples: + + + +
  • + Priority:For highest priority any of the + following keyword P1, Urgent,{' '} + Important, or ASAP. For lower + priorities, use P2, P3, or P4. +
  • +
  • + Due date: Specify dates with phrases like{' '} + tomorrow, next week, Monday, or{' '} + August 1st at 12pm. +
  • +
  • + Frequency: Set recurring tasks with terms + like daily, weekly, monthly,{' '} + yearly, or patterns such as{' '} + every Tuesday and Thursday. +
  • +
    + + } + />
    Title: setTaskTitle(e.target.value)} - placeholder='Type your full text here...' sx={{ width: '100%', fontSize: '16px' }} /> diff --git a/src/views/components/LearnMore.jsx b/src/views/components/LearnMore.jsx new file mode 100644 index 0000000..9145059 --- /dev/null +++ b/src/views/components/LearnMore.jsx @@ -0,0 +1,67 @@ +import { Info } from '@mui/icons-material' +import { Box, Button, Sheet } from '@mui/joy' +import React, { useRef, useState } from 'react' + +const LearnMoreButton = ({ content }) => { + const [open, setOpen] = useState(false) + const anchorRef = useRef(null) + + const handleToggle = () => { + setOpen(prev => !prev) + } + + const handleClickOutside = event => { + if (anchorRef.current && !anchorRef.current.contains(event.target)) { + setOpen(false) + } + } + + React.useEffect(() => { + if (open) { + document.addEventListener('mousedown', handleClickOutside) + } else { + document.removeEventListener('mousedown', handleClickOutside) + } + return () => { + document.removeEventListener('mousedown', handleClickOutside) + } + }, [open]) + + return ( + + + {open && ( + + {content} + + )} + + ) +} + +export default LearnMoreButton