Files
gaehsnitz/suff.md
T
flo 2d5ec8fc6d Style suff frontend mobile-first
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
2026-05-14 12:41:45 +02:00

3.5 KiB
Raw Blame History

Suff drink booking tool

Self-service drink tab for festival attendees. Lives at /suff/. Plain Django, no JS, no CSS yet.

Auth

  • User.pin field (hashed CharField) stores 3-digit PIN, separate from password. 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 by username + pin via user.check_pin(). Default ModelBackend stays first in AUTHENTICATION_BACKENDS so /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 on suff/no_pin.html explaining 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, calls user.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 = +1 POST form. Server creates Consumption(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_at shown as Do 18:42 etc.

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=False forces booking phase always.

Files

  • gaehsnitz/auth_backends.pyPinBackend
  • gaehsnitz/suff.py — views + phase logic
  • gaehsnitz/suff_urls.py — routes
  • gaehsnitz/admin.pySetPinForm + set_pin_view
  • gaehsnitz/templates/suff/{base,name,pin,no_pin,me}.html
  • gaehsnitz/templates/admin/gaehsnitz/user/set_pin.html
  • gaehsnitz/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, name and pin forms with stacked label/input, large tap targets
  • me page: 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)
  • :active scale(0.96) feedback on buttons + link-buttons
  • no_pin.html link-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 / closed if non-404)
  • PWA manifest for add-to-homescreen
  • Donation/free-drink flow if needed (currently admin-only via for_free)