Enhance user profiles with character class feature: Add character class field to user model and update related API routes, UI components, and validation logic. This update improves user profile customization and leaderboard entries by allowing users to select and display their character class.

This commit is contained in:
Julien Froidefond
2025-12-09 22:03:51 +01:00
parent 3a0dd57bb6
commit b245be3bf4
17 changed files with 438 additions and 25 deletions

View File

@@ -37,4 +37,3 @@ pnpm start
- React 18
- TypeScript
- Tailwind CSS

View File

@@ -15,6 +15,7 @@ export async function GET() {
level: true,
avatar: true,
bio: true,
characterClass: true,
},
});
@@ -27,6 +28,7 @@ export async function GET() {
level: number;
avatar: string | null;
bio: string | null;
characterClass: string | null;
},
index: number
) => ({
@@ -36,6 +38,7 @@ export async function GET() {
level: user.level,
avatar: user.avatar,
bio: user.bio,
characterClass: user.characterClass,
})
);

View File

@@ -1,6 +1,7 @@
import { NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
import { CharacterClass } from "@/prisma/generated/prisma/enums";
export async function GET() {
try {
@@ -18,6 +19,7 @@ export async function GET() {
username: true,
avatar: true,
bio: true,
characterClass: true,
hp: true,
maxHp: true,
xp: true,
@@ -51,7 +53,7 @@ export async function PUT(request: Request) {
}
const body = await request.json();
const { username, avatar, bio } = body;
const { username, avatar, bio, characterClass } = body;
// Validation
if (username !== undefined) {
@@ -101,8 +103,35 @@ export async function PUT(request: Request) {
}
}
// Validation characterClass
const validClasses = [
"WARRIOR",
"MAGE",
"ROGUE",
"RANGER",
"PALADIN",
"ENGINEER",
"MERCHANT",
"SCHOLAR",
"BERSERKER",
"NECROMANCER",
];
if (characterClass !== undefined && characterClass !== null) {
if (!validClasses.includes(characterClass)) {
return NextResponse.json(
{ error: "Classe de personnage invalide" },
{ status: 400 }
);
}
}
// Mettre à jour l'utilisateur
const updateData: { username?: string; avatar?: string | null; bio?: string | null } = {};
const updateData: {
username?: string;
avatar?: string | null;
bio?: string | null;
characterClass?: CharacterClass | null;
} = {};
if (username !== undefined) {
updateData.username = username.trim();
}
@@ -112,6 +141,9 @@ export async function PUT(request: Request) {
if (bio !== undefined) {
updateData.bio = bio.trim() || null;
}
if (characterClass !== undefined) {
updateData.characterClass = (characterClass as CharacterClass) || null;
}
const updatedUser = await prisma.user.update({
where: { id: session.user.id },
@@ -122,6 +154,7 @@ export async function PUT(request: Request) {
username: true,
avatar: true,
bio: true,
characterClass: true,
hp: true,
maxHp: true,
xp: true,

View File

@@ -10,6 +10,7 @@ interface LeaderboardEntry {
level: number;
avatar: string | null;
bio: string | null;
characterClass: string | null;
}
export default async function LeaderboardPage() {
@@ -25,6 +26,7 @@ export default async function LeaderboardPage() {
level: true,
avatar: true,
bio: true,
characterClass: true,
},
});
@@ -35,6 +37,7 @@ export default async function LeaderboardPage() {
level: user.level,
avatar: user.avatar,
bio: user.bio,
characterClass: user.characterClass,
}));
const backgroundImage = await getBackgroundImage(

View File

@@ -20,6 +20,7 @@ export default async function ProfilePage() {
username: true,
avatar: true,
bio: true,
characterClass: true,
hp: true,
maxHp: true,
xp: true,
@@ -34,13 +35,24 @@ export default async function ProfilePage() {
redirect("/login");
}
const backgroundImage = await getBackgroundImage("home", "/got-background.jpg");
const backgroundImage = await getBackgroundImage(
"home",
"/got-background.jpg"
);
// Convert Date to string for the component
const userProfile = {
...user,
createdAt: user.createdAt.toISOString(),
};
return (
<main className="min-h-screen bg-black relative">
<NavigationWrapper />
<ProfileForm initialProfile={user} backgroundImage={backgroundImage} />
<ProfileForm
initialProfile={userProfile}
backgroundImage={backgroundImage}
/>
</main>
);
}

View File

@@ -9,6 +9,7 @@ interface LeaderboardEntry {
level: number;
avatar?: string | null;
bio?: string | null;
characterClass?: string | null;
}
// Format number with consistent locale to avoid hydration mismatch
@@ -82,18 +83,80 @@ export default function Leaderboard() {
{entry.rank}
</span>
</div>
<div className="col-span-5 flex items-center relative group">
<div className="col-span-5 flex items-center gap-2 relative group">
<span className="font-bold text-pixel-gold cursor-pointer relative z-10">
{entry.username}
</span>
{entry.bio && (
{entry.characterClass && (
<span className="text-xs text-gray-400 uppercase tracking-wider">
[{entry.characterClass === "WARRIOR" && "⚔️ Guerrier"}
{entry.characterClass === "MAGE" && "🔮 Mage"}
{entry.characterClass === "ROGUE" && "🗡️ Voleur"}
{entry.characterClass === "RANGER" && "🏹 Rôdeur"}
{entry.characterClass === "PALADIN" && "🛡️ Paladin"}
{entry.characterClass === "ENGINEER" && "⚙️ Ingénieur"}
{entry.characterClass === "MERCHANT" && "💰 Marchand"}
{entry.characterClass === "SCHOLAR" && "📚 Érudit"}
{entry.characterClass === "BERSERKER" && "🔥 Berserker"}
{entry.characterClass === "NECROMANCER" &&
"💀 Nécromancien"}
]
</span>
)}
{(entry.bio || entry.characterClass) && (
<div className="absolute left-0 top-full mt-1 z-[100] w-72 p-4 bg-black border-2 border-pixel-gold/70 rounded-lg shadow-2xl opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 pointer-events-none">
<div className="text-xs text-pixel-gold uppercase tracking-widest mb-2 border-b border-pixel-gold/30 pb-1 font-bold">
Bio
</div>
<p className="text-sm text-gray-200 leading-relaxed whitespace-pre-wrap break-words">
{entry.bio}
</p>
{entry.characterClass && (
<div className="mb-3">
<div className="text-xs text-pixel-gold uppercase tracking-widest mb-1 font-bold">
Classe
</div>
<div className="text-sm text-gray-200 flex items-center gap-2">
<span>
{entry.characterClass === "WARRIOR" && "⚔️"}
{entry.characterClass === "MAGE" && "🔮"}
{entry.characterClass === "ROGUE" && "🗡️"}
{entry.characterClass === "RANGER" && "🏹"}
{entry.characterClass === "PALADIN" && "🛡️"}
{entry.characterClass === "ENGINEER" && "⚙️"}
{entry.characterClass === "MERCHANT" && "💰"}
{entry.characterClass === "SCHOLAR" && "📚"}
{entry.characterClass === "BERSERKER" && "🔥"}
{entry.characterClass === "NECROMANCER" && "💀"}
</span>
<span className="uppercase tracking-wider">
{entry.characterClass === "WARRIOR" && "Guerrier"}
{entry.characterClass === "MAGE" && "Mage"}
{entry.characterClass === "ROGUE" && "Voleur"}
{entry.characterClass === "RANGER" && "Rôdeur"}
{entry.characterClass === "PALADIN" && "Paladin"}
{entry.characterClass === "ENGINEER" &&
"Ingénieur"}
{entry.characterClass === "MERCHANT" &&
"Marchand"}
{entry.characterClass === "SCHOLAR" && "Érudit"}
{entry.characterClass === "BERSERKER" &&
"Berserker"}
{entry.characterClass === "NECROMANCER" &&
"Nécromancien"}
</span>
</div>
</div>
)}
{entry.bio && (
<>
{entry.characterClass && (
<div className="border-b border-pixel-gold/30 mb-3 pb-3"></div>
)}
<div>
<div className="text-xs text-pixel-gold uppercase tracking-widest mb-2 border-b border-pixel-gold/30 pb-1 font-bold">
Bio
</div>
<p className="text-sm text-gray-200 leading-relaxed whitespace-pre-wrap break-words">
{entry.bio}
</p>
</div>
</>
)}
</div>
)}
</div>

View File

@@ -7,6 +7,7 @@ interface LeaderboardEntry {
level: number;
avatar?: string | null;
bio?: string | null;
characterClass?: string | null;
}
interface LeaderboardSectionProps {
@@ -119,17 +120,77 @@ export default function LeaderboardSection({
>
{entry.username}
</span>
{entry.characterClass && (
<span className="text-xs text-gray-400 uppercase tracking-wider">
[{entry.characterClass === "WARRIOR" && "⚔️"}
{entry.characterClass === "MAGE" && "🔮"}
{entry.characterClass === "ROGUE" && "🗡️"}
{entry.characterClass === "RANGER" && "🏹"}
{entry.characterClass === "PALADIN" && "🛡️"}
{entry.characterClass === "ENGINEER" && "⚙️"}
{entry.characterClass === "MERCHANT" && "💰"}
{entry.characterClass === "SCHOLAR" && "📚"}
{entry.characterClass === "BERSERKER" && "🔥"}
{entry.characterClass === "NECROMANCER" && "💀"}]
</span>
)}
{entry.rank <= 3 && (
<span className="text-pixel-gold text-xs"></span>
)}
{entry.bio && (
{(entry.bio || entry.characterClass) && (
<div className="absolute left-0 top-full mt-1 z-[100] w-72 p-4 bg-black border-2 border-pixel-gold/70 rounded-lg shadow-2xl opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 pointer-events-none">
<div className="text-xs text-pixel-gold uppercase tracking-widest mb-2 border-b border-pixel-gold/30 pb-1 font-bold">
Bio
</div>
<p className="text-sm text-gray-200 leading-relaxed whitespace-pre-wrap break-words">
{entry.bio}
</p>
{entry.characterClass && (
<div className="mb-3">
<div className="text-xs text-pixel-gold uppercase tracking-widest mb-1 font-bold">
Classe
</div>
<div className="text-sm text-gray-200 flex items-center gap-2">
<span>
{entry.characterClass === "WARRIOR" && "⚔️"}
{entry.characterClass === "MAGE" && "🔮"}
{entry.characterClass === "ROGUE" && "🗡️"}
{entry.characterClass === "RANGER" && "🏹"}
{entry.characterClass === "PALADIN" && "🛡️"}
{entry.characterClass === "ENGINEER" && "⚙️"}
{entry.characterClass === "MERCHANT" && "💰"}
{entry.characterClass === "SCHOLAR" && "📚"}
{entry.characterClass === "BERSERKER" && "🔥"}
{entry.characterClass === "NECROMANCER" && "💀"}
</span>
<span className="uppercase tracking-wider">
{entry.characterClass === "WARRIOR" && "Guerrier"}
{entry.characterClass === "MAGE" && "Mage"}
{entry.characterClass === "ROGUE" && "Voleur"}
{entry.characterClass === "RANGER" && "Rôdeur"}
{entry.characterClass === "PALADIN" && "Paladin"}
{entry.characterClass === "ENGINEER" &&
"Ingénieur"}
{entry.characterClass === "MERCHANT" &&
"Marchand"}
{entry.characterClass === "SCHOLAR" && "Érudit"}
{entry.characterClass === "BERSERKER" &&
"Berserker"}
{entry.characterClass === "NECROMANCER" &&
"Nécromancien"}
</span>
</div>
</div>
)}
{entry.bio && (
<>
{entry.characterClass && (
<div className="border-b border-pixel-gold/30 mb-3 pb-3"></div>
)}
<div>
<div className="text-xs text-pixel-gold uppercase tracking-widest mb-2 border-b border-pixel-gold/30 pb-1 font-bold">
Bio
</div>
<p className="text-sm text-gray-200 leading-relaxed whitespace-pre-wrap break-words">
{entry.bio}
</p>
</div>
</>
)}
</div>
)}
</div>

View File

@@ -3,12 +3,26 @@
import { useState, useRef } from "react";
import { useRouter } from "next/navigation";
type CharacterClass =
| "WARRIOR"
| "MAGE"
| "ROGUE"
| "RANGER"
| "PALADIN"
| "ENGINEER"
| "MERCHANT"
| "SCHOLAR"
| "BERSERKER"
| "NECROMANCER"
| null;
interface UserProfile {
id: string;
email: string;
username: string;
avatar: string | null;
bio: string | null;
characterClass: CharacterClass;
hp: number;
maxHp: number;
xp: number;
@@ -40,6 +54,9 @@ export default function ProfileForm({
const [username, setUsername] = useState(initialProfile.username);
const [avatar, setAvatar] = useState<string | null>(initialProfile.avatar);
const [bio, setBio] = useState<string | null>(initialProfile.bio || null);
const [characterClass, setCharacterClass] = useState<CharacterClass>(
initialProfile.characterClass || null
);
const fileInputRef = useRef<HTMLInputElement>(null);
const [uploadingAvatar, setUploadingAvatar] = useState(false);
@@ -102,6 +119,7 @@ export default function ProfileForm({
username,
avatar,
bio,
characterClass,
}),
});
@@ -109,6 +127,7 @@ export default function ProfileForm({
const data = await response.json();
setProfile(data);
setBio(data.bio || null);
setCharacterClass(data.characterClass || null);
setSuccess("Profil mis à jour avec succès");
setTimeout(() => setSuccess(null), 3000);
} else {
@@ -338,6 +357,111 @@ export default function ProfileForm({
</p>
</div>
{/* Character Class Selection */}
<div>
<label className="block text-pixel-gold text-sm uppercase tracking-widest mb-3">
Classe de Personnage
</label>
<div className="grid grid-cols-2 md:grid-cols-3 gap-3">
{[
{
value: "WARRIOR",
name: "Guerrier",
icon: "⚔️",
desc: "Maître du combat au corps à corps",
},
{
value: "MAGE",
name: "Mage",
icon: "🔮",
desc: "Manipulateur des arcanes",
},
{
value: "ROGUE",
name: "Voleur",
icon: "🗡️",
desc: "Furtif et mortel",
},
{
value: "RANGER",
name: "Rôdeur",
icon: "🏹",
desc: "Chasseur des terres sauvages",
},
{
value: "PALADIN",
name: "Paladin",
icon: "🛡️",
desc: "Protecteur sacré",
},
{
value: "ENGINEER",
name: "Ingénieur",
icon: "⚙️",
desc: "Créateur d'artefacts",
},
{
value: "MERCHANT",
name: "Marchand",
icon: "💰",
desc: "Maître du commerce",
},
{
value: "SCHOLAR",
name: "Érudit",
icon: "📚",
desc: "Gardien du savoir",
},
{
value: "BERSERKER",
name: "Berserker",
icon: "🔥",
desc: "Rage destructrice",
},
{
value: "NECROMANCER",
name: "Nécromancien",
icon: "💀",
desc: "Maître des morts",
},
].map((cls) => (
<button
key={cls.value}
type="button"
onClick={() =>
setCharacterClass(cls.value as CharacterClass)
}
className={`p-4 border-2 rounded-lg text-left transition-all ${
characterClass === cls.value
? "border-pixel-gold bg-pixel-gold/20 shadow-lg shadow-pixel-gold/30"
: "border-pixel-gold/30 bg-black/40 hover:border-pixel-gold/50 hover:bg-black/60"
}`}
>
<div className="flex items-center gap-2 mb-1">
<span className="text-2xl">{cls.icon}</span>
<span
className={`font-bold text-sm uppercase tracking-wider ${
characterClass === cls.value
? "text-pixel-gold"
: "text-white"
}`}
>
{cls.name}
</span>
</div>
<p className="text-xs text-gray-400 leading-tight">
{cls.desc}
</p>
</button>
))}
</div>
{characterClass && (
<p className="text-pixel-gold text-xs mt-2 uppercase tracking-widest">
✓ Classe sélectionnée
</p>
)}
</div>
{/* Stats Display */}
<div className="border-t border-pixel-gold/20 pt-6">
<h3 className="text-pixel-gold text-sm uppercase tracking-widest mb-4">

View File

@@ -16,7 +16,7 @@ export async function getBackgroundImage(
const imageKey = `${page}Background` as keyof typeof sitePreferences;
const customImage = sitePreferences[imageKey];
return customImage || defaultImage;
return (customImage as string | null) || defaultImage;
} catch (error) {
console.error("Error fetching background image:", error);
return defaultImage;

View File

@@ -60,6 +60,13 @@ export type StringNullableFilter<$PrismaModel = never> = {
not?: Prisma.NestedStringNullableFilter<$PrismaModel> | string | null
}
export type EnumCharacterClassNullableFilter<$PrismaModel = never> = {
equals?: $Enums.CharacterClass | Prisma.EnumCharacterClassFieldRefInput<$PrismaModel> | null
in?: $Enums.CharacterClass[] | null
notIn?: $Enums.CharacterClass[] | null
not?: Prisma.NestedEnumCharacterClassNullableFilter<$PrismaModel> | $Enums.CharacterClass | null
}
export type DateTimeFilter<$PrismaModel = never> = {
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
in?: Date[] | string[]
@@ -136,6 +143,16 @@ export type StringNullableWithAggregatesFilter<$PrismaModel = never> = {
_max?: Prisma.NestedStringNullableFilter<$PrismaModel>
}
export type EnumCharacterClassNullableWithAggregatesFilter<$PrismaModel = never> = {
equals?: $Enums.CharacterClass | Prisma.EnumCharacterClassFieldRefInput<$PrismaModel> | null
in?: $Enums.CharacterClass[] | null
notIn?: $Enums.CharacterClass[] | null
not?: Prisma.NestedEnumCharacterClassNullableWithAggregatesFilter<$PrismaModel> | $Enums.CharacterClass | null
_count?: Prisma.NestedIntNullableFilter<$PrismaModel>
_min?: Prisma.NestedEnumCharacterClassNullableFilter<$PrismaModel>
_max?: Prisma.NestedEnumCharacterClassNullableFilter<$PrismaModel>
}
export type DateTimeWithAggregatesFilter<$PrismaModel = never> = {
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
in?: Date[] | string[]
@@ -230,6 +247,13 @@ export type NestedStringNullableFilter<$PrismaModel = never> = {
not?: Prisma.NestedStringNullableFilter<$PrismaModel> | string | null
}
export type NestedEnumCharacterClassNullableFilter<$PrismaModel = never> = {
equals?: $Enums.CharacterClass | Prisma.EnumCharacterClassFieldRefInput<$PrismaModel> | null
in?: $Enums.CharacterClass[] | null
notIn?: $Enums.CharacterClass[] | null
not?: Prisma.NestedEnumCharacterClassNullableFilter<$PrismaModel> | $Enums.CharacterClass | null
}
export type NestedDateTimeFilter<$PrismaModel = never> = {
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
in?: Date[] | string[]
@@ -323,6 +347,16 @@ export type NestedIntNullableFilter<$PrismaModel = never> = {
not?: Prisma.NestedIntNullableFilter<$PrismaModel> | number | null
}
export type NestedEnumCharacterClassNullableWithAggregatesFilter<$PrismaModel = never> = {
equals?: $Enums.CharacterClass | Prisma.EnumCharacterClassFieldRefInput<$PrismaModel> | null
in?: $Enums.CharacterClass[] | null
notIn?: $Enums.CharacterClass[] | null
not?: Prisma.NestedEnumCharacterClassNullableWithAggregatesFilter<$PrismaModel> | $Enums.CharacterClass | null
_count?: Prisma.NestedIntNullableFilter<$PrismaModel>
_min?: Prisma.NestedEnumCharacterClassNullableFilter<$PrismaModel>
_max?: Prisma.NestedEnumCharacterClassNullableFilter<$PrismaModel>
}
export type NestedDateTimeWithAggregatesFilter<$PrismaModel = never> = {
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
in?: Date[] | string[]

View File

@@ -34,3 +34,19 @@ export const EventStatus = {
} as const
export type EventStatus = (typeof EventStatus)[keyof typeof EventStatus]
export const CharacterClass = {
WARRIOR: 'WARRIOR',
MAGE: 'MAGE',
ROGUE: 'ROGUE',
RANGER: 'RANGER',
PALADIN: 'PALADIN',
ENGINEER: 'ENGINEER',
MERCHANT: 'MERCHANT',
SCHOLAR: 'SCHOLAR',
BERSERKER: 'BERSERKER',
NECROMANCER: 'NECROMANCER'
} as const
export type CharacterClass = (typeof CharacterClass)[keyof typeof CharacterClass]

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 bio String?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n preferences UserPreferences?\n eventRegistrations EventRegistration[]\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 registrations EventRegistration[]\n\n @@index([status])\n @@index([date])\n}\n\nmodel EventRegistration {\n id String @id @default(cuid())\n userId String\n eventId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n event Event @relation(fields: [eventId], references: [id], onDelete: Cascade)\n createdAt DateTime @default(now())\n\n @@unique([userId, eventId])\n @@index([userId])\n @@index([eventId])\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",
"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\nenum CharacterClass {\n WARRIOR\n MAGE\n ROGUE\n RANGER\n PALADIN\n ENGINEER\n MERCHANT\n SCHOLAR\n BERSERKER\n NECROMANCER\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 bio String?\n characterClass CharacterClass?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n preferences UserPreferences?\n eventRegistrations EventRegistration[]\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 registrations EventRegistration[]\n\n @@index([status])\n @@index([date])\n}\n\nmodel EventRegistration {\n id String @id @default(cuid())\n userId String\n eventId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n event Event @relation(fields: [eventId], references: [id], onDelete: Cascade)\n createdAt DateTime @default(now())\n\n @@unique([userId, eventId])\n @@index([userId])\n @@index([eventId])\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\":\"bio\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"preferences\",\"kind\":\"object\",\"type\":\"UserPreferences\",\"relationName\":\"UserToUserPreferences\"},{\"name\":\"eventRegistrations\",\"kind\":\"object\",\"type\":\"EventRegistration\",\"relationName\":\"EventRegistrationToUser\"}],\"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\"},{\"name\":\"registrations\",\"kind\":\"object\",\"type\":\"EventRegistration\",\"relationName\":\"EventToEventRegistration\"}],\"dbName\":null},\"EventRegistration\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"eventId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"EventRegistrationToUser\"},{\"name\":\"event\",\"kind\":\"object\",\"type\":\"Event\",\"relationName\":\"EventToEventRegistration\"},{\"name\":\"createdAt\",\"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\":{}}")
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\":\"bio\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"characterClass\",\"kind\":\"enum\",\"type\":\"CharacterClass\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"preferences\",\"kind\":\"object\",\"type\":\"UserPreferences\",\"relationName\":\"UserToUserPreferences\"},{\"name\":\"eventRegistrations\",\"kind\":\"object\",\"type\":\"EventRegistration\",\"relationName\":\"EventRegistrationToUser\"}],\"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\"},{\"name\":\"registrations\",\"kind\":\"object\",\"type\":\"EventRegistration\",\"relationName\":\"EventToEventRegistration\"}],\"dbName\":null},\"EventRegistration\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"eventId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"EventRegistrationToUser\"},{\"name\":\"event\",\"kind\":\"object\",\"type\":\"Event\",\"relationName\":\"EventToEventRegistration\"},{\"name\":\"createdAt\",\"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')

View File

@@ -828,6 +828,7 @@ export const UserScalarFieldEnum = {
maxXp: 'maxXp',
avatar: 'avatar',
bio: 'bio',
characterClass: 'characterClass',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
} as const
@@ -928,6 +929,13 @@ export type IntFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'In
/**
* Reference to a field of type 'CharacterClass'
*/
export type EnumCharacterClassFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'CharacterClass'>
/**
* Reference to a field of type 'DateTime'
*/

View File

@@ -85,6 +85,7 @@ export const UserScalarFieldEnum = {
maxXp: 'maxXp',
avatar: 'avatar',
bio: 'bio',
characterClass: 'characterClass',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
} as const

View File

@@ -58,6 +58,7 @@ export type UserMinAggregateOutputType = {
maxXp: number | null
avatar: string | null
bio: string | null
characterClass: $Enums.CharacterClass | null
createdAt: Date | null
updatedAt: Date | null
}
@@ -76,6 +77,7 @@ export type UserMaxAggregateOutputType = {
maxXp: number | null
avatar: string | null
bio: string | null
characterClass: $Enums.CharacterClass | null
createdAt: Date | null
updatedAt: Date | null
}
@@ -94,6 +96,7 @@ export type UserCountAggregateOutputType = {
maxXp: number
avatar: number
bio: number
characterClass: number
createdAt: number
updatedAt: number
_all: number
@@ -132,6 +135,7 @@ export type UserMinAggregateInputType = {
maxXp?: true
avatar?: true
bio?: true
characterClass?: true
createdAt?: true
updatedAt?: true
}
@@ -150,6 +154,7 @@ export type UserMaxAggregateInputType = {
maxXp?: true
avatar?: true
bio?: true
characterClass?: true
createdAt?: true
updatedAt?: true
}
@@ -168,6 +173,7 @@ export type UserCountAggregateInputType = {
maxXp?: true
avatar?: true
bio?: true
characterClass?: true
createdAt?: true
updatedAt?: true
_all?: true
@@ -273,6 +279,7 @@ export type UserGroupByOutputType = {
maxXp: number
avatar: string | null
bio: string | null
characterClass: $Enums.CharacterClass | null
createdAt: Date
updatedAt: Date
_count: UserCountAggregateOutputType | null
@@ -314,6 +321,7 @@ export type UserWhereInput = {
maxXp?: Prisma.IntFilter<"User"> | number
avatar?: Prisma.StringNullableFilter<"User"> | string | null
bio?: Prisma.StringNullableFilter<"User"> | string | null
characterClass?: Prisma.EnumCharacterClassNullableFilter<"User"> | $Enums.CharacterClass | null
createdAt?: Prisma.DateTimeFilter<"User"> | Date | string
updatedAt?: Prisma.DateTimeFilter<"User"> | Date | string
preferences?: Prisma.XOR<Prisma.UserPreferencesNullableScalarRelationFilter, Prisma.UserPreferencesWhereInput> | null
@@ -334,6 +342,7 @@ export type UserOrderByWithRelationInput = {
maxXp?: Prisma.SortOrder
avatar?: Prisma.SortOrderInput | Prisma.SortOrder
bio?: Prisma.SortOrderInput | Prisma.SortOrder
characterClass?: Prisma.SortOrderInput | Prisma.SortOrder
createdAt?: Prisma.SortOrder
updatedAt?: Prisma.SortOrder
preferences?: Prisma.UserPreferencesOrderByWithRelationInput
@@ -357,6 +366,7 @@ export type UserWhereUniqueInput = Prisma.AtLeast<{
maxXp?: Prisma.IntFilter<"User"> | number
avatar?: Prisma.StringNullableFilter<"User"> | string | null
bio?: Prisma.StringNullableFilter<"User"> | string | null
characterClass?: Prisma.EnumCharacterClassNullableFilter<"User"> | $Enums.CharacterClass | null
createdAt?: Prisma.DateTimeFilter<"User"> | Date | string
updatedAt?: Prisma.DateTimeFilter<"User"> | Date | string
preferences?: Prisma.XOR<Prisma.UserPreferencesNullableScalarRelationFilter, Prisma.UserPreferencesWhereInput> | null
@@ -377,6 +387,7 @@ export type UserOrderByWithAggregationInput = {
maxXp?: Prisma.SortOrder
avatar?: Prisma.SortOrderInput | Prisma.SortOrder
bio?: Prisma.SortOrderInput | Prisma.SortOrder
characterClass?: Prisma.SortOrderInput | Prisma.SortOrder
createdAt?: Prisma.SortOrder
updatedAt?: Prisma.SortOrder
_count?: Prisma.UserCountOrderByAggregateInput
@@ -403,6 +414,7 @@ export type UserScalarWhereWithAggregatesInput = {
maxXp?: Prisma.IntWithAggregatesFilter<"User"> | number
avatar?: Prisma.StringNullableWithAggregatesFilter<"User"> | string | null
bio?: Prisma.StringNullableWithAggregatesFilter<"User"> | string | null
characterClass?: Prisma.EnumCharacterClassNullableWithAggregatesFilter<"User"> | $Enums.CharacterClass | null
createdAt?: Prisma.DateTimeWithAggregatesFilter<"User"> | Date | string
updatedAt?: Prisma.DateTimeWithAggregatesFilter<"User"> | Date | string
}
@@ -421,6 +433,7 @@ export type UserCreateInput = {
maxXp?: number
avatar?: string | null
bio?: string | null
characterClass?: $Enums.CharacterClass | null
createdAt?: Date | string
updatedAt?: Date | string
preferences?: Prisma.UserPreferencesCreateNestedOneWithoutUserInput
@@ -441,6 +454,7 @@ export type UserUncheckedCreateInput = {
maxXp?: number
avatar?: string | null
bio?: string | null
characterClass?: $Enums.CharacterClass | null
createdAt?: Date | string
updatedAt?: Date | string
preferences?: Prisma.UserPreferencesUncheckedCreateNestedOneWithoutUserInput
@@ -461,6 +475,7 @@ export type UserUpdateInput = {
maxXp?: Prisma.IntFieldUpdateOperationsInput | number
avatar?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
bio?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
characterClass?: Prisma.NullableEnumCharacterClassFieldUpdateOperationsInput | $Enums.CharacterClass | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
preferences?: Prisma.UserPreferencesUpdateOneWithoutUserNestedInput
@@ -481,6 +496,7 @@ export type UserUncheckedUpdateInput = {
maxXp?: Prisma.IntFieldUpdateOperationsInput | number
avatar?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
bio?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
characterClass?: Prisma.NullableEnumCharacterClassFieldUpdateOperationsInput | $Enums.CharacterClass | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
preferences?: Prisma.UserPreferencesUncheckedUpdateOneWithoutUserNestedInput
@@ -501,6 +517,7 @@ export type UserCreateManyInput = {
maxXp?: number
avatar?: string | null
bio?: string | null
characterClass?: $Enums.CharacterClass | null
createdAt?: Date | string
updatedAt?: Date | string
}
@@ -519,6 +536,7 @@ export type UserUpdateManyMutationInput = {
maxXp?: Prisma.IntFieldUpdateOperationsInput | number
avatar?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
bio?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
characterClass?: Prisma.NullableEnumCharacterClassFieldUpdateOperationsInput | $Enums.CharacterClass | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
}
@@ -537,6 +555,7 @@ export type UserUncheckedUpdateManyInput = {
maxXp?: Prisma.IntFieldUpdateOperationsInput | number
avatar?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
bio?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
characterClass?: Prisma.NullableEnumCharacterClassFieldUpdateOperationsInput | $Enums.CharacterClass | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
}
@@ -555,6 +574,7 @@ export type UserCountOrderByAggregateInput = {
maxXp?: Prisma.SortOrder
avatar?: Prisma.SortOrder
bio?: Prisma.SortOrder
characterClass?: Prisma.SortOrder
createdAt?: Prisma.SortOrder
updatedAt?: Prisma.SortOrder
}
@@ -582,6 +602,7 @@ export type UserMaxOrderByAggregateInput = {
maxXp?: Prisma.SortOrder
avatar?: Prisma.SortOrder
bio?: Prisma.SortOrder
characterClass?: Prisma.SortOrder
createdAt?: Prisma.SortOrder
updatedAt?: Prisma.SortOrder
}
@@ -600,6 +621,7 @@ export type UserMinOrderByAggregateInput = {
maxXp?: Prisma.SortOrder
avatar?: Prisma.SortOrder
bio?: Prisma.SortOrder
characterClass?: Prisma.SortOrder
createdAt?: Prisma.SortOrder
updatedAt?: Prisma.SortOrder
}
@@ -638,6 +660,10 @@ export type NullableStringFieldUpdateOperationsInput = {
set?: string | null
}
export type NullableEnumCharacterClassFieldUpdateOperationsInput = {
set?: $Enums.CharacterClass | null
}
export type DateTimeFieldUpdateOperationsInput = {
set?: Date | string
}
@@ -684,6 +710,7 @@ export type UserCreateWithoutPreferencesInput = {
maxXp?: number
avatar?: string | null
bio?: string | null
characterClass?: $Enums.CharacterClass | null
createdAt?: Date | string
updatedAt?: Date | string
eventRegistrations?: Prisma.EventRegistrationCreateNestedManyWithoutUserInput
@@ -703,6 +730,7 @@ export type UserUncheckedCreateWithoutPreferencesInput = {
maxXp?: number
avatar?: string | null
bio?: string | null
characterClass?: $Enums.CharacterClass | null
createdAt?: Date | string
updatedAt?: Date | string
eventRegistrations?: Prisma.EventRegistrationUncheckedCreateNestedManyWithoutUserInput
@@ -738,6 +766,7 @@ export type UserUpdateWithoutPreferencesInput = {
maxXp?: Prisma.IntFieldUpdateOperationsInput | number
avatar?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
bio?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
characterClass?: Prisma.NullableEnumCharacterClassFieldUpdateOperationsInput | $Enums.CharacterClass | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
eventRegistrations?: Prisma.EventRegistrationUpdateManyWithoutUserNestedInput
@@ -757,6 +786,7 @@ export type UserUncheckedUpdateWithoutPreferencesInput = {
maxXp?: Prisma.IntFieldUpdateOperationsInput | number
avatar?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
bio?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
characterClass?: Prisma.NullableEnumCharacterClassFieldUpdateOperationsInput | $Enums.CharacterClass | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
eventRegistrations?: Prisma.EventRegistrationUncheckedUpdateManyWithoutUserNestedInput
@@ -776,6 +806,7 @@ export type UserCreateWithoutEventRegistrationsInput = {
maxXp?: number
avatar?: string | null
bio?: string | null
characterClass?: $Enums.CharacterClass | null
createdAt?: Date | string
updatedAt?: Date | string
preferences?: Prisma.UserPreferencesCreateNestedOneWithoutUserInput
@@ -795,6 +826,7 @@ export type UserUncheckedCreateWithoutEventRegistrationsInput = {
maxXp?: number
avatar?: string | null
bio?: string | null
characterClass?: $Enums.CharacterClass | null
createdAt?: Date | string
updatedAt?: Date | string
preferences?: Prisma.UserPreferencesUncheckedCreateNestedOneWithoutUserInput
@@ -830,6 +862,7 @@ export type UserUpdateWithoutEventRegistrationsInput = {
maxXp?: Prisma.IntFieldUpdateOperationsInput | number
avatar?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
bio?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
characterClass?: Prisma.NullableEnumCharacterClassFieldUpdateOperationsInput | $Enums.CharacterClass | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
preferences?: Prisma.UserPreferencesUpdateOneWithoutUserNestedInput
@@ -849,6 +882,7 @@ export type UserUncheckedUpdateWithoutEventRegistrationsInput = {
maxXp?: Prisma.IntFieldUpdateOperationsInput | number
avatar?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
bio?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
characterClass?: Prisma.NullableEnumCharacterClassFieldUpdateOperationsInput | $Enums.CharacterClass | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
preferences?: Prisma.UserPreferencesUncheckedUpdateOneWithoutUserNestedInput
@@ -899,6 +933,7 @@ export type UserSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = r
maxXp?: boolean
avatar?: boolean
bio?: boolean
characterClass?: boolean
createdAt?: boolean
updatedAt?: boolean
preferences?: boolean | Prisma.User$preferencesArgs<ExtArgs>
@@ -920,6 +955,7 @@ export type UserSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Extensio
maxXp?: boolean
avatar?: boolean
bio?: boolean
characterClass?: boolean
createdAt?: boolean
updatedAt?: boolean
}, ExtArgs["result"]["user"]>
@@ -938,6 +974,7 @@ export type UserSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensio
maxXp?: boolean
avatar?: boolean
bio?: boolean
characterClass?: boolean
createdAt?: boolean
updatedAt?: boolean
}, ExtArgs["result"]["user"]>
@@ -956,11 +993,12 @@ export type UserSelectScalar = {
maxXp?: boolean
avatar?: boolean
bio?: boolean
characterClass?: boolean
createdAt?: boolean
updatedAt?: boolean
}
export type UserOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "email" | "password" | "username" | "role" | "score" | "level" | "hp" | "maxHp" | "xp" | "maxXp" | "avatar" | "bio" | "createdAt" | "updatedAt", ExtArgs["result"]["user"]>
export type UserOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "email" | "password" | "username" | "role" | "score" | "level" | "hp" | "maxHp" | "xp" | "maxXp" | "avatar" | "bio" | "characterClass" | "createdAt" | "updatedAt", ExtArgs["result"]["user"]>
export type UserInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
preferences?: boolean | Prisma.User$preferencesArgs<ExtArgs>
eventRegistrations?: boolean | Prisma.User$eventRegistrationsArgs<ExtArgs>
@@ -989,6 +1027,7 @@ export type $UserPayload<ExtArgs extends runtime.Types.Extensions.InternalArgs =
maxXp: number
avatar: string | null
bio: string | null
characterClass: $Enums.CharacterClass | null
createdAt: Date
updatedAt: Date
}, ExtArgs["result"]["user"]>
@@ -1429,6 +1468,7 @@ export interface UserFieldRefs {
readonly maxXp: Prisma.FieldRef<"User", 'Int'>
readonly avatar: Prisma.FieldRef<"User", 'String'>
readonly bio: Prisma.FieldRef<"User", 'String'>
readonly characterClass: Prisma.FieldRef<"User", 'CharacterClass'>
readonly createdAt: Prisma.FieldRef<"User", 'DateTime'>
readonly updatedAt: Prisma.FieldRef<"User", 'DateTime'>
}

View File

@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "User" ADD COLUMN "characterClass" TEXT;

View File

@@ -28,6 +28,19 @@ enum EventStatus {
PAST
}
enum CharacterClass {
WARRIOR
MAGE
ROGUE
RANGER
PALADIN
ENGINEER
MERCHANT
SCHOLAR
BERSERKER
NECROMANCER
}
model User {
id String @id @default(cuid())
email String @unique
@@ -42,6 +55,7 @@ model User {
maxXp Int @default(5000)
avatar String?
bio String?
characterClass CharacterClass?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
preferences UserPreferences?