brewlog/templates/pages/edit_roast.html
Jon Seager cb28a6f8bb
fix: wire edit forms for Datastar form submission and add CLI tests
Add {contentType: 'form'} to all edit template @put() calls so form
inputs are submitted by name rather than as Datastar signals. Replace
the quick notes text input on the brew edit page with toggle pill
buttons matching the add form. Add CLI tests for brew and cup update
commands.
2026-02-10 19:42:58 +00:00

164 lines
5.6 KiB
HTML

{% extends "base.html" %}
{% import "partials/icons.html" as icons %}
{% import "partials/image_section.html" as img %}
{% block title %}Brewlog · Edit Roast{% endblock %}
{% block content %}
<header class="flex flex-col gap-2">
<h1 class="text-3xl font-semibold">Edit Roast</h1>
<p class="max-w-2xl text-sm text-text-secondary">Update roast details.</p>
</header>
<section class="rounded-lg border bg-surface p-5">
<form
class="flex flex-col gap-4"
data-signals:_submitting="false"
data-signals:_submit-error="''"
data-signals:_name="'{{ name }}'"
data-signals:_origin="'{{ origin }}'"
data-signals:_region="'{{ region }}'"
data-signals:_producer="'{{ producer }}'"
data-signals:_process="'{{ process }}'"
data-signals:_tasting-notes="'{{ tasting_notes }}'"
data-on:submit="$_submitting = true; $_submitError = ''; @put('/api/v1/roasts/{{ id }}', {contentType: 'form'})"
data-on:datastar-fetch="if (!$_submitting) return;
if (evt.detail.type === 'finished') { $_submitting = false; sessionStorage.setItem('toast', 'Roast updated'); window.location.href = evt.detail.response.headers.get('location') || '/roasts/{{ id }}' }
else if (evt.detail.type === 'error') { $_submitting = false; $_submitError = 'Failed to save changes.' }"
>
<div class="flex flex-col gap-1 text-sm">
<span
class="text-xs font-semibold text-text-muted uppercase tracking-wide"
>Roaster*</span
>
<searchable-select
name="roaster_id"
placeholder="Type to search roasters&hellip;"
initial-value="{{ roaster_id }}"
>
{% for roaster in roaster_options %}
<button
type="button"
value="{{ roaster.id }}"
data-display="{{ roaster.name }}"
class="w-full px-3 py-2 text-left text-sm hover:bg-surface-alt transition"
>
<span class="font-medium text-text">{{ roaster.name }}</span>
</button>
{% endfor %}
</searchable-select>
</div>
<div class="grid gap-4 sm:grid-cols-2">
<label class="flex flex-col gap-1 text-sm">
<span
class="text-xs font-semibold text-text-muted uppercase tracking-wide"
>Roast Name*</span
>
<input
type="text"
name="name"
required
aria-required="true"
class="input-field"
placeholder="Ethiopia Yirgacheffe"
data-bind:_name
/>
</label>
<label class="flex flex-col gap-1 text-sm">
<span
class="text-xs font-semibold text-text-muted uppercase tracking-wide"
>Origin*</span
>
<input
type="text"
name="origin"
required
aria-required="true"
class="input-field"
placeholder="Ethiopia"
data-bind:_origin
/>
</label>
<label class="flex flex-col gap-1 text-sm">
<span
class="text-xs font-semibold text-text-muted uppercase tracking-wide"
>Region*</span
>
<input
type="text"
name="region"
required
aria-required="true"
class="input-field"
placeholder="Guji"
data-bind:_region
/>
</label>
<label class="flex flex-col gap-1 text-sm">
<span
class="text-xs font-semibold text-text-muted uppercase tracking-wide"
>Producer*</span
>
<input
type="text"
name="producer"
required
aria-required="true"
class="input-field"
placeholder="Chelbesa Cooperative"
data-bind:_producer
/>
</label>
<label class="flex flex-col gap-1 text-sm">
<span
class="text-xs font-semibold text-text-muted uppercase tracking-wide"
>Process*</span
>
<input
type="text"
name="process"
required
aria-required="true"
class="input-field"
placeholder="Washed"
data-bind:_process
/>
</label>
<label class="sm:col-span-2 flex flex-col gap-1 text-sm">
<span
class="text-xs font-semibold text-text-muted uppercase tracking-wide"
>Tasting Notes* (comma or newline separated)</span
>
<textarea
name="tasting_notes"
rows="2"
required
aria-required="true"
class="input-field"
placeholder="Blueberry, Jasmine"
data-bind:_tasting-notes
></textarea>
</label>
</div>
{{ img::deferred_upload("edit-roast-image", "Roast Image") }}
<p
data-show="$_submitError"
data-text="$_submitError"
style="display:none"
class="text-sm text-error"
role="alert"
></p>
<div class="flex items-center justify-end">
<button
type="submit"
class="inline-flex items-center justify-center gap-2 rounded-md bg-accent px-4 py-2 text-sm font-semibold text-accent-text transition hover:bg-accent-hover disabled:opacity-50"
data-attr:disabled="$_submitting"
>
<span data-show="$_submitting" style="display:none"
>{{ icons::spinner("h-4 w-4") }}</span
>
Save Changes
</button>
</div>
</form>
</section>
{% endblock %}