filter; $selectedPlant = session('selected_plant'); $selectedLine = session('selected_line'); if (!$selectedPlant || !$selectedLine) { return [ 'datasets' => [], 'labels' => [], ]; } // Set time range based on active filter if ($activeFilter === 'yesterday') { $startDate = now()->subDay()->setTime(8, 0, 0); $endDate = now()->setTime(8, 0, 0); } elseif ($activeFilter === 'this_week') { $startDate = now()->startOfWeek()->setTime(8, 0, 0); $endDate = now()->endOfWeek()->addDay()->setTime(8, 0, 0); } elseif ($activeFilter === 'this_month') { $startDate = now()->startOfMonth(); $endDate = now()->endOfMonth(); } else { $startDate = now()->setTime(8, 0, 0); $endDate = now()->copy()->addDay()->setTime(8, 0, 0); } // Fetch stop reason data // treats minutes as a visual decimal (e.g., 15 mins = 0.15) $query = \DB::table('production_line_stops') ->join('line_stops as ls', 'production_line_stops.linestop_id', '=', 'ls.id') ->join('lines', 'production_line_stops.line_id', '=', 'lines.id') ->join('plants', 'production_line_stops.plant_id', '=', 'plants.id') ->select( 'ls.code', 'ls.reason', \DB::raw(" SUM(production_line_stops.stop_hour) as total_stop_hours, SUM(production_line_stops.stop_min) as total_stop_minutes ") ) ->when($selectedPlant, fn($q) => $q->where('plants.id', $selectedPlant)) ->when($selectedLine, fn($q) => $q->where('lines.id', $selectedLine)) ->whereBetween('production_line_stops.created_at', [$startDate, $endDate]) ->groupBy('ls.code', 'ls.reason') //->orderByDesc('total_hours') ->get(); // Handle empty data gracefully if ($query->isEmpty()) { return [ 'datasets' => [[ 'label' => 'Line Stop Reasons', 'data' => [1], 'backgroundColor' => ['rgba(200, 200, 200, 0.4)'], 'borderColor' => ['rgba(200, 200, 200, 1)'], 'borderWidth' => 1, ]], 'labels' => ['No Data'], ]; } $labels = []; $data = []; $backgroundColors = []; $borderColors = []; foreach ($query as $row) { // --- STOP TIME (HH.MM format) --- $stopHours = $row->total_stop_hours; $stopMinutes = $row->total_stop_minutes; $visualTotal = $stopHours + ($stopMinutes / 100); // e.g., 0.15 (15 mins), 1.30 (1h 30m) // --- RUNTIME (HH.MM format) --- // 1. Convert stop time to total minutes $totalStopMinutes = ($stopHours * 60) + $stopMinutes;// Using 60 for minutes conversion // Calculate remaining minutes (1440 = 24 hours) $remainingMinutes = 1440 - $totalStopMinutes; // Convert back to "HH.MM" format (e.g., 22.59 = 22 hours 59 minutes) $runtimeHours = floor($remainingMinutes / 60); $runtimeMinutes = $remainingMinutes % 60; $runtime = $runtimeHours + ($runtimeMinutes / 100); // Remaining hours correctly calculated // Labels for stop and runtime $stopLabel = $row->code . ' - ' . $row->reason . ' (Stop)'; $runtimeLabel = $row->code . ' - ' . $row->reason . ' (Runtime)'; // Red bar = visual format using stop time $labels[] = $stopLabel; $data[] = $visualTotal; $backgroundColors[] = 'rgba(255, 99, 132, 0.7)'; $borderColors[] = 'rgba(255, 99, 132, 1)'; // Green bar = correct runtime math $labels[] = $runtimeLabel; $data[] = $runtime; $backgroundColors[] = 'rgba(75, 192, 75, 0.4)'; $borderColors[] = 'rgba(75, 192, 75, 1)'; } return [ 'datasets' => [[ 'label' => 'Line Stop Durations (hrs)', 'data' => $data, 'backgroundColor' => $backgroundColors, 'borderColor' => $borderColors, 'borderWidth' => 1, ]], 'labels' => $labels, ]; } protected function getType(): string { return 'doughnut'; } protected function getFilters(): ?array { return [ 'today' => 'Today', 'yesterday' => 'Yesterday', 'this_week'=> 'This Week', 'this_month'=> 'This Month', ]; } public static function canView(): bool { // Only show on HourlyProduction page return request()->routeIs('filament.pages.production-line-stop-count'); } }