fix: alot
CI / build-and-test (push) Canceled after 0s

This commit is contained in:
2026-10-19 21:41:07 +02:00
parent df90cf8a18
commit fa38ac7617
70 changed files with 1389 additions and 1023 deletions
+68 -8
View File
@@ -23,6 +23,24 @@ const translations: Record<Lang, Record<string, string>> = {
'common.close': 'Close',
'common.copied': 'Copied',
'common.logged_out': 'Logged out',
'errors.invalid_credentials': 'Invalid email or password',
'errors.too_many_requests': 'Too many attempts. Wait a minute and try again.',
'errors.validation_error': 'Some fields are not filled in correctly',
'errors.version_mismatch': 'The tab changed since it was loaded. Check it and try again.',
'errors.command_already_pending': 'A close request for this tab is already waiting for the terminal',
'errors.tab_not_owned': 'This tab is no longer open on the terminal',
'errors.device_revoked': 'The terminal for this tab has been unpaired',
'errors.name_exists': 'This customer already exists',
'errors.email_exists': 'A user with this email already exists',
'errors.resend_not_configured': 'Sending email is not set up on the server',
'errors.reminders_in_progress': 'Reminders are already being sent',
'errors.no_email': 'This customer has no email address',
'errors.forbidden': "You don't have permission to do this",
'errors.venue_forbidden': "You don't have permission to do this",
'errors.internal_error': 'Something went wrong on the server',
'errors.network_error': "Can't reach the server. Check the connection.",
'errors.session_expired': 'Your session has expired. Log in again.',
'errors.unknown': 'An error occurred',
'status_page.home': 'Back to KoolTap',
'not_found.title': 'Page not found',
'not_found.desc': "This page doesn't exist or has been moved.",
@@ -56,7 +74,13 @@ const translations: Record<Lang, Record<string, string>> = {
'tabs.email': 'Email',
'tabs.amount': 'Amount',
'tabs.items': 'Items',
'tabs.version': 'Version',
'tabs.search_placeholder': 'Search customers…',
'tabs.sort': 'Sort by',
'tabs.sort_name': 'Name',
'tabs.sort_amount': 'Highest amount',
'tabs.outstanding': '{amount} outstanding',
'tabs.closing': 'Closing…',
'tabs.no_matches': 'No tabs match "{query}"',
'tabs.reported': 'Last updated',
'tabs.actions': 'Actions',
'tabs.close': 'Close',
@@ -140,7 +164,8 @@ const translations: Record<Lang, Record<string, string>> = {
'commands.load_failed': 'Failed to load commands',
'commands.empty': 'No commands found',
'commands.empty_desc': 'Commands appear here when you send close requests.',
'commands.tab': 'Tab',
'commands.customer': 'Customer',
'commands.amount': 'Amount',
'commands.requested': 'Requested By',
'commands.payment': 'Payment',
'commands.created': 'Created',
@@ -157,7 +182,6 @@ const translations: Record<Lang, Record<string, string>> = {
'settings.device': 'Terminal',
'settings.paired': 'Paired as "{name}" — last seen {time}',
'settings.not_paired': 'No terminal paired yet',
'settings.connected': 'Connected',
'settings.since': 'Since {date}',
'settings.pair_desc': 'Pair a bar terminal to start receiving tabs.',
'settings.pair': 'Pair Terminal',
@@ -178,7 +202,8 @@ const translations: Record<Lang, Record<string, string>> = {
'overview.title': 'Overview',
'overview.open_tabs': 'Open Tabs',
'overview.device': 'Terminal',
'overview.pending': 'Pending Commands',
'overview.pending': 'Waiting for terminal',
'overview.outstanding': 'Outstanding',
'overview.recent': 'Recent Commands',
'overview.no_commands': 'No commands yet',
'overview.not_connected': 'Not connected',
@@ -199,6 +224,7 @@ const translations: Record<Lang, Record<string, string>> = {
'reminders.no_candidates_desc': 'Make sure planned customers have an email address.',
'reminders.send': 'Send Reminders',
'reminders.sending': 'Sending...',
'reminders.admin_only': 'Only admins can send reminders.',
'reminders.confirm': 'This emails a payment reminder to {count} customer(s) with an unpaid tab.',
'reminders.sent_title': 'Reminders Sent',
'reminders.partial': '{sent} of {total} sent',
@@ -233,6 +259,24 @@ const translations: Record<Lang, Record<string, string>> = {
'common.close': 'Sluiten',
'common.copied': 'Gekopieerd',
'common.logged_out': 'Uitgelogd',
'errors.invalid_credentials': 'Ongeldig e-mailadres of wachtwoord',
'errors.too_many_requests': 'Te veel pogingen. Wacht een minuutje en probeer opnieuw.',
'errors.validation_error': 'Sommige velden zijn niet correct ingevuld',
'errors.version_mismatch': 'De poef is gewijzigd sinds ze geladen werd. Controleer en probeer opnieuw.',
'errors.command_already_pending': 'Er wacht al een sluitverzoek voor deze poef op de kassa',
'errors.tab_not_owned': 'Deze poef staat niet meer open op de kassa',
'errors.device_revoked': 'De kassa van deze poef is ontkoppeld',
'errors.name_exists': 'Deze klant bestaat al',
'errors.email_exists': 'Er bestaat al een gebruiker met dit e-mailadres',
'errors.resend_not_configured': 'E-mail versturen is niet ingesteld op de server',
'errors.reminders_in_progress': 'Herinneringen worden al verstuurd',
'errors.no_email': 'Deze klant heeft geen e-mailadres',
'errors.forbidden': 'Je hebt geen toestemming om dit te doen',
'errors.venue_forbidden': 'Je hebt geen toestemming om dit te doen',
'errors.internal_error': 'Er ging iets mis op de server',
'errors.network_error': 'Kan de server niet bereiken. Controleer de verbinding.',
'errors.session_expired': 'Je sessie is verlopen. Log opnieuw in.',
'errors.unknown': 'Er is een fout opgetreden',
'status_page.home': 'Terug naar KoolTap',
'not_found.title': 'Pagina niet gevonden',
'not_found.desc': 'Deze pagina bestaat niet of is verplaatst.',
@@ -266,7 +310,13 @@ const translations: Record<Lang, Record<string, string>> = {
'tabs.email': 'E-mail',
'tabs.amount': 'Bedrag',
'tabs.items': 'Items',
'tabs.version': 'Versie',
'tabs.search_placeholder': 'Zoek klant…',
'tabs.sort': 'Sorteer op',
'tabs.sort_name': 'Naam',
'tabs.sort_amount': 'Hoogste bedrag',
'tabs.outstanding': '{amount} openstaand',
'tabs.closing': 'Wordt gesloten…',
'tabs.no_matches': 'Geen poefs gevonden voor "{query}"',
'tabs.reported': 'Laatst bijgewerkt',
'tabs.actions': 'Acties',
'tabs.close': 'Sluiten',
@@ -350,7 +400,8 @@ const translations: Record<Lang, Record<string, string>> = {
'commands.load_failed': 'Opdrachten konden niet geladen worden',
'commands.empty': 'Geen opdrachten gevonden',
'commands.empty_desc': 'Opdrachten verschijnen hier zodra je een sluitverzoek verstuurt.',
'commands.tab': 'Poef',
'commands.customer': 'Klant',
'commands.amount': 'Bedrag',
'commands.requested': 'Aangevraagd door',
'commands.payment': 'Betaling',
'commands.created': 'Aangemaakt',
@@ -367,7 +418,6 @@ const translations: Record<Lang, Record<string, string>> = {
'settings.device': 'Terminal',
'settings.paired': 'Gekoppeld als "{name}" — laatst gezien {time}',
'settings.not_paired': 'Nog geen terminal gekoppeld',
'settings.connected': 'Verbonden',
'settings.since': 'Sinds {date}',
'settings.pair_desc': 'Koppel een barterminal om poefs te ontvangen.',
'settings.pair': 'Terminal koppelen',
@@ -388,7 +438,8 @@ const translations: Record<Lang, Record<string, string>> = {
'overview.title': 'Overzicht',
'overview.open_tabs': 'Open poefs',
'overview.device': 'Terminal',
'overview.pending': 'Openstaande opdrachten',
'overview.pending': 'Wachtend op kassa',
'overview.outstanding': 'Openstaand',
'overview.recent': 'Recente opdrachten',
'overview.no_commands': 'Nog geen opdrachten',
'overview.not_connected': 'Niet verbonden',
@@ -409,6 +460,7 @@ const translations: Record<Lang, Record<string, string>> = {
'reminders.no_candidates_desc': 'Zorg dat geplande klanten een e-mailadres hebben.',
'reminders.send': 'Herinneringen versturen',
'reminders.sending': 'Bezig met versturen...',
'reminders.admin_only': 'Alleen beheerders kunnen herinneringen versturen.',
'reminders.confirm': 'Er wordt een betalingsherinnering gemaild naar {count} klant(en) met een openstaande poef.',
'reminders.sent_title': 'Herinneringen verstuurd',
'reminders.partial': '{sent} van {total} verstuurd',
@@ -436,6 +488,8 @@ interface LangContextType {
t: (key: string, params?: Params) => string;
/** Uses `<key>_plural` unless `count` is 1; `{count}` is filled in. */
tn: (key: string, count: number, params?: Params) => string;
/** An API error in the current language: by its code when translated, else its message. */
te: (error: unknown, fallbackKey?: string) => string;
/** "just now", "5m ago"…, falling back to a date after a week. */
relativeTime: (date: string | Date) => string;
dateTime: (date: string | Date) => string;
@@ -459,6 +513,12 @@ function helpers(lang: Lang): Omit<LangContextType, 'setLang'> {
lang,
t,
tn: (key, count, params) => t(count === 1 ? key : `${key}_plural`, { count, ...params }),
te: (error, fallbackKey = 'common.unknown_error') => {
const { code, message } = (error ?? {}) as { code?: string; message?: string };
const key = `errors.${code}`;
if (code && (translations[lang][key] ?? translations.en[key])) return t(key);
return message || t(fallbackKey);
},
relativeTime: (value) => {
const date = new Date(value);
const seconds = Math.floor((Date.now() - date.getTime()) / 1000);