stadtwerke/innungsapp/apps/admin/lib/trpc-error.ts

91 lines
2.5 KiB
TypeScript

/**
* Converts a tRPC/Zod error into a user-friendly German string.
*/
export function getTrpcErrorMessage(error: { message: string } | null | undefined): string {
if (!error) return ''
try {
const issues = JSON.parse(error.message) as Array<{
code: string
path: string[]
message: string
minimum?: number
maximum?: number
}>
if (Array.isArray(issues) && issues.length > 0) {
return issues
.map((issue) => {
const field = fieldLabel(issue.path.join('.'))
const msg = zodMessageDe(issue)
return field ? `${field} ${msg}` : msg
})
.join(' · ')
}
} catch {
// Not JSON — fall through to generic messages below
}
return genericMessageDe(error.message)
}
function zodMessageDe(issue: {
code: string
minimum?: number
maximum?: number
message?: string
}): string {
switch (issue.code) {
case 'too_small':
if (issue.minimum === 1) return 'ist ein Pflichtfeld.'
return `muss mindestens ${issue.minimum} Zeichen lang sein.`
case 'too_big':
return `darf maximal ${issue.maximum} Zeichen lang sein.`
case 'invalid_string':
return 'hat ein ungültiges Format.'
case 'invalid_type':
return 'ist ein Pflichtfeld.'
case 'invalid_enum_value':
return 'enthält einen ungültigen Wert.'
default:
return 'ist ungültig.'
}
}
function genericMessageDe(message: string): string {
const lower = message.toLowerCase()
if (lower.includes('unauthorized') || lower.includes('not authenticated'))
return 'Sie sind nicht angemeldet.'
if (lower.includes('forbidden') || lower.includes('not allowed'))
return 'Sie haben keine Berechtigung für diese Aktion.'
if (lower.includes('not found'))
return 'Der Eintrag wurde nicht gefunden.'
if (lower.includes('email'))
return 'Die E-Mail-Adresse ist ungültig.'
return 'Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.'
}
const FIELD_LABELS: Record<string, string> = {
sparte: 'Sparte',
stellenAnz: 'Anzahl Stellen',
kontaktEmail: 'Kontakt-E-Mail',
kontaktName: 'Ansprechpartner',
verguetung: 'Vergütung',
lehrjahr: 'Lehrjahr',
beschreibung: 'Beschreibung',
memberId: 'Betrieb',
title: 'Titel',
body: 'Inhalt',
kategorie: 'Kategorie',
name: 'Name',
email: 'E-Mail',
betrieb: 'Betrieb',
ort: 'Ort',
telefon: 'Telefon',
datum: 'Datum',
titel: 'Titel',
maxTeilnehmer: 'Max. Teilnehmer',
typ: 'Typ',
}
function fieldLabel(field: string): string {
return FIELD_LABELS[field] ?? field
}