[WEB-3523] feat: start of week preference#7033
Conversation
WalkthroughThe changes introduce a user-configurable "start of the week" setting across the application. This involves adding a new enum and options list, updating user profile types and stores, modifying calendar and Gantt chart components to respect the user's preference, and providing a UI for users to select their preferred week start day. Supporting utilities and constants are also updated or added. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant StartOfWeekPreference
participant ProfileStore
participant CalendarComponent
User->>StartOfWeekPreference: Selects new start day
StartOfWeekPreference->>ProfileStore: updateUserProfile(start_of_the_week)
ProfileStore-->>StartOfWeekPreference: Update successful
StartOfWeekPreference->>User: Show success toast
ProfileStore-->>CalendarComponent: start_of_the_week changed (reactive)
CalendarComponent->>CalendarComponent: Re-render with new week start
Poem
Tip ⚡️ Faster reviews with caching
Enjoy the performance boost—your workflow just got faster. 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (5)
🚧 Files skipped from review as they are similar to previous changes (5)
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
|
Pull Request Linked with Plane Work Items Comment Automatically Generated by Plane |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (5)
web/core/store/user/profile.store.ts (1)
62-63: Consider updating ProfileStore action signatures for consistency.The store has methods like
updateUserProfileandupdateUserTheme, but no specific method for updating just the start of the week preference. While not strictly necessary since the genericupdateUserProfilemethod works, adding a dedicated method would maintain consistency with the pattern used for theme updates.export interface IUserProfileStore { // ...existing methods updateUserTheme: (data: Partial<IUserTheme>) => Promise<TUserProfile | undefined>; + updateStartOfTheWeek: (startOfTheWeek: EStartOfTheWeek) => Promise<TUserProfile | undefined>; } // In the class implementation +/** + * @description updates the user's start of the week preference + * @returns {Promise<TUserProfile | undefined>} + */ +updateStartOfTheWeek = async (startOfTheWeek: EStartOfTheWeek) => { + const currentStartOfTheWeek = this.data.start_of_the_week; + try { + this.mutateUserProfile({ start_of_the_week: startOfTheWeek }); + const userProfile = await this.userService.updateCurrentUserProfile({ start_of_the_week: startOfTheWeek }); + return userProfile; + } catch (error) { + runInAction(() => { + this.mutateUserProfile({ start_of_the_week: currentStartOfTheWeek }); + this.error = { + status: "user-profile-start-of-week-update-error", + message: "Failed to update start of the week preference", + }; + }); + throw error; + } +};web/core/components/gantt-chart/data/index.ts (1)
6-19: Consider consolidating duplicated day definitionsThe implementation of
generateWeeksis solid, but it duplicates the day definitions that already exist in the staticweeksarray below. This creates a maintenance burden as any updates would need to be applied in two places.Consider refactoring to eliminate duplication by reusing the static
weeksarray:-export const generateWeeks = (startOfWeek: EStartOfTheWeek = EStartOfTheWeek.SUNDAY): WeekMonthDataType[] => { - const allDays: WeekMonthDataType[] = [ - { key: 0, shortTitle: "sun", title: "sunday", abbreviation: "Su" }, - { key: 1, shortTitle: "mon", title: "monday", abbreviation: "M" }, - { key: 2, shortTitle: "tue", title: "tuesday", abbreviation: "T" }, - { key: 3, shortTitle: "wed", title: "wednesday", abbreviation: "W" }, - { key: 4, shortTitle: "thurs", title: "thursday", abbreviation: "Th" }, - { key: 5, shortTitle: "fri", title: "friday", abbreviation: "F" }, - { key: 6, shortTitle: "sat", title: "saturday", abbreviation: "Sa" }, - ]; +/** + * Generates an array of weekday objects ordered by the user's preferred start of week + * @param startOfWeek The day to use as the start of the week + * @returns Ordered array of week days + */ +export const generateWeeks = (startOfWeek: EStartOfTheWeek = EStartOfTheWeek.SUNDAY): WeekMonthDataType[] => { + const allDays = [...weeks]; // Reorder the array based on startOfWeek return [...allDays.slice(startOfWeek), ...allDays.slice(0, startOfWeek)]; };web/core/components/issues/issue-layouts/calendar/week-days.tsx (1)
81-85: LeveragestartOfWeekwhen filtering weekendsWhen the user chooses a week that starts on Saturday/Sunday, the current logic might unintentionally exclude two working days instead of weekends.
Consider deriving weekend keys (typically 0 & 6) once, unrelated tostartOfWeek, to ensure correctness regardless of user preference.web/core/components/profile/start-of-week-preference.tsx (1)
40-46: Remove the redundant fragment (<>…</>)Static analysis is correct – the fragment only wraps a single map. You can return the mapped elements directly:
-<> - {START_OF_THE_WEEK_OPTIONS.map((day) => ( - <CustomSelect.Option key={day.value} value={day.value}> - {day.label} - </CustomSelect.Option> - ))} -</> +{START_OF_THE_WEEK_OPTIONS.map((day) => ( + <CustomSelect.Option key={day.value} value={day.value}> + {day.label} + </CustomSelect.Option> +))}🧰 Tools
🪛 Biome (1.9.4)
[error] 40-46: Avoid using unnecessary Fragment.
A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment(lint/complexity/noUselessFragments)
web/core/components/gantt-chart/views/week-view.ts (1)
137-141: Edge-case: aligning to the correct week whenstartDateis already the desired start-dayCurrent math works, but using date-fns
startOfWeek(currentDate, { weekStartsOn: startOfWeek })would be more readable and locale-proof (handles DST transitions, etc.).
Consider switching to the utility function in a follow-up refactor.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (16)
packages/constants/src/profile.ts(1 hunks)packages/types/src/users.d.ts(3 hunks)packages/ui/src/calendar.tsx(1 hunks)web/app/profile/appearance/page.tsx(2 hunks)web/core/components/dropdowns/date.tsx(5 hunks)web/core/components/gantt-chart/chart/root.tsx(3 hunks)web/core/components/gantt-chart/data/index.ts(1 hunks)web/core/components/gantt-chart/views/week-view.ts(8 hunks)web/core/components/issues/issue-layouts/calendar/week-days.tsx(2 hunks)web/core/components/issues/issue-layouts/calendar/week-header.tsx(3 hunks)web/core/components/profile/index.ts(1 hunks)web/core/components/profile/start-of-week-preference.tsx(1 hunks)web/core/constants/calendar.ts(2 hunks)web/core/store/issue/issue_calendar_view.store.ts(1 hunks)web/core/store/user/profile.store.ts(2 hunks)web/helpers/calendar.helper.ts(2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (5)
web/core/store/issue/issue_calendar_view.store.ts (1)
web/core/components/gantt-chart/data/index.ts (1)
weeks(21-29)
web/core/components/issues/issue-layouts/calendar/week-header.tsx (1)
web/helpers/calendar.helper.ts (1)
getOrderedDays(98-103)
web/helpers/calendar.helper.ts (1)
web/core/constants/calendar.ts (1)
DAYS_LIST(60-102)
web/app/profile/appearance/page.tsx (1)
web/core/components/profile/start-of-week-preference.tsx (1)
StartOfWeekPreference(14-51)
web/core/components/gantt-chart/views/week-view.ts (1)
web/core/components/gantt-chart/data/index.ts (2)
weeks(21-29)generateWeeks(6-19)
🪛 Biome (1.9.4)
web/core/components/profile/start-of-week-preference.tsx
[error] 40-46: Avoid using unnecessary Fragment.
A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment
(lint/complexity/noUselessFragments)
🔇 Additional comments (25)
packages/constants/src/profile.ts (2)
75-87: Well-structured enum implementation for week start days.The
EStartOfTheWeekenum is correctly implemented with values matching JavaScript's Date object convention (0 for Sunday through 6 for Saturday). The JSDoc documentation clearly explains the purpose of this enum.
89-123: Well-defined options array with clear type documentation.The
START_OF_THE_WEEK_OPTIONSarray properly maps each enum value to its corresponding label, making it ready for use in dropdown selectors or other UI components. The JSDoc is comprehensive and includes the correct type definition.packages/ui/src/calendar.tsx (1)
20-20: Correctly implemented week start preference in the Calendar component.The
weekStartsOnprop is now properly passed to the DayPicker component, enabling user-configured start of week preferences to take effect in calendar displays.Note that this prop is defined before the spread operator
{...props}at line 81. This is fine if the intention is to allow overriding from the spread props, but worth noting as it affects precedence.web/core/components/profile/index.ts (1)
9-9: Good export of the new StartOfWeekPreference component.The new component is properly exported, making it available for use throughout the application.
web/core/store/user/profile.store.ts (2)
5-5: Correctly imported the EStartOfTheWeek enum.The import is properly placed with the other type imports.
63-63: Well-initialized start_of_the_week preference with a sensible default.The
start_of_the_weekproperty is added to the user profile data with Sunday as the default value, which is a common convention. This ensures new user profiles will have a consistent default.web/app/profile/appearance/page.tsx (2)
13-14: Refactored imports look goodThe change correctly separates imports from different modules, making the code more organized.
77-77: Successfully integrated start of week preference UIThe StartOfWeekPreference component is appropriately added to the profile appearance page, giving users control over their preferred first day of the week in calendars.
packages/types/src/users.d.ts (3)
1-1: Appropriately imported new enum typeThe import of EStartOfTheWeek from constants is correct and follows project conventions.
160-163: Improved type definition using PickGood use of TypeScript's Pick utility type to make the type definition more maintainable and precise.
68-68:Details
✅ Verification successful
Good addition of start of week preference to user profile
Adding the start_of_the_week property of type EStartOfTheWeek to the TUserProfile type properly extends the user profile data model to include this new preference.
Let's verify that the profile store provides a default value for this new property:
🏁 Script executed:
#!/bin/bash # Check if the profile store initializes the start_of_the_week property with a default value rg "start_of_the_week" "web/core/store/user/profile.store.ts"Length of output: 106
Confirmed default initialization of
start_of_the_weekThe profile store (
web/core/store/user/profile.store.ts) properly initializesstart_of_the_weektoEStartOfTheWeek.SUNDAY, ensuring a sane default for user preferences. All set—approving these changes.web/core/components/gantt-chart/chart/root.tsx (2)
8-8: Added necessary hook importCorrectly imported the useUserProfile hook to access user preferences.
91-93: Well-structured hook implementationGood use of destructuring to extract the start_of_the_week value from the user profile.
web/core/constants/calendar.ts (2)
1-1: Appropriate import of new enumThe import of EStartOfTheWeek is correct and follows project conventions.
64-64:Details
✅ Verification successful
Well-structured integration of enum values with day definitions
The addition of the enum value to each day in DAYS_LIST creates a clear mapping between days and their corresponding enum values, which is essential for consistent handling of the week start preference throughout the application.
Let's see how these enum values are used in helper functions:
Also applies to: 70-70, 75-75, 80-80, 85-85, 90-90, 95-95, 100-100
🏁 Script executed:
#!/bin/bash # Check how the day enums are used in calendar helpers rg --type-add 'ts:*.ts' --type ts "getOrderedDays|EStartOfTheWeek" "web/helpers/calendar.helper.ts"Length of output: 215
Integration Verified: Enum Values Properly Used in Helpers
The
DAYS_LISTentries map directly toEStartOfTheWeekmembers, and thegetOrderedDayshelper inweb/helpers/calendar.helper.tscorrectly imports and usesEStartOfTheWeekas its parameter type. No further changes are needed.web/core/store/issue/issue_calendar_view.store.ts (1)
71-93: Efficient week sorting in the calendar view getterThe modifications to the
allWeeksOfActiveMonthgetter now ensure weeks are sorted numerically, leading to a more predictable display order. This is an essential foundation for supporting user-configurable start-of-week preferences across the application.web/helpers/calendar.helper.ts (2)
1-1: Good addition of required import for start-of-week functionalityThe import of
EStartOfTheWeekenum is necessary for the new calendar ordering functionality.
98-103: Well-implemented day ordering helper functionThe
getOrderedDaysfunction elegantly handles reordering days of the week based on user preferences using modular arithmetic. This is a clean implementation that will ensure consistent ordering across the application.web/core/components/gantt-chart/data/index.ts (1)
2-2: Required import added for the start-of-week functionalityThe import of
EStartOfTheWeekenum from constants is necessary for the new week generation functionality.web/core/components/issues/issue-layouts/calendar/week-header.tsx (2)
3-17: Good implementation of user preference for week start dayThe integration of user preferences for the start of the week is well implemented. The component now properly:
- Retrieves the user's preference via the
useUserProfilehook- Uses the
getOrderedDayshelper to reorder days based on preference- Correctly structures the relevant code as hook calls and derived state
31-32: Correct handling of weekend filtering with ordered daysThe weekend filtering now correctly works with the dynamically ordered days by checking the day's value property (0 for Sunday and 6 for Saturday) rather than relying on the position in the array.
web/core/components/dropdowns/date.tsx (1)
195-196: ConfirmweekStartsOnaccepts the enum value (0-6)React-Day-Picker (and most date-lib wrappers) expect a plain 0-6 integer.
Ifstart_of_the_weekis stored as the enum value (0-6) you’re ✅.
If the enum is a string (e.g."SUNDAY") you’ll get an invalid prop warning and the calendar will silently default to Sunday.
Please double-check the enum definition or add a cast.web/core/components/issues/issue-layouts/calendar/week-days.tsx (1)
87-92: ✅ Nice, deterministic re-ordering of daysThe modulo math is a clean way to realign the array based on the preferred first day.
web/core/components/gantt-chart/views/week-view.ts (2)
184-196: 👍 Good reuse ofgenerateWeeksto keep labels in syncThe day objects and abbreviations will now consistently respect the user’s preference – nice touch!
42-47:Details
✅ Verification successful
Verify all call-sites updated to the new
startOfWeekparameter
generateWeekChart,getWeeksBetweenTwoDates, andpopulateDaysForWeeknow require the extra argument.
A missed update will silently passundefined, falling back to Sunday and breaking user expectations.The pattern searches for invocations with too few parameters.
🏁 Script executed:
#!/bin/bash # Find calls to the three functions that still use the old arity rg --type tsx --type ts --no-heading -n \ -e 'generateWeekChart\([^,)]*\)$' \ -e 'getWeeksBetweenTwoDates\([^,)]*,[^,)]*,[^)]*\)$' \ -e 'populateDaysForWeek\([^,)]*\)$'Length of output: 192
🏁 Script executed:
#!/bin/bash # Search for generateWeekChart calls missing the 4th argument rg -n 'generateWeekChart\(' -g '*.ts' -g '*.tsx' | grep -v -E 'generateWeekChart\([^)]*(,[^)]*){3}\)' # Search for getWeeksBetweenTwoDates calls missing the 3rd argument rg -n 'getWeeksBetweenTwoDates\(' -g '*.ts' -g '*.tsx' | grep -v -E 'getWeeksBetweenTwoDates\([^)]*(,[^)]*){2}\)' # Search for populateDaysForWeek calls missing the 2nd argument rg -n 'populateDaysForWeek\(' -g '*.ts' -g '*.tsx' | grep -v -E 'populateDaysForWeek\([^)]*(,[^)]*){1}\)'Length of output: 327
All call-sites include the new
startOfWeekargumentI searched across all
.tsand.tsxfiles for calls togenerateWeekChart,getWeeksBetweenTwoDates, andpopulateDaysForWeekthat don’t pass the fourth, third, and second parameters respectively—no occurrences were found. All call-sites have been updated to include the newstartOfWeekargument.
web/core/components/issues/issue-layouts/calendar/week-days.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
web/core/components/profile/start-of-week-preference.tsx (2)
44-50: Remove unnecessary Fragment.The
<>...</>Fragment wrapper is redundant here as it contains only a single child (the map function).- <> {START_OF_THE_WEEK_OPTIONS.map((day) => ( <CustomSelect.Option key={day.value} value={day.value}> {day.label} </CustomSelect.Option> ))} - </>🧰 Tools
🪛 Biome (1.9.4)
[error] 44-50: Avoid using unnecessary Fragment.
A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment(lint/complexity/noUselessFragments)
11-12: Consider using useMemo for the helper function.For optimization, you might want to memoize the
getStartOfWeekLabelfunction or move it inside the component and wrap it with useMemo, especially if the component re-renders frequently.-const getStartOfWeekLabel = (startOfWeek: EStartOfTheWeek) => - START_OF_THE_WEEK_OPTIONS.find((option) => option.value === startOfWeek)?.label; export const StartOfWeekPreference = observer(() => { // hooks const { data: userProfile, updateUserProfile } = useUserProfile(); + const getStartOfWeekLabel = useMemo(() => { + return (startOfWeek: EStartOfTheWeek) => + START_OF_THE_WEEK_OPTIONS.find((option) => option.value === startOfWeek)?.label; + }, []);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
space/core/store/profile.store.ts(2 hunks)web/core/components/dropdowns/date.tsx(4 hunks)web/core/components/gantt-chart/chart/root.tsx(3 hunks)web/core/components/issues/issue-layouts/calendar/week-days.tsx(2 hunks)web/core/components/issues/issue-layouts/calendar/week-header.tsx(3 hunks)web/core/components/profile/start-of-week-preference.tsx(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- space/core/store/profile.store.ts
🚧 Files skipped from review as they are similar to previous changes (4)
- web/core/components/gantt-chart/chart/root.tsx
- web/core/components/issues/issue-layouts/calendar/week-days.tsx
- web/core/components/issues/issue-layouts/calendar/week-header.tsx
- web/core/components/dropdowns/date.tsx
🧰 Additional context used
🧬 Code Graph Analysis (1)
web/core/components/profile/start-of-week-preference.tsx (2)
packages/constants/src/profile.ts (1)
START_OF_THE_WEEK_OPTIONS(94-123)packages/ui/src/dropdowns/custom-select.tsx (1)
CustomSelect(156-156)
🪛 Biome (1.9.4)
web/core/components/profile/start-of-week-preference.tsx
[error] 44-50: Avoid using unnecessary Fragment.
A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment
(lint/complexity/noUselessFragments)
⏰ Context from checks skipped due to timeout of 90000ms (2)
- GitHub Check: Analyze (javascript)
- GitHub Check: Analyze (python)
🔇 Additional comments (1)
web/core/components/profile/start-of-week-preference.tsx (1)
1-55: Well-implemented component with good user experience.The component is well-structured with clear separation of concerns, proper error handling, and responsive layout. The descriptive text explains the impact of this setting clearly to users.
🧰 Tools
🪛 Biome (1.9.4)
[error] 44-50: Avoid using unnecessary Fragment.
A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment(lint/complexity/noUselessFragments)
web/core/components/issues/issue-layouts/calendar/week-days.tsx
Outdated
Show resolved
Hide resolved
web/core/components/issues/issue-layouts/calendar/week-header.tsx
Outdated
Show resolved
Hide resolved
* chore: startOfWeek constant and types updated * chore: startOfWeek updated in profile store * chore: StartOfWeekPreference added to profile appearance settings * chore: calendar layout startOfWeek implementation * chore: date picker startOfWeek implementation * chore: gantt layout startOfWeek implementation * chore: code refactor * chore: code refactor * chore: code refactor
* chore: startOfWeek constant and types updated * chore: startOfWeek updated in profile store * chore: StartOfWeekPreference added to profile appearance settings * chore: calendar layout startOfWeek implementation * chore: date picker startOfWeek implementation * chore: gantt layout startOfWeek implementation * chore: code refactor * chore: code refactor * chore: code refactor
Description
This PR implements support for the start of week user preference. Users can now choose their preferred start day of the week from their profile settings. This setting will be applied consistently across the following areas:
Type of Change
Media
References
[WEB-3523]
Summary by CodeRabbit
New Features
Improvements
Bug Fixes