Google-SSO PWA for bistro employee clock-in/out, admin employee management, and stats with CSV export. Express + SQLite backend, React + Zustand frontend in the light-mono-tui design language. Multi-stage Dockerfile, compose.yaml for image-based deploys, nginx reverse-proxy template, and an OKF documentation bundle in docs/. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
97 lines
3.8 KiB
Markdown
97 lines
3.8 KiB
Markdown
# EatMe — Docházka
|
|
|
|
Evidence docházky pro bistro EatMe. Zaměstnanci se přihlašují Google účtem a
|
|
logují příchod / odchod / start a konec pauzy; admin (majitel) spravuje seznam
|
|
zaměstnanců (jen e-mail, žádná hesla) a vidí souhrnné i individuální statistiky
|
|
s grafem a exportem do CSV.
|
|
|
|
```
|
|
backend/ Express + TypeScript API, SQLite (better-sqlite3)
|
|
frontend/ React + TypeScript PWA (Vite), Google Sign-In, Zustand
|
|
docs/ OKF (Open Knowledge Format) — architektura, datový model, provoz
|
|
branding/ Logo a vygenerované favicony/PWA ikony z podkladu bistra
|
|
deploy/ Šablony configů pro hosty mimo tento repo (nginx server block)
|
|
Dockerfile Multi-stage build — jeden image pro API i frontend
|
|
compose.yaml Produkční nasazení hotového image (viz Produkce níž)
|
|
```
|
|
|
|
Vzhled je podle `~/doc/concepts/ui/light-mono-tui.md` — světlý monochromní
|
|
"TUI" styl (mono font, ostré hrany, žádné barvy, inverze pro aktivní stav).
|
|
|
|
## Požadavky
|
|
|
|
- Node.js 22+
|
|
- Google Cloud projekt s nakonfigurovaným OAuth Client ID (Web application)
|
|
— origins musí obsahovat `http://localhost:5174` pro vývoj a produkční
|
|
doménu. Client ID se nastavuje do `GOOGLE_CLIENT_ID` (backend) a
|
|
`VITE_GOOGLE_CLIENT_ID` (frontend) — musí být **stejné**.
|
|
|
|
## Vývoj
|
|
|
|
```bash
|
|
# backend
|
|
cd backend
|
|
cp .env.example .env # doplň GOOGLE_CLIENT_ID, ADMIN_EMAILS, JWT_SECRET
|
|
npm install
|
|
npm run dev # http://localhost:4000
|
|
|
|
# frontend (v druhém terminálu)
|
|
cd frontend
|
|
cp .env.example .env # VITE_GOOGLE_CLIENT_ID stejné jako backend
|
|
npm install
|
|
npm run dev # http://localhost:5174 (port je pinnutý — musí sedět s Google origin)
|
|
```
|
|
|
|
Frontend v dev módu proxuje `/api/*` na backend (viz `frontend/vite.config.ts`).
|
|
|
|
### Typecheck / build
|
|
|
|
```bash
|
|
cd backend && npm run typecheck && npm run build # -> dist/index.js (esbuild bundle)
|
|
cd frontend && npm run build # -> dist/ (Vite, PWA)
|
|
```
|
|
|
|
## Produkce (Docker)
|
|
|
|
Jeden multi-stage `Dockerfile` v rootu postaví frontend i backend a spustí je
|
|
jako jeden kontejner — backend servíruje API na `/api/*` a staticky sbalený
|
|
frontend na všem ostatním.
|
|
|
|
Image se buildí lokálně (pro platformu cílového serveru) a na server se
|
|
posílá hotový, ne zdrojáky:
|
|
|
|
```bash
|
|
# buildni pro platformu serveru (na Apple Silicon Macu proti x86_64 serveru
|
|
# je --platform linux/amd64 povinné, jinak image tam vůbec nenaběhne)
|
|
docker build --platform linux/amd64 \
|
|
--build-arg VITE_GOOGLE_CLIENT_ID=<client-id> \
|
|
-t eatme:latest .
|
|
|
|
# přenes hotový image přes ssh (žádný build na serveru)
|
|
docker save eatme:latest | gzip | ssh <host> "gunzip | docker load"
|
|
|
|
# pošli jen compose.yaml + .env (viz .env.example) a nastartuj
|
|
scp compose.yaml <host>:~/eatme/compose.yaml
|
|
ssh <host> "cd ~/eatme && docker compose up -d"
|
|
```
|
|
|
|
`VITE_GOOGLE_CLIENT_ID` musí jít jako **build arg** (Vite ho zapéká při
|
|
buildu, ne za běhu — v `.env` na serveru se proto řeší jen runtime proměnné).
|
|
Pojmenovaný volume `eatme_data` (viz `compose.yaml`) drží SQLite databázi
|
|
mimo kontejner, ať přežije redeploy.
|
|
|
|
Před kontejner patří TLS-terminující reverse proxy (mimo tento repo) —
|
|
šablona server blocku pro nginx je v `deploy/eatme.mipem.co`, proxuje na
|
|
`http://<deploy-host>:8092`.
|
|
|
|
## Datový model / provoz
|
|
|
|
Zaměstnanci jsou whitelist e-mailů spravovaný adminem (`ADMIN_EMAILS` v env —
|
|
samostatná role, není v tabulce zaměstnanců). Odebrání zaměstnance je pouze
|
|
soft-delete (`active = 0`) — historie docházky zůstává, opětovným přidáním
|
|
stejného e-mailu se účet reaktivuje. Statistiky se počítají po kalendářních
|
|
měsících (`?month=YYYY-MM`), s možností listovat měsíci v adminově detailu
|
|
zaměstnance (graf + export CSV).
|
|
|
|
Víc v `docs/` (OKF bundle).
|