Files
vergabe-teilnahme/vergabe_teilnahme/templates/feedback/partials/eintrag_zeile.html
tegwick 40e70e64f0 fix(feedback): inline edit + live status change without reload
- Replaced broken status_aendern (missing status_choices in response)
  with a single eintrag_bearbeiten view that always returns the full
  partial context
- eintrag_zeile.html is now a <tbody x-data="{ editing: false }"> with
  two rows: display row + collapsible edit form
- Click anywhere on a row to expand the edit form; @click.stop on the
  status cell prevents accidental toggles
- Status dropdown in the display row posts via HTMX and swaps the whole
  <tbody> — no page reload needed
- Edit form covers all fields: titel, beschreibung, kategorie,
  dringlichkeit, status, bewertung, entscheidung

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 23:45:10 +02:00

116 lines
5.2 KiB
HTML

<tbody id="eintrag-wrapper-{{ eintrag.pk }}" x-data="{ editing: false }">
{# display row #}
<tr class="border-b border-slate-100 hover:bg-slate-50 text-sm cursor-pointer select-none"
@click="editing = !editing">
<td class="py-2 pr-3 font-medium text-slate-800 max-w-xs">
<span class="flex items-start gap-1.5">
<span class="mt-0.5 text-slate-300 text-xs shrink-0" x-text="editing ? '▾' : '▸'"></span>
<span>
{{ eintrag.titel }}
{% if eintrag.ausschreibung %}
<span class="text-xs text-slate-400 block font-normal">{{ eintrag.ausschreibung.titel|truncatechars:40 }}</span>
{% endif %}
</span>
</span>
</td>
<td class="py-2 pr-3 text-slate-500 text-xs max-w-xs">{{ eintrag.beschreibung|truncatechars:120 }}</td>
<td class="py-2 pr-3">
<span class="inline-block rounded-full px-2 py-0.5 text-xs
{% if eintrag.kategorie == 'fehler' %}bg-red-100 text-red-700
{% elif eintrag.kategorie == 'verbesserung' %}bg-blue-100 text-blue-700
{% else %}bg-slate-100 text-slate-700{% endif %}">
{{ eintrag.get_kategorie_display }}
</span>
</td>
<td class="py-2 pr-3">
<span class="inline-block rounded-full px-2 py-0.5 text-xs
{% if eintrag.dringlichkeit == 'kritisch' %}bg-red-100 text-red-700
{% elif eintrag.dringlichkeit == 'hoch' %}bg-orange-100 text-orange-700
{% elif eintrag.dringlichkeit == 'mittel' %}bg-amber-100 text-amber-700
{% else %}bg-slate-100 text-slate-600{% endif %}">
{{ eintrag.get_dringlichkeit_display }}
</span>
</td>
<td class="py-2 pr-3" @click.stop>
<form hx-post="/feedback/backlog/{{ eintrag.pk }}/bearbeiten/"
hx-target="#eintrag-wrapper-{{ eintrag.pk }}"
hx-swap="outerHTML">
{% csrf_token %}
<select name="status" onchange="this.form.requestSubmit()"
class="text-xs border border-slate-200 rounded p-1 bg-white">
{% for val, label in status_choices %}
<option value="{{ val }}" {% if val == eintrag.status %}selected{% endif %}>{{ label }}</option>
{% endfor %}
</select>
</form>
</td>
<td class="py-2 text-xs text-slate-500 whitespace-nowrap">{{ eintrag.datum|date:"d.m.Y" }}</td>
</tr>
{# edit row #}
<tr x-show="editing" x-cloak class="bg-slate-50 border-b border-slate-200">
<td colspan="6" class="px-6 pt-3 pb-4">
<form hx-post="/feedback/backlog/{{ eintrag.pk }}/bearbeiten/"
hx-target="#eintrag-wrapper-{{ eintrag.pk }}"
hx-swap="outerHTML">
{% csrf_token %}
<div class="grid grid-cols-3 gap-3 mb-3">
<div class="col-span-3">
<label class="form-label">Titel</label>
<input type="text" name="titel" value="{{ eintrag.titel }}"
class="form-input w-full text-sm" required>
</div>
<div class="col-span-3">
<label class="form-label">Beschreibung</label>
<textarea name="beschreibung" rows="3"
class="form-input w-full text-sm">{{ eintrag.beschreibung }}</textarea>
</div>
<div>
<label class="form-label">Kategorie</label>
<select name="kategorie" class="form-input text-sm">
{% for val, label in kategorie_choices %}
<option value="{{ val }}" {% if val == eintrag.kategorie %}selected{% endif %}>{{ label }}</option>
{% endfor %}
</select>
</div>
<div>
<label class="form-label">Dringlichkeit</label>
<select name="dringlichkeit" class="form-input text-sm">
{% for val, label in dringlichkeit_choices %}
<option value="{{ val }}" {% if val == eintrag.dringlichkeit %}selected{% endif %}>{{ label }}</option>
{% endfor %}
</select>
</div>
<div>
<label class="form-label">Status</label>
<select name="status" class="form-input text-sm">
{% for val, label in status_choices %}
<option value="{{ val }}" {% if val == eintrag.status %}selected{% endif %}>{{ label }}</option>
{% endfor %}
</select>
</div>
<div class="col-span-3">
<label class="form-label">Bewertung / Notizen</label>
<textarea name="bewertung" rows="2"
class="form-input w-full text-sm"
placeholder="Interne Einschätzung...">{{ eintrag.bewertung }}</textarea>
</div>
<div class="col-span-3">
<label class="form-label">Entscheidung</label>
<textarea name="entscheidung" rows="2"
class="form-input w-full text-sm"
placeholder="Wie wird damit umgegangen?">{{ eintrag.entscheidung }}</textarea>
</div>
</div>
<div class="flex gap-2">
<button type="submit" class="btn-primary text-sm py-1.5 px-4">Speichern</button>
<button type="button" @click="editing = false"
class="btn-secondary text-sm py-1.5 px-4">Abbrechen</button>
</div>
</form>
</td>
</tr>
</tbody>