245 lines
7.9 KiB
PHP
245 lines
7.9 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\Product;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Storage;
|
|
|
|
class ProductController extends Controller
|
|
{
|
|
// Tampilkan daftar produk (Admin) - UPDATED dengan search dan filter
|
|
public function index(Request $request)
|
|
{
|
|
$query = Product::orderBy('created_at', 'desc');
|
|
|
|
// Search functionality
|
|
if ($request->filled('search')) {
|
|
$query->search($request->search);
|
|
}
|
|
|
|
// Filter by category
|
|
if ($request->filled('category')) {
|
|
$query->byCategory($request->category);
|
|
}
|
|
|
|
// Filter by status
|
|
if ($request->filled('status')) {
|
|
$query->where('status', $request->status);
|
|
}
|
|
|
|
$products = $query->paginate(10);
|
|
|
|
// Append query parameters to pagination links
|
|
$products->appends($request->query());
|
|
|
|
return view('admin.products.index', compact('products'));
|
|
}
|
|
|
|
// Form tambah produk
|
|
public function create()
|
|
{
|
|
return view('admin.products.create');
|
|
}
|
|
|
|
// Simpan produk baru - UPDATED dengan auto label
|
|
public function store(Request $request)
|
|
{
|
|
$request->validate([
|
|
'name' => 'required|string|max:255',
|
|
'category' => 'required|string|max:100',
|
|
'price' => 'required|numeric|min:0',
|
|
'stock' => 'required|integer|min:0',
|
|
'status' => 'required|in:aktif,nonaktif',
|
|
'description' => 'nullable|string',
|
|
'image' => 'nullable|image|mimes:jpg,png,jpeg,gif|max:4048'
|
|
], [
|
|
'name.required' => 'Nama produk wajib diisi',
|
|
'category.required' => 'Kategori wajib dipilih',
|
|
'price.required' => 'Harga wajib diisi',
|
|
'price.numeric' => 'Harga harus berupa angka',
|
|
'stock.required' => 'Stok wajib diisi',
|
|
'stock.integer' => 'Stok harus berupa angka bulat',
|
|
'status.required' => 'Status wajib dipilih',
|
|
'image.image' => 'File harus berupa gambar',
|
|
'image.max' => 'Ukuran gambar maksimal 4MB',
|
|
'image.mimes' => 'Format gambar harus JPG, PNG, JPEG, atau GIF'
|
|
]);
|
|
|
|
$data = $request->only([
|
|
'name',
|
|
'category',
|
|
'price',
|
|
'stock',
|
|
'status',
|
|
'description'
|
|
]);
|
|
|
|
// Upload gambar jika ada
|
|
if ($request->hasFile('image')) {
|
|
$gambar = $request->file('image');
|
|
$filename = time() . '_' . $gambar->getClientOriginalName();
|
|
$path = $gambar->storeAs('products', $filename, 'public');
|
|
$data['image'] = $path;
|
|
}
|
|
|
|
// Set default values
|
|
$data['sold'] = 0;
|
|
|
|
try {
|
|
$product = Product::create($data);
|
|
|
|
// Auto set label based on stock
|
|
$product->updateLabelBasedOnStock();
|
|
$product->save();
|
|
$this->syncLabelAfterSave($product);
|
|
|
|
return redirect()->route('admin.products.index')
|
|
->with('success', 'Produk berhasil ditambahkan!');
|
|
} catch (\Exception $e) {
|
|
return redirect()->back()
|
|
->withErrors(['error' => $e->getMessage()])
|
|
->withInput();
|
|
}
|
|
}
|
|
|
|
// Tampilkan detail produk
|
|
// public function show($id)
|
|
// {
|
|
// $product = Product::findOrFail($id);
|
|
// return view('admin.products.show', compact('product'));
|
|
// }
|
|
|
|
// Form edit produk
|
|
public function edit(Product $product)
|
|
{
|
|
return view('admin.products.edit', compact('product'));
|
|
}
|
|
|
|
// Ganti method update yang lama dengan yang ini:
|
|
public function update(Request $request, Product $product)
|
|
{
|
|
$request->validate([
|
|
'name' => 'required|string|max:255',
|
|
'category' => 'required|string|max:100',
|
|
'price' => 'required|numeric|min:0',
|
|
'stock' => 'required|integer|min:0',
|
|
'status' => 'required|in:aktif,nonaktif',
|
|
'description' => 'nullable|string',
|
|
'image' => 'nullable|image|mimes:jpg,png,jpeg,gif|max:2048'
|
|
], [
|
|
'name.required' => 'Nama produk wajib diisi',
|
|
'category.required' => 'Kategori wajib dipilih',
|
|
'price.required' => 'Harga wajib diisi',
|
|
'price.numeric' => 'Harga harus berupa angka',
|
|
'stock.required' => 'Stok wajib diisi',
|
|
'stock.integer' => 'Stok harus berupa angka bulat',
|
|
'status.required' => 'Status wajib dipilih',
|
|
'image.image' => 'File harus berupa gambar',
|
|
'image.max' => 'Ukuran gambar maksimal 2MB',
|
|
'image.mimes' => 'Format gambar harus JPG, PNG, JPEG, atau GIF'
|
|
]);
|
|
|
|
$data = $request->only([
|
|
'name',
|
|
'category',
|
|
'price',
|
|
'stock',
|
|
'status',
|
|
'description'
|
|
]);
|
|
|
|
// Upload gambar baru jika ada
|
|
if ($request->hasFile('image')) {
|
|
// Hapus gambar lama jika ada
|
|
if ($product->image && Storage::disk('public')->exists($product->image)) {
|
|
Storage::disk('public')->delete($product->image);
|
|
}
|
|
|
|
$image = $request->file('image');
|
|
$filename = time() . '_' . $image->getClientOriginalName();
|
|
$path = $image->storeAs('products', $filename, 'public');
|
|
$data['image'] = $path;
|
|
}
|
|
|
|
try {
|
|
$product->update($data);
|
|
|
|
// Auto update label based on new stock
|
|
$product->updateLabelBasedOnStock();
|
|
$product->save();
|
|
$this->syncLabelAfterSave($product);
|
|
|
|
return redirect()->route('admin.products.index')
|
|
->with('success', 'Produk berhasil diupdate!');
|
|
} catch (\Exception $e) {
|
|
return redirect()->back()
|
|
->withErrors(['error' => 'Terjadi kesalahan saat mengupdate produk'])
|
|
->withInput();
|
|
}
|
|
}
|
|
|
|
// Juga ubah method show dan destroy untuk konsistensi:
|
|
public function show(Product $product)
|
|
{
|
|
return view('admin.products.show', compact('product'));
|
|
}
|
|
|
|
public function destroy(Product $product)
|
|
{
|
|
// Hapus gambar dari storage sebelum menghapus record
|
|
if ($product->image && Storage::disk('public')->exists($product->image)) {
|
|
Storage::disk('public')->delete($product->image);
|
|
}
|
|
|
|
$product->delete();
|
|
|
|
return redirect()->route('admin.products.index')
|
|
->with('success', 'Produk berhasil dihapus');
|
|
}
|
|
// Tampilkan detail produk untuk user (public)
|
|
public function publicShow($id)
|
|
{
|
|
$product = Product::where('status', 'aktif')->findOrFail($id);
|
|
return view('products.show', compact('product'));
|
|
}
|
|
// NEW: Method untuk debugging gambar
|
|
public function debugImage($id)
|
|
{
|
|
$product = Product::findOrFail($id);
|
|
|
|
$debug = [
|
|
'product_id' => $product->id,
|
|
'image_field' => $product->image,
|
|
'image_url' => $product->image_url,
|
|
'storage_path' => $product->image ? storage_path('app/public/' . $product->image) : null,
|
|
'file_exists' => $product->image ? Storage::disk('public')->exists($product->image) : false,
|
|
'public_path' => $product->image ? public_path('storage/' . $product->image) : null,
|
|
];
|
|
|
|
return response()->json($debug);
|
|
}
|
|
/**
|
|
* Cek apakah produk ini termasuk top 10 terlaris, jika iya set label terlaris
|
|
*/
|
|
private function syncLabelAfterSave(Product $product)
|
|
{
|
|
if ($product->stock <= 0) {
|
|
return; // Sudah di-handle updateLabelBasedOnStock
|
|
}
|
|
|
|
$bestSellingIds = \Illuminate\Support\Facades\DB::table('transaksi_details')
|
|
->select('product_id', \Illuminate\Support\Facades\DB::raw('SUM(quantity) as total_sold'))
|
|
->groupBy('product_id')
|
|
->orderByDesc('total_sold')
|
|
->take(10)
|
|
->pluck('product_id')
|
|
->toArray();
|
|
|
|
if (in_array($product->id, $bestSellingIds)) {
|
|
$product->label = 'terlaris';
|
|
$product->save();
|
|
}
|
|
}
|
|
|
|
} |