import { useEffect, useMemo, useState } from 'react' import { Plus } from 'lucide-react' import { Breadcrumbs } from '../components/Breadcrumbs' import { ConfirmDeleteModal } from '../components/ConfirmDeleteModal' import { EditStoreItemsModal } from '../components/EditStoreItemsModal' import { PickStoreSpecialItemsModal } from '../components/PickStoreSpecialItemsModal' import { PickStoreVariantModal } from '../components/PickStoreVariantModal' import { ShoppingCartModal } from '../components/ShoppingCartModal' import { StoreItemDiscountModal } from '../components/StoreItemDiscountModal' import { StoreItemFestivalModal } from '../components/StoreItemFestivalModal' import { StoreSpecialCarousel } from '../components/StoreSpecialCarousel' import { StoreSpecialModal } from '../components/StoreSpecialModal' import { useDraftCart } from '../context/DraftCartContext' import { useToast } from '../context/ToastContext' import { useT } from '../i18n/useT' import { ApiError } from '../lib/api' import { createStoreSpecial, deleteStoreSpecial, listStoreSpecials, updateStoreSpecial, } from '../services/storeSpecialService' import type { StoreItem } from '../services/storeItemService' import type { StoreSpecial } from '../types/storeSpecial' import type { StoreProductListing } from '../utils/storeProductGroups' import pageStyles from '../components/PageContent.module.css' import fabStyles from './StoreItemsPage.module.css' import styles from './StoreSpecialsPage.module.css' export function StoreSpecialsPage() { const t = useT() const { itemCount, hasItems, addVariant } = useDraftCart() const { showToast } = useToast() const [specials, setSpecials] = useState([]) const [isLoading, setIsLoading] = useState(true) const [isSaving, setIsSaving] = useState(false) const [error, setError] = useState('') const [createOpen, setCreateOpen] = useState(false) const [editSpecialTarget, setEditSpecialTarget] = useState(null) const [deleteSpecialTarget, setDeleteSpecialTarget] = useState(null) const [pickItemsTarget, setPickItemsTarget] = useState(null) const [editListingTarget, setEditListingTarget] = useState(null) const [discountTarget, setDiscountTarget] = useState(null) const [festivalTarget, setFestivalTarget] = useState(null) const [removeTarget, setRemoveTarget] = useState<{ special: StoreSpecial listing: StoreProductListing } | null>(null) const [pickVariantTarget, setPickVariantTarget] = useState(null) const [cartOpen, setCartOpen] = useState(false) const productItems = useMemo(() => { const target = editListingTarget ?? discountTarget ?? festivalTarget if (!target) return [] return target.variants }, [editListingTarget, discountTarget, festivalTarget]) useEffect(() => { const controller = new AbortController() void loadSpecials(controller.signal) return () => controller.abort() }, []) async function loadSpecials(signal?: AbortSignal) { setIsLoading(true) setError('') try { const data = await listStoreSpecials(1, 50, signal) setSpecials(data.items) } catch (err) { if (err instanceof DOMException && err.name === 'AbortError') return if (err instanceof ApiError) { setError(err.message) } else { setError(t('website.specialItems.errorLoad')) } } finally { setIsLoading(false) } } function replaceSpecial(updated: StoreSpecial) { setSpecials((prev) => prev.map((entry) => (entry.id === updated.id ? updated : entry))) } function mergeUpdatedItems(updated: StoreItem[]) { const byId = new Map(updated.map((item) => [item.id, item])) setSpecials((prev) => prev.map((special) => ({ ...special, items: special.items.map((storeItem) => ({ ...storeItem, variants: storeItem.variants.map((variant) => { const next = byId.get(variant.id) if (!next) return variant return { ...variant, price: next.price, discountedPrice: next.discountedPrice, stockQuantity: next.stockQuantity, rewardPoints: next.rewardPoints, isFestival: next.isFestival, } }), })), })), ) } function replaceProductItems(updated: StoreItem[]) { const productId = updated[0]?.productId ?? editListingTarget?.productId if (!productId) return setSpecials((prev) => prev.map((special) => ({ ...special, items: special.items.map((storeItem) => { if (storeItem.productId !== productId) return storeItem if (updated.length === 0) return storeItem return { ...storeItem, productTitle: updated[0].productTitle, productNameFa: updated[0].productNameFa, productImage: updated[0].productImage, variants: updated.map((item) => ({ id: item.id, label: item.label, selections: item.selections, price: item.price, discountedPrice: item.discountedPrice, stockQuantity: item.stockQuantity, rewardPoints: item.rewardPoints, isFestival: item.isFestival, sortOrder: item.sortOrder, })), } }), })), ) } async function handleCreateSpecial(values: { key: string; title: string }) { setIsSaving(true) setError('') try { const result = await createStoreSpecial({ key: values.key, title: values.title, sortOrder: specials.length, }) setSpecials((prev) => [...prev, result.special]) setCreateOpen(false) showToast(t('website.specialItems.toastCreated'), 'success') } catch (err) { if (err instanceof ApiError) { setError(err.message) } else { setError(t('website.specialItems.errorCreate')) } } finally { setIsSaving(false) } } async function handleEditSpecial(values: { key: string; title: string }) { if (!editSpecialTarget) return setIsSaving(true) setError('') try { const result = await updateStoreSpecial(editSpecialTarget.id, { key: values.key, title: values.title, }) replaceSpecial(result.special) setEditSpecialTarget(null) showToast(t('website.specialItems.toastUpdated'), 'success') } catch (err) { if (err instanceof ApiError) { setError(err.message) } else { setError(t('website.specialItems.errorUpdate')) } } finally { setIsSaving(false) } } async function confirmDeleteSpecial() { if (!deleteSpecialTarget) return setIsSaving(true) setError('') try { await deleteStoreSpecial(deleteSpecialTarget.id) setSpecials((prev) => prev.filter((entry) => entry.id !== deleteSpecialTarget.id)) setDeleteSpecialTarget(null) showToast(t('website.specialItems.toastDeleted'), 'success') } catch (err) { if (err instanceof ApiError) { setError(err.message) } else { setError(t('website.specialItems.errorDelete')) } } finally { setIsSaving(false) } } async function handleAddItems(storeItemIds: string[]) { if (!pickItemsTarget) return const existingIds = pickItemsTarget.items.map((item) => item.id) const nextIds = [...existingIds, ...storeItemIds] setIsSaving(true) setError('') try { const result = await updateStoreSpecial(pickItemsTarget.id, { storeItemIds: nextIds, }) replaceSpecial(result.special) setPickItemsTarget(null) showToast(t('website.specialItems.toastAdded'), 'success') } catch (err) { if (err instanceof ApiError) { setError(err.message) } else { setError(t('website.specialItems.errorAdd')) } } finally { setIsSaving(false) } } async function confirmRemoveFromSpecial() { if (!removeTarget) return const { special, listing } = removeTarget const storeItemId = listing.representative.storeItemId ?? listing.representative.id const nextIds = special.items .map((item) => item.id) .filter((id) => id !== storeItemId) setIsSaving(true) setError('') try { const result = await updateStoreSpecial(special.id, { storeItemIds: nextIds, }) replaceSpecial(result.special) setRemoveTarget(null) showToast(t('website.specialItems.toastRemoved'), 'success') } catch (err) { if (err instanceof ApiError) { setError(err.message) } else { setError(t('website.specialItems.errorRemove')) } } finally { setIsSaving(false) } } function handleAddToCart(listing: StoreProductListing) { if (listing.variantCount > 1) { setPickVariantTarget(listing) return } const variant = listing.variants[0] if (!variant) return const feedback = addVariant(variant) if (feedback) { showToast(feedback, 'error') return } showToast(t('storeItems.addedToCart'), 'success') } function handleVariantPicked(variant: StoreItem) { const feedback = addVariant(variant) setPickVariantTarget(null) if (feedback) { showToast(feedback, 'error') return } showToast(t('storeItems.addedToCart'), 'success') } return (

{t('title.specialItems')}

{t('website.specialItems.subtitle')}

{error &&

{error}

} {isLoading ? (

{t('website.specialItems.loading')}

) : specials.length === 0 ? (

{t('website.specialItems.empty')}

) : (
{specials.map((special) => ( setRemoveTarget({ special: specialEntry, listing }) } onAddToCart={handleAddToCart} /> ))}
)}
{hasItems && ( )}
!isSaving && setCreateOpen(false)} onSubmit={handleCreateSpecial} title={t('website.specialItems.createTitle')} submitLabel={t('website.create')} isSubmitting={isSaving} /> !isSaving && setEditSpecialTarget(null)} onSubmit={handleEditSpecial} initialKey={editSpecialTarget?.key ?? ''} initialTitle={editSpecialTarget?.title ?? ''} title={t('website.specialItems.editTitle')} submitLabel={t('website.save')} isSubmitting={isSaving} /> item.id) ?? []} onClose={() => !isSaving && setPickItemsTarget(null)} onConfirm={handleAddItems} isSubmitting={isSaving} /> setEditListingTarget(null)} onSaved={replaceProductItems} /> setDiscountTarget(null)} onSaved={mergeUpdatedItems} /> setFestivalTarget(null)} onSaved={mergeUpdatedItems} /> void confirmDeleteSpecial()} onCancel={() => !isSaving && setDeleteSpecialTarget(null)} /> void confirmRemoveFromSpecial()} onCancel={() => !isSaving && setRemoveTarget(null)} /> setPickVariantTarget(null)} onSelect={handleVariantPicked} /> setCartOpen(false)} onOrderCreated={() => void loadSpecials()} />
) }