wutzcalc/client/src/api.ts
müde 2a43b59947 tablet: split price/pfand, light mode, bigger bold text
- show drink price and Pfand separately on tiles and in cart
- add light/dark toggle on the bar-picker page (persisted)
- theme via CSS variables, applied on load for tablet + admin
- larger, bolder text throughout; much bigger total sum
2026-06-14 21:57:52 +02:00

55 lines
1.6 KiB
TypeScript

import type {
Bar,
BarConfig,
CreateTransactionRequest,
CreateTransactionResponse,
} from '@wutzcalc/shared';
async function json<T>(res: Response): Promise<T> {
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
return res.json() as Promise<T>;
}
export const api = {
bars: () => fetch('/api/bars').then(json<Bar[]>),
config: (barId: number) => fetch(`/api/config?bar=${barId}`).then(json<BarConfig>),
createTransaction: (body: CreateTransactionRequest) =>
fetch('/api/transactions', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
}).then(json<CreateTransactionResponse>),
};
export function formatCents(cents: number): string {
const sign = cents < 0 ? '-' : '';
const abs = Math.abs(cents);
return `${sign}${(abs / 100).toFixed(2)} €`;
}
export type Theme = 'dark' | 'light';
const THEME_KEY = 'wutz.theme';
export function getTheme(): Theme {
return localStorage.getItem(THEME_KEY) === 'light' ? 'light' : 'dark';
}
export function applyTheme(t: Theme = getTheme()): void {
document.documentElement.setAttribute('data-theme', t);
}
export function setTheme(t: Theme): void {
localStorage.setItem(THEME_KEY, t);
applyTheme(t);
}
export function uuid(): string {
if (typeof crypto !== 'undefined' && 'randomUUID' in crypto) {
return (crypto as any).randomUUID();
}
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
const r = (Math.random() * 16) | 0;
const v = c === 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}