116 lines
4.5 KiB
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,
|
|
]);
|
|
}
|
|
}
|