diff --git a/src/routes/(app)/+page.svelte b/src/routes/(app)/+page.svelte
index 108340e..5a30e66 100644
--- a/src/routes/(app)/+page.svelte
+++ b/src/routes/(app)/+page.svelte
@@ -40,7 +40,7 @@
{survey.title}
({survey.fillRate.filled}/{survey.fillRate.expected})
- {#if survey.fillRate.filled === survey.fillRate.expected}
+ {#if survey.fillRate.filled === survey.fillRate.expected && survey.fillRate.expected > 0}
{/if}
diff --git a/src/routes/(app)/survey/[surveyId]/+page.svelte b/src/routes/(app)/survey/[surveyId]/+page.svelte
index 91cc3fb..ae024e0 100644
--- a/src/routes/(app)/survey/[surveyId]/+page.svelte
+++ b/src/routes/(app)/survey/[surveyId]/+page.svelte
@@ -17,13 +17,22 @@
let { data }: { data: PageData } = $props();
- const diagramData = data.skills.flatMap((skill) =>
- data.participants.map((participant) => ({
- skill: skill.title,
- participant: participant.id,
- rating: participant.answers.find((answer) => answer.skillId === skill.id)?.rating
- }))
- );
+ const diagramData = data.skills.flatMap((skill) => {
+ if (data.participants.length > 0) {
+ return data.participants.map((participant) => ({
+ skill: skill.title,
+ participant: participant.id,
+ rating: participant.answers.find((answer) => answer.skillId === skill.id)?.rating
+ }));
+ } else {
+ // fallback pseudo participant because empty diagram data will break the diagram and make the survey page unaccessible
+ return {
+ skill: skill.title,
+ participant: -1,
+ rating: undefined
+ };
+ }
+ });
function copyLinkToClipboard(link: string) {
navigator.clipboard.writeText(link);
diff --git a/src/routes/(app)/survey/[surveyId]/edit/+page.server.ts b/src/routes/(app)/survey/[surveyId]/edit/+page.server.ts
index 0e20af7..4883557 100644
--- a/src/routes/(app)/survey/[surveyId]/edit/+page.server.ts
+++ b/src/routes/(app)/survey/[surveyId]/edit/+page.server.ts
@@ -5,7 +5,7 @@ import debug from 'debug';
import { fromFormData } from '$lib/survey';
import { db } from '../../../../../db';
import { surveyAccessTable, surveyAnswersTable, surveySkillsTable, surveysTable } from '../../../../../db/schema';
-import { eq, inArray } from 'drizzle-orm';
+import { eq, inArray, and } from 'drizzle-orm';
import { addParticipant, addSkill, loadSurveyData } from '../../../../../db/survey';
const log = debug('survey:admin:edit');
@@ -58,10 +58,13 @@ export const actions = {
// update the participants where applicable (unchanged participants are left untouched)
const deletedParticipants = survey.participants.filter(participant => !participants.includes(participant.email));
const newParticipants = participants.filter(email => !survey.participants.some(candidate => candidate.email === email));
- // delete all participants no longer part of the survey
- await db.delete(surveyAccessTable).where(inArray(surveyAccessTable.recepientEmail, deletedParticipants.map(participant => participant.email)));
- // delete answers from deleted participants
- await db.delete(surveyAnswersTable).where(inArray(surveyAnswersTable.participantId, deletedParticipants.map(participant => participant.id)));
+ // delete all participants no longer part of the survey (this should also delete their answers via cascade delete)
+ await db.delete(surveyAccessTable).where(
+ and(
+ eq(surveyAccessTable.surveyId, survey.id),
+ inArray(surveyAccessTable.recepientEmail, deletedParticipants.map(participant => participant.email))
+ )
+ );
// add any new participants
for (const newParticipant of newParticipants) {
await addParticipant(survey.id, newParticipant);