Add per-user clock style preference for the home status bar.
Original task #20: Let each user pick their own home-screen clock style (analog/digital/minimal/etc.), persisted on the user record and restored on login / other devices. Default = "full". Changes: - DB: added `clock_style varchar(30)` (nullable) to `users` (lib/db/src/schema/users.ts) and applied via direct ALTER TABLE (drizzle-kit push had unrelated interactive prompts about app_opens / user_sessions which were not safe to answer). - OpenAPI: added `ClockStyle` enum (full/digital/digital-no-seconds /analog/minimal), `UpdateClockStyleBody`, exposed `clockStyle` on AuthUser and UserProfile, and added PATCH /auth/me/clock-style. Regenerated typed client and zod schemas. - API: `buildAuthUser` and `buildUserProfile` include `clockStyle`; new authenticated endpoint updates the current user's style and returns the refreshed AuthUser. - Frontend: new `Clock` component (artifacts/teaboy-os/src/ components/clock.tsx) with five variants sharing a single `useNow` tick hook, plus an SVG analog clock; honors existing Latin-digit/locale formatting helpers. New `ClockStylePicker` (popover) shown in the status bar with a live preview for each option and optimistic update through the AuthUser query cache. - home.tsx replaces the hard-coded clock block with `<Clock>` driven by `user.clockStyle`; trigger button placed next to the language toggle. - i18n: added `home.clockStyle.label` and per-style option labels to en.json and ar.json. Verified via e2e: register → default "full" rendered → switch to analog → reload → analog persists → switch to minimal → time-only renders. RTL layout + Latin digits both correct after language toggle.
This commit is contained in:
@@ -65,6 +65,24 @@ export interface UpdateLanguageBody {
|
||||
language: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Per-user home-screen clock style preference
|
||||
*/
|
||||
export type ClockStyle = (typeof ClockStyle)[keyof typeof ClockStyle];
|
||||
|
||||
export const ClockStyle = {
|
||||
full: "full",
|
||||
digital: "digital",
|
||||
"digital-no-seconds": "digital-no-seconds",
|
||||
analog: "analog",
|
||||
minimal: "minimal",
|
||||
} as const;
|
||||
|
||||
export interface UpdateClockStyleBody {
|
||||
/** Clock style; pass null to clear and use the default */
|
||||
clockStyle: ClockStyle | null;
|
||||
}
|
||||
|
||||
export interface AuthUser {
|
||||
id: number;
|
||||
username: string;
|
||||
@@ -74,6 +92,7 @@ export interface AuthUser {
|
||||
/** @nullable */
|
||||
displayNameEn?: string | null;
|
||||
preferredLanguage: string;
|
||||
clockStyle?: ClockStyle | null;
|
||||
/** @nullable */
|
||||
avatarUrl?: string | null;
|
||||
isActive: boolean;
|
||||
@@ -90,6 +109,7 @@ export interface UserProfile {
|
||||
/** @nullable */
|
||||
displayNameEn?: string | null;
|
||||
preferredLanguage: string;
|
||||
clockStyle?: ClockStyle | null;
|
||||
/** @nullable */
|
||||
avatarUrl?: string | null;
|
||||
isActive: boolean;
|
||||
|
||||
Reference in New Issue
Block a user