feat: Oberflaechenbausteine, Anwendungsrahmen und Konventionen
Basisbausteine im shadcn/ui-Stil, aber mit drei bewussten Abweichungen: - Bedienelemente sind 44px hoch statt 36px. Ich bediene die App oft am Handy im Heim oder auf dem Amt; kleiner ist dort nicht treffsicher. - Auswahlfelder benutzen das native <select>. Android und iOS oeffnen dafuer ihre eigene Liste - schneller als jeder Nachbau, und mit Screenreader und Tastatur funktioniert es ohne Zutun. - Eingabefelder haben mindestens 16px Schrift, sonst zoomt iOS-Safari beim Hineintippen das Formular heran. <Feld> verdrahtet Beschriftung, Erklaerung und Fehler ueber aria-describedby. Der Erklaerungstext ist kein Beiwerk: die Anwendung benutzt Begriffe aus dem Betreuungsrecht, die niemand nachschlagen soll. <Rechtshinweis> ist der stehende Vermerk, dass hier keine Rechtsberatung stattfindet. Er steht an jeder Stelle mit Paragraphenbezug. Der Anwendungsrahmen fuehrt drei Bedingungen zusammen, ohne die niemand an Fachdaten kommt: angemeldet, zweiter Faktor eingerichtet, mindestens eine betreute Person zugeordnet. Die Navigation zeigt Zaehler fuer ueberfaellige Fristen und neuen Posteingang - die Frage "wo muss ich hin?" wird schon im Menue beantwortet. Das Farbschema wird per Inline-Skript mit CSP-Nonce gesetzt, bevor die Seite gezeichnet wird - sonst blitzt beim Laden das helle Thema auf. docs/KONVENTIONEN.md haelt fest, was in allen weiteren Etappen gilt: Verzeichnisaufbau, Cent-Betraege, Umgang mit verschluesselten Feldern, Zugriffspruefung, Audit-Pflicht, Ampelfarben, Commit-Trailer. Etappe: 1 Phase: Fundament
This commit is contained in:
+17
-12
@@ -1,4 +1,4 @@
|
||||
import NextAuth from 'next-auth'
|
||||
import NextAuth, { CredentialsSignin } from 'next-auth'
|
||||
import Credentials from 'next-auth/providers/credentials'
|
||||
import type { Rolle } from '@prisma/client'
|
||||
import { db } from '@/lib/db'
|
||||
@@ -25,18 +25,23 @@ import { protokollieren } from '@/lib/audit'
|
||||
* Benutzer nur bis zur Einrichtungsseite - erzwungen im App-Layout.
|
||||
*/
|
||||
|
||||
export class AnmeldeFehler extends Error {
|
||||
constructor(
|
||||
public readonly grund:
|
||||
| 'daten-falsch'
|
||||
| 'gesperrt'
|
||||
| 'konto-inaktiv'
|
||||
| 'zweiter-faktor-fehlt'
|
||||
| 'code-falsch',
|
||||
public readonly nochSekunden?: number,
|
||||
) {
|
||||
export type AnmeldeGrund =
|
||||
| 'daten-falsch'
|
||||
| 'gesperrt'
|
||||
| 'konto-inaktiv'
|
||||
| 'code-falsch'
|
||||
|
||||
/**
|
||||
* Auth.js transportiert Fehler aus authorize() nur ueber das Feld "code".
|
||||
* Deshalb erbt der Fehler von CredentialsSignin und kodiert eine etwaige
|
||||
* Restsperrzeit in den Code hinein: "gesperrt:120".
|
||||
*/
|
||||
export class AnmeldeFehler extends CredentialsSignin {
|
||||
code: string
|
||||
|
||||
constructor(grund: AnmeldeGrund, nochSekunden?: number) {
|
||||
super(grund)
|
||||
this.name = 'AnmeldeFehler'
|
||||
this.code = nochSekunden ? `${grund}:${nochSekunden}` : grund
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user