Adding educational components
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
import { db } from '../db/client.js';
|
||||
import type { DailyEducationQuestion, DailyEducationRow, EducationQuestionRow } from '../types.js';
|
||||
|
||||
export const getEducationOptOut = async (userId: string) => {
|
||||
const result = await db.query<{ education_opt_out: boolean }>(
|
||||
`SELECT education_opt_out
|
||||
FROM users
|
||||
WHERE id = $1`,
|
||||
[userId],
|
||||
);
|
||||
|
||||
return result.rows[0]?.education_opt_out ?? false;
|
||||
};
|
||||
|
||||
export const updateEducationOptOut = async (userId: string, educationOptOut: boolean) => {
|
||||
const result = await db.query<{ education_opt_out: boolean }>(
|
||||
`UPDATE users
|
||||
SET education_opt_out = $2
|
||||
WHERE id = $1
|
||||
RETURNING education_opt_out`,
|
||||
[userId, educationOptOut],
|
||||
);
|
||||
|
||||
return result.rows[0]?.education_opt_out ?? educationOptOut;
|
||||
};
|
||||
|
||||
export const getDailyEducationForDate = async (publishDate?: string) => {
|
||||
const result = publishDate
|
||||
? await db.query<DailyEducationRow>(
|
||||
`SELECT id, publish_date::text, fact, quiz_questions, created_by_user_id, created_at, updated_at
|
||||
FROM daily_education
|
||||
WHERE publish_date = $1`,
|
||||
[publishDate],
|
||||
)
|
||||
: await db.query<DailyEducationRow>(
|
||||
`SELECT id, publish_date::text, fact, quiz_questions, created_by_user_id, created_at, updated_at
|
||||
FROM daily_education
|
||||
WHERE publish_date = CURRENT_DATE`,
|
||||
);
|
||||
|
||||
return result.rows[0] ?? null;
|
||||
};
|
||||
|
||||
export const listDailyEducationForAdmin = async () => {
|
||||
const result = await db.query<DailyEducationRow>(
|
||||
`SELECT id, publish_date::text, fact, quiz_questions, created_by_user_id, created_at, updated_at
|
||||
FROM daily_education
|
||||
ORDER BY publish_date DESC
|
||||
LIMIT 120`,
|
||||
);
|
||||
|
||||
return result.rows;
|
||||
};
|
||||
|
||||
export const upsertDailyEducation = async ({
|
||||
publishDate,
|
||||
fact,
|
||||
createdByUserId,
|
||||
}: {
|
||||
publishDate: string;
|
||||
fact: string;
|
||||
createdByUserId: string;
|
||||
}) => {
|
||||
const result = await db.query<DailyEducationRow>(
|
||||
`INSERT INTO daily_education (publish_date, fact, created_by_user_id)
|
||||
VALUES ($1, $2, $3)
|
||||
ON CONFLICT (publish_date) DO UPDATE
|
||||
SET fact = EXCLUDED.fact,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
RETURNING id, publish_date::text, fact, quiz_questions, created_by_user_id, created_at, updated_at`,
|
||||
[publishDate, fact, createdByUserId],
|
||||
);
|
||||
|
||||
return result.rows[0];
|
||||
};
|
||||
|
||||
export const listEducationQuestionsForAdmin = async () => {
|
||||
const result = await db.query<EducationQuestionRow>(
|
||||
`SELECT id, prompt, options, correct_answer_index, explanation, created_by_user_id, created_at, updated_at
|
||||
FROM education_question_bank
|
||||
ORDER BY updated_at DESC, created_at DESC
|
||||
LIMIT 400`,
|
||||
);
|
||||
|
||||
return result.rows;
|
||||
};
|
||||
|
||||
export const listDailyEducationQuestions = async (seedDate?: string) => {
|
||||
const result = await db.query<EducationQuestionRow>(
|
||||
`SELECT id, prompt, options, correct_answer_index, explanation, created_by_user_id, created_at, updated_at
|
||||
FROM education_question_bank
|
||||
ORDER BY md5(COALESCE($1::text, CURRENT_DATE::text) || id::text)
|
||||
LIMIT 4`,
|
||||
[seedDate ?? null],
|
||||
);
|
||||
|
||||
return result.rows;
|
||||
};
|
||||
|
||||
export const createEducationQuestion = async ({
|
||||
question,
|
||||
createdByUserId,
|
||||
}: {
|
||||
question: DailyEducationQuestion;
|
||||
createdByUserId: string;
|
||||
}) => {
|
||||
const result = await db.query<EducationQuestionRow>(
|
||||
`INSERT INTO education_question_bank (prompt, options, correct_answer_index, explanation, created_by_user_id)
|
||||
VALUES ($1, $2::jsonb, $3, $4, $5)
|
||||
RETURNING id, prompt, options, correct_answer_index, explanation, created_by_user_id, created_at, updated_at`,
|
||||
[question.prompt, JSON.stringify(question.options), question.correctAnswerIndex, question.explanation, createdByUserId],
|
||||
);
|
||||
|
||||
return result.rows[0];
|
||||
};
|
||||
|
||||
export const updateEducationQuestion = async (questionId: string, question: DailyEducationQuestion) => {
|
||||
const result = await db.query<EducationQuestionRow>(
|
||||
`UPDATE education_question_bank
|
||||
SET prompt = $2,
|
||||
options = $3::jsonb,
|
||||
correct_answer_index = $4,
|
||||
explanation = $5,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $1
|
||||
RETURNING id, prompt, options, correct_answer_index, explanation, created_by_user_id, created_at, updated_at`,
|
||||
[questionId, question.prompt, JSON.stringify(question.options), question.correctAnswerIndex, question.explanation],
|
||||
);
|
||||
|
||||
return result.rows[0] ?? null;
|
||||
};
|
||||
|
||||
export const deleteEducationQuestion = async (questionId: string) => {
|
||||
const result = await db.query<{ id: string }>(
|
||||
`DELETE FROM education_question_bank
|
||||
WHERE id = $1
|
||||
RETURNING id`,
|
||||
[questionId],
|
||||
);
|
||||
|
||||
return Boolean(result.rowCount);
|
||||
};
|
||||
|
||||
export const deleteDailyEducation = async (educationId: string) => {
|
||||
const result = await db.query<{ id: string }>(
|
||||
`DELETE FROM daily_education
|
||||
WHERE id = $1
|
||||
RETURNING id`,
|
||||
[educationId],
|
||||
);
|
||||
|
||||
return Boolean(result.rowCount);
|
||||
};
|
||||
Reference in New Issue
Block a user