Closes #40. New /stats route (client/stats.html + src/stats/), served by the same catch-all pattern as /admin. Reuses the admin login (STATS_PUBLIC env var on the server side decides whether it needs one at all). Three uPlot charts (daily revenue, daily transaction count, top-5-drink sold-qty trend) plus the same three tables Admin.tsx used to render inline — those move here wholesale, Admin.tsx now just links to /stats instead of fetching /admin/api/stats itself. The 'Statistik zurücksetzen' reset button moves here too, gated on an actual admin session (checked separately from whether /api/stats itself succeeded, since STATS_PUBLIC can make that true for an anonymous viewer). Chart lib is uPlot (~45kb) per mara's steer not to hand-roll this. Both client and server build/typecheck clean; manually smoke-tested the auth gate (401 unauthed, 200 after login) and the /stats route against a fresh DB.
54 lines
2 KiB
TypeScript
54 lines
2 KiB
TypeScript
import { defineConfig } from 'vite';
|
|
import preact from '@preact/preset-vite';
|
|
import legacy from '@vitejs/plugin-legacy';
|
|
import { resolve } from 'node:path';
|
|
|
|
// The dev-server proxy target — same default (3000) as the server's own
|
|
// `process.env.PORT ?? 3000` in server/src/index.ts. Override with
|
|
// `WUTZ_SERVER_PORT` when running `dev:server` on a non-default port, e.g.:
|
|
// PORT=4000 pnpm dev:server
|
|
// WUTZ_SERVER_PORT=4000 pnpm dev:client
|
|
const serverTarget = `http://localhost:${process.env.WUTZ_SERVER_PORT ?? 3000}`;
|
|
|
|
export default defineConfig({
|
|
plugins: [
|
|
preact(),
|
|
legacy({
|
|
targets: ['ios >= 12', 'safari >= 12'],
|
|
modernPolyfills: true,
|
|
renderLegacyChunks: true,
|
|
}),
|
|
],
|
|
build: {
|
|
target: 'es2017',
|
|
rollupOptions: {
|
|
input: {
|
|
main: resolve(__dirname, 'index.html'),
|
|
admin: resolve(__dirname, 'admin.html'),
|
|
stats: resolve(__dirname, 'stats.html'),
|
|
},
|
|
},
|
|
},
|
|
server: {
|
|
port: 5173,
|
|
proxy: {
|
|
'/api': serverTarget,
|
|
'/healthz': serverTarget,
|
|
// NOT a bare '/admin' prefix: that would also swallow the /admin and
|
|
// /admin.html *page* requests themselves (and, since Vite's proxy
|
|
// matches by string prefix, they do — '/admin' matches '/admin.html'
|
|
// too), forwarding them to the backend instead of letting Vite serve
|
|
// its own dev-mode admin.html. In dev the backend only has a stale
|
|
// production build to fall back on (or nothing, if `client` was never
|
|
// built), so the page ends up loaded with hashed prod asset paths that
|
|
// don't exist in Vite's dev module graph — Vite's dev server then
|
|
// answers those with its SPA-fallback HTML instead of JS, which is
|
|
// exactly the "wrong MIME type" / NS_ERROR_CORRUPTED_CONTENT failure
|
|
// reported for the admin page. Only the backend-owned endpoints need
|
|
// to cross the proxy.
|
|
'/admin/api': serverTarget,
|
|
'/admin/login': serverTarget,
|
|
'/admin/logout': serverTarget,
|
|
},
|
|
},
|
|
});
|