function ($query) { $query->where('notable_type', 'App\Models\PipelineItem'); }]) ->withCount(['todos' => function ($query) { $query->where('todoable_type', 'App\Models\PipelineItem'); }]) ->orderBy('position') ->get(); $pipelineItemsArray = $pipelineItems->map(function ($item) { $itemArray = $item->toArray(); $itemArray['next_todo_due_date'] = $item->todos->first()?->due_date?->toISOString() ?? null; unset($itemArray['todos']); // Remove the todos array return $itemArray; }); return ApiDataTransformer::snakeToCamel($pipelineItemsArray->toArray()); } /** * Display a listing of the resource. */ public function single(int $id) { $pipelineItem = PipelineItem ::with(['notes' => function ($query) { $query->where('notable_type', 'App\Models\PipelineItem')->orderBy('created_at', 'desc'); }])->with(['todos' => function ($query) { $query->where('todoable_type', 'App\Models\PipelineItem')->orderBy('due_date', 'asc'); }])->orderBy('position')->findOrFail($id); return ApiDataTransformer::snakeToCamel($pipelineItem->toArray()); } /** * Store a newly created resource in storage. */ public function store(Request $request) { $validatedData = $request->validate([ 'pipelineLaneId' => 'required|integer|exists:pipeline_lanes,id', 'title' => 'required|string', 'position' => 'required|integer|min:0', 'expectedRevenue' => 'nullable|numeric', 'dueDate' => 'nullable|date', 'description' => 'nullable|string', ]); $pipelineItem = PipelineItem::create($validatedData); return ApiDataTransformer::snakeToCamel($pipelineItem->toArray()); } /** * Update the specified resource in storage. */ public function update(Request $request, int $id) { $validatedData = $request->validate([ 'pipelineLaneId' => 'sometimes|integer|exists:pipeline_lanes,id', 'title' => 'sometimes|string', 'position' => 'sometimes|integer|min:0', 'expectedRevenue' => 'nullable|numeric', 'dueDate' => 'nullable|date', 'description' => 'nullable|string', ]); $snakeCaseData = ApiDataTransformer::camelToSnake($validatedData); DB::beginTransaction(); try { $pipelineItem = PipelineItem::findOrFail($id); $snakeCaseData = ApiDataTransformer::camelToSnake($validatedData); $pipelineItem->update($snakeCaseData); DB::commit(); return response()->noContent(); } catch (\Exception $e) { DB::rollBack(); return response()->json(['error' => 'Failed to update pipeline item', 'message' => $e->getMessage()], 500); } } /** * Remove the specified resource from storage. */ public function delete(int $id) { PipelineItem::findOrFail($id)->delete(); return response()->noContent(); } }