Skip to content

Commit 689816c

Browse files
committed
feat: adds userAnswered to /questions page
1 parent f8bc077 commit 689816c

File tree

2 files changed

+59
-10
lines changed

2 files changed

+59
-10
lines changed

src/components/app/questions/layout/question-card.tsx

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import { getQuestionStats } from '@/utils/data/questions/get-question-stats';
55
import Link from 'next/link';
66
import Chip from '@/components/ui/chip';
77
import { Suspense } from 'react';
8+
import { ChevronRight } from 'lucide-react';
9+
import { Circle } from 'lucide-react';
10+
import { CheckCircle } from 'lucide-react';
11+
import { Answer } from '@/types/Answers';
812

913
// separate async component for stats to avoid blocking render
1014
async function QuestionStats({
@@ -26,7 +30,7 @@ async function QuestionStats({
2630
}
2731

2832
export default function QuestionCard(opts: {
29-
questionData: QuestionWithoutAnswers;
33+
questionData: QuestionWithoutAnswers & { userAnswers: Answer[] };
3034
showSubmissions?: boolean;
3135
numberOfTags?: number;
3236
showcaseTag?: string;
@@ -75,6 +79,38 @@ export default function QuestionCard(opts: {
7579
</Suspense>
7680
)}
7781
</div>
82+
<div className="flex items-center gap-x-2">
83+
{questionData.userAnswers && questionData.userAnswers.length > 0 ? (
84+
<div>
85+
{questionData.userAnswers[0].correctAnswer ? (
86+
<CheckCircle className="flex-shrink-0 size-5 text-green-500" />
87+
) : (
88+
<Circle className="flex-shrink-0 size-5 text-black-50" />
89+
)}
90+
</div>
91+
) : (
92+
<Circle className="flex-shrink-0 size-5 text-black-50" />
93+
)}
94+
<div className="text-sm font-medium">
95+
{questionData.userAnswers && questionData.userAnswers.length > 0 ? (
96+
questionData.userAnswers[0].correctAnswer ? (
97+
<p>Correct</p>
98+
) : (
99+
<p>Incorrect</p>
100+
)
101+
) : (
102+
<div className="relative">
103+
<p className="group-hover:opacity-0 transition-opacity duration-300">
104+
Not Answered
105+
</p>
106+
<div className="absolute top-0 left-0 opacity-0 group-hover:opacity-100 transition-opacity duration-300 whitespace-nowrap flex items-center gap-x-1">
107+
<p>Learn Now</p>
108+
<ChevronRight className="flex-shrink-0 size-4 text-white group-hover:translate-x-2 transition-transform duration-300" />
109+
</div>
110+
</div>
111+
)}
112+
</div>
113+
</div>
78114
<div className="mt-5 w-full flex justify-between items-end z-10 relative">
79115
{!customQuestion && (
80116
<div className="flex gap-4 items-end">

src/utils/data/questions/list.ts

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,16 @@ import type {
88
import { getTagsFromQuestion } from './tags/get-tags-from-question';
99
import { QuestionFilters } from '@/types/Filters';
1010
import { getUser } from '@/actions/user/authed/get-user';
11+
import { Answer } from '@/types/Answers';
1112

1213
type ListQuestionsReturnType = {
13-
questions: Question[] | QuestionWithoutAnswers[];
14+
questions:
15+
| (Question[] & {
16+
userAnswers: Answer[] | null;
17+
})
18+
| (QuestionWithoutAnswers[] & {
19+
userAnswers: Answer[] | null;
20+
});
1421
total: number;
1522
page: number;
1623
pageSize: number;
@@ -38,16 +45,15 @@ export const listQuestions = async (
3845
previousQuestions = false,
3946
} = opts;
4047

41-
// Move authentication outside of cache to avoid cookie access inside cache
42-
let authenticatedUser = null;
43-
if (customQuestions) {
44-
authenticatedUser = await getUser();
48+
const user = await getUser();
4549

46-
if (!authenticatedUser || authenticatedUser.uid !== userUid) {
47-
throw new Error('Unauthorized access to custom questions');
48-
}
50+
if (customQuestions && !user) {
51+
throw new Error('Unauthorized access to custom questions');
4952
}
5053

54+
// if we have an authenticated user, we include the userAnswers in the query
55+
const includeUserAnswers = Boolean(user);
56+
5157
return unstable_cache(
5258
async () => {
5359
const skip = (page - 1) * pageSize;
@@ -143,6 +149,13 @@ export const listQuestions = async (
143149
tag: true,
144150
},
145151
},
152+
userAnswers: includeUserAnswers
153+
? {
154+
where: {
155+
userUid: userUid,
156+
},
157+
}
158+
: undefined,
146159
linkedReports: {
147160
select: {
148161
userUid: true,
@@ -159,7 +172,7 @@ export const listQuestions = async (
159172
questions.filter((question) => {
160173
if (!question.customQuestion) return true;
161174
return question.linkedReports.length > 0;
162-
}) as Question[]
175+
}) as unknown as Question[]
163176
);
164177

165178
// Get total count with same security constraints

0 commit comments

Comments
 (0)