Files
SkinsPins/app/templates/admin/edit_course.html
T
Rolf 3e98f5ae54 Import gender tees + front/back split ratings; front/back/9 hole selection
Course import now fetches both male and female tees, each with their own
per-tee stroke indices extracted from the holes array. Front and back 9
slope/rating are stored per tee for more accurate WHS handicap calculation.

New game creation replaces the 9/18 radio with a course-aware selector:
18-hole courses offer 18 holes, Front 9, or Back 9; 9-hole courses auto-
select. start_hole is stored on the game and used throughout scoring,
handicap calculation, and scorecard rendering.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 22:37:20 +01:00

208 lines
11 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 %}Edit Course Skins &amp; Pins{% endblock %}
{% block content %}
<div class="page">
<div class="page-header">
<a href="/admin/courses" style="color:var(--text-muted); font-size:0.9rem;">← Courses</a>
<h1 style="margin-top:0.25rem;">{{ course.name }}</h1>
</div>
{% if request.query_params.get('success') %}
<div class="alert alert-success">{{ request.query_params.get('success') }}</div>
{% endif %}
{# ── Course info + hole pars ── #}
<form method="post" action="/admin/courses/{{ course.id }}/edit">
<div class="card">
<h2 style="font-size:0.95rem; color:var(--text-muted); margin-bottom:1rem;">Course info</h2>
<div class="form-group">
<label for="name">Course name</label>
{% if errors and errors.name %}<div class="alert alert-error">{{ errors.name }}</div>{% endif %}
<input type="text" id="name" name="name" value="{{ course.name }}" required>
</div>
<div class="form-group">
<label for="location">Location <span style="color:var(--text-muted); font-size:0.8rem;">(optional)</span></label>
<input type="text" id="location" name="location" value="{{ course.location or '' }}"
placeholder="e.g. Augusta, Georgia">
</div>
<div class="form-group">
<label>Holes</label>
<div style="display:flex; gap:0.75rem;">
<label class="radio-card">
<input type="radio" name="holes" value="9" {% if course.holes == 9 %}checked{% endif %}>
<span>9 holes</span>
</label>
<label class="radio-card">
<input type="radio" name="holes" value="18" {% if course.holes == 18 %}checked{% endif %}>
<span>18 holes</span>
</label>
</div>
</div>
</div>
<div class="card"
x-data="{ pars: { {% for h in holes %}'{{ h.hole_number }}': {{ h.par or 4 }}{% if not loop.last %}, {% endif %}{% endfor %} }, coursePar() { return Object.values(this.pars).reduce((a, b) => a + parseInt(b), 0); } }">
<h2 style="font-size:0.95rem; color:var(--text-muted); margin-bottom:0.75rem;">
Hole details <span style="font-weight:400;">— Course par: <strong x-text="coursePar()"></strong></span>
</h2>
<div class="hole-pars-grid">
{% for h in holes %}
<div class="hole-par-cell">
<div class="hole-par-label">{{ h.hole_number }}</div>
<select name="par_{{ h.hole_number }}" class="hole-par-select" x-model="pars['{{ h.hole_number }}']">
<option value="3" {% if h.par == 3 %}selected{% endif %}>3</option>
<option value="4" {% if h.par == 4 %}selected{% endif %}>4</option>
<option value="5" {% if h.par == 5 %}selected{% endif %}>5</option>
</select>
<select name="si_{{ h.hole_number }}" class="hole-par-select">
<option value=""></option>
{% for s in range(1, course.holes + 1) %}
<option value="{{ s }}" {% if h.stroke_index == s %}selected{% endif %}>{{ s }}</option>
{% endfor %}
</select>
</div>
{% endfor %}
</div>
</div>
<button type="submit" class="btn btn-primary" style="margin-bottom:1.5rem;">Save changes</button>
</form>
{# ── Tees ── #}
<div class="card">
<h2 style="font-size:0.95rem; color:var(--text-muted); margin-bottom:1rem;">Tees</h2>
{% if tees %}
<div style="margin-bottom:1.25rem;">
{% for t in tees %}
<div x-data="{ editing: false }" style="border-bottom:1px solid var(--border); padding:0.6rem 0;">
<div x-show="!editing" style="display:flex; align-items:center; gap:0.75rem; flex-wrap:wrap;">
<span style="font-weight:500; min-width:5rem;">{{ t.name }}</span>
{% if t.gender %}<span style="font-size:0.75rem; padding:0.1rem 0.4rem; border-radius:0.25rem; background:var(--surface2); color:var(--text-muted);">{{ t.gender }}</span>{% endif %}
<span style="color:var(--text-muted); font-size:0.85rem;">Slope {{ t.slope }}</span>
<span style="color:var(--text-muted); font-size:0.85rem;">Rating {{ t.rating }}</span>
{% if t.front_slope and t.front_rating %}<span style="color:var(--text-muted); font-size:0.8rem;">· F {{ t.front_slope }}/{{ t.front_rating }}</span>{% endif %}
{% if t.back_slope and t.back_rating %}<span style="color:var(--text-muted); font-size:0.8rem;">B {{ t.back_slope }}/{{ t.back_rating }}</span>{% endif %}
<span style="margin-left:auto; display:flex; gap:0.4rem;">
<button type="button" @click="editing = true" class="btn-table-action">Edit</button>
<form method="post" action="/admin/courses/{{ course.id }}/tees/{{ t.id }}/delete"
style="display:inline;"
onsubmit="return confirm('Delete {{ t.name }} tee?')">
<button type="submit" class="btn-table-action danger">Delete</button>
</form>
</span>
</div>
<form x-show="editing" method="post"
action="/admin/courses/{{ course.id }}/tees/{{ t.id }}/edit"
style="display:flex; gap:0.5rem; align-items:flex-end; flex-wrap:wrap; padding-top:0.4rem;">
<div class="form-group" style="margin:0; flex:1; min-width:7rem;">
<label style="font-size:0.8rem;">Name</label>
<input type="text" name="name" value="{{ t.name }}" required style="padding:0.4rem 0.6rem;">
</div>
<div class="form-group" style="margin:0; width:6.5rem;">
<label style="font-size:0.8rem;">Gender</label>
<select name="gender" style="padding:0.4rem 0.6rem; border-radius:0.4rem; border:1px solid var(--border); background:var(--surface); color:var(--text); font-size:0.9rem;">
<option value="male" {% if t.gender == 'male' or not t.gender %}selected{% endif %}>Male</option>
<option value="female" {% if t.gender == 'female' %}selected{% endif %}>Female</option>
</select>
</div>
<div class="form-group" style="margin:0; width:6rem;">
<label style="font-size:0.8rem;">Slope</label>
<input type="number" name="slope" value="{{ t.slope }}" min="55" max="155" required style="padding:0.4rem 0.6rem;">
</div>
<div class="form-group" style="margin:0; width:7rem;">
<label style="font-size:0.8rem;">Rating</label>
<input type="number" step="0.1" name="rating" value="{{ t.rating }}"
min="{{ '29' if course.holes == 9 else '60' }}" max="{{ '40' if course.holes == 9 else '80' }}"
required style="padding:0.4rem 0.6rem;">
</div>
{% if course.holes == 18 %}
<div class="form-group" style="margin:0; width:5.5rem;">
<label style="font-size:0.8rem;">Front slope</label>
<input type="number" name="front_slope" value="{{ t.front_slope or '' }}" min="55" max="155" style="padding:0.4rem 0.6rem;">
</div>
<div class="form-group" style="margin:0; width:6rem;">
<label style="font-size:0.8rem;">Front rating</label>
<input type="number" step="0.1" name="front_rating" value="{{ t.front_rating or '' }}" min="29" max="45" style="padding:0.4rem 0.6rem;">
</div>
<div class="form-group" style="margin:0; width:5.5rem;">
<label style="font-size:0.8rem;">Back slope</label>
<input type="number" name="back_slope" value="{{ t.back_slope or '' }}" min="55" max="155" style="padding:0.4rem 0.6rem;">
</div>
<div class="form-group" style="margin:0; width:6rem;">
<label style="font-size:0.8rem;">Back rating</label>
<input type="number" step="0.1" name="back_rating" value="{{ t.back_rating or '' }}" min="29" max="45" style="padding:0.4rem 0.6rem;">
</div>
{% endif %}
<div style="display:flex; gap:0.4rem; padding-bottom:0.1rem;">
<button type="submit" class="btn btn-primary" style="padding:0.4rem 0.75rem; font-size:0.85rem;">Save</button>
<button type="button" @click="editing = false"
style="padding:0.4rem 0.75rem; font-size:0.85rem; background:none; border:1px solid var(--border); border-radius:0.4rem; color:var(--text-muted); cursor:pointer;">Cancel</button>
</div>
</form>
</div>
{% endfor %}
</div>
{% else %}
<p style="color:var(--text-muted); font-size:0.9rem; margin-bottom:1rem;">No tees yet. Add at least one tee so players can start a game on this course.</p>
{% endif %}
{# Add tee form #}
<h3 style="font-size:0.85rem; color:var(--text-muted); margin-bottom:0.75rem; text-transform:uppercase; letter-spacing:0.05em;">Add tee</h3>
<form method="post" action="/admin/courses/{{ course.id }}/tees/new"
style="display:flex; gap:0.5rem; align-items:flex-end; flex-wrap:wrap;">
<div class="form-group" style="margin:0; flex:1; min-width:7rem;">
<label style="font-size:0.8rem;">Name</label>
<input type="text" name="name" placeholder="e.g. White" required style="padding:0.4rem 0.6rem;">
</div>
<div class="form-group" style="margin:0; width:6.5rem;">
<label style="font-size:0.8rem;">Gender</label>
<select name="gender" style="padding:0.4rem 0.6rem; border-radius:0.4rem; border:1px solid var(--border); background:var(--surface); color:var(--text); font-size:0.9rem;">
<option value="male">Male</option>
<option value="female">Female</option>
</select>
</div>
<div class="form-group" style="margin:0; width:6rem;">
<label style="font-size:0.8rem;">Slope</label>
<input type="number" name="slope" placeholder="113" min="55" max="155" required style="padding:0.4rem 0.6rem;">
</div>
<div class="form-group" style="margin:0; width:7rem;">
<label style="font-size:0.8rem;">Rating</label>
<input type="number" step="0.1" name="rating"
placeholder="{{ '35.0' if course.holes == 9 else '72.0' }}"
min="{{ '29' if course.holes == 9 else '60' }}" max="{{ '40' if course.holes == 9 else '80' }}"
required style="padding:0.4rem 0.6rem;">
</div>
{% if course.holes == 18 %}
<div class="form-group" style="margin:0; width:5.5rem;">
<label style="font-size:0.8rem;">Front slope</label>
<input type="number" name="front_slope" placeholder="—" min="55" max="155" style="padding:0.4rem 0.6rem;">
</div>
<div class="form-group" style="margin:0; width:6rem;">
<label style="font-size:0.8rem;">Front rating</label>
<input type="number" step="0.1" name="front_rating" placeholder="—" min="29" max="45" style="padding:0.4rem 0.6rem;">
</div>
<div class="form-group" style="margin:0; width:5.5rem;">
<label style="font-size:0.8rem;">Back slope</label>
<input type="number" name="back_slope" placeholder="—" min="55" max="155" style="padding:0.4rem 0.6rem;">
</div>
<div class="form-group" style="margin:0; width:6rem;">
<label style="font-size:0.8rem;">Back rating</label>
<input type="number" step="0.1" name="back_rating" placeholder="—" min="29" max="45" style="padding:0.4rem 0.6rem;">
</div>
{% endif %}
<div style="padding-bottom:0.1rem;">
<button type="submit" class="btn btn-primary" style="padding:0.4rem 0.75rem; font-size:0.85rem;">Add tee</button>
</div>
</form>
</div>
</div>
{% endblock %}