diff --git a/frontend/src/routes/admin/+layout.svelte b/frontend/src/routes/admin/+layout.svelte index 7bf33ac..d141dbf 100644 --- a/frontend/src/routes/admin/+layout.svelte +++ b/frontend/src/routes/admin/+layout.svelte @@ -1,65 +1,45 @@ {#if $token} - - -
- -
+ + {#snippet children()} + + {/snippet} + {/if} - - diff --git a/frontend/src/routes/admin/+page.svelte b/frontend/src/routes/admin/+page.svelte index 98791d3..801a9a3 100644 --- a/frontend/src/routes/admin/+page.svelte +++ b/frontend/src/routes/admin/+page.svelte @@ -1,147 +1,214 @@ -

Admin Dashboard

+
-
- - -
- -{#if loading && sessions.length === 0} -

Loading sessions...

-{:else} -
- {#each sessions as session} -
-

Week {session.week_nr} - {session.date}

-
- {#if session.slots && session.slots.length > 0} - {#each session.slots as slot} -
-
- {slot.status} - {slot.start_time} - {slot.end_time} - {#if slot.code} - {slot.code} - {/if} -
-
- {#if slot.status === 'closed'} - - {:else if slot.status === 'open'} - - - - {:else if slot.status === 'locked'} - - - {/if} -
-
- {/each} - {:else} -

No slots scheduled.

- {/if} -
-
- {/each} + +
+
+
Dashboard
+
+ Diese Woche, Woche {String(currentWeekNr).padStart(2, '0')} +
+ {#if selectedCourse} +
+ {selectedCourse.name} · {selectedCourse.semester} +
+ {/if}
-{/if} +
+ {#if courses.length > 1} + + {/if} + + Export + +
+
- + +
+ 0 ? `Code: ${openSlots[0].code ?? '—'}` : 'Kein Slot offen'} + accent={openSlots.length > 0 ? 'var(--green)' : undefined} + /> + + + +
+ + +
+
+
+
Slots
+ +
+
Neueste zuerst
+
+ + {#if loading && slotRows.length === 0} +
+ Wird geladen… +
+ {:else if slotRows.length === 0} +
+ Noch keine Slots geplant. +
+ {:else} + + + + + + + + + + + + + {#each slotRows as { slot, session }, i} + + + + + + + + + {/each} + +
WocheDatumZeitStatusCodeAktionen
+ {weekLabel(session.week_nr)} + {session.date} + {slot.start_time}–{slot.end_time} + + {#if slot.code} + {slot.code} + {:else} + + {/if} + +
+ {#if slot.status === 'closed'} + + {:else if slot.status === 'open'} + {#if slot.code} + + {/if} + Anzeigen + + {:else if slot.status === 'locked'} + Anzeigen + + {/if} +
+
+ {/if} +
+ +
diff --git a/frontend/src/routes/admin/attendance/+page.svelte b/frontend/src/routes/admin/attendance/+page.svelte index f3a24e4..f6235f2 100644 --- a/frontend/src/routes/admin/attendance/+page.svelte +++ b/frontend/src/routes/admin/attendance/+page.svelte @@ -1,111 +1,220 @@ -

Attendance Matrix

+
-
- - - {#if sessions.length > 0} - - {/if} -
- -{#if data} -
- - - - - {#each data.slots as slot} - - {/each} - - - - {#each data.students as student} - - - {#each data.slots as slot} - {@const present = data.attendances.some(a => a.slot_id === slot.id && a.student_id === student.id)} - - {/each} - - {/each} - -
Student{slot.start_time}
{student.name} toggleAttendance(slot.id, student.id)}> - {present ? '✓' : ''} -
+ +
+
+
Anwesenheit
+
+ Kursmatrix · {selectedCourse?.semester ?? '—'} +
-{:else} -

Loading matrix...

-{/if} +
+ {#if courses.length > 1} + + {/if} + {#if selectedCourseId} + + CSV + + + Markdown + + + SQLite Backup + + {/if} +
+
- + +
+
+
+
Pro Studierende:r
+ +
+ {#if loading} + Wird geladen… + {/if} +
+ + {#if students.length === 0} +
+ Keine Studierenden gefunden. +
+ {:else} +
+ + + + + + {#each sessions as session, i} + + {/each} + + + + + + {#each students as student, i} + + + + {#each sessions as session} + {@const slotIds = (session.slots ?? []).map((sl: any) => sl.id)} + {@const sessionPresent = slotIds.some((sid: number) => isPresent(sid, student.id))} + + {/each} + + + + {/each} + +
#Studierende:r + W{String(session.week_nr).padStart(2, '0')} + AnwesendBonus
+ {i + 1} + +
+ + {initials(student.name)} + + {student.name} +
+
+ {#if slotIds.length > 0} + + {:else} + + {/if} + + {presentCount(student.id)} / {allSlotIds.length} + + {#if allSlotIds.length > 0} + + {#if bonusEligible(student.id)} + + {:else} + + {/if} + + {:else} + + {/if} +
+
+ {/if} +
+ +
diff --git a/frontend/src/routes/admin/login/+page.svelte b/frontend/src/routes/admin/login/+page.svelte index 9fcc2fa..ecea79a 100644 --- a/frontend/src/routes/admin/login/+page.svelte +++ b/frontend/src/routes/admin/login/+page.svelte @@ -1,82 +1,72 @@ - +
- + +
+
+ Tutor·manager +
+
Anwesenheit & Notizen für Tutorien.
+
+ + +
+
Anmeldung
+
Willkommen zurück
+ + +
{ e.preventDefault(); login(); }} style="margin-top:20px;display:flex;flex-direction:column;gap:12px"> +
+ + +
+ +
+ + +
+ + {#if error} +
+ {error} +
+ {/if} + + +
+ +
+ Nur für Tutor:innen. Studierende nutzen den Link der Tutor:in. +
+
+ +
~ Donnerstags ab 14 Uhr ~
+ +
diff --git a/frontend/src/routes/admin/students/+page.svelte b/frontend/src/routes/admin/students/+page.svelte index b49f46f..50a0f40 100644 --- a/frontend/src/routes/admin/students/+page.svelte +++ b/frontend/src/routes/admin/students/+page.svelte @@ -1,8 +1,158 @@ -
- Studierende -

Studierende

+
+ + +
+
+
Studierende
+
+ {selectedCourse?.name ?? 'Studierende'} + · {filtered.length} +
+
+
+ {#if courses.length > 1} + + {/if} + + +
+ + + + +
+ + + + + +
+ + +
+
+
+ + +
+ {#if filtered.length === 0} +
+ + {search ? 'Keine Treffer.' : 'Noch keine Studierenden.'} + +
+ {:else} + + + + + + + + + + {#each filtered as student, i} + + + + + + {/each} + +
#NameAktionen
+ {i + 1} + +
+ + {initials(student.name)} + + {student.name} +
+
+ +
+ {/if} +
+