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);
}
}
}