feat(admin): add product controller
This commit is contained in:
1 parent
d9cb77c6fe
commit
2d8d171f9f
1 file changed
+139
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
namespace Bazaar\Controllers\Admin;
|
||||
|
||||
use Bazaar\Controllers\Controller;
|
||||
use Bazaar\Core\Response;
|
||||
|
||||
final class ProductController extends Controller
|
||||
{
|
||||
public function index(): Response
|
||||
{
|
||||
return $this->view('admin.products.index', [
|
||||
'products' => $this->ctx->products->allForAdmin(),
|
||||
], 'admin.layout');
|
||||
}
|
||||
|
||||
public function create(): Response
|
||||
{
|
||||
return $this->view('admin.products.form', [
|
||||
'product' => null,
|
||||
'categories' => $this->ctx->categories->all(),
|
||||
'errors' => [],
|
||||
], 'admin.layout');
|
||||
}
|
||||
|
||||
public function store(): Response
|
||||
{
|
||||
[$fields, $errors] = $this->validate();
|
||||
if ($errors !== []) {
|
||||
return $this->view('admin.products.form', [
|
||||
'product' => $this->requestSnapshot(),
|
||||
'categories' => $this->ctx->categories->all(),
|
||||
'errors' => $errors,
|
||||
], 'admin.layout', 422);
|
||||
}
|
||||
|
||||
$this->ctx->products->create($fields);
|
||||
$this->ctx->session->flash('success', 'Product created.');
|
||||
return $this->redirect('/admin/products');
|
||||
}
|
||||
|
||||
public function edit(string $id): Response
|
||||
{
|
||||
$product = $this->ctx->products->find((int) $id);
|
||||
if ($product === null) {
|
||||
return $this->notFound();
|
||||
}
|
||||
|
||||
return $this->view('admin.products.form', [
|
||||
'product' => $product,
|
||||
'categories' => $this->ctx->categories->all(),
|
||||
'errors' => [],
|
||||
], 'admin.layout');
|
||||
}
|
||||
|
||||
public function update(string $id): Response
|
||||
{
|
||||
$product = $this->ctx->products->find((int) $id);
|
||||
if ($product === null) {
|
||||
return $this->notFound();
|
||||
}
|
||||
|
||||
[$fields, $errors] = $this->validate();
|
||||
if ($errors !== []) {
|
||||
return $this->view('admin.products.form', [
|
||||
'product' => array_merge($product, $this->requestSnapshot()),
|
||||
'categories' => $this->ctx->categories->all(),
|
||||
'errors' => $errors,
|
||||
], 'admin.layout', 422);
|
||||
}
|
||||
|
||||
$this->ctx->products->update((int) $id, $fields);
|
||||
$this->ctx->session->flash('success', 'Product updated.');
|
||||
return $this->redirect('/admin/products');
|
||||
}
|
||||
|
||||
public function destroy(string $id): Response
|
||||
{
|
||||
$this->ctx->products->delete((int) $id);
|
||||
$this->ctx->session->flash('success', 'Product deleted.');
|
||||
return $this->redirect('/admin/products');
|
||||
}
|
||||
|
||||
private function validate(): array
|
||||
{
|
||||
$request = $this->ctx->request;
|
||||
$name = trim((string) $request->input('name', ''));
|
||||
$categoryId = $request->integer('categoryId');
|
||||
$priceCents = (int) round((float) $request->input('price', 0) * 100);
|
||||
$stockQuantity = $request->integer('stockQuantity');
|
||||
$slug = trim((string) $request->input('slug', ''));
|
||||
if ($slug === '') {
|
||||
$slug = slugify($name);
|
||||
}
|
||||
|
||||
$errors = [];
|
||||
if ($name === '') {
|
||||
$errors['name'] = 'Name is required.';
|
||||
}
|
||||
if ($this->ctx->categories->find($categoryId) === null) {
|
||||
$errors['categoryId'] = 'Select a valid category.';
|
||||
}
|
||||
if ($priceCents < 0) {
|
||||
$errors['price'] = 'Price cannot be negative.';
|
||||
}
|
||||
if ($stockQuantity < 0) {
|
||||
$errors['stockQuantity'] = 'Stock cannot be negative.';
|
||||
}
|
||||
|
||||
$fields = [
|
||||
'categoryId' => $categoryId,
|
||||
'name' => $name,
|
||||
'slug' => $slug,
|
||||
'description' => trim((string) $request->input('description', '')),
|
||||
'priceCents' => $priceCents,
|
||||
'stockQuantity' => $stockQuantity,
|
||||
'imageUrl' => trim((string) $request->input('imageUrl', '')),
|
||||
'isActive' => $request->input('isActive') !== null,
|
||||
];
|
||||
|
||||
return [$fields, $errors];
|
||||
}
|
||||
|
||||
private function requestSnapshot(): array
|
||||
{
|
||||
$request = $this->ctx->request;
|
||||
return [
|
||||
'id' => null,
|
||||
'name' => (string) $request->input('name', ''),
|
||||
'slug' => (string) $request->input('slug', ''),
|
||||
'description' => (string) $request->input('description', ''),
|
||||
'categoryId' => $request->integer('categoryId'),
|
||||
'priceCents' => (int) round((float) $request->input('price', 0) * 100),
|
||||
'stockQuantity' => $request->integer('stockQuantity'),
|
||||
'imageUrl' => (string) $request->input('imageUrl', ''),
|
||||
'isActive' => $request->input('isActive') !== null ? 1 : 0,
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user