feat(catalog): add catalog and review controllers
This commit is contained in:
1 parent
fa11ab995c
commit
3c7288404c
2 files changed
+113
No files matched your search
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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']);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user