import { useEffect, useState } from 'react' import { Plus } from 'lucide-react' import { Breadcrumbs } from '../components/Breadcrumbs' import { PageTitle } from '../components/PageTitle' import { ConfirmDeleteModal } from '../components/ConfirmDeleteModal' import { PickWebsiteBrandsModal } from '../components/PickWebsiteBrandsModal' import { StoreSpecialModal } from '../components/StoreSpecialModal' import { WebsiteGroupCarousel } from '../components/WebsiteGroupCarousel' import { WebsiteGroupItemCard } from '../components/WebsiteGroupItemCard' import { useToast } from '../context/ToastContext' import { useT } from '../i18n/useT' import { ApiError } from '../lib/api' import { createWebsiteBrandGroup, deleteWebsiteBrandGroup, listWebsiteBrandGroups, updateWebsiteBrandGroup, } from '../services/websiteBrandGroupService' import type { WebsiteBrandGroup } from '../types/websiteBrandGroup' import pageStyles from '../components/PageContent.module.css' import fabStyles from './StoreItemsPage.module.css' import styles from './StoreSpecialsPage.module.css' export function WebsiteSpecialBrandsPage() { const t = useT() const { showToast } = useToast() const [groups, setGroups] = useState([]) const [isLoading, setIsLoading] = useState(true) const [isSaving, setIsSaving] = useState(false) const [error, setError] = useState('') const [createOpen, setCreateOpen] = useState(false) const [editGroupTarget, setEditGroupTarget] = useState(null) const [deleteGroupTarget, setDeleteGroupTarget] = useState(null) const [pickItemsTarget, setPickItemsTarget] = useState(null) const [removeTarget, setRemoveTarget] = useState<{ group: WebsiteBrandGroup brandId: string brandName: string } | null>(null) useEffect(() => { const controller = new AbortController() void loadGroups(controller.signal) return () => controller.abort() }, []) async function loadGroups(signal?: AbortSignal) { setIsLoading(true) setError('') try { const data = await listWebsiteBrandGroups(1, 50, signal) setGroups(data.items) } catch (err) { if (err instanceof DOMException && err.name === 'AbortError') return if (err instanceof ApiError) { setError(err.message) } else { setError(t('website.specialBrands.errorLoad')) } } finally { setIsLoading(false) } } function replaceGroup(updated: WebsiteBrandGroup) { setGroups((prev) => prev.map((entry) => (entry.id === updated.id ? updated : entry))) } async function handleCreateGroup(values: { key: string; title: string }) { setIsSaving(true) setError('') try { const result = await createWebsiteBrandGroup({ key: values.key, title: values.title, sortOrder: groups.length, }) setGroups((prev) => [...prev, result.group]) setCreateOpen(false) showToast(t('website.specialBrands.toastCreated'), 'success') } catch (err) { if (err instanceof ApiError) { setError(err.message) } else { setError(t('website.specialBrands.errorCreate')) } } finally { setIsSaving(false) } } async function handleEditGroup(values: { key: string; title: string }) { if (!editGroupTarget) return setIsSaving(true) setError('') try { const result = await updateWebsiteBrandGroup(editGroupTarget.id, { key: values.key, title: values.title, }) replaceGroup(result.group) setEditGroupTarget(null) showToast(t('website.specialBrands.toastUpdated'), 'success') } catch (err) { if (err instanceof ApiError) { setError(err.message) } else { setError(t('website.specialBrands.errorUpdate')) } } finally { setIsSaving(false) } } async function confirmDeleteGroup() { if (!deleteGroupTarget) return setIsSaving(true) setError('') try { await deleteWebsiteBrandGroup(deleteGroupTarget.id) setGroups((prev) => prev.filter((entry) => entry.id !== deleteGroupTarget.id)) setDeleteGroupTarget(null) showToast(t('website.specialBrands.toastDeleted'), 'success') } catch (err) { if (err instanceof ApiError) { setError(err.message) } else { setError(t('website.specialBrands.errorDelete')) } } finally { setIsSaving(false) } } async function handleAddBrands(brandIds: string[]) { if (!pickItemsTarget) return const existingIds = pickItemsTarget.items.map((item) => item.id) const nextIds = [...existingIds, ...brandIds] setIsSaving(true) setError('') try { const result = await updateWebsiteBrandGroup(pickItemsTarget.id, { brandIds: nextIds, }) replaceGroup(result.group) setPickItemsTarget(null) showToast(t('website.specialBrands.toastAdded'), 'success') } catch (err) { if (err instanceof ApiError) { setError(err.message) } else { setError(t('website.specialBrands.errorAdd')) } } finally { setIsSaving(false) } } async function confirmRemoveFromGroup() { if (!removeTarget) return const { group, brandId } = removeTarget const nextIds = group.items.map((item) => item.id).filter((id) => id !== brandId) setIsSaving(true) setError('') try { const result = await updateWebsiteBrandGroup(group.id, { brandIds: nextIds, }) replaceGroup(result.group) setRemoveTarget(null) showToast(t('website.specialBrands.toastRemoved'), 'success') } catch (err) { if (err instanceof ApiError) { setError(err.message) } else { setError(t('website.specialBrands.errorRemove')) } } finally { setIsSaving(false) } } return (
{t('title.specialBrands')}

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

{error &&

{error}

} {isLoading ? (

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

) : groups.length === 0 ? (

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

) : (
{groups.map((group) => ( item.id} onAddItems={() => setPickItemsTarget(group)} onEditGroup={() => setEditGroupTarget(group)} onDeleteGroup={() => setDeleteGroupTarget(group)} addTooltip={t('website.specialBrands.addTooltip', { title: group.title })} renderItem={(item) => ( setRemoveTarget({ group, brandId: item.id, brandName: item.nameEn, }) } /> )} /> ))}
)}
!isSaving && setCreateOpen(false)} onSubmit={handleCreateGroup} title={t('website.specialBrands.createTitle')} submitLabel={t('website.create')} isSubmitting={isSaving} /> !isSaving && setEditGroupTarget(null)} onSubmit={handleEditGroup} initialKey={editGroupTarget?.key ?? ''} initialTitle={editGroupTarget?.title ?? ''} title={t('website.specialBrands.editTitle')} submitLabel={t('website.save')} isSubmitting={isSaving} /> item.id) ?? []} onClose={() => !isSaving && setPickItemsTarget(null)} onConfirm={handleAddBrands} isSubmitting={isSaving} /> void confirmDeleteGroup()} onCancel={() => !isSaving && setDeleteGroupTarget(null)} /> void confirmRemoveFromGroup()} onCancel={() => !isSaving && setRemoveTarget(null)} />
) }