Shared + migration: table user_preference (thème clair/sombre/système) (step 1/4)
- Modèle Prisma UserPreference (1-1 avec UserProfile, onDelete Cascade), enum ThemePreference (LIGHT/DARK/SYSTEM, défaut SYSTEM) - packages/shared: THEME_PREFERENCES/ThemePreference, PreferencesView, updatePreferencesSchema
This commit is contained in:
parent
db427a3f30
commit
e3811dc280
5 changed files with 67 additions and 0 deletions
|
|
@ -0,0 +1,13 @@
|
|||
-- CreateEnum
|
||||
CREATE TYPE "ThemePreference" AS ENUM ('LIGHT', 'DARK', 'SYSTEM');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "user_preference" (
|
||||
"user_profile_id" INTEGER NOT NULL,
|
||||
"theme" "ThemePreference" NOT NULL DEFAULT 'SYSTEM',
|
||||
|
||||
CONSTRAINT "user_preference_pkey" PRIMARY KEY ("user_profile_id")
|
||||
);
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "user_preference" ADD CONSTRAINT "user_preference_user_profile_id_fkey" FOREIGN KEY ("user_profile_id") REFERENCES "user_profiles"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
|
@ -98,10 +98,36 @@ model UserProfile {
|
|||
/// a time — but Prisma models the admin side of a one-to-many FK as a
|
||||
/// list regardless of that real-world cardinality.
|
||||
administeredHouses House[] @relation("HouseAdmin")
|
||||
preferences UserPreference?
|
||||
|
||||
@@map("user_profiles")
|
||||
}
|
||||
|
||||
/// Not in the original spec doc — personalization settings (theme for now,
|
||||
/// meant to grow), one row per profile, created on demand (see
|
||||
/// `preferences.service.ts`) rather than at signup — same "absent means the
|
||||
/// default" philosophy as `dietId`/allergies.
|
||||
enum ThemePreference {
|
||||
LIGHT
|
||||
DARK
|
||||
/// Follow the OS/browser preference — the default. Not "no row yet" (that
|
||||
/// case is handled in the service layer) but an explicit choice to track
|
||||
/// the system, distinguishable from a user who hasn't decided yet if this
|
||||
/// model ever needs that distinction.
|
||||
SYSTEM
|
||||
}
|
||||
|
||||
model UserPreference {
|
||||
/// Both the primary key and the FK — a strict 1-1 with UserProfile, no
|
||||
/// separate auto-incrementing id (a profile has at most one preferences row).
|
||||
userProfileId Int @id @map("user_profile_id")
|
||||
theme ThemePreference @default(SYSTEM)
|
||||
|
||||
userProfile UserProfile @relation(fields: [userProfileId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("user_preference")
|
||||
}
|
||||
|
||||
/// Explicit join table for the user_profiles <-> allergy association
|
||||
/// (documented in the spec as a plain many-to-many, no extra fields).
|
||||
model UserProfileAllergy {
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@ export * from "./schemas/account.js";
|
|||
export * from "./schemas/auth.js";
|
||||
export * from "./schemas/household.js";
|
||||
export * from "./schemas/planning.js";
|
||||
export * from "./schemas/preferences.js";
|
||||
export * from "./schemas/profile.js";
|
||||
export * from "./tools/assert-is-never.js";
|
||||
export * from "./types/household.js";
|
||||
export * from "./types/planning.js";
|
||||
export * from "./types/preferences.js";
|
||||
export * from "./types/reference.js";
|
||||
export * from "./types/user-profile.js";
|
||||
|
|
|
|||
11
packages/shared/src/schemas/preferences.ts
Normal file
11
packages/shared/src/schemas/preferences.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { z } from "zod";
|
||||
import { THEME_PREFERENCES } from "../types/preferences.js";
|
||||
|
||||
// See schemas/auth.ts for the shared client/server validation rationale.
|
||||
|
||||
/** Payload accepted by `PATCH /preferences`. */
|
||||
export const updatePreferencesSchema = z.object({
|
||||
theme: z.enum(THEME_PREFERENCES),
|
||||
});
|
||||
/** Inferred TS type for {@link updatePreferencesSchema}'s validated output. */
|
||||
export type UpdatePreferencesInput = z.infer<typeof updatePreferencesSchema>;
|
||||
15
packages/shared/src/types/preferences.ts
Normal file
15
packages/shared/src/types/preferences.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* The 3 values a profile's theme preference can take — `SYSTEM` means "no
|
||||
* explicit choice, follow the OS/browser preference" (see `apps/web`'s
|
||||
* `ThemeContext`, which maps this to *not* setting the `data-theme`
|
||||
* attribute at all, letting `_theme.scss`'s `prefers-color-scheme` media
|
||||
* query take over).
|
||||
*/
|
||||
export const THEME_PREFERENCES = ["LIGHT", "DARK", "SYSTEM"] as const;
|
||||
/** Inferred TS type for one {@link THEME_PREFERENCES} member. */
|
||||
export type ThemePreference = (typeof THEME_PREFERENCES)[number];
|
||||
|
||||
/** A profile's personalization preferences, as returned by `GET /preferences` / `PATCH /preferences`. */
|
||||
export interface PreferencesView {
|
||||
theme: ThemePreference;
|
||||
}
|
||||
Loading…
Reference in a new issue