From 0e94ad36b580534877871ece247ed6085b5749ef Mon Sep 17 00:00:00 2001 From: Mohamed Bassem Date: Sun, 6 Jul 2025 18:26:41 +0000 Subject: feat: Add a new timezone user setting --- apps/web/app/settings/stats/page.tsx | 16 ++++++ apps/web/components/settings/UserOptions.tsx | 80 ++++++++++++++++++++++++++-- apps/web/lib/userSettings.tsx | 1 + 3 files changed, 94 insertions(+), 3 deletions(-) (limited to 'apps') diff --git a/apps/web/app/settings/stats/page.tsx b/apps/web/app/settings/stats/page.tsx index ab4fb22c..599e5362 100644 --- a/apps/web/app/settings/stats/page.tsx +++ b/apps/web/app/settings/stats/page.tsx @@ -110,6 +110,7 @@ function StatCard({ export default function StatsPage() { const { t } = useTranslation(); const { data: stats, isLoading } = api.users.stats.useQuery(); + const { data: userSettings } = api.users.settings.useQuery(); const maxHourlyActivity = useMemo(() => { if (!stats) return 0; @@ -176,6 +177,11 @@ export default function StatsPage() {

Insights into your bookmarking habits and collection + {userSettings?.timezone && userSettings.timezone !== "UTC" && ( + + Times shown in {userSettings.timezone} timezone + + )}

@@ -443,6 +449,11 @@ export default function StatsPage() { {t("settings.stats.activity_patterns.activity_by_hour")} + {userSettings?.timezone && userSettings.timezone !== "UTC" && ( + + ({userSettings.timezone}) + + )} @@ -462,6 +473,11 @@ export default function StatsPage() { {t("settings.stats.activity_patterns.activity_by_day")} + {userSettings?.timezone && userSettings.timezone !== "UTC" && ( + + ({userSettings.timezone}) + + )} diff --git a/apps/web/components/settings/UserOptions.tsx b/apps/web/components/settings/UserOptions.tsx index 4f18a2e3..02c27145 100644 --- a/apps/web/components/settings/UserOptions.tsx +++ b/apps/web/components/settings/UserOptions.tsx @@ -1,13 +1,13 @@ "use client"; -import { useEffect } from "react"; +import { useEffect, useState } from "react"; import { useClientConfig } from "@/lib/clientConfig"; import { useTranslation } from "@/lib/i18n/client"; import { useInterfaceLang } from "@/lib/userLocalSettings/bookmarksLayout"; import { updateInterfaceLang } from "@/lib/userLocalSettings/userLocalSettings"; import { useUserSettings } from "@/lib/userSettings"; import { zodResolver } from "@hookform/resolvers/zod"; -import { Archive, Bookmark, Globe } from "lucide-react"; +import { Archive, Bookmark, Clock, Globe } from "lucide-react"; import { useForm } from "react-hook-form"; import { z } from "zod"; @@ -71,6 +71,9 @@ export default function UserOptions() { }); }, }); + const [timezones, setTimezones] = useState< + { label: string; value: string }[] | null + >(null); const bookmarkClickActionTranslation: Record< ZUserSettings["bookmarkClickAction"], @@ -92,6 +95,39 @@ export default function UserOptions() { hide: t("settings.info.user_settings.archive_display_behaviour.hide"), }; + // Get all supported timezones and format them nicely + useEffect(() => { + try { + const browserTimezones = Intl.supportedValuesOf("timeZone"); + setTimezones( + browserTimezones + .map((tz) => { + // Create a more readable label by replacing underscores with spaces + // and showing the current time offset + const now = new Date(); + const formatter = new Intl.DateTimeFormat("en", { + timeZone: tz, + timeZoneName: "short", + }); + const parts = formatter.formatToParts(now); + const timeZoneName = + parts.find((part) => part.type === "timeZoneName")?.value || ""; + + // Format the timezone name for display + const displayName = tz.replace(/_/g, " ").replace("/", " / "); + const label = timeZoneName + ? `${displayName} (${timeZoneName})` + : displayName; + + return { value: tz, label }; + }) + .sort((a, b) => a.label.localeCompare(b.label)), + ); + } catch { + setTimezones(null); + } + }, []); + const form = useForm>({ resolver: zodResolver(zUserSettingsSchema), defaultValues: data, @@ -119,9 +155,47 @@ export default function UserOptions() { + ( +
+ + +
+ )} + /> + -
+
({ bookmarkClickAction: "open_original_link", archiveDisplayBehaviour: "show", + timezone: "UTC", }); export function UserSettingsContextProvider({ -- cgit v1.2.3-70-g09d2