Files
oikos/.superpowers/brainstorm/958518-1777309033/content/01-overview.html
T
Ulas Kalayci 82a1f2c239 feat: add flexible reminder options for birthdays
Add support for customizable birthday reminders with preset offsets
(none, at time, 15min, 1h, 1d, 2d, 1w, 2w) and custom intervals.
Users can now configure when to be reminded of upcoming birthdays.

- Add migration 31: reminder_offset, reminder_custom_amount, reminder_custom_unit to birthdays table
- Update POST/PUT /birthdays routes to accept reminder fields
- Add getOffsetMinutes() helper in birthday service
- Update birthdayReminderAt() to calculate reminder time with offset
- Modify syncBirthdayReminder() to handle empty offset (no reminder)
- Add renderBirthdayReminderSection() UI component
- Move reminder-custom CSS from calendar.css to reminders.css
- Add protocol check to service worker (non-http protocol guard)

All translations already present in de.json.
Tests: 109 passing, 0 failing.

Co-Authored-By: Rafael Foster <rafaelfoster@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-04 20:31:42 +02:00

180 lines
10 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Oikos UX/UI Analyse</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: #0f0f0e;
color: #f0ede8;
min-height: 100vh;
padding: 32px 24px 80px;
}
.header { max-width: 920px; margin: 0 auto 40px; }
.eyebrow { font-size: 11px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; color: #818CF8; margin-bottom: 8px; }
h1 { font-size: clamp(26px, 4vw, 40px); font-weight: 700; letter-spacing: -.03em; line-height: 1.1; margin-bottom: 10px; }
h1 span { color: #818CF8; }
.sub { font-size: 14px; color: #8E8D89; line-height: 1.5; }
.summary { max-width: 920px; margin: 0 auto 40px; background: rgba(129,140,248,.08); border: 1px solid rgba(129,140,248,.2); border-radius: 16px; padding: 24px; display: grid; grid-template-columns: repeat(3,1fr); gap: 12px; text-align: center; }
@media(max-width:480px){ .summary { grid-template-columns: 1fr; } }
.sum-num { font-size: 38px; font-weight: 700; letter-spacing: -.03em; line-height: 1; }
.sum-lbl { font-size: 11px; color: #8E8D89; margin-top: 4px; }
.c { color: #FCA5A5; } .h { color: #FCD34D; } .m { color: #6EE7B7; }
hr { max-width: 920px; margin: 0 auto 36px; border: none; border-top: 1px solid rgba(255,255,255,.06); }
.section { max-width: 920px; margin: 0 auto 40px; }
.slbl { font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; margin-bottom: 16px; display: flex; align-items: center; gap: 8px; }
.slbl::after { content:''; flex:1; height:1px; background:rgba(255,255,255,.06); }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px,1fr)); gap: 14px; }
.card { background: #1a1a18; border-radius: 14px; border: 1px solid rgba(255,255,255,.06); padding: 18px; display: flex; flex-direction: column; gap: 8px; }
.card:hover { border-color: rgba(255,255,255,.12); }
.card-ico { width: 34px; height: 34px; border-radius: 9px; display: flex; align-items: center; justify-content: center; font-size: 16px; flex-shrink: 0; margin-bottom: 2px; }
.ico-c { background: rgba(252,165,165,.12); }
.ico-h { background: rgba(252,211,77,.1); }
.ico-m { background: rgba(110,231,183,.1); }
.card-title { font-size: 13px; font-weight: 600; line-height: 1.35; }
.card-body { font-size: 12px; color: #8E8D89; line-height: 1.55; }
.badge { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 99px; font-size: 10px; font-weight: 600; margin-top: auto; align-self: flex-start; }
.bc { color:#FCA5A5; background:rgba(252,165,165,.1); }
.bh { color:#FCD34D; background:rgba(252,211,77,.08); }
.bm { color:#6EE7B7; background:rgba(110,231,183,.08); }
.strengths { display: grid; grid-template-columns: repeat(auto-fill,minmax(200px,1fr)); gap: 10px; }
.str { background: rgba(129,140,248,.06); border: 1px solid rgba(129,140,248,.12); border-radius: 12px; padding: 14px; }
.str-title { font-size: 12px; font-weight: 600; margin-bottom: 4px; }
.str-body { font-size: 11px; color: #8E8D89; line-height: 1.5; }
</style>
</head>
<body>
<div class="header">
<div class="eyebrow">Oikos UX/UI Analyse · April 2026</div>
<h1>Was funktioniert — was bremst <span>Oikos</span></h1>
<p class="sub">70 % Mobile-PWA · 30 % Desktop · 11 Module · Vanilla JS</p>
</div>
<div class="summary">
<div><div class="sum-num c">4</div><div class="sum-lbl">Kritisch<br>sofort beheben</div></div>
<div><div class="sum-num h">5</div><div class="sum-lbl">Hohe Priorität<br>nächster Sprint</div></div>
<div><div class="sum-num m">4</div><div class="sum-lbl">Mittlere Priorität<br>Backlog</div></div>
</div>
<hr>
<div class="section">
<div class="slbl" style="color:#FCA5A5">🔴 Kritisch</div>
<div class="grid">
<div class="card">
<div class="card-ico ico-c">🧭</div>
<div class="card-title">Sidebar 10241279 px: Icons ohne Labels/Tooltips</div>
<div class="card-body">Bei häufigster Desktop-Auflösung sind Modul-Icons ohne jede Beschriftung — kein Tooltip, kein Label. 11 Module sind nicht erkennbar.</div>
<div class="badge bc">Keine Discoverability</div>
</div>
<div class="card">
<div class="card-ico ico-c">👆</div>
<div class="card-title">Modal-Close: 40 px statt 44 px Minimum</div>
<div class="card-body"><code>.modal-panel__close</code> nutzt <code>--target-md</code> (40 px). iOS-Minimum ist 44 pt. Auf kleinen Screens spürbares Frustrationspotenzial.</div>
<div class="badge bc">Apple HIG Violation</div>
</div>
<div class="card">
<div class="card-ico ico-c">🔗</div>
<div class="card-title">Widget-Links: Tap-Target &lt; 44 px</div>
<div class="card-body"><code>.widget__link</code>: 12 px Text, kein <code>min-height</code>. Effektiver Tippbereich ~1618 px. Auf jedem Dashboard-Widget vorhanden.</div>
<div class="badge bc">Tap-Target Violation</div>
</div>
<div class="card">
<div class="card-ico ico-c">🔁</div>
<div class="card-title">Doppelter FAB: .fab vs .page-fab</div>
<div class="card-body">Zwei nahezu identische FAB-Klassen mit unterschiedlicher <code>bottom</code>-Berechnung erzeugen inkonsistente Positionierung auf verschiedenen Seiten.</div>
<div class="badge bc">Inkonsistente UI</div>
</div>
</div>
</div>
<div class="section">
<div class="slbl" style="color:#FCD34D">🟡 Hoch</div>
<div class="grid">
<div class="card">
<div class="card-ico ico-h">🗂️</div>
<div class="card-title">Onboarding: 3 Screens für 11 Module</div>
<div class="card-body">3 generische Steps erklären nicht Budget, RRule-Wiederholungen oder Calendar-Sync. Kein Feature-Discovery danach.</div>
<div class="badge bh">Discoverability</div>
</div>
<div class="card">
<div class="card-ico ico-h">📊</div>
<div class="card-title">Widget-Reihenfolge nicht anpassbar</div>
<div class="card-body">Config speichert nur <code>{ id, visible }</code> — kein order-Feld. Familien mit verschiedenen Prioritäten können das Dashboard nicht sinnvoll anpassen.</div>
<div class="badge bh">Personalisierung</div>
</div>
<div class="card">
<div class="card-ico ico-h">↩️</div>
<div class="card-title">Inkonsistentes Undo</div>
<div class="card-body">Manche Aktionen zeigen Undo-Toast, andere nicht. Kein zentrales Undo-System. Bei Kontakt/Notiz löschen fehlt der Weg zurück.</div>
<div class="badge bh">Fehlererholung</div>
</div>
<div class="card">
<div class="card-ico ico-h">📡</div>
<div class="card-title">Kein sichtbarer Offline-Indikator</div>
<div class="card-body">Service Worker existiert, aber kein Offline-Banner in der App-Shell. Nutzer merken Offline erst beim API-Fehler — zu spät.</div>
<div class="badge bh">PWA-Erfahrung</div>
</div>
<div class="card">
<div class="card-ico ico-h">⌨️</div>
<div class="card-title">Keine Keyboard Shortcuts</div>
<div class="card-body">30 % Desktop-Nutzung ohne globale Shortcuts. Kein „N" für neu, kein „/" für Suche. Power-User auf Maus angewiesen.</div>
<div class="badge bh">Desktop-Ergonomie</div>
</div>
</div>
</div>
<div class="section">
<div class="slbl" style="color:#6EE7B7">🟢 Mittel</div>
<div class="grid">
<div class="card">
<div class="card-ico ico-m">📦</div>
<div class="card-title">reminders.css global geladen</div>
<div class="card-body">Wird auf allen Seiten geparst, nicht lazy. Kein Blocking-Problem, aber vermeidbare CSS-Last auf Seiten ohne Reminder-UI.</div>
<div class="badge bm">Performance</div>
</div>
<div class="card">
<div class="card-ico ico-m">👉</div>
<div class="card-title">Swipe nur Tasks & Shopping</div>
<div class="card-body">Swipe-Reveal fehlt bei Kontakten, Notizen, Geburtstagen. Inkonsistente Erwartungshaltung im selben App-Kontext.</div>
<div class="badge bm">Interaktions-Konsistenz</div>
</div>
<div class="card">
<div class="card-ico ico-m">🎨</div>
<div class="card-title">11 Modulfarben gleichzeitig im Dashboard</div>
<div class="card-body">Wenn alle Widgets sichtbar sind, treffen 11 Akzentfarben aufeinander. Das Dashboard kann farblich überladen wirken.</div>
<div class="badge bm">Visuelle Ruhe</div>
</div>
<div class="card">
<div class="card-ico ico-m">💬</div>
<div class="card-title">Toast: kein Swipe-to-Dismiss</div>
<div class="card-body">Toasts sind nicht wegwischbar. Auf iOS/Android ist Swipe-to-Dismiss eine fest etablierte Konvention — ihr Fehlen fällt auf.</div>
<div class="badge bm">Mobile-Konvention</div>
</div>
</div>
</div>
<hr>
<div class="section">
<div class="slbl" style="color:#818CF8">✨ Was bereits ausgezeichnet ist</div>
<div class="strengths">
<div class="str"><div class="str-title">🌙 Dark Mode Architektur</div><div class="str-body">Private/Public-Token-Pattern ist mustergültig. Alle Kontraste WCAG-geprüft.</div></div>
<div class="str"><div class="str-title">♿ 4 A11y-Schichten</div><div class="str-body">reduced-motion, reduced-transparency, prefers-contrast, forced-colors — alle implementiert.</div></div>
<div class="str"><div class="str-title">🍎 iOS-PWA-Bewusstsein</div><div class="str-body">100dvh + webkit-Fallback, safe-area-inset, Flex-Kind statt fixed nav.</div></div>
<div class="str"><div class="str-title">💎 Glass Design System</div><div class="str-body">@supports-basiert, opake Fallbacks für reduced-transparency, konsistente Token.</div></div>
<div class="str"><div class="str-title">🎭 Modul-Theming</div><div class="str-body">--active-module-accent System elegant — FAB, Nav, Toggles spiegeln aktive Seite.</div></div>
<div class="str"><div class="str-title">📐 Design Tokens</div><div class="str-body">Vollständige Skala, kaum Hardcoding. Basis für alles weitere.</div></div>
</div>
</div>
</body>
</html>