integer('size', 10); $query = InsLahan::query()->with(['lahan']); if ($request->filled('search')) { $s = strtolower($request->search); $query->where(function($q) use ($s) { $q->whereRaw('lower(notes) like (?)', ["%{$s}%"]) ->orWhereRaw('lower(plant_cond) like (?)', ["%{$s}%"]); }); } if ($request->filled('sort')) { $sort = $request->sort; $direction = str_starts_with($sort, '-') ? 'desc' : 'asc'; $column = ltrim($sort, '-'); $query->orderBy($column, $direction); } else { $query->latest(); } return response()->json($query->paginate($size)); } public function store(Request $request): JsonResponse { Gate::authorize('petani'); $validated = $request->validate([ 'petani_id' => 'required|exists:users,id', 'lahan_id' => 'required|exists:map_lahan,id', 'air' => 'nullable|string', 'ph' => 'nullable|numeric|between:0,14', 'kelembapan' => 'nullable|string', 'temperature' => 'nullable|string', 'plant_cond' => 'nullable|string', 'catatan' => 'nullable|string', 'foto_url' => 'nullable|string', 'sync_status' => 'nullable|string', ]); $today = Carbon::today(); $inspeksi = InsLahan::updateOrCreate( [ 'petani_id' => $validated['petani_id'], 'lahan_id' => $validated['lahan_id'], 'created_at' => InsLahan::where('lahan_id', $validated['lahan_id']) ->whereDate('created_at', $today) ->exists() ? InsLahan::whereDate('created_at', $today)->first()->created_at : now() ], $validated ); return response()->json([ 'message' => $inspeksi->wasRecentlyCreated ? 'Inspeksi baru berhasil dibuat' : 'Inspeksi hari ini berhasil diperbarui', 'data' => $inspeksi ], $inspeksi->wasRecentlyCreated ? 201 : 200); } public function show(string $id): JsonResponse { $inspeksi = InsLahan::with('lahan')->findOrFail($id); return response()->json($inspeksi); } public function update(Request $request, string $id): JsonResponse { Gate::authorize('petani'); $inspeksi = InsLahan::findOrFail($id); $validated = $request->validate([ 'kadar_air' => 'nullable|string', 'kelembapan' => 'nullable|string', 'temperatur' => 'nullable|string', 'ph' => 'nullable|numeric|between:0,14', 'plant_cond' => 'nullable|string', 'catatan' => 'nullable|string', 'foto_url' => 'nullable|string', ]); $inspeksi->update($validated); return response()->json($inspeksi); } public function destroy(string $id): JsonResponse { Gate::authorize('petani'); InsLahan::findOrFail($id)->delete(); return response()->json(null, 204); } public function batchUpsert(Request $request): JsonResponse { Gate::authorize('petani'); $request->validate([ 'inspections' => 'required|array', 'inspections.*.lahan_id' => 'required', 'inspections.*.petani_id' => 'required', ]); $dataToUpsert = []; foreach ($request->inspections as $item) { $dataToUpsert[] = [ "petani_id" => $item['petani_id'], "lahan_id" => $item['lahan_id'], "air" => $item['air'] ?? null, "ph" => $item['ph'] ?? null, "humidity" => $item['humidity'] ?? null, "temperature" => $item['temperature'] ?? null, "plant_cond" => $item['plant_cond'] ?? null, "notes" => $item['notes'] ?? null, "foto_url" => $item['foto_url'] ?? null, "sync_status" => 'synced', "created_at" => $item['created_at'] ?? now(), "updated_at" => now(), ]; } InsLahan::upsert($dataToUpsert, ['id'], [ 'air', 'ph', 'humidity', 'temperature', 'plant_cond', 'notes', 'foto_url', 'sync_status', 'updated_at' ]); return response()->json(['message' => 'Sinkronisasi batch berhasil'], 200); } }