Refactor admin preferences management to use global site preferences, update UI components for better user experience, and implement image selection for background settings.

This commit is contained in:
Julien Froidefond
2025-12-09 08:37:52 +01:00
parent 4486f305f2
commit 8c326bdd20
21 changed files with 1853 additions and 199 deletions

View File

@@ -32,3 +32,8 @@ export type UserPreferences = Prisma.UserPreferencesModel
*
*/
export type Event = Prisma.EventModel
/**
* Model SitePreferences
*
*/
export type SitePreferences = Prisma.SitePreferencesModel

View File

@@ -54,3 +54,8 @@ export type UserPreferences = Prisma.UserPreferencesModel
*
*/
export type Event = Prisma.EventModel
/**
* Model SitePreferences
*
*/
export type SitePreferences = Prisma.SitePreferencesModel

View File

@@ -20,7 +20,7 @@ const config: runtime.GetPrismaClientConfig = {
"clientVersion": "7.1.0",
"engineVersion": "ab635e6b9d606fa5c8fb8b1a7f909c3c3c1c98ba",
"activeProvider": "sqlite",
"inlineSchema": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\ngenerator client {\n provider = \"prisma-client\"\n output = \"./generated/prisma\"\n}\n\ndatasource db {\n provider = \"sqlite\"\n}\n\nenum Role {\n USER\n ADMIN\n}\n\nenum EventType {\n SUMMIT\n LAUNCH\n FESTIVAL\n COMPETITION\n}\n\nenum EventStatus {\n UPCOMING\n LIVE\n PAST\n}\n\nmodel User {\n id String @id @default(cuid())\n email String @unique\n password String\n username String @unique\n role Role @default(USER)\n score Int @default(0)\n level Int @default(1)\n hp Int @default(1000)\n maxHp Int @default(1000)\n xp Int @default(0)\n maxXp Int @default(5000)\n avatar String?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n preferences UserPreferences?\n\n @@index([score])\n @@index([email])\n}\n\nmodel UserPreferences {\n id String @id @default(cuid())\n userId String @unique\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n // Background images for each page\n homeBackground String?\n eventsBackground String?\n leaderboardBackground String?\n\n // Other UI preferences can be added here\n theme String? @default(\"default\")\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Event {\n id String @id @default(cuid())\n date String\n name String\n description String\n type EventType\n status EventStatus\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([status])\n @@index([date])\n}\n",
"inlineSchema": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\ngenerator client {\n provider = \"prisma-client\"\n output = \"./generated/prisma\"\n}\n\ndatasource db {\n provider = \"sqlite\"\n}\n\nenum Role {\n USER\n ADMIN\n}\n\nenum EventType {\n SUMMIT\n LAUNCH\n FESTIVAL\n COMPETITION\n}\n\nenum EventStatus {\n UPCOMING\n LIVE\n PAST\n}\n\nmodel User {\n id String @id @default(cuid())\n email String @unique\n password String\n username String @unique\n role Role @default(USER)\n score Int @default(0)\n level Int @default(1)\n hp Int @default(1000)\n maxHp Int @default(1000)\n xp Int @default(0)\n maxXp Int @default(5000)\n avatar String?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n preferences UserPreferences?\n\n @@index([score])\n @@index([email])\n}\n\nmodel UserPreferences {\n id String @id @default(cuid())\n userId String @unique\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n // Background images for each page\n homeBackground String?\n eventsBackground String?\n leaderboardBackground String?\n\n // Other UI preferences can be added here\n theme String? @default(\"default\")\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Event {\n id String @id @default(cuid())\n date String\n name String\n description String\n type EventType\n status EventStatus\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([status])\n @@index([date])\n}\n\nmodel SitePreferences {\n id String @id @default(\"global\")\n homeBackground String?\n eventsBackground String?\n leaderboardBackground String?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n",
"runtimeDataModel": {
"models": {},
"enums": {},
@@ -28,7 +28,7 @@ const config: runtime.GetPrismaClientConfig = {
}
}
config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"password\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"username\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"role\",\"kind\":\"enum\",\"type\":\"Role\"},{\"name\":\"score\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"level\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"hp\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"maxHp\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"xp\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"maxXp\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"avatar\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"preferences\",\"kind\":\"object\",\"type\":\"UserPreferences\",\"relationName\":\"UserToUserPreferences\"}],\"dbName\":null},\"UserPreferences\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"UserToUserPreferences\"},{\"name\":\"homeBackground\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"eventsBackground\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"leaderboardBackground\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"theme\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Event\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"date\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"enum\",\"type\":\"EventType\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"EventStatus\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}")
config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"password\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"username\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"role\",\"kind\":\"enum\",\"type\":\"Role\"},{\"name\":\"score\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"level\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"hp\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"maxHp\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"xp\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"maxXp\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"avatar\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"preferences\",\"kind\":\"object\",\"type\":\"UserPreferences\",\"relationName\":\"UserToUserPreferences\"}],\"dbName\":null},\"UserPreferences\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"UserToUserPreferences\"},{\"name\":\"homeBackground\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"eventsBackground\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"leaderboardBackground\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"theme\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Event\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"date\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"enum\",\"type\":\"EventType\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"EventStatus\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"SitePreferences\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"homeBackground\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"eventsBackground\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"leaderboardBackground\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}")
async function decodeBase64AsWasm(wasmBase64: string): Promise<WebAssembly.Module> {
const { Buffer } = await import('node:buffer')
@@ -203,6 +203,16 @@ export interface PrismaClient<
* ```
*/
get event(): Prisma.EventDelegate<ExtArgs, { omit: OmitOpts }>;
/**
* `prisma.sitePreferences`: Exposes CRUD operations for the **SitePreferences** model.
* Example usage:
* ```ts
* // Fetch zero or more SitePreferences
* const sitePreferences = await prisma.sitePreferences.findMany()
* ```
*/
get sitePreferences(): Prisma.SitePreferencesDelegate<ExtArgs, { omit: OmitOpts }>;
}
export function getPrismaClientClass(): PrismaClientConstructor {

View File

@@ -386,7 +386,8 @@ type FieldRefInputType<Model, FieldType> = Model extends never ? never : FieldRe
export const ModelName = {
User: 'User',
UserPreferences: 'UserPreferences',
Event: 'Event'
Event: 'Event',
SitePreferences: 'SitePreferences'
} as const
export type ModelName = (typeof ModelName)[keyof typeof ModelName]
@@ -402,7 +403,7 @@ export type TypeMap<ExtArgs extends runtime.Types.Extensions.InternalArgs = runt
omit: GlobalOmitOptions
}
meta: {
modelProps: "user" | "userPreferences" | "event"
modelProps: "user" | "userPreferences" | "event" | "sitePreferences"
txIsolationLevel: TransactionIsolationLevel
}
model: {
@@ -628,6 +629,80 @@ export type TypeMap<ExtArgs extends runtime.Types.Extensions.InternalArgs = runt
}
}
}
SitePreferences: {
payload: Prisma.$SitePreferencesPayload<ExtArgs>
fields: Prisma.SitePreferencesFieldRefs
operations: {
findUnique: {
args: Prisma.SitePreferencesFindUniqueArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$SitePreferencesPayload> | null
}
findUniqueOrThrow: {
args: Prisma.SitePreferencesFindUniqueOrThrowArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$SitePreferencesPayload>
}
findFirst: {
args: Prisma.SitePreferencesFindFirstArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$SitePreferencesPayload> | null
}
findFirstOrThrow: {
args: Prisma.SitePreferencesFindFirstOrThrowArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$SitePreferencesPayload>
}
findMany: {
args: Prisma.SitePreferencesFindManyArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$SitePreferencesPayload>[]
}
create: {
args: Prisma.SitePreferencesCreateArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$SitePreferencesPayload>
}
createMany: {
args: Prisma.SitePreferencesCreateManyArgs<ExtArgs>
result: BatchPayload
}
createManyAndReturn: {
args: Prisma.SitePreferencesCreateManyAndReturnArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$SitePreferencesPayload>[]
}
delete: {
args: Prisma.SitePreferencesDeleteArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$SitePreferencesPayload>
}
update: {
args: Prisma.SitePreferencesUpdateArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$SitePreferencesPayload>
}
deleteMany: {
args: Prisma.SitePreferencesDeleteManyArgs<ExtArgs>
result: BatchPayload
}
updateMany: {
args: Prisma.SitePreferencesUpdateManyArgs<ExtArgs>
result: BatchPayload
}
updateManyAndReturn: {
args: Prisma.SitePreferencesUpdateManyAndReturnArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$SitePreferencesPayload>[]
}
upsert: {
args: Prisma.SitePreferencesUpsertArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$SitePreferencesPayload>
}
aggregate: {
args: Prisma.SitePreferencesAggregateArgs<ExtArgs>
result: runtime.Types.Utils.Optional<Prisma.AggregateSitePreferences>
}
groupBy: {
args: Prisma.SitePreferencesGroupByArgs<ExtArgs>
result: runtime.Types.Utils.Optional<Prisma.SitePreferencesGroupByOutputType>[]
}
count: {
args: Prisma.SitePreferencesCountArgs<ExtArgs>
result: runtime.Types.Utils.Optional<Prisma.SitePreferencesCountAggregateOutputType> | number
}
}
}
}
} & {
other: {
@@ -712,6 +787,18 @@ export const EventScalarFieldEnum = {
export type EventScalarFieldEnum = (typeof EventScalarFieldEnum)[keyof typeof EventScalarFieldEnum]
export const SitePreferencesScalarFieldEnum = {
id: 'id',
homeBackground: 'homeBackground',
eventsBackground: 'eventsBackground',
leaderboardBackground: 'leaderboardBackground',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
} as const
export type SitePreferencesScalarFieldEnum = (typeof SitePreferencesScalarFieldEnum)[keyof typeof SitePreferencesScalarFieldEnum]
export const SortOrder = {
asc: 'asc',
desc: 'desc'
@@ -880,6 +967,7 @@ export type GlobalOmitConfig = {
user?: Prisma.UserOmit
userPreferences?: Prisma.UserPreferencesOmit
event?: Prisma.EventOmit
sitePreferences?: Prisma.SitePreferencesOmit
}
/* Types for Logging */

View File

@@ -53,7 +53,8 @@ export const AnyNull = runtime.AnyNull
export const ModelName = {
User: 'User',
UserPreferences: 'UserPreferences',
Event: 'Event'
Event: 'Event',
SitePreferences: 'SitePreferences'
} as const
export type ModelName = (typeof ModelName)[keyof typeof ModelName]
@@ -117,6 +118,18 @@ export const EventScalarFieldEnum = {
export type EventScalarFieldEnum = (typeof EventScalarFieldEnum)[keyof typeof EventScalarFieldEnum]
export const SitePreferencesScalarFieldEnum = {
id: 'id',
homeBackground: 'homeBackground',
eventsBackground: 'eventsBackground',
leaderboardBackground: 'leaderboardBackground',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
} as const
export type SitePreferencesScalarFieldEnum = (typeof SitePreferencesScalarFieldEnum)[keyof typeof SitePreferencesScalarFieldEnum]
export const SortOrder = {
asc: 'asc',
desc: 'desc'

View File

@@ -11,4 +11,5 @@
export type * from './models/User'
export type * from './models/UserPreferences'
export type * from './models/Event'
export type * from './models/SitePreferences'
export type * from './commonInputTypes'

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
-- CreateTable
CREATE TABLE "SitePreferences" (
"id" TEXT NOT NULL PRIMARY KEY DEFAULT 'global',
"homeBackground" TEXT,
"eventsBackground" TEXT,
"leaderboardBackground" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);

View File

@@ -79,3 +79,12 @@ model Event {
@@index([status])
@@index([date])
}
model SitePreferences {
id String @id @default("global")
homeBackground String?
eventsBackground String?
leaderboardBackground String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}