import { useEffect, useState } from 'react' import { createPortal } from 'react-dom' import { X } from 'lucide-react' import { useLocale } from '@meshkee/dashboard-ui' import { useToast } from '../context/ToastContext' import { useT } from '../i18n/useT' import { ApiError } from '../lib/api' import { updateOrder, type Order } from '../services/orderService' import type { OrderProcessStep } from '../services/settingsService' import { defaultStepColorForId, normalizeStepColor, stepBadgeStyle } from '../utils/stepColors' import modalStyles from './VariationsModal.module.css' import styles from './OrderStepModal.module.css' interface OrderStepModalProps { open: boolean order: Order | null steps: OrderProcessStep[] onClose: () => void onSaved?: (order: Order) => void } const ANIMATION_MS = 220 function stepDisplayLabel(step: OrderProcessStep, locale: string) { if (locale === 'fa') { const fa = step.labelFa?.trim() if (fa) return fa } return step.label } export function OrderStepModal({ open, order, steps, onClose, onSaved, }: OrderStepModalProps) { const t = useT() const { locale } = useLocale() const { showToast } = useToast() const [mounted, setMounted] = useState(open) const [closing, setClosing] = useState(false) const [savingStepId, setSavingStepId] = useState(null) const [error, setError] = useState('') useEffect(() => { if (open && order) { setMounted(true) setClosing(false) setError('') setSavingStepId(null) } else if (mounted) { setClosing(true) const timer = setTimeout(() => { setMounted(false) setClosing(false) }, ANIMATION_MS) return () => clearTimeout(timer) } }, [open, mounted, order]) useEffect(() => { if (!mounted || closing) return const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape' && !savingStepId) onClose() } document.addEventListener('keydown', onKey) return () => document.removeEventListener('keydown', onKey) }, [mounted, closing, onClose, savingStepId]) async function handleSelectStep(stepId: string) { if (!order || savingStepId) return if (stepId === order.processStepId) { onClose() return } setSavingStepId(stepId) setError('') try { const result = await updateOrder(order.id, { processStepId: stepId }) showToast(t('orderStep.updated', { orderNumber: order.orderNumber }), 'success') onSaved?.(result.order) onClose() } catch (err) { setError(err instanceof ApiError ? err.message : t('orderStep.error')) } finally { setSavingStepId(null) } } if (!mounted || !order) return null const currentStep = steps.find((step) => step.id === order.processStepId) ?? null const currentLabel = (locale === 'fa' ? order.processStepLabelFa?.trim() || currentStep?.labelFa?.trim() : null) || order.processStepLabel?.trim() || currentStep?.label || order.processStepId return createPortal(
{ if (!savingStepId) onClose() }} >
e.stopPropagation()} role="dialog" aria-modal="true" aria-labelledby="order-step-title" lang={locale === 'fa' ? 'fa' : undefined} dir={locale === 'fa' ? 'rtl' : undefined} >

{t('orderStep.title')}

{t('orderStep.current', { orderNumber: order.orderNumber, step: currentLabel, })}

{error && (
{error}
)}
{steps.map((step, index) => { const selected = order.processStepId === step.id const saving = savingStepId === step.id const color = normalizeStepColor(step.color, defaultStepColorForId(step.id, index)) const label = stepDisplayLabel(step, locale) return ( ) })}
{!steps.length && (

{t('orderStep.empty')}

)}
, document.body, ) }