feat(roasts): consolidate table columns and add tasting notes search

- Combine Roast/Roaster into single column with roaster as subtext on desktop
- Combine Origin/Producer into single column with producer as subtext on desktop
- Add Roaster and Producer as separate mobile-only fields for card layout
- Replace tasting notes pill badges with comma-separated list
- Rename "Notes" column to "Tasting Notes" with right-aligned mobile text
- Include tasting_notes in repository search filter columns
This commit is contained in:
Jon Seager 2026-02-03 12:40:18 +00:00
parent 39bad42f9c
commit 1fa88d054c
No known key found for this signature in database
2 changed files with 24 additions and 28 deletions

View file

@ -264,6 +264,7 @@ impl RoastRepository for SqlRoastRepository {
"ro.name", "ro.name",
"COALESCE(r.origin,'')", "COALESCE(r.origin,'')",
"COALESCE(r.producer,'')", "COALESCE(r.producer,'')",
"COALESCE(r.tasting_notes,'')",
], ],
) )
}); });

View file

@ -16,12 +16,10 @@
<table class="responsive-table min-w-full divide-y divide-amber-200 text-left text-sm text-stone-700"> <table class="responsive-table min-w-full divide-y divide-amber-200 text-left text-sm text-stone-700">
<thead class="bg-amber-200/60 text-xs font-semibold tracking-wide text-amber-900"> <thead class="bg-amber-200/60 text-xs font-semibold tracking-wide text-amber-900">
<tr> <tr>
{% call table::sortable_header("Added", "created-at", navigator, "#roast-list") %} {% {% call table::sortable_header("Added", "created-at", navigator, "#roast-list") %}
call table::sortable_header("Roast", "name", navigator, "#roast-list") %} {% call {% call table::sortable_header("Roast", "name", navigator, "#roast-list") %}
table::sortable_header("Roaster", "roaster", navigator, "#roast-list") %} {% call {% call table::sortable_header("Origin", "origin", navigator, "#roast-list") %}
table::sortable_header("Origin", "origin", navigator, "#roast-list") %} {% call <th scope="col" class="px-4 py-3">Tasting Notes</th>
table::sortable_header("Producer", "producer", navigator, "#roast-list") %}
<th scope="col" class="px-4 py-3">Notes</th>
{% if is_authenticated %} {% if is_authenticated %}
<th scope="col" class="px-4 py-3 text-right">Actions</th> <th scope="col" class="px-4 py-3 text-right">Actions</th>
{% endif %} {% endif %}
@ -42,31 +40,28 @@
{{ roast.created_at }} {{ roast.created_at }}
</td> </td>
<td data-label="Roast" class="px-4 py-3"> <td data-label="Roast" class="px-4 py-3">
<div class="flex flex-col">
<a <a
href="{{ roast.detail_path }}" href="{{ roast.detail_path }}"
class="font-semibold text-amber-800 hover:text-amber-600" class="font-semibold text-amber-800 hover:text-amber-600"
>{{ roast.name }}</a >{{ roast.name }}</a
> >
</div> <div class="hidden md:block text-xs text-stone-500">{{ roast.roaster_label }}</div>
</td> </td>
<td data-label="Roaster" class="px-4 py-3 whitespace-nowrap">{{ roast.roaster_label }}</td> <td data-label="Roaster" class="px-4 py-3 whitespace-nowrap md:hidden">{{ roast.roaster_label }}</td>
<td data-label="Origin" class="px-4 py-3 whitespace-nowrap">{{ roast.origin }}</td> <td data-label="Origin" class="px-4 py-3 whitespace-nowrap">
<td data-label="Producer" class="px-4 py-3 whitespace-nowrap">{{ roast.producer }}</td> {{ roast.origin }}
<td data-label="Notes" class="px-4 py-3"> {% if !roast.producer.is_empty() %}
<div class="hidden md:block text-xs text-stone-500">{{ roast.producer }}</div>
{% endif %}
</td>
{% if !roast.producer.is_empty() %}
<td data-label="Producer" class="px-4 py-3 whitespace-nowrap md:hidden">{{ roast.producer }}</td>
{% endif %}
<td data-label="Tasting Notes" class="px-4 py-3 text-stone-600 text-right md:text-left">
{% if roast.tasting_notes.is_empty() %} {% if roast.tasting_notes.is_empty() %}
<span class="text-xs text-stone-500">No tasting notes yet.</span> <span class="text-stone-500">No tasting notes yet.</span>
{% else %} {% else %}
<ul class="flex flex-wrap gap-2"> {{ roast.tasting_notes.join(", ") }}
{% for note in roast.tasting_notes %}
<li>
<span
class="inline-flex items-center rounded-full border border-amber-500/60 bg-amber-500/10 px-3 py-1 text-xs font-semibold text-amber-700"
>{{ note }}</span
>
</li>
{% endfor %}
</ul>
{% endif %} {% endif %}
</td> </td>
{% if is_authenticated %} {% if is_authenticated %}