weekStart = Carbon::now()->startOfWeek()->toDateString(); } public function setWeek(int $delta): void { $this->weekStart = Carbon::parse($this->weekStart)->addWeeks($delta)->toDateString(); } public function data(): array { $start = Carbon::parse($this->weekStart); $end = (clone $start)->addDays(6); $posts = Post::where('is_active', true)->orderBy('sort_order')->get(); $days = collect(range(0, 6))->map(fn ($i) => $start->copy()->addDays($i)); // Appointments grouped by post + day. $appts = Appointment::whereBetween('date', [$start, $end]) ->whereNotIn('status', ['cancelled', 'no_show']) ->get() ->groupBy(fn ($a) => $a->post_id . '|' . $a->date->format('Y-m-d')); // Compute total hours per cell. $matrix = []; foreach ($posts as $post) { $matrix[$post->id] = ['post' => $post, 'days' => []]; foreach ($days as $d) { $key = $post->id . '|' . $d->format('Y-m-d'); $items = $appts->get($key, collect()); $hours = $items->sum(function ($a) { $start = strtotime("1970-01-01 {$a->time_start}"); $end = strtotime("1970-01-01 {$a->time_end}"); return max(0, ($end - $start) / 3600); }); $matrix[$post->id]['days'][$d->format('Y-m-d')] = [ 'date' => $d, 'hours' => $hours, 'count' => $items->count(), ]; } } // Same for appointments without post (drop them on a virtual "—" row). $unposted = $appts->keys()->filter(fn ($k) => str_starts_with($k, '|')); if ($unposted->isNotEmpty()) { $matrix[0] = ['post' => (object) ['id' => 0, 'name' => '— fără pod —', 'color' => '#9ca3af'], 'days' => []]; foreach ($days as $d) { $key = '|' . $d->format('Y-m-d'); $items = $appts->get($key, collect()); $hours = $items->sum(function ($a) { $start = strtotime("1970-01-01 {$a->time_start}"); $end = strtotime("1970-01-01 {$a->time_end}"); return max(0, ($end - $start) / 3600); }); $matrix[0]['days'][$d->format('Y-m-d')] = ['date' => $d, 'hours' => $hours, 'count' => $items->count()]; } } return [ 'matrix' => $matrix, 'days' => $days, 'weekLabel' => $start->format('d.m') . ' – ' . $end->format('d.m.Y'), // Working day = 10h. Color scale: 0..10h → light to red. 'capacity' => 10, ]; } }