MIF_E31232103/app/Http/Controllers/AdminRental/VehicleController.php

317 lines
11 KiB
PHP

<?php
namespace App\Http\Controllers\AdminRental;
use App\Http\Controllers\Controller;
use App\Http\Requests\StoreVehicleRequest;
use App\Http\Requests\UpdateVehicleRequest;
use App\Models\Inventory;
use App\Models\RentalCompany;
use App\Models\Vehicle;
use App\Models\VehicleImage;
use App\Services\ActivityLogService;
use App\Services\FileUploadService;
use App\Services\SlugService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
class VehicleController extends Controller
{
public function __construct(
private readonly SlugService $slugService,
private readonly FileUploadService $fileUploadService,
private readonly ActivityLogService $activityLogService,
) {
}
public function index(Request $request): View|RedirectResponse
{
$rentalCompany = $this->getRentalCompany();
if (!$rentalCompany) {
return redirect()
->route('admin-rental.dashboard')
->with('error', 'Akun admin rental ini belum memiliki rental company. Silakan lengkapi data rental company terlebih dahulu.');
}
$vehicles = Vehicle::query()
->where('rental_company_id', $rentalCompany->id)
->when($request->filled('search'), function ($query) use ($request): void {
$search = $request->string('search')->toString();
$query->where(function ($subQuery) use ($search): void {
$subQuery->where('name', 'like', '%' . $search . '%')
->orWhere('brand', 'like', '%' . $search . '%')
->orWhere('category', 'like', '%' . $search . '%');
});
})
->withCount('images')
->with(['images'])
->latest()
->paginate(10)
->withQueryString();
return view('admin-rental.vehicles.index', compact('vehicles', 'rentalCompany'));
}
public function create(): View|RedirectResponse
{
$this->authorize('create', Vehicle::class);
$rentalCompany = $this->getRentalCompany();
if (!$rentalCompany) {
return redirect()
->route('admin-rental.dashboard')
->with('error', 'Akun admin rental ini belum memiliki rental company. Silakan lengkapi data rental company terlebih dahulu.');
}
$vehicle = new Vehicle([
'status' => Vehicle::STATUS_ACTIVE,
]);
return view('admin-rental.vehicles.create', compact('vehicle', 'rentalCompany'));
}
public function store(StoreVehicleRequest $request): RedirectResponse
{
$this->authorize('create', Vehicle::class);
$rentalCompany = $this->getRentalCompany();
if (!$rentalCompany) {
return redirect()
->route('admin-rental.dashboard')
->with('error', 'Akun admin rental ini belum memiliki rental company. Silakan lengkapi data rental company terlebih dahulu.');
}
$validated = $request->validated();
$slug = $this->slugService->generateUnique(Vehicle::class, 'slug', $validated['name']);
$mainImagePath = null;
try {
if ($request->hasFile('main_image')) {
$mainImagePath = $this->fileUploadService->storePublic($request->file('main_image'), 'vehicles/main');
}
} catch (\Throwable $exception) {
return back()->withInput()->with('error', 'Upload foto utama gagal. Silakan coba lagi dengan file yang valid.');
}
$vehicle = Vehicle::create([
'rental_company_id' => $rentalCompany->id,
'name' => $validated['name'],
'slug' => $slug,
'brand' => $validated['brand'],
'type' => $validated['type'],
'category' => $validated['category'],
'year' => $validated['year'],
'transmission' => $validated['transmission'],
'fuel_type' => $validated['fuel_type'],
'seat_capacity' => $validated['seat_capacity'],
'luggage_capacity' => $validated['luggage_capacity'] ?? null,
'color' => $validated['color'] ?? null,
'price_per_day' => $validated['price_per_day'],
'description' => $validated['description'] ?? null,
'terms_conditions' => $validated['terms_conditions'] ?? null,
'status' => $validated['status'],
'main_image' => $mainImagePath,
]);
Inventory::create([
'rental_company_id' => $rentalCompany->id,
'vehicle_id' => $vehicle->id,
'total' => 0,
'reserved' => 0,
'available' => 0,
]);
$this->storeGalleryImages($request, $vehicle);
$this->activityLogService->log(
action: 'vehicle.created',
description: 'Admin rental membuat kendaraan baru: ' . $vehicle->name,
targetType: 'vehicle',
targetId: $vehicle->id,
meta: ['slug' => $vehicle->slug]
);
return redirect()
->route('admin-rental.vehicles.index')
->with('success', 'Data kendaraan berhasil ditambahkan.');
}
public function edit(Vehicle $vehicle): View|RedirectResponse
{
$this->authorize('update', $vehicle);
$rentalCompany = $this->getRentalCompany();
if (!$rentalCompany) {
return redirect()
->route('admin-rental.dashboard')
->with('error', 'Akun admin rental ini belum memiliki rental company. Silakan lengkapi data rental company terlebih dahulu.');
}
$vehicle->load('images');
return view('admin-rental.vehicles.edit', compact('vehicle', 'rentalCompany'));
}
public function update(UpdateVehicleRequest $request, Vehicle $vehicle): RedirectResponse
{
$this->authorize('update', $vehicle);
$rentalCompany = $this->getRentalCompany();
if (!$rentalCompany) {
return redirect()
->route('admin-rental.dashboard')
->with('error', 'Akun admin rental ini belum memiliki rental company. Silakan lengkapi data rental company terlebih dahulu.');
}
$validated = $request->validated();
try {
if ($request->hasFile('main_image')) {
$this->fileUploadService->deletePublic($vehicle->main_image);
$vehicle->main_image = $this->fileUploadService->storePublic($request->file('main_image'), 'vehicles/main');
}
} catch (\Throwable $exception) {
return back()->withInput()->with('error', 'Upload foto utama gagal. Silakan coba lagi dengan file yang valid.');
}
$vehicle->fill([
'name' => $validated['name'],
'slug' => $this->slugService->generateUnique(Vehicle::class, 'slug', $validated['name'], $vehicle->id),
'brand' => $validated['brand'],
'type' => $validated['type'],
'category' => $validated['category'],
'year' => $validated['year'],
'transmission' => $validated['transmission'],
'fuel_type' => $validated['fuel_type'],
'seat_capacity' => $validated['seat_capacity'],
'luggage_capacity' => $validated['luggage_capacity'] ?? null,
'color' => $validated['color'] ?? null,
'price_per_day' => $validated['price_per_day'],
'description' => $validated['description'] ?? null,
'terms_conditions' => $validated['terms_conditions'] ?? null,
'status' => $validated['status'],
]);
$vehicle->save();
$this->storeGalleryImages($request, $vehicle);
$this->deleteSelectedGalleryImages($request, $vehicle);
$this->activityLogService->log(
action: 'vehicle.updated',
description: 'Admin rental memperbarui kendaraan: ' . $vehicle->name,
targetType: 'vehicle',
targetId: $vehicle->id,
meta: ['slug' => $vehicle->slug]
);
return redirect()
->route('admin-rental.vehicles.index')
->with('success', 'Data kendaraan berhasil diperbarui.');
}
public function destroy(Vehicle $vehicle): RedirectResponse
{
$this->authorize('delete', $vehicle);
$rentalCompany = $this->getRentalCompany();
if (!$rentalCompany) {
return redirect()
->route('admin-rental.dashboard')
->with('error', 'Akun admin rental ini belum memiliki rental company. Silakan lengkapi data rental company terlebih dahulu.');
}
if ($vehicle->bookings()->exists()) {
return redirect()
->route('admin-rental.vehicles.index')
->with('error', 'Kendaraan tidak dapat dihapus karena memiliki riwayat booking.');
}
$this->fileUploadService->deletePublic($vehicle->main_image);
foreach ($vehicle->images as $image) {
$this->fileUploadService->deletePublic($image->image_path);
$image->delete();
}
$vehicle->reviews()->delete();
$vehicle->inventory()->delete();
$deletedVehicleId = $vehicle->id;
$deletedVehicleName = $vehicle->name;
$vehicle->delete();
$this->activityLogService->log(
action: 'vehicle.deleted',
description: 'Admin rental menghapus kendaraan: ' . $deletedVehicleName,
targetType: 'vehicle',
targetId: $deletedVehicleId
);
return redirect()
->route('admin-rental.vehicles.index')
->with('success', 'Data kendaraan berhasil dihapus.');
}
public function destroyGalleryImage(VehicleImage $image): RedirectResponse
{
$image->load('vehicle');
$this->authorize('update', $image->vehicle);
$this->fileUploadService->deletePublic($image->image_path);
$image->delete();
return back()->with('success', 'Gambar galeri berhasil dihapus.');
}
private function getRentalCompany(): ?RentalCompany
{
return Auth::user()?->rentalCompany;
}
private function storeGalleryImages(StoreVehicleRequest|UpdateVehicleRequest $request, Vehicle $vehicle): void
{
if (!$request->hasFile('gallery_images')) {
return;
}
foreach ($request->file('gallery_images') as $imageFile) {
$imagePath = $this->fileUploadService->storePublic($imageFile, 'vehicles/gallery');
VehicleImage::create([
'vehicle_id' => $vehicle->id,
'image_path' => $imagePath,
'is_primary' => false,
]);
}
}
private function deleteSelectedGalleryImages(UpdateVehicleRequest $request, Vehicle $vehicle): void
{
$deleteIds = $request->input('delete_gallery_images', []);
if (empty($deleteIds)) {
return;
}
$galleryImages = VehicleImage::query()
->where('vehicle_id', $vehicle->id)
->whereIn('id', $deleteIds)
->get();
foreach ($galleryImages as $image) {
$this->fileUploadService->deletePublic($image->image_path);
$image->delete();
}
}
}