Make sleep phase bars proportional
This commit is contained in:
+26
-1
@@ -926,13 +926,38 @@ body.page-dashboard .content {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 0.25rem;
|
gap: 0.25rem;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
flex-basis: 0;
|
flex: 0 0 var(--sleep-segment-width, auto);
|
||||||
padding: 0.35rem 0.65rem;
|
padding: 0.35rem 0.65rem;
|
||||||
color: rgba(255, 255, 255, 0.94);
|
color: rgba(255, 255, 255, 0.94);
|
||||||
font-size: 0.82rem;
|
font-size: 0.82rem;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sleep-phase-bar__segment::after {
|
||||||
|
content: attr(data-tooltip);
|
||||||
|
position: fixed;
|
||||||
|
left: 50%;
|
||||||
|
bottom: calc(1.2rem + env(safe-area-inset-bottom));
|
||||||
|
z-index: 1400;
|
||||||
|
max-width: min(18rem, calc(100vw - 2rem));
|
||||||
|
padding: 0.55rem 0.75rem;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: rgba(6, 16, 28, 0.92);
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 12px 34px rgba(0, 0, 0, 0.32);
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
transform: translateX(-50%) translateY(0.35rem);
|
||||||
|
transition: opacity 140ms ease, transform 140ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sleep-phase-bar__segment:hover::after,
|
||||||
|
.sleep-phase-bar__segment.is-tooltip-visible::after {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateX(-50%) translateY(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sleep-phase-bar__segment--deep {
|
.sleep-phase-bar__segment--deep {
|
||||||
|
|||||||
@@ -1703,6 +1703,31 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initSleepPhaseTooltips() {
|
||||||
|
document.querySelectorAll(".sleep-phase-bar__segment[data-tooltip]").forEach(segment => {
|
||||||
|
segment.addEventListener("click", event => {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
document.querySelectorAll(".sleep-phase-bar__segment.is-tooltip-visible").forEach(active => {
|
||||||
|
if (active !== segment) {
|
||||||
|
active.classList.remove("is-tooltip-visible");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
segment.classList.toggle("is-tooltip-visible");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener("click", event => {
|
||||||
|
if (event.target.closest(".sleep-phase-bar__segment[data-tooltip]")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.querySelectorAll(".sleep-phase-bar__segment.is-tooltip-visible").forEach(segment => {
|
||||||
|
segment.classList.remove("is-tooltip-visible");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function csrfToken() {
|
function csrfToken() {
|
||||||
return document.querySelector('meta[name="csrf-token"]')?.getAttribute("content") || "";
|
return document.querySelector('meta[name="csrf-token"]')?.getAttribute("content") || "";
|
||||||
}
|
}
|
||||||
@@ -2036,6 +2061,7 @@
|
|||||||
initOptionsPanels();
|
initOptionsPanels();
|
||||||
initHealthImportStatus();
|
initHealthImportStatus();
|
||||||
initMediaLightbox();
|
initMediaLightbox();
|
||||||
|
initSleepPhaseTooltips();
|
||||||
initSportTypeManager();
|
initSportTypeManager();
|
||||||
initPwaShell();
|
initPwaShell();
|
||||||
initPullToRefresh();
|
initPullToRefresh();
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ $optimalSleepHours = max(1.0, min(16.0, (float) ($settings['sleep']['optimal_hou
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$sleepPhaseTotal = max(0.0, array_sum($sleepPhases));
|
$sleepPhaseTotal = max(0.0, array_sum($sleepPhases));
|
||||||
$sleepBarTotal = $eventType === 'sleep' ? max((float) ($item['value'] ?? 0), $sleepPhaseTotal, $optimalSleepHours) : 0.0;
|
$sleepBarTotal = $eventType === 'sleep' ? max((float) ($item['value'] ?? 0), $sleepPhaseTotal, $optimalSleepHours / 0.75) : 0.0;
|
||||||
$sleepPhaseRemainder = max(0.0, $sleepBarTotal - $sleepPhaseTotal);
|
$sleepPhaseRemainder = max(0.0, $sleepBarTotal - $sleepPhaseTotal);
|
||||||
$sleepOptimalPercent = $sleepBarTotal > 0 ? max(0, min(100, ($optimalSleepHours / $sleepBarTotal) * 100)) : 0;
|
$sleepOptimalPercent = $sleepBarTotal > 0 ? max(0, min(100, ($optimalSleepHours / $sleepBarTotal) * 100)) : 0;
|
||||||
?>
|
?>
|
||||||
@@ -191,12 +191,14 @@ $optimalSleepHours = max(1.0, min(16.0, (float) ($settings['sleep']['optimal_hou
|
|||||||
<?php foreach (['deep' => ['Tief', 'deep'], 'rem' => ['REM', 'rem'], 'core' => ['Kern', 'core']] as $phase => [$label, $class]): ?>
|
<?php foreach (['deep' => ['Tief', 'deep'], 'rem' => ['REM', 'rem'], 'core' => ['Kern', 'core']] as $phase => [$label, $class]): ?>
|
||||||
<?php $phaseHours = max(0.0, (float) ($sleepPhases[$phase] ?? 0)); ?>
|
<?php $phaseHours = max(0.0, (float) ($sleepPhases[$phase] ?? 0)); ?>
|
||||||
<?php if ($phaseHours <= 0) { continue; } ?>
|
<?php if ($phaseHours <= 0) { continue; } ?>
|
||||||
<span class="sleep-phase-bar__segment sleep-phase-bar__segment--<?= e($class) ?>" style="flex-grow: <?= e((string) max(0.1, $phaseHours)) ?>" title="<?= e($label) ?>: <?= e(format_points($phaseHours)) ?> h">
|
<?php $phasePercent = $sleepBarTotal > 0 ? max(0.5, min(100, ($phaseHours / $sleepBarTotal) * 100)) : 0; ?>
|
||||||
|
<span class="sleep-phase-bar__segment sleep-phase-bar__segment--<?= e($class) ?>" style="--sleep-segment-width: <?= e((string) $phasePercent) ?>%" title="<?= e($label) ?>: <?= e(format_points($phaseHours)) ?> h" data-tooltip="<?= e($label) ?>: <?= e(format_points($phaseHours)) ?> h">
|
||||||
<strong><?= e($label) ?></strong> <?= e(format_points($phaseHours)) ?> h
|
<strong><?= e($label) ?></strong> <?= e(format_points($phaseHours)) ?> h
|
||||||
</span>
|
</span>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<?php if ($sleepPhaseRemainder > 0): ?>
|
<?php if ($sleepPhaseRemainder > 0): ?>
|
||||||
<span class="sleep-phase-bar__segment sleep-phase-bar__segment--rest" style="flex-grow: <?= e((string) max(0.1, $sleepPhaseRemainder)) ?>" title="Nicht phasenzugeordnet: <?= e(format_points($sleepPhaseRemainder)) ?> h"></span>
|
<?php $remainderPercent = $sleepBarTotal > 0 ? max(0.5, min(100, ($sleepPhaseRemainder / $sleepBarTotal) * 100)) : 0; ?>
|
||||||
|
<span class="sleep-phase-bar__segment sleep-phase-bar__segment--rest" style="--sleep-segment-width: <?= e((string) $remainderPercent) ?>%" title="Bis Ziel-/Skalenende: <?= e(format_points($sleepPhaseRemainder)) ?> h" data-tooltip="Bis Ziel-/Skalenende: <?= e(format_points($sleepPhaseRemainder)) ?> h"></span>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<span class="sleep-phase-bar__target"><span><?= e(format_points($optimalSleepHours)) ?> h</span></span>
|
<span class="sleep-phase-bar__target"><span><?= e(format_points($optimalSleepHours)) ?> h</span></span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user