feat(admin): add coupon, order and review controllers
This commit is contained in:
1 parent
bffd4c82c7
commit
ed2f18bb14
3 files changed
+158
No files matched your search
@@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Bazaar\Controllers\Admin;
|
||||||
|
|
||||||
|
use Bazaar\Controllers\Controller;
|
||||||
|
use Bazaar\Core\Response;
|
||||||
|
|
||||||
|
final class CouponController extends Controller
|
||||||
|
{
|
||||||
|
public function index(): Response
|
||||||
|
{
|
||||||
|
return $this->view('admin.coupons.index', [
|
||||||
|
'coupons' => $this->ctx->coupons->all(),
|
||||||
|
], 'admin.layout');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(): Response
|
||||||
|
{
|
||||||
|
return $this->view('admin.coupons.form', ['errors' => []], 'admin.layout');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(): Response
|
||||||
|
{
|
||||||
|
[$fields, $errors] = $this->validate();
|
||||||
|
if ($errors !== []) {
|
||||||
|
return $this->view('admin.coupons.form', ['errors' => $errors], 'admin.layout', 422);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->ctx->coupons->create($fields);
|
||||||
|
$this->ctx->session->flash('success', 'Coupon created.');
|
||||||
|
return $this->redirect('/admin/coupons');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(string $id): Response
|
||||||
|
{
|
||||||
|
$this->ctx->coupons->delete((int) $id);
|
||||||
|
$this->ctx->session->flash('success', 'Coupon deleted.');
|
||||||
|
return $this->redirect('/admin/coupons');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function validate(): array
|
||||||
|
{
|
||||||
|
$request = $this->ctx->request;
|
||||||
|
$code = strtoupper(trim((string) $request->input('code', '')));
|
||||||
|
$type = $request->input('type') === 'fixed' ? 'fixed' : 'percent';
|
||||||
|
$rawValue = (float) $request->input('value', 0);
|
||||||
|
$value = $type === 'percent' ? (int) round($rawValue) : (int) round($rawValue * 100);
|
||||||
|
$maxRedemptions = $request->input('maxRedemptions', '');
|
||||||
|
|
||||||
|
$errors = [];
|
||||||
|
if ($code === '') {
|
||||||
|
$errors['code'] = 'Code is required.';
|
||||||
|
} elseif ($this->ctx->coupons->findByCode($code) !== null) {
|
||||||
|
$errors['code'] = 'A coupon with this code already exists.';
|
||||||
|
}
|
||||||
|
if ($type === 'percent' && ($value < 1 || $value > 100)) {
|
||||||
|
$errors['value'] = 'Percent must be between 1 and 100.';
|
||||||
|
}
|
||||||
|
if ($type === 'fixed' && $value < 1) {
|
||||||
|
$errors['value'] = 'Amount must be greater than zero.';
|
||||||
|
}
|
||||||
|
|
||||||
|
$fields = [
|
||||||
|
'code' => $code,
|
||||||
|
'type' => $type,
|
||||||
|
'value' => $value,
|
||||||
|
'minSubtotalCents' => (int) round((float) $request->input('minSubtotal', 0) * 100),
|
||||||
|
'maxRedemptions' => is_numeric($maxRedemptions) ? (int) $maxRedemptions : null,
|
||||||
|
'startsAt' => $this->normalizeDate((string) $request->input('startsAt', '')),
|
||||||
|
'expiresAt' => $this->normalizeDate((string) $request->input('expiresAt', '')),
|
||||||
|
'isActive' => $request->input('isActive') !== null,
|
||||||
|
];
|
||||||
|
|
||||||
|
return [$fields, $errors];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function normalizeDate(string $value): ?string
|
||||||
|
{
|
||||||
|
$value = trim($value);
|
||||||
|
if ($value === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$timestamp = strtotime($value);
|
||||||
|
return $timestamp === false ? null : gmdate('c', $timestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Bazaar\Controllers\Admin;
|
||||||
|
|
||||||
|
use Bazaar\Controllers\Controller;
|
||||||
|
use Bazaar\Core\Response;
|
||||||
|
|
||||||
|
final class OrderController extends Controller
|
||||||
|
{
|
||||||
|
public function index(): Response
|
||||||
|
{
|
||||||
|
return $this->view('admin.orders.index', [
|
||||||
|
'orders' => $this->ctx->orders->all(),
|
||||||
|
], 'admin.layout');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(string $id): Response
|
||||||
|
{
|
||||||
|
$order = $this->ctx->orders->find((int) $id);
|
||||||
|
if ($order === null) {
|
||||||
|
return $this->notFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->view('admin.orders.show', [
|
||||||
|
'order' => $order,
|
||||||
|
'items' => $this->ctx->orders->items((int) $id),
|
||||||
|
], 'admin.layout');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fulfill(string $id): Response
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->ctx->orderService->markFulfilled((int) $id);
|
||||||
|
$this->ctx->session->flash('success', 'Order marked as fulfilled.');
|
||||||
|
} catch (\RuntimeException $error) {
|
||||||
|
$this->ctx->session->flash('error', $error->getMessage());
|
||||||
|
}
|
||||||
|
return $this->redirect('/admin/orders/' . (int) $id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Bazaar\Controllers\Admin;
|
||||||
|
|
||||||
|
use Bazaar\Controllers\Controller;
|
||||||
|
use Bazaar\Core\Response;
|
||||||
|
|
||||||
|
final class ReviewController extends Controller
|
||||||
|
{
|
||||||
|
public function index(): Response
|
||||||
|
{
|
||||||
|
return $this->view('admin.reviews.index', [
|
||||||
|
'pending' => $this->ctx->reviews->moderationQueue('pending'),
|
||||||
|
'approved' => $this->ctx->reviews->moderationQueue('approved'),
|
||||||
|
'rejected' => $this->ctx->reviews->moderationQueue('rejected'),
|
||||||
|
], 'admin.layout');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function approve(string $id): Response
|
||||||
|
{
|
||||||
|
$this->ctx->reviewService->approve((int) $id);
|
||||||
|
$this->ctx->session->flash('success', 'Review approved.');
|
||||||
|
return $this->redirect('/admin/reviews');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function reject(string $id): Response
|
||||||
|
{
|
||||||
|
$this->ctx->reviewService->reject((int) $id);
|
||||||
|
$this->ctx->session->flash('success', 'Review rejected.');
|
||||||
|
return $this->redirect('/admin/reviews');
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user