95 lines
No EOL
4.1 KiB
TypeScript
95 lines
No EOL
4.1 KiB
TypeScript
import { error, redirect } from '@sveltejs/kit';
|
|
import { db } from '../../db';
|
|
import { surveyAccessTable, surveyAnswersTable, surveySkillsTable, surveysTable } from '../../db/schema';
|
|
import type { PageServerLoad } from './$types';
|
|
|
|
import { eq } from 'drizzle-orm';
|
|
|
|
import debug from 'debug';
|
|
|
|
const log_load = debug('survey:load');
|
|
const log_store = debug('survey:store');
|
|
|
|
export const load: PageServerLoad = async ({ params, url }) => {
|
|
const results = await db.select()
|
|
.from(surveyAccessTable)
|
|
.where(eq(surveyAccessTable.accessToken, params.accessToken))
|
|
.innerJoin(surveysTable, eq(surveysTable.id, surveyAccessTable.surveyId))
|
|
.limit(1);
|
|
|
|
if (results.length === 0) {
|
|
log_load('Survey not found: %s', params.accessToken);
|
|
error(404, 'Survey not found');
|
|
}
|
|
|
|
if (await db.$count(surveyAnswersTable, eq(surveyAnswersTable.participantId, results[0].survey_access_table.id)) > 0) {
|
|
log_load('Answers already submitted: %s', params.accessToken);
|
|
error(400, 'Answers already submitted');
|
|
}
|
|
|
|
const survey = results[0].surveys_table;
|
|
|
|
const skills = await db.select().from(surveySkillsTable).where(eq(surveySkillsTable.surveyId, survey.id));
|
|
|
|
return {
|
|
title: survey.title,
|
|
description: survey.description,
|
|
skills: skills.map(skills => ({
|
|
id: skills.id,
|
|
title: skills.title,
|
|
description: skills.description,
|
|
}))
|
|
}
|
|
}
|
|
|
|
export const actions = {
|
|
default: async ({ request, params }) => {
|
|
const results = await db.select()
|
|
.from(surveyAccessTable)
|
|
.where(eq(surveyAccessTable.accessToken, params.accessToken))
|
|
.innerJoin(surveysTable, eq(surveysTable.id, surveyAccessTable.surveyId))
|
|
.limit(1);
|
|
|
|
if (results.length === 0) {
|
|
log_store('Survey not found: %s', params.accessToken);
|
|
error(404, 'Survey not found');
|
|
}
|
|
|
|
if (await db.$count(surveyAnswersTable, eq(surveyAnswersTable.participantId, results[0].survey_access_table.id)) > 0) {
|
|
log_store('Answers already submitted: %s', params.accessToken);
|
|
error(400, 'Answers already submitted');
|
|
}
|
|
|
|
const survey = results[0].surveys_table;
|
|
const skills = await db.select().from(surveySkillsTable).where(eq(surveySkillsTable.surveyId, survey.id));
|
|
|
|
const formData = await request.formData();
|
|
// validate that the form doesn't contain invalid skill IDs
|
|
const skillEntries = [...formData.entries()].filter(([key, _]) => !key.startsWith('disable-'));
|
|
const allIdsValid = skillEntries.every(([key, _]) => skills.some(skill => skill.id.toString() === key));
|
|
const deselectedIds = [...formData.entries().filter(([key, _]) => key.startsWith('disable-')).map(([key, _]) => parseInt(key.replace('disable-', '')))];
|
|
if (!allIdsValid || skillEntries.length + deselectedIds.length !== skills.length) {
|
|
let missing_ids = skills.filter(skill => !skillEntries.some(([key, _]) => key === skill.id.toString()) && !deselectedIds.includes(skill.id));
|
|
let invalid_ids = skillEntries.filter(([key, _]) => !skills.some(skill => skill.id.toString() === key)).map(([key, _]) => key);
|
|
log_store.log("Invalid (%o) or missing (%o) skill IDs", invalid_ids, missing_ids);
|
|
error(400, 'Invalid skill ID');
|
|
}
|
|
|
|
const answers = skillEntries.map(([key, value]) => ({
|
|
participantId: results[0].survey_access_table.id,
|
|
skillId: parseInt(key),
|
|
rating: parseFloat(value.toString()) * 10 // convert to int to store in the database without rounding issues etc.
|
|
}));
|
|
if (answers.some(answer => isNaN(answer.rating) || answer.rating < 0 || answer.rating > 30)) {
|
|
log_store(
|
|
"Invalid answer: %o",
|
|
answers.filter(answer => isNaN(answer.rating) || answer.rating < 0 || answer.rating > 30)
|
|
);
|
|
error(400, 'Invalid answer');
|
|
}
|
|
|
|
await db.insert(surveyAnswersTable).values([...answers]);
|
|
|
|
redirect(303, `/${params.accessToken}/thanks`);
|
|
}
|
|
} |