Add event registration and feedback points to site preferences: Update SitePreferences model and related components to include eventRegistrationPoints and eventFeedbackPoints, ensuring proper handling of user scores during event interactions.
This commit is contained in:
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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) {
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
<BackgroundPreferences initialPreferences={initialPreferences} />
|
||||
<EventPointsPreferences initialPreferences={initialPreferences} />
|
||||
<EventFeedbackPointsPreferences initialPreferences={initialPreferences} />
|
||||
</div>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
@@ -11,6 +11,7 @@ interface SitePreferences {
|
||||
eventsBackground: string | null;
|
||||
leaderboardBackground: string | null;
|
||||
challengesBackground: string | null;
|
||||
eventRegistrationPoints?: number;
|
||||
}
|
||||
|
||||
interface BackgroundPreferencesProps {
|
||||
|
||||
166
components/admin/EventFeedbackPointsPreferences.tsx
Normal file
166
components/admin/EventFeedbackPointsPreferences.tsx
Normal file
@@ -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<SitePreferences | null>(
|
||||
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 (
|
||||
<Card variant="default" className="p-3 sm:p-4">
|
||||
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-start gap-3 mb-4">
|
||||
<div className="min-w-0 flex-1">
|
||||
<h3 className="text-pixel-gold font-bold text-base sm:text-lg break-words">
|
||||
Points de feedback sur les événements
|
||||
</h3>
|
||||
<p className="text-gray-400 text-xs sm:text-sm">
|
||||
Nombre de points attribués lorsqu'un utilisateur donne un feedback à un événement (première fois uniquement)
|
||||
</p>
|
||||
</div>
|
||||
{!isEditing && (
|
||||
<Button
|
||||
onClick={handleEdit}
|
||||
variant="primary"
|
||||
size="sm"
|
||||
className="whitespace-nowrap flex-shrink-0"
|
||||
>
|
||||
Modifier
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{isEditing ? (
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label
|
||||
htmlFor="eventFeedbackPoints"
|
||||
className="block text-sm font-medium text-pixel-gold mb-2"
|
||||
>
|
||||
Points de feedback
|
||||
</label>
|
||||
<Input
|
||||
id="eventFeedbackPoints"
|
||||
type="number"
|
||||
min="0"
|
||||
value={formData.eventFeedbackPoints}
|
||||
onChange={(e) =>
|
||||
setFormData({
|
||||
...formData,
|
||||
eventFeedbackPoints: e.target.value,
|
||||
})
|
||||
}
|
||||
placeholder="100"
|
||||
className="w-full"
|
||||
/>
|
||||
<p className="text-xs text-gray-400 mt-1">
|
||||
Les utilisateurs gagneront ce nombre de points lors de leur premier feedback sur un événement
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-col sm:flex-row gap-2 pt-4">
|
||||
<Button
|
||||
onClick={handleSave}
|
||||
variant="success"
|
||||
size="md"
|
||||
disabled={isSaving}
|
||||
>
|
||||
{isSaving ? "Enregistrement..." : "Enregistrer"}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleCancel}
|
||||
variant="secondary"
|
||||
size="md"
|
||||
disabled={isSaving}
|
||||
>
|
||||
Annuler
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4">
|
||||
<span className="text-pixel-gold font-bold text-sm sm:text-base min-w-0 sm:min-w-[200px] flex-shrink-0">
|
||||
Points actuels:
|
||||
</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-lg sm:text-xl font-bold text-white">
|
||||
{preferences?.eventFeedbackPoints ?? 100}
|
||||
</span>
|
||||
<span className="text-xs sm:text-sm text-gray-400">points</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
166
components/admin/EventPointsPreferences.tsx
Normal file
166
components/admin/EventPointsPreferences.tsx
Normal file
@@ -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<SitePreferences | null>(
|
||||
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 (
|
||||
<Card variant="default" className="p-3 sm:p-4">
|
||||
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-start gap-3 mb-4">
|
||||
<div className="min-w-0 flex-1">
|
||||
<h3 className="text-pixel-gold font-bold text-base sm:text-lg break-words">
|
||||
Points d'inscription aux événements
|
||||
</h3>
|
||||
<p className="text-gray-400 text-xs sm:text-sm">
|
||||
Nombre de points attribués lorsqu'un utilisateur s'inscrit à un événement
|
||||
</p>
|
||||
</div>
|
||||
{!isEditing && (
|
||||
<Button
|
||||
onClick={handleEdit}
|
||||
variant="primary"
|
||||
size="sm"
|
||||
className="whitespace-nowrap flex-shrink-0"
|
||||
>
|
||||
Modifier
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{isEditing ? (
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label
|
||||
htmlFor="eventRegistrationPoints"
|
||||
className="block text-sm font-medium text-pixel-gold mb-2"
|
||||
>
|
||||
Points d'inscription
|
||||
</label>
|
||||
<Input
|
||||
id="eventRegistrationPoints"
|
||||
type="number"
|
||||
min="0"
|
||||
value={formData.eventRegistrationPoints}
|
||||
onChange={(e) =>
|
||||
setFormData({
|
||||
...formData,
|
||||
eventRegistrationPoints: e.target.value,
|
||||
})
|
||||
}
|
||||
placeholder="100"
|
||||
className="w-full"
|
||||
/>
|
||||
<p className="text-xs text-gray-400 mt-1">
|
||||
Les utilisateurs gagneront ce nombre de points lors de leur inscription à un événement
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-col sm:flex-row gap-2 pt-4">
|
||||
<Button
|
||||
onClick={handleSave}
|
||||
variant="success"
|
||||
size="md"
|
||||
disabled={isSaving}
|
||||
>
|
||||
{isSaving ? "Enregistrement..." : "Enregistrer"}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleCancel}
|
||||
variant="secondary"
|
||||
size="md"
|
||||
disabled={isSaving}
|
||||
>
|
||||
Annuler
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4">
|
||||
<span className="text-pixel-gold font-bold text-sm sm:text-base min-w-0 sm:min-w-[200px] flex-shrink-0">
|
||||
Points actuels:
|
||||
</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-lg sm:text-xl font-bold text-white">
|
||||
{preferences?.eventRegistrationPoints ?? 100}
|
||||
</span>
|
||||
<span className="text-xs sm:text-sm text-gray-400">points</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1045,6 +1045,8 @@ export const SitePreferencesScalarFieldEnum = {
|
||||
eventsBackground: 'eventsBackground',
|
||||
leaderboardBackground: 'leaderboardBackground',
|
||||
challengesBackground: 'challengesBackground',
|
||||
eventRegistrationPoints: 'eventRegistrationPoints',
|
||||
eventFeedbackPoints: 'eventFeedbackPoints',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
} as const
|
||||
|
||||
@@ -154,6 +154,8 @@ export const SitePreferencesScalarFieldEnum = {
|
||||
eventsBackground: 'eventsBackground',
|
||||
leaderboardBackground: 'leaderboardBackground',
|
||||
challengesBackground: 'challengesBackground',
|
||||
eventRegistrationPoints: 'eventRegistrationPoints',
|
||||
eventFeedbackPoints: 'eventFeedbackPoints',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
} as const
|
||||
|
||||
@@ -20,16 +20,30 @@ export type SitePreferencesModel = runtime.Types.Result.DefaultSelection<Prisma.
|
||||
|
||||
export type AggregateSitePreferences = {
|
||||
_count: SitePreferencesCountAggregateOutputType | null
|
||||
_avg: SitePreferencesAvgAggregateOutputType | null
|
||||
_sum: SitePreferencesSumAggregateOutputType | null
|
||||
_min: SitePreferencesMinAggregateOutputType | null
|
||||
_max: SitePreferencesMaxAggregateOutputType | null
|
||||
}
|
||||
|
||||
export type SitePreferencesAvgAggregateOutputType = {
|
||||
eventRegistrationPoints: number | null
|
||||
eventFeedbackPoints: number | null
|
||||
}
|
||||
|
||||
export type SitePreferencesSumAggregateOutputType = {
|
||||
eventRegistrationPoints: number | null
|
||||
eventFeedbackPoints: number | null
|
||||
}
|
||||
|
||||
export type SitePreferencesMinAggregateOutputType = {
|
||||
id: string | null
|
||||
homeBackground: string | null
|
||||
eventsBackground: string | null
|
||||
leaderboardBackground: string | null
|
||||
challengesBackground: string | null
|
||||
eventRegistrationPoints: number | null
|
||||
eventFeedbackPoints: number | null
|
||||
createdAt: Date | null
|
||||
updatedAt: Date | null
|
||||
}
|
||||
@@ -40,6 +54,8 @@ export type SitePreferencesMaxAggregateOutputType = {
|
||||
eventsBackground: string | null
|
||||
leaderboardBackground: string | null
|
||||
challengesBackground: string | null
|
||||
eventRegistrationPoints: number | null
|
||||
eventFeedbackPoints: number | null
|
||||
createdAt: Date | null
|
||||
updatedAt: Date | null
|
||||
}
|
||||
@@ -50,18 +66,32 @@ export type SitePreferencesCountAggregateOutputType = {
|
||||
eventsBackground: number
|
||||
leaderboardBackground: number
|
||||
challengesBackground: number
|
||||
eventRegistrationPoints: number
|
||||
eventFeedbackPoints: number
|
||||
createdAt: number
|
||||
updatedAt: number
|
||||
_all: number
|
||||
}
|
||||
|
||||
|
||||
export type SitePreferencesAvgAggregateInputType = {
|
||||
eventRegistrationPoints?: true
|
||||
eventFeedbackPoints?: true
|
||||
}
|
||||
|
||||
export type SitePreferencesSumAggregateInputType = {
|
||||
eventRegistrationPoints?: true
|
||||
eventFeedbackPoints?: true
|
||||
}
|
||||
|
||||
export type SitePreferencesMinAggregateInputType = {
|
||||
id?: true
|
||||
homeBackground?: true
|
||||
eventsBackground?: true
|
||||
leaderboardBackground?: true
|
||||
challengesBackground?: true
|
||||
eventRegistrationPoints?: true
|
||||
eventFeedbackPoints?: true
|
||||
createdAt?: true
|
||||
updatedAt?: true
|
||||
}
|
||||
@@ -72,6 +102,8 @@ export type SitePreferencesMaxAggregateInputType = {
|
||||
eventsBackground?: true
|
||||
leaderboardBackground?: true
|
||||
challengesBackground?: true
|
||||
eventRegistrationPoints?: true
|
||||
eventFeedbackPoints?: true
|
||||
createdAt?: true
|
||||
updatedAt?: true
|
||||
}
|
||||
@@ -82,6 +114,8 @@ export type SitePreferencesCountAggregateInputType = {
|
||||
eventsBackground?: true
|
||||
leaderboardBackground?: true
|
||||
challengesBackground?: true
|
||||
eventRegistrationPoints?: true
|
||||
eventFeedbackPoints?: true
|
||||
createdAt?: true
|
||||
updatedAt?: true
|
||||
_all?: true
|
||||
@@ -122,6 +156,18 @@ export type SitePreferencesAggregateArgs<ExtArgs extends runtime.Types.Extension
|
||||
* Count returned SitePreferences
|
||||
**/
|
||||
_count?: true | SitePreferencesCountAggregateInputType
|
||||
/**
|
||||
* {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs}
|
||||
*
|
||||
* Select which fields to average
|
||||
**/
|
||||
_avg?: SitePreferencesAvgAggregateInputType
|
||||
/**
|
||||
* {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs}
|
||||
*
|
||||
* Select which fields to sum
|
||||
**/
|
||||
_sum?: SitePreferencesSumAggregateInputType
|
||||
/**
|
||||
* {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs}
|
||||
*
|
||||
@@ -155,6 +201,8 @@ export type SitePreferencesGroupByArgs<ExtArgs extends runtime.Types.Extensions.
|
||||
take?: number
|
||||
skip?: number
|
||||
_count?: SitePreferencesCountAggregateInputType | true
|
||||
_avg?: SitePreferencesAvgAggregateInputType
|
||||
_sum?: SitePreferencesSumAggregateInputType
|
||||
_min?: SitePreferencesMinAggregateInputType
|
||||
_max?: SitePreferencesMaxAggregateInputType
|
||||
}
|
||||
@@ -165,9 +213,13 @@ export type SitePreferencesGroupByOutputType = {
|
||||
eventsBackground: string | null
|
||||
leaderboardBackground: string | null
|
||||
challengesBackground: string | null
|
||||
eventRegistrationPoints: number
|
||||
eventFeedbackPoints: number
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
_count: SitePreferencesCountAggregateOutputType | null
|
||||
_avg: SitePreferencesAvgAggregateOutputType | null
|
||||
_sum: SitePreferencesSumAggregateOutputType | null
|
||||
_min: SitePreferencesMinAggregateOutputType | null
|
||||
_max: SitePreferencesMaxAggregateOutputType | null
|
||||
}
|
||||
@@ -196,6 +248,8 @@ export type SitePreferencesWhereInput = {
|
||||
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
|
||||
}
|
||||
@@ -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<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
|
||||
@@ -357,6 +451,8 @@ export type SitePreferencesSelect<ExtArgs extends runtime.Types.Extensions.Inter
|
||||
eventsBackground?: boolean
|
||||
leaderboardBackground?: boolean
|
||||
challengesBackground?: boolean
|
||||
eventRegistrationPoints?: boolean
|
||||
eventFeedbackPoints?: boolean
|
||||
createdAt?: boolean
|
||||
updatedAt?: boolean
|
||||
}, ExtArgs["result"]["sitePreferences"]>
|
||||
@@ -367,6 +463,8 @@ export type SitePreferencesSelectCreateManyAndReturn<ExtArgs extends runtime.Typ
|
||||
eventsBackground?: boolean
|
||||
leaderboardBackground?: boolean
|
||||
challengesBackground?: boolean
|
||||
eventRegistrationPoints?: boolean
|
||||
eventFeedbackPoints?: boolean
|
||||
createdAt?: boolean
|
||||
updatedAt?: boolean
|
||||
}, ExtArgs["result"]["sitePreferences"]>
|
||||
@@ -377,6 +475,8 @@ export type SitePreferencesSelectUpdateManyAndReturn<ExtArgs extends runtime.Typ
|
||||
eventsBackground?: boolean
|
||||
leaderboardBackground?: boolean
|
||||
challengesBackground?: boolean
|
||||
eventRegistrationPoints?: boolean
|
||||
eventFeedbackPoints?: boolean
|
||||
createdAt?: boolean
|
||||
updatedAt?: boolean
|
||||
}, ExtArgs["result"]["sitePreferences"]>
|
||||
@@ -387,11 +487,13 @@ export type SitePreferencesSelectScalar = {
|
||||
eventsBackground?: boolean
|
||||
leaderboardBackground?: boolean
|
||||
challengesBackground?: boolean
|
||||
eventRegistrationPoints?: boolean
|
||||
eventFeedbackPoints?: boolean
|
||||
createdAt?: boolean
|
||||
updatedAt?: boolean
|
||||
}
|
||||
|
||||
export type SitePreferencesOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "homeBackground" | "eventsBackground" | "leaderboardBackground" | "challengesBackground" | "createdAt" | "updatedAt", ExtArgs["result"]["sitePreferences"]>
|
||||
export type SitePreferencesOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "homeBackground" | "eventsBackground" | "leaderboardBackground" | "challengesBackground" | "eventRegistrationPoints" | "eventFeedbackPoints" | "createdAt" | "updatedAt", ExtArgs["result"]["sitePreferences"]>
|
||||
|
||||
export type $SitePreferencesPayload<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
|
||||
name: "SitePreferences"
|
||||
@@ -402,6 +504,8 @@ export type $SitePreferencesPayload<ExtArgs extends runtime.Types.Extensions.Int
|
||||
eventsBackground: string | null
|
||||
leaderboardBackground: string | null
|
||||
challengesBackground: string | null
|
||||
eventRegistrationPoints: number
|
||||
eventFeedbackPoints: number
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
}, ExtArgs["result"]["sitePreferences"]>
|
||||
@@ -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'>
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<void> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user