feat(catalog): add catalog and review controllers

This commit is contained in:
dualfroz committed 2026-08-25 15:03:10 +02:00
1 parent fa11ab995c
commit 3c7288404c
2 files changed
+113

No files matched your search

+81
View File
@@ -0,0 +1,81 @@
<?php
namespace Bazaar\Controllers;
use Bazaar\Core\Response;
final class CatalogController extends Controller
{
public function index(): Response
{
$request = $this->ctx->request;
$criteria = [
'categorySlug' => (string) $request->query('category', ''),
'term' => (string) $request->query('q', ''),
'sort' => (string) $request->query('sort', 'newest'),
'page' => max(1, (int) $request->query('page', 1)),
'attributeSelections' => $this->parseAttributeSelections($request->query('attr', [])),
];
$minPrice = $request->query('minPrice');
$maxPrice = $request->query('maxPrice');
if (is_numeric($minPrice)) {
$criteria['minPriceCents'] = (int) round((float) $minPrice * 100);
}
if (is_numeric($maxPrice)) {
$criteria['maxPriceCents'] = (int) round((float) $maxPrice * 100);
}
$result = $this->ctx->productSearch->search($criteria);
$wishlisted = $this->ctx->auth->check()
? $this->ctx->wishlist->productIdsForUser((int) $this->ctx->auth->id())
: [];
return $this->view('catalog.index', [
'result' => $result,
'activeCategory' => $criteria['categorySlug'],
'term' => $criteria['term'],
'sort' => $criteria['sort'],
'minPrice' => is_numeric($minPrice) ? $minPrice : '',
'maxPrice' => is_numeric($maxPrice) ? $maxPrice : '',
'wishlisted' => $wishlisted,
]);
}
public function show(string $slug): Response
{
$product = $this->ctx->products->findBySlug($slug);
if ($product === null) {
return $this->notFound();
}
$productId = (int) $product['id'];
$userId = $this->ctx->auth->check() ? (int) $this->ctx->auth->id() : null;
return $this->view('catalog.show', [
'product' => $product,
'variants' => $this->ctx->variants->activeForProduct($productId),
'reviewSummary' => $this->ctx->reviews->summary($productId),
'reviews' => $this->ctx->reviews->approvedForProduct($productId),
'inWishlist' => $userId !== null && $this->ctx->wishlist->has($userId, $productId),
'reviewEligibility' => $userId !== null
? $this->ctx->reviewService->eligibility($userId, $productId)
: null,
]);
}
private function parseAttributeSelections(mixed $raw): array
{
if (!is_array($raw)) {
return [];
}
$selections = [];
foreach ($raw as $attributeSlug => $values) {
$selections[(string) $attributeSlug] = array_values(array_filter(
array_map('strval', (array) $values),
static fn (string $value): bool => $value !== ''
));
}
return $selections;
}
}
+32
View File
@@ -0,0 +1,32 @@
<?php
namespace Bazaar\Controllers;
use Bazaar\Core\Response;
final class ReviewController extends Controller
{
public function store(): Response
{
$request = $this->ctx->request;
$productId = $request->integer('productId');
$product = $this->ctx->products->findActive($productId);
if ($product === null) {
return $this->notFound();
}
$userId = (int) $this->ctx->auth->id();
if (!$this->ctx->reviewService->canReview($userId, $productId)) {
$this->ctx->session->flash('error', $this->ctx->translator->get('product.reviewGateBuy'));
return $this->redirect('/products/' . $product['slug']);
}
$rating = max(1, min(5, $request->integer('rating', 5)));
$title = trim((string) $request->input('title', ''));
$body = trim((string) $request->input('body', ''));
$this->ctx->reviewService->submit($userId, $productId, $rating, $title, $body);
$this->ctx->session->flash('success', $this->ctx->translator->get('product.reviewPending'));
return $this->redirect('/products/' . $product['slug']);
}
}