feat: Set up initial monorepo structure for admin and mobile applications with core configurations and database integration.
This commit is contained in:
90
innungsapp/apps/admin/lib/trpc-error.ts
Normal file
90
innungsapp/apps/admin/lib/trpc-error.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
Reference in New Issue
Block a user