Localize order modals, add dual logos, and improve admin order tools.

Farsi business order/variation UI, light/dark logo upload on business profile, payment order steps, variation editing, super-admin site links, and checkout/auth fixes.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-08-26 00:21:48 +03:30
co-authored by Cursor
parent dc570c1e7f
commit 5e799eddf9
30 changed files with 779 additions and 169 deletions
@@ -13,14 +13,22 @@ interface AddVariationModalProps {
open: boolean
onClose: () => void
onSubmit: (variation: Omit<Variation, 'id'>) => void
/** When set, form opens in edit mode with values pre-filled. */
initial?: Variation | null
}
const ANIMATION_MS = 220
export function AddVariationModal({ open, onClose, onSubmit }: AddVariationModalProps) {
function seedCustomValues(values: string[]) {
const trimmed = values.map((value) => value.trim()).filter(Boolean)
return trimmed.length ? trimmed : ['']
}
export function AddVariationModal({ open, onClose, onSubmit, initial = null }: AddVariationModalProps) {
const t = useT()
const { locale } = useLocale()
const isFa = locale === 'fa'
const isEdit = Boolean(initial)
const [mounted, setMounted] = useState(open)
const [closing, setClosing] = useState(false)
const [type, setType] = useState<VariationType>('color')
@@ -41,11 +49,21 @@ export function AddVariationModal({ open, onClose, onSubmit }: AddVariationModal
if (open) {
setMounted(true)
setClosing(false)
setType('color')
setCustomName('')
setSelectedColors([])
setSelectedSizes([])
setCustomValues([''])
if (initial) {
setType(initial.type)
setCustomName(initial.type === 'custom' ? initial.name : '')
setSelectedColors(initial.type === 'color' ? [...initial.values] : [])
setSelectedSizes(initial.type === 'size' ? [...initial.values] : [])
setCustomValues(
initial.type === 'custom' ? seedCustomValues(initial.values) : [''],
)
} else {
setType('color')
setCustomName('')
setSelectedColors([])
setSelectedSizes([])
setCustomValues([''])
}
} else if (mounted) {
setClosing(true)
const timer = setTimeout(() => {
@@ -54,7 +72,7 @@ export function AddVariationModal({ open, onClose, onSubmit }: AddVariationModal
}, ANIMATION_MS)
return () => clearTimeout(timer)
}
}, [open, mounted])
}, [open, mounted, initial])
useEffect(() => {
if (!mounted || closing) return
@@ -128,7 +146,7 @@ export function AddVariationModal({ open, onClose, onSubmit }: AddVariationModal
onClick={onClose}
>
<div
className={`${styles.modal} ${closing ? styles.modalOut : styles.modalIn}`}
className={`${styles.modal} ${styles.modalFormWide} ${closing ? styles.modalOut : styles.modalIn}`}
onClick={(e) => e.stopPropagation()}
role="dialog"
aria-modal="true"
@@ -138,7 +156,7 @@ export function AddVariationModal({ open, onClose, onSubmit }: AddVariationModal
>
<div className={styles.header}>
<h3 id="add-variation-title" className={styles.title}>
{t('categories.variations.addTitle')}
{isEdit ? t('categories.variations.editTitle') : t('categories.variations.addTitle')}
</h3>
<button className={styles.closeBtn} onClick={onClose} aria-label={t('common.close')}>
<X size={20} />
@@ -151,6 +169,7 @@ export function AddVariationModal({ open, onClose, onSubmit }: AddVariationModal
<select
id="variationType"
value={type}
disabled={isEdit}
onChange={(e) => setType(e.target.value as VariationType)}
>
<option value="color">{t('categories.variations.type.color')}</option>
@@ -250,7 +269,7 @@ export function AddVariationModal({ open, onClose, onSubmit }: AddVariationModal
{t('categories.modal.cancel')}
</button>
<button type="submit" className={styles.submitBtn} disabled={!canSubmit}>
{t('categories.variations.submit')}
{isEdit ? t('categories.variations.saveEdit') : t('categories.variations.submit')}
</button>
</div>
</form>