import { useEffect, useState } from 'react' import { createPortal } from 'react-dom' import { Plus, X } from 'lucide-react' import { useLocale } from '@meshkee/dashboard-ui' import { useT } from '../i18n/useT' import type { BusinessMessageKey } from '../i18n/messages' import type { Variation, VariationType } from '../types/variation' import { COLOR_OPTIONS } from '../types/variation' import { createId } from '../utils/id' import { textLocaleAttrs } from '../utils/textLocale' import { AddVariationModal } from './AddVariationModal' import { Tooltip } from './Tooltip' import styles from './VariationsModal.module.css' interface VariationsModalProps { open: boolean categoryName: string variations: Variation[] isSaving?: boolean onClose: () => void onChange: (variations: Variation[]) => void onSave: () => void } const ANIMATION_MS = 220 export function VariationsModal({ open, categoryName, variations, isSaving = false, onClose, onChange, onSave, }: VariationsModalProps) { const t = useT() const { locale } = useLocale() const isFa = locale === 'fa' const [mounted, setMounted] = useState(open) const [closing, setClosing] = useState(false) const [addOpen, setAddOpen] = useState(false) useEffect(() => { if (open) { setMounted(true) setClosing(false) } else if (mounted) { setClosing(true) const timer = setTimeout(() => { setMounted(false) setClosing(false) setAddOpen(false) }, ANIMATION_MS) return () => clearTimeout(timer) } }, [open, mounted]) useEffect(() => { if (!mounted || closing) return const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape' && !addOpen) onClose() } document.addEventListener('keydown', onKey) return () => document.removeEventListener('keydown', onKey) }, [mounted, closing, addOpen, onClose]) if (!mounted) return null const list = variations const categoryLocale = textLocaleAttrs(categoryName) function handleAdd(variation: Omit) { onChange([ ...list, { ...variation, id: createId() }, ]) setAddOpen(false) } function handleRemove(id: string) { onChange(list.filter((variation) => variation.id !== id)) } function typeLabel(type: VariationType) { if (type === 'color') return t('categories.variations.type.color') if (type === 'size') return t('categories.variations.type.size') return t('categories.variations.type.custom') } function variationTitle(variation: Variation) { if (variation.type === 'color' || variation.type === 'size') { return typeLabel(variation.type) } return variation.name } function localizeValue(value: string) { if ((COLOR_OPTIONS as string[]).includes(value)) { return t(`categories.variations.color.${value}` as BusinessMessageKey) } return value } return createPortal( <>
e.stopPropagation()} role="dialog" aria-modal="true" aria-labelledby="variations-modal-title" lang={isFa ? 'fa' : 'en'} dir={isFa ? 'rtl' : 'ltr'} >

{t('categories.variations.title')}

{categoryName && (

{categoryName}

)}
{list.map((variation) => { const title = variationTitle(variation) const nameLocale = textLocaleAttrs(title) const valuesText = variation.values.map(localizeValue).join(' ยท ') || t('categories.variations.noValues') const valuesLocale = textLocaleAttrs(valuesText) return (
{title}
{valuesText}
{typeLabel(variation.type)}
) })} {!list.length && (

{t('categories.variations.empty')}

)}
setAddOpen(false)} onSubmit={handleAdd} /> , document.body, ) }