HEX
Server: Apache/2.4.58 (Ubuntu)
System: Linux ip-172-26-0-120 6.17.0-1009-aws #9~24.04.2-Ubuntu SMP Fri Mar 6 23:50:29 UTC 2026 x86_64
User: ubuntu (1000)
PHP: 8.3.6
Disabled: NONE
Upload Files
File: /var/www/html/dashboard.orbiwheels.com/app/Http/Controllers/Transporter/VehicleController.php
<?php

namespace App\Http\Controllers\Transporter;

use App\DataTables\Transporter\DriverDataTable;
use App\DataTables\Transporter\VehicleDataTable;
use App\Http\Controllers\Controller;
use App\Models\Document;
use App\Models\Driver;
use App\Models\Vehicle;
use App\Models\VehicleType;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;

class VehicleController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index(VehicleDataTable $dataTable)
    {
        $transporter = Auth::guard('trans')->user();

        if (!$transporter) {
            return redirect()->route('login')->with('error', 'Please login first.');
        }
        $hasVehicle = $transporter->vehicles()->exists();
        $message = null;
        if (!$hasVehicle) {
            $message = "Please add at least one Vehicle.";
        }
        return $dataTable->render('transporter.vehicle.index', compact('message'));
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create()
    {
        $vehicleTypes = VehicleType::all();
        return view('transporter.vehicle.create', compact('vehicleTypes'));
    }


    public function store(Request $request)
    {
        // dd($request->all());
        $request->validate([
            'vehicle_type' => 'required|exists:vehicle_types,id',
            'make' => 'required|string|max:255',
            'model' => 'required|string|max:255',
            'manufacturing_year' => 'required|integer|min:1900|max:' . date('Y'),
            'status' => 'required|in:active,under_maintenance,inactive',
            'documents.*.type' => 'required|string|in:rc,insurance,pollution,permit,other',
            'documents.*.number' => 'nullable|string|max:255',
            'documents.*.file' => 'nullable|file|mimes:jpg,jpeg,png,pdf|max:2048',
            'documents.*.expiry_date' => 'nullable|date',
        ], [
            // Document messages
            'documents.*.type.required' => 'Please select the document type.',
            'documents.*.type.in' => 'Selected document type is invalid.',
            'documents.*.number.max' => 'Document number cannot exceed 255 characters.',
            'documents.*.file.file' => 'Uploaded document must be a file.',
            'documents.*.file.mimes' => 'Document must be a file of type: jpg, jpeg, png, pdf.',
            'documents.*.file.max' => 'Document size cannot exceed 2MB.',
            'documents.*.expiry_date.date' => 'Expiry date must be a valid date.',
            'vehicle_images.*' => 'nullable|file|mimes:jpg,jpeg,png|max:2048',
        ]);

        $vehicle = new Vehicle();
        $vehicle->vehicle_type_id = $request->vehicle_type;
        $vehicle->transporter_id = auth()->guard('trans')->user()->id;
        $vehicle->make = $request->make;
        $vehicle->model = $request->model;
        $vehicle->year = $request->manufacturing_year;
        $vehicle->status = $request->status;

        // Set RC registration number if present
        $rcDocument = collect($request->documents)->firstWhere('type', 'rc');
        $vehicle->registration_number = $rcDocument['number'] ?? null;

        $vehicle->save();

        // Save documents
        if ($request->has('documents')) {
            foreach ($request->documents as $doc) {
                $filePath = isset($doc['file']) ? $doc['file']->store("uploads/vehicle/{$vehicle->id}", 'public') : null;

                $vehicle->documents()->create([
                    'doc_type' => $doc['type'],
                    'doc_number' => $doc['number'] ?? null,
                    'file_url' => $filePath,
                    'expiry_date' => $doc['expiry_date'] ?? null,
                ]);
            }
        }

        $vehicle->refreshVerificationStatus();

        if ($request->hasFile('vehicle_images')) {
            $file = $request->file('vehicle_images');
            $path = $file->store("uploads/vehicle/{$vehicle->id}", 'public');
            $vehicle->vehicle_image = $path;
            $vehicle->save();
        }

        return redirect()->route('vehicle.index')->with('success', 'Vehicle created successfully!');
    }

    public function view(string $id)
    {
        $vehicle = Vehicle::with('documents')->find($id);
        if (!isset($vehicle)) {
            return redirect()->route('vehicle.index')->with('error', 'vehicle not found!');
        }
        // dd($vehicle);
        return view('transporter.vehicle.view', compact('vehicle'));
    }


    public function edit(string $id)
    {
        $vehicle = Vehicle::find($id);
        if (!isset($vehicle)) {
            return redirect()->route('vehicle.index')->with('error', 'Vehicle not found!');
        }
        $vehicleTypes = VehicleType::all();
        return view('transporter.vehicle.edit', compact('vehicle', 'vehicleTypes'));
    }


    public function update(Request $request, string $id)
    {
        $vehicle = Vehicle::find($id);
        if (!$vehicle) {
            return redirect()->route('vehicle.index')->with('error', 'Vehicle not found!');
        }

        $request->validate([
            'vehicle_type' => 'required|exists:vehicle_types,id',
            'make' => 'required|string|max:255',
            'model' => 'required|string|max:255',
            'manufacturing_year' => 'required|integer|min:1900|max:' . date('Y'),
            'status' => 'required|in:active,under_maintenance,inactive',
            'documents.*.type' => 'required|string|in:rc,insurance,pollution,permit,other',
            'documents.*.number' => 'nullable|string|max:255',
            'documents.*.file' => 'nullable|file|mimes:jpg,jpeg,png,pdf|max:2048',
            'documents.*.expiry_date' => 'nullable|date',
        ], [
            'documents.*.type.required' => 'Please select the document type.',
            'documents.*.type.in' => 'Selected document type is invalid.',
            'documents.*.number.max' => 'Document number cannot exceed 255 characters.',
            'documents.*.file.file' => 'Uploaded document must be a file.',
            'documents.*.file.mimes' => 'Document must be a file of type: jpg, jpeg, png, pdf.',
            'documents.*.file.max' => 'Document size cannot exceed 2MB.',
            'documents.*.expiry_date.date' => 'Expiry date must be a valid date.',
            'vehicle_images.*' => 'nullable|file|mimes:jpg,jpeg,png|max:2048',
        ]);

        $vehicle->vehicle_type_id = $request->vehicle_type;
        $vehicle->make = $request->make;
        $vehicle->model = $request->model;
        $vehicle->year = $request->manufacturing_year;
        $vehicle->status = $request->status;

        $rcDocument = collect($request->documents)->firstWhere('type', 'rc');
        $vehicle->registration_number = $rcDocument['number'] ?? $vehicle->registration_number;

        $vehicle->save();

        if ($request->has('documents')) {
            foreach ($request->documents as $doc) {
                $existingDoc = $vehicle->documents()->where('doc_type', $doc['type'])->first();

                $filePath = isset($doc['file']) ? $doc['file']->store("uploads/vehicle/{$vehicle->id}", 'public') : ($existingDoc->file_url ?? null);

                if ($existingDoc) {
                    // Update existing document
                    $existingDoc->update([
                        'doc_number' => $doc['number'] ?? $existingDoc->doc_number,
                        'file_url' => $filePath,
                        'expiry_date' => $doc['expiry_date'] ?? $existingDoc->expiry_date,
                    ]);
                } else {
                    // Create new document
                    $vehicle->documents()->create([
                        'doc_type' => $doc['type'],
                        'doc_number' => $doc['number'] ?? null,
                        'file_url' => $filePath,
                        'expiry_date' => $doc['expiry_date'] ?? null,
                    ]);
                }
            }
        }
        $vehicle->refreshVerificationStatus();
        if ($request->hasFile('vehicle_images')) {
            if ($vehicle->vehicle_image && Storage::disk('public')->exists($vehicle->vehicle_image)) {
                Storage::disk('public')->delete($vehicle->vehicle_image);
            }

            $file = $request->file('vehicle_images');
            $path = $file->store("uploads/vehicle/{$vehicle->id}", 'public');

            $vehicle->vehicle_image = $path;
            $vehicle->save();
        }


        return redirect()->route('vehicle.index')->with('success', 'Vehicle updated successfully!');
    }


    /**
     * Remove the specified resource from storage.
     */
    public function destroy(string $id)
    {
        $vehicle = Vehicle::find($id);
        if (!isset($vehicle)) {
            return response()->json([
                'status' => false,
                'message' => 'Vehicle not found!',
            ]);
        }
        foreach ($vehicle->documents as $document) {
            if ($document->file_url && Storage::disk('public')->exists($document->file_url)) {
                Storage::disk('public')->delete($document->file_url);
            }
            $document->delete();
        }
        $vehicle->delete();

        return response()->json([
            'status' => true,
            'message' => 'Vehicle deleted successfully!',
        ]);
    }
    public function updateVehicleStatus(Request $request, $id)
    {
        try {
            $vehicle = Vehicle::findOrFail($id);
            $vehicle->status = $request->status;
            $vehicle->save();

            return response()->json([
                'success' => true,
                'message' => 'Vehicle status updated successfully!',
                'status'  => $vehicle->status
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Something went wrong: ' . $e->getMessage()
            ], 500);
        }
    }
    public function search(Request $request)
    {
        $transporterId = auth()->guard('trans')->user()->id;
        $query = $request->get('q');

        $vehicles = Vehicle::query()
            ->where('transporter_id', $transporterId)
            ->where('status', 'active')
            ->where('is_verified', 1)
            ->where(function ($q) use ($query) {
                $q->where('registration_number', 'like', "%{$query}%")
                    ->orWhere('make', 'like', "%{$query}%")
                    ->orWhere('model', 'like', "%{$query}%");
            })
            ->limit(10)
            ->get();

        return response()->json($vehicles);
    }


    /**
     * Display a listing of the resource.
     */
    public function driverIndex(DriverDataTable $dataTable)
    {
         $transporter = Auth::guard('trans')->user();

        if (!$transporter) {
            return redirect()->route('login')->with('error', 'Please login first.');
        }
        $hasDriver = $transporter->drivers()->exists();
        $message = null;
        if (!$hasDriver) {
            $message = "Please add at least one Driver.";
        }
        return $dataTable->render('transporter.driver.index', compact('message'));
    }

    /**
     * Show the form for creating a new resource.
     */
    public function createDriver()
    {
        return view('transporter.driver.create');
    }


    public function storeDriver(Request $request)
    {
        // dd($request->all());
        $request->validate([
            'name'          => 'required|string|max:255',
            'email'         => 'required|email|max:255|unique:drivers,email',
            'phone'         => 'required|string|unique:drivers,phone',
            'status'        => 'required|in:active,inactive,suspended',
            'age'           => 'required|string',
            'gender'        => 'required|in:male,female,other',
            'profile_image' => 'required|file|mimes:jpg,jpeg,png|max:2048',
            'documents'             => 'required|array|min:1',
            'documents.*.type'      => 'required|string|in:dl,aadhar,pan,passport',
            'documents.*.number'    => 'required|string|max:255',
            'documents.*.file'      => 'required|file|mimes:jpg,jpeg,png,pdf|max:2048',
            // 'documents.*.expiry_date' => 'required_if:documents.*.type,dl|date|after:today',
        ], [
            'documents.required'      => 'At least one document is required.',
            'documents.*.type.required'   => 'Document type is required.',
            'documents.*.type.in'         => 'Invalid document type selected.',
            'documents.*.number.required' => 'Document number is required.',
            'documents.*.file.required'   => 'Document photo/file is required.',
            'documents.*.expiry_date.required_if' => 'Expiry date is required for Driving License.',
            'documents.*.expiry_date.after' => 'Expiry date must be a future date.',
        ]);
        $driver = new Driver();
        $driver->transporter_id = auth()->guard('trans')->user()->id;
        $driver->name  = $request->name;
        $driver->email = $request->email;
        $driver->phone = $request->phone;
        $driver->about = $request->about;
        $driver->experience = $request->experience;
        $driver->alternate_number = $request->alternate_number;
        $driver->age    = $request->age;
        $driver->gender = $request->gender;
        $driver->status = $request->status;

        if ($request->hasFile('profile_image')) {
            $driver->image = $request->file('profile_image')->store("uploads/driver/{$driver->id}", 'public');
        }

        $driver->save();

        foreach ($request->documents as $doc) {
            $path = null;
            if (!empty($doc['file'])) {
                $path = $doc['file']->store("uploads/driver/{$driver->id}", 'public');
            }

            $driver->documents()->create([
                'doc_type'   => $doc['type'],
                'doc_number' => $doc['number'],
                'file_url'   => $path,
                'expiry_date' => $doc['expiry_date'] ?? null,
            ]);
        }
        $driver->refreshVerificationStatus();
        return redirect()->route('driver.index')->with('success', 'Driver created successfully!');
    }

    public function viewDriver(string $id)
    {
        $driver = Driver::with('documents')->find($id);
        if (!isset($driver)) {
            return redirect()->route('driver.index')->with('error', 'Driver not found!');
        }
        // dd($driver);
        return view('transporter.driver.view', compact('driver'));
    }
    public function editDriver(string $id)
    {
        $driver = Driver::with('documents')->find($id);
        if (!isset($driver)) {
            return redirect()->route('driver.index')->with('error', 'Driver not found!');
        }
        // dd($driver);
        return view('transporter.driver.edit', compact('driver'));
    }


    public function updateDriver(Request $request, string $id)
    {
        try {
            $driver = Driver::find($id);
            if (!$driver) {
                return redirect()->route('driver.index')->with('error', 'Driver not found!');
            }

            $hasDocuments = $driver->documents()->exists();

            $rules = [
                'name'          => 'required|string|max:255',
                'email'         => 'required|email|max:255|unique:drivers,email,' . $driver->id,
                'phone'         => 'required|string|unique:drivers,phone,' . $driver->id,
                'status'        => 'required|in:active,inactive,suspended',
                'profile_image' => 'nullable|file|mimes:jpg,jpeg,png|max:2048',
                'age'           => 'required|string',
                'gender'        => 'required|in:male,female,other',
            ];

            // Only force documents if none exist yet
            if (!$hasDocuments) {
                $rules['documents'] = 'nullable|array';
            } else {
                $rules['documents'] = 'nullable|array';
            }

            $rules['documents.*.type']   = 'required|string|in:dl,aadhar,pan,passport';
            $rules['documents.*.number'] = 'required|string|max:255';
            $rules['documents.*.file']   = 'nullable|file|mimes:jpg,jpeg,png,pdf|max:2048';

            $request->validate($rules, [
                'documents.required'         => 'At least one document is required.',
                'documents.*.type.required'  => 'Document type is required.',
                'documents.*.type.in'        => 'Invalid document type selected.',
                'documents.*.number.required' => 'Document number is required.',
                'documents.*.file.required'  => 'Document photo/file is required.',
                'documents.*.expiry_date.after' => 'Expiry date must be a future date.',
            ]);

            $driver->fill([
                'name'             => $request->name,
                'email'            => $request->email,
                'phone'            => $request->phone,
                'about'            => $request->about,
                'experience'       => $request->experience,
                'alternate_number' => $request->alternate_number ?? null,
                'age'              => $request->age,
                'gender'           => $request->gender,
                'status'           => $request->status,
            ]);

            if ($request->hasFile('profile_image')) {
                if ($driver->image && Storage::disk('public')->exists($driver->image)) {
                    Storage::disk('public')->delete($driver->image);
                }
                $driver->image = $request->file('profile_image')
                    ->store("uploads/driver/{$driver->id}", 'public');
            }

            $driver->save();

            if ($request->filled('documents')) {
                foreach ($request->documents as $doc) {
                    $existingDoc = $driver->documents()->where('doc_type', $doc['type'])->first();
                    $path = $existingDoc->file_url ?? null;

                    if (!empty($doc['file'])) {
                        if ($path && Storage::disk('public')->exists($path)) {
                            Storage::disk('public')->delete($path);
                        }
                        $path = $doc['file']->store("uploads/driver/{$driver->id}", 'public');
                    }

                    $driver->documents()->updateOrCreate(
                        ['doc_type' => $doc['type']],
                        [
                            'doc_number'  => $doc['number'],
                            'file_url'    => $path,
                            'expiry_date' => $doc['expiry_date'] ?? ($existingDoc->expiry_date ?? null),
                        ]
                    );
                }
            }

            $driver->refreshVerificationStatus();

            return redirect()->route('driver.index')->with('success', 'Driver updated successfully!');
        } catch (\Exception $e) {
            Log::error('Driver update failed: ' . $e->getMessage());
            return redirect()->back()->withInput()->with('error', 'Something went wrong while updating driver.');
        }
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroyDriver(string $id)
    {
        $driver = Driver::find($id);
        if (!isset($driver)) {
            return response()->json([
                'status' => false,
                'message' => 'Driver not found!',
            ]);
        }
        foreach ($driver->documents as $document) {
            if ($document->file_url && Storage::disk('public')->exists($document->file_url)) {
                Storage::disk('public')->delete($document->file_url);
            }
            $document->delete();
        }
        $driver->delete();

        return response()->json([
            'status' => true,
            'message' => 'Driver deleted successfully!',
        ]);
    }

    public function deleteDocument(string $id)
    {
        $doc = Document::findOrFail($id);
        if ($doc->file_url && Storage::disk('public')->exists($doc->file_url)) {
            Storage::disk('public')->delete($doc->file_url);
        }

        $doc->delete();

        return response()->json(['success' => true, 'message' => 'Document deleted successfully.']);
    }

    public function searchDriver(Request $request)
    {
        $transporterId = auth()->guard('trans')->user()->id;
        $query = $request->get('q');

        $drivers = Driver::query()
            ->where('transporter_id', $transporterId)
            ->where('status', 'active')
            ->where('is_verified', 1)
            ->where(function ($q) use ($query) {
                $q->where('name', 'like', "%{$query}%")
                    ->orWhere('email', 'like', "%{$query}%")
                    ->orWhere('phone', 'like', "%{$query}%");
            })
            ->limit(10)
            ->get();

        return response()->json($drivers);
    }
    public function updateStatus(Request $request, $id)
    {
        try {
            $driver = Driver::findOrFail($id);
            $driver->status = $request->status;
            $driver->save();

            return response()->json([
                'success' => true,
                'message' => 'Driver status updated successfully!',
                'status'  => $driver->status
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Something went wrong: ' . $e->getMessage()
            ], 500);
        }
    }
}