diff --git a/actions/admin/preferences.ts b/actions/admin/preferences.ts index b41add5..0dd64f5 100644 --- a/actions/admin/preferences.ts +++ b/actions/admin/preferences.ts @@ -20,6 +20,8 @@ export async function updateSitePreferences(data: { eventsBackground?: string | null; leaderboardBackground?: string | null; challengesBackground?: string | null; + eventRegistrationPoints?: number; + eventFeedbackPoints?: number; }) { try { await checkAdminAccess()(); @@ -29,6 +31,8 @@ export async function updateSitePreferences(data: { eventsBackground: data.eventsBackground, leaderboardBackground: data.leaderboardBackground, challengesBackground: data.challengesBackground, + eventRegistrationPoints: data.eventRegistrationPoints, + eventFeedbackPoints: data.eventFeedbackPoints, }); revalidatePath("/admin"); diff --git a/app/feedback/[eventId]/FeedbackPageClient.tsx b/app/feedback/[eventId]/FeedbackPageClient.tsx index aec711c..d4069ff 100644 --- a/app/feedback/[eventId]/FeedbackPageClient.tsx +++ b/app/feedback/[eventId]/FeedbackPageClient.tsx @@ -128,6 +128,9 @@ export default function FeedbackPageClient({ }); } + // Rafraîchir le score dans le header + window.dispatchEvent(new Event("refreshUserScore")); + // Rediriger après 2 secondes setTimeout(() => { router.push("/events"); diff --git a/components/admin/AdminPanel.tsx b/components/admin/AdminPanel.tsx index 72e597c..4f585dc 100644 --- a/components/admin/AdminPanel.tsx +++ b/components/admin/AdminPanel.tsx @@ -6,6 +6,8 @@ import EventManagement from "@/components/admin/EventManagement"; import FeedbackManagement from "@/components/admin/FeedbackManagement"; import ChallengeManagement from "@/components/admin/ChallengeManagement"; import BackgroundPreferences from "@/components/admin/BackgroundPreferences"; +import EventPointsPreferences from "@/components/admin/EventPointsPreferences"; +import EventFeedbackPointsPreferences from "@/components/admin/EventFeedbackPointsPreferences"; import { Button, Card, SectionTitle } from "@/components/ui"; interface SitePreferences { @@ -14,6 +16,8 @@ interface SitePreferences { eventsBackground: string | null; leaderboardBackground: string | null; challengesBackground: string | null; + eventRegistrationPoints: number; + eventFeedbackPoints: number; } interface AdminPanelProps { @@ -93,6 +97,8 @@ export default function AdminPanel({ initialPreferences }: AdminPanelProps) {
+ +
)} diff --git a/components/admin/BackgroundPreferences.tsx b/components/admin/BackgroundPreferences.tsx index 6cf1b9a..bb56c11 100644 --- a/components/admin/BackgroundPreferences.tsx +++ b/components/admin/BackgroundPreferences.tsx @@ -11,6 +11,7 @@ interface SitePreferences { eventsBackground: string | null; leaderboardBackground: string | null; challengesBackground: string | null; + eventRegistrationPoints?: number; } interface BackgroundPreferencesProps { diff --git a/components/admin/EventFeedbackPointsPreferences.tsx b/components/admin/EventFeedbackPointsPreferences.tsx new file mode 100644 index 0000000..08c8722 --- /dev/null +++ b/components/admin/EventFeedbackPointsPreferences.tsx @@ -0,0 +1,166 @@ +"use client"; + +import { useState, useEffect } from "react"; +import { updateSitePreferences } from "@/actions/admin/preferences"; +import { Button, Card, Input } from "@/components/ui"; + +interface SitePreferences { + id: string; + eventFeedbackPoints: number; +} + +interface EventFeedbackPointsPreferencesProps { + initialPreferences: SitePreferences; +} + +export default function EventFeedbackPointsPreferences({ + initialPreferences, +}: EventFeedbackPointsPreferencesProps) { + const [preferences, setPreferences] = useState( + initialPreferences + ); + const [isEditing, setIsEditing] = useState(false); + const [formData, setFormData] = useState({ + eventFeedbackPoints: initialPreferences.eventFeedbackPoints.toString(), + }); + const [isSaving, setIsSaving] = useState(false); + + // Synchroniser les préférences quand initialPreferences change + useEffect(() => { + setPreferences(initialPreferences); + setFormData({ + eventFeedbackPoints: initialPreferences.eventFeedbackPoints.toString(), + }); + }, [initialPreferences]); + + const handleEdit = () => { + setIsEditing(true); + }; + + const handleSave = async () => { + const points = parseInt(formData.eventFeedbackPoints, 10); + + if (isNaN(points) || points < 0) { + alert("Le nombre de points doit être un nombre positif"); + return; + } + + setIsSaving(true); + try { + const result = await updateSitePreferences({ + eventFeedbackPoints: points, + }); + + if (result.success && result.data) { + setPreferences(result.data); + setFormData({ + eventFeedbackPoints: result.data.eventFeedbackPoints.toString(), + }); + setIsEditing(false); + } else { + console.error("Error updating preferences:", result.error); + alert(result.error || "Erreur lors de la mise à jour"); + } + } catch (error) { + console.error("Error updating preferences:", error); + alert("Erreur lors de la mise à jour"); + } finally { + setIsSaving(false); + } + }; + + const handleCancel = () => { + setIsEditing(false); + if (preferences) { + setFormData({ + eventFeedbackPoints: preferences.eventFeedbackPoints.toString(), + }); + } + }; + + return ( + +
+
+

+ Points de feedback sur les événements +

+

+ Nombre de points attribués lorsqu'un utilisateur donne un feedback à un événement (première fois uniquement) +

+
+ {!isEditing && ( + + )} +
+ + {isEditing ? ( +
+
+ + + setFormData({ + ...formData, + eventFeedbackPoints: e.target.value, + }) + } + placeholder="100" + className="w-full" + /> +

+ Les utilisateurs gagneront ce nombre de points lors de leur premier feedback sur un événement +

+
+
+ + +
+
+ ) : ( +
+ + Points actuels: + +
+ + {preferences?.eventFeedbackPoints ?? 100} + + points +
+
+ )} +
+ ); +} + diff --git a/components/admin/EventPointsPreferences.tsx b/components/admin/EventPointsPreferences.tsx new file mode 100644 index 0000000..921aa55 --- /dev/null +++ b/components/admin/EventPointsPreferences.tsx @@ -0,0 +1,166 @@ +"use client"; + +import { useState, useEffect } from "react"; +import { updateSitePreferences } from "@/actions/admin/preferences"; +import { Button, Card, Input } from "@/components/ui"; + +interface SitePreferences { + id: string; + eventRegistrationPoints: number; +} + +interface EventPointsPreferencesProps { + initialPreferences: SitePreferences; +} + +export default function EventPointsPreferences({ + initialPreferences, +}: EventPointsPreferencesProps) { + const [preferences, setPreferences] = useState( + initialPreferences + ); + const [isEditing, setIsEditing] = useState(false); + const [formData, setFormData] = useState({ + eventRegistrationPoints: initialPreferences.eventRegistrationPoints.toString(), + }); + const [isSaving, setIsSaving] = useState(false); + + // Synchroniser les préférences quand initialPreferences change + useEffect(() => { + setPreferences(initialPreferences); + setFormData({ + eventRegistrationPoints: initialPreferences.eventRegistrationPoints.toString(), + }); + }, [initialPreferences]); + + const handleEdit = () => { + setIsEditing(true); + }; + + const handleSave = async () => { + const points = parseInt(formData.eventRegistrationPoints, 10); + + if (isNaN(points) || points < 0) { + alert("Le nombre de points doit être un nombre positif"); + return; + } + + setIsSaving(true); + try { + const result = await updateSitePreferences({ + eventRegistrationPoints: points, + }); + + if (result.success && result.data) { + setPreferences(result.data); + setFormData({ + eventRegistrationPoints: result.data.eventRegistrationPoints.toString(), + }); + setIsEditing(false); + } else { + console.error("Error updating preferences:", result.error); + alert(result.error || "Erreur lors de la mise à jour"); + } + } catch (error) { + console.error("Error updating preferences:", error); + alert("Erreur lors de la mise à jour"); + } finally { + setIsSaving(false); + } + }; + + const handleCancel = () => { + setIsEditing(false); + if (preferences) { + setFormData({ + eventRegistrationPoints: preferences.eventRegistrationPoints.toString(), + }); + } + }; + + return ( + +
+
+

+ Points d'inscription aux événements +

+

+ Nombre de points attribués lorsqu'un utilisateur s'inscrit à un événement +

+
+ {!isEditing && ( + + )} +
+ + {isEditing ? ( +
+
+ + + setFormData({ + ...formData, + eventRegistrationPoints: e.target.value, + }) + } + placeholder="100" + className="w-full" + /> +

+ Les utilisateurs gagneront ce nombre de points lors de leur inscription à un événement +

+
+
+ + +
+
+ ) : ( +
+ + Points actuels: + +
+ + {preferences?.eventRegistrationPoints ?? 100} + + points +
+
+ )} +
+ ); +} + diff --git a/components/events/EventsPageSection.tsx b/components/events/EventsPageSection.tsx index d64b4fb..d3158d4 100644 --- a/components/events/EventsPageSection.tsx +++ b/components/events/EventsPageSection.tsx @@ -564,6 +564,8 @@ export default function EventsPageSection({ ...prev, [eventId]: true, })); + // Rafraîchir le score dans le header + window.dispatchEvent(new Event("refreshUserScore")); } else { setError(result.error || "Une erreur est survenue"); } @@ -583,6 +585,8 @@ export default function EventsPageSection({ ...prev, [eventId]: false, })); + // Rafraîchir le score dans le header + window.dispatchEvent(new Event("refreshUserScore")); } else { setError(result.error || "Une erreur est survenue"); } diff --git a/components/feedback/FeedbackModal.tsx b/components/feedback/FeedbackModal.tsx index e4163e1..25ef858 100644 --- a/components/feedback/FeedbackModal.tsx +++ b/components/feedback/FeedbackModal.tsx @@ -155,6 +155,9 @@ export default function FeedbackModal({ }); } + // Rafraîchir le score dans le header + window.dispatchEvent(new Event("refreshUserScore")); + // Fermer la modale après 1.5 secondes setTimeout(() => { onClose(); diff --git a/components/profile/PlayerStats.tsx b/components/profile/PlayerStats.tsx index 81c95eb..43251cd 100644 --- a/components/profile/PlayerStats.tsx +++ b/components/profile/PlayerStats.tsx @@ -1,6 +1,6 @@ "use client"; -import { useEffect, useState } from "react"; +import { useEffect, useState, useCallback } from "react"; import { useSession } from "next-auth/react"; import Link from "next/link"; import { Avatar } from "@/components/ui"; @@ -42,6 +42,31 @@ export default function PlayerStats({ initialUserData }: PlayerStatsProps) { initialUserData || defaultUserData ); + const refreshUserData = useCallback(async () => { + if (!session?.user?.id) return; + + try { + const res = await fetch(`/api/users/${session.user.id}`); + const data = await res.json(); + if (data) { + requestAnimationFrame(() => { + setUserData({ + username: data.username || "Guest", + avatar: data.avatar, + hp: data.hp || 1000, + maxHp: data.maxHp || 1000, + xp: data.xp || 0, + maxXp: data.maxXp || 5000, + level: data.level || 1, + score: data.score || 0, + }); + }); + } + } catch (error) { + console.error("Error refreshing user data:", error); + } + }, [session]); + useEffect(() => { // Si on a déjà des données initiales, ne rien faire (déjà initialisé dans useState) if (initialUserData) { @@ -92,6 +117,18 @@ export default function PlayerStats({ initialUserData }: PlayerStatsProps) { } }, [session, initialUserData]); + // Écouter les événements de refresh du score + useEffect(() => { + const handleRefreshScore = () => { + refreshUserData(); + }; + + window.addEventListener("refreshUserScore", handleRefreshScore); + return () => { + window.removeEventListener("refreshUserScore", handleRefreshScore); + }; + }, [refreshUserData]); + const { username, avatar, level, score } = userData; return ( @@ -136,7 +173,6 @@ export default function PlayerStats({ initialUserData }: PlayerStatsProps) { - ); } diff --git a/prisma/generated/prisma/internal/class.ts b/prisma/generated/prisma/internal/class.ts index 8085cd8..c2455be 100644 --- a/prisma/generated/prisma/internal/class.ts +++ b/prisma/generated/prisma/internal/class.ts @@ -20,7 +20,7 @@ const config: runtime.GetPrismaClientConfig = { "clientVersion": "7.1.0", "engineVersion": "ab635e6b9d606fa5c8fb8b1a7f909c3c3c1c98ba", "activeProvider": "sqlite", - "inlineSchema": "generator client {\n provider = \"prisma-client\"\n output = \"./generated/prisma\"\n}\n\ndatasource db {\n provider = \"sqlite\"\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 bio String?\n characterClass CharacterClass?\n eventFeedbacks EventFeedback[]\n eventRegistrations EventRegistration[]\n preferences UserPreferences?\n challengesAsChallenger Challenge[] @relation(\"Challenger\")\n challengesAsChallenged Challenge[] @relation(\"Challenged\")\n challengesAsAdmin Challenge[] @relation(\"AdminValidator\")\n challengesAsWinner Challenge[] @relation(\"ChallengeWinner\")\n\n @@index([score])\n @@index([email])\n}\n\nmodel UserPreferences {\n id String @id @default(cuid())\n userId String @unique\n homeBackground String?\n eventsBackground String?\n leaderboardBackground String?\n theme String? @default(\"default\")\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n}\n\nmodel Event {\n id String @id @default(cuid())\n date DateTime\n name String\n description String\n type EventType\n room String?\n time String?\n maxPlaces Int?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n feedbacks EventFeedback[]\n registrations EventRegistration[]\n\n @@index([date])\n}\n\nmodel EventRegistration {\n id String @id @default(cuid())\n userId String\n eventId String\n createdAt DateTime @default(now())\n event Event @relation(fields: [eventId], references: [id], onDelete: Cascade)\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@unique([userId, eventId])\n @@index([userId])\n @@index([eventId])\n}\n\nmodel EventFeedback {\n id String @id @default(cuid())\n userId String\n eventId String\n rating Int\n comment String?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n event Event @relation(fields: [eventId], references: [id], onDelete: Cascade)\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\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 challengesBackground String?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nenum Role {\n USER\n ADMIN\n}\n\nenum EventType {\n ATELIER\n KATA\n PRESENTATION\n LEARNING_HOUR\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\nenum ChallengeStatus {\n PENDING\n ACCEPTED\n COMPLETED\n REJECTED\n CANCELLED\n}\n\nmodel Challenge {\n id String @id @default(cuid())\n challengerId String // Joueur qui lance le défi\n challengedId String // Joueur qui reçoit le défi\n challenger User @relation(\"Challenger\", fields: [challengerId], references: [id], onDelete: Cascade)\n challenged User @relation(\"Challenged\", fields: [challengedId], references: [id], onDelete: Cascade)\n title String // Titre du défi\n description String // Description détaillée du défi\n pointsReward Int @default(100) // Points à gagner pour le gagnant\n status ChallengeStatus @default(PENDING)\n adminId String? // Admin qui valide le défi\n admin User? @relation(\"AdminValidator\", fields: [adminId], references: [id], onDelete: SetNull)\n adminComment String? // Commentaire de l'admin lors de la validation/rejet\n winnerId String? // ID du gagnant (challengerId ou challengedId)\n winner User? @relation(\"ChallengeWinner\", fields: [winnerId], references: [id], onDelete: SetNull)\n createdAt DateTime @default(now())\n acceptedAt DateTime? // Date d'acceptation du défi\n completedAt DateTime? // Date de validation par l'admin\n updatedAt DateTime @updatedAt\n\n @@index([challengerId])\n @@index([challengedId])\n @@index([status])\n @@index([adminId])\n}\n", + "inlineSchema": "generator client {\n provider = \"prisma-client\"\n output = \"./generated/prisma\"\n}\n\ndatasource db {\n provider = \"sqlite\"\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 bio String?\n characterClass CharacterClass?\n eventFeedbacks EventFeedback[]\n eventRegistrations EventRegistration[]\n preferences UserPreferences?\n challengesAsChallenger Challenge[] @relation(\"Challenger\")\n challengesAsChallenged Challenge[] @relation(\"Challenged\")\n challengesAsAdmin Challenge[] @relation(\"AdminValidator\")\n challengesAsWinner Challenge[] @relation(\"ChallengeWinner\")\n\n @@index([score])\n @@index([email])\n}\n\nmodel UserPreferences {\n id String @id @default(cuid())\n userId String @unique\n homeBackground String?\n eventsBackground String?\n leaderboardBackground String?\n theme String? @default(\"default\")\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n}\n\nmodel Event {\n id String @id @default(cuid())\n date DateTime\n name String\n description String\n type EventType\n room String?\n time String?\n maxPlaces Int?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n feedbacks EventFeedback[]\n registrations EventRegistration[]\n\n @@index([date])\n}\n\nmodel EventRegistration {\n id String @id @default(cuid())\n userId String\n eventId String\n createdAt DateTime @default(now())\n event Event @relation(fields: [eventId], references: [id], onDelete: Cascade)\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@unique([userId, eventId])\n @@index([userId])\n @@index([eventId])\n}\n\nmodel EventFeedback {\n id String @id @default(cuid())\n userId String\n eventId String\n rating Int\n comment String?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n event Event @relation(fields: [eventId], references: [id], onDelete: Cascade)\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\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 challengesBackground String?\n eventRegistrationPoints Int @default(100)\n eventFeedbackPoints Int @default(50)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nenum Role {\n USER\n ADMIN\n}\n\nenum EventType {\n ATELIER\n KATA\n PRESENTATION\n LEARNING_HOUR\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\nenum ChallengeStatus {\n PENDING\n ACCEPTED\n COMPLETED\n REJECTED\n CANCELLED\n}\n\nmodel Challenge {\n id String @id @default(cuid())\n challengerId String // Joueur qui lance le défi\n challengedId String // Joueur qui reçoit le défi\n challenger User @relation(\"Challenger\", fields: [challengerId], references: [id], onDelete: Cascade)\n challenged User @relation(\"Challenged\", fields: [challengedId], references: [id], onDelete: Cascade)\n title String // Titre du défi\n description String // Description détaillée du défi\n pointsReward Int @default(100) // Points à gagner pour le gagnant\n status ChallengeStatus @default(PENDING)\n adminId String? // Admin qui valide le défi\n admin User? @relation(\"AdminValidator\", fields: [adminId], references: [id], onDelete: SetNull)\n adminComment String? // Commentaire de l'admin lors de la validation/rejet\n winnerId String? // ID du gagnant (challengerId ou challengedId)\n winner User? @relation(\"ChallengeWinner\", fields: [winnerId], references: [id], onDelete: SetNull)\n createdAt DateTime @default(now())\n acceptedAt DateTime? // Date d'acceptation du défi\n completedAt DateTime? // Date de validation par l'admin\n updatedAt DateTime @updatedAt\n\n @@index([challengerId])\n @@index([challengedId])\n @@index([status])\n @@index([adminId])\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\":\"bio\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"characterClass\",\"kind\":\"enum\",\"type\":\"CharacterClass\"},{\"name\":\"eventFeedbacks\",\"kind\":\"object\",\"type\":\"EventFeedback\",\"relationName\":\"EventFeedbackToUser\"},{\"name\":\"eventRegistrations\",\"kind\":\"object\",\"type\":\"EventRegistration\",\"relationName\":\"EventRegistrationToUser\"},{\"name\":\"preferences\",\"kind\":\"object\",\"type\":\"UserPreferences\",\"relationName\":\"UserToUserPreferences\"},{\"name\":\"challengesAsChallenger\",\"kind\":\"object\",\"type\":\"Challenge\",\"relationName\":\"Challenger\"},{\"name\":\"challengesAsChallenged\",\"kind\":\"object\",\"type\":\"Challenge\",\"relationName\":\"Challenged\"},{\"name\":\"challengesAsAdmin\",\"kind\":\"object\",\"type\":\"Challenge\",\"relationName\":\"AdminValidator\"},{\"name\":\"challengesAsWinner\",\"kind\":\"object\",\"type\":\"Challenge\",\"relationName\":\"ChallengeWinner\"}],\"dbName\":null},\"UserPreferences\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"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\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"UserToUserPreferences\"}],\"dbName\":null},\"Event\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"date\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"enum\",\"type\":\"EventType\"},{\"name\":\"room\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"time\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"maxPlaces\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"feedbacks\",\"kind\":\"object\",\"type\":\"EventFeedback\",\"relationName\":\"EventToEventFeedback\"},{\"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\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"event\",\"kind\":\"object\",\"type\":\"Event\",\"relationName\":\"EventToEventRegistration\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"EventRegistrationToUser\"}],\"dbName\":null},\"EventFeedback\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"eventId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"rating\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"comment\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"event\",\"kind\":\"object\",\"type\":\"Event\",\"relationName\":\"EventToEventFeedback\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"EventFeedbackToUser\"}],\"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\":\"challengesBackground\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Challenge\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"challengerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"challengedId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"challenger\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"Challenger\"},{\"name\":\"challenged\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"Challenged\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"pointsReward\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"ChallengeStatus\"},{\"name\":\"adminId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"admin\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"AdminValidator\"},{\"name\":\"adminComment\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"winnerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"winner\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ChallengeWinner\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"acceptedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completedAt\",\"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\":\"bio\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"characterClass\",\"kind\":\"enum\",\"type\":\"CharacterClass\"},{\"name\":\"eventFeedbacks\",\"kind\":\"object\",\"type\":\"EventFeedback\",\"relationName\":\"EventFeedbackToUser\"},{\"name\":\"eventRegistrations\",\"kind\":\"object\",\"type\":\"EventRegistration\",\"relationName\":\"EventRegistrationToUser\"},{\"name\":\"preferences\",\"kind\":\"object\",\"type\":\"UserPreferences\",\"relationName\":\"UserToUserPreferences\"},{\"name\":\"challengesAsChallenger\",\"kind\":\"object\",\"type\":\"Challenge\",\"relationName\":\"Challenger\"},{\"name\":\"challengesAsChallenged\",\"kind\":\"object\",\"type\":\"Challenge\",\"relationName\":\"Challenged\"},{\"name\":\"challengesAsAdmin\",\"kind\":\"object\",\"type\":\"Challenge\",\"relationName\":\"AdminValidator\"},{\"name\":\"challengesAsWinner\",\"kind\":\"object\",\"type\":\"Challenge\",\"relationName\":\"ChallengeWinner\"}],\"dbName\":null},\"UserPreferences\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"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\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"UserToUserPreferences\"}],\"dbName\":null},\"Event\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"date\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"enum\",\"type\":\"EventType\"},{\"name\":\"room\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"time\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"maxPlaces\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"feedbacks\",\"kind\":\"object\",\"type\":\"EventFeedback\",\"relationName\":\"EventToEventFeedback\"},{\"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\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"event\",\"kind\":\"object\",\"type\":\"Event\",\"relationName\":\"EventToEventRegistration\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"EventRegistrationToUser\"}],\"dbName\":null},\"EventFeedback\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"eventId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"rating\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"comment\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"event\",\"kind\":\"object\",\"type\":\"Event\",\"relationName\":\"EventToEventFeedback\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"EventFeedbackToUser\"}],\"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\":\"challengesBackground\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"eventRegistrationPoints\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"eventFeedbackPoints\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Challenge\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"challengerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"challengedId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"challenger\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"Challenger\"},{\"name\":\"challenged\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"Challenged\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"pointsReward\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"ChallengeStatus\"},{\"name\":\"adminId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"admin\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"AdminValidator\"},{\"name\":\"adminComment\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"winnerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"winner\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ChallengeWinner\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"acceptedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}") async function decodeBase64AsWasm(wasmBase64: string): Promise { const { Buffer } = await import('node:buffer') diff --git a/prisma/generated/prisma/internal/prismaNamespace.ts b/prisma/generated/prisma/internal/prismaNamespace.ts index 2ccf43a..d868283 100644 --- a/prisma/generated/prisma/internal/prismaNamespace.ts +++ b/prisma/generated/prisma/internal/prismaNamespace.ts @@ -1045,6 +1045,8 @@ export const SitePreferencesScalarFieldEnum = { eventsBackground: 'eventsBackground', leaderboardBackground: 'leaderboardBackground', challengesBackground: 'challengesBackground', + eventRegistrationPoints: 'eventRegistrationPoints', + eventFeedbackPoints: 'eventFeedbackPoints', createdAt: 'createdAt', updatedAt: 'updatedAt' } as const diff --git a/prisma/generated/prisma/internal/prismaNamespaceBrowser.ts b/prisma/generated/prisma/internal/prismaNamespaceBrowser.ts index faa805f..63d8c82 100644 --- a/prisma/generated/prisma/internal/prismaNamespaceBrowser.ts +++ b/prisma/generated/prisma/internal/prismaNamespaceBrowser.ts @@ -154,6 +154,8 @@ export const SitePreferencesScalarFieldEnum = { eventsBackground: 'eventsBackground', leaderboardBackground: 'leaderboardBackground', challengesBackground: 'challengesBackground', + eventRegistrationPoints: 'eventRegistrationPoints', + eventFeedbackPoints: 'eventFeedbackPoints', createdAt: 'createdAt', updatedAt: 'updatedAt' } as const diff --git a/prisma/generated/prisma/models/SitePreferences.ts b/prisma/generated/prisma/models/SitePreferences.ts index 170f0d3..52aecfb 100644 --- a/prisma/generated/prisma/models/SitePreferences.ts +++ b/prisma/generated/prisma/models/SitePreferences.ts @@ -20,16 +20,30 @@ export type SitePreferencesModel = runtime.Types.Result.DefaultSelection | string | null leaderboardBackground?: Prisma.StringNullableFilter<"SitePreferences"> | string | null challengesBackground?: Prisma.StringNullableFilter<"SitePreferences"> | string | null + eventRegistrationPoints?: Prisma.IntFilter<"SitePreferences"> | number + eventFeedbackPoints?: Prisma.IntFilter<"SitePreferences"> | number createdAt?: Prisma.DateTimeFilter<"SitePreferences"> | Date | string updatedAt?: Prisma.DateTimeFilter<"SitePreferences"> | Date | string } @@ -206,6 +260,8 @@ export type SitePreferencesOrderByWithRelationInput = { eventsBackground?: Prisma.SortOrderInput | Prisma.SortOrder leaderboardBackground?: Prisma.SortOrderInput | Prisma.SortOrder challengesBackground?: Prisma.SortOrderInput | Prisma.SortOrder + eventRegistrationPoints?: Prisma.SortOrder + eventFeedbackPoints?: Prisma.SortOrder createdAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder } @@ -219,6 +275,8 @@ export type SitePreferencesWhereUniqueInput = Prisma.AtLeast<{ eventsBackground?: Prisma.StringNullableFilter<"SitePreferences"> | string | null leaderboardBackground?: Prisma.StringNullableFilter<"SitePreferences"> | string | null challengesBackground?: Prisma.StringNullableFilter<"SitePreferences"> | string | null + eventRegistrationPoints?: Prisma.IntFilter<"SitePreferences"> | number + eventFeedbackPoints?: Prisma.IntFilter<"SitePreferences"> | number createdAt?: Prisma.DateTimeFilter<"SitePreferences"> | Date | string updatedAt?: Prisma.DateTimeFilter<"SitePreferences"> | Date | string }, "id"> @@ -229,11 +287,15 @@ export type SitePreferencesOrderByWithAggregationInput = { eventsBackground?: Prisma.SortOrderInput | Prisma.SortOrder leaderboardBackground?: Prisma.SortOrderInput | Prisma.SortOrder challengesBackground?: Prisma.SortOrderInput | Prisma.SortOrder + eventRegistrationPoints?: Prisma.SortOrder + eventFeedbackPoints?: Prisma.SortOrder createdAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder _count?: Prisma.SitePreferencesCountOrderByAggregateInput + _avg?: Prisma.SitePreferencesAvgOrderByAggregateInput _max?: Prisma.SitePreferencesMaxOrderByAggregateInput _min?: Prisma.SitePreferencesMinOrderByAggregateInput + _sum?: Prisma.SitePreferencesSumOrderByAggregateInput } export type SitePreferencesScalarWhereWithAggregatesInput = { @@ -245,6 +307,8 @@ export type SitePreferencesScalarWhereWithAggregatesInput = { eventsBackground?: Prisma.StringNullableWithAggregatesFilter<"SitePreferences"> | string | null leaderboardBackground?: Prisma.StringNullableWithAggregatesFilter<"SitePreferences"> | string | null challengesBackground?: Prisma.StringNullableWithAggregatesFilter<"SitePreferences"> | string | null + eventRegistrationPoints?: Prisma.IntWithAggregatesFilter<"SitePreferences"> | number + eventFeedbackPoints?: Prisma.IntWithAggregatesFilter<"SitePreferences"> | number createdAt?: Prisma.DateTimeWithAggregatesFilter<"SitePreferences"> | Date | string updatedAt?: Prisma.DateTimeWithAggregatesFilter<"SitePreferences"> | Date | string } @@ -255,6 +319,8 @@ export type SitePreferencesCreateInput = { eventsBackground?: string | null leaderboardBackground?: string | null challengesBackground?: string | null + eventRegistrationPoints?: number + eventFeedbackPoints?: number createdAt?: Date | string updatedAt?: Date | string } @@ -265,6 +331,8 @@ export type SitePreferencesUncheckedCreateInput = { eventsBackground?: string | null leaderboardBackground?: string | null challengesBackground?: string | null + eventRegistrationPoints?: number + eventFeedbackPoints?: number createdAt?: Date | string updatedAt?: Date | string } @@ -275,6 +343,8 @@ export type SitePreferencesUpdateInput = { eventsBackground?: Prisma.NullableStringFieldUpdateOperationsInput | string | null leaderboardBackground?: Prisma.NullableStringFieldUpdateOperationsInput | string | null challengesBackground?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + eventRegistrationPoints?: Prisma.IntFieldUpdateOperationsInput | number + eventFeedbackPoints?: Prisma.IntFieldUpdateOperationsInput | number createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string } @@ -285,6 +355,8 @@ export type SitePreferencesUncheckedUpdateInput = { eventsBackground?: Prisma.NullableStringFieldUpdateOperationsInput | string | null leaderboardBackground?: Prisma.NullableStringFieldUpdateOperationsInput | string | null challengesBackground?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + eventRegistrationPoints?: Prisma.IntFieldUpdateOperationsInput | number + eventFeedbackPoints?: Prisma.IntFieldUpdateOperationsInput | number createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string } @@ -295,6 +367,8 @@ export type SitePreferencesCreateManyInput = { eventsBackground?: string | null leaderboardBackground?: string | null challengesBackground?: string | null + eventRegistrationPoints?: number + eventFeedbackPoints?: number createdAt?: Date | string updatedAt?: Date | string } @@ -305,6 +379,8 @@ export type SitePreferencesUpdateManyMutationInput = { eventsBackground?: Prisma.NullableStringFieldUpdateOperationsInput | string | null leaderboardBackground?: Prisma.NullableStringFieldUpdateOperationsInput | string | null challengesBackground?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + eventRegistrationPoints?: Prisma.IntFieldUpdateOperationsInput | number + eventFeedbackPoints?: Prisma.IntFieldUpdateOperationsInput | number createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string } @@ -315,6 +391,8 @@ export type SitePreferencesUncheckedUpdateManyInput = { eventsBackground?: Prisma.NullableStringFieldUpdateOperationsInput | string | null leaderboardBackground?: Prisma.NullableStringFieldUpdateOperationsInput | string | null challengesBackground?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + eventRegistrationPoints?: Prisma.IntFieldUpdateOperationsInput | number + eventFeedbackPoints?: Prisma.IntFieldUpdateOperationsInput | number createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string } @@ -325,16 +403,25 @@ export type SitePreferencesCountOrderByAggregateInput = { eventsBackground?: Prisma.SortOrder leaderboardBackground?: Prisma.SortOrder challengesBackground?: Prisma.SortOrder + eventRegistrationPoints?: Prisma.SortOrder + eventFeedbackPoints?: Prisma.SortOrder createdAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder } +export type SitePreferencesAvgOrderByAggregateInput = { + eventRegistrationPoints?: Prisma.SortOrder + eventFeedbackPoints?: Prisma.SortOrder +} + export type SitePreferencesMaxOrderByAggregateInput = { id?: Prisma.SortOrder homeBackground?: Prisma.SortOrder eventsBackground?: Prisma.SortOrder leaderboardBackground?: Prisma.SortOrder challengesBackground?: Prisma.SortOrder + eventRegistrationPoints?: Prisma.SortOrder + eventFeedbackPoints?: Prisma.SortOrder createdAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder } @@ -345,10 +432,17 @@ export type SitePreferencesMinOrderByAggregateInput = { eventsBackground?: Prisma.SortOrder leaderboardBackground?: Prisma.SortOrder challengesBackground?: Prisma.SortOrder + eventRegistrationPoints?: Prisma.SortOrder + eventFeedbackPoints?: Prisma.SortOrder createdAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder } +export type SitePreferencesSumOrderByAggregateInput = { + eventRegistrationPoints?: Prisma.SortOrder + eventFeedbackPoints?: Prisma.SortOrder +} + export type SitePreferencesSelect = runtime.Types.Extensions.GetSelect<{ @@ -357,6 +451,8 @@ export type SitePreferencesSelect @@ -367,6 +463,8 @@ export type SitePreferencesSelectCreateManyAndReturn @@ -377,6 +475,8 @@ export type SitePreferencesSelectUpdateManyAndReturn @@ -387,11 +487,13 @@ export type SitePreferencesSelectScalar = { eventsBackground?: boolean leaderboardBackground?: boolean challengesBackground?: boolean + eventRegistrationPoints?: boolean + eventFeedbackPoints?: boolean createdAt?: boolean updatedAt?: boolean } -export type SitePreferencesOmit = runtime.Types.Extensions.GetOmit<"id" | "homeBackground" | "eventsBackground" | "leaderboardBackground" | "challengesBackground" | "createdAt" | "updatedAt", ExtArgs["result"]["sitePreferences"]> +export type SitePreferencesOmit = runtime.Types.Extensions.GetOmit<"id" | "homeBackground" | "eventsBackground" | "leaderboardBackground" | "challengesBackground" | "eventRegistrationPoints" | "eventFeedbackPoints" | "createdAt" | "updatedAt", ExtArgs["result"]["sitePreferences"]> export type $SitePreferencesPayload = { name: "SitePreferences" @@ -402,6 +504,8 @@ export type $SitePreferencesPayload @@ -832,6 +936,8 @@ export interface SitePreferencesFieldRefs { readonly eventsBackground: Prisma.FieldRef<"SitePreferences", 'String'> readonly leaderboardBackground: Prisma.FieldRef<"SitePreferences", 'String'> readonly challengesBackground: Prisma.FieldRef<"SitePreferences", 'String'> + readonly eventRegistrationPoints: Prisma.FieldRef<"SitePreferences", 'Int'> + readonly eventFeedbackPoints: Prisma.FieldRef<"SitePreferences", 'Int'> readonly createdAt: Prisma.FieldRef<"SitePreferences", 'DateTime'> readonly updatedAt: Prisma.FieldRef<"SitePreferences", 'DateTime'> } diff --git a/prisma/migrations/20251216153031_add_event_registration_points/migration.sql b/prisma/migrations/20251216153031_add_event_registration_points/migration.sql new file mode 100644 index 0000000..ef95838 --- /dev/null +++ b/prisma/migrations/20251216153031_add_event_registration_points/migration.sql @@ -0,0 +1,18 @@ +-- RedefineTables +PRAGMA defer_foreign_keys=ON; +PRAGMA foreign_keys=OFF; +CREATE TABLE "new_SitePreferences" ( + "id" TEXT NOT NULL PRIMARY KEY DEFAULT 'global', + "homeBackground" TEXT, + "eventsBackground" TEXT, + "leaderboardBackground" TEXT, + "challengesBackground" TEXT, + "eventRegistrationPoints" INTEGER NOT NULL DEFAULT 100, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL +); +INSERT INTO "new_SitePreferences" ("challengesBackground", "createdAt", "eventsBackground", "homeBackground", "id", "leaderboardBackground", "updatedAt") SELECT "challengesBackground", "createdAt", "eventsBackground", "homeBackground", "id", "leaderboardBackground", "updatedAt" FROM "SitePreferences"; +DROP TABLE "SitePreferences"; +ALTER TABLE "new_SitePreferences" RENAME TO "SitePreferences"; +PRAGMA foreign_keys=ON; +PRAGMA defer_foreign_keys=OFF; diff --git a/prisma/migrations/20251216153510_add_event_feedback_points/migration.sql b/prisma/migrations/20251216153510_add_event_feedback_points/migration.sql new file mode 100644 index 0000000..9d0f861 --- /dev/null +++ b/prisma/migrations/20251216153510_add_event_feedback_points/migration.sql @@ -0,0 +1,19 @@ +-- RedefineTables +PRAGMA defer_foreign_keys=ON; +PRAGMA foreign_keys=OFF; +CREATE TABLE "new_SitePreferences" ( + "id" TEXT NOT NULL PRIMARY KEY DEFAULT 'global', + "homeBackground" TEXT, + "eventsBackground" TEXT, + "leaderboardBackground" TEXT, + "challengesBackground" TEXT, + "eventRegistrationPoints" INTEGER NOT NULL DEFAULT 100, + "eventFeedbackPoints" INTEGER NOT NULL DEFAULT 50, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL +); +INSERT INTO "new_SitePreferences" ("challengesBackground", "createdAt", "eventRegistrationPoints", "eventsBackground", "homeBackground", "id", "leaderboardBackground", "updatedAt") SELECT "challengesBackground", "createdAt", "eventRegistrationPoints", "eventsBackground", "homeBackground", "id", "leaderboardBackground", "updatedAt" FROM "SitePreferences"; +DROP TABLE "SitePreferences"; +ALTER TABLE "new_SitePreferences" RENAME TO "SitePreferences"; +PRAGMA foreign_keys=ON; +PRAGMA defer_foreign_keys=OFF; diff --git a/prisma/migrations/20251216153605_change_feedback_points_default_to_100/migration.sql b/prisma/migrations/20251216153605_change_feedback_points_default_to_100/migration.sql new file mode 100644 index 0000000..a6b3005 --- /dev/null +++ b/prisma/migrations/20251216153605_change_feedback_points_default_to_100/migration.sql @@ -0,0 +1,19 @@ +-- RedefineTables +PRAGMA defer_foreign_keys=ON; +PRAGMA foreign_keys=OFF; +CREATE TABLE "new_SitePreferences" ( + "id" TEXT NOT NULL PRIMARY KEY DEFAULT 'global', + "homeBackground" TEXT, + "eventsBackground" TEXT, + "leaderboardBackground" TEXT, + "challengesBackground" TEXT, + "eventRegistrationPoints" INTEGER NOT NULL DEFAULT 100, + "eventFeedbackPoints" INTEGER NOT NULL DEFAULT 100, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL +); +INSERT INTO "new_SitePreferences" ("challengesBackground", "createdAt", "eventFeedbackPoints", "eventRegistrationPoints", "eventsBackground", "homeBackground", "id", "leaderboardBackground", "updatedAt") SELECT "challengesBackground", "createdAt", "eventFeedbackPoints", "eventRegistrationPoints", "eventsBackground", "homeBackground", "id", "leaderboardBackground", "updatedAt" FROM "SitePreferences"; +DROP TABLE "SitePreferences"; +ALTER TABLE "new_SitePreferences" RENAME TO "SitePreferences"; +PRAGMA foreign_keys=ON; +PRAGMA defer_foreign_keys=OFF; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index b239421..23fa4a1 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -100,6 +100,8 @@ model SitePreferences { eventsBackground String? leaderboardBackground String? challengesBackground String? + eventRegistrationPoints Int @default(100) + eventFeedbackPoints Int @default(100) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } diff --git a/services/events/event-feedback.service.ts b/services/events/event-feedback.service.ts index 635cf0f..933f88a 100644 --- a/services/events/event-feedback.service.ts +++ b/services/events/event-feedback.service.ts @@ -2,6 +2,7 @@ import { prisma } from "../database"; import type { EventFeedback, Prisma } from "@/prisma/generated/prisma/client"; import { ValidationError, NotFoundError } from "../errors"; import { eventService } from "./event.service"; +import { sitePreferencesService } from "../preferences/site-preferences.service"; export interface CreateOrUpdateFeedbackInput { rating: number; @@ -168,11 +169,34 @@ export class EventFeedbackService { throw new NotFoundError("Événement"); } - // Créer ou mettre à jour le feedback - return this.createOrUpdateFeedback(userId, eventId, { - rating: data.rating, - comment: data.comment || null, - }); + // Vérifier si c'est un nouveau feedback ou une mise à jour + const existingFeedback = await this.getUserFeedback(userId, eventId); + const isNewFeedback = !existingFeedback; + + // Récupérer les points à attribuer depuis les préférences du site + const sitePreferences = await sitePreferencesService.getOrCreateSitePreferences(); + const pointsToAward = sitePreferences.eventFeedbackPoints || 100; + + // Créer ou mettre à jour le feedback et attribuer les points (seulement pour nouveau feedback) + const [feedback] = await Promise.all([ + this.createOrUpdateFeedback(userId, eventId, { + rating: data.rating, + comment: data.comment || null, + }), + // Attribuer les points seulement si c'est un nouveau feedback + isNewFeedback + ? prisma.user.update({ + where: { id: userId }, + data: { + score: { + increment: pointsToAward, + }, + }, + }) + : Promise.resolve(null), + ]); + + return feedback; } } diff --git a/services/events/event-registration.service.ts b/services/events/event-registration.service.ts index f0c1c93..04825b5 100644 --- a/services/events/event-registration.service.ts +++ b/services/events/event-registration.service.ts @@ -3,6 +3,7 @@ import type { EventRegistration } from "@/prisma/generated/prisma/client"; import { ValidationError, NotFoundError, ConflictError } from "../errors"; import { eventService } from "./event.service"; import { calculateEventStatus } from "@/lib/eventStatus"; +import { sitePreferencesService } from "../preferences/site-preferences.service"; /** * Service de gestion des inscriptions aux événements @@ -24,18 +25,39 @@ export class EventRegistrationService { } /** - * Désinscrit un utilisateur d'un événement + * Désinscrit un utilisateur d'un événement et retire les points attribués */ async unregisterUserFromEvent( userId: string, eventId: string ): Promise { - await prisma.eventRegistration.deleteMany({ - where: { - userId, - eventId, - }, - }); + // Vérifier que l'utilisateur est bien inscrit avant de retirer les points + const isRegistered = await this.checkUserRegistration(userId, eventId); + if (!isRegistered) { + return; // Pas d'inscription, rien à faire + } + + // Récupérer les points à retirer depuis les préférences du site + const sitePreferences = await sitePreferencesService.getOrCreateSitePreferences(); + const pointsToRemove = sitePreferences.eventRegistrationPoints || 100; + + // Supprimer l'inscription et retirer les points en parallèle + await Promise.all([ + prisma.eventRegistration.deleteMany({ + where: { + userId, + eventId, + }, + }), + prisma.user.update({ + where: { id: userId }, + data: { + score: { + decrement: pointsToRemove, + }, + }, + }), + ]); } /** @@ -123,8 +145,24 @@ export class EventRegistrationService { throw new ConflictError("Vous êtes déjà inscrit à cet événement"); } - // Créer l'inscription - return this.registerUserToEvent(userId, eventId); + // Récupérer les points à attribuer depuis les préférences du site + const sitePreferences = await sitePreferencesService.getOrCreateSitePreferences(); + const pointsToAward = sitePreferences.eventRegistrationPoints || 100; + + // Créer l'inscription et attribuer les points en parallèle + const [registration] = await Promise.all([ + this.registerUserToEvent(userId, eventId), + prisma.user.update({ + where: { id: userId }, + data: { + score: { + increment: pointsToAward, + }, + }, + }), + ]); + + return registration; } } diff --git a/services/preferences/site-preferences.service.ts b/services/preferences/site-preferences.service.ts index 5d9e424..531e2fb 100644 --- a/services/preferences/site-preferences.service.ts +++ b/services/preferences/site-preferences.service.ts @@ -7,6 +7,8 @@ export interface UpdateSitePreferencesInput { eventsBackground?: string | null; leaderboardBackground?: string | null; challengesBackground?: string | null; + eventRegistrationPoints?: number; + eventFeedbackPoints?: number; } /** @@ -38,6 +40,8 @@ export class SitePreferencesService { eventsBackground: null, leaderboardBackground: null, challengesBackground: null, + eventRegistrationPoints: 100, + eventFeedbackPoints: 100, }, }); } @@ -70,6 +74,14 @@ export class SitePreferencesService { data.challengesBackground === "" ? null : (data.challengesBackground ?? undefined), + eventRegistrationPoints: + data.eventRegistrationPoints !== undefined + ? data.eventRegistrationPoints + : undefined, + eventFeedbackPoints: + data.eventFeedbackPoints !== undefined + ? data.eventFeedbackPoints + : undefined, }, create: { id: "global", @@ -85,6 +97,8 @@ export class SitePreferencesService { data.challengesBackground === "" ? null : (data.challengesBackground ?? null), + eventRegistrationPoints: data.eventRegistrationPoints ?? 100, + eventFeedbackPoints: data.eventFeedbackPoints ?? 100, }, }); }