Files
SkinsPins/app/templates/games/summary.html
T
Rolf 3a1da1482c Add full SkinsPins application
- FastAPI + SQLite + Alpine.js + HTMX PWA for Bingo Bango Bongo golf scoring
- Passwordless magic link auth with email (aiosmtplib) and admin invite system
- Real-time score entry via WebSocket with drag-and-drop player ordering
- Course management with per-hole par and stroke index
- Scorecard with golf score markers (birdie, eagle, bogey, etc.)
- Two-step new game form with tee selection per player
- Dashboard with stats, live games social stream, and recent game history
- Game summary view (read-only scorecard with leaderboard)
- User profile pages with win stats
- PWA install support with generated PNG icons
- Admin panel for users, courses, games, and invitations

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 10:16:46 +01:00

155 lines
5.7 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}{{ game.course_name or 'Game' }} Skins &amp; Pins{% endblock %}
{% block content %}
<div class="page" x-data="{ view: 'strokes' }">
<div class="page-header" style="display:flex; align-items:center; justify-content:space-between;">
<a href="javascript:history.back()" style="color:var(--text-muted); font-size:0.9rem;">← Back</a>
<div style="text-align:center;">
<div style="font-weight:600;">{{ game.course_name or 'Bingo Bango Bongo' }}</div>
<div style="font-size:0.8rem; color:var(--text-muted);">{{ game.holes_count }} holes · {{ game.created_at[:10] }}</div>
</div>
<div style="width:3rem;"></div>
</div>
{# Leaderboard #}
<div class="card" style="padding:0.75rem 1rem;">
{% for p in results %}
{% set t = totals.get(p.id, {}) %}
<div class="result-row {% if loop.first %}result-winner{% endif %}" style="padding:0.4rem 0;">
<span class="result-rank">{% if loop.first %}🏆{% else %}{{ loop.index }}{% endif %}</span>
<span class="result-avatar">
{% if p.avatar and p.avatar.startswith('/') %}
<img src="{{ p.avatar }}" style="width:1.4rem;height:1.4rem;border-radius:50%;object-fit:cover;vertical-align:middle;">
{% else %}
{{ p.avatar or '👤' }}
{% endif %}
</span>
<a href="/users/{{ p.id }}" style="flex:1; color:inherit; text-decoration:none;">{{ p.name }}</a>
<span class="result-pts">{{ t.total | round(1) }} pts</span>
<span style="font-size:0.75rem; color:var(--text-muted); margin-left:0.5rem;">
B{{ t.bingo | int }}/{{ t.bango | round(1) }}/{{ t.bongo | int }}
</span>
</div>
{% endfor %}
</div>
{# Scorecard toggle #}
<div class="scorecard-toggle" style="margin-top:1rem;">
<button @click="view = 'strokes'" :class="{ active: view === 'strokes' }">Strokes</button>
<button @click="view = 'points'" :class="{ active: view === 'points' }">Points</button>
</div>
{# Strokes scorecard #}
<table class="scorecard" x-show="view === 'strokes'">
<thead>
<tr>
<th>Hole</th>
{% if hole_pars %}<th style="color:var(--text-muted);">Par</th>{% endif %}
{% for p in players %}
<th>
{% if p.avatar and p.avatar.startswith('/') %}
<img src="{{ p.avatar }}" style="width:1.3rem;height:1.3rem;border-radius:50%;object-fit:cover;vertical-align:middle;">
{% else %}
{{ p.avatar or '👤' }}
{% endif %}<br>
<a href="/users/{{ p.id }}" style="font-size:0.7rem; color:inherit; text-decoration:none;">{{ p.name.split()[0] }}</a>
</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for h in holes %}
<tr>
<td class="hole-num">{{ h }}</td>
{% if hole_pars %}<td class="score-cell" style="color:var(--text-muted);">{{ hole_pars.get(h, '—') }}</td>{% endif %}
{% for p in players %}
{% set s = scores.get(h, {}).get(p.id, {}) %}
{% set strokes = s.strokes if s else 0 %}
{% set par = hole_pars.get(h, 0) %}
<td class="score-cell">
{% if strokes %}
{% if par %}
{% set diff = strokes - par %}
{% if strokes == 1 %}
<span class="score-hio">{{ strokes }}</span>
{% elif diff <= -2 %}
<span class="score-eagle">{{ strokes }}</span>
{% elif diff == -1 %}
<span class="score-birdie">{{ strokes }}</span>
{% elif diff == 1 %}
<span class="score-bogey">{{ strokes }}</span>
{% elif diff >= 2 %}
<span class="score-double-bogey">{{ strokes }}</span>
{% else %}
{{ strokes }}
{% endif %}
{% else %}
{{ strokes }}
{% endif %}
{% else %}
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr class="totals-row">
<td>Total</td>
{% if hole_pars %}<td style="color:var(--text-muted);">{{ hole_pars.values() | sum }}</td>{% endif %}
{% for p in players %}
{% set stroke_total = namespace(val=0) %}
{% for h in holes %}
{% set s = scores.get(h, {}).get(p.id, {}) %}
{% if s and s.strokes %}{% set stroke_total.val = stroke_total.val + s.strokes %}{% endif %}
{% endfor %}
<td>{{ stroke_total.val or '—' }}</td>
{% endfor %}
</tr>
</tfoot>
</table>
{# Points scorecard #}
<table class="scorecard" x-show="view === 'points'">
<thead>
<tr>
<th>Hole</th>
{% for p in players %}
<th>
{% if p.avatar and p.avatar.startswith('/') %}
<img src="{{ p.avatar }}" style="width:1.3rem;height:1.3rem;border-radius:50%;object-fit:cover;vertical-align:middle;">
{% else %}
{{ p.avatar or '👤' }}
{% endif %}<br>
<a href="/users/{{ p.id }}" style="font-size:0.7rem; color:inherit; text-decoration:none;">{{ p.name.split()[0] }}</a>
</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for h in holes %}
<tr>
<td class="hole-num">{{ h }}</td>
{% for p in players %}
{% set s = scores.get(h, {}).get(p.id, {}) %}
{% set pts = (s.bingo + s.bango + s.bongo) if s else 0 %}
<td class="score-cell">{{ pts | round(1) if pts else '—' }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr class="totals-row">
<td>Total</td>
{% for p in players %}
<td>{{ totals.get(p.id, {}).get('total', 0) | round(1) }}</td>
{% endfor %}
</tr>
</tfoot>
</table>
</div>
{% endblock %}