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:
Alireza Hassani
2026-08-03 00:06:44 +03:30
co-authored by Cursor
parent 66004a0fba
commit 672091d1f5
113 changed files with 4154 additions and 1451 deletions
+34 -34
View File
@@ -31,6 +31,8 @@ import {
type StoreProductListing,
} from '../utils/storeProductGroups'
import { formatIrtInput, parseIrtInput } from '../utils/irtPrice'
import { useLocale } from '@meshkee/dashboard-ui'
import { useT } from '../i18n/useT'
import filterStyles from '../components/ListFiltersPanel.module.css'
import pageStyles from '../components/PageContent.module.css'
import styles from './StoreItemsPage.module.css'
@@ -40,6 +42,8 @@ export function StoreItemsPage() {
}
function StoreItemsPageContent() {
const t = useT()
const { locale } = useLocale()
const { itemCount, hasItems, addVariant, loadShoppingCard } = useDraftCart()
const { showToast } = useToast()
const [items, setItems] = useState<StoreItem[]>([])
@@ -139,7 +143,7 @@ function StoreItemsPageContent() {
if (err instanceof ApiError) {
setError(err.message)
} else {
setError('Unable to load store items.')
setError(t('storeItems.errorLoad'))
}
} finally {
setIsLoading(false)
@@ -188,7 +192,7 @@ function StoreItemsPageContent() {
return
}
showToast('Added to shopping cart.', 'success')
showToast(t('storeItems.addedToCart'), 'success')
}
function handleVariantPicked(variant: StoreItem) {
@@ -198,7 +202,7 @@ function StoreItemsPageContent() {
showToast(feedback, 'error')
return
}
showToast('Added to shopping cart.', 'success')
showToast(t('storeItems.addedToCart'), 'success')
}
async function confirmDelete() {
@@ -215,7 +219,7 @@ function StoreItemsPageContent() {
if (err instanceof ApiError) {
setError(err.message)
} else {
setError('Unable to remove store item.')
setError(t('storeItems.errorRemove'))
}
} finally {
setIsDeleting(false)
@@ -234,65 +238,60 @@ function StoreItemsPageContent() {
<div className={pageStyles.pageHeader}>
<div>
<h2 className={pageStyles.pageTitle}>My Store Items</h2>
<p className={pageStyles.pageSubtitle}>
Products for sale with one or more priced variants.
</p>
<h2 className={pageStyles.pageTitle}>{t('title.storeItems')}</h2>
<p className={pageStyles.pageSubtitle}>{t('storeItems.subtitle')}</p>
</div>
</div>
<div className={filterStyles.filtersPanel}>
<div className={filterStyles.filtersTitle}>Filters</div>
<div className={filterStyles.filtersTitle}>{t('storeItems.filters')}</div>
<div className={filterStyles.filtersGrid}>
<div className={filterStyles.filtersInputs}>
<div className={`${filterStyles.field} ${filterStyles.fieldCol3}`}>
<label htmlFor="filter-store-name">Name</label>
<input
id="filter-store-name"
value={draftName}
onChange={(e) => setDraftName(e.target.value)}
placeholder="Search by product name"
placeholder={t('storeItems.filterNamePlaceholder')}
aria-label={t('storeItems.filterName')}
disabled={isLoading}
/>
</div>
<div className={`${filterStyles.field} ${filterStyles.fieldCol2} ${filterStyles.fieldHalfWidth}`}>
<label htmlFor="filter-store-min-price">Min price (IRT)</label>
<input
id="filter-store-min-price"
inputMode="numeric"
value={draftMinPrice}
onChange={(e) => setDraftMinPrice(formatIrtInput(e.target.value))}
placeholder="0"
placeholder={t('storeItems.minPrice')}
aria-label={t('storeItems.minPrice')}
disabled={isLoading}
/>
</div>
<div className={`${filterStyles.field} ${filterStyles.fieldCol2} ${filterStyles.fieldHalfWidth}`}>
<label htmlFor="filter-store-max-price">Max price (IRT)</label>
<input
id="filter-store-max-price"
inputMode="numeric"
value={draftMaxPrice}
onChange={(e) => setDraftMaxPrice(formatIrtInput(e.target.value))}
placeholder="0"
placeholder={t('storeItems.maxPrice')}
aria-label={t('storeItems.maxPrice')}
disabled={isLoading}
/>
</div>
<div className={`${filterStyles.switchField} ${filterStyles.fieldCol3}`}>
<span className={filterStyles.switchFieldSpacer} aria-hidden="true">
Only discounted
</span>
<div className={filterStyles.switchInline}>
<ToggleSwitch
checked={draftOnlyDiscounted}
onChange={setDraftOnlyDiscounted}
disabled={isLoading}
ariaLabel="Only discounted"
ariaLabel={t('storeItems.onlyDiscounted')}
/>
<span
className={filterStyles.switchLabel}
onClick={() => !isLoading && setDraftOnlyDiscounted(!draftOnlyDiscounted)}
>
Only discounted
{t('storeItems.onlyDiscounted')}
</span>
</div>
</div>
@@ -303,8 +302,8 @@ function StoreItemsPageContent() {
className={`${filterStyles.iconActionBtn} ${filterStyles.iconActionBtnPrimary}`}
onClick={applyFilters}
disabled={isLoading}
aria-label="Search"
title="Search"
aria-label={t('storeItems.search')}
title={t('storeItems.search')}
>
<Search size={18} />
</button>
@@ -313,8 +312,8 @@ function StoreItemsPageContent() {
className={`${filterStyles.iconActionBtn} ${filterStyles.iconActionBtnGhost}`}
onClick={clearFilters}
disabled={isLoading}
aria-label="Clear filters"
title="Clear filters"
aria-label={t('storeItems.clearFilters')}
title={t('storeItems.clearFilters')}
>
<RotateCcw size={18} />
</button>
@@ -325,13 +324,11 @@ function StoreItemsPageContent() {
{error && <p className={styles.error}>{error}</p>}
{isLoading ? (
<p className={styles.empty}>Loading store items...</p>
<p className={styles.empty}>{t('storeItems.loading')}</p>
) : listings.length === 0 ? (
<p className={styles.empty}>
No store items yet. Use the + button to add products from your catalog.
</p>
<p className={styles.empty}>{t('storeItems.empty')}</p>
) : filteredListings.length === 0 ? (
<p className={styles.empty}>No store items match your filters.</p>
<p className={styles.empty}>{t('storeItems.emptyFiltered')}</p>
) : (
<div className={styles.grid}>
{filteredListings.map((listing) => (
@@ -355,11 +352,11 @@ function StoreItemsPageContent() {
type="button"
className={styles.cartFabStrip}
onClick={() => setCartOpen(true)}
aria-label={`Open shopping cart, ${itemCount} items`}
aria-label={t('storeItems.cartOpen', { count: itemCount })}
>
<span className={styles.cartFabCount}>{itemCount}</span>
<span className={styles.cartFabLabel}>
{itemCount === 1 ? 'item in cart' : 'items in cart'}
{itemCount === 1 ? t('storeItems.cartOne') : t('storeItems.cartMany')}
</span>
</button>
)}
@@ -367,7 +364,7 @@ function StoreItemsPageContent() {
type="button"
className={styles.addFab}
onClick={() => setCreateOpen(true)}
aria-label="Add store items"
aria-label={t('storeItems.add')}
>
<Plus size={24} />
</button>
@@ -408,10 +405,13 @@ function StoreItemsPageContent() {
<ConfirmDeleteModal
open={!!deleteTarget}
title="Remove from Store"
title={t('storeItems.deleteTitle')}
message={
deleteTarget
? `Remove "${deleteTarget.productTitle}" and all ${formatVariantCount(deleteTarget.variantCount)} from your store? This cannot be undone.`
? t('storeItems.deleteMessage', {
name: deleteTarget.productNameFa || deleteTarget.productTitle,
variants: formatVariantCount(deleteTarget.variantCount, locale),
})
: ''
}
onConfirm={() => void confirmDelete()}