implement survey review mode

Closes #19
This commit is contained in:
Markus Brueckner 2025-02-08 08:38:44 +01:00
parent 0d32c93787
commit 1ab979b5b4
5 changed files with 103 additions and 52 deletions

View file

@ -11,7 +11,7 @@
primary: 'bg-sky-200 hover:bg-sky-300 text-black border border-black rounded',
secondary: 'bg-slate-200 hover:bg-slate-300 text-black border border-black rounded',
tertiary: 'bg-white hover:bg-slate-100 text-black border border-slate-500 rounded',
ghost: 'bg-white hover:bg-slate-100 text-sky-600'
ghost: 'bg-none hover:bg-slate-100 text-sky-600'
};
</script>

View file

@ -4,11 +4,12 @@
import { flatGroup } from 'd3-array';
import { Axis, Chart, Points, Spline, Svg } from 'layerchart';
const {
data
}: {
type Props = {
reviewMode: boolean;
data: { skill: string; participant: number; rating: number | undefined }[];
} = $props();
};
const { data, reviewMode }: Props = $props();
const averageValues = flatGroup(data, (d) => d.skill)
.map(([skill, ratings]) => {
@ -34,6 +35,15 @@
{ stroke: 'stroke-cyan-300', fill: 'fill-cyan-400' },
{ stroke: 'stroke-pink-300', fill: 'fill-pink-400' }
];
const anonymousColor = { stroke: 'stroke-slate-300', fill: 'fill-slate-400' };
function getColor(idx: number) {
if (reviewMode) {
return anonymousColor;
}
return colors[idx % colors.length];
}
</script>
<div class="chart-container">
@ -59,13 +69,9 @@
<Spline
data={[...ratings, ratings[0]]}
curve={curveLinear}
class="{colors[idx % colors.length].stroke} stroke-[2px]"
/>
<Points
data={ratings}
class="{colors[idx % colors.length].stroke} {colors[idx % colors.length]
.fill} stroke-[2px]"
class="{getColor(idx).stroke} stroke-[2px]"
/>
<Points data={ratings} class="{getColor(idx).stroke} {getColor(idx).fill} stroke-[2px]" />
{/each}
<Spline
data={[...averageValues, averageValues[0]]}

View file

@ -0,0 +1,15 @@
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="size-5"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z"
/>
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
</svg>

After

Width:  |  Height:  |  Size: 493 B

View file

@ -0,0 +1,14 @@
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="size-5"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M3.98 8.223A10.477 10.477 0 0 0 1.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.451 10.451 0 0 1 12 4.5c4.756 0 8.773 3.162 10.065 7.498a10.522 10.522 0 0 1-4.293 5.774M6.228 6.228 3 3m3.228 3.228 3.65 3.65m7.894 7.894L21 21m-3.228-3.228-3.65-3.65m0 0a3 3 0 1 0-4.243-4.243m4.242 4.242L9.88 9.88"
/>
</svg>

After

Width:  |  Height:  |  Size: 544 B

View file

@ -17,6 +17,9 @@
import ShareIcon from '$lib/components/icons/ShareIcon.svelte';
import { checkAccess } from '$lib/helpers/shared/permissions';
import { AccessLevel, type ParticipantId } from '$lib/types';
import Button from '$lib/components/Button.svelte';
import EyeSlash from '$lib/components/icons/EyeSlash.svelte';
import Eye from '$lib/components/icons/Eye.svelte';
let { data }: { data: PageData } = $props();
@ -45,8 +48,7 @@
let deleteAnswersDialogRef: HTMLDialogElement | null = $state(null);
let participantAnswersDeletionCandidateId = $state<number | null>(null);
$inspect(data);
let reviewMode = $state(false);
async function deleteSurvey() {
await fetch('', {
@ -61,6 +63,18 @@
<a href="/" class="flex items-center" aria-label="Home" title="Home">
<HomeIcon />
</a>
<Button
kind="ghost"
class="text-white hover:bg-indigo-900"
onclick={() => (reviewMode = !reviewMode)}
title={reviewMode ? 'Show details' : 'Hide details'}
>
{#if reviewMode}
<Eye />
{:else}
<EyeSlash />
{/if}
</Button>
{#if checkAccess(data, AccessLevel.Clone)}
<a
href="../survey/new?from={data.id}"
@ -104,8 +118,9 @@
<MarkdownBlock class="ml-4 mt-4 text-xs text-slate-500" value={data.description} />
{/if}
<h2 class="ml-2 mt-4 text-2xl">Participants</h2>
<ul class="disc ml-4">
{#if !reviewMode}
<h2 class="ml-2 mt-4 text-2xl">Participants</h2>
<ul class="disc ml-4">
{#each data.participants as participant}
<li>
<span class="mr-5">
@ -142,11 +157,12 @@
{/if}
</li>
{/each}
</ul>
</ul>
{/if}
{#if checkAccess(data, AccessLevel.ReadResult)}
<div class="grid grid-cols-1 justify-items-center">
<Diagram data={diagramData} />
<Diagram data={diagramData} {reviewMode}/>
</div>
{:else}
<div class="text-center">You do not have permission to see the survey results</div>