From 54a90bd0e66b3237277d13463c5dd81a77272b7c Mon Sep 17 00:00:00 2001 From: Dominik Borbuliak Date: Sun, 15 Dec 2024 12:47:02 +0100 Subject: [PATCH 1/3] feat: Implemented quiz edit --- .../(app)/auth/quiz/[quizId]/edit/page.tsx | 15 +++++- .../quiz/detail/quiz-detail-my-attempts.tsx | 2 +- .../detail/quiz-detail-other-attempts.tsx | 2 +- .../components/quiz/quiz-form/quiz-form.tsx | 35 +++++++++++--- .../quiz-form/quiz-questions-form-part.tsx | 16 +++++-- quizeek/src/db/queries/index.ts | 2 +- quizeek/src/db/queries/quiz-attempt.ts | 9 ++-- quizeek/src/db/queries/quiz.ts | 48 +++++++++++++++---- quizeek/src/db/schema/quiz.ts | 4 +- quizeek/src/hooks/quiz.ts | 3 +- quizeek/src/models/quiz.ts | 1 + .../create-quiz-attempt-action.ts | 4 +- .../quiz/activate-quiz-action.ts | 4 +- .../quiz/submit-quiz-form-action.ts | 34 +++++++++++-- .../server-actions/user/update-user-action.ts | 4 +- quizeek/src/utils/error.ts | 10 ++-- quizeek/src/utils/number.ts | 8 +++- 17 files changed, 153 insertions(+), 48 deletions(-) diff --git a/quizeek/src/app/(app)/auth/quiz/[quizId]/edit/page.tsx b/quizeek/src/app/(app)/auth/quiz/[quizId]/edit/page.tsx index 5d54cf0..1a6aa06 100644 --- a/quizeek/src/app/(app)/auth/quiz/[quizId]/edit/page.tsx +++ b/quizeek/src/app/(app)/auth/quiz/[quizId]/edit/page.tsx @@ -1,5 +1,16 @@ -const Page = async () => { - return

Quiz edit

; +import QuizForm from '@/components/quiz/quiz-form/quiz-form'; +import { getEditableQuiz } from '@/db/queries'; + +type PageParams = { + params: Promise<{ + quizId: string; + }>; +}; + +const Page = async ({ params }: PageParams) => { + const editableQuiz = await getEditableQuiz((await params).quizId); + + return ; }; export default Page; diff --git a/quizeek/src/components/quiz/detail/quiz-detail-my-attempts.tsx b/quizeek/src/components/quiz/detail/quiz-detail-my-attempts.tsx index 95452ab..f1956b8 100644 --- a/quizeek/src/components/quiz/detail/quiz-detail-my-attempts.tsx +++ b/quizeek/src/components/quiz/detail/quiz-detail-my-attempts.tsx @@ -1,5 +1,5 @@ import { Card, CardContent, CardTitle } from '@/components/ui/card'; -import { getMyQuizAttempts } from '@/db/queries/quiz-attempt'; +import { getMyQuizAttempts } from '@/db/queries'; import { QuizWithUser } from '@/db/schema/quiz'; import { toLocalDateTimeString } from '@/utils/date'; import { SquareArrowRight } from 'lucide-react'; diff --git a/quizeek/src/components/quiz/detail/quiz-detail-other-attempts.tsx b/quizeek/src/components/quiz/detail/quiz-detail-other-attempts.tsx index 02d6722..8ebe820 100644 --- a/quizeek/src/components/quiz/detail/quiz-detail-other-attempts.tsx +++ b/quizeek/src/components/quiz/detail/quiz-detail-other-attempts.tsx @@ -1,5 +1,5 @@ import { Card, CardContent, CardTitle } from '@/components/ui/card'; -import { getOtherQuizAttempts } from '@/db/queries/quiz-attempt'; +import { getOtherQuizAttempts } from '@/db/queries'; import { QuizWithUser } from '@/db/schema/quiz'; import { toLocalDateTimeString } from '@/utils/date'; import { CircleUserRound } from 'lucide-react'; diff --git a/quizeek/src/components/quiz/quiz-form/quiz-form.tsx b/quizeek/src/components/quiz/quiz-form/quiz-form.tsx index 3b9352d..83621b1 100644 --- a/quizeek/src/components/quiz/quiz-form/quiz-form.tsx +++ b/quizeek/src/components/quiz/quiz-form/quiz-form.tsx @@ -8,8 +8,13 @@ import { AccordionTrigger, } from '@/components/ui/accordion'; import { Form } from '@/components/ui/form'; -import { QuizForm as QuizFormData, quizFormSchema } from '@/db/schema/quiz'; +import { + EditableQuiz, + QuizForm as QuizFormData, + quizFormSchema, +} from '@/db/schema/quiz'; import { useSubmitQuizFormMutation } from '@/hooks/quiz'; +import { toQuizDuration } from '@/utils'; import { useUploadThing } from '@/utils/uploadthing'; import { zodResolver } from '@hookform/resolvers/zod'; import { redirect } from 'next/navigation'; @@ -20,15 +25,33 @@ import { toast } from 'sonner'; import QuizInfoFormPart from './quiz-info-form-part'; import QuizQuestionsFormPart from './quiz-questions-form-part'; -const QuizForm = () => { +type QuizFormProps = { + editableQuiz?: EditableQuiz; +}; + +const QuizForm = ({ editableQuiz }: QuizFormProps) => { const [files, setFiles] = useState([]); const form = useForm({ resolver: zodResolver(quizFormSchema), defaultValues: { - title: '', - isActive: false, - questions: [], + title: editableQuiz?.title ?? '', + description: editableQuiz?.description ?? '', + duration: toQuizDuration(editableQuiz?.timeLimitSeconds), + isActive: editableQuiz?.isActive ?? false, + imageUrl: editableQuiz?.imageUrl ?? undefined, + questions: + editableQuiz?.questions.map((q) => ({ + id: q.id, + text: q.text ?? '', + number: q.number, + choices: q.choices.map((c) => ({ + id: c.id, + text: c.text, + points: c.points, + isCorrect: c.isCorrect, + })), + })) ?? [], }, }); @@ -42,7 +65,7 @@ const QuizForm = () => { const onSubmit = async (data: QuizFormData) => { await submitQuizFormMutation.mutateAsync( - { data, file: files[0], startUpload }, + { id: editableQuiz?.id, data, file: files[0], startUpload }, { onSuccess: async (quizId) => { toast.success('Successfully submitted form'); diff --git a/quizeek/src/components/quiz/quiz-form/quiz-questions-form-part.tsx b/quizeek/src/components/quiz/quiz-form/quiz-questions-form-part.tsx index 2f14696..04885eb 100644 --- a/quizeek/src/components/quiz/quiz-form/quiz-questions-form-part.tsx +++ b/quizeek/src/components/quiz/quiz-form/quiz-questions-form-part.tsx @@ -81,7 +81,7 @@ const QuizQuestionsFormPart = () => { key: string, value: T ) => { - setQuestions( + setQuestions((questions) => questions.map((q) => q.id === questionId ? { @@ -227,14 +227,20 @@ const QuizQuestionsFormPart = () => { decimalScale={0} placeholder="Points" value={choice.points} - onChange={(e) => + onChange={(e) => { updateChoice( question.id, choice.id, 'points', parseInt(e.currentTarget.value) - ) - } + ); + updateChoice( + question.id, + choice.id, + 'isCorrect', + parseInt(e.currentTarget.value) > 0 + ); + }} /> { @@ -249,7 +255,7 @@ const QuizQuestionsFormPart = () => { updateChoice( question.id, diff --git a/quizeek/src/db/queries/index.ts b/quizeek/src/db/queries/index.ts index dc986ee..f9fc950 100644 --- a/quizeek/src/db/queries/index.ts +++ b/quizeek/src/db/queries/index.ts @@ -1,6 +1,6 @@ // export * from './answer'; // export * from './choice'; // export * from './question'; -// export * from './quiz-attempt'; // export * from './user'; export * from './quiz'; +export * from './quiz-attempt'; diff --git a/quizeek/src/db/queries/quiz-attempt.ts b/quizeek/src/db/queries/quiz-attempt.ts index 7eff819..ee55770 100644 --- a/quizeek/src/db/queries/quiz-attempt.ts +++ b/quizeek/src/db/queries/quiz-attempt.ts @@ -1,4 +1,5 @@ import { auth } from '@/auth'; +import { handleError } from '@/utils'; import { and, eq, getTableColumns, lt, ne, sql } from 'drizzle-orm'; import { db } from '..'; @@ -35,8 +36,8 @@ export const getMyQuizAttempts = async ( .orderBy(sql`${quizAttempts.timestamp} desc`); return myQuizAttempts; - } catch { - throw new Error('Failed to load quiz attempts.'); + } catch (error) { + throw handleError(error); } }; @@ -67,7 +68,7 @@ export const getOtherQuizAttempts = async ( .orderBy(sql`${quizAttempts.timestamp} desc`); return otherQuizAttempts; - } catch { - throw new Error('Failed to load quiz attempts.'); + } catch (error) { + throw handleError(error); } }; diff --git a/quizeek/src/db/queries/quiz.ts b/quizeek/src/db/queries/quiz.ts index 0421d7c..1242c2a 100644 --- a/quizeek/src/db/queries/quiz.ts +++ b/quizeek/src/db/queries/quiz.ts @@ -1,10 +1,12 @@ 'use server'; import { auth } from '@/auth'; +import { InvalidSessionError } from '@/models'; +import { handleError } from '@/utils'; import { and, eq, getTableColumns, like, or } from 'drizzle-orm'; import { db } from '..'; -import { quizes, QuizWithUser } from '../schema/quiz'; +import { EditableQuiz, quizes, QuizWithUser } from '../schema/quiz'; import { quizAttempts } from '../schema/quiz-attempt'; import { users } from '../schema/user'; @@ -24,8 +26,8 @@ export const getActiveQuizes = async ( }); return dbQuizes; - } catch { - throw new Error('Failed to load quizes.'); + } catch (error) { + throw handleError(error); } }; @@ -39,8 +41,8 @@ export const getQuizById = async ( }); return quiz; - } catch { - throw new Error('Failed to load quiz.'); + } catch (error) { + throw handleError(error); } }; @@ -64,8 +66,8 @@ export const getMyQuizes = async ( }); return dbQuizes; - } catch { - throw new Error('Failed to load quizes.'); + } catch (error) { + throw handleError(error); } }; @@ -97,7 +99,35 @@ export const getTakenQuizes = async ( ); return dbQuizes; - } catch { - throw new Error('Failed to load quizes.'); + } catch (error) { + throw handleError(error); + } +}; + +export const getEditableQuiz = async (id: string): Promise => { + try { + const session = await auth(); + + const dbQuiz = await db.query.quizes.findFirst({ + where: and( + eq(quizes.id, id), + eq(quizes.createdBy, session?.user.id ?? '') + ), + with: { + questions: { + with: { + choices: true, + }, + }, + }, + }); + + if (!dbQuiz) { + throw new InvalidSessionError('User is not creator of the quiz'); + } + + return dbQuiz; + } catch (error) { + throw handleError(error); } }; diff --git a/quizeek/src/db/schema/quiz.ts b/quizeek/src/db/schema/quiz.ts index ca41568..5e4e590 100644 --- a/quizeek/src/db/schema/quiz.ts +++ b/quizeek/src/db/schema/quiz.ts @@ -3,7 +3,7 @@ import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'; import { v7 as uuid } from 'uuid'; import { z } from 'zod'; -import { questions } from './question'; +import { questions, QuestionWithChoices } from './question'; import { quizAttempts } from './quiz-attempt'; import { User, users } from './user'; @@ -30,6 +30,8 @@ export type Quiz = InferSelectModel; export type QuizWithUser = Quiz & { creator: User }; +export type EditableQuiz = Quiz & { questions: QuestionWithChoices[] }; + export const quizFormSchema = z.object({ title: z .string({ required_error: 'Title can not be empty' }) diff --git a/quizeek/src/hooks/quiz.ts b/quizeek/src/hooks/quiz.ts index 375b34e..0ff830e 100644 --- a/quizeek/src/hooks/quiz.ts +++ b/quizeek/src/hooks/quiz.ts @@ -5,6 +5,7 @@ import { useMutation } from '@tanstack/react-query'; export const useSubmitQuizFormMutation = () => useMutation({ mutationFn: async ({ + id, data, file, startUpload, @@ -18,7 +19,7 @@ export const useSubmitQuizFormMutation = () => } } - return await submitQuizFormAction(data); + return await submitQuizFormAction(data, id); }, }); diff --git a/quizeek/src/models/quiz.ts b/quizeek/src/models/quiz.ts index 17cb97f..b8869c9 100644 --- a/quizeek/src/models/quiz.ts +++ b/quizeek/src/models/quiz.ts @@ -2,6 +2,7 @@ import { QuizForm } from '@/db/schema/quiz'; import { ClientUploadedFileData } from 'uploadthing/types'; export type SubmitQuizFormMutationType = { + id?: string; data: QuizForm; file: File; startUpload: ( diff --git a/quizeek/src/server-actions/quiz-attempt/create-quiz-attempt-action.ts b/quizeek/src/server-actions/quiz-attempt/create-quiz-attempt-action.ts index d8ff37f..b7a9b26 100644 --- a/quizeek/src/server-actions/quiz-attempt/create-quiz-attempt-action.ts +++ b/quizeek/src/server-actions/quiz-attempt/create-quiz-attempt-action.ts @@ -3,7 +3,7 @@ import { auth } from '@/auth'; import { db } from '@/db'; import { quizAttempts } from '@/db/schema/quiz-attempt'; -import { handleServerActionError } from '@/utils'; +import { handleError } from '@/utils'; export const createQuizAttemptAction = async ( quizId: string @@ -18,6 +18,6 @@ export const createQuizAttemptAction = async ( return createdQuiz[0].id; } catch (error) { - return handleServerActionError(error); + throw handleError(error); } }; diff --git a/quizeek/src/server-actions/quiz/activate-quiz-action.ts b/quizeek/src/server-actions/quiz/activate-quiz-action.ts index b0ba343..b548fa2 100644 --- a/quizeek/src/server-actions/quiz/activate-quiz-action.ts +++ b/quizeek/src/server-actions/quiz/activate-quiz-action.ts @@ -3,7 +3,7 @@ import { db } from '@/db'; import { quizes } from '@/db/schema/quiz'; import { InvalidDataError } from '@/models'; -import { handleServerActionError } from '@/utils'; +import { handleError } from '@/utils'; import { eq } from 'drizzle-orm'; import { revalidatePath } from 'next/cache'; @@ -21,6 +21,6 @@ export const activateQuizAction = async (quizId: string): Promise => { revalidatePath(`/quiz/${quizId}`); } catch (error) { - handleServerActionError(error); + throw handleError(error); } }; diff --git a/quizeek/src/server-actions/quiz/submit-quiz-form-action.ts b/quizeek/src/server-actions/quiz/submit-quiz-form-action.ts index ba4b6d6..56eefd6 100644 --- a/quizeek/src/server-actions/quiz/submit-quiz-form-action.ts +++ b/quizeek/src/server-actions/quiz/submit-quiz-form-action.ts @@ -6,9 +6,10 @@ import { choices } from '@/db/schema/choice'; import { questions, QuestionType } from '@/db/schema/question'; import { quizes, QuizForm, quizFormSchema } from '@/db/schema/quiz'; import { InvalidDataError, InvalidSessionError } from '@/models'; -import { handleServerActionError } from '@/utils'; +import { handleError } from '@/utils'; +import { and, eq, inArray } from 'drizzle-orm'; -export const submitQuizFormAction = async (body: QuizForm) => { +export const submitQuizFormAction = async (body: QuizForm, id?: string) => { try { const session = await auth(); @@ -31,6 +32,32 @@ export const submitQuizFormAction = async (body: QuizForm) => { return await db.transaction(async (tx) => { try { + if (id) { + const questionsToDelete = await tx.query.questions.findMany({ + where: eq(questions.quizId, id), + }); + + await tx.delete(choices).where( + inArray( + choices.questionId, + questionsToDelete.map((q) => q.id) + ) + ); + + await tx.delete(questions).where(eq(questions.quizId, id)); + + const deletedQuiz = await tx + .delete(quizes) + .where( + and(eq(quizes.id, id), eq(quizes.createdBy, session.user.id)) + ) + .returning(); + + if (deletedQuiz.length !== 1) { + throw new InvalidDataError('Quiz not found'); + } + } + const quizToCreate = { createdBy: session.user.id, timeLimitSeconds, @@ -95,7 +122,6 @@ export const submitQuizFormAction = async (body: QuizForm) => { } }); } catch (error) { - handleServerActionError(error); - return ''; + throw handleError(error); } }; diff --git a/quizeek/src/server-actions/user/update-user-action.ts b/quizeek/src/server-actions/user/update-user-action.ts index 9d8eb61..028c62b 100644 --- a/quizeek/src/server-actions/user/update-user-action.ts +++ b/quizeek/src/server-actions/user/update-user-action.ts @@ -3,7 +3,7 @@ import { db } from '@/db'; import { UpdateUser, updateUserSchema, users } from '@/db/schema/user'; import { InvalidDataError } from '@/models'; -import { handleServerActionError } from '@/utils'; +import { handleError } from '@/utils'; import { eq } from 'drizzle-orm'; import { revalidatePath } from 'next/cache'; @@ -23,6 +23,6 @@ export const updateUserAction = async (body: UpdateUser) => { revalidatePath('/auth/profile'); } catch (error) { - handleServerActionError(error); + throw handleError(error); } }; diff --git a/quizeek/src/utils/error.ts b/quizeek/src/utils/error.ts index de4b309..b7d102e 100644 --- a/quizeek/src/utils/error.ts +++ b/quizeek/src/utils/error.ts @@ -1,18 +1,18 @@ import { InvalidDataError, InvalidSessionError } from '@/models'; import { ZodError } from 'zod'; -export const handleServerActionError = (error: unknown) => { +export const handleError = (error: unknown) => { if (error instanceof InvalidDataError) { - throw error; + return error; } if (error instanceof InvalidSessionError) { - throw error; + return error; } if (error instanceof ZodError) { - throw new InvalidDataError(error.errors.map((e) => e.message).join(' | ')); + return new InvalidDataError(error.errors.map((e) => e.message).join(' | ')); } - throw new Error('Something went wrong'); + return new Error('Something went wrong'); }; diff --git a/quizeek/src/utils/number.ts b/quizeek/src/utils/number.ts index 75730cb..ea187bd 100644 --- a/quizeek/src/utils/number.ts +++ b/quizeek/src/utils/number.ts @@ -1,7 +1,11 @@ import { Duration } from 'luxon'; -export const toQuizDuration = (seconds: number) => { +export const toQuizDuration = (seconds?: number) => { + if (!seconds) { + return ''; + } + const quizDuration = Duration.fromObject({ seconds }); - return quizDuration.toFormat(`h'h' mm'min' ss's`); + return quizDuration.toFormat(`h'h' mm'm' ss's`); }; From 2f5ee0228dde98409c2dd8e4bf5d4c446756e166 Mon Sep 17 00:00:00 2001 From: Dominik Borbuliak Date: Sun, 15 Dec 2024 13:02:24 +0100 Subject: [PATCH 2/3] feat: Added quiz delete --- .../quiz/detail/quiz-activate-dialog.tsx | 2 +- .../quiz/detail/quiz-detail-actions.tsx | 28 ++++++++-- quizeek/src/hooks/quiz.ts | 6 +++ .../server-actions/quiz/delete-quiz-action.ts | 51 +++++++++++++++++++ .../quiz/submit-quiz-form-action.ts | 2 +- 5 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 quizeek/src/server-actions/quiz/delete-quiz-action.ts diff --git a/quizeek/src/components/quiz/detail/quiz-activate-dialog.tsx b/quizeek/src/components/quiz/detail/quiz-activate-dialog.tsx index 484636a..d8e7b88 100644 --- a/quizeek/src/components/quiz/detail/quiz-activate-dialog.tsx +++ b/quizeek/src/components/quiz/detail/quiz-activate-dialog.tsx @@ -34,7 +34,7 @@ export const QuizActivateDialog = ({ quiz }: QuizActivateDialogProps) => { return ( - + diff --git a/quizeek/src/components/quiz/detail/quiz-detail-actions.tsx b/quizeek/src/components/quiz/detail/quiz-detail-actions.tsx index 2dcf930..4cff66a 100644 --- a/quizeek/src/components/quiz/detail/quiz-detail-actions.tsx +++ b/quizeek/src/components/quiz/detail/quiz-detail-actions.tsx @@ -4,10 +4,10 @@ import ActionButton from '@/components/action-button'; import { SignInButton } from '@/components/sign-in-button'; import { Button } from '@/components/ui/button'; import { QuizWithUser } from '@/db/schema/quiz'; -import { useCreateQuizAttemptMutation } from '@/hooks'; +import { useCreateQuizAttemptMutation, useDeleteQuizMutation } from '@/hooks'; import { User } from 'next-auth'; import Link from 'next/link'; -import { useRouter } from 'next/navigation'; +import { redirect, useRouter } from 'next/navigation'; import { toast } from 'sonner'; import { QuizActivateDialog } from './quiz-activate-dialog'; @@ -24,6 +24,8 @@ export const QuizDetailActions = ({ user, quiz }: QuizDetailActionsProps) => { const createQuizAttempt = useCreateQuizAttemptMutation(); + const deleteQuizMutation = useDeleteQuizMutation(); + const takeQuiz = async () => { await createQuizAttempt.mutateAsync(quiz.id, { onSuccess: async (attemptId: string) => { @@ -35,6 +37,18 @@ export const QuizDetailActions = ({ user, quiz }: QuizDetailActionsProps) => { }); }; + const deleteQuiz = async () => { + await deleteQuizMutation.mutateAsync(quiz.id, { + onSuccess: async () => { + toast.success('Successfully deleted quiz'); + redirect('/auth/profile'); + }, + onError: (e) => { + toast.error(e.message); + }, + }); + }; + return ( <> {!user && ( @@ -44,9 +58,17 @@ export const QuizDetailActions = ({ user, quiz }: QuizDetailActionsProps) => { {!quiz.isActive && isOwner && (
- + + + Delete +
)} diff --git a/quizeek/src/hooks/quiz.ts b/quizeek/src/hooks/quiz.ts index 0ff830e..81fbbc8 100644 --- a/quizeek/src/hooks/quiz.ts +++ b/quizeek/src/hooks/quiz.ts @@ -1,5 +1,6 @@ import { SubmitQuizFormMutationType } from '@/models'; import { activateQuizAction, submitQuizFormAction } from '@/server-actions'; +import { deleteQuizAction } from '@/server-actions/quiz/delete-quiz-action'; import { useMutation } from '@tanstack/react-query'; export const useSubmitQuizFormMutation = () => @@ -27,3 +28,8 @@ export const useActivateQuizMutation = () => useMutation({ mutationFn: activateQuizAction, }); + +export const useDeleteQuizMutation = () => + useMutation({ + mutationFn: deleteQuizAction, + }); diff --git a/quizeek/src/server-actions/quiz/delete-quiz-action.ts b/quizeek/src/server-actions/quiz/delete-quiz-action.ts new file mode 100644 index 0000000..e74aa5b --- /dev/null +++ b/quizeek/src/server-actions/quiz/delete-quiz-action.ts @@ -0,0 +1,51 @@ +'use server'; + +import { auth } from '@/auth'; +import { db } from '@/db'; +import { choices } from '@/db/schema/choice'; +import { questions } from '@/db/schema/question'; +import { quizes } from '@/db/schema/quiz'; +import { InvalidDataError, InvalidSessionError } from '@/models'; +import { handleError } from '@/utils'; +import { and, eq, inArray } from 'drizzle-orm'; + +export const deleteQuizAction = async (id: string) => { + try { + const session = await auth(); + + if (!session?.user) { + throw new InvalidSessionError('Session is invalid'); + } + + return await db.transaction(async (tx) => { + try { + const questionsToDelete = await tx.query.questions.findMany({ + where: eq(questions.quizId, id), + }); + + await tx.delete(choices).where( + inArray( + choices.questionId, + questionsToDelete.map((q) => q.id) + ) + ); + + await tx.delete(questions).where(eq(questions.quizId, id)); + + const deletedQuiz = await tx + .delete(quizes) + .where(and(eq(quizes.id, id), eq(quizes.createdBy, session.user.id))) + .returning(); + + if (deletedQuiz.length !== 1) { + throw new InvalidDataError('Quiz not found'); + } + } catch (e) { + tx.rollback(); + throw e; + } + }); + } catch (error) { + throw handleError(error); + } +}; diff --git a/quizeek/src/server-actions/quiz/submit-quiz-form-action.ts b/quizeek/src/server-actions/quiz/submit-quiz-form-action.ts index 56eefd6..ea6c522 100644 --- a/quizeek/src/server-actions/quiz/submit-quiz-form-action.ts +++ b/quizeek/src/server-actions/quiz/submit-quiz-form-action.ts @@ -104,7 +104,7 @@ export const submitQuizFormAction = async (body: QuizForm, id?: string) => { })) ); - const newChoices = await await tx + const newChoices = await tx .insert(choices) .values(choicesToCreate) .returning(); From 9da2f4a27fe6fd128ecd7a6b8cab5598c5c8df1b Mon Sep 17 00:00:00 2001 From: Dominik Borbuliak Date: Sun, 15 Dec 2024 13:05:59 +0100 Subject: [PATCH 3/3] fix: Fixed revalidation of pages --- quizeek/src/server-actions/quiz/delete-quiz-action.ts | 3 +++ quizeek/src/server-actions/quiz/submit-quiz-form-action.ts | 3 +++ 2 files changed, 6 insertions(+) diff --git a/quizeek/src/server-actions/quiz/delete-quiz-action.ts b/quizeek/src/server-actions/quiz/delete-quiz-action.ts index e74aa5b..7bfc6d4 100644 --- a/quizeek/src/server-actions/quiz/delete-quiz-action.ts +++ b/quizeek/src/server-actions/quiz/delete-quiz-action.ts @@ -8,6 +8,7 @@ import { quizes } from '@/db/schema/quiz'; import { InvalidDataError, InvalidSessionError } from '@/models'; import { handleError } from '@/utils'; import { and, eq, inArray } from 'drizzle-orm'; +import { revalidatePath } from 'next/cache'; export const deleteQuizAction = async (id: string) => { try { @@ -40,6 +41,8 @@ export const deleteQuizAction = async (id: string) => { if (deletedQuiz.length !== 1) { throw new InvalidDataError('Quiz not found'); } + + revalidatePath('/auth/profile'); } catch (e) { tx.rollback(); throw e; diff --git a/quizeek/src/server-actions/quiz/submit-quiz-form-action.ts b/quizeek/src/server-actions/quiz/submit-quiz-form-action.ts index ea6c522..45f2ef3 100644 --- a/quizeek/src/server-actions/quiz/submit-quiz-form-action.ts +++ b/quizeek/src/server-actions/quiz/submit-quiz-form-action.ts @@ -8,6 +8,7 @@ import { quizes, QuizForm, quizFormSchema } from '@/db/schema/quiz'; import { InvalidDataError, InvalidSessionError } from '@/models'; import { handleError } from '@/utils'; import { and, eq, inArray } from 'drizzle-orm'; +import { revalidatePath } from 'next/cache'; export const submitQuizFormAction = async (body: QuizForm, id?: string) => { try { @@ -115,6 +116,8 @@ export const submitQuizFormAction = async (body: QuizForm, id?: string) => { throw new InvalidDataError('Could not create choices'); } + revalidatePath('/'); + return newQuiz[0].id; } catch (e) { tx.rollback();