modifyQueryUsing(fn (Builder $query) => $query // A round trip's return leg is its own Booking row, but // showing both legs side by side in one list reads as two // unrelated bookings rather than one round trip — hide it // here; it's still reachable via the primary leg's "Linked // Leg" link on the detail page (view its own row directly). ->where('is_return_leg', false) ->with([ 'route.company', 'route.fromDestination', 'route.toDestination', 'timeSlot', 'vehicleOptions', 'linkedBooking', ])) ->defaultSort('created_at', 'desc') ->columns([ TextColumn::make('booking_ref') ->label('Ref') ->searchable() ->sortable(), TextColumn::make('status') ->badge() ->color(fn (BookingStatus $state) => match ($state) { BookingStatus::PendingPayment => 'warning', BookingStatus::Confirmed => 'success', BookingStatus::Cancelled => 'gray', BookingStatus::Expired => 'danger', }), TextColumn::make('route.company.name') ->label('Company') ->searchable() ->sortable(), TextColumn::make('route.fromDestination.name') ->label('From'), TextColumn::make('route.toDestination.name') ->label('To'), TextColumn::make('travel_date') ->date() ->sortable(), TextColumn::make('timeSlot.label') ->label('Time Slot'), IconColumn::make('is_round_trip') ->label('Round Trip') ->boolean() ->toggleable(), TextColumn::make('vehicleOptions') ->label('Vehicle Options') ->state(fn (Booking $record) => $record->vehicleOptions ->map(fn ($line) => str($line->vehicle_option->value)->headline().' x'.$line->passenger_count) ->all()) ->listWithLineBreaks(), TextColumn::make('price') ->label('Price') // Since the return leg no longer has its own row (it's // now hidden — see the query above), the price shown // here for a round trip needs to be both legs combined, // or it silently reads as just the outbound half. ->state(fn (Booking $record) => $record->is_round_trip ? bcadd((string) $record->price, (string) ($record->linkedBooking?->price ?? '0'), 2) : $record->price) ->description(fn (Booking $record) => $record->is_round_trip ? number_format((float) $record->price, 2).' + '.number_format((float) ($record->linkedBooking?->price ?? 0), 2) : null) ->numeric(2) ->sortable(), TextColumn::make('passenger_name') ->label('Passenger') ->description(fn (Booking $record) => $record->passenger_phone) ->searchable(['passenger_name', 'passenger_phone']) ->toggleable(isToggledHiddenByDefault: true), TextColumn::make('created_by_channel') ->badge() ->toggleable(isToggledHiddenByDefault: true), TextColumn::make('driver_name') ->label('Driver') ->placeholder('Not yet assigned') ->description(fn (Booking $record) => collect([$record->driver_phone, $record->car_plate_number, $record->car_model]) ->filter() ->join(' • ') ?: null) ->searchable(['driver_name', 'driver_phone', 'car_plate_number', 'car_model']) ->toggleable(), TextColumn::make('notes') ->label('Customer Notes') ->placeholder('—') ->limit(50) ->toggleable(isToggledHiddenByDefault: true), TextColumn::make('remark') ->label('Staff Remark') ->placeholder('—') ->limit(50) ->toggleable(isToggledHiddenByDefault: true), TextColumn::make('created_at') ->dateTime() ->sortable() ->toggleable(isToggledHiddenByDefault: true), ]) ->filters([ SelectFilter::make('status') ->options(array_combine( array_map(fn (BookingStatus $status) => $status->value, BookingStatus::cases()), array_map(fn (BookingStatus $status) => str($status->value)->headline()->toString(), BookingStatus::cases()), )), Filter::make('travel_date') ->schema([ DatePicker::make('travel_date'), ]) ->query(fn (Builder $query, array $data) => $query->when( $data['travel_date'] ?? null, fn (Builder $q, $date) => $q->whereDate('travel_date', $date), )), SelectFilter::make('ev_route_id') ->label('Route') ->options(fn () => EvRoute::with(['fromDestination', 'toDestination'])->get() ->mapWithKeys(fn (EvRoute $route) => [ $route->id => "{$route->fromDestination?->name} → {$route->toDestination?->name}", ])) ->searchable(), SelectFilter::make('company') ->options(fn () => EvCompany::pluck('name', 'id')) ->searchable() ->query(fn (Builder $query, array $data) => $query->when( $data['value'] ?? null, fn (Builder $q, $companyId) => $q->whereHas('route', fn (Builder $rq) => $rq->where('ev_company_id', $companyId)), )), // is_round_trip is a computed accessor (linked_booking_id // !== null), not a DB column — TernaryFilter builds a raw // where() on it, which breaks now that the column is gone. Filter::make('is_round_trip') ->schema([Toggle::make('is_round_trip')]) ->query(fn (Builder $query, array $data) => $query->when( $data['is_round_trip'] ?? null, fn (Builder $q) => $q->whereNotNull('linked_booking_id'), )), // Deleted bookings are soft-deleted, not hard-removed // (domain.md; T7.x follow-up) — this is the only place they // become visible again, off by default. TrashedFilter::make(), ]) ->recordActions([ ViewAction::make(), AssignDriverTableAction::make(), SetRemarkTableAction::make(), CancelBookingTableAction::make(), RefundBookingTableAction::make(), DeleteBookingTableAction::make(), RestoreBookingTableAction::make(), ]); } }