Add feedback management features: Implement functions to add bonus points and mark feedback as read in the FeedbackManagement component. Update EventFeedback model to include isRead property, enhancing user interaction and feedback tracking.

This commit is contained in:
Julien Froidefond
2025-12-16 16:43:53 +01:00
parent 3dd82c2bd4
commit 16e4b63ffd
10 changed files with 387 additions and 16 deletions

127
actions/admin/feedback.ts Normal file
View File

@@ -0,0 +1,127 @@
"use server";
import { revalidatePath } from "next/cache";
import { auth } from "@/lib/auth";
import { prisma } from "@/services/database";
import { Role } from "@/prisma/generated/prisma/client";
import { NotFoundError } from "@/services/errors";
function checkAdminAccess() {
return async () => {
const session = await auth();
if (!session?.user || session.user.role !== Role.ADMIN) {
throw new Error("Accès refusé");
}
return session;
};
}
export async function addFeedbackBonusPoints(
userId: string,
points: number
) {
try {
await checkAdminAccess()();
// Vérifier que l'utilisateur existe
const user = await prisma.user.findUnique({
where: { id: userId },
select: { id: true, score: true },
});
if (!user) {
throw new NotFoundError("Utilisateur");
}
// Ajouter les points
const updatedUser = await prisma.user.update({
where: { id: userId },
data: {
score: {
increment: points,
},
},
select: {
id: true,
username: true,
score: true,
},
});
revalidatePath("/admin");
revalidatePath("/leaderboard");
return {
success: true,
message: `${points} points ajoutés avec succès`,
data: updatedUser,
};
} catch (error) {
console.error("Error adding bonus points:", error);
if (error instanceof NotFoundError) {
return { success: false, error: error.message };
}
if (error instanceof Error && error.message === "Accès refusé") {
return { success: false, error: "Accès refusé" };
}
return {
success: false,
error: "Erreur lors de l'ajout des points",
};
}
}
export async function markFeedbackAsRead(feedbackId: string, isRead: boolean) {
try {
await checkAdminAccess()();
// Vérifier que le feedback existe
const feedback = await prisma.eventFeedback.findUnique({
where: { id: feedbackId },
select: { id: true },
});
if (!feedback) {
throw new NotFoundError("Feedback");
}
// Mettre à jour le statut
const updatedFeedback = await prisma.eventFeedback.update({
where: { id: feedbackId },
data: {
isRead,
},
select: {
id: true,
isRead: true,
},
});
revalidatePath("/admin");
return {
success: true,
message: isRead
? "Feedback marqué comme lu"
: "Feedback marqué comme non lu",
data: updatedFeedback,
};
} catch (error) {
console.error("Error marking feedback as read:", error);
if (error instanceof NotFoundError) {
return { success: false, error: error.message };
}
if (error instanceof Error && error.message === "Accès refusé") {
return { success: false, error: "Accès refusé" };
}
return {
success: false,
error: "Erreur lors de la mise à jour du feedback",
};
}
}

View File

@@ -1,11 +1,18 @@
"use client"; "use client";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import {
addFeedbackBonusPoints,
markFeedbackAsRead,
} from "@/actions/admin/feedback";
import { Button } from "@/components/ui";
import Avatar from "@/components/ui/Avatar";
interface Feedback { interface Feedback {
id: string; id: string;
rating: number; rating: number;
comment: string | null; comment: string | null;
isRead: boolean;
createdAt: string; createdAt: string;
event: { event: {
id: string; id: string;
@@ -17,6 +24,8 @@ interface Feedback {
id: string; id: string;
username: string; username: string;
email: string; email: string;
avatar: string | null;
score: number;
}; };
} }
@@ -35,6 +44,10 @@ export default function FeedbackManagement() {
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [error, setError] = useState(""); const [error, setError] = useState("");
const [selectedEvent, setSelectedEvent] = useState<string | null>(null); const [selectedEvent, setSelectedEvent] = useState<string | null>(null);
const [addingPoints, setAddingPoints] = useState<Record<string, boolean>>(
{}
);
const [markingRead, setMarkingRead] = useState<Record<string, boolean>>({});
useEffect(() => { useEffect(() => {
fetchFeedbacks(); fetchFeedbacks();
@@ -92,9 +105,59 @@ export default function FeedbackManagement() {
); );
}; };
const filteredFeedbacks = selectedEvent const handleAddPoints = async (userId: string, points: number) => {
const key = `${userId}-${points}`;
setAddingPoints((prev) => ({ ...prev, [key]: true }));
setError("");
try {
const result = await addFeedbackBonusPoints(userId, points);
if (result.success) {
// Rafraîchir les données pour voir les nouveaux scores
await fetchFeedbacks();
// Rafraîchir le score dans le header si l'utilisateur est connecté
window.dispatchEvent(new Event("refreshUserScore"));
} else {
setError(result.error || "Erreur lors de l'ajout des points");
}
} catch {
setError("Erreur lors de l'ajout des points");
} finally {
setAddingPoints((prev) => ({ ...prev, [key]: false }));
}
};
const handleMarkAsRead = async (feedbackId: string, isRead: boolean) => {
setMarkingRead((prev) => ({ ...prev, [feedbackId]: true }));
setError("");
try {
const result = await markFeedbackAsRead(feedbackId, isRead);
if (result.success) {
// Rafraîchir les données pour voir le nouveau statut
await fetchFeedbacks();
} else {
setError(result.error || "Erreur lors de la mise à jour");
}
} catch {
setError("Erreur lors de la mise à jour");
} finally {
setMarkingRead((prev) => ({ ...prev, [feedbackId]: false }));
}
};
const filteredFeedbacks = (selectedEvent
? feedbacks.filter((f) => f.event.id === selectedEvent) ? feedbacks.filter((f) => f.event.id === selectedEvent)
: feedbacks; : feedbacks
).sort((a, b) => {
// Trier : non lus en premier, puis par date décroissante
if (a.isRead !== b.isRead) {
return a.isRead ? 1 : -1;
}
return (
new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
);
});
if (loading) { if (loading) {
return ( return (
@@ -184,21 +247,46 @@ export default function FeedbackManagement() {
{filteredFeedbacks.map((feedback) => ( {filteredFeedbacks.map((feedback) => (
<div <div
key={feedback.id} key={feedback.id}
className="bg-black/40 border border-pixel-gold/20 rounded p-3 sm:p-4" className={`bg-black/40 border rounded p-3 sm:p-4 ${
feedback.isRead
? "border-pixel-gold/20 opacity-75"
: "border-pixel-gold/50 bg-pixel-gold/5"
}`}
> >
<div className="flex flex-col sm:flex-row sm:items-start sm:justify-between gap-3 mb-3"> <div className="flex flex-col sm:flex-row sm:items-start sm:justify-between gap-3 mb-3">
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<div className="flex flex-col sm:flex-row sm:items-center gap-1 sm:gap-3 mb-2"> {/* En-tête utilisateur avec avatar */}
<div className="flex items-center gap-2 sm:gap-3 mb-3">
<Avatar
src={feedback.user.avatar}
username={feedback.user.username}
size="md"
borderClassName="border-pixel-gold/30"
/>
<div className="flex-1 min-w-0">
<div className="flex flex-col sm:flex-row sm:items-center gap-1 sm:gap-2 mb-1">
<h4 className="text-white font-semibold text-sm sm:text-base break-words"> <h4 className="text-white font-semibold text-sm sm:text-base break-words">
{feedback.user.username} {feedback.user.username}
</h4> </h4>
<span className="text-pixel-gold font-bold text-xs sm:text-sm">
{feedback.user.score.toLocaleString("fr-FR")} pts
</span>
</div>
<span className="text-gray-500 text-[10px] sm:text-xs break-all"> <span className="text-gray-500 text-[10px] sm:text-xs break-all">
{feedback.user.email} {feedback.user.email}
</span> </span>
</div> </div>
<div className="text-pixel-gold text-xs sm:text-sm font-semibold mb-2 break-words"> </div>
<div className="flex items-center gap-2 mb-2">
<div className="text-pixel-gold text-xs sm:text-sm font-semibold break-words">
{feedback.event.name} {feedback.event.name}
</div> </div>
{!feedback.isRead && (
<span className="bg-pixel-gold/20 text-pixel-gold text-[10px] px-1.5 py-0.5 rounded uppercase font-semibold">
Non lu
</span>
)}
</div>
<div className="text-gray-500 text-[10px] sm:text-xs mb-2"> <div className="text-gray-500 text-[10px] sm:text-xs mb-2">
{new Date(feedback.createdAt).toLocaleDateString( {new Date(feedback.createdAt).toLocaleDateString(
"fr-FR", "fr-FR",
@@ -212,8 +300,23 @@ export default function FeedbackManagement() {
)} )}
</div> </div>
</div> </div>
<div className="flex-shrink-0"> <div className="flex flex-col items-end gap-2 flex-shrink-0">
{renderStars(feedback.rating)} {renderStars(feedback.rating)}
<Button
variant={feedback.isRead ? "secondary" : "success"}
size="sm"
onClick={() =>
handleMarkAsRead(feedback.id, !feedback.isRead)
}
disabled={markingRead[feedback.id]}
className="text-xs whitespace-nowrap"
>
{markingRead[feedback.id]
? "..."
: feedback.isRead
? "Marquer non lu"
: "Marquer lu"}
</Button>
</div> </div>
</div> </div>
{feedback.comment && ( {feedback.comment && (
@@ -223,6 +326,39 @@ export default function FeedbackManagement() {
</p> </p>
</div> </div>
)} )}
{/* Boutons pour ajouter des points bonus */}
<div className="mt-3 pt-3 border-t border-pixel-gold/20 flex flex-wrap gap-2">
<span className="text-gray-400 text-xs sm:text-sm mr-2">
Points bonus:
</span>
<Button
variant="primary"
size="sm"
onClick={() => handleAddPoints(feedback.user.id, 10)}
disabled={addingPoints[`${feedback.user.id}-10`]}
className="text-xs"
>
{addingPoints[`${feedback.user.id}-10`] ? "..." : "+10"}
</Button>
<Button
variant="primary"
size="sm"
onClick={() => handleAddPoints(feedback.user.id, 100)}
disabled={addingPoints[`${feedback.user.id}-100`]}
className="text-xs"
>
{addingPoints[`${feedback.user.id}-100`] ? "..." : "+100"}
</Button>
<Button
variant="primary"
size="sm"
onClick={() => handleAddPoints(feedback.user.id, 1000)}
disabled={addingPoints[`${feedback.user.id}-1000`]}
className="text-xs"
>
{addingPoints[`${feedback.user.id}-1000`] ? "..." : "+1000"}
</Button>
</div>
</div> </div>
))} ))}
</div> </div>

View File

@@ -211,6 +211,19 @@ export type IntNullableWithAggregatesFilter<$PrismaModel = never> = {
_max?: Prisma.NestedIntNullableFilter<$PrismaModel> _max?: Prisma.NestedIntNullableFilter<$PrismaModel>
} }
export type BoolFilter<$PrismaModel = never> = {
equals?: boolean | Prisma.BooleanFieldRefInput<$PrismaModel>
not?: Prisma.NestedBoolFilter<$PrismaModel> | boolean
}
export type BoolWithAggregatesFilter<$PrismaModel = never> = {
equals?: boolean | Prisma.BooleanFieldRefInput<$PrismaModel>
not?: Prisma.NestedBoolWithAggregatesFilter<$PrismaModel> | boolean
_count?: Prisma.NestedIntFilter<$PrismaModel>
_min?: Prisma.NestedBoolFilter<$PrismaModel>
_max?: Prisma.NestedBoolFilter<$PrismaModel>
}
export type EnumChallengeStatusFilter<$PrismaModel = never> = { export type EnumChallengeStatusFilter<$PrismaModel = never> = {
equals?: $Enums.ChallengeStatus | Prisma.EnumChallengeStatusFieldRefInput<$PrismaModel> equals?: $Enums.ChallengeStatus | Prisma.EnumChallengeStatusFieldRefInput<$PrismaModel>
in?: $Enums.ChallengeStatus[] in?: $Enums.ChallengeStatus[]
@@ -467,6 +480,19 @@ export type NestedFloatNullableFilter<$PrismaModel = never> = {
not?: Prisma.NestedFloatNullableFilter<$PrismaModel> | number | null not?: Prisma.NestedFloatNullableFilter<$PrismaModel> | number | null
} }
export type NestedBoolFilter<$PrismaModel = never> = {
equals?: boolean | Prisma.BooleanFieldRefInput<$PrismaModel>
not?: Prisma.NestedBoolFilter<$PrismaModel> | boolean
}
export type NestedBoolWithAggregatesFilter<$PrismaModel = never> = {
equals?: boolean | Prisma.BooleanFieldRefInput<$PrismaModel>
not?: Prisma.NestedBoolWithAggregatesFilter<$PrismaModel> | boolean
_count?: Prisma.NestedIntFilter<$PrismaModel>
_min?: Prisma.NestedBoolFilter<$PrismaModel>
_max?: Prisma.NestedBoolFilter<$PrismaModel>
}
export type NestedEnumChallengeStatusFilter<$PrismaModel = never> = { export type NestedEnumChallengeStatusFilter<$PrismaModel = never> = {
equals?: $Enums.ChallengeStatus | Prisma.EnumChallengeStatusFieldRefInput<$PrismaModel> equals?: $Enums.ChallengeStatus | Prisma.EnumChallengeStatusFieldRefInput<$PrismaModel>
in?: $Enums.ChallengeStatus[] in?: $Enums.ChallengeStatus[]

File diff suppressed because one or more lines are too long

View File

@@ -1032,6 +1032,7 @@ export const EventFeedbackScalarFieldEnum = {
eventId: 'eventId', eventId: 'eventId',
rating: 'rating', rating: 'rating',
comment: 'comment', comment: 'comment',
isRead: 'isRead',
createdAt: 'createdAt', createdAt: 'createdAt',
updatedAt: 'updatedAt' updatedAt: 'updatedAt'
} as const } as const
@@ -1138,6 +1139,13 @@ export type EnumEventTypeFieldRefInput<$PrismaModel> = FieldRefInputType<$Prisma
/**
* Reference to a field of type 'Boolean'
*/
export type BooleanFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Boolean'>
/** /**
* Reference to a field of type 'ChallengeStatus' * Reference to a field of type 'ChallengeStatus'
*/ */

View File

@@ -141,6 +141,7 @@ export const EventFeedbackScalarFieldEnum = {
eventId: 'eventId', eventId: 'eventId',
rating: 'rating', rating: 'rating',
comment: 'comment', comment: 'comment',
isRead: 'isRead',
createdAt: 'createdAt', createdAt: 'createdAt',
updatedAt: 'updatedAt' updatedAt: 'updatedAt'
} as const } as const

View File

@@ -40,6 +40,7 @@ export type EventFeedbackMinAggregateOutputType = {
eventId: string | null eventId: string | null
rating: number | null rating: number | null
comment: string | null comment: string | null
isRead: boolean | null
createdAt: Date | null createdAt: Date | null
updatedAt: Date | null updatedAt: Date | null
} }
@@ -50,6 +51,7 @@ export type EventFeedbackMaxAggregateOutputType = {
eventId: string | null eventId: string | null
rating: number | null rating: number | null
comment: string | null comment: string | null
isRead: boolean | null
createdAt: Date | null createdAt: Date | null
updatedAt: Date | null updatedAt: Date | null
} }
@@ -60,6 +62,7 @@ export type EventFeedbackCountAggregateOutputType = {
eventId: number eventId: number
rating: number rating: number
comment: number comment: number
isRead: number
createdAt: number createdAt: number
updatedAt: number updatedAt: number
_all: number _all: number
@@ -80,6 +83,7 @@ export type EventFeedbackMinAggregateInputType = {
eventId?: true eventId?: true
rating?: true rating?: true
comment?: true comment?: true
isRead?: true
createdAt?: true createdAt?: true
updatedAt?: true updatedAt?: true
} }
@@ -90,6 +94,7 @@ export type EventFeedbackMaxAggregateInputType = {
eventId?: true eventId?: true
rating?: true rating?: true
comment?: true comment?: true
isRead?: true
createdAt?: true createdAt?: true
updatedAt?: true updatedAt?: true
} }
@@ -100,6 +105,7 @@ export type EventFeedbackCountAggregateInputType = {
eventId?: true eventId?: true
rating?: true rating?: true
comment?: true comment?: true
isRead?: true
createdAt?: true createdAt?: true
updatedAt?: true updatedAt?: true
_all?: true _all?: true
@@ -197,6 +203,7 @@ export type EventFeedbackGroupByOutputType = {
eventId: string eventId: string
rating: number rating: number
comment: string | null comment: string | null
isRead: boolean
createdAt: Date createdAt: Date
updatedAt: Date updatedAt: Date
_count: EventFeedbackCountAggregateOutputType | null _count: EventFeedbackCountAggregateOutputType | null
@@ -230,6 +237,7 @@ export type EventFeedbackWhereInput = {
eventId?: Prisma.StringFilter<"EventFeedback"> | string eventId?: Prisma.StringFilter<"EventFeedback"> | string
rating?: Prisma.IntFilter<"EventFeedback"> | number rating?: Prisma.IntFilter<"EventFeedback"> | number
comment?: Prisma.StringNullableFilter<"EventFeedback"> | string | null comment?: Prisma.StringNullableFilter<"EventFeedback"> | string | null
isRead?: Prisma.BoolFilter<"EventFeedback"> | boolean
createdAt?: Prisma.DateTimeFilter<"EventFeedback"> | Date | string createdAt?: Prisma.DateTimeFilter<"EventFeedback"> | Date | string
updatedAt?: Prisma.DateTimeFilter<"EventFeedback"> | Date | string updatedAt?: Prisma.DateTimeFilter<"EventFeedback"> | Date | string
event?: Prisma.XOR<Prisma.EventScalarRelationFilter, Prisma.EventWhereInput> event?: Prisma.XOR<Prisma.EventScalarRelationFilter, Prisma.EventWhereInput>
@@ -242,6 +250,7 @@ export type EventFeedbackOrderByWithRelationInput = {
eventId?: Prisma.SortOrder eventId?: Prisma.SortOrder
rating?: Prisma.SortOrder rating?: Prisma.SortOrder
comment?: Prisma.SortOrderInput | Prisma.SortOrder comment?: Prisma.SortOrderInput | Prisma.SortOrder
isRead?: Prisma.SortOrder
createdAt?: Prisma.SortOrder createdAt?: Prisma.SortOrder
updatedAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder
event?: Prisma.EventOrderByWithRelationInput event?: Prisma.EventOrderByWithRelationInput
@@ -258,6 +267,7 @@ export type EventFeedbackWhereUniqueInput = Prisma.AtLeast<{
eventId?: Prisma.StringFilter<"EventFeedback"> | string eventId?: Prisma.StringFilter<"EventFeedback"> | string
rating?: Prisma.IntFilter<"EventFeedback"> | number rating?: Prisma.IntFilter<"EventFeedback"> | number
comment?: Prisma.StringNullableFilter<"EventFeedback"> | string | null comment?: Prisma.StringNullableFilter<"EventFeedback"> | string | null
isRead?: Prisma.BoolFilter<"EventFeedback"> | boolean
createdAt?: Prisma.DateTimeFilter<"EventFeedback"> | Date | string createdAt?: Prisma.DateTimeFilter<"EventFeedback"> | Date | string
updatedAt?: Prisma.DateTimeFilter<"EventFeedback"> | Date | string updatedAt?: Prisma.DateTimeFilter<"EventFeedback"> | Date | string
event?: Prisma.XOR<Prisma.EventScalarRelationFilter, Prisma.EventWhereInput> event?: Prisma.XOR<Prisma.EventScalarRelationFilter, Prisma.EventWhereInput>
@@ -270,6 +280,7 @@ export type EventFeedbackOrderByWithAggregationInput = {
eventId?: Prisma.SortOrder eventId?: Prisma.SortOrder
rating?: Prisma.SortOrder rating?: Prisma.SortOrder
comment?: Prisma.SortOrderInput | Prisma.SortOrder comment?: Prisma.SortOrderInput | Prisma.SortOrder
isRead?: Prisma.SortOrder
createdAt?: Prisma.SortOrder createdAt?: Prisma.SortOrder
updatedAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder
_count?: Prisma.EventFeedbackCountOrderByAggregateInput _count?: Prisma.EventFeedbackCountOrderByAggregateInput
@@ -288,6 +299,7 @@ export type EventFeedbackScalarWhereWithAggregatesInput = {
eventId?: Prisma.StringWithAggregatesFilter<"EventFeedback"> | string eventId?: Prisma.StringWithAggregatesFilter<"EventFeedback"> | string
rating?: Prisma.IntWithAggregatesFilter<"EventFeedback"> | number rating?: Prisma.IntWithAggregatesFilter<"EventFeedback"> | number
comment?: Prisma.StringNullableWithAggregatesFilter<"EventFeedback"> | string | null comment?: Prisma.StringNullableWithAggregatesFilter<"EventFeedback"> | string | null
isRead?: Prisma.BoolWithAggregatesFilter<"EventFeedback"> | boolean
createdAt?: Prisma.DateTimeWithAggregatesFilter<"EventFeedback"> | Date | string createdAt?: Prisma.DateTimeWithAggregatesFilter<"EventFeedback"> | Date | string
updatedAt?: Prisma.DateTimeWithAggregatesFilter<"EventFeedback"> | Date | string updatedAt?: Prisma.DateTimeWithAggregatesFilter<"EventFeedback"> | Date | string
} }
@@ -296,6 +308,7 @@ export type EventFeedbackCreateInput = {
id?: string id?: string
rating: number rating: number
comment?: string | null comment?: string | null
isRead?: boolean
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
event: Prisma.EventCreateNestedOneWithoutFeedbacksInput event: Prisma.EventCreateNestedOneWithoutFeedbacksInput
@@ -308,6 +321,7 @@ export type EventFeedbackUncheckedCreateInput = {
eventId: string eventId: string
rating: number rating: number
comment?: string | null comment?: string | null
isRead?: boolean
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
} }
@@ -316,6 +330,7 @@ export type EventFeedbackUpdateInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string id?: Prisma.StringFieldUpdateOperationsInput | string
rating?: Prisma.IntFieldUpdateOperationsInput | number rating?: Prisma.IntFieldUpdateOperationsInput | number
comment?: Prisma.NullableStringFieldUpdateOperationsInput | string | null comment?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
isRead?: Prisma.BoolFieldUpdateOperationsInput | boolean
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
event?: Prisma.EventUpdateOneRequiredWithoutFeedbacksNestedInput event?: Prisma.EventUpdateOneRequiredWithoutFeedbacksNestedInput
@@ -328,6 +343,7 @@ export type EventFeedbackUncheckedUpdateInput = {
eventId?: Prisma.StringFieldUpdateOperationsInput | string eventId?: Prisma.StringFieldUpdateOperationsInput | string
rating?: Prisma.IntFieldUpdateOperationsInput | number rating?: Prisma.IntFieldUpdateOperationsInput | number
comment?: Prisma.NullableStringFieldUpdateOperationsInput | string | null comment?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
isRead?: Prisma.BoolFieldUpdateOperationsInput | boolean
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
} }
@@ -338,6 +354,7 @@ export type EventFeedbackCreateManyInput = {
eventId: string eventId: string
rating: number rating: number
comment?: string | null comment?: string | null
isRead?: boolean
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
} }
@@ -346,6 +363,7 @@ export type EventFeedbackUpdateManyMutationInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string id?: Prisma.StringFieldUpdateOperationsInput | string
rating?: Prisma.IntFieldUpdateOperationsInput | number rating?: Prisma.IntFieldUpdateOperationsInput | number
comment?: Prisma.NullableStringFieldUpdateOperationsInput | string | null comment?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
isRead?: Prisma.BoolFieldUpdateOperationsInput | boolean
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
} }
@@ -356,6 +374,7 @@ export type EventFeedbackUncheckedUpdateManyInput = {
eventId?: Prisma.StringFieldUpdateOperationsInput | string eventId?: Prisma.StringFieldUpdateOperationsInput | string
rating?: Prisma.IntFieldUpdateOperationsInput | number rating?: Prisma.IntFieldUpdateOperationsInput | number
comment?: Prisma.NullableStringFieldUpdateOperationsInput | string | null comment?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
isRead?: Prisma.BoolFieldUpdateOperationsInput | boolean
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
} }
@@ -381,6 +400,7 @@ export type EventFeedbackCountOrderByAggregateInput = {
eventId?: Prisma.SortOrder eventId?: Prisma.SortOrder
rating?: Prisma.SortOrder rating?: Prisma.SortOrder
comment?: Prisma.SortOrder comment?: Prisma.SortOrder
isRead?: Prisma.SortOrder
createdAt?: Prisma.SortOrder createdAt?: Prisma.SortOrder
updatedAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder
} }
@@ -395,6 +415,7 @@ export type EventFeedbackMaxOrderByAggregateInput = {
eventId?: Prisma.SortOrder eventId?: Prisma.SortOrder
rating?: Prisma.SortOrder rating?: Prisma.SortOrder
comment?: Prisma.SortOrder comment?: Prisma.SortOrder
isRead?: Prisma.SortOrder
createdAt?: Prisma.SortOrder createdAt?: Prisma.SortOrder
updatedAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder
} }
@@ -405,6 +426,7 @@ export type EventFeedbackMinOrderByAggregateInput = {
eventId?: Prisma.SortOrder eventId?: Prisma.SortOrder
rating?: Prisma.SortOrder rating?: Prisma.SortOrder
comment?: Prisma.SortOrder comment?: Prisma.SortOrder
isRead?: Prisma.SortOrder
createdAt?: Prisma.SortOrder createdAt?: Prisma.SortOrder
updatedAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder
} }
@@ -497,10 +519,15 @@ export type EventFeedbackUncheckedUpdateManyWithoutEventNestedInput = {
deleteMany?: Prisma.EventFeedbackScalarWhereInput | Prisma.EventFeedbackScalarWhereInput[] deleteMany?: Prisma.EventFeedbackScalarWhereInput | Prisma.EventFeedbackScalarWhereInput[]
} }
export type BoolFieldUpdateOperationsInput = {
set?: boolean
}
export type EventFeedbackCreateWithoutUserInput = { export type EventFeedbackCreateWithoutUserInput = {
id?: string id?: string
rating: number rating: number
comment?: string | null comment?: string | null
isRead?: boolean
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
event: Prisma.EventCreateNestedOneWithoutFeedbacksInput event: Prisma.EventCreateNestedOneWithoutFeedbacksInput
@@ -511,6 +538,7 @@ export type EventFeedbackUncheckedCreateWithoutUserInput = {
eventId: string eventId: string
rating: number rating: number
comment?: string | null comment?: string | null
isRead?: boolean
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
} }
@@ -549,6 +577,7 @@ export type EventFeedbackScalarWhereInput = {
eventId?: Prisma.StringFilter<"EventFeedback"> | string eventId?: Prisma.StringFilter<"EventFeedback"> | string
rating?: Prisma.IntFilter<"EventFeedback"> | number rating?: Prisma.IntFilter<"EventFeedback"> | number
comment?: Prisma.StringNullableFilter<"EventFeedback"> | string | null comment?: Prisma.StringNullableFilter<"EventFeedback"> | string | null
isRead?: Prisma.BoolFilter<"EventFeedback"> | boolean
createdAt?: Prisma.DateTimeFilter<"EventFeedback"> | Date | string createdAt?: Prisma.DateTimeFilter<"EventFeedback"> | Date | string
updatedAt?: Prisma.DateTimeFilter<"EventFeedback"> | Date | string updatedAt?: Prisma.DateTimeFilter<"EventFeedback"> | Date | string
} }
@@ -557,6 +586,7 @@ export type EventFeedbackCreateWithoutEventInput = {
id?: string id?: string
rating: number rating: number
comment?: string | null comment?: string | null
isRead?: boolean
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
user: Prisma.UserCreateNestedOneWithoutEventFeedbacksInput user: Prisma.UserCreateNestedOneWithoutEventFeedbacksInput
@@ -567,6 +597,7 @@ export type EventFeedbackUncheckedCreateWithoutEventInput = {
userId: string userId: string
rating: number rating: number
comment?: string | null comment?: string | null
isRead?: boolean
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
} }
@@ -601,6 +632,7 @@ export type EventFeedbackCreateManyUserInput = {
eventId: string eventId: string
rating: number rating: number
comment?: string | null comment?: string | null
isRead?: boolean
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
} }
@@ -609,6 +641,7 @@ export type EventFeedbackUpdateWithoutUserInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string id?: Prisma.StringFieldUpdateOperationsInput | string
rating?: Prisma.IntFieldUpdateOperationsInput | number rating?: Prisma.IntFieldUpdateOperationsInput | number
comment?: Prisma.NullableStringFieldUpdateOperationsInput | string | null comment?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
isRead?: Prisma.BoolFieldUpdateOperationsInput | boolean
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
event?: Prisma.EventUpdateOneRequiredWithoutFeedbacksNestedInput event?: Prisma.EventUpdateOneRequiredWithoutFeedbacksNestedInput
@@ -619,6 +652,7 @@ export type EventFeedbackUncheckedUpdateWithoutUserInput = {
eventId?: Prisma.StringFieldUpdateOperationsInput | string eventId?: Prisma.StringFieldUpdateOperationsInput | string
rating?: Prisma.IntFieldUpdateOperationsInput | number rating?: Prisma.IntFieldUpdateOperationsInput | number
comment?: Prisma.NullableStringFieldUpdateOperationsInput | string | null comment?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
isRead?: Prisma.BoolFieldUpdateOperationsInput | boolean
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
} }
@@ -628,6 +662,7 @@ export type EventFeedbackUncheckedUpdateManyWithoutUserInput = {
eventId?: Prisma.StringFieldUpdateOperationsInput | string eventId?: Prisma.StringFieldUpdateOperationsInput | string
rating?: Prisma.IntFieldUpdateOperationsInput | number rating?: Prisma.IntFieldUpdateOperationsInput | number
comment?: Prisma.NullableStringFieldUpdateOperationsInput | string | null comment?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
isRead?: Prisma.BoolFieldUpdateOperationsInput | boolean
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
} }
@@ -637,6 +672,7 @@ export type EventFeedbackCreateManyEventInput = {
userId: string userId: string
rating: number rating: number
comment?: string | null comment?: string | null
isRead?: boolean
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
} }
@@ -645,6 +681,7 @@ export type EventFeedbackUpdateWithoutEventInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string id?: Prisma.StringFieldUpdateOperationsInput | string
rating?: Prisma.IntFieldUpdateOperationsInput | number rating?: Prisma.IntFieldUpdateOperationsInput | number
comment?: Prisma.NullableStringFieldUpdateOperationsInput | string | null comment?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
isRead?: Prisma.BoolFieldUpdateOperationsInput | boolean
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
user?: Prisma.UserUpdateOneRequiredWithoutEventFeedbacksNestedInput user?: Prisma.UserUpdateOneRequiredWithoutEventFeedbacksNestedInput
@@ -655,6 +692,7 @@ export type EventFeedbackUncheckedUpdateWithoutEventInput = {
userId?: Prisma.StringFieldUpdateOperationsInput | string userId?: Prisma.StringFieldUpdateOperationsInput | string
rating?: Prisma.IntFieldUpdateOperationsInput | number rating?: Prisma.IntFieldUpdateOperationsInput | number
comment?: Prisma.NullableStringFieldUpdateOperationsInput | string | null comment?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
isRead?: Prisma.BoolFieldUpdateOperationsInput | boolean
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
} }
@@ -664,6 +702,7 @@ export type EventFeedbackUncheckedUpdateManyWithoutEventInput = {
userId?: Prisma.StringFieldUpdateOperationsInput | string userId?: Prisma.StringFieldUpdateOperationsInput | string
rating?: Prisma.IntFieldUpdateOperationsInput | number rating?: Prisma.IntFieldUpdateOperationsInput | number
comment?: Prisma.NullableStringFieldUpdateOperationsInput | string | null comment?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
isRead?: Prisma.BoolFieldUpdateOperationsInput | boolean
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
} }
@@ -676,6 +715,7 @@ export type EventFeedbackSelect<ExtArgs extends runtime.Types.Extensions.Interna
eventId?: boolean eventId?: boolean
rating?: boolean rating?: boolean
comment?: boolean comment?: boolean
isRead?: boolean
createdAt?: boolean createdAt?: boolean
updatedAt?: boolean updatedAt?: boolean
event?: boolean | Prisma.EventDefaultArgs<ExtArgs> event?: boolean | Prisma.EventDefaultArgs<ExtArgs>
@@ -688,6 +728,7 @@ export type EventFeedbackSelectCreateManyAndReturn<ExtArgs extends runtime.Types
eventId?: boolean eventId?: boolean
rating?: boolean rating?: boolean
comment?: boolean comment?: boolean
isRead?: boolean
createdAt?: boolean createdAt?: boolean
updatedAt?: boolean updatedAt?: boolean
event?: boolean | Prisma.EventDefaultArgs<ExtArgs> event?: boolean | Prisma.EventDefaultArgs<ExtArgs>
@@ -700,6 +741,7 @@ export type EventFeedbackSelectUpdateManyAndReturn<ExtArgs extends runtime.Types
eventId?: boolean eventId?: boolean
rating?: boolean rating?: boolean
comment?: boolean comment?: boolean
isRead?: boolean
createdAt?: boolean createdAt?: boolean
updatedAt?: boolean updatedAt?: boolean
event?: boolean | Prisma.EventDefaultArgs<ExtArgs> event?: boolean | Prisma.EventDefaultArgs<ExtArgs>
@@ -712,11 +754,12 @@ export type EventFeedbackSelectScalar = {
eventId?: boolean eventId?: boolean
rating?: boolean rating?: boolean
comment?: boolean comment?: boolean
isRead?: boolean
createdAt?: boolean createdAt?: boolean
updatedAt?: boolean updatedAt?: boolean
} }
export type EventFeedbackOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "userId" | "eventId" | "rating" | "comment" | "createdAt" | "updatedAt", ExtArgs["result"]["eventFeedback"]> export type EventFeedbackOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "userId" | "eventId" | "rating" | "comment" | "isRead" | "createdAt" | "updatedAt", ExtArgs["result"]["eventFeedback"]>
export type EventFeedbackInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = { export type EventFeedbackInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
event?: boolean | Prisma.EventDefaultArgs<ExtArgs> event?: boolean | Prisma.EventDefaultArgs<ExtArgs>
user?: boolean | Prisma.UserDefaultArgs<ExtArgs> user?: boolean | Prisma.UserDefaultArgs<ExtArgs>
@@ -742,6 +785,7 @@ export type $EventFeedbackPayload<ExtArgs extends runtime.Types.Extensions.Inter
eventId: string eventId: string
rating: number rating: number
comment: string | null comment: string | null
isRead: boolean
createdAt: Date createdAt: Date
updatedAt: Date updatedAt: Date
}, ExtArgs["result"]["eventFeedback"]> }, ExtArgs["result"]["eventFeedback"]>
@@ -1174,6 +1218,7 @@ export interface EventFeedbackFieldRefs {
readonly eventId: Prisma.FieldRef<"EventFeedback", 'String'> readonly eventId: Prisma.FieldRef<"EventFeedback", 'String'>
readonly rating: Prisma.FieldRef<"EventFeedback", 'Int'> readonly rating: Prisma.FieldRef<"EventFeedback", 'Int'>
readonly comment: Prisma.FieldRef<"EventFeedback", 'String'> readonly comment: Prisma.FieldRef<"EventFeedback", 'String'>
readonly isRead: Prisma.FieldRef<"EventFeedback", 'Boolean'>
readonly createdAt: Prisma.FieldRef<"EventFeedback", 'DateTime'> readonly createdAt: Prisma.FieldRef<"EventFeedback", 'DateTime'>
readonly updatedAt: Prisma.FieldRef<"EventFeedback", 'DateTime'> readonly updatedAt: Prisma.FieldRef<"EventFeedback", 'DateTime'>
} }

View File

@@ -0,0 +1,24 @@
-- RedefineTables
PRAGMA defer_foreign_keys=ON;
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_EventFeedback" (
"id" TEXT NOT NULL PRIMARY KEY,
"userId" TEXT NOT NULL,
"eventId" TEXT NOT NULL,
"rating" INTEGER NOT NULL,
"comment" TEXT,
"isRead" BOOLEAN NOT NULL DEFAULT false,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "EventFeedback_eventId_fkey" FOREIGN KEY ("eventId") REFERENCES "Event" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "EventFeedback_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
INSERT INTO "new_EventFeedback" ("comment", "createdAt", "eventId", "id", "rating", "updatedAt", "userId") SELECT "comment", "createdAt", "eventId", "id", "rating", "updatedAt", "userId" FROM "EventFeedback";
DROP TABLE "EventFeedback";
ALTER TABLE "new_EventFeedback" RENAME TO "EventFeedback";
CREATE INDEX "EventFeedback_userId_idx" ON "EventFeedback"("userId");
CREATE INDEX "EventFeedback_eventId_idx" ON "EventFeedback"("eventId");
CREATE INDEX "EventFeedback_isRead_idx" ON "EventFeedback"("isRead");
CREATE UNIQUE INDEX "EventFeedback_userId_eventId_key" ON "EventFeedback"("userId", "eventId");
PRAGMA foreign_keys=ON;
PRAGMA defer_foreign_keys=OFF;

View File

@@ -84,6 +84,7 @@ model EventFeedback {
eventId String eventId String
rating Int rating Int
comment String? comment String?
isRead Boolean @default(false)
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
event Event @relation(fields: [eventId], references: [id], onDelete: Cascade) event Event @relation(fields: [eventId], references: [id], onDelete: Cascade)
@@ -92,6 +93,7 @@ model EventFeedback {
@@unique([userId, eventId]) @@unique([userId, eventId])
@@index([userId]) @@index([userId])
@@index([eventId]) @@index([eventId])
@@index([isRead])
} }
model SitePreferences { model SitePreferences {

View File

@@ -98,6 +98,8 @@ export class EventFeedbackService {
id: true, id: true,
username: true, username: true,
email: true, email: true,
avatar: true,
score: true,
}, },
}, },
}, },