diff --git a/src/views/ChoreEdit/RepeatSection.jsx b/src/views/ChoreEdit/RepeatSection.jsx index f76f4be..b1ab401 100644 --- a/src/views/ChoreEdit/RepeatSection.jsx +++ b/src/views/ChoreEdit/RepeatSection.jsx @@ -62,6 +62,51 @@ const DAYS = [ 'saturday', 'sunday', ] + +const WEEK_PATTERNS = { + every_week: 'Every week', + nth_day_of_month: 'Specific occurrences in the month', +} + +const DAY_OCCURRENCE_OPTIONS = [ + { value: 1, label: '1st occurrence' }, + { value: 2, label: '2nd occurrence' }, + { value: 3, label: '3rd occurrence' }, + { value: 4, label: '4th occurrence' }, + { value: -1, label: 'Last occurrence' }, +] +// Helper function to generate schedule preview text +const generateSchedulePreview = metadata => { + if (!metadata?.days?.length) return '' + + const dayNames = metadata.days + .map(day => day.charAt(0).toUpperCase() + day.slice(1, 3)) + .join(', ') + + const timeStr = metadata.time + ? moment(metadata.time).format('h:mm A') + : '6:00 PM' + + if (metadata.weekPattern === 'every_week' || !metadata.weekPattern) { + return `Every ${dayNames} at ${timeStr}` + } + + if ( + metadata.weekPattern === 'nth_day_of_month' && + metadata.dayOccurrences?.length + ) { + const occurrenceStr = metadata.dayOccurrences + .map(w => { + if (w === -1) return 'last' + return `${w}${w === 1 ? 'st' : w === 2 ? 'nd' : w === 3 ? 'rd' : 'th'}` + }) + .join(', ') + return `Every ${occurrenceStr} ${dayNames} of the month at ${timeStr}` + } + + return `Every ${dayNames} at ${timeStr}` +} + const RepeatOnSections = ({ frequencyType, frequency, @@ -77,13 +122,30 @@ const RepeatOnSections = ({ moment(new Date()).format('YYYY-MM-DD') + 'T' + '18:00', ).format() } - }, [frequencyMetadata]) + // Initialize weekPattern if not set + if (!frequencyMetadata?.weekPattern) { + onFrequencyMetadataUpdate({ + ...frequencyMetadata, + weekPattern: 'every_week', + dayOccurrences: [], + }) + } + }, [frequencyMetadata, onFrequencyMetadataUpdate]) const timePickerComponent = ( - - At: + + Time of day: { onFrequencyMetadataUpdate({ @@ -192,6 +254,8 @@ const RepeatOnSections = ({ onFrequencyMetadataUpdate({ ...frequencyMetadata, days: [], + weekPattern: 'every_week', + dayOccurrences: [], }) } else { onFrequencyMetadataUpdate({ @@ -209,6 +273,140 @@ const RepeatOnSections = ({ + + + + { + const newPattern = event.target.value + onFrequencyMetadataUpdate({ + ...frequencyMetadata, + weekPattern: newPattern, + dayOccurrences: + newPattern === 'every_week' + ? [] + : frequencyMetadata?.dayOccurrences || [], + }) + }} + sx={{ gap: 1, '& > div': { p: 1 } }} + > + {Object.entries(WEEK_PATTERNS).map(([value, label]) => ( + + + {value === 'every_week' && ( + + Task repeats every week on selected days + + )} + {value === 'nth_day_of_month' && ( + + Task repeats on specific day occurrences each month + (e.g., 1st Monday, 3rd Friday) + + )} + + ))} + + + {frequencyMetadata?.weekPattern === 'nth_day_of_month' && ( + + + Select which occurrences of the selected days: + + + Example: "1st Monday" means the first Monday of each month + + + + {DAY_OCCURRENCE_OPTIONS.map(option => ( + + { + const currentOccurrences = + frequencyMetadata?.dayOccurrences || [] + const newOccurrences = + currentOccurrences.includes(option.value) + ? currentOccurrences.filter( + w => w !== option.value, + ) + : [...currentOccurrences, option.value] + onFrequencyMetadataUpdate({ + ...frequencyMetadata, + dayOccurrences: newOccurrences.sort((a, b) => { + if (a === -1) return 1 // Last occurrence goes to end + if (b === -1) return -1 + return a - b + }), + }) + }} + overlay + disableIcon + variant='soft' + label={option.label} + /> + + ))} + + + + + )} + + {/* Quarter week pattern removed - doesn't make sense with Nth day approach */} + + {/* Live Preview */} + {frequencyMetadata?.days?.length > 0 && ( + + + {generateSchedulePreview(frequencyMetadata)} + + + )} + + + {timePickerComponent} ) @@ -461,6 +659,8 @@ const RepeatSection = ({ onFrequencyMetadataUpdate({ ...frequencyMetadata, days: [], + weekPattern: 'every_week', + weekNumbers: [], }) } else if (item === 'day_of_the_month') { onFrequencyMetadataUpdate({