{% extends "admin/_base.html" %}
{% block content %}
<nav class="rio-crumbs"><a href="/admin">Home</a><span class="rio-crumb-sep">·</span><a href="/admin/dev/view-designer">View designer</a><span class="rio-crumb-sep">·</span><span class="rio-crumb-current">{{ display_name }}</span></nav>
<div class="rio-masthead-top">
<div>
<h1>Composition editor</h1>
<p class="rio-masthead-desc">
Define how {{ display_name }} renders — the editor only produces a <code>ViewSpec</code>.
<span class="rio-vd-flag">deterministic · no AI at runtime</span>
</p>
</div>
<div class="rio-masthead-cta">
<span class="rio-vd-chip">Primary developer</span>
<button type="submit" form="vdform" class="rio-btn rio-btn--primary rio-btn--md">Save ViewSpec</button>
</div>
</div>
{% if flash %}<div class="rio-alert rio-alert--{{ flash.kind }}" role="status">{{ flash.message }}</div>{% endif %}
{# ---- Live preview (server-rendered through the runtime render core) ---- #}
<section class="rio-vd-preview" aria-label="Live preview">
<header class="rio-vd-preview__head">
<span class="rio-vd-preview__title">Live preview <span class="rio-meta">· {{ preview.mode }} mode</span></span>
<span class="rio-vd-flag rio-vd-flag--quiet">deterministic · no AI</span>
</header>
<div class="rio-vd-filters">
<span class="rio-vd-filters__label">Filters</span>
{% for f in fields %}{% if f.filterable %}<span class="rio-vd-chip rio-vd-chip--filter">{{ f.label }}</span>{% endif %}{% endfor %}
</div>
<div class="rio-vd-canvas">
<div class="av-list av-list--{{ preview.mode }}">
{% for row in preview.rows %}
<div class="av-row">{% include "admin/view_layer/_row.html" %}</div>
{% else %}
<div class="rio-empty-state"><p class="rio-empty-state__lead">No preview rows.</p></div>
{% endfor %}
</div>
</div>
<p class="rio-vd-note">Reflects the last <strong>saved</strong> state — save to refresh the preview.</p>
</section>
<form id="vdform" method="post" action="/admin/dev/view-designer/{{ admin_name }}/save" data-rio-vd>
<input type="hidden" name="_csrf" value="{{ csrf_token }}">
{# ---- Modes ---- #}
<section class="rio-vd-modes" aria-label="Modes">
<label class="rio-vd-mode-default">
<span>Default mode</span>
<select name="default_mode" class="rio-input">
{% for opt in mode_options %}<option value="{{ opt.slug }}"{% if opt.slug == default_mode %} selected{% endif %}>{{ opt.label }}</option>{% endfor %}
</select>
</label>
<div class="rio-vd-allowed">
<span class="rio-vd-allowed__label">In the switcher</span>
{% for m in mode_choices %}
<label class="rio-vd-allowed__opt">
<input type="checkbox" name="mode_allowed__{{ m.slug }}"{% if m.allowed %} checked{% endif %}{% if m.is_default %} disabled{% endif %}>
<span>{{ m.label }}{% if m.is_default %} (default){% endif %}</span>
</label>
{% endfor %}
</div>
</section>
{# ---- Fields as rows ---- #}
<section class="rio-vd-fields" aria-label="Fields">
<header class="rio-vd-fields__head">
<h2 class="rio-vd-fields__title">Fields</h2>
<span class="rio-meta">Set a role · toggle filter · reorder</span>
</header>
<ul class="rio-vd-rows">
{% for field in fields %}
<li class="rio-vd-row" data-rio-vd-row>
<span class="rio-vd-grip" aria-hidden="true"></span>
<span class="rio-vd-dot rio-vd-dot--{{ field.role }}" data-rio-vd-dot></span>
<span class="rio-vd-name">
<code>{{ field.name }}</code>
<span class="rio-meta">{{ field.label }}</span>
{% if field.composed %}<span class="rio-vd-badge">Composed</span>{% endif %}
</span>
<span class="rio-vd-controls">
<select name="role__{{ field.name }}" class="rio-input rio-vd-role" data-rio-vd-role aria-label="Role for {{ field.name }}">
{% for opt in role_options %}<option value="{{ opt.slug }}"{% if opt.slug == field.role %} selected{% endif %}>{{ opt.label }}</option>{% endfor %}
</select>
<label class="rio-vd-toggle" title="Show a filter control for this field">
<input type="checkbox" name="filter__{{ field.name }}"{% if field.filterable %} checked{% endif %}>
<span class="rio-vd-toggle__face">Filter</span>
</label>
<input type="number" name="priority__{{ field.name }}" value="{{ field.priority }}" class="rio-input rio-input--mono rio-vd-prio" data-rio-vd-priority aria-label="Order for {{ field.name }}">
<span class="rio-vd-reorder">
<button type="button" class="rio-iconbtn rio-iconbtn--sm" data-rio-vd-up aria-label="Move up">↑</button>
<button type="button" class="rio-iconbtn rio-iconbtn--sm" data-rio-vd-down aria-label="Move down">↓</button>
</span>
</span>
</li>
{% endfor %}
</ul>
</section>
{# ---- Compositions (merge fields into one cell) ---- #}
<section class="rio-vd-comp" aria-label="Compositions">
<header class="rio-vd-fields__head">
<h2 class="rio-vd-fields__title">Merge fields into one cell</h2>
<span class="rio-meta">Optional — combine a primary with secondaries (e.g. name over email)</span>
</header>
{% for slot in comp_slots %}
<fieldset class="rio-vd-slot">
<legend>Composition {{ slot.index }}</legend>
<label class="rio-form-field">
<span>Primary field</span>
<select name="comp{{ slot.index }}_primary" class="rio-input">
<option value="">— none (disabled) —</option>
{% for f in slot.fields %}<option value="{{ f.name }}"{% if f.name == slot.primary %} selected{% endif %}>{{ f.label }}</option>{% endfor %}
</select>
</label>
<label class="rio-form-field">
<span>Label (optional)</span>
<input type="text" name="comp{{ slot.index }}_label" value="{{ slot.label }}" class="rio-input">
</label>
<label class="rio-form-field">
<span>Style</span>
<select name="comp{{ slot.index }}_style" class="rio-input">
{% for s in compose_styles %}<option value="{{ s.slug }}"{% if s.slug == slot.style %} selected{% endif %}>{{ s.label }}</option>{% endfor %}
</select>
</label>
<div class="rio-form-field">
<span>Secondary fields</span>
<div class="rio-vd-secs">
{% for f in slot.fields %}
<label class="rio-vd-sec"><input type="checkbox" name="comp{{ slot.index }}_sec__{{ f.name }}"{% if f.is_secondary %} checked{% endif %}> <span class="rio-meta">{{ f.name }}</span></label>
{% endfor %}
</div>
</div>
</fieldset>
{% endfor %}
</section>
<div class="rio-vd-save"><button type="submit" class="rio-btn rio-btn--primary rio-btn--md">Save ViewSpec</button></div>
</form>
{# ---- Generated ViewSpec (the single source of truth) ---- #}
<section class="rio-vd-json" aria-label="Generated ViewSpec">
<header class="rio-vd-json__bar">
<span class="rio-vd-json__dots" aria-hidden="true"><i></i><i></i><i></i></span>
<span class="rio-vd-json__name">{{ admin_name }}.viewspec.json</span>
<span class="rio-vd-json__hint">generated from the editor above</span>
</header>
<pre class="rio-vd-json__body"><code>{{ spec_json }}</code></pre>
<footer class="rio-vd-json__foot">{% if is_saved %}Saved{% else %}Draft — not yet saved{% endif %} · Ready.</footer>
</section>
{% endblock %}