'required|date|unique:technician_workloads,workload_date,NULL,id,technician_id,' . null, 'scheduled_hours' => 'required|numeric|min:0|max:24', 'actual_hours' => 'required|numeric|min:0|max:24', 'overtime_hours' => 'nullable|numeric|min:0|max:12', 'jobs_assigned' => 'required|integer|min:0', 'jobs_completed' => 'required|integer|min:0', 'notes' => 'nullable|string|max:1000' ]; public function mount() { $this->setWeekView(); $this->workload_date = now()->format('Y-m-d'); } #[On('manage-workload')] public function manageWorkload($technicianId) { $this->technicianId = $technicianId; $this->technician = Technician::with('workloads')->findOrFail($technicianId); $this->showModal = true; $this->resetForm(); } public function updatedViewMode() { switch ($this->viewMode) { case 'week': $this->setWeekView(); break; case 'month': $this->setMonthView(); break; // custom stays as is } } public function setWeekView() { $this->startDate = now()->startOfWeek()->format('Y-m-d'); $this->endDate = now()->endOfWeek()->format('Y-m-d'); } public function setMonthView() { $this->startDate = now()->startOfMonth()->format('Y-m-d'); $this->endDate = now()->endOfMonth()->format('Y-m-d'); } public function previousPeriod() { if ($this->viewMode === 'week') { $start = Carbon::parse($this->startDate)->subWeek(); $this->startDate = $start->format('Y-m-d'); $this->endDate = $start->endOfWeek()->format('Y-m-d'); } elseif ($this->viewMode === 'month') { $start = Carbon::parse($this->startDate)->subMonth()->startOfMonth(); $this->startDate = $start->format('Y-m-d'); $this->endDate = $start->endOfMonth()->format('Y-m-d'); } } public function nextPeriod() { if ($this->viewMode === 'week') { $start = Carbon::parse($this->startDate)->addWeek(); $this->startDate = $start->format('Y-m-d'); $this->endDate = $start->endOfWeek()->format('Y-m-d'); } elseif ($this->viewMode === 'month') { $start = Carbon::parse($this->startDate)->addMonth()->startOfMonth(); $this->startDate = $start->format('Y-m-d'); $this->endDate = $start->endOfMonth()->format('Y-m-d'); } } public function addWorkloadRecord() { $this->resetForm(); $this->editing = false; } public function editWorkload($workloadId) { $workload = TechnicianWorkload::findOrFail($workloadId); $this->workloadId = $workload->id; $this->workload_date = $workload->workload_date->format('Y-m-d'); $this->scheduled_hours = $workload->scheduled_hours; $this->actual_hours = $workload->actual_hours; $this->overtime_hours = $workload->overtime_hours; $this->jobs_assigned = $workload->jobs_assigned; $this->jobs_completed = $workload->jobs_completed; $this->notes = $workload->notes; $this->editing = true; } public function saveWorkload() { // Update unique rule for editing if ($this->editing) { $this->rules['workload_date'] = 'required|date|unique:technician_workloads,workload_date,' . $this->workloadId . ',id,technician_id,' . $this->technicianId; } else { $this->rules['workload_date'] = 'required|date|unique:technician_workloads,workload_date,NULL,id,technician_id,' . $this->technicianId; } $this->validate(); $data = [ 'technician_id' => $this->technicianId, 'workload_date' => $this->workload_date, 'scheduled_hours' => $this->scheduled_hours, 'actual_hours' => $this->actual_hours, 'overtime_hours' => $this->overtime_hours ?? 0, 'jobs_assigned' => $this->jobs_assigned, 'jobs_completed' => $this->jobs_completed, 'notes' => $this->notes, ]; if ($this->editing) { $workload = TechnicianWorkload::findOrFail($this->workloadId); $workload->update($data); // Recalculate rates $workload->utilization_rate = $workload->calculateUtilizationRate(); $workload->efficiency_rate = $workload->calculateEfficiencyRate(); $workload->save(); session()->flash('message', 'Workload record updated successfully!'); } else { $workload = TechnicianWorkload::create($data); // Calculate rates $workload->utilization_rate = $workload->calculateUtilizationRate(); $workload->efficiency_rate = $workload->calculateEfficiencyRate(); $workload->save(); session()->flash('message', 'Workload record added successfully!'); } $this->technician->refresh(); $this->resetForm(); } public function deleteWorkload($workloadId) { TechnicianWorkload::findOrFail($workloadId)->delete(); $this->technician->refresh(); session()->flash('message', 'Workload record deleted successfully!'); } public function closeModal() { $this->showModal = false; $this->resetForm(); } public function resetForm() { $this->workloadId = null; $this->workload_date = now()->format('Y-m-d'); $this->scheduled_hours = 8.0; $this->actual_hours = 0.0; $this->overtime_hours = 0.0; $this->jobs_assigned = 0; $this->jobs_completed = 0; $this->notes = ''; $this->editing = false; $this->resetErrorBag(); } public function getFilteredWorkloadsProperty() { if (!$this->technician) return collect(); return $this->technician->workloads() ->whereBetween('workload_date', [$this->startDate, $this->endDate]) ->orderBy('workload_date') ->get(); } public function getWorkloadStatsProperty() { $workloads = $this->filteredWorkloads; if ($workloads->isEmpty()) { return [ 'total_scheduled' => 0, 'total_actual' => 0, 'total_overtime' => 0, 'avg_utilization' => 0, 'avg_efficiency' => 0, 'total_jobs_assigned' => 0, 'total_jobs_completed' => 0, 'completion_rate' => 0 ]; } $totalJobsAssigned = $workloads->sum('jobs_assigned'); $totalJobsCompleted = $workloads->sum('jobs_completed'); return [ 'total_scheduled' => $workloads->sum('scheduled_hours'), 'total_actual' => $workloads->sum('actual_hours'), 'total_overtime' => $workloads->sum('overtime_hours'), 'avg_utilization' => round($workloads->avg('utilization_rate'), 1), 'avg_efficiency' => round($workloads->avg('efficiency_rate'), 1), 'total_jobs_assigned' => $totalJobsAssigned, 'total_jobs_completed' => $totalJobsCompleted, 'completion_rate' => $totalJobsAssigned > 0 ? round(($totalJobsCompleted / $totalJobsAssigned) * 100, 1) : 0 ]; } public function render() { return view('livewire.technician-management.workload-management', [ 'filteredWorkloads' => $this->filteredWorkloads, 'workloadStats' => $this->workloadStats ]); } }