dstpabuaran.com/resources/js/pages/admin/manage/purchase/index.tsx
Yoga Pangestu 9637671713 feat: enhance product management and purchase functionality
- Updated ProductIndex component to improve category and product filtering with memoization.
- Refactored Combobox components for better performance and usability.
- Added PurchaseController routes for managing purchases with appropriate permissions.
- Created comprehensive tests for purchase management, covering creation, updating, and deletion scenarios.
- Ensured proper handling of raw materials and their variants during purchase operations.
- Implemented validation for required fields in purchase creation and updates.
2026-08-02 14:07:16 +07:00

163 lines
5.3 KiB
TypeScript

import { Head, router } from '@inertiajs/react';
import { Plus } from 'lucide-react';
import { useCallback, useState } from 'react';
import { CardTable } from '@/components/card-table';
import { ConfirmDialog } from '@/components/confirm-dialog';
import { useCardTableExpand } from '@/components/hooks/use-card-table-expand';
import { Button } from '@/components/ui/button';
import {
destroy,
create as purchaseCreate,
index as purchaseIndex,
edit as purchaseEdit,
} from '@/routes/admin/manage/purchases';
import type { Purchase } from './columns';
import { PurchaseCardRow } from './purchase-card';
import { PurchaseItemSubRow } from './purchase-sub-row';
type Props = {
purchases: {
data: Purchase[];
current_page: number;
last_page: number;
per_page: number;
total: number;
};
};
export default function PurchaseIndex({ purchases }: Props) {
const [deleting, setDeleting] = useState<Purchase | null>(null);
const [search, setSearch] = useState('');
const expand = useCardTableExpand(true);
const pagination = {
current_page: purchases.current_page,
last_page: purchases.last_page,
per_page: purchases.per_page,
total: purchases.total,
};
function handlePageChange(page: number) {
router.get(
purchaseIndex.url(),
{
page,
per_page: pagination.per_page,
search,
},
{ preserveState: true, replace: true },
);
}
function handlePerPageChange(perPage: number) {
router.get(
purchaseIndex.url(),
{
page: 1,
per_page: perPage,
search,
},
{ preserveState: true, replace: true },
);
}
const handleSearchChange = useCallback(
(value: string) => {
setSearch(value);
router.get(
purchaseIndex.url(),
{
page: 1,
per_page: pagination.per_page,
search: value,
},
{ preserveState: true, replace: true },
);
},
[pagination.per_page],
);
function handleDelete() {
if (!deleting) {
return;
}
router.delete(destroy.url(deleting.id), {
onSuccess: () => setDeleting(null),
});
}
return (
<>
<Head title="Belanja" />
<div className="flex h-full flex-1 flex-col gap-6 overflow-x-auto p-4 md:p-6">
<div className="flex items-center justify-between">
<div>
<h2 className="text-2xl font-semibold tracking-tight">
Belanja
</h2>
</div>
<Button asChild>
<a href={purchaseCreate.url()}>
<Plus className="h-4 w-4" />
Tambah
</a>
</Button>
</div>
<CardTable
data={purchases.data}
getItemKey={(p) => p.id}
expandedKeys={expand.expandedKeys}
onToggleExpand={expand.toggleExpand}
searchValue={search}
onSearchChange={handleSearchChange}
searchPlaceholder="Cari berdasarkan supplier..."
pagination={pagination}
onPageChange={handlePageChange}
onPerPageChange={handlePerPageChange}
renderCard={({
item,
index,
isExpanded,
onToggleExpand,
}) => (
<PurchaseCardRow
purchase={item}
index={
(pagination.current_page - 1) *
pagination.per_page +
index +
1
}
isExpanded={isExpanded}
onToggleExpand={onToggleExpand}
onEdit={(p) => {
window.location.href = purchaseEdit.url(p.id);
}}
onDelete={(p) => setDeleting(p)}
/>
)}
renderSubContent={(purchase) => (
<PurchaseItemSubRow purchase={purchase} />
)}
/>
<ConfirmDialog
open={deleting !== null}
onOpenChange={(open) => {
if (!open) {
setDeleting(null);
}
}}
title="Hapus Belanja"
description={`Apakah Anda yakin ingin menghapus belanja dari "${deleting?.supplier?.name}"? Stok akan dikembalikan. Tindakan ini tidak dapat dibatalkan.`}
confirmLabel="Hapus"
onConfirm={handleDelete}
/>
</div>
</>
);
}