Product::with(['prices', 'categories', 'media'])->latest()->paginate(10), 'categories' => Category::active()->get(), ]); } public function create(): Response { return Inertia::render('admin/master/product/create', [ 'categories' => Category::active()->get(), ]); } public function store(ProductRequest $request): RedirectResponse { $validated = $request->validated(); try { DB::transaction(function () use ($request, $validated) { $product = Product::create([ 'name' => $validated['name'], 'description' => $validated['description'], ]); $product->categories()->sync($validated['category_ids'] ?? []); foreach ($validated['prices'] as $type => $price) { $enumType = PriceType::tryFrom($type); if ($enumType) { $product->prices()->create([ 'price_type' => $enumType, 'price' => $price, ]); } } if ($request->hasFile('thumbnail')) { $product->addMediaFromRequest('thumbnail') ->toMediaCollection('thumbnail'); } if ($request->hasFile('images')) { foreach ($request->file('images') as $image) { $product->addMedia($image) ->toMediaCollection('images'); } } }); return redirect()->route('product.index')->with('success', 'Data berhasil disimpan'); } catch (\Throwable $e) { LogHelper::logException($e, 'Failed to store product', [ 'input_summary' => [ 'name' => $request->input('name'), 'categories_count' => count($request->input('category_ids', [])), 'prices_keys' => array_keys($request->input('prices', [])), 'has_thumbnail' => $request->hasFile('thumbnail'), 'images_count' => $request->hasFile('images') ? count($request->file('images')) : 0, ], ]); return redirect() ->back() ->withInput() ->with('error', 'Terjadi kesalahan, silakan hubungi pengembang'); } } public function edit(Product $product): Response { $product->load(['prices', 'categories']); return Inertia::render('admin/master/product/edit', [ 'product' => $product->toArray(), 'categories' => Category::active()->get(), ]); } public function update(ProductRequest $request, Product $product): RedirectResponse { $validated = $request->validated(); try { DB::transaction(function () use ($request, $product, $validated) { $product->update([ 'name' => $validated['name'], 'description' => $validated['description'], 'stock' => $validated['stock'] ?? 0, ]); $product->categories()->sync($validated['category_ids'] ?? []); foreach ($validated['prices'] as $type => $price) { $enumType = PriceType::tryFrom($type); if ($enumType) { $product->prices()->updateOrCreate( ['price_type' => $enumType], ['price' => $price] ); } } if (! empty($validated['delete_image_ids'])) { Media::whereIn('id', $validated['delete_image_ids']) ->where('model_type', Product::class) ->where('model_id', $product->id) ->each(fn ($media) => $media->delete()); } if ($request->hasFile('thumbnail')) { $product->addMediaFromRequest('thumbnail') ->toMediaCollection('thumbnail'); } if ($request->hasFile('images')) { foreach ($request->file('images') as $image) { $product->addMedia($image) ->toMediaCollection('images'); } } }); return redirect()->route('product.index')->with('success', 'Data berhasil diperbarui'); } catch (\Throwable $e) { LogHelper::logException($e, 'Failed to update product', [ 'product_id' => $product->id, 'input_summary' => [ 'name' => $request->input('name'), 'categories_count' => count($request->input('category_ids', [])), 'prices_keys' => array_keys($request->input('prices', [])), 'has_thumbnail' => $request->hasFile('thumbnail'), ], ]); return redirect() ->back() ->withInput() ->with('error', 'Terjadi kesalahan, silakan hubungi pengembang'); } } public function destroy(Product $product): RedirectResponse { $product->delete(); return redirect()->back()->with('success', 'Data berhasil dihapus'); } public function bulkDestroy(Request $request): RedirectResponse { $ids = $request->input('ids'); Product::whereIn('id', $ids)->delete(); return redirect()->back()->with('success', 'Data terpilih berhasil dihapus'); } public function toggleStatus(Product $product): RedirectResponse { $product->update([ 'is_active' => ! $product->is_active, ]); return redirect()->back()->with('success', 'Status berhasil diperbarui'); } }