validate([ 'status' => ['nullable', 'in:active,inactive'], 'q' => ['nullable', 'string', 'max:100'], ]); $areas = ServiceArea::query() ->when($request->filled('tenant_id'), function ($q) use ($request) { $q->withoutGlobalScopes()->where('tenant_id', $request->integer('tenant_id')); }) ->withCount('barangays') ->when($request->filled('status'), fn ($q) => $q->where('status', $request->string('status'))) ->when($request->filled('q'), fn ($q) => $q->where('name', 'like', '%'.$request->string('q').'%')) ->orderBy('name') ->get(); return $this->ok(ServiceAreaResource::collection($areas)); } public function store(StoreServiceAreaRequest $request): JsonResponse { $data = $request->validated(); $barangayIds = $data['barangay_ids'] ?? []; unset($data['barangay_ids']); if (! empty($data['boundary'])) { $data['boundary'] = $this->buildPolygon($data['boundary']); } $area = DB::transaction(function () use ($data, $barangayIds) { $area = ServiceArea::create($data); if (! empty($barangayIds)) { $area->barangays()->sync($barangayIds); } return $area; }); return $this->created( new ServiceAreaResource($area->loadCount('barangays')), 'Service area created', ); } public function show(ServiceArea $serviceArea): JsonResponse { $serviceArea->load(['barangays.cityMunicipality.province']) ->loadCount('barangays'); return $this->ok(new ServiceAreaResource($serviceArea)); } public function update(UpdateServiceAreaRequest $request, ServiceArea $serviceArea): JsonResponse { $data = $request->validated(); $barangayIds = $data['barangay_ids'] ?? null; unset($data['barangay_ids']); if (array_key_exists('boundary', $data)) { $data['boundary'] = ! empty($data['boundary']) ? $this->buildPolygon($data['boundary']) : null; } DB::transaction(function () use ($serviceArea, $data, $barangayIds) { $serviceArea->update($data); if ($barangayIds !== null) { $serviceArea->barangays()->sync($barangayIds); } }); return $this->ok( new ServiceAreaResource($serviceArea->fresh()->loadCount('barangays')), 'Service area updated', ); } private function buildPolygon(array $points): Polygon { $ring = array_map( fn ($p) => new Point((float) $p['lat'], (float) $p['lng'], 4326), $points, ); $first = $ring[0]; $last = $ring[count($ring) - 1]; if ($first->latitude !== $last->latitude || $first->longitude !== $last->longitude) { $ring[] = new Point($first->latitude, $first->longitude, 4326); } return new Polygon([new LineString($ring)], 4326); } public function destroy(ServiceArea $serviceArea): JsonResponse { $serviceArea->delete(); return $this->ok(null, 'Service area deleted'); } public function attachBarangays(AttachBarangaysRequest $request, ServiceArea $serviceArea): JsonResponse { $serviceArea->barangays()->syncWithoutDetaching($request->validated('barangay_ids')); return $this->ok( new ServiceAreaResource($serviceArea->load('barangays')->loadCount('barangays')), 'Barangays attached', ); } public function detachBarangay(ServiceArea $serviceArea, Barangay $barangay): JsonResponse { $serviceArea->barangays()->detach($barangay->id); return $this->ok(null, 'Barangay detached'); } }