Skip to content

Conversation

@ming4762
Copy link
Contributor

@ming4762 ming4762 commented Oct 22, 2025

feat: increase support for multiple time zones
image

Summary by CodeRabbit

  • New Features

    • Timezone selector widget added to the header with a modal to choose timezone.
    • Users can load, select, and save their preferred timezone; selection persists and is applied as the app default.
    • Client APIs and stores added to fetch options and get/set user timezone.
    • Preference flag added to enable/disable the timezone widget.
  • Localization

    • Added timezone-related translations for English and Chinese.

@changeset-bot
Copy link

changeset-bot bot commented Oct 22, 2025

⚠️ No Changeset found

Latest commit: e01803c

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 22, 2025

Warning

Rate limit exceeded

@ming4762 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 14 minutes and 29 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between e3e5755 and e01803c.

📒 Files selected for processing (4)
  • apps/web-antd/src/store/user-profile.ts (1 hunks)
  • apps/web-ele/src/store/user-profile.ts (1 hunks)
  • apps/web-naive/src/store/user-profile.ts (1 hunks)
  • packages/effects/layouts/src/widgets/timezone/timezone-button.vue (1 hunks)

Walkthrough

Adds end-to-end timezone support: mock backend endpoints and data, timezone utilities, client APIs and Pinia stores, a TimezoneButton UI widget with header slot integration, date/time utilities and typings, preferences toggle, and i18n strings across apps and packages.

Changes

Cohort / File(s) Summary
Backend mock endpoints
apps/backend-mock/api/profile/timezone.ts, apps/backend-mock/api/user/timezone.ts, apps/backend-mock/api/user/setTimezone.ts
New h3 event handlers: return timezone options, return authenticated user timezone, and set authenticated user timezone (reads body), using mock utilities and standardized responses.
Backend mock data & utils
apps/backend-mock/utils/mock-data.ts, apps/backend-mock/utils/timezone-utils.ts
Added TimeZoneOption / TimezoneOption typings, TIME_ZONE_OPTIONS list, and simple in-memory setTimezone / getTimezone.
Client API modules (web apps)
apps/*/src/api/core/user-profile.ts, apps/*/src/api/core/index.ts
New API wrappers: getTimezoneOptionsApi, getUserTimezoneApi, setUserTimezoneApi; re-exported from core barrels.
Pinia stores (web apps)
apps/*/src/store/user-profile.ts, apps/*/src/store/index.ts
New useUserProfileStore: timezone state, setTimezone, initTimezone (auto-run); store re-exported from store index.
Layout integrations (web apps)
apps/*/src/layouts/basic.vue
Injected TimezoneButton slot, fetch timezone options on mount, added handleSetTimezone to update store and show success message.
Timezone widget & layout slots
packages/effects/layouts/src/widgets/timezone/timezone-button.vue, packages/effects/layouts/src/widgets/timezone/index.ts, packages/effects/layouts/src/widgets/index.ts, packages/effects/layouts/src/basic/*, packages/effects/layouts/src/basic/header/header.vue
New TimezoneButton component (modal + radio list), widget re-exports, new timezone header slot and adjusted slot ordering/indices.
Date utilities & typings
packages/@core/base/shared/src/utils/date.ts, packages/@core/base/typings/src/user-profile.d.ts, packages/@core/base/typings/src/index.ts
Added dayjs utc/timezone plugins, setDefaultTimezone, getTimezone; added TimezoneOption type and re-export in typings.
Preferences / types
packages/@core/preferences/src/config.ts, packages/@core/preferences/src/types.ts
Added timezone: boolean to default preferences and WidgetPreferences type.
Localization
packages/locales/src/langs/en-US/ui.json, packages/locales/src/langs/zh-CN/ui.json
Added widgets.timezone keys: setTimezone, setSuccess in en-US and zh-CN.
Minor / formatting
packages/effects/plugins/src/echarts/use-echarts.ts
Trailing comma added to function parameters (formatting-only).

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant UI as TimezoneButton
    participant Store as useUserProfileStore
    participant API as requestClient
    participant Backend as backend-mock

    User->>UI: open modal & select timezone
    UI->>UI: confirm -> call okHandler
    UI->>Store: setTimezone(timezone)
    Store->>API: setUserTimezoneApi(timezone) POST /user/setTimezone
    API->>Backend: POST /user/setTimezone
    Backend->>Backend: verifyAccessToken, setTimezone(mock)
    Backend-->>API: 200 success
    API-->>Store: resolved
    Store->>Store: update timezone state, setDefaultTimezone
    Store-->>UI: success
    UI->>User: show success, close modal

    Note over Store,Backend: On initialization
    Store->>API: getUserTimezoneApi() GET /user/timezone
    API->>Backend: GET /user/timezone
    Backend-->>API: current timezone (or null)
    API-->>Store: timezone
    Store->>Store: apply timezone via setDefaultTimezone
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

feature

Suggested reviewers

  • anncwb
  • vince292007
  • mynetfan
  • jinmao88

Poem

🐰 I hopped through code to set the clocks,
A modal, radios, little ticks and tocks,
Dayjs learned where each timezone docks,
From mock backend to header blocks,
Now every rabbit’s schedule rocks.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The pull request description fails to follow the required template structure. The provided description contains only the title repeated and an embedded screenshot, but is missing all required sections: the Description section (with details about the changes and context), the Type of change section (with checkboxes indicating the nature of the change), and the Checklist section (confirming quality assurance steps). While the PR objectives suggest this is a new feature for timezone support, the description provides no written explanation of what was implemented, why, or how, and includes no confirmation of testing, documentation, or code quality measures. Please update the PR description to follow the repository template. Add a detailed Description section explaining the timezone feature implementation and motivation, select "New feature" in the Type of change section, and verify and check off all applicable items in the Checklist (including testing, code review, and documentation updates). The screenshot is helpful context, but should be accompanied by written explanations of the changes made.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title "feat: increase support for multiple time zones" is clearly related to the changeset, which adds comprehensive timezone functionality across the backend, frontend, and shared utilities. The title accurately represents the main change—introducing multi-timezone support including API endpoints, UI components, store management, and locale translations. The title is concise, uses proper semantic commit conventions (feat:), and is specific enough for teammates to understand the primary change when scanning history. While "increase support" could be slightly more specific, it effectively conveys that new timezone capabilities are being added.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 17

♻️ Duplicate comments (1)
apps/web-antd/src/api/core/user-profile.ts (1)

1-3: Same as web‑naive API: confirm TimezoneOption uses the same key ('timezone').

See the verification script added in apps/web-naive/src/api/core/user-profile.ts.

Also applies to: 8-16, 21-23

🧹 Nitpick comments (14)
packages/@core/base/shared/src/utils/date.ts (1)

37-39: Consider simplifying the timezone setter.

The ternary operator works correctly but could be more explicit for better readability.

 export const setDefaultTimezone = (timezone?: string) => {
-  timezone ? dayjs.tz.setDefault(timezone) : dayjs.tz.setDefault();
+  if (timezone) {
+    dayjs.tz.setDefault(timezone);
+  } else {
+    dayjs.tz.setDefault();
+  }
 };
apps/backend-mock/api/user/setTimezone.ts (1)

11-12: Consider adding input validation for the timezone parameter.

The timezone value from the request body is used directly without validation. While this is a mock endpoint, adding basic validation (e.g., checking if timezone exists and is a non-empty string) would improve robustness and catch potential issues during development.

Example validation:

  const { timezone } = await readBody(event);
+ if (!timezone || typeof timezone !== 'string') {
+   setResponseStatus(event, 400);
+   return useResponseError('Invalid timezone', 'Timezone is required and must be a string');
+ }
  setTimezone(timezone);
apps/web-ele/src/api/core/user-profile.ts (1)

14-16: Consider simplifying the return type.

The return type Promise<null | string | undefined> suggests three distinct states (null, undefined, string), which may be unnecessarily complex. Consider whether Promise<string | null> or Promise<string | undefined> would suffice.

apps/web-antd/src/store/user-profile.ts (1)

41-41: Consider deferring auto-initialization.

Calling initTimezone() during store creation is a side effect that executes immediately when the module loads. This could cause issues if:

  • The API is not yet ready
  • Authentication is not yet established
  • Multiple components trigger store creation simultaneously

Consider one of these approaches:

  1. Let consuming components call initTimezone() explicitly when appropriate
  2. Use a lazy initialization pattern that triggers on first access
  3. Add a flag to track initialization state and prevent duplicate calls
apps/web-ele/src/store/user-profile.ts (2)

41-41: Consider deferring auto-initialization.

Calling initTimezone() during store creation creates a side effect that executes immediately when the module loads. This could cause issues if the API or authentication is not yet ready.

Consider:

  1. Explicit initialization by consuming components
  2. Lazy initialization on first access
  3. Initialization state tracking to prevent duplicate calls

1-56: Consider extracting shared store logic.

This store is nearly identical to apps/web-antd/src/store/user-profile.ts. Consider extracting the common timezone management logic into a shared composable or utility to maintain consistency and reduce duplication across projects.

apps/web-ele/src/layouts/basic.vue (3)

77-89: Add error feedback on save failure.

Currently only finally resets loading. Surface failures to users.

 const handleSetTimezone = async (
   timezone: string,
   modalApi: ExtendedModalApi,
 ) => {
   try {
     modalApi.setState({ confirmLoading: true });
     await userProfileStore.setTimezone(timezone);
     ElMessage.success($t('ui.widgets.timezone.setSuccess'));
     modalApi.close();
+  } catch (err) {
+    ElMessage.error($t?.('common.error') || 'Failed to update timezone');
   } finally {
     modalApi.setState({ confirmLoading: false });
   }
 };

178-185: Minor: remove unused name attr; rely on unwrapped ref.

name="out" is unused and leaks to DOM. Also, after fixing computedTimezone, this remains valid.

   <TimezoneButton
     :ok-handler="handleSetTimezone"
     :timezone="computedTimezone"
     :timezone-options="timezoneOptions"
-    name="out"
   />

72-76: Defensive mapping for backend key drift (timezone vs timeZone).

Until backend/type is unified, tolerate both keys to avoid undefined values.

-  timezoneOptions.value = ((await getTimezoneOptionsApi()) || []).map(
-    (item) => item.timezone,
-  );
+  const list = (await getTimezoneOptionsApi()) || [];
+  timezoneOptions.value = list.map((item: any) => item.timezone ?? item.timeZone).filter(Boolean);
packages/effects/layouts/src/widgets/timezone/timezone-button.vue (1)

70-78: Minor: fix label a11y and style class.

Bind label to control and align class name with CSS.

-          <div
+          <div
             class="flex cursor-pointer items-center gap-2"
             v-for="item in props.timezoneOptions"
             :key="`container${item}`"
             @click="handleClickItem(item)"
           >
-            <RadioGroupItem :id="item" :value="item" />
-            <label class="cursor-pointer">{{ item }}</label>
+            <RadioGroupItem :id="item" :value="item" />
+            <label class="cursor-pointer" :for="item">{{ item }}</label>
           </div>
@@
-<style scoped>
-.container {
-  padding-left: 20px;
-}
-</style>
+<style scoped>
+.timezone-container {
+  padding-left: 20px;
+}
+</style>

Also applies to: 85-89

apps/web-naive/src/layouts/basic.vue (2)

78-90: Add error feedback on failure.

   try {
     modalApi.setState({ confirmLoading: true });
     await userProfileStore.setTimezone(timezone);
     message.success($t('ui.widgets.timezone.setSuccess'));
     modalApi.close();
+  } catch (err) {
+    message.error($t?.('common.error') || 'Failed to update timezone');
   } finally {
     modalApi.setState({ confirmLoading: false });
   }

181-187: Minor: remove unused name attr.

   <TimezoneButton
     :ok-handler="handleSetTimezone"
     :timezone="computedTimezone"
     :timezone-options="timezoneOptions"
-    name="out"
   />
apps/web-antd/src/layouts/basic.vue (2)

77-89: Add error feedback on failure.

   try {
     modalApi.setState({ confirmLoading: true });
     await userProfileStore.setTimezone(timezone);
     message.success($t('ui.widgets.timezone.setSuccess'));
     modalApi.close();
+  } catch (err) {
+    message.error($t?.('common.error') || 'Failed to update timezone');
   } finally {
     modalApi.setState({ confirmLoading: false });
   }

179-185: Minor: remove unused name attr.

   <TimezoneButton
     :ok-handler="handleSetTimezone"
     :timezone="computedTimezone"
     :timezone-options="timezoneOptions"
-    name="out"
   />
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 03ce030 and 0a8339a.

📒 Files selected for processing (32)
  • apps/backend-mock/api/profile/timezone.ts (1 hunks)
  • apps/backend-mock/api/user/setTimezone.ts (1 hunks)
  • apps/backend-mock/api/user/timezone.ts (1 hunks)
  • apps/backend-mock/utils/mock-data.ts (2 hunks)
  • apps/backend-mock/utils/timezone-utils.ts (1 hunks)
  • apps/web-antd/src/api/core/index.ts (1 hunks)
  • apps/web-antd/src/api/core/user-profile.ts (1 hunks)
  • apps/web-antd/src/layouts/basic.vue (4 hunks)
  • apps/web-antd/src/store/index.ts (1 hunks)
  • apps/web-antd/src/store/user-profile.ts (1 hunks)
  • apps/web-ele/src/api/core/index.ts (1 hunks)
  • apps/web-ele/src/api/core/user-profile.ts (1 hunks)
  • apps/web-ele/src/layouts/basic.vue (4 hunks)
  • apps/web-ele/src/store/index.ts (1 hunks)
  • apps/web-ele/src/store/user-profile.ts (1 hunks)
  • apps/web-naive/src/api/core/index.ts (1 hunks)
  • apps/web-naive/src/api/core/user-profile.ts (1 hunks)
  • apps/web-naive/src/layouts/basic.vue (4 hunks)
  • apps/web-naive/src/store/index.ts (1 hunks)
  • apps/web-naive/src/store/user-profile.ts (1 hunks)
  • packages/@core/base/shared/src/utils/date.ts (2 hunks)
  • packages/@core/base/typings/src/index.ts (1 hunks)
  • packages/@core/base/typings/src/user-profile.d.ts (1 hunks)
  • packages/@core/preferences/src/config.ts (1 hunks)
  • packages/@core/preferences/src/types.ts (1 hunks)
  • packages/effects/layouts/src/basic/header/header.vue (1 hunks)
  • packages/effects/layouts/src/basic/layout.vue (1 hunks)
  • packages/effects/layouts/src/widgets/index.ts (1 hunks)
  • packages/effects/layouts/src/widgets/timezone/index.ts (1 hunks)
  • packages/effects/layouts/src/widgets/timezone/timezone-button.vue (1 hunks)
  • packages/locales/src/langs/en-US/ui.json (1 hunks)
  • packages/locales/src/langs/zh-CN/ui.json (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (11)
apps/web-ele/src/api/core/user-profile.ts (3)
apps/web-antd/src/api/core/user-profile.ts (3)
  • getTimezoneOptionsApi (8-10)
  • getUserTimezoneApi (14-16)
  • setUserTimezoneApi (21-23)
apps/web-naive/src/api/core/user-profile.ts (3)
  • getTimezoneOptionsApi (8-10)
  • getUserTimezoneApi (14-16)
  • setUserTimezoneApi (21-23)
packages/@core/base/typings/src/user-profile.d.ts (1)
  • TimezoneOption (9-9)
apps/backend-mock/api/profile/timezone.ts (2)
apps/backend-mock/utils/response.ts (1)
  • useResponseSuccess (5-12)
apps/backend-mock/utils/mock-data.ts (1)
  • TIME_ZONE_OPTIONS (400-421)
apps/backend-mock/api/user/setTimezone.ts (3)
apps/backend-mock/utils/jwt-utils.ts (1)
  • verifyAccessToken (29-58)
apps/backend-mock/utils/response.ts (2)
  • unAuthorizedResponse (52-55)
  • useResponseSuccess (5-12)
apps/backend-mock/utils/timezone-utils.ts (1)
  • setTimezone (3-5)
apps/backend-mock/utils/timezone-utils.ts (1)
packages/@core/base/shared/src/utils/date.ts (1)
  • getTimezone (45-47)
apps/web-antd/src/store/user-profile.ts (3)
apps/backend-mock/utils/timezone-utils.ts (2)
  • getTimezone (7-10)
  • setTimezone (3-5)
packages/@core/base/shared/src/utils/date.ts (2)
  • getTimezone (45-47)
  • setDefaultTimezone (37-39)
apps/web-antd/src/api/core/user-profile.ts (2)
  • setUserTimezoneApi (21-23)
  • getUserTimezoneApi (14-16)
apps/web-naive/src/api/core/user-profile.ts (3)
apps/web-antd/src/api/core/user-profile.ts (3)
  • getTimezoneOptionsApi (8-10)
  • getUserTimezoneApi (14-16)
  • setUserTimezoneApi (21-23)
apps/web-ele/src/api/core/user-profile.ts (3)
  • getTimezoneOptionsApi (8-10)
  • getUserTimezoneApi (14-16)
  • setUserTimezoneApi (21-23)
packages/@core/base/typings/src/user-profile.d.ts (1)
  • TimezoneOption (9-9)
apps/web-ele/src/store/user-profile.ts (2)
packages/@core/base/shared/src/utils/date.ts (2)
  • getTimezone (45-47)
  • setDefaultTimezone (37-39)
apps/web-ele/src/api/core/user-profile.ts (2)
  • setUserTimezoneApi (21-23)
  • getUserTimezoneApi (14-16)
packages/@core/base/shared/src/utils/date.ts (1)
apps/backend-mock/utils/timezone-utils.ts (1)
  • getTimezone (7-10)
apps/backend-mock/api/user/timezone.ts (3)
apps/backend-mock/utils/jwt-utils.ts (1)
  • verifyAccessToken (29-58)
apps/backend-mock/utils/response.ts (2)
  • unAuthorizedResponse (52-55)
  • useResponseSuccess (5-12)
apps/backend-mock/utils/timezone-utils.ts (1)
  • getTimezone (7-10)
apps/web-antd/src/api/core/user-profile.ts (3)
apps/web-ele/src/api/core/user-profile.ts (3)
  • getTimezoneOptionsApi (8-10)
  • getUserTimezoneApi (14-16)
  • setUserTimezoneApi (21-23)
apps/web-naive/src/api/core/user-profile.ts (3)
  • getTimezoneOptionsApi (8-10)
  • getUserTimezoneApi (14-16)
  • setUserTimezoneApi (21-23)
packages/@core/base/typings/src/user-profile.d.ts (1)
  • TimezoneOption (9-9)
apps/web-naive/src/store/user-profile.ts (3)
apps/backend-mock/utils/timezone-utils.ts (2)
  • getTimezone (7-10)
  • setTimezone (3-5)
packages/@core/base/shared/src/utils/date.ts (2)
  • getTimezone (45-47)
  • setDefaultTimezone (37-39)
apps/web-naive/src/api/core/user-profile.ts (2)
  • setUserTimezoneApi (21-23)
  • getUserTimezoneApi (14-16)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Check (ubuntu-latest)
  • GitHub Check: Lint (windows-latest)
  • GitHub Check: Check (windows-latest)
  • GitHub Check: post-update (ubuntu-latest)
  • GitHub Check: post-update (windows-latest)
🔇 Additional comments (21)
packages/locales/src/langs/zh-CN/ui.json (1)

106-108: LGTM!

The timezone localization strings are properly structured and translations appear appropriate for the Chinese locale.

packages/locales/src/langs/en-US/ui.json (1)

106-108: LGTM!

The timezone localization strings are properly structured and consistent with the Chinese locale file.

packages/@core/preferences/src/types.ts (1)

278-279: LGTM!

The timezone widget preference field is properly typed and follows the existing pattern for widget configuration flags.

packages/@core/base/shared/src/utils/date.ts (3)

2-6: LGTM!

The dayjs timezone and UTC plugins are properly imported and extended in the correct order.


45-46: LGTM!

The getTimezone function correctly uses dayjs's built-in timezone guessing functionality.


14-14: Verify the semantic change in timezone handling is intentional.

The date.tz() method without arguments will use the default timezone if one is set, otherwise it falls back to the local timezone and does not throw an error. This means the code is safe and won't fail unexpectedly.

However, changing from date.format(format) to date.tz().format(format) shifts the function's behavior from timezone-unaware to timezone-aware (defaulting to local timezone). Confirm this semantic change aligns with the intended behavior of formatDate.

apps/backend-mock/utils/timezone-utils.ts (1)

3-5: LGTM!

The mock setTimezone function is appropriately simple for backend testing purposes.

apps/web-ele/src/api/core/index.ts (1)

4-4: LGTM!

The user-profile module re-export follows the existing barrel export pattern.

apps/web-naive/src/store/index.ts (1)

2-2: LGTM!

The user-profile store module re-export follows the existing barrel export pattern.

apps/web-naive/src/api/core/index.ts (1)

4-4: LGTM!

The user-profile module re-export follows the existing barrel export pattern.

packages/effects/layouts/src/basic/layout.vue (1)

305-307: LGTM! Slot implementation follows existing patterns.

The timezone slot is correctly implemented and follows the same pattern as the notification slot above it. This provides a clean extension point for timezone UI components.

packages/@core/preferences/src/config.ts (1)

137-137: LGTM! Widget configuration follows established pattern.

The timezone widget flag is correctly added with a default value of true, consistent with other widget preferences in the configuration object.

apps/backend-mock/api/profile/timezone.ts (1)

5-6: LGTM! Appropriate implementation for a public options endpoint.

This endpoint correctly returns the available timezone options without requiring authentication, which is appropriate for a resource that provides configuration options to all users.

packages/effects/layouts/src/widgets/timezone/index.ts (1)

1-1: LGTM!

Standard barrel export pattern for the TimezoneButton component.

packages/@core/base/typings/src/user-profile.d.ts (1)

1-9: LGTM!

Type definition is clear and appropriately structured for timezone options.

packages/effects/layouts/src/widgets/index.ts (1)

11-11: LGTM!

Consistent barrel export pattern extending the public API to include timezone widgets.

packages/effects/layouts/src/basic/header/header.vue (1)

75-86: LGTM!

Slot index adjustments are correct. Fullscreen moved to +50 and notification moved to +60 to accommodate the new timezone slot at +40.

apps/web-ele/src/api/core/user-profile.ts (2)

8-10: LGTM!

API wrapper is correctly implemented with proper JSDoc documentation.

Ensure that the requestClient has appropriate error handling and retry logic for these timezone endpoints, especially for getTimezoneOptionsApi which is critical for the timezone selection UI.


21-23: LGTM!

Timezone persistence API is correctly implemented.

apps/web-antd/src/store/user-profile.ts (1)

10-12: LGTM!

Fallback logic appropriately handles cases where getTimezone() returns a falsy value by using the browser's default timezone.

apps/backend-mock/api/user/timezone.ts (1)

6-12: LGTM!

Mock endpoint correctly implements authentication check and returns timezone data. Implementation is clean and follows established patterns.

Comment on lines +10 to +13
export interface TimeZoneOption {
offset: number;
timeZone: string;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Unify timezone key and type name; current code won’t type‑check.

Interface uses timeZone while data uses timezone. Also type is TimeZoneOption vs shared TimezoneOption elsewhere.

-export interface TimeZoneOption {
-  offset: number;
-  timeZone: string;
-}
+export interface TimezoneOption {
+  offset: number;
+  timezone: string;
+}
@@
-export const TIME_ZONE_OPTIONS: TimeZoneOption[] = [
+export const TIME_ZONE_OPTIONS: TimezoneOption[] = [

Also applies to: 400-421

🤖 Prompt for AI Agents
In apps/backend-mock/utils/mock-data.ts around lines 10 to 13 (and similarly
lines ~400-421), the interface and the data are mismatched: the interface
declares timeZone: string and is named TimeZoneOption while the actual mock
objects use timezone and the shared type elsewhere is named TimezoneOption;
update the file so the property name and type name match the rest of the
codebase — either rename the interface to export interface TimezoneOption {
offset: number; timezone: string; } or change the mock data to use timeZone and
export the interface as TimeZoneOption consistently, and update any
imports/usages to reference the unified type name.

@@ -1,7 +1,8 @@
<script lang="ts" setup>
import type { ExtendedModalApi } from '@vben/common-ui';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Unify ExtendedModalApi source with widget (popup-ui).

-import type { ExtendedModalApi } from '@vben/common-ui';
+import type { ExtendedModalApi } from '@vben-core/popup-ui';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import type { ExtendedModalApi } from '@vben/common-ui';
import type { ExtendedModalApi } from '@vben-core/popup-ui';
🤖 Prompt for AI Agents
In apps/web-antd/src/layouts/basic.vue around line 2, the ExtendedModalApi type
is imported from '@vben/common-ui' but should be unified with the widget's
popup-ui; change the import source to the widget module (e.g.
'@vben/widget/popup-ui'), update the import statement accordingly, and ensure
TypeScript path/module resolution is correct so the new module compiles.

Comment on lines 19 to 25
async function setTimezone(timezone: string) {
timezoneRef.value = timezone;
// 设置dayjs默认时区
setDefaultTimezone(timezone);
// 保存用户的时区设置
await setUserTimezoneApi(timezone);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add error handling for timezone persistence.

The setTimezone function updates local state before confirming the server update succeeds. If setUserTimezoneApi fails, the local timezone will be out of sync with the server.

Consider this approach:

  async function setTimezone(timezone: string) {
-   timezoneRef.value = timezone;
-   // 设置dayjs默认时区
-   setDefaultTimezone(timezone);
-   // 保存用户的时区设置
-   await setUserTimezoneApi(timezone);
+   try {
+     // 保存用户的时区设置
+     await setUserTimezoneApi(timezone);
+     // 只有在服务器更新成功后才更新本地状态
+     timezoneRef.value = timezone;
+     // 设置dayjs默认时区
+     setDefaultTimezone(timezone);
+   } catch (error) {
+     console.error('Failed to set timezone:', error);
+     throw error; // Re-throw to allow caller to handle
+   }
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async function setTimezone(timezone: string) {
timezoneRef.value = timezone;
// 设置dayjs默认时区
setDefaultTimezone(timezone);
// 保存用户的时区设置
await setUserTimezoneApi(timezone);
}
async function setTimezone(timezone: string) {
try {
// 保存用户的时区设置
await setUserTimezoneApi(timezone);
// 只有在服务器更新成功后才更新本地状态
timezoneRef.value = timezone;
// 设置dayjs默认时区
setDefaultTimezone(timezone);
} catch (error) {
console.error('Failed to set timezone:', error);
throw error; // Re-throw to allow caller to handle
}
}
🤖 Prompt for AI Agents
In apps/web-antd/src/store/user-profile.ts around lines 19–25, setTimezone
currently updates timezoneRef and calls setDefaultTimezone before awaiting
setUserTimezoneApi, which can leave local state inconsistent if the API fails;
change the flow to await the API call inside a try/catch and only update
timezoneRef and call setDefaultTimezone after a successful response, and in the
catch log the error (or show user feedback) and do not change local state (or if
you prefer optimistic update, perform the update first but revert it in the
catch and notify the user); ensure the function rethrows or returns a failure
indicator so callers can react.

Comment on lines +10 to +13
const timezoneRef = ref(
getTimezone() || new Intl.DateTimeFormat().resolvedOptions().timeZone,
);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Prevent init/save races and set default TZ immediately.

  • initTimezone may overwrite a user’s selection if it resolves later.
  • Default timezone isn’t set from the initial value until init or set.
  • No rollback on failed save.
   const timezoneRef = ref(
     getTimezone() || new Intl.DateTimeFormat().resolvedOptions().timeZone,
   );

+  // Ensure dayjs default timezone is set from initial value
+  setDefaultTimezone(timezoneRef.value);
@@
   async function setTimezone(timezone: string) {
-    timezoneRef.value = timezone;
-    // 设置dayjs默认时区
-    setDefaultTimezone(timezone);
-    // 保存用户的时区设置
-    await setUserTimezoneApi(timezone);
+    const prev = timezoneRef.value;
+    timezoneRef.value = timezone;
+    setDefaultTimezone(timezone);
+    try {
+      await setUserTimezoneApi(timezone);
+    } catch (err) {
+      // rollback on failure
+      timezoneRef.value = prev;
+      setDefaultTimezone(prev);
+      throw err;
+    }
   }
@@
   async function initTimezone() {
-    // 从服务器获取用户时区
-    const timezone = await getUserTimezoneApi();
-    if (timezone) {
-      timezoneRef.value = timezone;
-      // 设置dayjs默认时区
-      setDefaultTimezone(timezone);
-    }
+    const snapshot = timezoneRef.value;
+    try {
+      const timezone = await getUserTimezoneApi();
+      if (timezone && timezoneRef.value === snapshot) {
+        timezoneRef.value = timezone;
+        setDefaultTimezone(timezone);
+      }
+    } catch {
+      // ignore init errors; keep local guess
+    }
   }
@@
-  initTimezone();
+  initTimezone();

Also applies to: 21-25, 31-39, 41-41

🤖 Prompt for AI Agents
In apps/web-naive/src/store/user-profile.ts around lines 10-13 (and also
affecting 21-25, 31-39, 41), the timezone handling can race with async
init/save, doesn't apply the default TZ immediately, and lacks rollback on
failed saves; change the logic to: set the timezone ref synchronously to the
computed default immediately on creation, use a local incrementing
request/version token or abortable promise so any async initTimezone result is
ignored if a newer user selection happened, perform optimistic updates when
setTimezone is called (update ref/store and persist), and if the save/persist
call fails revert the ref/store to the prior value and surface the error; also
ensure initTimezone writes only when no user-selection/version supersedes it and
that all persistence calls return and handle errors for rollback.

Comment on lines +69 to +74
if (preferences.widget.timezone) {
list.push({
index: REFERENCE_VALUE + 40,
name: 'timezone',
});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Timezone slot is registered but never rendered in the template.

The timezone slot is correctly added to the rightSlots computed property, but there's no corresponding template rendering block in the <template> section (lines 150-176). This means the timezone widget will never be displayed.

Add the timezone template block after the language-toggle section:

         <template v-else-if="slot.name === 'language-toggle'">
           <LanguageToggle class="mr-1" />
         </template>
+        <template v-else-if="slot.name === 'timezone'">
+          <slot name="timezone"></slot>
+        </template>
         <template v-else-if="slot.name === 'fullscreen'">
           <VbenFullScreen class="mr-1" />
         </template>

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In packages/effects/layouts/src/basic/header/header.vue around lines 69 and
150-176, the computed rightSlots registers a timezone entry but the template
never renders it; add a template block immediately after the language-toggle
block that conditionally renders the timezone slot when
preferences.widget.timezone is truthy, using the same wrapper structure/classes
as the other widgets and the named slot "timezone" so the registered slot
content is actually displayed.

@@ -0,0 +1,89 @@
<script setup lang="ts">
import type { ExtendedModalApi } from '@vben-core/popup-ui';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Type alignment: ExtendedModalApi must match consumers.

Parents import ExtendedModalApi from '@vben/common-ui' while this component uses '@vben-core/popup-ui'. Unify on one (recommend popup-ui everywhere, since useVbenModal comes from it), or re-export the type from a shared package.


🏁 Script executed:

#!/bin/bash
# Where ExtendedModalApi is imported
rg -nP "ExtendedModalApi" -C1 --type=ts --type=vue

Length of output: 27


🏁 Script executed:

#!/bin/bash
# Search for ExtendedModalApi imports without type restrictions
rg -nP "ExtendedModalApi" -C2 -g "*.{ts,tsx,js,jsx,vue}"

Length of output: 6115


🏁 Script executed:

#!/bin/bash
# Find where @vben/common-ui is located and check exports
fd -t f "package.json" -x grep -l "common-ui" {} \;

Length of output: 174


🏁 Script executed:

#!/bin/bash
# Search for ExtendedModalApi exports (not just imports)
rg -nP "export.*ExtendedModalApi|export.*from.*ExtendedModalApi" -g "*.{ts,tsx,js,jsx}"

Length of output: 97


🏁 Script executed:

#!/bin/bash
# Find main/index exports from @vben/common-ui
fd -t f "index.ts\|index.js" -path "*packages/effects/common-ui*"

Length of output: 168


🏁 Script executed:

#!/bin/bash
# Check common-ui exports for ExtendedModalApi
rg -nP "ExtendedModalApi" -g "*.{ts,tsx,js,jsx}" "packages/effects/common-ui/"

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Check common-ui package.json for dependencies
cat packages/effects/common-ui/package.json

Length of output: 1513


🏁 Script executed:

#!/bin/bash
# Check main index file from @vben/common-ui
cat packages/effects/common-ui/src/index.ts

Length of output: 51


🏁 Script executed:

#!/bin/bash
# List structure of common-ui/src
find packages/effects/common-ui/src -name "*.ts" -type f | head -20

Length of output: 1228


🏁 Script executed:

#!/bin/bash
# Check ui directory exports from common-ui
cat packages/effects/common-ui/src/ui/index.ts

Length of output: 115


🏁 Script executed:

#!/bin/bash
# Double-check: does common-ui actually export ExtendedModalApi anywhere?
rg -nP "ExtendedModalApi" packages/effects/common-ui/

Length of output: 0


Fix parent layout imports: ExtendedModalApi unavailable from @vben/common-ui.

Parents (apps/web-{ele,antd,naive}/src/layouts/basic.vue) import ExtendedModalApi from '@vben/common-ui', but this type is not exported by that package—it is defined only in @vben-core/popup-ui. The timezone-button.vue component correctly imports from @vben-core/popup-ui.

Either:

  1. Update parents to import from @vben-core/popup-ui, or
  2. Re-export ExtendedModalApi from @vben/common-ui's index
🤖 Prompt for AI Agents
In packages/effects/layouts/src/widgets/timezone/timezone-button.vue around line
2, parents currently import ExtendedModalApi from @vben/common-ui but that type
is only defined in @vben-core/popup-ui; fix by updating parent layout imports
(apps/web-{ele,antd,naive}/src/layouts/basic.vue) to import ExtendedModalApi
directly from '@vben-core/popup-ui' (or alternatively add a re-export of
ExtendedModalApi from the @vben/common-ui index) so the type resolves correctly.

Comment on lines 45 to 51
const timezoneValue = ref(props.timezone);
watch(
() => props.timezone,
(newTimezone) => {
timezoneValue.value = newTimezone;
},
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Ensure timezoneValue is always a string (unwrap incoming refs).

Avoid ref-of-ref when parent passes a Ref. Also keep in sync on prop change.

-const timezoneValue = ref(props.timezone);
+const timezoneValue = ref<string | undefined>(unref(props.timezone));
 watch(
   () => props.timezone,
   (newTimezone) => {
-    timezoneValue.value = newTimezone;
+    timezoneValue.value = unref(newTimezone);
   },
 );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const timezoneValue = ref(props.timezone);
watch(
() => props.timezone,
(newTimezone) => {
timezoneValue.value = newTimezone;
},
);
const timezoneValue = ref<string | undefined>(unref(props.timezone));
watch(
() => props.timezone,
(newTimezone) => {
timezoneValue.value = unref(newTimezone);
},
);
🤖 Prompt for AI Agents
In packages/effects/layouts/src/widgets/timezone/timezone-button.vue around
lines 45 to 51, props.timezone may be a plain string or a Ref, causing a
ref-of-ref; ensure timezoneValue is always a simple string by unwrapping
incoming refs when initializing and updating it. Initialize timezoneValue with
ref(String(unref(props.timezone) ?? '')), and in the watcher set
timezoneValue.value = String(unref(newTimezone) ?? ''); this prevents nested
refs and keeps the value synchronized with prop changes.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (4)
apps/web-ele/src/store/user-profile.ts (2)

31-39: Add error handling for timezone initialization.

Missing error handling could lead to unhandled promise rejections if the API call fails.

  async function initTimezone() {
-   // 从服务器获取用户时区
-   const timezone = await getUserTimezoneApi();
-   if (timezone) {
-     timezoneRef.value = timezone;
-     // 设置dayjs默认时区
-     setDefaultTimezone(timezone);
-   }
+   try {
+     // 从服务器获取用户时区
+     const timezone = await getUserTimezoneApi();
+     if (timezone) {
+       timezoneRef.value = timezone;
+       // 设置dayjs默认时区
+       setDefaultTimezone(timezone);
+     }
+   } catch (error) {
+     console.error('Failed to initialize timezone:', error);
+     // Fallback to browser timezone already set in timezoneRef initialization
+   }
  }

19-25: Add error handling for timezone persistence.

The function now correctly calls the API before updating local state, which is an improvement. However, error handling is still missing. If setUserTimezoneApi fails, the error will propagate silently without logging.

Apply this diff to add error handling:

  async function setTimezone(timezone: string) {
-   // 保存用户的时区设置
-   await setUserTimezoneApi(timezone);
-   timezoneRef.value = timezone;
-   // 设置dayjs默认时区
-   setDefaultTimezone(timezone);
+   try {
+     // 保存用户的时区设置
+     await setUserTimezoneApi(timezone);
+     timezoneRef.value = timezone;
+     // 设置dayjs默认时区
+     setDefaultTimezone(timezone);
+   } catch (error) {
+     console.error('Failed to set timezone:', error);
+     throw error;
+   }
  }
packages/effects/layouts/src/widgets/timezone/timezone-button.vue (1)

45-51: Normalize timezoneValue to a plain string; avoid ref-of-ref and undefined.

Initialize and sync as a string to prevent v-model edge cases and nested refs.

-const timezoneValue = ref<string | undefined>(unref(props.timezone));
+const timezoneValue = ref<string>(String(unref(props.timezone) ?? ''));
 watch(
   () => props.timezone,
   (newTimezone) => {
-    timezoneValue.value = unref(newTimezone);
+    timezoneValue.value = String(unref(newTimezone) ?? '');
   },
 );
apps/web-antd/src/layouts/basic.vue (1)

2-2: Wrong source for ExtendedModalApi — switch to popup-ui.

@vben/common-ui does not export ExtendedModalApi; use @vben-core/popup-ui to match the widget and avoid TS errors.

-import type { ExtendedModalApi } from '@vben/common-ui';
+import type { ExtendedModalApi } from '@vben-core/popup-ui';
#!/bin/bash
# Verify there are no remaining imports from @vben/common-ui for ExtendedModalApi
rg -nP "import\s+type\s+\{\s*ExtendedModalApi\s*\}\s+from\s+'@vben/common-ui'" -g "apps/**/layouts/**.vue" -S
🧹 Nitpick comments (6)
packages/effects/layouts/src/widgets/timezone/timezone-button.vue (3)

69-79: Improve a11y: sanitize IDs and link label via :for.

Timezone strings contain slashes; prefer safe IDs and associate label.

+const toId = (tz: string) => `tz-${tz.replace(/[^A-Za-z0-9_-]/g, '-')}`;

(Place in <script setup>)

-            <RadioGroupItem :id="item" :value="item" />
-            <label class="cursor-pointer">{{ item }}</label>
+            <RadioGroupItem :id="toId(item)" :value="item" />
+            <label class="cursor-pointer" :for="toId(item)">{{ item }}</label>

85-89: Fix style class mismatch.

Template uses .timezone-container but CSS targets .container. Align them.

-<style scoped>
-.container {
-  padding-left: 20px;
-}
-</style>
+<style scoped>
+.timezone-container {
+  padding-left: 20px;
+}
+</style>

52-55: Emit 'change' only if consumed (or document it).

Parent in apps/web-antd/basic.vue doesn't listen to change; either remove emit to avoid confusion or ensure parent registers @change.

Do you intend consumers to react instantly on selection (before OK)? If yes, add @change in parents; otherwise, drop the emit here.

apps/web-antd/src/layouts/basic.vue (3)

71-76: Harden options mapping: filter invalids and dedupe.

APIs may return null/duplicate entries; keep string[] invariant.

-onMounted(async () => {
-  timezoneOptions.value = ((await getTimezoneOptionsApi()) || []).map(
-    (item) => item.timezone,
-  );
-});
+onMounted(async () => {
+  const list = (await getTimezoneOptionsApi()) ?? [];
+  timezoneOptions.value = Array.from(
+    new Set(
+      list
+        .map((item) => item?.timezone)
+        .filter((tz): tz is string => typeof tz === 'string' && tz.length > 0),
+    ),
+  );
+});

77-92: Surface errors to users when setTimezone fails.

Add an error toast in the catch to improve UX.

 try {
   modalApi.setState({ confirmLoading: true });
   await userProfileStore.setTimezone(timezone);
   message.success($t('ui.widgets.timezone.setSuccess'));
   modalApi.close();
+} catch (err) {
+  message.error(($t('ui.error.operationFailed') as string) || 'Failed to set timezone');
 } finally {
   modalApi.setState({ confirmLoading: false });
 }

181-188: Remove stray attribute on TimezoneButton.

name="out" isn’t a declared prop; it bubbles to DOM. Drop it unless required.

-      <TimezoneButton
+      <TimezoneButton
         :ok-handler="handleSetTimezone"
         :timezone="computedTimezone"
         :timezone-options="timezoneOptions"
-        name="out"
       />
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0a8339a and b029f77.

⛔ Files ignored due to path filters (1)
  • packages/@core/preferences/__tests__/__snapshots__/config.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (9)
  • apps/backend-mock/utils/timezone-utils.ts (1 hunks)
  • apps/web-antd/src/layouts/basic.vue (4 hunks)
  • apps/web-antd/src/store/user-profile.ts (1 hunks)
  • apps/web-ele/src/layouts/basic.vue (4 hunks)
  • apps/web-ele/src/store/user-profile.ts (1 hunks)
  • apps/web-naive/src/layouts/basic.vue (4 hunks)
  • apps/web-naive/src/store/user-profile.ts (1 hunks)
  • packages/effects/layouts/src/widgets/timezone/timezone-button.vue (1 hunks)
  • packages/effects/plugins/src/echarts/use-echarts.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • apps/web-naive/src/store/user-profile.ts
  • apps/web-ele/src/layouts/basic.vue
  • apps/web-antd/src/store/user-profile.ts
  • apps/web-naive/src/layouts/basic.vue
🧰 Additional context used
🧬 Code graph analysis (2)
apps/backend-mock/utils/timezone-utils.ts (1)
packages/@core/base/shared/src/utils/date.ts (1)
  • getTimezone (45-47)
apps/web-ele/src/store/user-profile.ts (2)
packages/@core/base/shared/src/utils/date.ts (2)
  • getTimezone (45-47)
  • setDefaultTimezone (37-39)
apps/web-ele/src/api/core/user-profile.ts (2)
  • setUserTimezoneApi (21-23)
  • getUserTimezoneApi (14-16)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Lint (windows-latest)
  • GitHub Check: Test (windows-latest)
  • GitHub Check: post-update (windows-latest)
  • GitHub Check: post-update (ubuntu-latest)
🔇 Additional comments (5)
packages/effects/plugins/src/echarts/use-echarts.ts (1)

70-73: Trailing comma added—unrelated to timezone feature.

The trailing comma is syntactically valid and follows modern formatting conventions. However, this change appears unrelated to the PR's stated objective of adding timezone support.

apps/backend-mock/utils/timezone-utils.ts (1)

1-9: LGTM! Clean mock implementation.

The previous debug logging issue has been resolved. The implementation is clean and appropriate for a mock backend utility.

apps/web-ele/src/store/user-profile.ts (2)

1-12: LGTM: Solid initialization with fallback.

The import structure and timezone initialization logic are well-designed. The fallback chain ensures a timezone is always available, even if getTimezone() returns undefined.


43-56: LGTM: Proper store setup and HMR support.

The store return statement correctly exposes the timezone state and actions. HMR support is properly configured for development experience.

apps/web-antd/src/layouts/basic.vue (1)

68-70: Nice fix: avoid nested Ref for timezone.

Using unref(userProfileStore.timezone) ensures a plain string for the child prop.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
packages/effects/layouts/src/widgets/timezone/timezone-button.vue (1)

69-74: Potential redundant state update from v-model and click handler.

The RadioGroup at line 69 is bound with v-model="timezoneValue", which automatically updates timezoneValue when a RadioGroupItem is selected. The @click="handleClickItem(item)" handler at line 74 also manually updates timezoneValue.value = timezone. This causes the value to be set twice for each selection.

If you want the change event to emit immediately on selection, keep the click handler but remove the manual assignment inside handleClickItem since v-model handles it. If you want changes to apply only on modal confirmation, consider removing the immediate click handler and emit logic.

Apply this diff to remove the redundant manual assignment:

 const handleClickItem = (timezone: string) => {
-  timezoneValue.value = timezone;
   emit('change', timezone);
 };
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b029f77 and 61ce53b.

📒 Files selected for processing (1)
  • packages/effects/layouts/src/widgets/timezone/timezone-button.vue (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: post-update (ubuntu-latest)
  • GitHub Check: post-update (windows-latest)
  • GitHub Check: Lint (windows-latest)
  • GitHub Check: Test (windows-latest)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant