Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { QuizAttempt } from '@/components/quiz/quiz-attempt';
import { getQuizAttemptById, getQuizWithQuestionsById } from '@/db/queries';
import {
getQuizAttemptById,
getQuizWithPublicQuestionsById,
} from '@/db/queries';
import { notFound, redirect } from 'next/navigation';
import React from 'react';

Expand All @@ -21,7 +24,7 @@ const Page = async ({ params }: AttemptPageProps) => {
notFound();
}

const quiz = await getQuizWithQuestionsById(routeParams.quizId);
const quiz = await getQuizWithPublicQuestionsById(routeParams.quizId);
const attempt = await getQuizAttemptById(routeParams.attemptId);

if (!quiz || !attempt) {
Expand Down
36 changes: 34 additions & 2 deletions quizeek/src/app/(app)/auth/quiz/[quizId]/view/[attemptId]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,41 @@
import { QuizAttempt } from '@/components/quiz/quiz-attempt';
import {
getQuizAttemptWithAnswers,
getQuizWithQuestionsById,
} from '@/db/queries';
import { notFound } from 'next/navigation';

type PageProps = {
params?: Promise<{
quizId?: string;
attemptId?: string;
}>;
};

export const metadata = {
title: 'View Results',
};

const Page = async () => {
return <p>Quiz view</p>;
const Page = async ({ params }: PageProps) => {
const routeParams = await params;

if (!routeParams?.quizId || !routeParams.attemptId) {
notFound();
}

const quiz = await getQuizWithQuestionsById(routeParams.quizId);
const attempt = await getQuizAttemptWithAnswers(routeParams.attemptId);

if (!quiz || !attempt) {
return notFound();
}

return (
<>
<h1 className="text-xl font-bold">{quiz.title}</h1>
<QuizAttempt quiz={quiz} attempt={attempt} />
</>
);
};

export default Page;
2 changes: 1 addition & 1 deletion quizeek/src/components/profile/update-user-form.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client';

import { UpdateUser, updateUserSchema } from '@/db/schema/user';
import { useUpdateUserMutation } from '@/hooks/user';
import { useUpdateUserMutation } from '@/hooks';
import { cn } from '@/lib/utils';
import { zodResolver } from '@hookform/resolvers/zod';
import { SessionContextValue } from 'next-auth/react';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const QuizAttemptSaveDialog = ({
}: QuizAttemptSaveDialogProps) => {
return (
<Dialog>
<DialogTrigger asChild className="float-right">
<DialogTrigger asChild className="float-right mt-2 w-full md:w-fit">
<Button type="button">Finish</Button>
</DialogTrigger>
<DialogContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
DialogTrigger,
} from '@/components/ui/dialog';
import { QuizWithUser } from '@/db/schema/quiz';
import { useActivateQuizMutation } from '@/hooks/quiz';
import { useActivateQuizMutation } from '@/hooks';
import React from 'react';
import { toast } from 'sonner';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Card, CardContent, CardTitle } from '@/components/ui/card';
import { getMyQuizAttempts } from '@/db/queries';
import { QuizWithUser } from '@/db/schema/quiz';
import { toLocalDateTimeString } from '@/utils/date';
import { toLocalDateTimeString } from '@/utils';
import { SquareArrowRight } from 'lucide-react';
import Link from 'next/link';
import React from 'react';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Card, CardContent, CardTitle } from '@/components/ui/card';
import { getOtherQuizAttempts } from '@/db/queries';
import { QuizWithUser } from '@/db/schema/quiz';
import { toLocalDateTimeString } from '@/utils/date';
import { toLocalDateTimeString } from '@/utils';
import { CircleUserRound } from 'lucide-react';
import Image from 'next/image';
import React from 'react';
Expand Down
34 changes: 31 additions & 3 deletions quizeek/src/components/quiz/question/choice/choice.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,39 @@
import { Card } from '@/components/ui/card';
import { cn } from '@/lib/utils';
import { PropsWithChildren } from 'react';

export type ChoiceProps = PropsWithChildren;
export type ChoiceProps = {
enableHiglighting: boolean;
isCorrect: boolean;
wasSelected: boolean;
} & PropsWithChildren;

export const Choice = ({ children }: ChoiceProps) => {
export const Choice = ({
enableHiglighting,
isCorrect,
wasSelected,
children,
...props
}: ChoiceProps) => {
return (
<Card className="w-full py-0 px-3 rounded-md hover:bg-secondary flex items-center gap-2 mb-2 last:mb-0">
<Card
className={cn(
'w-full py-0 px-3 rounded-md hover:bg-secondary flex items-center gap-2 mb-2 last:mb-0',
enableHiglighting &&
wasSelected &&
isCorrect &&
'border-2 dark:border-green-600 border-green-400',
enableHiglighting &&
wasSelected &&
!isCorrect &&
'border-2 dark:border-red-600 border-red-400',
enableHiglighting &&
!wasSelected &&
isCorrect &&
'border-2 dark:border-yellow-600 border-yellow-400'
)}
{...props}
>
{children}
</Card>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,35 @@
import { ScrollArea } from '@/components/ui/scroll-area';
import { Choice, PublicChoice } from '@/db/schema/choice';
import {
type QuizAttempt as QuizAttemptType,
QuizAttemptWithAnswers,
} from '@/db/schema/quiz-attempt';

import { MultiChoice } from './multi-choice';

export type MultiChoiceListProps = {
questionId: string;
choices: (Choice | PublicChoice)[];
attempt: QuizAttemptType | QuizAttemptWithAnswers;
};

export const MultiChoiceList = ({
questionId,
choices,
attempt,
}: MultiChoiceListProps) => {
return (
<ScrollArea
type="auto"
className="mt-4 flex flex-col max-h-[40vh] overflow-y-auto pr-4"
>
{choices.map((choice) => (
<MultiChoice key={choice.id} choice={choice} questionId={questionId} />
<MultiChoice
key={choice.id}
choice={choice}
questionId={questionId}
attempt={attempt}
/>
))}
</ScrollArea>
);
Expand Down
25 changes: 23 additions & 2 deletions quizeek/src/components/quiz/question/choice/multi-choice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,40 @@ import { Checkbox } from '@/components/ui/checkbox';
import { FormControl, FormField, FormItem } from '@/components/ui/form';
import { Label } from '@/components/ui/label';
import { Choice as ChoiceType, PublicChoice } from '@/db/schema/choice';
import {
type QuizAttempt as QuizAttemptType,
QuizAttemptWithAnswers,
} from '@/db/schema/quiz-attempt';
import { useFormContext } from 'react-hook-form';

import { Choice } from './choice';

export type MultiChoiceProps = {
questionId: string;
choice: ChoiceType | PublicChoice;
attempt: QuizAttemptType | QuizAttemptWithAnswers;
};

export const MultiChoice = ({ questionId, choice }: MultiChoiceProps) => {
export const MultiChoice = ({
questionId,
choice,
attempt,
}: MultiChoiceProps) => {
const form = useFormContext();

const enableHiglighting =
attempt.type === 'with_answers' && choice.type === 'private';
const wasSelected =
enableHiglighting &&
!!attempt.answers.find((a) => a.choiceId === choice.id);
const isCorrect = enableHiglighting && choice.isCorrect;

return (
<Choice>
<Choice
enableHiglighting={enableHiglighting}
wasSelected={wasSelected}
isCorrect={isCorrect}
>
<FormField
control={form.control}
name={questionId}
Expand All @@ -30,6 +50,7 @@ export const MultiChoice = ({ questionId, choice }: MultiChoiceProps) => {
<FormControl>
<Checkbox
id={choice.id}
disabled={attempt.type === 'with_answers'}
{...field}
checked={field.value?.includes(choice.id)}
onCheckedChange={(checked) => {
Expand Down
15 changes: 13 additions & 2 deletions quizeek/src/components/quiz/question/choice/single-choice-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,24 @@ import { FormControl, FormField, FormItem } from '@/components/ui/form';
import { RadioGroup } from '@/components/ui/radio-group';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Choice, PublicChoice } from '@/db/schema/choice';
import {
type QuizAttempt as QuizAttemptType,
QuizAttemptWithAnswers,
} from '@/db/schema/quiz-attempt';
import { useFormContext } from 'react-hook-form';

import { SingleChoice } from './single-choice';

export type SingleChoiceListProps = {
questionId: string;
choices: (Choice | PublicChoice)[];
attempt: QuizAttemptType | QuizAttemptWithAnswers;
};

export const SingleChoiceList = ({
questionId,
choices,
attempt,
}: SingleChoiceListProps) => {
const form = useFormContext();

Expand All @@ -30,10 +36,15 @@ export const SingleChoiceList = ({
<FormControl>
<RadioGroup
onValueChange={(v) => field.onChange([v])}
defaultValue={field.value}
value={field.value?.[0]}
defaultValue={field.value?.[0]}
>
{choices.map((choice) => (
<SingleChoice key={choice.id} choice={choice} />
<SingleChoice
key={choice.id}
choice={choice}
attempt={attempt}
/>
))}
</RadioGroup>
</FormControl>
Expand Down
26 changes: 23 additions & 3 deletions quizeek/src/components/quiz/question/choice/single-choice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,38 @@ import { FormControl } from '@/components/ui/form';
import { Label } from '@/components/ui/label';
import { RadioGroupItem } from '@/components/ui/radio-group';
import { Choice as ChoiceType, PublicChoice } from '@/db/schema/choice';
import {
type QuizAttempt as QuizAttemptType,
QuizAttemptWithAnswers,
} from '@/db/schema/quiz-attempt';

import { Choice } from './choice';

export type SingleChoiceProps = {
choice: ChoiceType | PublicChoice;
attempt: QuizAttemptType | QuizAttemptWithAnswers;
};

export const SingleChoice = ({ choice }: SingleChoiceProps) => {
export const SingleChoice = ({ choice, attempt }: SingleChoiceProps) => {
const enableHiglighting =
attempt.type === 'with_answers' && choice.type === 'private';
const wasSelected =
enableHiglighting &&
!!attempt.answers.find((a) => a.choiceId === choice.id);
const isCorrect = enableHiglighting && choice.isCorrect;

return (
<Choice>
<Choice
enableHiglighting={enableHiglighting}
wasSelected={wasSelected}
isCorrect={isCorrect}
>
<FormControl>
<RadioGroupItem value={choice.id} id={choice.id} />
<RadioGroupItem
value={choice.id}
id={choice.id}
disabled={attempt.type === 'with_answers'}
/>
</FormControl>
<Label htmlFor={choice.id} className="block w-full h-full p-3 leading-4">
{choice.text}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CarouselApi } from '@/components/ui/carousel';
import { QuestionBubbleType } from '@/models/question';
import { QuestionBubbleType } from '@/models';
import { DndContext, DragEndEvent } from '@dnd-kit/core';
import { arrayMove, SortableContext } from '@dnd-kit/sortable';
import { Dispatch, PropsWithChildren, SetStateAction } from 'react';
Expand Down
4 changes: 2 additions & 2 deletions quizeek/src/components/quiz/question/question-bubble.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { CarouselApi } from '@/components/ui/carousel';
import { cn } from '@/lib/utils';
import { QuestionBubbleType } from '@/models/question';
import { QuestionBubbleType } from '@/models';
import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import { Dispatch, SetStateAction } from 'react';
Expand Down Expand Up @@ -42,7 +42,7 @@ export const QuestionBubble = <TQuestion extends QuestionBubbleType>({
transition,
}}
className={cn(
'rounded-full border w-6 h-6 text-center hover:bg-primary cursor-pointer overflow-x-auto text-foreground',
'rounded-full border w-6 h-6 text-center hover:bg-primary cursor-pointer text-foreground',
currentQuestion === question.id && 'bg-primary dark:text-black'
)}
onMouseUp={onClick}
Expand Down
15 changes: 12 additions & 3 deletions quizeek/src/components/quiz/question/question-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,23 @@ import {
CarouselNext,
CarouselPrevious,
} from '@/components/ui/carousel';
import { type QuestionWithPublicChoices } from '@/db/schema/question';
import {
QuestionWithChoices,
type QuestionWithPublicChoices,
} from '@/db/schema/question';
import {
type QuizAttempt as QuizAttemptType,
QuizAttemptWithAnswers,
} from '@/db/schema/quiz-attempt';
import { cn } from '@/lib/utils';
import { useState } from 'react';

import { Question as QuestionComponent } from './question';
import { QuestionBubbleList } from './question-bubble-list';

export type QuestionListProps = {
questions: QuestionWithPublicChoices[];
attempt: QuizAttemptType | QuizAttemptWithAnswers;
questions: QuestionWithPublicChoices[] | QuestionWithChoices[];
draggableBubbles: boolean;
className?: string;
};
Expand All @@ -25,6 +33,7 @@ export const QuestionList = ({
questions,
draggableBubbles,
className,
attempt,
}: QuestionListProps) => {
const [carouselApi, setCarouselApi] = useState<CarouselApi>();
const [currentQuestion, setCurrentQuestion] = useState<string>(
Expand Down Expand Up @@ -52,7 +61,7 @@ export const QuestionList = ({
<CarouselContent>
{questions.map((question) => (
<CarouselItem key={question.id}>
<QuestionComponent question={question} />
<QuestionComponent question={question} attempt={attempt} />
</CarouselItem>
))}
</CarouselContent>
Expand Down
Loading