chore(frontend): delete obsolete login and notes routes

This commit is contained in:
2026-04-28 19:16:06 +02:00
parent 0298e03781
commit 74255f23ac
2 changed files with 0 additions and 254 deletions

View File

@@ -1,172 +0,0 @@
<script lang="ts">
import { onMount } from 'svelte';
import { api } from '$lib/api';
import RoomCanvas from '$lib/RoomCanvas.svelte';
import type { Course, Session, Slot, Room, Student, LayoutElement, Note } from '$lib/types';
let courses = $state<Course[]>([]);
let selectedCourseId = $state<number | null>(null);
let sessions = $state<Session[]>([]);
let selectedSessionId = $state<number | null>(null);
let slots = $state<Slot[]>([]);
let selectedSlotId = $state<number | null>(null);
let layout = $state<LayoutElement[]>([]);
let notes = $state<Note[]>([]);
let students = $state<Student[]>([]);
let attendances = $state<any[]>([]);
onMount(async () => {
courses = await api.admin.courses.list();
if (courses.length > 0) selectedCourseId = courses[0].id;
});
$effect(() => {
if (selectedCourseId) {
api.admin.sessions.list(selectedCourseId).then(res => {
sessions = res;
if (sessions.length > 0) selectedSessionId = sessions[0].id;
});
api.admin.courses.listStudents(selectedCourseId).then(res => students = res);
}
});
$effect(() => {
if (selectedSessionId) {
const s = sessions.find(s => s.id === selectedSessionId);
slots = s?.slots || [];
if (slots.length > 0) selectedSlotId = slots[0].id;
}
});
$effect(() => {
if (selectedSlotId) {
const slot = slots.find(s => s.id === selectedSlotId);
if (slot?.room_id) {
api.admin.rooms.get(slot.room_id).then(r => layout = r.layout);
} else {
layout = [];
}
api.admin.slots.getNotes(selectedSlotId).then(res => notes = res);
api.admin.sessions.getAttendance(selectedSessionId!).then(res => {
attendances = res.attendances.filter((a: any) => a.slot_id === selectedSlotId);
});
}
});
let activeSeatId = $state<string | null>(null);
let noteContent = $state('');
function handleSeatClick(el: LayoutElement) {
if (el.type !== 'seat') return;
activeSeatId = el.id;
const studentId = attendances.find(a => a.seat_id === el.id)?.student_id;
if (studentId) {
const existing = notes.find(n => n.student_id === studentId);
noteContent = existing?.content || '';
} else {
noteContent = '';
}
}
async function saveNote() {
if (!selectedSlotId || !activeSeatId) return;
const studentId = attendances.find(a => a.seat_id === activeSeatId)?.student_id;
if (!studentId) {
alert('No student at this seat');
return;
}
try {
await api.admin.slots.upsertNote(selectedSlotId, studentId, noteContent);
notes = await api.admin.slots.getNotes(selectedSlotId);
activeSeatId = null;
} catch (e) {
alert(e);
}
}
let studentNames = $derived.by(() => {
const map: Record<string, string> = {};
attendances.forEach(a => {
if (a.seat_id) {
const s = students.find(s => s.id === a.student_id);
map[a.seat_id] = s?.name || 'Unknown';
}
});
return map;
});
let occupiedSeatIds = $derived(attendances.map(a => a.seat_id).filter(id => id !== null));
</script>
<h1>Seat Notes</h1>
<div class="selectors">
<select bind:value={selectedCourseId}>
{#each courses as course}
<option value={course.id}>{course.name}</option>
{/each}
</select>
<select bind:value={selectedSessionId}>
{#each sessions as session}
<option value={session.id}>Week {session.week_nr}</option>
{/each}
</select>
<select bind:value={selectedSlotId}>
{#each slots as slot}
<option value={slot.id}>{slot.start_time} - {slot.end_time}</option>
{/each}
</select>
</div>
<div class="notes-container">
<div class="map-view">
<RoomCanvas
elements={layout}
{occupiedSeatIds}
selectedId={activeSeatId}
{studentNames}
onElementClick={handleSeatClick}
/>
</div>
<div class="note-editor">
{#if activeSeatId}
{@const studentName = studentNames[activeSeatId]}
<h3>Note for {studentName || 'Empty Seat'}</h3>
{#if studentName}
<textarea bind:value={noteContent} placeholder="Enter observations..."></textarea>
<button class="primary" onclick={saveNote}>Save Note</button>
{:else}
<p>Select a seat occupied by a student to leave a note.</p>
{/if}
<button onclick={() => activeSeatId = null}>Cancel</button>
{:else}
<p>Click a seat on the map to add or view notes.</p>
{/if}
<div class="existing-notes">
<h3>Recent Notes</h3>
{#each notes as note}
<div class="note-item">
<strong>{students.find(s => s.id === note.student_id)?.name}:</strong>
<p>{note.content}</p>
</div>
{/each}
</div>
</div>
</div>
<style>
.selectors { margin-bottom: 20px; }
select { margin-right: 10px; padding: 5px; }
.notes-container { display: grid; grid-template-columns: 1fr 300px; gap: 20px; }
.note-editor { background: #f8f9fa; padding: 20px; border-radius: 8px; }
textarea { width: 100%; height: 100px; margin: 10px 0; }
.primary { background: #007bff; color: white; border: none; padding: 8px 16px; border-radius: 4px; }
.note-item { font-size: 0.9em; border-bottom: 1px solid #ddd; padding: 5px 0; }
.note-item p { margin: 5px 0; }
</style>

View File

@@ -1,82 +0,0 @@
<script lang="ts">
import { api } from '$lib/api';
import { token } from '$lib/auth';
import { goto } from '$app/navigation';
let email = '';
let password = '';
let error = '';
let loading = false;
async function login() {
loading = true;
error = '';
try {
const res = await api.auth.login(email, password);
token.set(res.token);
goto('/admin');
} catch (e: any) {
error = e.message || 'Invalid credentials';
} finally {
loading = false;
}
}
</script>
<div class="login-container">
<h1>Tutor Login</h1>
<form on:submit|preventDefault={login}>
<div class="field">
<label for="email">Email</label>
<input id="email" type="email" bind:value={email} required />
</div>
<div class="field">
<label for="password">Password</label>
<input id="password" type="password" bind:value={password} required />
</div>
{#if error}
<p class="error">{error}</p>
{/if}
<button type="submit" disabled={loading}>
{loading ? 'Logging in...' : 'Login'}
</button>
</form>
</div>
<style>
.login-container {
max-width: 400px;
margin: 100px auto;
padding: 20px;
border: 1px solid #ccc;
border-radius: 8px;
}
.field {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
}
input {
width: 100%;
padding: 8px;
box-sizing: border-box;
}
.error {
color: red;
margin-bottom: 15px;
}
button {
width: 100%;
padding: 10px;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:disabled {
background: #ccc;
}
</style>