import { useEffect, useState } from 'react' import { Plus } from 'lucide-react' import { Breadcrumbs } from '../components/Breadcrumbs' 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 { 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 { 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('Unable to load special brand groups.') } } finally { setIsLoading(false) } } function replaceGroup(updated: WebsiteBrandGroup) { setGroups((prev) => prev.map((entry) => (entry.id === updated.id ? updated : entry))) } async function handleCreateGroup(title: string) { setIsSaving(true) setError('') try { const result = await createWebsiteBrandGroup({ title, sortOrder: groups.length, }) setGroups((prev) => [...prev, result.group]) setCreateOpen(false) showToast('Special brand group created.', 'success') } catch (err) { if (err instanceof ApiError) { setError(err.message) } else { setError('Unable to create special brand group.') } } finally { setIsSaving(false) } } async function handleEditGroup(title: string) { if (!editGroupTarget) return setIsSaving(true) setError('') try { const result = await updateWebsiteBrandGroup(editGroupTarget.id, { title }) replaceGroup(result.group) setEditGroupTarget(null) showToast('Special brand group updated.', 'success') } catch (err) { if (err instanceof ApiError) { setError(err.message) } else { setError('Unable to update special brand group.') } } 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('Special brand group deleted.', 'success') } catch (err) { if (err instanceof ApiError) { setError(err.message) } else { setError('Unable to delete special brand group.') } } 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('Brands added to group.', 'success') } catch (err) { if (err instanceof ApiError) { setError(err.message) } else { setError('Unable to add brands.') } } 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('Removed from special brand group.', 'success') } catch (err) { if (err instanceof ApiError) { setError(err.message) } else { setError('Unable to remove brand.') } } finally { setIsSaving(false) } } return (

Special Brands

Curate featured brands into groups for your website homepage.

{error &&

{error}

} {isLoading ? (

Loading special brand groups...

) : groups.length === 0 ? (

No special brand groups yet. Use the + button to create one, then add brands to each carousel.

) : (
{groups.map((group) => ( item.id} onAddItems={() => setPickItemsTarget(group)} onEditGroup={() => setEditGroupTarget(group)} onDeleteGroup={() => setDeleteGroupTarget(group)} addTooltip={`Add brands to ${group.title}`} editTooltip="Edit group" deleteTooltip="Delete group" renderItem={(item) => ( setRemoveTarget({ group, brandId: item.id, brandName: item.nameEn, }) } removeTooltip="Remove from group" /> )} /> ))}
)}
!isSaving && setCreateOpen(false)} onSubmit={handleCreateGroup} title="Add Special Brand Group" isSubmitting={isSaving} /> !isSaving && setEditGroupTarget(null)} onSubmit={handleEditGroup} initialTitle={editGroupTarget?.title ?? ''} title="Edit Special Brand Group" submitLabel="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)} />
) }