- |
+ |
{t('table.title')}
|
-
+ |
{t('table.slug')}
|
-
+ |
{t('table.price')}
|
-
+ |
{t('table.category')}
|
-
+ |
{t('table.type')}
|
-
+ |
{t('table.stock')}
|
-
+ |
{t('table.badge')}
|
-
+ |
{t('table.active')}
|
-
+ |
{t('table.featured')}
|
-
+ |
{t('table.created')}
|
-
+ |
{t('table.actions')}
|
@@ -379,7 +380,9 @@ export default async function AdminProductsPage({
- {row.isFeatured ? t('actions.yes') : t('actions.no')}
+ {row.isFeatured
+ ? t('actions.yes')
+ : t('actions.no')}
|
@@ -388,19 +391,23 @@ export default async function AdminProductsPage({
-
+
{t('actions.view')}
{t('actions.edit')}
diff --git a/frontend/app/[locale]/shop/cart/page.tsx b/frontend/app/[locale]/shop/cart/page.tsx
index 5f22926d..658fe356 100644
--- a/frontend/app/[locale]/shop/cart/page.tsx
+++ b/frontend/app/[locale]/shop/cart/page.tsx
@@ -3,15 +3,56 @@
import { useState } from 'react';
import Image from 'next/image';
import { useParams } from 'next/navigation';
-import { useRouter } from '@/i18n/routing';
+import { useRouter, Link } from '@/i18n/routing';
import { useTranslations } from 'next-intl';
-
+import { cn } from '@/lib/utils';
import { Minus, Plus, Trash2, ShoppingBag } from 'lucide-react';
-import { Link } from '@/i18n/routing';
import { useCart } from '@/components/shop/cart-provider';
import { generateIdempotencyKey } from '@/lib/shop/idempotency';
import { formatMoney } from '@/lib/shop/currency';
+import {
+ SHOP_FOCUS,
+ SHOP_LINK_BASE,
+ SHOP_LINK_MD,
+ SHOP_LINK_XS,
+ SHOP_DISABLED,
+ SHOP_CHIP_INTERACTIVE,
+ SHOP_CHIP_SHADOW_HOVER,
+ SHOP_CHIP_BORDER_HOVER,
+ SHOP_STEPPER_BUTTON_BASE,
+ SHOP_CTA_BASE,
+ SHOP_CTA_INTERACTIVE,
+ SHOP_CTA_INSET,
+ SHOP_CTA_WAVE,
+ shopCtaGradient,
+} from '@/lib/shop/ui-classes';
+
+const SHOP_PRODUCT_LINK = cn(
+ 'block truncate',
+ SHOP_LINK_BASE,
+ SHOP_LINK_MD,
+ SHOP_FOCUS
+);
+
+const SHOP_STEPPER_BTN = cn(
+ SHOP_STEPPER_BUTTON_BASE,
+ 'h-8 w-8',
+ SHOP_CHIP_INTERACTIVE,
+ SHOP_CHIP_SHADOW_HOVER,
+ SHOP_CHIP_BORDER_HOVER,
+ SHOP_FOCUS,
+ SHOP_DISABLED
+);
+
+const SHOP_HERO_CTA = cn(
+ SHOP_CTA_BASE,
+ SHOP_CTA_INTERACTIVE,
+ SHOP_FOCUS,
+ SHOP_DISABLED,
+ 'w-full justify-center gap-2 px-6 py-3 text-sm text-white',
+ 'shadow-[var(--shop-hero-btn-shadow)] hover:shadow-[var(--shop-hero-btn-shadow-hover)]'
+);
export default function CartPage() {
const { cart, updateQuantity, removeFromCart } = useCart();
@@ -32,7 +73,7 @@ export default function CartPage() {
try {
return tColors(colorSlug);
} catch {
- return color;
+ return color;
}
};
@@ -67,9 +108,8 @@ export default function CartPage() {
typeof data?.message === 'string'
? data.message
: typeof data?.error === 'string'
- ? data.error
- : 'Unable to start checkout right now.';
-
+ ? data.error
+ : 'Unable to start checkout right now.';
setCheckoutError(message);
return;
}
@@ -86,7 +126,7 @@ export default function CartPage() {
? data.clientSecret
: null;
- const orderId: string = String(data.orderId);
+ const orderId = String(data.orderId);
setCreatedOrderId(orderId);
if (paymentProvider === 'stripe' && clientSecret) {
@@ -95,7 +135,6 @@ export default function CartPage() {
orderId
)}?clientSecret=${encodeURIComponent(clientSecret)}&clearCart=1`
);
-
return;
}
@@ -120,22 +159,28 @@ export default function CartPage() {
return (
-
+
{t('empty')}
-
- {t('emptyDescription')}
-
-
- {t('startShopping')}
-
+ {t('emptyDescription')}
+
+
+
+
+
+
+ {t('startShopping')}
+
+
);
@@ -162,9 +207,7 @@ export default function CartPage() {
{cart.items.map(item => (
@@ -183,7 +226,7 @@ export default function CartPage() {
{item.title}
@@ -200,11 +243,7 @@ export default function CartPage() {
{item.quantity >= item.stock && (
-
+
{t('actions.maxStock', { stock: item.stock })}
)}
- {formatMoney(
- item.lineTotalMinor,
- item.currency,
- locale
- )}
+ {formatMoney(item.lineTotalMinor, item.currency, locale)}
@@ -278,14 +310,8 @@ export default function CartPage() {
- |