filled('filter')) { $filter = $request->get('filter'); if ($filter === 'expired') { // Menampilkan makanan yang sudah kadaluwarsa $query->whereNotNull('expired_at')->where('expired_at', '<', $now); } elseif ($filter === 'expiring_soon') { // Menampilkan yang kadaluwarsa dalam 7 hari kedepan $query->whereNotNull('expired_at') ->whereBetween('expired_at', [$now, $now->copy()->addDays(7)]); } elseif ($filter === 'low_stock') { // Menampilkan stok kritis $query->where('qty', '<=', 5); } } // 2. SEARCH GLOBAL if ($request->filled('search')) { $search = $request->search; $query->where(function($q) use ($search) { $q->where('nama_makanan', 'like', "%{$search}%") ->orWhere('kategori', 'like', "%{$search}%") ->orWhere('unit', 'like', "%{$search}%"); }); } // 3. SORTING DINAMIS (Menambahkan kembali expired_at) $allowedSorts = ['nama_makanan', 'qty', 'expired_at', 'created_at']; $sort = in_array($request->get('sort'), $allowedSorts) ? $request->get('sort') : 'nama_makanan'; $direction = strtolower($request->get('direction')) === 'desc' ? 'desc' : 'asc'; $foods = $query->orderBy($sort, $direction) ->paginate(15) ->withQueryString(); // 4. STATISTIK (Komprehensif) $totalStock = Food::sum('qty'); $lowStockCount = Food::where('qty', '<=', 5)->count(); // Hitung item yang expired (Wajib ada kolom expired_at di database) $expiredCount = Food::whereNotNull('expired_at') ->where('expired_at', '<', $now) ->count(); $totalItems = Food::count(); return view('pages.inventory.foods.index', compact( 'foods', 'totalStock', 'lowStockCount', 'expiredCount', 'totalItems' )); } /** * Tampilkan form tambah. */ public function create(): View { return view('pages.inventory.foods.create'); } /** * Simpan data makanan baru. */ public function store(Request $request): RedirectResponse { $validated = $request->validate([ 'nama_makanan' => 'required|string|max:255', 'qty' => 'required|numeric|min:0', 'unit' => 'required|string|max:50', 'expired_date' => 'nullable|date|after_or_equal:today', 'foto_produk' => 'nullable|image|max:1024', ]); if ($request->hasFile('foto_produk')) { $validated['foto_produk'] = $request->file('foto_produk')->store('foods', 'public'); } // Simpan data & tangkap objeknya untuk logging $food = Food::create($validated); // Tambahkan Log Aktivitas (Sangat penting untuk audit stok) $this->logAction('CREATED_FOOD', $food, "Menambah stok pakan baru: {$food->nama_makanan}"); // FIX: Tambahkan .index agar tidak error RouteNotFound return redirect()->route('inventory.foods.index')->with('success', 'Stok pakan berhasil ditambahkan.'); } /** * Tampilkan form edit. */ public function edit(Food $food): View { $categories = Category::all(); return view('pages.inventory.foods.edit', compact('food', 'categories')); } /** * Update data makanan. */ public function update(Request $request, Food $food): RedirectResponse { $validated = $request->validate([ 'nama_makanan' => 'required|string|max:255', 'qty' => 'required|numeric|min:0', 'unit' => 'required|string|max:50', 'category_id' => 'nullable|exists:categories,id', 'expired_date' => 'nullable|date|after_or_equal:today', 'foto_produk' => 'nullable|image|max:1024', ]); if ($request->hasFile('foto_produk')) { if ($food->foto_produk) { Storage::disk('public')->delete($food->foto_produk); } $validated['foto_produk'] = $request->file('foto_produk')->store('foods', 'public'); } $food->update($validated); $this->logAction('UPDATED_FOOD', $food, "Memperbarui stok pakan: {$food->nama_makanan}"); // FIX: Tambahkan .index return redirect()->route('inventory.foods.index')->with('success', 'Data stok pakan berhasil diperbarui.'); } /** * Hapus data makanan. */ public function destroy(Food $food): RedirectResponse { if (auth()->user()->role !== 'admin') { abort(403, 'Hanya Admin yang dapat menghapus data stok pakan.'); } $foodName = $food->nama_makanan; if ($food->foto_produk) { Storage::disk('public')->delete($food->foto_produk); } // Log dilakukan SEBELUM delete $this->logAction('DELETED_FOOD', $food, "Menghapus data pakan: {$foodName}"); $food->delete(); // FIX: Tambahkan .index return redirect()->route('inventory.foods.index')->with('success', 'Stok pakan berhasil dihapus.'); } }