feat: integrate dynamic geofence fetching, service area spatial boundaries, partner store profiles & editing with Leaflet maps, custom store portal icons, QR distribution charts with geographic/LGU filters, and optimize admin dashboards

This commit is contained in:
Super Admin
2026-07-04 18:30:46 +08:00
parent 8d82674e8f
commit a2cf8c2c75
44 changed files with 3854 additions and 99 deletions

View File

@@ -12,6 +12,9 @@ use App\Models\ServiceArea;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use MatanYadaev\EloquentSpatial\Objects\LineString;
use MatanYadaev\EloquentSpatial\Objects\Point;
use MatanYadaev\EloquentSpatial\Objects\Polygon;
class ServiceAreaController extends ApiController
{
@@ -23,6 +26,9 @@ class ServiceAreaController extends ApiController
]);
$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').'%'))
@@ -38,6 +44,10 @@ class ServiceAreaController extends ApiController
$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)) {
@@ -67,6 +77,10 @@ class ServiceAreaController extends ApiController
$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) {
@@ -80,6 +94,22 @@ class ServiceAreaController extends ApiController
);
}
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();