{% extends "base.html" %} {% block title %}{% block page_title %}Garment{% endblock %}{% endblock %} {# ──────────────────────────────────────────────────────────────────── garment_form_base.html Shared form skeleton for Add and Edit. Blocks for child templates to override: page_title — and h1 text breadcrumb — nav link above the h1 form_action — action= URL submit_label — text of the primary submit button form_actions_extra — cancel link etc. after submit images_section — existing image grid (edit only; empty on add) danger_zone — relinquish panel (edit only; empty on add) ──────────────────────────────────────────────────────────────────── #} {% block styles %} <style> /* ── Page layout ─────────────────────────────────────────────────── */ .edit-page { max-width: 820px; margin: 0 auto; padding: 2rem 1.5rem; } .edit-header { margin-bottom: 1.5rem; } .edit-title { font-family: var(--font-display); font-size: clamp(1.4rem, 4vw, 1.8rem); font-weight: 400; margin: 0.4rem 0 0; border: none; padding: 0; } .edit-breadcrumb { margin-bottom: 0.5rem; } .breadcrumb-link { min-height: 44px; display: inline-flex; align-items: center; } .breadcrumb-link:hover { text-decoration: underline; } /* scope input overrides to .edit-form rather than global */ .edit-form input[type="text"], .edit-form input[type="number"], .edit-form input[type="date"], .edit-form select, .edit-form textarea { ... } /* ── Errors ──────────────────────────────────────────────────────── */ .edit-errors { background: #fdecea; border-left: 3px solid var(--red); padding: 0.75rem 1rem; margin: 0 0 1.5rem; list-style: none; font-size: 0.9rem; color: #7a2020; } /* ── Sections ────────────────────────────────────────────────────── */ .edit-section { border-top: 1px solid rgba(42,77,58,0.15); padding: 1.5rem 0; } .edit-section-heading { font-family: var(--serif-body); font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); font-weight: 400; margin: 0 0 1rem; border: none; padding: 0; } /* ── Field grid ──────────────────────────────────────────────────── */ .field-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem 1.5rem; } @media (max-width: 580px) { .field-grid { grid-template-columns: 1fr; } } .field { display: flex; flex-direction: column; gap: 0.3rem; } .field--full { grid-column: 1 / -1; } .field--checkbox { justify-content: flex-end; padding-bottom: 0.1rem; } label { font-family: var(--serif-body); font-size: 0.75rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); } input[type="text"], input[type="number"], input[type="date"], select, textarea { font-family: var(--serif-body); font-size: 0.95rem; padding: 0.4rem 0.6rem; border: 1px solid rgba(42,77,58,0.25); border-radius: 2px; background: #fff; color: inherit; width: 100%; } input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent); outline-offset: 1px; } textarea { resize: vertical; } .field--checkbox label { display: flex; align-items: center; gap: 0.4rem; text-transform: none; font-size: 0.9rem; letter-spacing: 0; color: inherit; cursor: pointer; } .field--checkbox input[type="checkbox"] { width: auto; } /* ── Style panels ────────────────────────────────────────────────── */ .style-hint { font-style: italic; color: #aaa; font-size: 0.85rem; margin: 0 0 0.75rem; } /* ── Material rows ───────────────────────────────────────────────── */ .material-row { display: grid; grid-template-columns: 70px 1fr 2rem; gap: 0.5rem; align-items: center; margin-bottom: 0.5rem; } .material-row input[type="number"] { text-align: right; } .btn-remove-row { background: none; border: none; font-size: 1.2rem; color: #bbb; cursor: pointer; line-height: 1; padding: 0; } .btn-remove-row:hover { color: var(--red); } /* ── Images ──────────────────────────────────────────────────────── */ .image-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 1rem; margin-bottom: 1.5rem; } .image-card { display: flex; flex-direction: column; gap: 0.4rem; background: #f9f8f6; border: 1px solid rgba(42,77,58,0.12); border-radius: 2px; padding: 0.5rem; } .image-card img { width: 100%; aspect-ratio: 3/4; object-fit: cover; border-radius: 1px; } .image-flags { display: flex; flex-direction: column; gap: 0.15rem; } .image-flags label { text-transform: none; font-size: 0.78rem; letter-spacing: 0; color: inherit; display: flex; align-items: center; gap: 0.3rem; cursor: pointer; } .image-flags input[type="checkbox"] { width: auto; } .image-filename { font-size: 0.65rem; color: #aaa; font-family: monospace; margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* ── Upload block ────────────────────────────────────────────────── */ .upload-block { border: 1px dashed rgba(42,77,58,0.25); border-radius: 2px; padding: 1rem 1.25rem; } .upload-heading { font-size: 0.72rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); font-weight: 400; margin: 0 0 0.75rem; } .upload-inner { display: flex; align-items: flex-start; gap: 1.5rem; flex-wrap: wrap; } .upload-flags { display: flex; gap: 1rem; } .upload-flags label { text-transform: none; letter-spacing: 0; font-size: 0.85rem; color: inherit; display: flex; align-items: center; gap: 0.3rem; cursor: pointer; } .upload-flags input[type="checkbox"] { width: auto; } .upload-hint { font-size: 0.78rem; color: #aaa; margin: 0.5rem 0 0; font-style: italic; } /* ── Form actions ────────────────────────────────────────────────── */ .form-actions { display: flex; gap: 0.75rem; align-items: center; padding: 1.5rem 0 0.5rem; border-top: 1px solid rgba(42,77,58,0.15); } .btn { font-family: var(--serif-body); font-size: 0.82rem; letter-spacing: 0.08em; text-transform: uppercase; padding: 0.55rem 1.4rem; border-radius: 2px; border: 1px solid transparent; cursor: pointer; text-decoration: none; display: inline-block; } .btn--primary { background: var(--accent); color: #fff; border-color: var(--accent); } .btn--primary:hover { background: #1e3829; } .btn--ghost { background: none; color: var(--accent); border-color: rgba(42,77,58,0.3); } .btn--ghost:hover { background: rgba(42,77,58,0.06); } .btn--danger { background: none; color: var(--red); border-color: rgba(139,35,32,0.4); } .btn--danger:hover { background: #fdecea; } .btn--small { font-size: 0.7rem; padding: 0.3rem 0.75rem; width: 100%; } /* ── Danger zone ─────────────────────────────────────────────────── */ .danger-zone { margin-top: 2rem; border-top: 1px solid rgba(139,35,32,0.25); padding-top: 1.5rem; } .danger-inner { display: flex; align-items: center; gap: 2rem; flex-wrap: wrap; } .danger-inner p { font-size: 0.88rem; color: var(--muted); margin: 0; flex: 1; min-width: 200px; } /* ── Membership panel ────────────────────────────────────────────── */ .membership-section { border-top: 1px solid rgba(42,77,58,0.15); padding: 1.5rem 0; } .membership-panel { margin-bottom: 1rem; } .membership-panel summary { font-family: var(--serif-body); font-size: 0.75rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); cursor: pointer; padding: 0.3rem 0; list-style: none; display: flex; align-items: center; gap: 0.4rem; } .membership-panel summary::-webkit-details-marker { display: none; } .membership-panel summary::before { content: '▸'; font-size: 0.7rem; transition: transform 0.15s; } .membership-panel[open] summary::before { transform: rotate(90deg); } .membership-list { list-style: none; margin: 0.5rem 0 0.75rem; padding: 0; display: flex; flex-direction: column; gap: 0.35rem; } .membership-item { display: flex; align-items: center; gap: 0.6rem; font-size: 0.9rem; } .membership-type { font-size: 0.78rem; color: var(--muted); font-style: italic; } .membership-manage { margin-left: auto; font-size: 0.78rem; color: var(--accent); text-decoration: none; white-space: nowrap; } .membership-manage:hover { text-decoration: underline; } .membership-add { display: flex; flex-direction: column; gap: 0.3rem; margin-top: 0.5rem; } .membership-add-form { display: flex; align-items: center; gap: 0.6rem; font-size: 0.9rem; } .membership-option-name { flex: 1; } .membership-empty { font-size: 0.85rem; color: var(--muted); font-style: italic; margin: 0.5rem 0 0; } </style> {% endblock %} {% block content %} {# ── Classification → base_category map for JS style switching ── #} <script> var CLASS_MAP = {{ classes | map(attribute='name') | list | tojson }}; var CAT_MAP = {}; var GARMENT_BASE_CAT = {{ garment.base_category | tojson }}; {% for c in classes %} CAT_MAP[{{ c.name | tojson }}] = {{ c.base_category | tojson }}; {% endfor %} </script> <article class="edit-page"> {# ── Header ──────────────────────────────────────────────────── #} <header class="edit-header"> <nav class="edit-breadcrumb">{% block breadcrumb %}{% endblock %}</nav> <h1 class="edit-title">{% block form_title %}Garment{% endblock %}</h1> </header> {# ── Validation errors ───────────────────────────────────────── #} {% if errors %} <ul class="edit-errors" role="alert"> {% for e in errors %}<li>{{ e }}</li>{% endfor %} </ul> {% endif %} {# ═══════════════════════════════════════════════════════════════ MAIN FORM ════════════════════════════════════════════════════════════════ #} <form method="post" action="{% block form_action %}{% endblock %}" enctype="multipart/form-data" class="edit-form"> {# ── § Identity ──────────────────────────────────────────── #} <section class="edit-section" id="s-identity"> <h2 class="edit-section-heading">Identity</h2> <div class="field-grid"> <div class="field"> <label for="name">Name</label> <input type="text" id="name" name="name" value="{{ garment.name or '' }}"> </div> <div class="field field--required"> <label for="classification">Classification</label> <select id="classification" name="classification" required> <option value="">— select —</option> {% for cat, group in classes | groupby('base_category') %} <optgroup label="{{ cat }}"> {% for c in group %} <option value="{{ c.name }}" data-category="{{ c.base_category }}" {% if c.name == garment.classification %}selected{% endif %}> {{ c.name }} </option> {% endfor %} </optgroup> {% endfor %} </select> </div> <div class="field"> <label for="vendor">Vendor</label> <select id="vendor" name="vendor"> <option value="">— none —</option> {% for v in vendors %} <option value="{{ v }}" {% if v == garment.vendor %}selected{% endif %}> {{ v }} </option> {% endfor %} </select> </div> <div class="field"> <label for="label">Label</label> <select id="label" name="label"> <option value="">— none —</option> {% for l in labels %} <option value="{{ l.name }}" data-vendor="{{ l.vendor }}" {% if l.name == garment.label %}selected{% endif %}> {{ l.name }} </option> {% endfor %} </select> </div> <div class="field field--full"> <label for="description">Description</label> <textarea id="description" name="description" rows="3">{{ garment.description or '' }}</textarea> </div> </div> </section> {# ── § Appearance ─────────────────────────────────────────── #} <section class="edit-section" id="s-appearance"> <h2 class="edit-section-heading">Appearance</h2> <div class="field-grid"> <div class="field"> <label for="colour">Colour</label> <select id="colour" name="colour"> <option value="">— none / multicoloured —</option> {% for c in colours %} <option value="{{ c }}" {% if c == garment.colour %}selected{% endif %}> {{ c }} </option> {% endfor %} </select> </div> <div class="field"> <label for="colour_secondary">Secondary Colour</label> <select id="colour_secondary" name="colour_secondary"> <option value="">— none —</option> {% for c in colours %} <option value="{{ c }}" {% if c == garment.colour_secondary %}selected{% endif %}> {{ c }} </option> {% endfor %} </select> </div> <div class="field"> <label for="gender">Gender</label> <select id="gender" name="gender"> <option value="">— unset —</option> {% for g in genders %} <option value="{{ g }}" {% if g == garment.gender %}selected{% endif %}> {{ g }} </option> {% endfor %} </select> </div> <div class="field"> <label for="formal">Formality</label> <select id="formal" name="formal"> <option value="" {% if garment.formal is none %}selected{% endif %}>— unset —</option> <option value="true" {% if garment.formal == true %}selected{% endif %}>Formal</option> <option value="false" {% if garment.formal == false %}selected{% endif %}>Casual</option> </select> </div> <div class="field field--checkbox"> <label> <input type="checkbox" name="patterned" {% if garment.patterned %}checked{% endif %}> Patterned </label> </div> </div> </section> {# ── § Acquisition ────────────────────────────────────────── #} <section class="edit-section" id="s-acquisition"> <h2 class="edit-section-heading">Acquisition</h2> <div class="field-grid"> <div class="field field--required"> <label for="obtained">Obtained</label> <input type="date" id="obtained" name="obtained" required value="{{ garment.obtained.strftime('%Y-%m-%d') if garment.obtained else today }}"> </div> <div class="field"> <label for="cost">Cost (£)</label> <input type="text" id="cost" name="cost" placeholder="e.g. 34.00" value="{{ '%.2f'|format(garment.cost|float) if garment.cost is not none else '' }}"> </div> <div class="field"> <label for="relinquished">Relinquished</label> <input type="date" id="relinquished" name="relinquished" value="{{ garment.relinquished.strftime('%Y-%m-%d') if garment.relinquished else '' }}"> </div> <div class="field field--checkbox"> <label> <input type="checkbox" name="owned" {% if garment.owned != false %}checked{% endif %}> Currently owned </label> </div> </div> </section> {# ── § Care ───────────────────────────────────────────────── #} <section class="edit-section" id="s-care"> <h2 class="edit-section-heading">Care</h2> <div class="field-grid"> <div class="field"> <label for="washing_direction">Washing</label> <select id="washing_direction" name="washing_direction"> <option value="">— unset —</option> {% for d in washing_directions %} <option value="{{ d }}" {% if d == garment.washing_direction %}selected{% endif %}> {{ d }} </option> {% endfor %} </select> </div> <div class="field"> <label for="maximum_washing_temperature">Max Wash °C</label> <input type="number" id="maximum_washing_temperature" name="maximum_washing_temperature" min="0" max="200" value="{{ garment.maximum_washing_temperature or '' }}"> </div> <div class="field"> <label for="ironing_direction">Ironing</label> <select id="ironing_direction" name="ironing_direction"> <option value="">— unset —</option> {% for d in ironing_directions %} <option value="{{ d }}" {% if d == garment.ironing_direction %}selected{% endif %}> {{ d }} </option> {% endfor %} </select> </div> <div class="field"> <label for="maximum_ironing_temperature">Max Iron °C</label> <input type="number" id="maximum_ironing_temperature" name="maximum_ironing_temperature" min="0" max="400" value="{{ garment.maximum_ironing_temperature or '' }}"> </div> </div> </section> {# ── § Composition ────────────────────────────────────────── #} <section class="edit-section" id="s-composition"> <h2 class="edit-section-heading">Composition</h2> <div id="material-rows"> {% for m in material %} <div class="material-row"> <input type="number" name="material_percentage" min="1" max="100" value="{{ m.percentage }}" placeholder="%"> <select name="material_name"> <option value="">— select —</option> {% for mat in materials_list %} <option value="{{ mat }}" {% if mat == m.material %}selected{% endif %}> {{ mat }} </option> {% endfor %} </select> <button type="button" class="btn-remove-row" aria-label="Remove">×</button> </div> {% endfor %} </div> <button type="button" id="add-material" class="btn btn--ghost">+ Add material</button> <template id="material-row-template"> <div class="material-row"> <input type="number" name="material_percentage" min="1" max="100" placeholder="%"> <select name="material_name"> <option value="">— select —</option> {% for mat in materials_list %} <option value="{{ mat }}">{{ mat }}</option> {% endfor %} </select> <button type="button" class="btn-remove-row" aria-label="Remove">×</button> </div> </template> </section> {# ── § Style ──────────────────────────────────────────────── #} <section class="edit-section" id="s-style"> <h2 class="edit-section-heading">Style</h2> <p class="style-hint" id="style-hint"></p> {# Bra #} <div class="style-panel" data-for="Bra"> <div class="field-grid"> <div class="field field--checkbox"> <label><input type="checkbox" name="bra_wired" {% if garment.wired %}checked{% endif %}> Wired</label> </div> <div class="field field--checkbox"> <label><input type="checkbox" name="bra_padded" {% if garment.padded %}checked{% endif %}> Padded</label> </div> <div class="field field--checkbox"> <label><input type="checkbox" name="bra_push_up" {% if garment.push_up %}checked{% endif %}> Push-up</label> </div> <div class="field field--checkbox"> <label><input type="checkbox" name="bra_side_support" {% if garment.side_support %}checked{% endif %}> Side support</label> </div> <div class="field field--checkbox"> <label><input type="checkbox" name="bra_front_fastening" {% if garment.front_fastening %}checked{% endif %}> Front fastening</label> </div> <div class="field"> <label for="bra_neckline">Neckline</label> <select id="bra_neckline" name="bra_neckline"> <option value="">— none —</option> {% for n in necklines %} <option value="{{ n }}" {% if n == garment.bra_neckline %}selected{% endif %}>{{ n }}</option> {% endfor %} </select> </div> <div class="field field--checkbox"> <label><input type="checkbox" name="bra_double_strapped" {% if garment.double_strapped %}checked{% endif %}> Double-strapped</label> </div> <div class="field"> <label for="bra_cut">Cut</label> <select id="bra_cut" name="bra_cut"> <option value="">— unset —</option> {% for c in bra_cuts %} <option value="{{ c }}" {% if c == garment.bra_cut %}selected{% endif %}>{{ c }}</option> {% endfor %} </select> </div> </div> </div> {# Dress #} <div class="style-panel" data-for="Dress"> <div class="field-grid"> <div class="field"> <label for="dress_sleeve">Sleeve</label> <select id="dress_sleeve" name="dress_sleeve"> <option value="">— sleeveless —</option> {% for s in sleeve_types %} <option value="{{ s }}" {% if s == garment.dress_sleeve %}selected{% endif %}>{{ s }}</option> {% endfor %} </select> </div> <div class="field"> <label for="dress_neckline">Neckline</label> <select id="dress_neckline" name="dress_neckline"> <option value="">— none —</option> {% for n in necklines %} <option value="{{ n }}" {% if n == garment.dress_neckline %}selected{% endif %}>{{ n }}</option> {% endfor %} </select> </div> <div class="field"> <label for="dress_skirt_length">Skirt Length</label> <select id="dress_skirt_length" name="dress_skirt_length"> {% for l in skirt_lengths %} <option value="{{ l }}" {% if l == garment.dress_skirt_length %}selected{% endif %}>{{ l }}</option> {% endfor %} </select> </div> <div class="field"> <label for="dress_bodice">Bodice</label> <select id="dress_bodice" name="dress_bodice"> <option value="">— none —</option> {% for b in bodices %} <option value="{{ b }}" {% if b == garment.bodice %}selected{% endif %}>{{ b }}</option> {% endfor %} </select> </div> </div> </div> {# Shirt #} <div class="style-panel" data-for="Shirt"> <div class="field-grid"> <div class="field"> <label for="shirt_sleeve">Sleeve</label> <select id="shirt_sleeve" name="shirt_sleeve"> <option value="">— sleeveless —</option> {% for s in shirt_sleeves %} <option value="{{ s }}" {% if s == garment.shirt_sleeve %}selected{% endif %}>{{ s }}</option> {% endfor %} </select> </div> <div class="field"> <label for="shirt_collar">Collar</label> <select id="shirt_collar" name="shirt_collar"> <option value="">— none —</option> {% for c in shirt_collars %} <option value="{{ c }}" {% if c == garment.collar %}selected{% endif %}>{{ c }}</option> {% endfor %} </select> </div> <div class="field"> <label for="shirt_cuffs">Cuffs</label> <select id="shirt_cuffs" name="shirt_cuffs"> <option value="">— none —</option> {% for c in shirt_cuffs %} <option value="{{ c }}" {% if c == garment.cuffs %}selected{% endif %}>{{ c }}</option> {% endfor %} </select> </div> <div class="field field--checkbox"> <label><input type="checkbox" name="shirt_pintucks" {% if garment.pintucks %}checked{% endif %}> Pintucks</label> </div> </div> </div> {# Underwear #} <div class="style-panel" data-for="Underwear"> <div class="field-grid"> <div class="field field--checkbox"> <label><input type="checkbox" name="pant_high_waist" {% if garment.high_waist %}checked{% endif %}> High waist</label> </div> <div class="field field--checkbox"> <label><input type="checkbox" name="pant_high_leg" {% if garment.high_leg %}checked{% endif %}> High leg (French cut)</label> </div> <div class="field field--checkbox"> <label><input type="checkbox" name="pant_seamless" {% if garment.seamless %}checked{% endif %}> Seamless</label> </div> </div> </div> {# Skirt #} <div class="style-panel" data-for="Skirt"> <div class="field-grid"> <div class="field"> <label for="skirt_length">Length</label> <select id="skirt_length" name="skirt_length"> {% for l in skirt_lengths %} <option value="{{ l }}" {% if l == garment.skirt_length %}selected{% endif %}>{{ l }}</option> {% endfor %} </select> </div> </div> </div> {# Hosiery #} <div class="style-panel" data-for="Hosiery"> <div class="field-grid"> <div class="field"> <label for="hosiery_denier">Denier</label> <input type="number" id="hosiery_denier" name="hosiery_denier" min="1" value="{{ garment.denier or '' }}"> </div> <div class="field field--checkbox"> <label><input type="checkbox" name="hosiery_lace_top" {% if garment.lace_top %}checked{% endif %}> Lace top</label> </div> </div> </div> {# Jumper #} <div class="style-panel" data-for="Jumper"> <div class="field-grid"> <div class="field"> <label for="jumper_sleeve">Sleeve</label> <select id="jumper_sleeve" name="jumper_sleeve"> <option value="">— sleeveless —</option> {% for s in sleeve_types %} <option value="{{ s }}" {% if s == garment.jumper_sleeve %}selected{% endif %}>{{ s }}</option> {% endfor %} </select> </div> <div class="field"> <label for="jumper_neckline">Neckline</label> <select id="jumper_neckline" name="jumper_neckline"> <option value="">— none —</option> {% for n in necklines %} <option value="{{ n }}" {% if n == garment.jumper_neckline %}selected{% endif %}>{{ n }}</option> {% endfor %} </select> </div> <div class="field field--checkbox"> <label><input type="checkbox" name="jumper_cropped" {% if garment.jumper_cropped %}checked{% endif %}> Cropped</label> </div> </div> </div> {# Trouser #} <div class="style-panel" data-for="Trouser"> <div class="field-grid"> <div class="field"> <label for="trouser_cut">Cut</label> <select id="trouser_cut" name="trouser_cut"> <option value="">— unset —</option> {% for c in trouser_cuts %} <option value="{{ c }}" {% if c == garment.trouser_cut %}selected{% endif %}>{{ c }}</option> {% endfor %} </select> </div> <div class="field"> <label for="trouser_rise">Rise</label> <select id="trouser_rise" name="trouser_rise"> <option value="">— unset —</option> {% for r in trouser_rises %} <option value="{{ r }}" {% if r == garment.trouser_rise %}selected{% endif %}>{{ r }}</option> {% endfor %} </select> </div> </div> </div> {# Shoe #} <div class="style-panel" data-for="Shoe"> <div class="field-grid"> <div class="field"> <label for="shoe_heel_height">Heel height (mm)</label> <input type="number" id="shoe_heel_height" name="shoe_heel_height" min="0" max="200" value="{{ garment.shoe_heel_height or '' }}"> </div> <div class="field"> <label for="shoe_closure">Closure</label> <select id="shoe_closure" name="shoe_closure"> <option value="">— unset —</option> {% for c in shoe_closures %} <option value="{{ c }}" {% if c == garment.shoe_closure %}selected{% endif %}>{{ c }}</option> {% endfor %} </select> </div> </div> </div> {# Coat #} <div class="style-panel" data-for="Coat"> <div class="field-grid"> <div class="field"> <label for="coat_length">Length</label> <select id="coat_length" name="coat_length"> <option value="">— unset —</option> {% for l in coat_lengths %} <option value="{{ l }}" {% if l == garment.coat_length %}selected{% endif %}>{{ l }}</option> {% endfor %} </select> </div> <div class="field"> <label for="coat_lapel">Lapel</label> <select id="coat_lapel" name="coat_lapel"> <option value="">— unset —</option> {% for l in lapels %} <option value="{{ l }}" {% if l == garment.coat_lapel %}selected{% endif %}>{{ l }}</option> {% endfor %} </select> </div> </div> </div> </section>{# /s-style #} {# ── § Images ─────────────────────────────────────────────── #} <section class="edit-section" id="s-images"> <h2 class="edit-section-heading">Images</h2> {% block images_section %}{% endblock %} <div class="upload-block"> <h3 class="upload-heading">Add Images</h3> <div class="upload-inner"> <input type="file" name="image" id="image-upload" accept="image/*" multiple> <div class="upload-flags"> <label><input type="checkbox" name="img_new_front"> Front</label> <label><input type="checkbox" name="img_new_back"> Back</label> <label><input type="checkbox" name="img_new_model" checked> Model</label> </div> </div> <p class="upload-hint"> JPG, PNG, or WebP. On mobile, tap to use your camera or photo library. Upload happens on save. </p> </div> </section> {# ── Save ─────────────────────────────────────────────────── #} <div class="form-actions"> <button type="submit" class="btn btn--primary"> {% block submit_label %}Save{% endblock %} </button> {% block form_actions_extra %}{% endblock %} </div> </form> {# ── Danger Zone (edit only) ──────────────────────────────────── #} {% block danger_zone %}{% endblock %} {% block membership %}{% endblock %} </article> {# ── JS ────────────────────────────────────────────────────────── #} <script> (function () { // ── Style panel switching ──────────────────────────────────────── var panels = document.querySelectorAll('.style-panel'); var hint = document.getElementById('style-hint'); function showStylePanel(baseCat) { panels.forEach(function (p) { p.style.display = (p.dataset.for === baseCat) ? 'block' : 'none'; }); if (hint) { hint.textContent = baseCat ? '' : 'Select a classification above to see style options.'; } } var classSelect = document.getElementById('classification'); if (classSelect) { classSelect.addEventListener('change', function () { showStylePanel(CAT_MAP[this.value] || ''); }); showStylePanel(GARMENT_BASE_CAT || CAT_MAP[classSelect.value] || ''); } // ── Label filtering by vendor ──────────────────────────────────── var vendorSelect = document.getElementById('vendor'); var labelSelect = document.getElementById('label'); function filterLabels(vendor) { if (!labelSelect) return; Array.from(labelSelect.options).forEach(function (opt) { if (!opt.value) return; opt.hidden = vendor ? (opt.dataset.vendor !== vendor) : false; }); var sel = labelSelect.options[labelSelect.selectedIndex]; if (sel && sel.hidden) labelSelect.value = ''; } if (vendorSelect) { vendorSelect.addEventListener('change', function () { filterLabels(this.value); }); filterLabels(vendorSelect.value); } // ── Material rows: add / remove ────────────────────────────────── var addBtn = document.getElementById('add-material'); var rowsTpl = document.getElementById('material-row-template'); var rowsDiv = document.getElementById('material-rows'); if (addBtn && rowsTpl && rowsDiv) { addBtn.addEventListener('click', function () { rowsDiv.appendChild(rowsTpl.content.cloneNode(true)); }); } rowsDiv && rowsDiv.addEventListener('click', function (e) { if (e.target.classList.contains('btn-remove-row')) { e.target.closest('.material-row').remove(); } }); // ── Image remove (edit only) ───────────────────────────────────── document.querySelectorAll('.btn-img-remove').forEach(function (btn) { btn.addEventListener('click', function () { if (!confirm('Remove this image?')) return; var frm = document.createElement('form'); frm.method = 'post'; frm.action = btn.dataset.action; var inp = document.createElement('input'); inp.type = 'hidden'; inp.name = 'filename'; inp.value = btn.dataset.filename; frm.appendChild(inp); document.body.appendChild(frm); frm.submit(); }); }); })(); </script> {% endblock %}