Inactive Driver Feature — Changes Summary
Date: February 20, 2026
Overview
The inactive driver feature adds status (boolean) and inactive_at (date) columns to the drivers table, allowing drivers to be marked as active or inactive. Inactive drivers are hidden from assignment dropdowns, blocked from new task assignments, and prevented from logging into the mobile app.
Total files changed: 41 modified + 6 new files/directories
1. Database Migration
[NEW] database/migrations/2026_02_19_113248_add_status_to_drivers_table.php
- Adds
status(BOOLEAN, default1) afterline_color - Adds
inactive_at(DATE, nullable) afterstatus - Creates indexes on both columns
2. Model Layer
app/Driver.php
- Imports: Added
Carbon,Task,RunsheetRental - Fillable: Added
'status','inactive_at' - Casts: New
$castsarray —'status' => 'boolean','inactive_at' => 'date:Y-m-d','licence_expired_date' => 'date:Y-m-d' - Default Attributes:
'status' => true - New Scopes:
scopeActive($query, $date = null)— filters active drivers; optionally includes drivers inactive after a given datescopeInactive($query)— filters inactive drivers
- New Helper Methods:
isActive(): bool— checks ifstatus === truewasActiveOn(string $date): bool— checks if driver was still active on a historical date
3. Repository Layer
app/Repositories/DriverRepository.php
- New Methods:
canBeDeactivated(Driver $driver): bool— returns true if no blocking future tasks existgetDeactivationErrors(Driver $driver): array— checks future direct tasks (viauser_id→due_date) and future runsheet rental tasks (viadriver_id→date)deactivate(Driver $driver): bool— setsstatus = false,inactive_at = today, syncsUser.status = 0, unassigns vehicle (within DB transaction)activate(Driver $driver): bool— setsstatus = true,inactive_at = null, syncsUser.status = 1(within DB transaction)
4. Shared Trait
[NEW] app/Http/Controllers/Traits/ManagesDriverStatus.php
Shared trait used by both Admin\DriverController and Dashboard\DriverController.
- Abstract methods (implemented per controller):
getDriverForStatusUpdate($id)— retrieves driver (with scoping)authorizeDriverStatusUpdate(Request $request)— authorization check
- Public endpoints:
activate(Request, DriverRepository, $id)— activates a driver (AJAX + redirect support)deactivate(Request, DriverRepository, $id)— validates deactivation, then deactivates (AJAX + redirect support)toggleStatus(Request, DriverRepository, $id)— AJAX-only toggle with validation
5. Middleware
[NEW] app/Http/Middleware/CheckDriverActive.php
- Blocks inactive drivers from accessing
api-driverandapi-approutes - Returns
403JSON response:"Your account is inactive. Please contact support." - Exempts the logout route
app/Http/Kernel.php
- Registered as
'driver.active'in route middleware
app/Providers/RouteServiceProvider.php
- Added
'driver.active'middleware to thedriverApiRoutes()group
6. Controller Changes — By Endpoint
6.1 Admin\DriverController
| Endpoint | Method | Changes |
|---|---|---|
GET /admin/drivers | index() | Added ?status=active|inactive|all query filter; eager-loads user; passes $statusFilter and $repo to view |
POST /admin/drivers | store() | Explicitly sets 'status' => true on new driver |
GET /admin/drivers/{id}/edit | edit() | Injects DriverRepository, passes $repo to view |
PUT /admin/drivers/{id} | update() | Handles status change via $repo->canBeDeactivated() / $repo->deactivate() / $repo->activate() |
POST /admin/drivers/{id}/activate | activate() | Via ManagesDriverStatus trait |
POST /admin/drivers/{id}/deactivate | deactivate() | Via ManagesDriverStatus trait |
PUT /admin/drivers/{id}/toggle-status | toggleStatus() | Via ManagesDriverStatus trait |
Trait implementation: getDriverForStatusUpdate() uses Driver::findOrFail($id). Authorization checks drivers-update permission.
6.2 Dashboard\DriverController
| Endpoint | Method | Changes |
|---|---|---|
GET /dashboard/drivers | index() | Added ?status=active|inactive|all query filter scoped by supplier; passes $statusFilter and $repo to view |
GET /dashboard/drivers/{id}/edit | edit() | Injects DriverRepository, passes $repo to view |
POST /dashboard/drivers/{id}/activate | activate() | Via ManagesDriverStatus trait |
POST /dashboard/drivers/{id}/deactivate | deactivate() | Via ManagesDriverStatus trait |
POST /dashboard/drivers/{id}/toggle-status | toggleStatus() | Via ManagesDriverStatus trait |
Trait implementation: getDriverForStatusUpdate() scopes by supplier_id. Authorization defers to middleware.
6.3 Admin\TaskController
| Endpoint | Method | Changes |
|---|---|---|
GET /admin/tasks/create | create() | Driver dropdown now filters by ->active() scope |
GET /admin/tasks/{task}/edit | edit() | Driver dropdown includes active drivers + the currently assigned driver (even if inactive) via ->active()->orWhere('user_id', $task->user_id) |
PUT /admin/tasks/{task} | update() | Validates that newly assigned driver (by driver_id or user_id) is active; throws exception if inactive |
POST /admin/tasks/change-status | changeStatus() | Validates assigned driver is active before saving |
POST /admin/tasks/move-multi-task | moveMultiTask() | Validates target driver is active; returns error if inactive |
GET /admin/tasks/get-active-drivers | getActiveDrivers() | New endpoint — returns JSON list of active drivers (id, name, licence_class) |
6.4 Dashboard\TaskController
| Endpoint | Method | Changes |
|---|---|---|
GET /dashboard/tasks | index() | Driver filter dropdown scoped to ->active() for supplier |
GET /dashboard/tasks/{task}/edit | edit() | Driver dropdown includes active + currently assigned driver via ->active()->orWhere('user_id', $task->user_id) |
PUT /dashboard/tasks/{task} | update() | Validates new driver assignment is active before saving |
PUT /dashboard/tasks-assign/{task} | assignTask() | Validates driver is active before assignment |
6.5 Admin\TaskRunsheetController
| Endpoint | Method | Changes |
|---|---|---|
GET /admin/task-runsheet/schedule | schedule() | Filters drivers by ->active($date) scope; skips inactive drivers during day iteration via inactive_at check |
GET /admin/task-runsheet/timesheet | timesheet() | Filters drivers by ->active($startDate) |
6.6 Admin\RunsheetGroupController
| Endpoint | Method | Changes |
|---|---|---|
GET /admin/runsheet-groups/create | create() | Driver dropdown filtered by ->active() |
GET /admin/runsheet-groups/{id}/edit | edit() | Driver dropdown includes active + currently assigned driver via ->active()->orWhere('id', $runSheetGroup->driver_id) |
6.7 Admin\RunsheetRentalController
| Endpoint | Method | Changes |
|---|---|---|
GET /admin/runsheet-rentals | index() | Driver dropdown filtered by ->active($date) |
GET /admin/runsheet-rentals/create | create() | Driver dropdown filtered by ->active() |
GET /admin/runsheet-rentals/{id}/edit | edit() | Driver dropdown includes active + currently assigned driver via ->active()->orWhere('id', $runSheetRental->driver_id) |
6.8 Admin\BinLogisticController
| Endpoint | Method | Changes |
|---|---|---|
GET /admin/bin-logistic | index() | Driver list filtered by ->active($startDate) |
POST /admin/bin-logistic/search | search() | $all_drivers query filters by ->active($startDate) via whereHas('driver') |
6.9 Admin\DriverTimesheetController
| Endpoint | Method | Changes |
|---|---|---|
GET /admin/driver/timesheet | index() | Moved driver query after date calculation; filters by ->active($startDate) |
6.10 Admin\TrackLocationController
| Endpoint | Method | Changes |
|---|---|---|
GET /admin/driver-timesheet | driverTimesheet() | Filters drivers by ->active($date) |
GET /admin/track-driver | exportTrackLocation() | Filters drivers by ->active($startDate) |
6.11 Api\DriverController
| Endpoint | Method | Changes |
|---|---|---|
GET /api/driver-room | getDriverRoom() | Filters by Driver::active() |
GET /api/driver-supplier-room | getDriverSupplierRoom() | Filters by ->active() |
GET /api/driver-availability | getDriverAvailability() | Filters by ->active($date) via whereHas('driver'); adds 'is_inactive' flag to response |
6.12 ApiApp\RunsheetController
| Endpoint | Method | Changes |
|---|---|---|
POST /api-app/runsheet/staff | runsheetStaff() | Changed Driver::get() → Driver::active()->get() |
7. Route Changes
routes/admin.php
- Added:
POST drivers/{id}/activate,POST drivers/{id}/deactivate,PUT drivers/{id}/toggle-status - Added:
GET tasks/get-active-drivers
routes/dashboard.php
- Added:
POST drivers/{id}/activate,POST drivers/{id}/deactivate,POST drivers/{id}/toggle-status
routes/api-app.php
- Added
'driver.active'middleware to the main API group
8. Vue Component Changes
resources/js/components/runsheets/Assign2.vue
- Drag-and-drop: blocks assigning tasks to inactive drivers with SweetAlert warning
MoveMultiTaskmodal: passesactive_driver_tasks(new computed) instead of alldriver_tasks- Shows
"Inactive"badge next to inactive driver names in the driver panel
resources/js/components/DriverAvailabilityOption.vue
isDisabled(): addsdriver.is_inactivecheckdriverLabel(): shows"- Inactive"label for inactive drivers
resources/js/components/TrackMap.vue
- Shows
"Inactive"warning badge next to driver name wheninactive_atis set
9. Blade View Changes
The following views were modified (primarily adding status badges, filter dropdowns, and activate/deactivate buttons):
| View | Key Changes |
|---|---|
admin/driver/index.blade.php | Status filter dropdown, status badge column, activate/deactivate buttons |
admin/driver/edit.blade.php | Status display + action buttons |
admin/driver/timesheet.blade.php | Accommodates active driver filtering |
admin/task/index.blade.php | Driver filter uses active drivers |
admin/task/edit.blade.php | Driver dropdown shows active + assigned |
admin/bin-logistic/index.blade.php | Uses filtered active drivers |
admin/bin-logistic/task-listing-list-view.blade.php | Uses filtered $all_drivers |
admin/runsheet-groups/index.blade.php | Uses filtered active drivers |
admin/runsheet-rentals/index.blade.php | Uses filtered active drivers |
admin/runsheet-rentals/form.blade.php | Active driver dropdown |
admin/summary.blade.php | Active driver timesheet |
dashboard/driver/index.blade.php | Status filter, badges, action buttons |
dashboard/driver/edit.blade.php | Status display + action buttons |
dashboard/task/index.blade.php | Active driver filter |
dashboard/task/edit.blade.php | Active + assigned driver dropdown |
dashboard/bin-logistic/task-listing-list-view.blade.php | Uses filtered active drivers |
[NEW] resources/views/dashboard/driver/partials/
- New partial directory (likely for SweetAlert confirmation scripts)
10. Other Modified Files
| File | Changes |
|---|---|
app/Scopes/OrderByCreatedAtDesc.php | Formatting only |
public/js/app.js | Rebuilt with Vue component changes |
public/mix-manifest.json | Updated asset hashes |