@props([ 'title' => 'Sommeil', 'weekPoints' => [], 'monthPoints' => [], ]) @php $datasets = [ 'week' => ['label' => '7 jours', 'points' => $weekPoints], 'month' => ['label' => '30 jours', 'points' => $monthPoints], ]; $chartId = md5($title); $buildAxis = function (float $min, float $max): array { if ($min === $max) { $max = $min + 1; } $rawStep = ($max - $min) / 4; $magnitude = 10 ** floor(log10(max($rawStep, 1))); $normalized = $rawStep / $magnitude; $step = match (true) { $normalized <= 1 => $magnitude, $normalized <= 2 => 2 * $magnitude, $normalized <= 5 => 5 * $magnitude, default => 10 * $magnitude, }; $axisMin = $min < 0 ? floor($min / $step) * $step : 0; $axisMax = max($step, ceil($max / $step) * $step); return [$axisMin, $axisMax, max($step, $axisMax - $axisMin)]; }; $formatHours = function (mixed $minutes): string { $minutes = max(0, (int) $minutes); $hours = intdiv($minutes, 60); $remaining = $minutes % 60; return $hours . 'h' . str_pad((string) $remaining, 2, '0', STR_PAD_LEFT); }; @endphp
merge(['class' => 'dashboard-panel module-chart-card module-chart-card--selectable']) }}>

{{ __('Avec / sans sieste') }}

{{ $title }}

@foreach ($datasets as $key => $dataset) @php $points = collect($dataset['points']); $sleepValues = $points->map(fn ($point) => data_get($point, 'has_data') ? (float) data_get($point, 'sleep', 0) : null)->values(); $totalValues = $points->map(fn ($point) => data_get($point, 'has_data') ? (float) data_get($point, 'total', 0) : null)->values(); $numericValues = $sleepValues ->merge($totalValues) ->filter(fn ($value) => $value !== null) ->map(fn ($value) => (float) $value) ->values(); $labels = $points->map(fn ($point) => (string) data_get($point, 'label', ''))->values(); $minValue = (float) ($numericValues->min() ?? 0); $actualMaxValue = (float) ($numericValues->max() ?? 0); [$axisMin, $maxValue, $rangeValue] = $buildAxis($minValue, $actualMaxValue); $count = max(1, $points->count()); $plotLeft = 2; $plotRight = 98; $plotTop = 8; $plotBottom = 88; $plotWidth = $plotRight - $plotLeft; $plotHeight = $plotBottom - $plotTop; $axisTicks = collect([1, 0.75, 0.5, 0.25, 0])->map(function (float $ratio) use ($axisMin, $rangeValue, $plotTop, $plotHeight) { return [ 'value' => $axisMin + ($rangeValue * $ratio), 'y' => $plotTop + ((1 - $ratio) * $plotHeight), ]; }); $buildSvgData = function ($values) use ($points, $count, $axisMin, $rangeValue, $plotLeft, $plotWidth, $plotBottom, $plotHeight): array { $segments = []; $currentSegment = []; $dotPoints = []; foreach (collect($values)->values() as $index => $value) { if ($value === null) { continue; } $floatValue = (float) $value; $x = $count === 1 ? $plotLeft + ($plotWidth / 2) : $plotLeft + (($index / ($count - 1)) * $plotWidth); $y = $plotBottom - ((($floatValue - $axisMin) / $rangeValue) * $plotHeight); $currentSegment[] = number_format($x, 2, '.', '') . ',' . number_format($y, 2, '.', ''); if ($floatValue > 0) { $dotPoints[] = [ 'x' => $x, 'y' => $y, 'value' => $floatValue, 'label' => (string) data_get($points->get($index), 'label', ''), 'date' => (string) data_get($points->get($index), 'date', ''), ]; } } if ($currentSegment !== []) { $segments[] = implode(' ', $currentSegment); } return [ 'segments' => $segments, 'dots' => $dotPoints, ]; }; $sleepSvg = $buildSvgData($sleepValues); $totalSvg = $buildSvgData($totalValues); $firstLabel = $labels->first(); $lastLabel = $labels->last(); $sleepLast = (int) ($sleepValues->filter(fn ($value) => $value !== null)->last() ?? 0); $totalLast = (int) ($totalValues->filter(fn ($value) => $value !== null)->last() ?? 0); $sleepSum = (int) $sleepValues->filter(fn ($value) => $value !== null)->sum(); $totalSum = (int) $totalValues->filter(fn ($value) => $value !== null)->sum(); $xAxisLabels = $labels ->map(fn (string $label, int $index): array => [ 'label' => $label, 'x' => $labels->count() <= 1 ? 50 : $plotLeft + (($index / max(1, $labels->count() - 1)) * $plotWidth), 'index' => $index, ]) ->values(); @endphp
@foreach ($axisTicks as $tick) @endforeach @foreach ($totalSvg['segments'] as $segment) @endforeach @foreach ($sleepSvg['segments'] as $segment) @endforeach
@foreach ($totalSvg['dots'] as $point) @endforeach @foreach ($sleepSvg['dots'] as $point) @endforeach
{{ $firstLabel }} → {{ $lastLabel }} {{ __('Nuit') }} {{ $formatHours($sleepLast) }} {{ __('Avec sieste') }} {{ $formatHours($totalLast) }} {{ __('Total nuit') }} {{ $formatHours($sleepSum) }} · {{ __('total repos') }} {{ $formatHours($totalSum) }}
@endforeach