feat(dashboard): add immersive day range views
This commit is contained in:
+507
-92
@@ -1,99 +1,514 @@
|
||||
<section class="hero-grid">
|
||||
<article class="hero-card hero-card--wide glass-panel">
|
||||
<p class="eyebrow">Stimmung im Blick</p>
|
||||
<h3>Dein Dashboard verbindet Verlauf, Score und Bewegungsdaten in einer schnellen Übersicht.</h3>
|
||||
<p class="hero-copy">Die Bewertung basiert auf deiner konfigurierbaren Logik. Sobald du die Regeln in den Optionen änderst, spiegeln Archiv und Statistiken die neue Gewichtung wider.</p>
|
||||
</article>
|
||||
<?php
|
||||
$dayDateLabel = format_display_date((string) $dayEntry['date']);
|
||||
$dayWeekday = strtok($dayDateLabel, ',');
|
||||
$dayBackground = is_string($dayEntry['background_image_url'] ?? null) ? (string) $dayEntry['background_image_url'] : null;
|
||||
$summaryComment = trim((string) ($dayEntry['summary']['comment'] ?? $dayEntry['summary_comment'] ?? ''));
|
||||
$summaryMood = normalize_signal_value($dayEntry['summary']['mood'] ?? $dayEntry['summary_mood'] ?? 0);
|
||||
$summaryEnergy = normalize_signal_value($dayEntry['summary']['energy'] ?? $dayEntry['summary_energy'] ?? 0);
|
||||
$summaryStress = normalize_signal_value($dayEntry['summary']['stress'] ?? $dayEntry['summary_stress'] ?? 0);
|
||||
$summaryAlcohol = !empty($dayEntry['summary']['alcohol'] ?? $dayEntry['summary_alcohol'] ?? false);
|
||||
?>
|
||||
|
||||
<article class="hero-card glass-panel">
|
||||
<p class="eyebrow">Heute</p>
|
||||
<?php if ($summary['today'] !== null): ?>
|
||||
<div class="hero-score"><?= e(format_points((float) $summary['today']['evaluation']['total'])) ?></div>
|
||||
<p class="hero-label"><?= e($summary['today']['evaluation']['label']) ?></p>
|
||||
<?php else: ?>
|
||||
<div class="hero-score">-</div>
|
||||
<p class="hero-label">Noch kein Eintrag für heute</p>
|
||||
<?php endif; ?>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="stats-grid">
|
||||
<article class="metric-card glass-panel">
|
||||
<span>Getrackte Tage</span>
|
||||
<strong><?= e((string) $summary['tracked_days']) ?></strong>
|
||||
</article>
|
||||
<article class="metric-card glass-panel">
|
||||
<span>Ø Score</span>
|
||||
<strong><?= e(format_points((float) $summary['average_score'])) ?></strong>
|
||||
</article>
|
||||
<article class="metric-card glass-panel">
|
||||
<span>Ø Stimmung</span>
|
||||
<strong><?= e(format_points((float) $summary['average_mood'])) ?>/10</strong>
|
||||
</article>
|
||||
<article class="metric-card glass-panel">
|
||||
<span>Ø Stress</span>
|
||||
<strong><?= e(format_points((float) $summary['average_stress'])) ?>/10</strong>
|
||||
</article>
|
||||
<article class="metric-card glass-panel">
|
||||
<span>Serie</span>
|
||||
<strong><?= e((string) $summary['streak']) ?> Tage</strong>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="dashboard-grid">
|
||||
<article class="glass-panel chart-card chart-card--calendar">
|
||||
<div class="section-head">
|
||||
<div>
|
||||
<p class="eyebrow">Kalender</p>
|
||||
<h3>Gesamtstimmung pro Tag</h3>
|
||||
</div>
|
||||
<section class="dashboard-shell<?= $dayBackground !== null ? ' dashboard-shell--with-image' : '' ?>" data-dashboard-root>
|
||||
<?php if ($dayBackground !== null): ?>
|
||||
<div class="dashboard-shell__background" aria-hidden="true">
|
||||
<img src="<?= e($dayBackground) ?>" alt="">
|
||||
</div>
|
||||
<div id="calendar-heatmap" class="calendar-heatmap" data-payload="<?= e($chartPayload) ?>"></div>
|
||||
</article>
|
||||
|
||||
<article class="glass-panel chart-card">
|
||||
<div class="section-head">
|
||||
<div>
|
||||
<p class="eyebrow">Trend</p>
|
||||
<h3>Tagesstimmung</h3>
|
||||
</div>
|
||||
<span class="chart-chip">letzte 30 Einträge</span>
|
||||
</div>
|
||||
<div class="line-chart" data-chart-type="line" data-series="mood" data-payload="<?= e($chartPayload) ?>"></div>
|
||||
</article>
|
||||
|
||||
<article class="glass-panel chart-card">
|
||||
<div class="section-head">
|
||||
<div>
|
||||
<p class="eyebrow">Belastung</p>
|
||||
<h3>Stressverlauf</h3>
|
||||
</div>
|
||||
<span class="chart-chip chart-chip--warm">weniger ist besser</span>
|
||||
</div>
|
||||
<div class="line-chart" data-chart-type="line" data-series="stress" data-payload="<?= e($chartPayload) ?>"></div>
|
||||
</article>
|
||||
|
||||
<?php if (!empty($settings['tracking']['pain_enabled'])): ?>
|
||||
<article class="glass-panel chart-card">
|
||||
<div class="section-head">
|
||||
<div>
|
||||
<p class="eyebrow">Körper</p>
|
||||
<h3>Schmerzverlauf</h3>
|
||||
</div>
|
||||
<span class="chart-chip chart-chip--warm">weniger ist besser</span>
|
||||
</div>
|
||||
<div class="line-chart" data-chart-type="line" data-series="pain" data-payload="<?= e($chartPayload) ?>"></div>
|
||||
</article>
|
||||
<?php endif; ?>
|
||||
|
||||
<article class="glass-panel chart-card chart-card--wide">
|
||||
<div class="section-head">
|
||||
<div>
|
||||
<p class="eyebrow">Aktivität</p>
|
||||
<h3>Sport und Spaziergang</h3>
|
||||
<header class="dashboard-topbar">
|
||||
<nav class="dashboard-switcher glass-panel" aria-label="Ansicht wechseln">
|
||||
<a class="<?= $dashboardView === 'day' ? 'active' : '' ?>" href="/?view=day&date=<?= e(rawurlencode($dashboardDate)) ?>">Tag</a>
|
||||
<a class="<?= $dashboardView === 'week' ? 'active' : '' ?>" href="/?view=week&date=<?= e(rawurlencode(today())) ?>">Woche</a>
|
||||
<a class="<?= $dashboardView === 'month' ? 'active' : '' ?>" href="/?view=month&date=<?= e(rawurlencode(today())) ?>">Monat</a>
|
||||
</nav>
|
||||
|
||||
<button class="dashboard-settings glass-panel" type="button" data-settings-menu-open aria-label="Optionen öffnen">
|
||||
<img src="<?= e(icon_path('options')) ?>" alt="">
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<?php if ($dashboardView === 'day'): ?>
|
||||
<div class="dashboard-day" data-day-swipe data-prev-date="<?= e($dashboardPrevDate) ?>" data-next-date="<?= e($dashboardNextDate) ?>">
|
||||
<div class="dashboard-day__hero">
|
||||
<p class="dashboard-day__eyebrow"><?= e((string) $dayWeekday) ?></p>
|
||||
<h1><?= e(format_display_date((string) $dayEntry['date'], false)) ?></h1>
|
||||
|
||||
<nav class="dashboard-compare-strip" aria-label="Tagesvergleich">
|
||||
<?php foreach ($dashboardCompareDays as $compareDay): ?>
|
||||
<a class="compare-day offset-<?= e((string) ($compareDay['offset'] ?? 0)) ?><?= !empty($compareDay['is_current']) ? ' is-current' : '' ?><?= empty($compareDay['has_content']) ? ' is-empty' : '' ?>" href="/?view=day&date=<?= e(rawurlencode((string) $compareDay['date'])) ?>">
|
||||
<span class="compare-day__line<?= empty($compareDay['has_content']) ? ' is-empty' : '' ?><?= !empty($compareDay['is_current']) ? ' is-primary' : '' ?> score-<?= e((string) ($compareDay['score_level'] ?? 'empty')) ?> compare-tone-<?= e((string) ($compareDay['line_tone'] ?? 'empty')) ?>">
|
||||
<span class="compare-day__marker"></span>
|
||||
</span>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</nav>
|
||||
</div>
|
||||
<span class="chart-chip chart-chip--cool">Aktivität pro Tag</span>
|
||||
|
||||
<button class="day-summary-card glass-panel<?= $dashboardHasContent ? ' is-filled' : '' ?>" type="button" data-summary-overlay-open>
|
||||
<span class="day-summary-card__label">Tagesbilanz</span>
|
||||
<strong class="day-summary-card__title"><?= $summaryComment !== '' ? e($summaryComment) : 'Tagesbilanz' ?></strong>
|
||||
</button>
|
||||
|
||||
<section class="dashboard-moments-block">
|
||||
<div class="section-head section-head--compact section-head--dashboard">
|
||||
<div>
|
||||
<p class="eyebrow">Deine Momente</p>
|
||||
<h2>Momente des Tages</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="timeline-list">
|
||||
<?php if ($dashboardTimeline === []): ?>
|
||||
<article class="timeline-card timeline-card--empty glass-panel">
|
||||
<div class="timeline-card__body">
|
||||
<h3>Noch keine Momente</h3>
|
||||
<p>Du kannst auch vergangene Tage jederzeit nachtragen.</p>
|
||||
</div>
|
||||
</article>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php foreach ($dashboardTimeline as $item): ?>
|
||||
<?php $sportType = ($item['type'] ?? '') === 'sport' ? find_sport_type($settings, (string) ($item['sport_type_id'] ?? '')) : null; ?>
|
||||
<?php $eventTone = signal_value_class(normalize_signal_value($item['mood'] ?? 0)); ?>
|
||||
<?php $eventPayload = encode_payload([
|
||||
'id' => (string) ($item['id'] ?? ''),
|
||||
'type' => (string) ($item['type'] ?? 'event'),
|
||||
'time' => (string) ($item['time'] ?? ''),
|
||||
'comment' => (string) ($item['comment'] ?? ''),
|
||||
'value' => (float) ($item['value'] ?? 0),
|
||||
'unit' => (string) ($item['unit'] ?? ''),
|
||||
'sport_type_id' => (string) ($item['sport_type_id'] ?? ''),
|
||||
'consumed' => !empty($item['consumed']),
|
||||
'mood' => normalize_signal_value($item['mood'] ?? 0),
|
||||
'energy' => normalize_signal_value($item['energy'] ?? 0),
|
||||
'stress' => normalize_signal_value($item['stress'] ?? 0),
|
||||
]); ?>
|
||||
<article class="timeline-card timeline-card--event timeline-card--<?= e($eventTone) ?> glass-panel" data-event-editable data-event-payload="<?= e($eventPayload) ?>">
|
||||
<div class="timeline-card__meta">
|
||||
<div class="timeline-card__icon-wrap" title="<?= e(day_event_type_label((string) $item['type'])) ?>">
|
||||
<img class="timeline-card__icon" src="<?= e(day_event_type_icon((string) $item['type'])) ?>" alt="">
|
||||
</div>
|
||||
<div>
|
||||
<strong><?= e($item['time'] !== '' ? $item['time'] : '--:--') ?></strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="timeline-card__body">
|
||||
<h3>
|
||||
<?php if ((string) ($item['type'] ?? '') === 'alcohol'): ?>
|
||||
<?= !empty($item['consumed']) ? 'Heute getrunken' : 'Heute nicht getrunken' ?>
|
||||
<?php else: ?>
|
||||
<?= e($item['comment'] !== '' ? $item['comment'] : day_event_type_label((string) $item['type'])) ?>
|
||||
<?php endif; ?>
|
||||
</h3>
|
||||
<?php if ((float) $item['value'] > 0): ?>
|
||||
<p class="timeline-card__value">
|
||||
<?= e(rtrim(rtrim(number_format((float) $item['value'], 2, ',', '.'), '0'), ',')) ?>
|
||||
<?= e((string) $item['unit']) ?>
|
||||
<?php if ($sportType !== null): ?>
|
||||
· <?= e((string) ($sportType['label'] ?? '')) ?>
|
||||
<?php endif; ?>
|
||||
</p>
|
||||
<?php elseif ($sportType !== null): ?>
|
||||
<p class="timeline-card__value"><?= e((string) ($sportType['label'] ?? '')) ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ((string) ($item['comment'] ?? '') !== '' && (string) ($item['type'] ?? '') === 'alcohol'): ?>
|
||||
<p class="timeline-card__value"><?= e((string) $item['comment']) ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="signal-row">
|
||||
<?php foreach (['mood' => 'Stimmung', 'energy' => 'Energie', 'stress' => 'Stress'] as $metric => $label): ?>
|
||||
<?php $value = normalize_signal_value($item[$metric] ?? 0); ?>
|
||||
<span class="signal-pill signal-pill--<?= e(signal_badge_tone($value, $metric)) ?>">
|
||||
<strong><?= e($label) ?></strong>
|
||||
<span><?= $value >= 0 ? '+' : '' ?><?= e((string) $value) ?></span>
|
||||
</span>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form method="post" action="/" class="timeline-card__delete">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="form_name" value="delete_event">
|
||||
<input type="hidden" name="date" value="<?= e((string) $dayEntry['date']) ?>">
|
||||
<input type="hidden" name="event_id" value="<?= e((string) $item['id']) ?>">
|
||||
<button class="ghost-button ghost-button--small" type="submit" data-confirm-delete aria-label="Moment löschen">×</button>
|
||||
</form>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<button class="dashboard-fab" type="button" data-moment-overlay-open aria-label="Neuen Moment hinzufügen">+</button>
|
||||
</div>
|
||||
<div class="bar-chart" data-chart-type="bars" data-series="sport" data-payload="<?= e($chartPayload) ?>"></div>
|
||||
</article>
|
||||
|
||||
<div class="dashboard-overlay" data-summary-overlay hidden>
|
||||
<div class="dashboard-overlay__backdrop" data-summary-overlay-close></div>
|
||||
<section class="dashboard-modal glass-panel dashboard-modal--summary" role="dialog" aria-modal="true">
|
||||
<div class="dashboard-modal__controls">
|
||||
<button class="dashboard-modal__round" type="button" data-summary-overlay-close>×</button>
|
||||
<button class="dashboard-modal__round dashboard-modal__round--confirm" type="submit" form="day-summary-form">✓</button>
|
||||
</div>
|
||||
|
||||
<form method="post" action="/" enctype="multipart/form-data" class="dashboard-modal__form" id="day-summary-form">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="form_name" value="save_day_summary">
|
||||
<input type="hidden" name="date" value="<?= e((string) $dayEntry['date']) ?>">
|
||||
|
||||
<h2 class="dashboard-modal__title"><?= e(format_display_date((string) $dayEntry['date'], false)) ?></h2>
|
||||
<p class="dashboard-modal__subtitle">Deine Tagesbilanz</p>
|
||||
|
||||
<label class="dashboard-modal__textarea">
|
||||
<textarea name="summary_comment" rows="5" placeholder="Fasse deinen Tag zusammen"><?= e($summaryComment) ?></textarea>
|
||||
</label>
|
||||
|
||||
<div class="overlay-signal-grid overlay-signal-grid--summary-row">
|
||||
<?php foreach (['summary_mood' => ['Stimmung', $summaryMood], 'summary_energy' => ['Energie', $summaryEnergy], 'summary_stress' => ['Stress', $summaryStress]] as $field => [$label, $value]): ?>
|
||||
<?php $metric = str_replace('summary_', '', $field); ?>
|
||||
<div class="overlay-signal-card overlay-signal-card--inline" data-stepper data-stepper-metric="<?= e($metric) ?>">
|
||||
<div>
|
||||
<h3><?= e($label) ?></h3>
|
||||
<p>
|
||||
<?= e(signal_labels_for_metric($metric)[$value]) ?>
|
||||
</p>
|
||||
</div>
|
||||
<div class="overlay-signal-card__control">
|
||||
<div class="overlay-signal-card__ring tone-<?= e(signal_value_class($value)) ?>">
|
||||
<span data-stepper-value><?= $value >= 0 ? '+' : '' ?><?= e((string) $value) ?></span>
|
||||
</div>
|
||||
<div class="overlay-signal-card__buttons">
|
||||
<button type="button" data-stepper-minus>-</button>
|
||||
<button type="button" data-stepper-plus>+</button>
|
||||
</div>
|
||||
<input type="hidden" name="<?= e($field) ?>" value="<?= e((string) $value) ?>" data-stepper-input>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<fieldset class="moment-alcohol-field moment-alcohol-field--summary">
|
||||
<legend>Alkohol</legend>
|
||||
<div class="moment-choice-row">
|
||||
<label class="moment-choice-pill">
|
||||
<input type="radio" name="summary_alcohol" value="1" <?= $summaryAlcohol ? 'checked' : '' ?>>
|
||||
<span>Ja</span>
|
||||
</label>
|
||||
<label class="moment-choice-pill">
|
||||
<input type="radio" name="summary_alcohol" value="0" <?= !$summaryAlcohol ? 'checked' : '' ?>>
|
||||
<span>Nein</span>
|
||||
</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<label>
|
||||
<span>Tagesbild</span>
|
||||
<input type="file" name="background_image" accept="image/jpeg,image/png,image/webp">
|
||||
</label>
|
||||
</form>
|
||||
|
||||
<?php if ($dayBackground !== null): ?>
|
||||
<form method="post" action="/" class="dashboard-modal__secondary-action">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="form_name" value="remove_background">
|
||||
<input type="hidden" name="date" value="<?= e((string) $dayEntry['date']) ?>">
|
||||
<button class="ghost-button" type="submit">Bild entfernen</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="dashboard-overlay" data-moment-overlay hidden>
|
||||
<div class="dashboard-overlay__backdrop" data-moment-overlay-close></div>
|
||||
<section class="dashboard-modal glass-panel dashboard-modal--moment" role="dialog" aria-modal="true" data-moment-modal>
|
||||
<div class="dashboard-modal__controls">
|
||||
<button class="dashboard-modal__round" type="button" data-moment-overlay-close>×</button>
|
||||
<button class="dashboard-modal__round dashboard-modal__round--confirm" type="submit" form="moment-form" data-moment-submit disabled>✓</button>
|
||||
</div>
|
||||
|
||||
<div data-moment-step="choose">
|
||||
<h2 class="dashboard-modal__title">Neuer Moment</h2>
|
||||
<div class="moment-type-grid">
|
||||
<?php foreach ($dashboardEventTypes as $type => $meta): ?>
|
||||
<?php if ($type === 'alcohol') { continue; } ?>
|
||||
<button class="moment-type-card" type="button" data-moment-type-choice="<?= e($type) ?>">
|
||||
<img src="<?= e((string) $meta['icon']) ?>" alt="">
|
||||
<span><?= e((string) $meta['label']) ?></span>
|
||||
</button>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form method="post" action="/" class="dashboard-modal__form" id="moment-form" data-moment-step="form" hidden>
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="form_name" value="add_event" data-moment-form-name>
|
||||
<input type="hidden" name="date" value="<?= e((string) $dayEntry['date']) ?>">
|
||||
<input type="hidden" name="event_id" value="" data-moment-event-id>
|
||||
<input type="hidden" name="event_type" value="event" data-moment-type-input>
|
||||
<input type="hidden" name="event_unit" value="" data-event-unit>
|
||||
<input type="hidden" name="event_walk_mode" value="time" data-walk-mode-input>
|
||||
|
||||
<div class="dashboard-modal__heading-row">
|
||||
<div>
|
||||
<p class="dashboard-modal__subtitle" data-moment-type-label>Neuer Moment</p>
|
||||
<h2 class="dashboard-modal__title">Was ist passiert?</h2>
|
||||
</div>
|
||||
<button class="ghost-button ghost-button--small" type="button" data-moment-back>Typ ändern</button>
|
||||
</div>
|
||||
|
||||
<label class="dashboard-modal__textarea">
|
||||
<textarea name="event_comment" rows="4" placeholder="Was hast du erlebt?" data-moment-comment></textarea>
|
||||
</label>
|
||||
|
||||
<div class="field-grid field-grid--two">
|
||||
<label>
|
||||
<span>Erfasst um</span>
|
||||
<input type="time" name="event_time" value="<?= e(date('H:i')) ?>" required>
|
||||
</label>
|
||||
<label data-moment-value-field>
|
||||
<span data-moment-value-label>Wert</span>
|
||||
<input type="number" name="event_value" min="0" max="50000" step="0.25" placeholder="optional" data-moment-value-input>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<fieldset data-moment-sport-field hidden>
|
||||
<legend>Sportart</legend>
|
||||
<input type="hidden" name="event_sport_type_id" value="">
|
||||
<div class="moment-type-grid moment-type-grid--sport">
|
||||
<?php foreach ($dashboardSportTypes as $sportType): ?>
|
||||
<button class="moment-type-card moment-type-card--sport" type="button" data-sport-choice="<?= e((string) ($sportType['id'] ?? '')) ?>">
|
||||
<img src="<?= e(sport_icon_path((string) ($sportType['icon'] ?? 'run'))) ?>" alt="">
|
||||
<span><?= e((string) ($sportType['label'] ?? '')) ?></span>
|
||||
</button>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="moment-alcohol-field" data-moment-walk-field hidden>
|
||||
<legend>Spaziergang als</legend>
|
||||
<div class="moment-choice-row">
|
||||
<label class="moment-choice-pill"><input type="radio" name="event_walk_mode" value="time" checked><span>Dauer</span></label>
|
||||
<label class="moment-choice-pill"><input type="radio" name="event_walk_mode" value="steps"><span>Schritte</span></label>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="moment-alcohol-field" data-moment-alcohol-field hidden>
|
||||
<legend>Heute Alkohol getrunken?</legend>
|
||||
<div class="moment-choice-row">
|
||||
<label class="moment-choice-pill">
|
||||
<input type="radio" name="event_consumed" value="1" checked>
|
||||
<span>Ja</span>
|
||||
</label>
|
||||
<label class="moment-choice-pill">
|
||||
<input type="radio" name="event_consumed" value="0">
|
||||
<span>Nein</span>
|
||||
</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div class="overlay-signal-grid overlay-signal-grid--summary-row overlay-signal-grid--moment">
|
||||
<?php foreach (['event_mood' => ['Stimmung', 0], 'event_energy' => ['Energie', 0], 'event_stress' => ['Stress', 0]] as $field => [$label, $value]): ?>
|
||||
<?php $metric = str_replace('event_', '', $field); ?>
|
||||
<div class="overlay-signal-card overlay-signal-card--inline overlay-signal-card--moment" data-stepper data-stepper-metric="<?= e($metric) ?>">
|
||||
<div>
|
||||
<h3><?= e($label) ?></h3>
|
||||
</div>
|
||||
<div class="overlay-signal-card__control">
|
||||
<div class="overlay-signal-card__ring tone-zero">
|
||||
<span data-stepper-value><?= $value >= 0 ? '+' : '' ?><?= e((string) $value) ?></span>
|
||||
</div>
|
||||
<div class="overlay-signal-card__buttons">
|
||||
<button type="button" data-stepper-minus>-</button>
|
||||
<button type="button" data-stepper-plus>+</button>
|
||||
</div>
|
||||
<input type="hidden" name="<?= e($field) ?>" value="<?= e((string) $value) ?>" data-stepper-input>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form method="post" action="/" class="dashboard-modal__secondary-action" data-moment-delete-form hidden>
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="form_name" value="delete_event">
|
||||
<input type="hidden" name="date" value="<?= e((string) $dayEntry['date']) ?>">
|
||||
<input type="hidden" name="event_id" value="" data-moment-delete-id>
|
||||
<button class="ghost-button" type="submit">Moment löschen</button>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
<?php elseif ($dashboardView === 'week'): ?>
|
||||
<section class="dashboard-range-view dashboard-range-view--week">
|
||||
<header class="dashboard-range-view__hero">
|
||||
<p class="eyebrow">Wochenansicht</p>
|
||||
<h1><?= e($dashboardWeek['title']) ?></h1>
|
||||
<h2><?= e($dashboardWeek['range']) ?></h2>
|
||||
</header>
|
||||
|
||||
<div class="range-period-rail range-period-rail--week">
|
||||
<?php foreach (($dashboardWeek['periods'] ?? [$dashboardWeek]) as $week): ?>
|
||||
<article class="range-period-panel<?= !empty($week['is_selected']) ? ' is-selected' : '' ?>">
|
||||
<header class="range-period-panel__head">
|
||||
<a href="/?view=week&date=<?= e(rawurlencode((string) ($week['key'] ?? $dashboardDate))) ?>">
|
||||
<h3><?= e((string) $week['title']) ?></h3>
|
||||
<p><?= e((string) $week['range']) ?></p>
|
||||
</a>
|
||||
</header>
|
||||
|
||||
<nav class="range-score-strip range-score-strip--week glass-panel" aria-label="Tage dieser Woche">
|
||||
<?php foreach ($week['days'] as $day): ?>
|
||||
<a class="range-score-day<?= !empty($day['is_current']) ? ' is-current' : '' ?><?= empty($day['has_content']) ? ' is-empty' : '' ?>" href="/?view=week&date=<?= e(rawurlencode((string) $day['date'])) ?>" title="<?= e((string) $day['weekday']) ?>">
|
||||
<span class="compare-day__line<?= !empty($day['is_current']) ? ' is-primary' : '' ?> score-<?= e((string) ($day['score_level'] ?? 'empty')) ?> compare-tone-<?= e((string) ($day['line_tone'] ?? 'empty')) ?>">
|
||||
<span class="compare-day__marker"></span>
|
||||
</span>
|
||||
<span class="range-score-day__label"><?= e((string) $day['day']) ?></span>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</nav>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<?php $weekDetailDays = array_values(array_filter($dashboardWeek['days'], static fn (array $day): bool => !empty($day['has_content']))); ?>
|
||||
<?php if ($weekDetailDays !== []): ?>
|
||||
<div class="range-day-list">
|
||||
<?php foreach ($weekDetailDays as $day): ?>
|
||||
<?php
|
||||
$entry = is_array($day['entry'] ?? null) ? $day['entry'] : null;
|
||||
$events = $entry !== null && is_array($entry['events'] ?? null) ? $entry['events'] : [];
|
||||
$summaryText = $entry !== null ? trim((string) ($entry['summary']['comment'] ?? $entry['summary_comment'] ?? '')) : '';
|
||||
$dayTone = (string) ($day['line_tone'] ?? 'empty');
|
||||
$dayImage = $entry !== null && is_string($entry['background_image_url'] ?? null) ? (string) $entry['background_image_url'] : null;
|
||||
?>
|
||||
<a class="range-day-card range-day-card--<?= e($dayTone) ?><?= empty($day['has_content']) ? ' is-empty' : '' ?> glass-panel" href="/?view=day&date=<?= e(rawurlencode((string) $day['date'])) ?>">
|
||||
<?php if ($dayImage !== null): ?>
|
||||
<img class="range-day-card__image" src="<?= e($dayImage) ?>" alt="">
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="range-day-card__body">
|
||||
<p class="eyebrow"><?= e((string) $day['weekday']) ?></p>
|
||||
<p class="range-day-card__summary"><?= $summaryText !== '' ? e($summaryText) : 'Noch keine Tagesbilanz.' ?></p>
|
||||
|
||||
<?php if ($events !== []): ?>
|
||||
<ul class="range-moment-list">
|
||||
<?php foreach ($events as $event): ?>
|
||||
<?php if (!is_array($event)) { continue; } ?>
|
||||
<?php
|
||||
$eventType = (string) ($event['type'] ?? 'event');
|
||||
$eventScore = signal_combo_score($event['mood'] ?? 0, $event['energy'] ?? 0, $event['stress'] ?? 0);
|
||||
$eventTone = signal_value_class($eventScore);
|
||||
$sportType = $eventType === 'sport' ? find_sport_type($settings, (string) ($event['sport_type_id'] ?? '')) : null;
|
||||
$eventValue = (float) ($event['value'] ?? 0);
|
||||
$eventValueText = $eventValue > 0 ? rtrim(rtrim(number_format($eventValue, 2, ',', '.'), '0'), ',') . ' ' . (string) ($event['unit'] ?? '') : '';
|
||||
$eventTitle = trim((string) ($event['comment'] ?? '')) !== '' ? trim((string) $event['comment']) : day_event_type_label($eventType);
|
||||
$eventDetail = $eventValueText;
|
||||
|
||||
if ($eventType === 'sport') {
|
||||
$eventTitle = (string) ($sportType['label'] ?? 'Sport');
|
||||
}
|
||||
|
||||
if ($eventType === 'sleep') {
|
||||
$eventTitle = 'Schlaf';
|
||||
}
|
||||
?>
|
||||
<li class="range-moment-list__item range-moment-list__item--<?= e($eventTone) ?>">
|
||||
<span class="range-moment-list__bullet" aria-hidden="true"></span>
|
||||
<span>
|
||||
<strong><?= e($eventTitle) ?></strong>
|
||||
<?php if ($eventDetail !== ''): ?>
|
||||
<span><?= e($eventDetail) ?></span>
|
||||
<?php endif; ?>
|
||||
</span>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
<?php else: ?>
|
||||
<section class="dashboard-range-view dashboard-range-view--month">
|
||||
<header class="dashboard-range-view__hero">
|
||||
<p class="eyebrow">Monatsansicht</p>
|
||||
<h1><?= e($dashboardMonth['title']) ?></h1>
|
||||
</header>
|
||||
|
||||
<div class="range-period-rail range-period-rail--month">
|
||||
<?php foreach (($dashboardMonth['periods'] ?? [$dashboardMonth]) as $month): ?>
|
||||
<article class="range-period-panel<?= !empty($month['is_selected']) ? ' is-selected' : '' ?>">
|
||||
<header class="range-period-panel__head">
|
||||
<a href="/?view=month&date=<?= e(rawurlencode((string) ($month['key'] ?? $dashboardDate))) ?>">
|
||||
<h3><?= e((string) $month['title']) ?></h3>
|
||||
</a>
|
||||
</header>
|
||||
|
||||
<nav class="range-score-strip range-score-strip--month glass-panel" aria-label="Tage dieses Monats">
|
||||
<?php foreach ($month['days'] as $day): ?>
|
||||
<a class="range-score-day<?= empty($day['has_content']) ? ' is-empty' : '' ?><?= !empty($day['is_future']) ? ' is-future' : '' ?>" href="/?view=month&date=<?= e(rawurlencode((string) $day['date'])) ?>" title="<?= e((string) $day['weekday']) ?>">
|
||||
<span class="compare-day__line score-<?= e((string) ($day['score_level'] ?? 'empty')) ?> compare-tone-<?= e((string) ($day['line_tone'] ?? 'empty')) ?>">
|
||||
<span class="compare-day__marker"></span>
|
||||
</span>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</nav>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<?php $monthDetailDays = array_values(array_filter($dashboardMonth['days'], static function (array $day): bool {
|
||||
$entry = is_array($day['entry'] ?? null) ? $day['entry'] : null;
|
||||
$summaryText = $entry !== null ? trim((string) ($entry['summary']['comment'] ?? $entry['summary_comment'] ?? '')) : '';
|
||||
|
||||
return !empty($day['has_content']) || $summaryText !== '';
|
||||
})); ?>
|
||||
<?php if ($monthDetailDays !== []): ?>
|
||||
<div class="range-day-list range-day-list--month">
|
||||
<?php foreach ($monthDetailDays as $day): ?>
|
||||
<?php
|
||||
$entry = is_array($day['entry'] ?? null) ? $day['entry'] : null;
|
||||
$summaryText = $entry !== null ? trim((string) ($entry['summary']['comment'] ?? $entry['summary_comment'] ?? '')) : '';
|
||||
$dayTone = (string) ($day['line_tone'] ?? 'empty');
|
||||
?>
|
||||
<a class="range-day-card range-day-card--summary-only range-day-card--<?= e($dayTone) ?> glass-panel" href="/?view=day&date=<?= e(rawurlencode((string) $day['date'])) ?>">
|
||||
<div class="range-day-card__body">
|
||||
<p class="eyebrow"><?= e((string) $day['weekday']) ?></p>
|
||||
<p class="range-day-card__summary"><?= $summaryText !== '' ? e($summaryText) : 'Tagesbilanz' ?></p>
|
||||
</div>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="dashboard-overlay" data-settings-menu-overlay hidden>
|
||||
<div class="dashboard-overlay__backdrop" data-settings-menu-close></div>
|
||||
<section class="dashboard-modal dashboard-modal--settings glass-panel" role="dialog" aria-modal="true">
|
||||
<div class="dashboard-modal__controls">
|
||||
<button class="dashboard-modal__round" type="button" data-settings-menu-close>×</button>
|
||||
</div>
|
||||
|
||||
<h2 class="dashboard-modal__title">Einstellungen und Bereiche</h2>
|
||||
<div class="settings-menu-grid">
|
||||
<a class="options-menu-card" href="/options?panel=score"><strong>Score anpassen</strong><span>Multiplikatoren und Tageslogik</span></a>
|
||||
<a class="options-menu-card" href="/options?panel=sports"><strong>Sportarten anpassen</strong><span>Eigene Sportarten und Bonuspunkte</span></a>
|
||||
<a class="options-menu-card" href="/options?panel=walk"><strong>Spaziergang anpassen</strong><span>Zeit oder Schritte auswerten</span></a>
|
||||
<a class="options-menu-card" href="/options?panel=reminders"><strong>Erinnerungen setzen</strong><span>Push und tägliche Erinnerung</span></a>
|
||||
<a class="options-menu-card" href="/options?panel=ratings"><strong>Bewertungsskala ändern</strong><span>Labels und Schutzregeln</span></a>
|
||||
<a class="options-menu-card" href="/options?panel=stats"><strong>Statistik</strong><span>Verlauf und Aktivität</span></a>
|
||||
<?php if (!empty($authUser['is_admin'])): ?>
|
||||
<a class="options-menu-card" href="/options?panel=users"><strong>Neue Nutzer anlegen</strong><span>Accounts und Adminrechte</span></a>
|
||||
<?php endif; ?>
|
||||
<form method="post" action="/logout" class="options-logout-form">
|
||||
<?= csrf_field() ?>
|
||||
<button class="options-menu-card options-menu-card--danger" type="submit"><strong>Abmelden</strong><span>Sitzung sicher beenden</span></button>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user