fix(frontend): enforce lint locally and in CI, fix all pre-existing violations
Some checks failed
CI / Unit & Component Tests (push) Successful in 1m59s
CI / E2E Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled

## Pre-commit hook
- Add .husky/pre-commit at repo root: runs `cd frontend && npm run lint`
- Update prepare script in package.json to auto-configure git hooks path
  on npm install (git -C .. config core.hooksPath .husky)
- Add lint step to CI unit-tests job so it catches issues before tests run
- Add generated dirs to .prettierignore (paraglide_bak*, test-results, .auth)
- Add src/lib/paraglide_bak* to .gitignore so ESLint can ignore them

## ESLint fixes (all pre-existing)
- Disable svelte/no-navigation-without-resolve: false positive in SvelteKit
  (rule targets Svelte 5 standalone routing, not SvelteKit <a href>)
- Fix svelte/require-each-key: add (item.id)/(item) keys to all {#each} blocks
  across 10 files — improves Svelte reconciliation performance
- Fix svelte/prefer-writable-derived in PersonTypeahead: $state+$effect → $derived
- Fix svelte/prefer-svelte-reactivity: URLSearchParams → SvelteURLSearchParams,
  Map → SvelteMap (enables Svelte reactive tracking)
- Fix @typescript-eslint/no-unused-vars: remove dead imports/variables

## Prettier
- Run npm run format to bring all source files in line with .prettierrc

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-03-20 15:55:42 +01:00
parent 28dea45cc3
commit db2fc33e99
53 changed files with 2522 additions and 2061 deletions

View File

@@ -3,8 +3,17 @@ import { env } from '$env/dynamic/private';
import { createApiClient } from '$lib/api.server';
import { parseBackendError, getErrorMessage } from '$lib/errors';
export async function load({ fetch, locals }: { fetch: typeof globalThis.fetch; locals: App.Locals }) {
const canWrite = locals.user?.groups?.some((g: { permissions: string[] }) => g.permissions.includes('WRITE_ALL')) ?? false;
export async function load({
fetch,
locals
}: {
fetch: typeof globalThis.fetch;
locals: App.Locals;
}) {
const canWrite =
locals.user?.groups?.some((g: { permissions: string[] }) =>
g.permissions.includes('WRITE_ALL')
) ?? false;
if (!canWrite) throw error(403, 'Forbidden');
const api = createApiClient(fetch);

View File

@@ -74,7 +74,9 @@ function handleDateInput(e: Event) {
<form method="POST" enctype="multipart/form-data" use:enhance class="space-y-6 pb-20">
<!-- ── Section 1: Wer & Wann ── -->
<div class="rounded-sm border border-brand-sand bg-white p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-gray-400 uppercase">{m.doc_section_who_when()}</h2>
<h2 class="mb-5 text-xs font-bold tracking-widest text-gray-400 uppercase">
{m.doc_section_who_when()}
</h2>
<div class="grid grid-cols-1 gap-5 md:grid-cols-2">
<!-- Datum -->
@@ -104,7 +106,9 @@ function handleDateInput(e: Event) {
<!-- Ort -->
<div>
<label for="location" class="mb-1 block text-sm font-medium text-gray-700">{m.form_label_location()}</label>
<label for="location" class="mb-1 block text-sm font-medium text-gray-700"
>{m.form_label_location()}</label
>
<input
id="location"
type="text"
@@ -129,12 +133,16 @@ function handleDateInput(e: Event) {
<!-- ── Section 2: Beschreibung ── -->
<div class="rounded-sm border border-brand-sand bg-white p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-gray-400 uppercase">{m.doc_section_description()}</h2>
<h2 class="mb-5 text-xs font-bold tracking-widest text-gray-400 uppercase">
{m.doc_section_description()}
</h2>
<div class="space-y-5">
<!-- Titel -->
<div>
<label for="title" class="mb-1 block text-sm font-medium text-gray-700">{m.form_label_title()} *</label>
<label for="title" class="mb-1 block text-sm font-medium text-gray-700"
>{m.form_label_title()} *</label
>
<input
id="title"
type="text"
@@ -168,7 +176,9 @@ function handleDateInput(e: Event) {
<!-- Inhalt -->
<div>
<label for="summary" class="mb-1 block text-sm font-medium text-gray-700">{m.form_label_content()}</label>
<label for="summary" class="mb-1 block text-sm font-medium text-gray-700"
>{m.form_label_content()}</label
>
<textarea
id="summary"
name="summary"
@@ -182,7 +192,9 @@ function handleDateInput(e: Event) {
<!-- ── Section 3: Transkription ── -->
<div class="rounded-sm border border-brand-sand bg-white p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-gray-400 uppercase">{m.form_label_transcription()}</h2>
<h2 class="mb-5 text-xs font-bold tracking-widest text-gray-400 uppercase">
{m.form_label_transcription()}
</h2>
<textarea
id="transcription"
name="transcription"
@@ -194,10 +206,13 @@ function handleDateInput(e: Event) {
<!-- ── Section 4: Datei ── -->
<div class="rounded-sm border border-brand-sand bg-white p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-gray-400 uppercase">{m.doc_section_file()}</h2>
<h2 class="mb-5 text-xs font-bold tracking-widest text-gray-400 uppercase">
{m.doc_section_file()}
</h2>
<label for="file-upload" class="mb-1 block text-sm font-medium text-gray-700">
{m.doc_file_upload_label()} <span class="font-normal text-gray-400">({m.doc_file_upload_note()})</span>
{m.doc_file_upload_label()}
<span class="font-normal text-gray-400">({m.doc_file_upload_note()})</span>
</label>
<input
id="file-upload"