Polish business FA layout and wire special-group keys plus SSL sync.
RTL carousels/FABs, special key+title fields, slider gallery fixes, and dashboard SSL sync agent for super-admin. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
66004a0fba
commit
672091d1f5
@@ -1,5 +1,7 @@
|
||||
import { useId } from 'react'
|
||||
import { Pencil, Percent, Sparkles, Trash2 } from 'lucide-react'
|
||||
import { useLocale } from '@meshkee/dashboard-ui'
|
||||
import { useT } from '../i18n/useT'
|
||||
import {
|
||||
formatVariantCount,
|
||||
type StoreProductListing,
|
||||
@@ -63,9 +65,21 @@ export function StoreItemCard({
|
||||
onFestival,
|
||||
onRemove,
|
||||
onAddToCart,
|
||||
removeTooltip = 'Remove from store',
|
||||
removeTooltip,
|
||||
}: StoreItemCardProps) {
|
||||
const t = useT()
|
||||
const { locale } = useLocale()
|
||||
const isFa = locale === 'fa'
|
||||
const plusGradientId = `add-cart-gradient-${useId().replace(/:/g, '')}`
|
||||
const removeLabel = removeTooltip ?? t('storeItems.card.remove')
|
||||
const primaryName = isFa
|
||||
? listing.productNameFa || listing.productTitle
|
||||
: listing.productTitle
|
||||
const secondaryName = isFa
|
||||
? listing.productNameFa
|
||||
? listing.productTitle
|
||||
: ''
|
||||
: listing.productNameFa
|
||||
|
||||
return (
|
||||
<article className={styles.card}>
|
||||
@@ -74,23 +88,43 @@ export function StoreItemCard({
|
||||
{listing.productImage ? (
|
||||
<img
|
||||
src={listing.productImage}
|
||||
alt={listing.productTitle}
|
||||
alt={primaryName}
|
||||
className={styles.image}
|
||||
loading="lazy"
|
||||
/>
|
||||
) : (
|
||||
<div className={styles.imagePlaceholder} />
|
||||
)}
|
||||
{listing.showFestival && <span className={styles.festivalBadge}>Festival</span>}
|
||||
{listing.showFestival && (
|
||||
<span className={styles.festivalBadge}>{t('storeItems.card.festival')}</span>
|
||||
)}
|
||||
{listing.productTotalStock > 0 && (
|
||||
<span className={styles.stockBadge}>{listing.productTotalStock} in stock</span>
|
||||
<span className={styles.stockBadge}>
|
||||
{t('storeItems.card.inStock', { count: listing.productTotalStock })}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className={styles.body}>
|
||||
<h3 className={styles.nameEn}>{listing.productTitle}</h3>
|
||||
{listing.productNameFa && <p className={styles.nameFa}>{listing.productNameFa}</p>}
|
||||
<p className={styles.variantLabel}>{formatVariantCount(listing.variantCount)}</p>
|
||||
<div
|
||||
className={`${styles.body}${isFa ? '' : ` ${styles.bodyLtr}`}`}
|
||||
dir={isFa ? 'rtl' : 'ltr'}
|
||||
>
|
||||
{isFa ? (
|
||||
<>
|
||||
<h3 className={styles.nameFa}>{primaryName}</h3>
|
||||
{secondaryName ? <p className={styles.nameEn}>{secondaryName}</p> : null}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<h3 className={styles.nameEnPrimary}>{primaryName}</h3>
|
||||
{secondaryName ? (
|
||||
<p className={styles.nameFaSecondary}>{secondaryName}</p>
|
||||
) : null}
|
||||
</>
|
||||
)}
|
||||
<p className={styles.variantLabel}>
|
||||
{formatVariantCount(listing.variantCount, locale)}
|
||||
</p>
|
||||
<StoreItemPrice
|
||||
price={listing.displayPrice}
|
||||
discountedPrice={listing.displayDiscountedPrice}
|
||||
@@ -100,44 +134,52 @@ export function StoreItemCard({
|
||||
|
||||
<div className={styles.controls} onClick={(e) => e.stopPropagation()}>
|
||||
<div className={styles.controlsLeft}>
|
||||
<Tooltip label="Edit store items">
|
||||
<button type="button" onClick={() => onEdit(listing)} aria-label="Edit store items">
|
||||
<Tooltip label={t('storeItems.card.edit')}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onEdit(listing)}
|
||||
aria-label={t('storeItems.card.edit')}
|
||||
>
|
||||
<Pencil size={16} />
|
||||
</button>
|
||||
</Tooltip>
|
||||
<Tooltip label="Set discounts">
|
||||
<button type="button" onClick={() => onDiscount(listing)} aria-label="Set discounts">
|
||||
<Tooltip label={t('storeItems.card.discount')}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onDiscount(listing)}
|
||||
aria-label={t('storeItems.card.discount')}
|
||||
>
|
||||
<Percent size={16} />
|
||||
</button>
|
||||
</Tooltip>
|
||||
<Tooltip label="Festival reward points">
|
||||
<Tooltip label={t('storeItems.card.festivalPoints')}>
|
||||
<button
|
||||
type="button"
|
||||
className={listing.showFestival ? styles.festivalActive : undefined}
|
||||
onClick={() => onFestival(listing)}
|
||||
aria-label="Festival reward points"
|
||||
aria-label={t('storeItems.card.festivalPoints')}
|
||||
>
|
||||
<Sparkles size={16} />
|
||||
</button>
|
||||
</Tooltip>
|
||||
<Tooltip label={removeTooltip}>
|
||||
<Tooltip label={removeLabel}>
|
||||
<button
|
||||
type="button"
|
||||
className={styles.danger}
|
||||
onClick={() => onRemove(listing)}
|
||||
aria-label={removeTooltip}
|
||||
aria-label={removeLabel}
|
||||
>
|
||||
<Trash2 size={16} />
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<Tooltip label="Add to shopping cart">
|
||||
<Tooltip label={t('storeItems.card.addToCart')}>
|
||||
<button
|
||||
type="button"
|
||||
className={styles.addToCartBtn}
|
||||
onClick={() => onAddToCart(listing)}
|
||||
aria-label="Add to shopping cart"
|
||||
aria-label={t('storeItems.card.addToCart')}
|
||||
>
|
||||
<GradientPlusIcon gradientId={plusGradientId} />
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user