feat(v2): implement scoped player search and detail flows
This commit is contained in:
@ -22,8 +22,6 @@
|
||||
<h2 class="text-base">Summary</h2>
|
||||
<dl class="mt-2 space-y-1 text-sm">
|
||||
<div><dt class="inline font-semibold">Nationality:</dt> <dd class="inline">{{ player.nationality.name|default:"-" }}</dd></div>
|
||||
<div><dt class="inline font-semibold">Origin competition:</dt> <dd class="inline">{{ player.origin_competition.name|default:"-" }}</dd></div>
|
||||
<div><dt class="inline font-semibold">Origin team:</dt> <dd class="inline">{{ player.origin_team.name|default:"-" }}</dd></div>
|
||||
<div><dt class="inline font-semibold">Birth date:</dt> <dd class="inline">{{ player.birth_date|date:"Y-m-d"|default:"-" }}</dd></div>
|
||||
<div><dt class="inline font-semibold">Age:</dt> <dd class="inline">{{ age|default:"-" }}</dd></div>
|
||||
<div><dt class="inline font-semibold">Height:</dt> <dd class="inline">{{ player.height_cm|default:"-" }} cm</dd></div>
|
||||
@ -47,14 +45,11 @@
|
||||
</div>
|
||||
|
||||
<div class="rounded-lg border border-slate-200 p-4">
|
||||
<h2 class="text-base">Aliases</h2>
|
||||
<ul class="mt-2 list-inside list-disc text-sm text-slate-700">
|
||||
{% for alias in player.aliases.all %}
|
||||
<li>{{ alias.alias }}{% if alias.source %} ({{ alias.source }}){% endif %}</li>
|
||||
{% empty %}
|
||||
<li>No aliases recorded.</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<h2 class="text-base">Snapshot Coverage</h2>
|
||||
<dl class="mt-2 space-y-1 text-sm">
|
||||
<div><dt class="inline font-semibold">Seasons imported:</dt> <dd class="inline">{{ season_rows|length }}</dd></div>
|
||||
<div><dt class="inline font-semibold">Latest season:</dt> <dd class="inline">{% if season_rows %}{{ season_rows.0.season.label|default:"-" }}{% else %}-{% endif %}</dd></div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@ -77,33 +72,6 @@
|
||||
{% endif %}
|
||||
</section>
|
||||
|
||||
<section class="panel mt-4">
|
||||
<h2>Career History</h2>
|
||||
{% if career_entries %}
|
||||
<div class="table-wrap mt-3">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr><th>Season</th><th>Team</th><th>Competition</th><th>Role</th><th>From</th><th>To</th></tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-slate-100 bg-white">
|
||||
{% for entry in career_entries %}
|
||||
<tr>
|
||||
<td>{{ entry.season.label|default:"-" }}</td>
|
||||
<td>{{ entry.team.name|default:"-" }}</td>
|
||||
<td>{{ entry.competition.name|default:"-" }}</td>
|
||||
<td>{{ entry.role_snapshot.name|default:"-" }}</td>
|
||||
<td>{{ entry.start_date|date:"Y-m-d"|default:"-" }}</td>
|
||||
<td>{{ entry.end_date|date:"Y-m-d"|default:"-" }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="empty-state mt-3">No career entries available.</div>
|
||||
{% endif %}
|
||||
</section>
|
||||
|
||||
<section class="panel mt-4">
|
||||
<h2>Season-by-Season Stats</h2>
|
||||
{% if season_rows %}
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
{% block content %}
|
||||
<section class="panel">
|
||||
<h1>Player Search</h1>
|
||||
<p class="mt-1 text-sm text-slate-600">Filter players by profile, origin, context, and production metrics.</p>
|
||||
<p class="mt-1 text-sm text-slate-600">Filter players by profile, team-season context, and production metrics.</p>
|
||||
{% if search_has_errors %}
|
||||
<div class="mt-4 rounded-md border border-rose-200 bg-rose-50 p-3 text-sm text-rose-800">
|
||||
<p class="font-medium">Please correct the highlighted filters.</p>
|
||||
@ -56,8 +56,6 @@
|
||||
<div><label for="id_competition">Competition</label>{{ search_form.competition }}</div>
|
||||
<div><label for="id_team">Team</label>{{ search_form.team }}</div>
|
||||
<div><label for="id_season">Season</label>{{ search_form.season }}</div>
|
||||
<div><label for="id_origin_competition">Origin competition</label>{{ search_form.origin_competition }}</div>
|
||||
<div><label for="id_origin_team">Origin team</label>{{ search_form.origin_team }}</div>
|
||||
</div>
|
||||
|
||||
<details class="rounded-lg border border-slate-200 bg-slate-50 p-3">
|
||||
@ -97,8 +95,6 @@
|
||||
<div><label for="id_three_pct_max">3P% max</label>{{ search_form.three_pct_max }}</div>
|
||||
<div><label for="id_ft_pct_min">FT% min</label>{{ search_form.ft_pct_min }}</div>
|
||||
<div><label for="id_ft_pct_max">FT% max</label>{{ search_form.ft_pct_max }}</div>
|
||||
<div><label for="id_efficiency_metric_min">Impact min</label>{{ search_form.efficiency_metric_min }}</div>
|
||||
<div><label for="id_efficiency_metric_max">Impact max</label>{{ search_form.efficiency_metric_max }}</div>
|
||||
</div>
|
||||
</details>
|
||||
</form>
|
||||
|
||||
@ -36,13 +36,18 @@
|
||||
<th>Player</th>
|
||||
<th>Nationality</th>
|
||||
<th>Pos / Role</th>
|
||||
<th>Origin</th>
|
||||
<th>Height / Weight</th>
|
||||
<th>Best Eligible Games</th>
|
||||
<th>Best Eligible MPG</th>
|
||||
<th>Best Eligible PPG</th>
|
||||
<th>Best Eligible RPG</th>
|
||||
<th>Best Eligible APG</th>
|
||||
<th>Best Eligible SPG</th>
|
||||
<th>Best Eligible BPG</th>
|
||||
<th>Best Eligible TOV</th>
|
||||
<th>Best Eligible FG%</th>
|
||||
<th>Best Eligible 3P%</th>
|
||||
<th>Best Eligible FT%</th>
|
||||
{% if request.user.is_authenticated %}<th>Watchlist</th>{% endif %}
|
||||
</tr>
|
||||
</thead>
|
||||
@ -52,16 +57,18 @@
|
||||
<td><a class="font-medium" href="{% url 'players:detail' player.pk %}">{{ player.full_name }}</a></td>
|
||||
<td>{{ player.nationality.name|default:"-" }}</td>
|
||||
<td>{{ player.nominal_position.code|default:"-" }} / {{ player.inferred_role.name|default:"-" }}</td>
|
||||
<td>
|
||||
{{ player.origin_competition.name|default:"-" }}
|
||||
{% if player.origin_team %}<div class="text-xs text-slate-500">{{ player.origin_team.name }}</div>{% endif %}
|
||||
</td>
|
||||
<td>{{ player.height_cm|default:"-" }} / {{ player.weight_kg|default:"-" }}</td>
|
||||
<td>{{ player.games_played_value|floatformat:0 }}</td>
|
||||
<td>{{ player.mpg_value|floatformat:1 }}</td>
|
||||
<td>{{ player.ppg_value|floatformat:1 }}</td>
|
||||
<td>{{ player.rpg_value|floatformat:1 }}</td>
|
||||
<td>{{ player.apg_value|floatformat:1 }}</td>
|
||||
<td>{% if player.games_played_value is not None %}{{ player.games_played_value|floatformat:0 }}{% else %}-{% endif %}</td>
|
||||
<td>{% if player.mpg_value is not None %}{{ player.mpg_value|floatformat:1 }}{% else %}-{% endif %}</td>
|
||||
<td>{% if player.ppg_value is not None %}{{ player.ppg_value|floatformat:1 }}{% else %}-{% endif %}</td>
|
||||
<td>{% if player.rpg_value is not None %}{{ player.rpg_value|floatformat:1 }}{% else %}-{% endif %}</td>
|
||||
<td>{% if player.apg_value is not None %}{{ player.apg_value|floatformat:1 }}{% else %}-{% endif %}</td>
|
||||
<td>{% if player.spg_value is not None %}{{ player.spg_value|floatformat:1 }}{% else %}-{% endif %}</td>
|
||||
<td>{% if player.bpg_value is not None %}{{ player.bpg_value|floatformat:1 }}{% else %}-{% endif %}</td>
|
||||
<td>{% if player.tov_value is not None %}{{ player.tov_value|floatformat:1 }}{% else %}-{% endif %}</td>
|
||||
<td>{% if player.fg_pct_value is not None %}{{ player.fg_pct_value|floatformat:1 }}{% else %}-{% endif %}</td>
|
||||
<td>{% if player.three_pct_value is not None %}{{ player.three_pct_value|floatformat:1 }}{% else %}-{% endif %}</td>
|
||||
<td>{% if player.ft_pct_value is not None %}{{ player.ft_pct_value|floatformat:1 }}{% else %}-{% endif %}</td>
|
||||
{% if request.user.is_authenticated %}
|
||||
<td>
|
||||
{% if player.id in favorite_player_ids %}
|
||||
|
||||
Reference in New Issue
Block a user