Skip to content

Commit f3de433

Browse files
authored
feat: adds ability to configure and read prompts from database (#173)
1 parent b1904fd commit f3de433

File tree

7 files changed

+71
-24
lines changed

7 files changed

+71
-24
lines changed

lib/javascript/quiz-app/prisma/schema.prisma

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,13 @@ model Votes {
1515
option String @db.VarChar
1616
userId String @db.VarChar
1717
created_at DateTime @default(now()) @db.Timestamptz(6)
18+
prompt_id BigInt
19+
}
20+
21+
/// This model contains row level security and requires additional setup for migrations. Visit https://pris.ly/d/row-level-security for more info.
22+
model Prompts {
23+
id BigInt @id @default(autoincrement())
24+
Prompt String? @db.VarChar
25+
created_at DateTime @default(now()) @db.Timestamptz(6)
26+
Options Json @db.Json
1827
}

lib/javascript/quiz-app/src/app/results/page.tsx renamed to lib/javascript/quiz-app/src/app/results/[promptId]/page.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
import ClearVotesButton from "@/components/clear-votes-button"
22
import ResultsChart from "@/components/results-chart"
3-
import { getAllVotes } from "@/lib/db"
3+
import { getAllVotes, getPrompt } from "@/lib/db"
44
import { currentUser } from "@clerk/nextjs/server"
55
import { redirect } from "next/navigation"
66

7-
export default async function ResultsPage() {
7+
export default async function ResultsPage({
8+
params,
9+
}: {
10+
params: Promise<{ promptId: string }>
11+
}) {
812
const user = await currentUser()
913

1014
// Redirect to sign-in if not authenticated
@@ -18,16 +22,18 @@ export default async function ResultsPage() {
1822
isAdmin = true;
1923
}
2024

21-
const topic = "What's your favorite programming language?"
22-
const votes = await getAllVotes()
25+
const promptId = +(await params).promptId;
26+
const prompt = await getPrompt(promptId);
27+
const topic = prompt?.Prompt;
28+
const votes = await getAllVotes(promptId);
2329

2430
return (
2531
<div className="container mx-auto py-10">
2632
<div className="flex flex-col justify-between items-center mb-8">
2733
<h1 className="text-3xl font-bold mb-8 text-center">{topic}</h1>
2834
{isAdmin &&(
2935
<div className="flex items-center gap-4">
30-
<ClearVotesButton />
36+
<ClearVotesButton promptId={promptId} />
3137
</div>
3238
)}
3339
</div>

lib/javascript/quiz-app/src/app/vote/page.tsx renamed to lib/javascript/quiz-app/src/app/vote/[promptId]/page.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import VoteForm from "@/components/vote-form";
2-
import { getUserVote } from "@/lib/db";
2+
import { getPrompt, getUserVote } from "@/lib/db";
33
import { currentUser } from "@clerk/nextjs/server";
44
import { redirect } from "next/navigation";
55

6-
export default async function VotePage() {
6+
export default async function VotePage({
7+
params,
8+
}: {
9+
params: Promise<{ promptId: string }>
10+
}) {
711
const user = await currentUser()
812

913
// Redirect to sign-in if not authenticated
@@ -21,13 +25,15 @@ export default async function VotePage() {
2125
return redirect("/results")
2226
}
2327

24-
const topic = "What's your favorite programming language?"
25-
const options = ["JavaScript", "TypeScript", "Python", "Rust", "Go", "Other"]
28+
const promptId = +(await params).promptId;
29+
const prompt = await getPrompt(promptId);
30+
const topic = '' + prompt?.Prompt;
31+
const options = (prompt?.Options as {options: string[]}).options;
2632

2733
return (
2834
<div className="container mx-auto py-10">
2935
<h1 className="text-3xl font-bold mb-8 text-center">{topic}</h1>
30-
<VoteForm topic={topic} options={options} userId={userId} />
36+
<VoteForm promptId={promptId} topic={topic} options={options} userId={userId} />
3137
</div>
3238
)
3339
}

lib/javascript/quiz-app/src/components/clear-votes-button.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ import { Trash2 } from "lucide-react"
1717
import { useRouter } from "next/navigation"
1818
import { useState } from "react"
1919

20-
export default function ClearVotesButton() {
20+
export default function ClearVotesButton({ promptId }: { promptId: number }) {
2121
const [isClearing, setIsClearing] = useState(false)
2222
const router = useRouter()
2323

2424
const handleClearVotes = async () => {
2525
setIsClearing(true)
2626
try {
27-
await clearAllVotes()
28-
router.push("/vote")
27+
await clearAllVotes(promptId)
28+
router.push(`/vote/${promptId}`)
2929
} catch (error) {
3030
console.error("Failed to clear votes:", error)
3131
} finally {

lib/javascript/quiz-app/src/components/vote-form.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ import { useRouter } from "next/navigation"
1010
import { useState } from "react"
1111

1212
interface VoteFormProps {
13+
promptId: number
1314
topic: string
1415
options: string[]
1516
userId: string
1617
}
1718

18-
export default function VoteForm({ topic, options, userId }: VoteFormProps) {
19+
export default function VoteForm({ promptId, topic, options, userId }: VoteFormProps) {
1920
const [selectedOption, setSelectedOption] = useState<string>("")
2021
const [isSubmitting, setIsSubmitting] = useState(false)
2122
const router = useRouter()
@@ -30,10 +31,11 @@ export default function VoteForm({ topic, options, userId }: VoteFormProps) {
3031
await submitVote({
3132
topic,
3233
option: selectedOption,
34+
promptId,
3335
userId,
3436
})
3537

36-
router.push("/results")
38+
router.push(`/results/${promptId}`)
3739
} catch (error) {
3840
console.error("Error submitting vote:", error)
3941
} finally {

lib/javascript/quiz-app/src/lib/actions.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import { clearVotes, saveVote } from "./db"
55
interface VoteData {
66
topic: string
77
option: string
8-
userId: string // Changed from userEmail to userId
8+
promptId: number
9+
userId: string
910
}
1011

1112
export async function submitVote(data: VoteData) {
@@ -19,6 +20,7 @@ export async function submitVote(data: VoteData) {
1920
await saveVote({
2021
topic: data.topic,
2122
option: data.option,
23+
promptId: data.promptId,
2224
userId: data.userId,
2325
})
2426

@@ -29,9 +31,9 @@ export async function submitVote(data: VoteData) {
2931
}
3032
}
3133

32-
export async function clearAllVotes() {
34+
export async function clearAllVotes(promptId: number) {
3335
try {
34-
await clearVotes()
36+
await clearVotes(promptId)
3537
return { success: true }
3638
} catch (error) {
3739
console.error("Error clearing votes:", error)

lib/javascript/quiz-app/src/lib/db.ts

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,19 @@ import prisma from "./prisma"
66
interface VoteRecord {
77
topic: string
88
option: string
9-
userId: string // Changed from userEmail to userId
9+
userId: string
10+
promptId: number
1011
createdAt: Date
1112
}
1213

1314
export async function saveVote(vote: Omit<VoteRecord, "createdAt">) {
1415
const newVote = await prisma.votes.create({
15-
data: vote,
16+
data: {
17+
prompt_id: vote.promptId,
18+
topic: vote.topic,
19+
userId: vote.userId,
20+
option: vote.option,
21+
},
1622
})
1723
return {...newVote, createdAt: newVote.created_at}
1824
}
@@ -27,11 +33,15 @@ export async function getUserVote(userId: string | null | undefined) {
2733
})
2834
}
2935

30-
export async function getAllVotes() {
36+
export async function getAllVotes(promptId: number) {
3137
// Count votes by option
3238
const voteCounts: Record<string, number> = {}
3339

34-
const votes = await prisma.votes.findMany();
40+
const votes = await prisma.votes.findMany({
41+
where: {
42+
prompt_id: promptId,
43+
},
44+
});
3545

3646
votes.forEach((vote) => {
3747
if (voteCounts[vote.option]) {
@@ -48,7 +58,19 @@ export async function getAllVotes() {
4858
}))
4959
}
5060

51-
export async function clearVotes() {
52-
await prisma.votes.deleteMany({})
61+
export async function clearVotes(promptId: number) {
62+
await prisma.votes.deleteMany({
63+
where: {
64+
prompt_id: promptId,
65+
},
66+
})
67+
}
68+
69+
export async function getPrompt(id: number) {
70+
return await prisma.prompts.findFirst({
71+
where: {
72+
id: id,
73+
},
74+
});
5375
}
5476

0 commit comments

Comments
 (0)