From 488c732f3ce57d903c4cf6b0cd6f5b7af665db28 Mon Sep 17 00:00:00 2001 From: Mo Tarbin Date: Sun, 15 Feb 2026 11:39:05 -0500 Subject: [PATCH] Unify the chip texts generator logic for chorecard --- src/utils/ChoreCardHelpers.jsx | 104 +++++++++++++++++++++++- src/views/Chores/ChoreCard.jsx | 107 +------------------------ src/views/Chores/CompactChoreCard.jsx | 109 +------------------------- 3 files changed, 106 insertions(+), 214 deletions(-) diff --git a/src/utils/ChoreCardHelpers.jsx b/src/utils/ChoreCardHelpers.jsx index ca87966..013d5e5 100644 --- a/src/utils/ChoreCardHelpers.jsx +++ b/src/utils/ChoreCardHelpers.jsx @@ -1,5 +1,18 @@ import moment from 'moment' - +const allMonths = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December', +] /** * Get the text to display for a chore's due date * @param {string|null} nextDueDate - The next due date of the chore @@ -60,3 +73,92 @@ export const getDueDateChipColor = (nextDueDate, chore) => { return 'neutral' } + +export 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' + } + switch (n % 10) { + case 1: + return 'st' + case 2: + return 'nd' + case 3: + return 'rd' + default: + return 'th' + } + } + if (chore.frequencyType === 'once') { + return 'Once' + } else if (chore.frequencyType === 'trigger') { + return 'Trigger' + } else if (chore.frequencyType === 'daily') { + return 'Daily' + } else if (chore.frequencyType === 'adaptive') { + return 'Adaptive' + } else if (chore.frequencyType === 'weekly') { + return 'Weekly' + } else if (chore.frequencyType === 'monthly') { + return 'Monthly' + } else if (chore.frequencyType === 'yearly') { + return 'Yearly' + } else if (chore.frequencyType === 'days_of_the_week') { + let days = metadata.days + if (days.length > 4) { + const allDays = [ + 'Sunday', + 'Monday', + 'Tuesday', + 'Wednesday', + 'Thursday', + 'Friday', + 'Saturday', + ] + const selectedDays = days.map(d => moment().day(d).format('dddd')) + const notSelectedDay = allDays.filter(day => !selectedDays.includes(day)) + const notSelectedShortdays = notSelectedDay.map(d => + moment().day(d).format('ddd'), + ) + return `Daily except ${notSelectedShortdays.join(', ')}` + } else { + days = days.map(d => moment().day(d).format('ddd')) + return days.join(', ') + } + } else if (chore.frequencyType === 'day_of_the_month') { + let months = metadata?.months ? metadata.months : allMonths + if (months.length > 6) { + const selectedMonths = months.map(m => moment().month(m).format('MMMM')) + const notSelectedMonth = allMonths.filter( + month => !selectedMonths.includes(month), + ) + const notSelectedShortMonths = notSelectedMonth.map(m => + moment().month(m).format('MMM'), + ) + let result = `Monthly ${chore.frequency}${dayOfMonthSuffix( + chore.frequency, + )}` + if (notSelectedShortMonths.length > 0) + result += ` + except ${notSelectedShortMonths.join(', ')}` + return result + } else { + 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} ${metadata.unit}` + } else { + return chore.frequencyType + } +} diff --git a/src/views/Chores/ChoreCard.jsx b/src/views/Chores/ChoreCard.jsx index c7c2b9d..8ed5fcf 100644 --- a/src/views/Chores/ChoreCard.jsx +++ b/src/views/Chores/ChoreCard.jsx @@ -20,12 +20,12 @@ import { IconButton, Typography, } from '@mui/joy' -import moment from 'moment' import { useImpersonateUser } from '../../contexts/ImpersonateUserContext.jsx' import { useUserProfile } from '../../queries/UserQueries.jsx' import { getDueDateChipColor, getDueDateChipText, + getRecurrentChipText, } from '../../utils/ChoreCardHelpers.jsx' import { notInCompletionWindow } from '../../utils/Chores.jsx' import { getTextColorFromBackgroundColor } from '../../utils/Colors.jsx' @@ -66,111 +66,6 @@ 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' - } - switch (n % 10) { - case 1: - return 'st' - case 2: - return 'nd' - case 3: - return 'rd' - default: - return 'th' - } - } - if (chore.frequencyType === 'once') { - return 'Once' - } else if (chore.frequencyType === 'trigger') { - return 'Trigger' - } else if (chore.frequencyType === 'daily') { - return 'Daily' - } else if (chore.frequencyType === 'adaptive') { - return 'Adaptive' - } else if (chore.frequencyType === 'weekly') { - return 'Weekly' - } else if (chore.frequencyType === 'monthly') { - return 'Monthly' - } else if (chore.frequencyType === 'yearly') { - return 'Yearly' - } else if (chore.frequencyType === 'days_of_the_week') { - let days = metadata.days - if (days.length > 4) { - const allDays = [ - 'Sunday', - 'Monday', - 'Tuesday', - 'Wednesday', - 'Thursday', - 'Friday', - 'Saturday', - ] - const selectedDays = days.map(d => moment().day(d).format('dddd')) - const notSelectedDay = allDays.filter( - day => !selectedDays.includes(day), - ) - const notSelectedShortdays = notSelectedDay.map(d => - moment().day(d).format('ddd'), - ) - return `Daily except ${notSelectedShortdays.join(', ')}` - } else { - days = days.map(d => moment().day(d).format('ddd')) - return days.join(', ') - } - } else if (chore.frequencyType === 'day_of_the_month') { - let months = metadata.months - if (months.length > 6) { - const allMonths = [ - 'January', - 'February', - 'March', - 'April', - 'May', - 'June', - 'July', - 'August', - 'September', - 'October', - 'November', - 'December', - ] - const selectedMonths = months.map(m => moment().month(m).format('MMMM')) - const notSelectedMonth = allMonths.filter( - month => !selectedMonths.includes(month), - ) - const notSelectedShortMonths = notSelectedMonth.map(m => - moment().month(m).format('MMM'), - ) - let result = `Monthly ${chore.frequency}${dayOfMonthSuffix( - chore.frequency, - )}` - if (notSelectedShortMonths.length > 0) - result += ` - except ${notSelectedShortMonths.join(', ')}` - return result - } else { - 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} ${metadata.unit}` - } else { - return chore.frequencyType - } - } - const getFrequencyIcon = chore => { if (['once', 'no_repeat'].includes(chore.frequencyType)) { return diff --git a/src/views/Chores/CompactChoreCard.jsx b/src/views/Chores/CompactChoreCard.jsx index e69a75c..ac11c07 100644 --- a/src/views/Chores/CompactChoreCard.jsx +++ b/src/views/Chores/CompactChoreCard.jsx @@ -9,13 +9,13 @@ import { Webhook, } from '@mui/icons-material' import { Box, Checkbox, Chip, IconButton, Typography } from '@mui/joy' -import moment from 'moment' import { useNavigate } from 'react-router-dom' import { useImpersonateUser } from '../../contexts/ImpersonateUserContext.jsx' import { useCircleMembers, useUserProfile } from '../../queries/UserQueries.jsx' import { getDueDateChipColor, getDueDateChipText, + getRecurrentChipText, } from '../../utils/ChoreCardHelpers.jsx' import { notInCompletionWindow } from '../../utils/Chores.jsx' import { @@ -65,111 +65,6 @@ const CompactChoreCard = ({ // Utility functions - const getRecurrentText = 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' - } - switch (n % 10) { - case 1: - return 'st' - case 2: - return 'nd' - case 3: - return 'rd' - default: - return 'th' - } - } - if (chore.frequencyType === 'once') { - return 'Once' - } else if (chore.frequencyType === 'trigger') { - return 'Trigger' - } else if (chore.frequencyType === 'daily') { - return 'Daily' - } else if (chore.frequencyType === 'adaptive') { - return 'Adaptive' - } else if (chore.frequencyType === 'weekly') { - return 'Weekly' - } else if (chore.frequencyType === 'monthly') { - return 'Monthly' - } else if (chore.frequencyType === 'yearly') { - return 'Yearly' - } else if (chore.frequencyType === 'days_of_the_week') { - let days = metadata.days - if (days.length > 4) { - const allDays = [ - 'Sunday', - 'Monday', - 'Tuesday', - 'Wednesday', - 'Thursday', - 'Friday', - 'Saturday', - ] - const selectedDays = days.map(d => moment().day(d).format('dddd')) - const notSelectedDay = allDays.filter( - day => !selectedDays.includes(day), - ) - const notSelectedShortdays = notSelectedDay.map(d => - moment().day(d).format('ddd'), - ) - return `Daily except ${notSelectedShortdays.join(', ')}` - } else { - days = days.map(d => moment().day(d).format('ddd')) - return days.join(', ') - } - } else if (chore.frequencyType === 'day_of_the_month') { - let months = metadata.months - if (months.length > 6) { - const allMonths = [ - 'January', - 'February', - 'March', - 'April', - 'May', - 'June', - 'July', - 'August', - 'September', - 'October', - 'November', - 'December', - ] - const selectedMonths = months.map(m => moment().month(m).format('MMMM')) - const notSelectedMonth = allMonths.filter( - month => !selectedMonths.includes(month), - ) - const notSelectedShortMonths = notSelectedMonth.map(m => - moment().month(m).format('MMM'), - ) - let result = `Monthly ${chore.frequency}${dayOfMonthSuffix( - chore.frequency, - )}` - if (notSelectedShortMonths.length > 0) - result += ` - except ${notSelectedShortMonths.join(', ')}` - return result - } else { - 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} ${metadata.unit}` - } else { - return chore.frequencyType - } - } - const getFrequencyIcon = chore => { if (['once', 'no_repeat'].includes(chore.frequencyType)) { return @@ -184,7 +79,7 @@ const CompactChoreCard = ({ const parts = [] // Frequency - parts.push(getRecurrentText(chore)) + parts.push(getRecurrentChipText(chore)) // Assignee (if not current user) if (chore.assignedTo && chore.assignedTo !== userProfile.id) {