diff --git a/src/client/features/legislation/lib/user-votes-db.test.ts b/src/client/features/legislation/lib/user-votes-db.test.ts new file mode 100644 index 0000000..45339fb --- /dev/null +++ b/src/client/features/legislation/lib/user-votes-db.test.ts @@ -0,0 +1,42 @@ +import { createTestDb } from "@/shared/db/client" +import type { PGlite } from "@electric-sql/pglite" +import { beforeEach, describe, expect, it } from "vitest" + +let db: PGlite + +beforeEach(async () => { + db = await createTestDb() +}) + +const { getUserVote, saveUserVote, deleteUserVote } = await import( + "./user-votes-db" +) + +describe("user-votes-db", () => { + it("returns null when no vote exists", async () => { + const vote = await getUserVote(db, 1) + expect(vote).toBeNull() + }) + + it("saves and retrieves a vote", async () => { + await saveUserVote(db, 1, "ja") + const vote = await getUserVote(db, 1) + expect(vote).not.toBeNull() + expect(vote?.vote).toBe("ja") + expect(vote?.legislation_id).toBe(1) + }) + + it("overwrites an existing vote", async () => { + await saveUserVote(db, 1, "ja") + await saveUserVote(db, 1, "nein") + const vote = await getUserVote(db, 1) + expect(vote?.vote).toBe("nein") + }) + + it("deletes a vote", async () => { + await saveUserVote(db, 1, "ja") + await deleteUserVote(db, 1) + const vote = await getUserVote(db, 1) + expect(vote).toBeNull() + }) +}) diff --git a/src/client/features/legislation/lib/user-votes-db.ts b/src/client/features/legislation/lib/user-votes-db.ts new file mode 100644 index 0000000..d3d6427 --- /dev/null +++ b/src/client/features/legislation/lib/user-votes-db.ts @@ -0,0 +1,42 @@ +import type { PGlite } from "@electric-sql/pglite" +import type { UserVoteChoice } from "../../../../shared/legislation-types" + +interface UserVoteRow { + legislation_id: number + vote: string + voted_at: string +} + +export async function getUserVote( + db: PGlite, + legislationId: number, +): Promise { + const result = await db.query( + "SELECT * FROM user_votes WHERE legislation_id = $1 LIMIT 1", + [legislationId], + ) + return result.rows[0] ?? null +} + +export async function saveUserVote( + db: PGlite, + legislationId: number, + vote: UserVoteChoice, +): Promise { + await db.query( + `INSERT INTO user_votes (legislation_id, vote, voted_at) + VALUES ($1, $2, now()) + ON CONFLICT (legislation_id) DO UPDATE + SET vote = $2, voted_at = now()`, + [legislationId, vote], + ) +} + +export async function deleteUserVote( + db: PGlite, + legislationId: number, +): Promise { + await db.query("DELETE FROM user_votes WHERE legislation_id = $1", [ + legislationId, + ]) +}