- 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
55 lines
1.6 KiB
TypeScript
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);
|
|
});
|
|
}
|