2d5ec8fc6d
Dark theme matching GOA palette, standalone microsite (no nav). - Landing/login: GOA subhead + big "Suff" wordmark, large tap targets - me page: 2-col 4:3 drink grid, bordered total box, day-grouped history with zebra rows, emoji empty-state - Booking confirmation toast (amber, 5s, then 800ms CSS collapse) - Touch feedback via :active scale, SVG beer favicon - no_pin.html link-buttons styled
3.5 KiB
3.5 KiB
Suff – drink booking tool
Self-service drink tab for festival attendees. Lives at /suff/. Plain Django, no JS, no CSS yet.
Auth
User.pinfield (hashed CharField) stores 3-digit PIN, separate frompassword. Lets staff keep a strong password for/admin/and use the same username on/suff/with just a PIN.PinBackend(gaehsnitz/auth_backends.py) authenticates byusername+pinviauser.check_pin(). DefaultModelBackendstays first inAUTHENTICATION_BACKENDSso/admin/keeps requiring the strong password.- Staff PINs cannot be self-set on
/suff/. If a name matches an existing user with no PIN, the user lands onsuff/no_pin.htmlexplaining that an admin must set the PIN via the admin panel — otherwise anyone could claim a staff name and lock out the real owner. - Admin convenience: User change page shows PIN status ("gesetzt"/"nicht gesetzt") + "PIN setzen" link → custom admin view
<id>/pin/with a 3-digit form, callsuser.set_pin().
Name flow
- Username =
slugify(input)(e.g. "Flo Hä!" → "flo-ha"). Slug shown back so user can memorize it. - POST name → check existence:
- not found → set new PIN → create user → login
- found, has PIN → enter PIN → login
- found, no PIN →
no_pin.html(ask admin)
Booking
/suff/me/shows: greeting (slug), running paid total, full consumption history with timestamps, drink buttons.- Each drink =
+1POST form. Server createsConsumption(amount=1, day=current_weekday, for_free=False, created_at=auto). - No undo, no delete, no edit. No special bartender role.
- History sorted newest-first,
created_atshown asDo 18:42etc.
Time gating (Berlin tz)
- Phases:
before/booking/readonly/closed. - Booking allowed Thu 2026-06-11 00:00 → Sun 2026-06-14 23:59.
- Read-only until Sun 2026-06-21 23:59.
- After: every
/suff/URL returns 404. - Local dev:
settings.PRODUCTION=Falseforcesbookingphase always.
Files
gaehsnitz/auth_backends.py—PinBackendgaehsnitz/suff.py— views + phase logicgaehsnitz/suff_urls.py— routesgaehsnitz/admin.py—SetPinForm+set_pin_viewgaehsnitz/templates/suff/{base,name,pin,no_pin,me}.htmlgaehsnitz/templates/admin/gaehsnitz/user/set_pin.htmlgaehsnitz/static/suff/{style.css,favicon.svg}gaehsnitz/migrations/0003_consumption_created_at_user_pin.py- Edits:
gaehsnitzproject/settings.py,gaehsnitzproject/urls.py,gaehsnitz/models.py
Frontend
Mobile-first styled. Dark theme matching GOA palette (#161616 bg, #EE9933/#FFCC77 amber accents, #885522 brown borders). Standalone microsite — no nav to main GOA page.
- Landing/login: GOA subhead + big "Suff" wordmark,
nameandpinforms with stacked label/input, large tap targets mepage: 2-col drink button grid (4:3 aspect), stacked +1 / name / price; bordered total box; day-grouped history with zebra rows; emoji empty-state- Booking confirmation: amber toast, 5s display, then 800ms collapse animation (pure CSS, no JS)
:activescale(0.96) feedback on buttons + link-buttonsno_pin.htmllink-buttons styled (primary + secondary)- SVG favicon (🍺)
Further ideas
- Color-code drink buttons (per-drink accent border or bg — Bier amber, Wasser blue, etc.) for fast visual recognition in dim light
- Drink icons/emoji per type
- Style phase pages (
before/closedif non-404) - PWA manifest for add-to-homescreen
- Donation/free-drink flow if needed (currently admin-only via
for_free)