feat: make server own tabs
CI / build-and-test (push) Canceled after 0s

This commit is contained in:
2026-10-20 16:18:36 +02:00
parent 1e4438ec5a
commit 0ca9f4d16a
31 changed files with 2101 additions and 892 deletions
+36 -22
View File
@@ -29,6 +29,8 @@ const translations: Record<Lang, Record<string, string>> = {
'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.tab_not_found': 'This tab is no longer open',
'errors.tab_empty': 'There is nothing on this tab to settle',
'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',
@@ -90,14 +92,13 @@ const translations: Record<Lang, Record<string, string>> = {
'tabs.lines_empty': 'No items on this tab.',
'tabs.each': 'each',
'tabs.close_title': "Close {name}'s tab?",
'tabs.close_desc': 'Send a close request to the terminal.',
'tabs.close_desc': 'Settles everything on the tab now. The terminals show it after their next sync.',
'tabs.payment': 'Payment method',
'tabs.select_payment': 'Please select a payment method',
'tabs.send': 'Send close request',
'tabs.sending': 'Sending...',
'tabs.request_sent': 'Close request sent',
'tabs.request_sent_desc': 'Sent to the terminal',
'tabs.request_result': 'Close request for {name}: {status}',
'tabs.settled': 'Tab settled',
'tabs.settled_desc': '{name}: {amount}',
'tabs.send_test': 'Send test email',
'tabs.test_sent': 'Test email sent',
'tabs.test_sent_desc': 'Sent to {email}',
@@ -185,7 +186,12 @@ const translations: Record<Lang, Record<string, string>> = {
'settings.since': 'Since {date}',
'settings.pair_desc': 'Pair a bar terminal to start receiving tabs.',
'settings.pair': 'Pair Terminal',
'settings.repair': 'Re-pair Terminal',
'settings.repair': 'Pair Another Terminal',
'settings.unpair': 'Unpair',
'settings.unpair_title': 'Unpair {name}?',
'settings.unpair_desc': 'The terminal stops syncing and has to be paired again to reconnect. Its changes that have not been synced yet are lost.',
'settings.unpaired': '{name} is unpaired',
'settings.terminals': '{count} terminals paired',
'settings.generating': 'Generating...',
'settings.pair_title': 'Pair a Terminal',
'settings.pair_instructions': 'Enter this code on the bar terminal to connect it to your venue.',
@@ -208,6 +214,7 @@ const translations: Record<Lang, Record<string, string>> = {
'overview.no_commands': 'No commands yet',
'overview.not_connected': 'Not connected',
'overview.last_seen': 'Last seen {time}',
'overview.terminals': '{count} terminals, last seen {time}',
'auth.login': 'Sign in',
'auth.logging_in': 'Signing in...',
'auth.email': 'Email',
@@ -293,27 +300,27 @@ const translations: Record<Lang, Record<string, string>> = {
'stock.out': 'Out',
'stock.adjust': 'Adjust',
'stock.start_tracking': 'Track stock',
'stock.start_tracking_desc': "The terminal doesn't track stock for this product yet. Enter how many you have to start tracking it.",
'stock.start_tracking_desc': "Stock isn't tracked for this product yet. Enter how many you have to start tracking it.",
'stock.cancel_adjustment': 'Cancel {change} for {name}',
'stock.cancelled': 'Change cancelled',
'stock.current': 'Currently {stock} in stock on the terminal.',
'stock.current': 'Currently {stock} in stock.',
'stock.mode_add': 'Add (delivery)',
'stock.mode_remove': 'Take out (breakage, own use…)',
'stock.mode_count': 'Count (set the stock to what you counted)',
'stock.quantity': 'Quantity',
'stock.counted': 'Counted',
'stock.preview': '{from} → {to}',
'stock.count_hint': 'Drinks sold between your count and the terminal receiving it are not subtracted.',
'stock.count_hint': 'Drinks rung up before your count are in it: they are not subtracted again, also not when an offline terminal sends them later.',
'stock.note': 'Note (optional)',
'stock.note_placeholder': 'e.g. delivery from the brewery',
'stock.threshold': 'Warn when stock is at or below',
'stock.threshold_none': 'No warning',
'stock.threshold_save': 'Save',
'stock.threshold_saved': 'Warning level saved',
'stock.send': 'Send to terminal',
'stock.send': 'Save',
'stock.sending': 'Sending…',
'stock.sent': 'Sent to the terminal',
'stock.sent_desc': 'The stock changes on the terminal at its next sync.',
'stock.sent': 'Stock updated',
'stock.sent_desc': 'The terminals show it after their next sync.',
'stock.delivery': 'Register delivery',
'stock.delivery_title': 'Register delivery',
'stock.delivery_desc': 'Enter how many of each product were delivered. Products you leave empty are not changed.',
@@ -355,6 +362,8 @@ const translations: Record<Lang, Record<string, string>> = {
'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.tab_not_found': 'Deze poef staat niet meer open',
'errors.tab_empty': 'Er staat niets op deze poef om af te rekenen',
'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',
@@ -416,14 +425,13 @@ const translations: Record<Lang, Record<string, string>> = {
'tabs.lines_empty': 'Geen items op deze poef.',
'tabs.each': 'per stuk',
'tabs.close_title': 'Poef van {name} sluiten?',
'tabs.close_desc': 'Stuur een verzoek naar de terminal om deze poef te sluiten.',
'tabs.close_desc': 'Rekent alles op de poef nu af. De terminals tonen het na hun volgende synchronisatie.',
'tabs.payment': 'Betaalmethode',
'tabs.select_payment': 'Kies een betaalmethode',
'tabs.send': 'Sluitverzoek versturen',
'tabs.sending': 'Bezig met versturen...',
'tabs.request_sent': 'Sluitverzoek verstuurd',
'tabs.request_sent_desc': 'Verstuurd naar de terminal',
'tabs.request_result': 'Sluitverzoek voor {name}: {status}',
'tabs.settled': 'Poef afgerekend',
'tabs.settled_desc': '{name}: {amount}',
'tabs.send_test': 'Testmail versturen',
'tabs.test_sent': 'Testmail verstuurd',
'tabs.test_sent_desc': 'Verstuurd naar {email}',
@@ -511,7 +519,12 @@ const translations: Record<Lang, Record<string, string>> = {
'settings.since': 'Sinds {date}',
'settings.pair_desc': 'Koppel een barterminal om poefs te ontvangen.',
'settings.pair': 'Terminal koppelen',
'settings.repair': 'Terminal opnieuw koppelen',
'settings.repair': 'Nog een terminal koppelen',
'settings.unpair': 'Ontkoppelen',
'settings.unpair_title': '{name} ontkoppelen?',
'settings.unpair_desc': 'De terminal synchroniseert niet meer en moet opnieuw gekoppeld worden. Wijzigingen die nog niet gesynchroniseerd zijn, gaan verloren.',
'settings.unpaired': '{name} is ontkoppeld',
'settings.terminals': '{count} terminals gekoppeld',
'settings.generating': 'Code aanmaken...',
'settings.pair_title': 'Terminal koppelen',
'settings.pair_instructions': 'Voer deze code in op de barterminal om hem met je zaak te verbinden.',
@@ -534,6 +547,7 @@ const translations: Record<Lang, Record<string, string>> = {
'overview.no_commands': 'Nog geen opdrachten',
'overview.not_connected': 'Niet verbonden',
'overview.last_seen': 'Laatst gezien {time}',
'overview.terminals': '{count} terminals, laatst gezien {time}',
'auth.login': 'Inloggen',
'auth.logging_in': 'Bezig met inloggen...',
'auth.email': 'E-mail',
@@ -619,27 +633,27 @@ const translations: Record<Lang, Record<string, string>> = {
'stock.out': 'Op',
'stock.adjust': 'Aanpassen',
'stock.start_tracking': 'Voorraad bijhouden',
'stock.start_tracking_desc': 'De kassa houdt voor dit product nog geen voorraad bij. Vul in hoeveel je er hebt om te beginnen.',
'stock.start_tracking_desc': 'Voor dit product wordt nog geen voorraad bijgehouden. Vul in hoeveel je er hebt om te beginnen.',
'stock.cancel_adjustment': '{change} voor {name} annuleren',
'stock.cancelled': 'Wijziging geannuleerd',
'stock.current': 'Nu {stock} in voorraad op de kassa.',
'stock.current': 'Nu {stock} in voorraad.',
'stock.mode_add': 'Bijvullen (levering)',
'stock.mode_remove': 'Afboeken (breuk, eigen gebruik…)',
'stock.mode_count': 'Tellen (voorraad wordt wat je telde)',
'stock.quantity': 'Aantal',
'stock.counted': 'Geteld',
'stock.preview': '{from} → {to}',
'stock.count_hint': 'Wat verkocht wordt tussen je telling en het moment dat de kassa ze ontvangt, wordt niet afgetrokken.',
'stock.count_hint': 'Wat voor je telling aangeslagen werd, zit erin: het wordt niet nog eens afgetrokken, ook niet als een offline kassa het later doorstuurt.',
'stock.note': 'Notitie (optioneel)',
'stock.note_placeholder': 'bv. levering brouwerij',
'stock.threshold': 'Waarschuw vanaf',
'stock.threshold_none': 'Geen waarschuwing',
'stock.threshold_save': 'Opslaan',
'stock.threshold_saved': 'Waarschuwingsniveau opgeslagen',
'stock.send': 'Naar kassa sturen',
'stock.send': 'Opslaan',
'stock.sending': 'Versturen…',
'stock.sent': 'Naar de kassa gestuurd',
'stock.sent_desc': 'De voorraad wijzigt op de kassa bij de volgende synchronisatie.',
'stock.sent': 'Voorraad bijgewerkt',
'stock.sent_desc': 'De kassa\'s tonen het na hun volgende synchronisatie.',
'stock.delivery': 'Levering invoeren',
'stock.delivery_title': 'Levering invoeren',
'stock.delivery_desc': 'Vul in hoeveel er van elk product geleverd is. Lege producten blijven ongewijzigd.',