TA/web_JMW/app/Http/Controllers/CategoryController.php

260 lines
9.4 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\Category;
use App\Models\Favorite;
use App\Services\CarRecommendationService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class CategoryController extends Controller
{
public function index()
{
Category::releaseExpiredReservations();
$categories = Category::orderBy('created_at', 'desc')->get();
return view('admin.kategori', compact('categories'));
}
public function store(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'description' => 'required|string|max:1000',
'merk' => 'nullable|string|max:255',
'model' => 'nullable|string|max:255',
'kategori' => 'nullable|string|max:255',
'price' => 'required|numeric|min:0',
'year' => 'required|integer|min:1900|max:' . date('Y'),
'mesin_cc' => 'nullable|integer|min:0',
'transmisi' => 'nullable|string|max:255',
'bahan_bakar' => 'nullable|string|max:255',
'status' => 'required|in:available,reserved,sold',
'image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048',
], [
'name.required' => 'Nama kategori wajib diisi.',
'description.required' => 'Deskripsi kategori wajib diisi.',
'price.required' => 'Harga mobil wajib diisi.',
'price.numeric' => 'Harga mobil harus berupa angka.',
'price.min' => 'Harga mobil tidak boleh negatif.',
'year.required' => 'Tahun mobil wajib diisi.',
'year.integer' => 'Tahun mobil harus berupa angka.',
'year.min' => 'Tahun mobil tidak valid.',
'year.max' => 'Tahun mobil tidak valid.',
'status.required' => 'Status mobil wajib dipilih.',
'status.in' => 'Status mobil tidak valid.',
'image.image' => 'File harus berupa gambar.',
'image.mimes' => 'Format gambar harus jpeg, png, jpg, atau gif.',
'image.max' => 'Ukuran gambar maksimal 2MB.',
]);
if ($request->hasFile('image')) {
$validated['image'] = $request->file('image')->store('categories', 'public');
}
Category::create($validated);
return redirect()->route('kategori')->with('success', 'Kategori berhasil ditambahkan.');
}
public function edit(Category $category)
{
return view('admin.kategori-edit', compact('category'));
}
public function update(Request $request, Category $category)
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'description' => 'required|string|max:1000',
'merk' => 'nullable|string|max:255',
'model' => 'nullable|string|max:255',
'kategori' => 'nullable|string|max:255',
'price' => 'required|numeric|min:0',
'year' => 'required|integer|min:1900|max:' . date('Y'),
'mesin_cc' => 'nullable|integer|min:0',
'transmisi' => 'nullable|string|max:255',
'bahan_bakar' => 'nullable|string|max:255',
'status' => 'required|in:available,reserved,sold',
'image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048',
], [
'name.required' => 'Nama kategori wajib diisi.',
'description.required' => 'Deskripsi kategori wajib diisi.',
'price.required' => 'Harga mobil wajib diisi.',
'price.numeric' => 'Harga mobil harus berupa angka.',
'price.min' => 'Harga mobil tidak boleh negatif.',
'year.required' => 'Tahun mobil wajib diisi.',
'year.integer' => 'Tahun mobil harus berupa angka.',
'year.min' => 'Tahun mobil tidak valid.',
'year.max' => 'Tahun mobil tidak valid.',
'status.required' => 'Status mobil wajib dipilih.',
'status.in' => 'Status mobil tidak valid.',
'image.image' => 'File harus berupa gambar.',
'image.mimes' => 'Format gambar harus jpeg, png, jpg, atau gif.',
'image.max' => 'Ukuran gambar maksimal 2MB.',
]);
if ($request->hasFile('image')) {
if ($category->image) {
Storage::disk('public')->delete($category->image);
}
$validated['image'] = $request->file('image')->store('categories', 'public');
}
$category->update($validated);
return redirect()->route('kategori')->with('success', 'Kategori berhasil diperbarui.');
}
public function destroy(Category $category)
{
if ($category->image) {
Storage::disk('public')->delete($category->image);
}
$category->delete();
return redirect()->route('kategori')->with('success', 'Kategori berhasil dihapus.');
}
public function userIndex(Request $request, CarRecommendationService $recommendationService)
{
Category::releaseExpiredReservations();
$budget = $request->query('budget');
$budgetValue = is_numeric($budget) ? (float) $budget : null;
$year = $request->query('year');
$yearValue = is_numeric($year) ? (int) $year : null;
$mesinCc = $request->query('mesin_cc');
$mesinCcValue = is_numeric($mesinCc) ? (int) $mesinCc : null;
$categories = Category::where('status', 'available')->orderBy('created_at', 'desc')->get();
$hasExactBudgetMatch = false;
$recommendationSource = null;
$recommendationMeta = null;
if ($budgetValue) {
$recommendation = $recommendationService->recommendForBudget($budgetValue, 50, [
'year' => $yearValue,
'mesin_cc' => $mesinCcValue,
]);
$recommended = $recommendation['cars'];
$hasExactBudgetMatch = $recommendation['has_exact_budget_match'];
$recommendationSource = $recommendation['source'];
$recommendationMeta = $recommendation['meta'];
} else {
$recommended = Category::where('status', 'available')
->orderBy('created_at', 'desc')
->get();
}
return view('user.cars', compact(
'categories',
'recommended',
'budget',
'year',
'mesinCc',
'hasExactBudgetMatch',
'recommendationSource',
'recommendationMeta'
));
}
public function allCars()
{
Category::releaseExpiredReservations();
$categories = Category::where('status', 'available')
->orderBy('created_at', 'desc')
->paginate(12);
return view('user.all-cars', compact('categories'));
}
public function budgetCars(Request $request, CarRecommendationService $recommendationService)
{
Category::releaseExpiredReservations();
$budget = $request->query('budget');
$budgetValue = is_numeric($budget) ? (float) $budget : null;
$year = $request->query('year');
$yearValue = is_numeric($year) ? (int) $year : null;
$mesinCc = $request->query('mesin_cc');
$mesinCcValue = is_numeric($mesinCc) ? (int) $mesinCc : null;
$availableCount = Category::where('status', 'available')->count();
$hasExactBudgetMatch = false;
$recommendationSource = null;
$recommendationMeta = null;
$recommended = collect();
if ($budgetValue) {
$recommendation = $recommendationService->recommendForBudget($budgetValue, 50, [
'year' => $yearValue,
'mesin_cc' => $mesinCcValue,
]);
$recommended = $recommendation['cars'];
$hasExactBudgetMatch = $recommendation['has_exact_budget_match'];
$recommendationSource = $recommendation['source'];
$recommendationMeta = $recommendation['meta'];
}
return view('user.budget-cars', compact(
'budget',
'year',
'mesinCc',
'availableCount',
'recommended',
'hasExactBudgetMatch',
'recommendationSource',
'recommendationMeta'
));
}
public function show(Category $category)
{
Category::releaseExpiredReservations();
$category->refresh();
return view('user.car-detail', compact('category'));
}
public function addToFavorites(Category $category)
{
Category::releaseExpiredReservations();
$category->refresh();
$username = auth()->user()->username;
if ($category->status !== 'available') {
return response()->json(['message' => 'Mobil ini sedang tidak tersedia.'], 422);
}
// Check if already favorited
if (Favorite::where('username', $username)->where('category_id', $category->id)->exists()) {
return response()->json(['message' => 'Already in favorites'], 409);
}
Favorite::create([
'username' => $username,
'category_id' => $category->id,
]);
return response()->json(['message' => 'Added to favorites']);
}
public function removeFromFavorites(Category $category)
{
$username = auth()->user()->username;
Favorite::where('username', $username)
->where('category_id', $category->id)
->delete();
return response()->json(['message' => 'Removed from favorites']);
}
}