change layout settings for lebensmittel

This commit is contained in:
2026-04-14 11:04:38 +02:00
parent 6f6269c66d
commit 216dde1414
5 changed files with 168 additions and 14 deletions
View File
+7 -1
View File
@@ -2906,12 +2906,16 @@ def sync_item_set_items(set_id: int, item_ids: list[int]) -> None:
def extract_item_set_form_data(existing: dict | None = None) -> dict: def extract_item_set_form_data(existing: dict | None = None) -> dict:
form_data = existing or {} form_data = existing or {}
item_ids = [int(value) for value in request.form.getlist("item_ids") if value.isdigit()]
remove_item_id = request.form.get("remove_item_id", "").strip()
if remove_item_id.isdigit():
item_ids = [item_id for item_id in item_ids if item_id != int(remove_item_id)]
form_data.update( form_data.update(
{ {
"name": request.form.get("name", "").strip(), "name": request.form.get("name", "").strip(),
"description": request.form.get("description", "").strip(), "description": request.form.get("description", "").strip(),
"visibility": normalize_visibility(request.form.get("visibility"), form_data.get("visibility", "shared")), "visibility": normalize_visibility(request.form.get("visibility"), form_data.get("visibility", "shared")),
"item_ids": [int(value) for value in request.form.getlist("item_ids") if value.isdigit()], "item_ids": item_ids,
"item_search": request.form.get("item_search", "").strip(), "item_search": request.form.get("item_search", "").strip(),
} }
) )
@@ -3441,6 +3445,7 @@ def item_set_create():
visibility_options=VISIBILITY_FORM_OPTIONS, visibility_options=VISIBILITY_FORM_OPTIONS,
name_suggestions=ITEM_SET_NAME_SUGGESTIONS, name_suggestions=ITEM_SET_NAME_SUGGESTIONS,
item_groups=group_items_by_availability(items), item_groups=group_items_by_availability(items),
selected_items=fetch_items_by_ids(form_data["item_ids"]),
) )
@@ -3491,6 +3496,7 @@ def item_set_edit(set_id: int):
visibility_options=VISIBILITY_FORM_OPTIONS, visibility_options=VISIBILITY_FORM_OPTIONS,
name_suggestions=ITEM_SET_NAME_SUGGESTIONS, name_suggestions=ITEM_SET_NAME_SUGGESTIONS,
item_groups=group_items_by_availability(items), item_groups=group_items_by_availability(items),
selected_items=fetch_items_by_ids(form_data["item_ids"]),
) )
+70
View File
@@ -981,12 +981,82 @@ h3 {
.item-body { .item-body {
min-width: 0; min-width: 0;
display: grid;
gap: 0.7rem;
} }
.item-body p { .item-body p {
margin: 0;
line-height: 1.55; line-height: 1.55;
} }
.item-meta-disclosure {
display: grid;
gap: 0.65rem;
margin-top: 0.05rem;
}
.item-meta-disclosure > summary {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.45rem;
width: fit-content;
padding: 0.55rem 0.9rem;
border-radius: 999px;
border: 1px solid color-mix(in srgb, var(--line) 78%, transparent 22%);
background: color-mix(in srgb, var(--surface-soft) 38%, transparent 62%);
color: var(--muted);
cursor: pointer;
list-style: none;
transition: background 0.18s ease, border-color 0.18s ease, color 0.18s ease, transform 0.18s ease;
}
.item-meta-disclosure > summary::-webkit-details-marker {
display: none;
}
.item-meta-disclosure > summary:hover {
color: var(--text);
border-color: color-mix(in srgb, var(--accent) 32%, var(--line) 68%);
background: color-mix(in srgb, var(--accent-soft) 22%, var(--surface-soft) 78%);
transform: translateY(-1px);
}
.item-meta-disclosure[open] > summary {
color: var(--text);
border-color: color-mix(in srgb, var(--accent) 36%, var(--line) 64%);
background: color-mix(in srgb, var(--accent-soft) 26%, var(--surface-soft) 74%);
}
.item-meta-panel {
display: grid;
gap: 0.7rem;
padding: 0.9rem 1rem 0.95rem;
border-radius: 18px;
border: 1px solid color-mix(in srgb, var(--line) 82%, transparent 18%);
background: color-mix(in srgb, var(--surface-soft) 46%, transparent 54%);
}
[data-theme="dark"] .item-meta-disclosure > summary {
background: color-mix(in srgb, var(--surface-soft) 42%, rgba(33, 28, 27, 0.58) 58%);
border-color: color-mix(in srgb, var(--line) 62%, rgba(243, 177, 125, 0.12) 38%);
}
[data-theme="dark"] .item-meta-disclosure > summary:hover,
[data-theme="dark"] .item-meta-disclosure[open] > summary {
background: color-mix(in srgb, var(--accent-soft) 24%, rgba(38, 31, 29, 0.76) 76%);
}
[data-theme="dark"] .item-meta-panel {
background: linear-gradient(
180deg,
color-mix(in srgb, var(--surface-soft) 60%, #463c39 40%),
color-mix(in srgb, var(--surface) 92%, #2a2422 8%)
);
border-color: color-mix(in srgb, var(--line) 58%, rgba(243, 177, 125, 0.16) 42%);
}
.item-actions { .item-actions {
grid-column: 1 / -1; grid-column: 1 / -1;
display: flex; display: flex;
+30 -7
View File
@@ -69,22 +69,45 @@
<h2>{{ item.name }}</h2> <h2>{{ item.name }}</h2>
<span class="status-pill status-{{ item.availability_state }}">{{ availability_labels[item.availability_state] }}</span> <span class="status-pill status-{{ item.availability_state }}">{{ availability_labels[item.availability_state] }}</span>
</div> </div>
{% if item.kind == 'food' %}
<div class="chip-row">
<span class="chip">{{ item.for_label }}</span>
{% if item.is_on_shopping_list %}
<span class="chip status-idea">Auf Einkaufsliste</span>
{% endif %}
</div>
<details class="item-meta-disclosure">
<summary>Mehr zeigen</summary>
<div class="item-meta-panel">
<div class="chip-row"> <div class="chip-row">
<span class="chip">{{ item.visibility_label }}</span> <span class="chip">{{ item.visibility_label }}</span>
<span class="chip status-soft">{{ item.owner_label }}</span> <span class="chip status-soft">{{ item.owner_label }}</span>
<span class="chip">{{ item.for_label }}</span>
</div>
{% if item.kind == 'food' %}
<div class="chip-row">
<span class="chip">{{ item.base_type_label }}</span> <span class="chip">{{ item.base_type_label }}</span>
<span class="chip">{{ item.suggestion_role_label }}</span> <span class="chip">{{ item.suggestion_role_label }}</span>
<span class="chip">{{ item.suggestion_priority_label }}</span> <span class="chip">{{ item.suggestion_priority_label }}</span>
{% if item.can_be_meal_core %} {% if item.can_be_meal_core %}
<span class="chip status-okay">Trägt gut eine Mahlzeit</span> <span class="chip status-okay">Trägt gut eine Mahlzeit</span>
{% endif %} {% endif %}
<span class="chip">{{ item_kind_labels[item.kind] }}</span>
</div> </div>
<p class="muted">{{ item_kind_labels[item.kind] }}</p> {% if item.dayparts %}
<div class="chip-row">
{% for daypart in item.dayparts %}
<span class="chip">{{ daypart }}</span>
{% endfor %}
</div>
{% endif %}
{% if item.note %}
<p>{{ item.note }}</p>
{% endif %}
</div>
</details>
{% else %} {% else %}
<div class="chip-row">
<span class="chip">{{ item.visibility_label }}</span>
<span class="chip status-soft">{{ item.owner_label }}</span>
<span class="chip">{{ item.for_label }}</span>
</div>
<div class="chip-row"> <div class="chip-row">
<span class="chip">{{ item.meal_type_label }}</span> <span class="chip">{{ item.meal_type_label }}</span>
<span class="chip">{{ energy_density_labels[item.energy_density] }}</span> <span class="chip">{{ energy_density_labels[item.energy_density] }}</span>
@@ -93,7 +116,7 @@
{% endfor %} {% endfor %}
</div> </div>
{% endif %} {% endif %}
{% if item.dayparts %} {% if item.kind != 'food' and item.dayparts %}
<div class="chip-row"> <div class="chip-row">
{% for daypart in item.dayparts %} {% for daypart in item.dayparts %}
<span class="chip">{{ daypart }}</span> <span class="chip">{{ daypart }}</span>
@@ -103,7 +126,7 @@
{% if item.components %} {% if item.components %}
<p class="muted">Mit: {{ item.components|join(', ') }}</p> <p class="muted">Mit: {{ item.components|join(', ') }}</p>
{% endif %} {% endif %}
{% if item.note %} {% if item.kind != 'food' and item.note %}
<p>{{ item.note }}</p> <p>{{ item.note }}</p>
{% endif %} {% endif %}
</div> </div>
+55
View File
@@ -38,6 +38,61 @@
{% endfor %} {% endfor %}
</div> </div>
{% if selected_items %}
<fieldset>
<legend>Schon ausgewählt</legend>
{% for item_id in form_data.item_ids %}
<input type="hidden" name="item_ids" value="{{ item_id }}">
{% endfor %}
<div class="selected-components-grid">
{% for item in selected_items %}
{% if item.kind == 'meal' %}
{% set item_icon_class = {
'breakfast': 'icon-daypart-breakfast',
'lunch': 'icon-daypart-lunch',
'dinner': 'icon-daypart-dinner',
'snack': 'icon-daypart-afternoon-snack',
}.get(item.meal_type, 'icon-utensils') %}
{% else %}
{% set item_icon_class = {
'protein': 'icon-component-protein',
'carb': 'icon-component-carb',
'veg': 'icon-component-veg',
'fruit': 'icon-component-fruit',
'dairy': 'icon-component-dairy',
'nuts': 'icon-component-nuts',
'seeds': 'icon-component-seeds',
'neutral': 'icon-component-neutral',
}.get(item.primary_builder_key or item.base_type, 'icon-component-neutral') %}
{% endif %}
<article class="selected-component-card">
<button class="selected-component-remove" type="submit" name="remove_item_id" value="{{ item.id }}">
<span aria-hidden="true">×</span>
<span class="sr-only">{{ item.name }} entfernen</span>
</button>
<div class="selected-component-visual">
{% if item.photo_filename %}
<img
src="{{ image_url(item.photo_filename, 'md') }}"
srcset="{{ image_srcset(item.photo_filename) }}"
sizes="{{ image_sizes('grid') }}"
alt="{{ item.name }}"
loading="lazy">
{% else %}
<span class="selected-component-fallback">
<span class="ui-icon {{ item_icon_class }}"></span>
</span>
{% endif %}
</div>
<div class="selected-component-main">
<strong>{{ item.name }}</strong>
</div>
</article>
{% endfor %}
</div>
</fieldset>
{% endif %}
<fieldset> <fieldset>
<legend>Einträge auswählen</legend> <legend>Einträge auswählen</legend>
<label> <label>