mtg_python_deckbuilder/code/web/templates/decks/view.html

195 lines
10 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 banner_subtitle %}Finished Decks{% endblock %}
{% block content %}
<h2>Finished Deck</h2>
{% if display_name %}
<div><strong>{{ display_name }}</strong></div>
{% endif %}
{% set hover_tags_source = deck_theme_tags if deck_theme_tags else (tags if tags else commander_combined_tags) %}
{% set hover_tags_joined = hover_tags_source|join(', ') %}
<div class="muted">Commander:
<strong class="commander-hover"
data-card-name="{{ commander }}"
data-original-name="{{ commander }}"
data-role="{{ commander_role_label }}"
{% if hover_tags_joined %}data-tags="{{ hover_tags_joined }}"{% endif %}
{% if commander_tag_slugs %}data-tags-slug="{{ commander_tag_slugs|join(' ') }}"{% endif %}
{% if commander_overlap_tags %}data-overlaps="{{ commander_overlap_tags|join(', ') }}"{% endif %}
{% if commander_reason_text %}data-reasons="{{ commander_reason_text|e }}"{% endif %}>{{ commander }}</strong>
{% if tags and tags|length %} • Themes: {{ tags|join(', ') }}{% endif %}
</div>
<div class="muted">This view mirrors the end-of-build summary. Use the buttons to download the CSV/TXT exports.</div>
<div class="two-col two-col-left-rail" style="margin-top:.75rem;">
<aside class="card-preview">
{% if commander %}
{# Strip synergy annotation for Scryfall search and image fuzzy param #}
{% set commander_base = (commander.split(' - Synergy (')[0] if ' - Synergy (' in commander else commander) %}
<div class="commander-card"
tabindex="0"
style="display:inline-block; cursor:pointer;"
data-card-name="{{ commander_base }}"
data-original-name="{{ commander }}"
data-role="{{ commander_role_label }}"
{% if hover_tags_joined %}data-tags="{{ hover_tags_joined }}"{% endif %}
{% if commander_tag_slugs %}data-tags-slug="{{ commander_tag_slugs|join(' ') }}"{% endif %}
{% if commander_overlap_tags %}data-overlaps="{{ commander_overlap_tags|join(', ') }}"{% endif %}
{% if commander_reason_text %}data-reasons="{{ commander_reason_text|e }}"{% endif %}>
<img src="{{ commander_base|card_image('normal') }}"
alt="{{ commander }} card image"
data-card-name="{{ commander_base }}"
data-original-name="{{ commander }}"
data-role="{{ commander_role_label }}"
{% if hover_tags_joined %}data-tags="{{ hover_tags_joined }}"{% endif %}
{% if commander_tag_slugs %}data-tags-slug="{{ commander_tag_slugs|join(' ') }}"{% endif %}
{% if commander_overlap_tags %}data-overlaps="{{ commander_overlap_tags|join(', ') }}"{% endif %}
{% if commander_reason_text %}data-reasons="{{ commander_reason_text|e }}"{% endif %}
width="320" />
</div>
<div class="muted" style="margin-top:.25rem;">Commander: <span data-card-name="{{ commander }}"
data-original-name="{{ commander }}"
data-role="{{ commander_role_label }}"
{% if hover_tags_joined %}data-tags="{{ hover_tags_joined }}"{% endif %}
{% if commander_tag_slugs %}data-tags-slug="{{ commander_tag_slugs|join(' ') }}"{% endif %}
{% if commander_overlap_tags %}data-overlaps="{{ commander_overlap_tags|join(', ') }}"{% endif %}
{% if commander_reason_text %}data-reasons="{{ commander_reason_text|e }}"{% endif %}>{{ commander }}</span></div>
{% endif %}
<div style="margin-top:.75rem; display:flex; gap:.35rem; flex-wrap:wrap;">
{% if csv_path %}
<form action="/decks/download-csv" method="get" target="_blank" style="display:inline; margin:0;">
<input type="hidden" name="name" value="{{ name }}" />
<button type="submit">Download CSV</button>
</form>
{% endif %}
{% if txt_path %}
<form action="/files" method="get" target="_blank" style="display:inline; margin:0;">
<input type="hidden" name="path" value="{{ txt_path }}" />
<button type="submit">Download TXT</button>
</form>
{% endif %}
<a href="/decks/compare?A={{ name|urlencode }}" class="btn" role="button" title="Compare this deck with another">Compare…</a>
{% if budget_report %}
<a href="/decks/pickups?name={{ name|urlencode }}" class="btn" role="button" title="View cards to acquire for this budget build">Pickups List</a>
{% endif %}
<form method="get" action="/decks" style="display:inline; margin:0;">
<button type="submit">Back to Finished Decks</button>
</form>
</div>
{% if budget_report %}
{% set bstatus = budget_report.budget_status %}
<div class="budget-badge budget-badge--{{ bstatus }}" style="margin-top:.6rem;">
{% if bstatus == 'under' %}
Under Budget: ${{ "%.2f"|format(budget_report.total_price) }} / ${{ "%.2f"|format(budget_config.total) }}
{% elif bstatus == 'soft_exceeded' %}
Over Budget (soft): ${{ "%.2f"|format(budget_report.total_price) }} / ${{ "%.2f"|format(budget_config.total) }}
(+${{ "%.2f"|format(budget_report.overage) }})
{% else %}
Hard Cap Exceeded: ${{ "%.2f"|format(budget_report.total_price) }} / ${{ "%.2f"|format(budget_config.total) }}
(+${{ "%.2f"|format(budget_report.overage) }})
{% endif %}
</div>
{% if budget_report.over_budget_cards %}
<div class="panel panel-info-warning" style="margin-top:.5rem;">
<strong>Cards over budget:</strong>
<ul class="muted" style="margin:.25rem 0 0 1rem; padding:0; font-size:.85em;">
{% for c in budget_report.over_budget_cards %}
<li>{{ c.card }} — ${{ "%.2f"|format(c.price) }}{% if c.ceiling_exceeded %} (above ${{ "%.2f"|format(budget_config.card_ceiling) }} ceiling){% endif %}</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% endif %}
</aside>
<div class="grow">
{% if summary %}
{% if owned_set %}
{% set ns = namespace(owned=0, total=0) %}
{% set tb = summary.type_breakdown %}
{% if tb and tb.cards %}
{% for t, clist in tb.cards.items() %}
{% for c in clist %}
{% set cnt = c.count if c.count else 1 %}
{% set ns.total = ns.total + cnt %}
{% if c.name and (c.name|lower in owned_set) %}
{% set ns.owned = ns.owned + cnt %}
{% endif %}
{% endfor %}
{% endfor %}
{% endif %}
{% set not_owned = (ns.total - ns.owned) %}
{% set pct = ( (ns.owned * 100.0 / (ns.total or 1)) | round(1) ) %}
<div class="panel" style="margin-bottom:.75rem;">
<div style="display:flex; gap:1rem; align-items:center; flex-wrap:wrap;">
<div><strong>Ownership</strong></div>
<div class="muted">Owned: {{ ns.owned }} • Not owned: {{ not_owned }} • Total: {{ ns.total }} ({{ pct }}%)</div>
</div>
</div>
{% endif %}
{{ render_cached('partials/deck_summary.html', name, request=request, summary=summary, game_changers=game_changers, owned_set=owned_set, combos=combos, synergies=synergies, versions=versions) | safe }}
{# M8: Price charts accordion — placed in main area, only available on the saved deck view #}
{% if (price_category_chart and price_category_chart.total > 0) or price_histogram_chart %}
<section class="summary-section-lg">
<details class="analytics-accordion" id="price-charts-accordion">
<summary class="combo-summary">
<span>Price Breakdown</span>
<span class="muted text-xs font-normal ml-2">spend by category &amp; distribution</span>
</summary>
<div class="analytics-content mt-3">
{% if price_category_chart and price_category_chart.total > 0 %}
<div class="price-cat-section">
<div class="price-cat-heading">Spend by Category — ${{ '%.2f'|format(price_category_chart.total) }} total</div>
<div class="price-cat-bar" title="Total: ${{ '%.2f'|format(price_category_chart.total) }}">
{% for cat in price_category_chart.order %}
{% set cat_total = price_category_chart.totals.get(cat, 0) %}
{% if cat_total > 0 %}
{% set pct = (cat_total * 100 / price_category_chart.total) | round(1) %}
<div class="price-cat-seg"
style="width:{{ pct }}%; background:{{ price_category_chart.colors.get(cat, '#f59e0b') }};"
title="{{ cat }}: ${{ '%.2f'|format(cat_total) }} ({{ pct }}%)"></div>
{% endif %}
{% endfor %}
</div>
<div class="price-cat-legend">
{% for cat in price_category_chart.order %}
{% set cat_total = price_category_chart.totals.get(cat, 0) %}
{% if cat_total > 0 %}
<span class="price-cat-legend-item">
<span class="price-cat-swatch" style="background:{{ price_category_chart.colors.get(cat, '#f59e0b') }};"></span>
{{ cat }} ${{ '%.2f'|format(cat_total) }}
</span>
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
{% if price_histogram_chart %}
<div class="price-hist-section">
<div class="price-hist-heading">Price Distribution</div>
<div class="price-hist-bars">
{% for bin in price_histogram_chart %}
<div class="price-hist-column"
data-type="hist"
data-range="${{ '%.2f'|format(bin.range_min) }}${{ '%.2f'|format(bin.range_max) }}"
data-val="{{ bin.count }}"
data-cards="{% for c in bin.cards %}{{ c.name }}|{{ '%.2f'|format(c.price) }}{% if not loop.last %} • {% endif %}{% endfor %}">
<div class="price-hist-bar" style="height:{{ bin.pct | default(0) }}%; background:{{ bin.color }};"></div>
</div>
{% endfor %}
</div>
<div class="price-hist-xlabels">
{% for bin in price_histogram_chart %}
<div class="price-hist-xlabel">{{ bin.x_label }}</div>
{% endfor %}
</div>
</div>
{% endif %}
</div>
</details>
</section>
{% endif %}
{% else %}
<div class="muted">No summary available.</div>
{% endif %}
</div>
</div>
{% endblock %}