Files
Verde-Web/app/Http/Controllers/Api/V1/Me/UpcomingPickupsController.php

116 lines
4.5 KiB
PHP

<?php
namespace App\Http\Controllers\Api\V1\Me;
use App\Http\Controllers\Api\V1\ApiController;
use App\Models\Household;
use App\Models\Trip;
use App\Services\DropOff\DropOffPointFinder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpcomingPickupsController extends ApiController
{
/**
* Trips scheduled at or after today whose route includes this
* resident's assigned drop-off point. In-progress trips are
* always included so the resident sees a "truck on the way"
* card even mid-day.
*/
public function index(Request $request, DropOffPointFinder $finder): JsonResponse
{
$household = Household::with('assignedDropOffPoint')
->where('head_user_id', $request->user()->id)
->first();
if (! $household) {
return $this->ok([
'household_assigned' => false,
'pickups' => [],
]);
}
$nearbyDopIds = [];
if ($household->coordinates) {
$nearbyDops = $finder->nearby(
$household->coordinates->latitude,
$household->coordinates->longitude,
2.0, // 2km radius
10 // max 10 nearby drop-off points
);
$nearbyDopIds = $nearbyDops->pluck('id')->toArray();
}
if ($household->assigned_drop_off_point_id) {
$nearbyDopIds[] = $household->assigned_drop_off_point_id;
}
$nearbyDopIds = array_unique($nearbyDopIds);
if (empty($nearbyDopIds)) {
return $this->ok([
'household_assigned' => (bool) $household->assigned_drop_off_point_id,
'drop_off_point' => null,
'pickups' => [],
]);
}
$trips = Trip::query()
->with([
'route:id,name,code',
'route.stops' => fn ($q) => $q->whereIn('drop_off_point_id', $nearbyDopIds),
'team:id,name,driver_id',
'team.driver:id,first_name,last_name',
'truck:id,plate_number',
])
->whereHas('route.stops', fn ($q) => $q->whereIn('drop_off_point_id', $nearbyDopIds))
->whereNotIn('status', [Trip::STATUS_CANCELLED, Trip::STATUS_COMPLETED, Trip::STATUS_HANDED_OFF])
->where(function ($query) {
// Future dates are always upcoming (evaluated in Manila time)
$query->where('scheduled_date', '>', now('Asia/Manila')->toDateString())
// For today, check the time
->orWhere(function ($q) {
$q->where('scheduled_date', now('Asia/Manila')->toDateString())
->where(function ($sub) {
// Keep if the time hasn't passed yet (evaluated in Manila time)
$sub->where('scheduled_start_time', '>=', now('Asia/Manila')->toTimeString())
// OR if the driver has already started the trip
->orWhereIn('status', [Trip::STATUS_IN_PROGRESS, Trip::STATUS_AT_DUMPSITE]);
});
});
})
->orderBy('scheduled_date')
->orderBy('scheduled_start_time')
->limit(10)
->get();
$pickups = $trips->map(function (Trip $trip) {
$myStop = $trip->route?->stops->first();
return [
'trip_id' => $trip->uuid,
'trip_number' => $trip->trip_number,
'status' => $trip->status,
'scheduled_date' => $trip->scheduled_date?->toDateString(),
'scheduled_start_time' => $trip->scheduled_start_time,
'route' => $trip->route?->name,
'truck_plate' => $trip->truck?->plate_number,
'driver_name' => $trip->team?->driver?->full_name,
'my_stop_sequence' => $myStop?->sequence,
];
});
return $this->ok([
'household_assigned' => (bool) $household->assigned_drop_off_point_id,
'drop_off_point' => $household->assignedDropOffPoint ? [
'id' => $household->assignedDropOffPoint->uuid,
'name' => $household->assignedDropOffPoint->name,
'lat' => $household->assignedDropOffPoint->coordinates?->latitude,
'lng' => $household->assignedDropOffPoint->coordinates?->longitude,
] : null,
'pickups' => $pickups,
]);
}
}