91 lines
2.5 KiB
TypeScript
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
|
|
}
|