Skip to content

Commit

Permalink
fix: bind questions to sessions
Browse files Browse the repository at this point in the history
  • Loading branch information
pepyta committed Feb 15, 2024
1 parent 52167e9 commit ba6cc4f
Show file tree
Hide file tree
Showing 7 changed files with 309 additions and 23 deletions.
17 changes: 17 additions & 0 deletions db/migrations/0003_brown_machine_man.sql
@@ -0,0 +1,17 @@
CREATE TABLE IF NOT EXISTS "session_questions" (
"session_id" uuid NOT NULL,
"question_id" uuid NOT NULL,
CONSTRAINT "session_questions_session_id_question_id_pk" PRIMARY KEY("session_id","question_id")
);
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "session_questions" ADD CONSTRAINT "session_questions_session_id_sessions_id_fk" FOREIGN KEY ("session_id") REFERENCES "sessions"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "session_questions" ADD CONSTRAINT "session_questions_question_id_questions_id_fk" FOREIGN KEY ("question_id") REFERENCES "questions"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
213 changes: 213 additions & 0 deletions db/migrations/meta/0003_snapshot.json
@@ -0,0 +1,213 @@
{
"id": "56b027e7-fe2e-4b95-88af-70e184c66726",
"prevId": "d2b74978-f605-42b7-8961-c5d9a2fe592b",
"version": "5",
"dialect": "pg",
"tables": {
"answers": {
"name": "answers",
"schema": "",
"columns": {
"session_id": {
"name": "session_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"question_id": {
"name": "question_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"choice": {
"name": "choice",
"type": "boolean",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {
"answers_session_id_question_id_pk": {
"name": "answers_session_id_question_id_pk",
"columns": [
"session_id",
"question_id"
]
}
},
"uniqueConstraints": {}
},
"categories": {
"name": "categories",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"categories_name_unique": {
"name": "categories_name_unique",
"nullsNotDistinct": false,
"columns": [
"name"
]
}
}
},
"questions": {
"name": "questions",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"answer": {
"name": "answer",
"type": "boolean",
"primaryKey": false,
"notNull": true
},
"category_id": {
"name": "category_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"questions_category_id_categories_id_fk": {
"name": "questions_category_id_categories_id_fk",
"tableFrom": "questions",
"tableTo": "categories",
"columnsFrom": [
"category_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"questions_name_unique": {
"name": "questions_name_unique",
"nullsNotDistinct": false,
"columns": [
"name"
]
}
}
},
"session_questions": {
"name": "session_questions",
"schema": "",
"columns": {
"session_id": {
"name": "session_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"question_id": {
"name": "question_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"session_questions_session_id_sessions_id_fk": {
"name": "session_questions_session_id_sessions_id_fk",
"tableFrom": "session_questions",
"tableTo": "sessions",
"columnsFrom": [
"session_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"session_questions_question_id_questions_id_fk": {
"name": "session_questions_question_id_questions_id_fk",
"tableFrom": "session_questions",
"tableTo": "questions",
"columnsFrom": [
"question_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"session_questions_session_id_question_id_pk": {
"name": "session_questions_session_id_question_id_pk",
"columns": [
"session_id",
"question_id"
]
}
},
"uniqueConstraints": {}
},
"sessions": {
"name": "sessions",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
}
},
"enums": {},
"schemas": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}
7 changes: 7 additions & 0 deletions db/migrations/meta/_journal.json
Expand Up @@ -22,6 +22,13 @@
"when": 1708016871904,
"tag": "0002_heavy_wolfsbane",
"breakpoints": true
},
{
"idx": 3,
"version": "5",
"when": 1708021355786,
"tag": "0003_brown_machine_man",
"breakpoints": true
}
]
}
20 changes: 20 additions & 0 deletions db/schema.ts
Expand Up @@ -17,6 +17,15 @@ export const sessions = pgTable("sessions", {
id: uuid("id").defaultRandom().primaryKey(),
});

export const sessionQuestions = pgTable("session_questions", {
sessionId: uuid("session_id").references(() => sessions.id).notNull(),
questionId: uuid("question_id").references(() => questions.id).notNull(),
}, (fields) => ({
pk: primaryKey({
columns: [fields.sessionId, fields.questionId],
}),
}));

export const answers = pgTable("answers", {
sessionId: uuid("session_id").notNull(),
questionId: uuid("question_id").notNull(),
Expand All @@ -27,6 +36,17 @@ export const answers = pgTable("answers", {
}),
}));

export const sessionQuestionRelations = relations(sessionQuestions, ({ one }) => ({
session: one(sessions, {
fields: [sessionQuestions.sessionId],
references: [sessions.id],
}),
question: one(questions, {
fields: [sessionQuestions.questionId],
references: [questions.id],
}),
}));

export const questionRelations = relations(questions, ({ one, many }) => ({
answers: many(answers),
category: one(categories, {
Expand Down
1 change: 1 addition & 0 deletions db/seed.ts
Expand Up @@ -16,6 +16,7 @@ const main = async () => {
});

await db.transaction(async (tx) => {
await tx.delete(schema.sessionQuestions);
await tx.delete(schema.sessions);
await tx.delete(schema.answers);
await tx.delete(schema.questions);
Expand Down
8 changes: 6 additions & 2 deletions pages/quiz.tsx
Expand Up @@ -25,7 +25,11 @@ const QuizScreen = () => {
enabled: !!sessionId,
});

const { data: questionsData } = trpc.question.list.useQuery();
const { data: questionsData } = trpc.question.list.useQuery({
sessionId,
}, {
enabled: !!sessionId,
});

const questions = useMemo(
() => questionsData
Expand Down Expand Up @@ -75,7 +79,7 @@ const QuizScreen = () => {
</Grid>
<Grid item xs={12}>
<Typography align={"center"}>
{`${Object.keys(answers).length + 1} of ${questions?.length}`}
{`${answers.length + 1} of ${questions.length}`}
</Typography>
</Grid>
<Grid item xs={6}>
Expand Down
66 changes: 45 additions & 21 deletions trpc/server/router/index.ts
@@ -1,20 +1,38 @@
import { procedure, router } from "@/trpc/server";
import { dbMiddleware } from "../middleware/db.middleware";
import { answers, sessions } from "@/db/schema";
import { answers, sessionQuestions, sessions } from "@/db/schema";
import { z } from "zod";
import { eq, sql } from "drizzle-orm";

export const appRouter = router({
session: router({
create: procedure
.use(dbMiddleware)
.mutation(async (opts) => (
await opts.ctx.db
.insert(sessions)
.values({})
.returning()
.execute()
)[0]),
.mutation(async (opts) => {
const session = (
await opts.ctx.db
.insert(sessions)
.values({})
.returning()
.execute()
)[0];

const questions = await opts.ctx.db.query.questions.findMany({
columns: {
id: true,
},
orderBy: () => sql`RANDOM()`,
limit: 10,
});

await opts.ctx.db.insert(sessionQuestions)
.values(questions.map((question) => ({
questionId: question.id,
sessionId: session.id,
})))

return session;
}),
}),

answer: router({
Expand Down Expand Up @@ -43,21 +61,27 @@ export const appRouter = router({
question: router({
list: procedure
.use(dbMiddleware)
.query((opts) => opts.ctx.db.query.questions.findMany({
columns: {
id: true,
name: true,
},
with: {
category: {
columns: {
name: true,
.input(z.object({
sessionId: z.string().uuid()
}))
.query(async (opts) => {
const sessionQuestions = await opts.ctx.db.query.sessionQuestions.findMany({
with: {
question: {
with: {
category: {
columns: {
name: true,
},
},
},
},
},
},
orderBy: () => sql`RANDOM()`,
limit: 10,
})),
where: (fields) => eq(fields.sessionId, opts.input.sessionId),
});

return sessionQuestions.map((sessionQuestion) => sessionQuestion.question);
}),
})
});

Expand Down

0 comments on commit ba6cc4f

Please sign in to comment.