diff --git a/distribution_fe/app/(dashboard)/catalogue/categories/_components/categories-client.tsx b/distribution_fe/app/(dashboard)/catalogue/categories/_components/categories-client.tsx index 4e507fc..8151543 100644 --- a/distribution_fe/app/(dashboard)/catalogue/categories/_components/categories-client.tsx +++ b/distribution_fe/app/(dashboard)/catalogue/categories/_components/categories-client.tsx @@ -13,6 +13,7 @@ import { categories as categoriesApi, getApiError } from '@/lib/api/index' import type { CategoryResponse } from '@/types/api' import { CategorySheet } from './category-sheet' +import { CategoryViewSheet } from './category-view-sheet' export function CategoriesClient() { const [data, setData] = useState([]) @@ -21,6 +22,8 @@ export function CategoriesClient() { const [sheetOpen, setSheetOpen] = useState(false) const [editing, setEditing] = useState(null) + const [viewOpen, setViewOpen] = useState(false) + const [viewing, setViewing] = useState(null) const fetchData = useCallback(async () => { setLoading(true) @@ -49,6 +52,21 @@ export function CategoriesClient() { setSheetOpen(true) } + function openView(category: CategoryResponse) { + setViewing(category) + setViewOpen(true) + } + + async function handleDelete(category: CategoryResponse) { + try { + await categoriesApi.remove(category.id) + toast.add({ title: 'Category deactivated', type: 'success' }) + fetchData() + } catch (err) { + toast.add({ title: 'Failed to deactivate category', description: getApiError(err), type: 'error' }) + } + } + const tableConfig = useMemo>(() => ({ rowKey: 'id', serverSide: false, @@ -99,11 +117,22 @@ export function CategoriesClient() { ], rowActions: { actions: () => [ + { + action: 'view', + label: 'View category', + onClick: openView, + }, { action: 'edit', label: 'Edit category', onClick: openEdit, }, + { + action: 'cancel', + label: 'Delete category', + onClick: handleDelete, + visible: (target) => target.isActive, + }, ], }, }), [openEdit]) @@ -135,6 +164,12 @@ export function CategoriesClient() { category={editing} onSuccess={() => fetchData()} /> + + setViewOpen(false)} + category={viewing} + /> ) } diff --git a/distribution_fe/app/(dashboard)/catalogue/categories/_components/category-view-sheet.tsx b/distribution_fe/app/(dashboard)/catalogue/categories/_components/category-view-sheet.tsx new file mode 100644 index 0000000..08a778c --- /dev/null +++ b/distribution_fe/app/(dashboard)/catalogue/categories/_components/category-view-sheet.tsx @@ -0,0 +1,67 @@ +'use client' + +import { Badge } from '@/components/ui/badge' +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog' +import { Separator } from '@/components/ui/separator' +import type { CategoryResponse } from '@/types/api' + +const fmtDate = (v: string) => + new Date(v).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }) + +interface CategoryViewSheetProps { + open: boolean + onClose: () => void + category: CategoryResponse | null +} + +function Row({ label, value }: { label: string; value: React.ReactNode }) { + return ( +
+ {label} + {value} +
+ ) +} + +export function CategoryViewSheet({ open, onClose, category }: CategoryViewSheetProps) { + if (!category) return null + + return ( + !v && onClose()}> + + + Category Details + + +
+ + {category.isActive ? 'Active' : 'Inactive'}} /> + +
+ + + +
+

Sub-categories ({category.subCategories.length})

+ {category.subCategories.length === 0 ? ( +

No sub-categories yet.

+ ) : ( +
+ {category.subCategories.map((sub) => ( +
+ {sub.name} + {sub.isActive ? 'Active' : 'Inactive'} +
+ ))} +
+ )} +
+
+
+ ) +} diff --git a/distribution_fe/app/(dashboard)/catalogue/items/_components/item-sheet.tsx b/distribution_fe/app/(dashboard)/catalogue/items/_components/item-sheet.tsx index ecc3f6c..7dba95e 100644 --- a/distribution_fe/app/(dashboard)/catalogue/items/_components/item-sheet.tsx +++ b/distribution_fe/app/(dashboard)/catalogue/items/_components/item-sheet.tsx @@ -23,7 +23,7 @@ import { SelectValue, } from '@/components/ui/select' import { toast } from '@/components/ui/toast' -import { items as itemsApi, categories as categoriesApi, brands as brandsApi, uoms as uomsApi, getApiError, getPaginatedItems } from '@/lib/api/index' +import { items as itemsApi, categories as categoriesApi, brands as brandsApi, uoms as uomsApi, getApiError } from '@/lib/api/index' import type { ItemSummaryResponse, CategoryResponse, BrandResponse, UomResponse } from '@/types/api' const schema = z.object({ @@ -69,11 +69,11 @@ export function ItemSheet({ open, onClose, item, onSuccess }: ItemSheetProps) { if (open) { Promise.all([ categoriesApi.list(), - brandsApi.list({ page: 1, pageSize: 200 }), + brandsApi.list(), uomsApi.list(), ]).then(([cats, brandsRes, uomsRes]) => { setCategories(cats) - setBrandsList(getPaginatedItems(brandsRes)) + setBrandsList(brandsRes) setUomsList(uomsRes) }).catch((err) => { toast.add({ title: 'Failed to load reference data', description: getApiError(err), type: 'error' })