Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .claude/settings.local.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
"mcp__laravel-boost__application-info",
"mcp__laravel-boost__database-schema",
"mcp__laravel-boost__search-docs",
"WebFetch(domain:spatie.be)"
"WebFetch(domain:spatie.be)",
"mcp__laravel-boost__list-routes",
"mcp__laravel-boost__browser-logs"
]
},
"enableAllProjectMcpServers": true,
Expand Down
19 changes: 19 additions & 0 deletions app/Http/Controllers/Api/ModelVersionController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\VehicleModel;
use Illuminate\Http\JsonResponse;

class ModelVersionController extends Controller
{
public function index(VehicleModel $vehicleModel): JsonResponse
{
$modelVersions = $vehicleModel->modelVersions()
->orderBy('name')
->get(['id', 'name']);

return response()->json($modelVersions);
}
}
19 changes: 19 additions & 0 deletions app/Http/Controllers/Api/VehicleModelController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Make;
use Illuminate\Http\JsonResponse;

class VehicleModelController extends Controller
{
public function index(Make $make): JsonResponse
{
$vehicleModels = $make->vehicleModels()
->orderBy('name')
->get(['id', 'name']);

return response()->json($vehicleModels);
}
}
24 changes: 24 additions & 0 deletions app/Http/Controllers/Vehicle/CreateVehicleController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace App\Http\Controllers\Vehicle;

use App\Enums\FuelType;
use App\Enums\Transmission;
use App\Enums\VehicleStatus;
use App\Http\Controllers\Controller;
use App\Models\Make;
use Inertia\Inertia;
use Inertia\Response;

class CreateVehicleController extends Controller
{
public function __invoke(): Response
{
return Inertia::render('vehicles/Create', [
'makes' => Make::query()->orderBy('name')->get(['id', 'name']),
'fuelTypes' => FuelType::cases(),
'transmissions' => Transmission::cases(),
'statuses' => VehicleStatus::cases(),
]);
}
}
17 changes: 17 additions & 0 deletions app/Http/Controllers/Vehicle/DestroyVehicleController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace App\Http\Controllers\Vehicle;

use App\Http\Controllers\Controller;
use App\Models\Vehicle;
use Illuminate\Http\RedirectResponse;

class DestroyVehicleController extends Controller
{
public function __invoke(Vehicle $vehicle): RedirectResponse
{
$vehicle->delete();

return to_route('vehicles.index');
}
}
28 changes: 28 additions & 0 deletions app/Http/Controllers/Vehicle/EditVehicleController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace App\Http\Controllers\Vehicle;

use App\Enums\FuelType;
use App\Enums\Transmission;
use App\Enums\VehicleStatus;
use App\Http\Controllers\Controller;
use App\Models\Make;
use App\Models\Vehicle;
use Inertia\Inertia;
use Inertia\Response;

class EditVehicleController extends Controller
{
public function __invoke(Vehicle $vehicle): Response
{
$vehicle->load(['modelVersion.vehicleModel.make', 'media']);

return Inertia::render('vehicles/Edit', [
'vehicle' => $vehicle,
'makes' => Make::query()->orderBy('name')->get(['id', 'name']),
'fuelTypes' => FuelType::cases(),
'transmissions' => Transmission::cases(),
'statuses' => VehicleStatus::cases(),
]);
}
}
50 changes: 50 additions & 0 deletions app/Http/Controllers/Vehicle/IndexVehicleController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace App\Http\Controllers\Vehicle;

use App\Enums\FuelType;
use App\Enums\Transmission;
use App\Enums\VehicleStatus;
use App\Http\Controllers\Controller;
use App\Models\Vehicle;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;

class IndexVehicleController extends Controller
{
public function __invoke(Request $request): Response
{
$vehicles = Vehicle::query()
->with(['modelVersion.vehicleModel.make'])
->when($request->search, function ($query, $search) {
$query->whereHas('modelVersion.vehicleModel.make', function ($q) use ($search) {
$q->where('name', 'ilike', "%{$search}%");
})->orWhereHas('modelVersion.vehicleModel', function ($q) use ($search) {
$q->where('name', 'ilike', "%{$search}%");
})->orWhereHas('modelVersion', function ($q) use ($search) {
$q->where('name', 'ilike', "%{$search}%");
})->orWhere('color', 'ilike', "%{$search}%");
})
->when($request->status, function ($query, $status) {
$query->where('status', $status);
})
->when($request->fuel_type, function ($query, $fuelType) {
$query->where('fuel_type', $fuelType);
})
->when($request->transmission, function ($query, $transmission) {
$query->where('transmission', $transmission);
})
->latest()
->paginate(15)
->withQueryString();

return Inertia::render('vehicles/Index', [
'vehicles' => $vehicles,
'filters' => $request->only(['search', 'status', 'fuel_type', 'transmission']),
'fuelTypes' => FuelType::cases(),
'transmissions' => Transmission::cases(),
'statuses' => VehicleStatus::cases(),
]);
}
}
20 changes: 20 additions & 0 deletions app/Http/Controllers/Vehicle/ShowVehicleController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace App\Http\Controllers\Vehicle;

use App\Http\Controllers\Controller;
use App\Models\Vehicle;
use Inertia\Inertia;
use Inertia\Response;

class ShowVehicleController extends Controller
{
public function __invoke(Vehicle $vehicle): Response
{
$vehicle->load(['modelVersion.vehicleModel.make', 'media']);

return Inertia::render('vehicles/Show', [
'vehicle' => $vehicle,
]);
}
}
24 changes: 24 additions & 0 deletions app/Http/Controllers/Vehicle/StoreVehicleController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace App\Http\Controllers\Vehicle;

use App\Http\Controllers\Controller;
use App\Http\Requests\Vehicle\StoreVehicleRequest;
use App\Models\Vehicle;
use Illuminate\Http\RedirectResponse;

class StoreVehicleController extends Controller
{
public function __invoke(StoreVehicleRequest $request): RedirectResponse
{
$vehicle = Vehicle::create($request->validated());

if ($request->hasFile('images')) {
foreach ($request->file('images') as $image) {
$vehicle->addMedia($image)->toMediaCollection('images');
}
}

return to_route('vehicles.show', $vehicle);
}
}
30 changes: 30 additions & 0 deletions app/Http/Controllers/Vehicle/UpdateVehicleController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace App\Http\Controllers\Vehicle;

use App\Http\Controllers\Controller;
use App\Http\Requests\Vehicle\UpdateVehicleRequest;
use App\Models\Vehicle;
use Illuminate\Http\RedirectResponse;

class UpdateVehicleController extends Controller
{
public function __invoke(UpdateVehicleRequest $request, Vehicle $vehicle): RedirectResponse
{
$vehicle->update($request->validated());

if ($request->hasFile('images')) {
foreach ($request->file('images') as $image) {
$vehicle->addMedia($image)->toMediaCollection('images');
}
}

if ($request->has('remove_images')) {
$vehicle->media()
->whereIn('id', $request->input('remove_images'))
->each(fn ($media) => $media->delete());
}

return to_route('vehicles.show', $vehicle);
}
}
65 changes: 65 additions & 0 deletions app/Http/Requests/Vehicle/StoreVehicleRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace App\Http\Requests\Vehicle;

use App\Enums\FuelType;
use App\Enums\Transmission;
use App\Enums\VehicleStatus;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class StoreVehicleRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}

/**
* @return array<string, mixed>
*/
public function rules(): array
{
$currentYear = (int) date('Y');

return [
'model_version_id' => ['required', 'exists:model_versions,id'],
'year' => ['required', 'integer', 'min:1900', 'max:'.($currentYear + 1)],
'price' => ['required', 'numeric', 'min:0'],
'mileage' => ['required', 'integer', 'min:0'],
'color' => ['required', 'string', 'max:50'],
'fuel_type' => ['required', Rule::enum(FuelType::class)],
'transmission' => ['required', Rule::enum(Transmission::class)],
'description' => ['nullable', 'string', 'max:5000'],
'status' => ['required', Rule::enum(VehicleStatus::class)],
'images' => ['nullable', 'array'],
'images.*' => ['image', 'max:5120'],
];
}

/**
* @return array<string, string>
*/
public function messages(): array
{
return [
'model_version_id.required' => 'Selecione uma versão do modelo.',
'model_version_id.exists' => 'A versão selecionada não existe.',
'year.required' => 'O ano é obrigatório.',
'year.min' => 'O ano deve ser no mínimo 1900.',
'year.max' => 'O ano não pode ser maior que o próximo ano.',
'price.required' => 'O preço é obrigatório.',
'price.min' => 'O preço deve ser um valor positivo.',
'mileage.required' => 'A quilometragem é obrigatória.',
'mileage.min' => 'A quilometragem deve ser um valor positivo.',
'color.required' => 'A cor é obrigatória.',
'color.max' => 'A cor deve ter no máximo 50 caracteres.',
'fuel_type.required' => 'O tipo de combustível é obrigatório.',
'transmission.required' => 'O tipo de câmbio é obrigatório.',
'description.max' => 'A descrição deve ter no máximo 5000 caracteres.',
'status.required' => 'O status é obrigatório.',
'images.*.image' => 'Cada arquivo deve ser uma imagem válida.',
'images.*.max' => 'Cada imagem deve ter no máximo 5MB.',
];
}
}
67 changes: 67 additions & 0 deletions app/Http/Requests/Vehicle/UpdateVehicleRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

namespace App\Http\Requests\Vehicle;

use App\Enums\FuelType;
use App\Enums\Transmission;
use App\Enums\VehicleStatus;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class UpdateVehicleRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}

/**
* @return array<string, mixed>
*/
public function rules(): array
{
$currentYear = (int) date('Y');

return [
'model_version_id' => ['required', 'exists:model_versions,id'],
'year' => ['required', 'integer', 'min:1900', 'max:'.($currentYear + 1)],
'price' => ['required', 'numeric', 'min:0'],
'mileage' => ['required', 'integer', 'min:0'],
'color' => ['required', 'string', 'max:50'],
'fuel_type' => ['required', Rule::enum(FuelType::class)],
'transmission' => ['required', Rule::enum(Transmission::class)],
'description' => ['nullable', 'string', 'max:5000'],
'status' => ['required', Rule::enum(VehicleStatus::class)],
'images' => ['nullable', 'array'],
'images.*' => ['image', 'max:5120'],
'remove_images' => ['nullable', 'array'],
'remove_images.*' => ['integer', 'exists:media,id'],
];
}

/**
* @return array<string, string>
*/
public function messages(): array
{
return [
'model_version_id.required' => 'Selecione uma versão do modelo.',
'model_version_id.exists' => 'A versão selecionada não existe.',
'year.required' => 'O ano é obrigatório.',
'year.min' => 'O ano deve ser no mínimo 1900.',
'year.max' => 'O ano não pode ser maior que o próximo ano.',
'price.required' => 'O preço é obrigatório.',
'price.min' => 'O preço deve ser um valor positivo.',
'mileage.required' => 'A quilometragem é obrigatória.',
'mileage.min' => 'A quilometragem deve ser um valor positivo.',
'color.required' => 'A cor é obrigatória.',
'color.max' => 'A cor deve ter no máximo 50 caracteres.',
'fuel_type.required' => 'O tipo de combustível é obrigatório.',
'transmission.required' => 'O tipo de câmbio é obrigatório.',
'description.max' => 'A descrição deve ter no máximo 5000 caracteres.',
'status.required' => 'O status é obrigatório.',
'images.*.image' => 'Cada arquivo deve ser uma imagem válida.',
'images.*.max' => 'Cada imagem deve ter no máximo 5MB.',
];
}
}
1 change: 1 addition & 0 deletions bootstrap/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
api: __DIR__.'/../routes/api.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
Expand Down
Loading
Loading