function ($query) { $query->selectRaw(' timesheet_id, SUM(hours) as total_hours, SUM(CASE WHEN billed = 1 THEN hours ELSE 0 END) as hours_billed, MIN(date) as earliest_date, MAX(date) as latest_date ') ->groupBy('timesheet_id'); }])->get(); // Sort timesheets by the updated_at timestamp of the latest entry $timesheets = $timesheets->sortByDesc(function ($timesheet) { $latestEntry = $timesheet->entries()->latest('updated_at')->first(); return $latestEntry ? $latestEntry->updated_at : $timesheet->updated_at; })->values(); $snakeCaseData = $timesheets->map(function ($timesheet) { $entryStats = $timesheet->entries->first(); return [ 'id' => $timesheet->id, 'title' => $timesheet->title, 'total_hours' => $entryStats->total_hours ?? 0, 'hours_billed' => $entryStats->hours_billed ?? 0, 'earliest_date' => $entryStats->earliest_date ?? null, 'latest_date' => $entryStats->latest_date ?? null, 'created_at' => $timesheet->created_at->toISOString(), 'updated_at' => $timesheet->updated_at->toISOString(), ]; }); return ApiDataTransformer::snakeToCamel($snakeCaseData->toArray()); } /** * Store a newly created resource in storage. */ public function store(Request $request) { $validated = $request->validate([ 'title' => 'required|string|max:255', ]); $snakeCaseData = Timesheet::create($validated); return ApiDataTransformer::snakeToCamel($snakeCaseData->toArray()); } /** * Display the specified resource. */ public function show(Timesheet $timesheet) { return Inertia::render('Timesheets', [ 'timesheetData' => $this->index() ]); } /** * Update the specified resource in storage. */ public function update(Request $request, Timesheet $timesheet) { $validatedData = $request->validate([ 'title' => 'required|string|max:255', ]); // Convert camelCase to snake_case $snakeCaseData = ApiDataTransformer::camelToSnake($validatedData); $timesheet->update($snakeCaseData); return $timesheet; } /** * Remove the specified resource from storage. */ public function destroy(Timesheet $timesheet) { $timesheet->delete(); return response()->noContent(); } }