v0.2 planning and ux improvements

This commit is contained in:
2026-04-12 11:21:09 +02:00
parent 21014c246e
commit 36bde02c54
30 changed files with 1456 additions and 368 deletions
+104
View File
@@ -0,0 +1,104 @@
{% extends "base.html" %}
{% block title %}Tagesplan | Nouri{% endblock %}
{% block content %}
<section class="page-intro">
<div>
<p class="eyebrow">Tagesplan</p>
<h1>{{ weekday_name(selected_date) }}, {{ selected_date.strftime('%d.%m.%Y') }}</h1>
<p class="lead">Der Tagesplan bleibt bewusst ruhig. Jede Tageszeit ist eine eigene Kachel und öffnet sich erst, wenn du sie brauchst.</p>
</div>
<div class="week-nav">
<a class="ghost-button" href="{{ url_for('main.planner_day', date=previous_day.isoformat()) }}">Vorheriger Tag</a>
<a class="ghost-button" href="{{ url_for('main.planner') }}">Zur Woche</a>
<a class="ghost-button" href="{{ url_for('main.planner_day', date=next_day.isoformat()) }}">Nächster Tag</a>
</div>
</section>
<section class="planner-day-stack">
{% for section in sections %}
<details class="day-tile" id="daypart-{{ section.daypart.id }}" {% if section.is_open %}open{% endif %}>
<summary class="day-tile-summary">
<div class="day-tile-summary-main">
<div class="day-tile-icon"><span class="ui-icon icon-calendar"></span></div>
<div>
<h2>{{ section.daypart.name }}</h2>
{% if section.summary_items %}
<p class="muted">{{ section.summary_items|join(', ') }}</p>
{% else %}
<p class="muted">Noch frei. Öffnen, wenn du etwas ergänzen möchtest.</p>
{% endif %}
</div>
</div>
<span class="status-pill">{{ section.entries|length }} geplant</span>
</summary>
<div class="day-tile-body">
{% if section.quick_items %}
<div class="quick-add-row">
{% for item in section.quick_items %}
<form method="post" action="{{ url_for('main.planner_day', date=selected_date.isoformat()) }}">
{{ csrf_input() }}
<input type="hidden" name="plan_date" value="{{ selected_date.isoformat() }}">
<input type="hidden" name="daypart_id" value="{{ section.daypart.id }}">
<input type="hidden" name="item_id" value="{{ item.id }}">
<button class="quick-add-button" type="submit">
<span>{{ item.name }}</span>
<small>{{ item_kind_labels[item.kind] }}{% if item.availability_state == 'home' %} · zuhause{% endif %}</small>
</button>
</form>
{% endfor %}
</div>
{% endif %}
<form method="post" class="planner-entry-form">
{{ csrf_input() }}
<input type="hidden" name="plan_date" value="{{ selected_date.isoformat() }}">
<input type="hidden" name="daypart_id" value="{{ section.daypart.id }}">
<label class="wide">
Eintrag hinzufügen
<select name="item_id">
<option value="">Etwas für {{ section.daypart.name }} wählen</option>
{% for item in section.candidates %}
<option value="{{ item.id }}" {% if section.selected_item_id == item.id %}selected{% endif %}>
{{ item.name }} · {{ item_kind_labels[item.kind] }}{% if item.availability_state == 'home' %} · zuhause{% endif %}{% if item.dayparts and section.daypart.name not in item.dayparts %} · auch flexibel{% endif %}
</option>
{% endfor %}
</select>
</label>
<label class="wide">
Notiz
<input type="text" name="note" placeholder="Optional, wenn eine kleine Erinnerung hilft">
</label>
<button type="submit">Eintragen</button>
</form>
{% if section.entries %}
<div class="planner-entry-list">
{% for entry in section.entries %}
<article class="planner-entry">
<div class="planner-entry-top">
<div>
<strong>{{ entry.item_name }}</strong>
<small>{{ item_kind_labels[entry.item_kind] }}{% if entry.availability_state == 'home' %} · zuhause{% else %} · bei Bedarf auf Einkaufsliste{% endif %}</small>
</div>
<div class="row-actions">
<form method="post" action="{{ url_for('main.planner_remove', entry_id=entry.id, date=selected_date.isoformat()) }}">
{{ csrf_input() }}
<button class="ghost-button" type="submit">Entfernen</button>
</form>
</div>
</div>
{% if entry.note %}
<p>{{ entry.note }}</p>
{% endif %}
</article>
{% endfor %}
</div>
{% else %}
<p class="empty-state">Hier ist noch nichts eingetragen. Ein kleiner Anfang reicht völlig.</p>
{% endif %}
</div>
</details>
{% endfor %}
</section>
{% endblock %}
+57 -67
View File
@@ -1,81 +1,71 @@
{% extends "base.html" %}
{% block title %}Wochenplan | Nouri{% endblock %}
{% block title %}Wochenansicht | Nouri{% endblock %}
{% block content %}
<section class="page-intro">
<div>
<p class="eyebrow">Wochenplan</p>
<h1>Struktur fuer die naechsten Tage</h1>
<p class="lead">Der Plan bleibt bewusst leichtgewichtig. Vorhandene Dinge tauchen in der Auswahl zuerst auf.</p>
<p class="eyebrow">Wochenansicht</p>
<h1>Ein sanfter Blick auf die nächsten sieben Tage</h1>
<p class="lead">Du kannst bestehende Einträge zwischen Tagen und Tageszeiten verschieben. Wenn etwas noch nicht zuhause ist, landet es dabei automatisch auf der Einkaufsliste.</p>
</div>
<div class="week-nav">
<a class="ghost-button" href="{{ url_for('main.planner', week=prev_week.isoformat()) }}">Vorige Woche</a>
<span>{{ days[0].strftime('%d.%m.') }} bis {{ days[-1].strftime('%d.%m.%Y') }}</span>
<a class="ghost-button" href="{{ url_for('main.planner', week=next_week.isoformat()) }}">Naechste Woche</a>
<span>{{ week_start.strftime('%d.%m.%Y') }} bis {{ week_end.strftime('%d.%m.%Y') }}</span>
<a class="ghost-button" href="{{ url_for('main.planner', week=next_week.isoformat()) }}">Nächste Woche</a>
</div>
</section>
<section class="panel compact-form-panel">
<form method="post" class="planner-form">
{{ csrf_input() }}
<label>
Tag
<input type="date" name="plan_date" value="{{ days[0].isoformat() }}">
</label>
<label>
Tageszeit
<select name="daypart_id">
{% for daypart in dayparts %}
<option value="{{ daypart.id }}">{{ daypart.name }}</option>
{% endfor %}
</select>
</label>
<label class="wide">
Eintrag
<select name="item_id">
<option value="">Etwas fuer den Plan waehlen</option>
{% for item in selectable_items %}
<option value="{{ item.id }}">{{ item.name }} · {{ item_kind_labels[item.kind] }}{% if item.availability_state == 'home' %} · zuhause{% endif %}</option>
{% endfor %}
</select>
</label>
<label class="wide">
Notiz
<input type="text" name="note" placeholder="Optional, z. B. zuerst einkaufen">
</label>
<button type="submit">In den Plan legen</button>
</form>
</section>
<section class="planner-grid">
{% for daypart in dayparts %}
<div class="planner-row">
<div class="planner-label">{{ daypart.name }}</div>
{% for day in days %}
<div class="planner-cell">
<div class="planner-date">{{ day.strftime('%a %d.%m.') }}</div>
{% set slot_entries = entries.get((day.isoformat(), daypart.id), []) %}
{% if slot_entries %}
<div class="planner-entry-stack">
{% for entry in slot_entries %}
<article class="planner-entry">
<strong>{{ entry.item_name }}</strong>
<small>{{ item_kind_labels[entry.item_kind] }}</small>
{% if entry.note %}
<p>{{ entry.note }}</p>
{% endif %}
<form method="post" action="{{ url_for('main.planner_remove', entry_id=entry.id, week=week_start.isoformat()) }}">
{{ csrf_input() }}
<button class="ghost-button" type="submit">Entfernen</button>
</form>
</article>
{% endfor %}
</div>
{% else %}
<p class="empty-slot">frei</p>
{% endif %}
<section class="week-overview-grid week-board" data-csrf-token="{{ csrf_token_value }}">
{% for card in week_cards %}
<article class="week-card">
<div class="week-card-head">
<div>
<p class="eyebrow">{{ weekday_name(card.date) }}</p>
<h2>{{ card.date.strftime('%d.%m.%Y') }}</h2>
</div>
{% endfor %}
</div>
{% if card.date == today %}
<span class="status-pill status-home">heute</span>
{% endif %}
</div>
{% if card.filled_dayparts %}
<p class="week-card-count">{{ card.planned_count }} Einträge</p>
<div class="chip-row">
{% for slot in card.filled_dayparts %}
<span class="chip">{{ slot.name }} · {{ slot.count }}</span>
{% endfor %}
</div>
<p class="muted">{{ card.preview_items | join(', ') }}</p>
{% else %}
<p class="empty-state">Noch offen. Du kannst den Tag ganz leicht nach und nach füllen.</p>
{% endif %}
<div class="week-slot-stack">
{% for slot in card.slots %}
<div class="week-slot drop-slot" data-target-date="{{ card.date.isoformat() }}" data-target-daypart-id="{{ slot.daypart.id }}">
<div class="week-slot-head">
<strong>{{ slot.daypart.name }}</strong>
<span>{{ slot.entries|length }}</span>
</div>
{% if slot.entries %}
<div class="week-entry-stack">
{% for entry in slot.entries %}
<article class="plan-chip draggable-plan-entry" draggable="true" data-entry-id="{{ entry.id }}" data-move-url="{{ url_for('main.planner_move', entry_id=entry.id) }}">
<strong>{{ entry.item_name }}</strong>
<small>{{ item_kind_labels[entry.item_kind] }}</small>
</article>
{% endfor %}
</div>
{% else %}
<p class="week-slot-empty">Hierher ziehen</p>
{% endif %}
</div>
{% endfor %}
</div>
<div class="week-card-actions">
<a class="button" href="{{ url_for('main.planner_day', date=card.date.isoformat()) }}">Tagesplan öffnen</a>
</div>
</article>
{% endfor %}
</section>
{% endblock %}