dstpabuaran.com/resources/js/pages/admin/manage/purchase/purchase-sub-row.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

136 lines
4.8 KiB
TypeScript

import { useState } from 'react';
import { ImagePreviewModal } from '@/components/image-preview-modal';
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/components/ui/table';
import type { Purchase } from './columns';
function formatCurrency(amount: number): string {
return new Intl.NumberFormat('id-ID', {
style: 'currency',
currency: 'IDR',
minimumFractionDigits: 0,
}).format(amount);
}
function formatNumber(num: number): string {
return new Intl.NumberFormat('id-ID', {
maximumFractionDigits: 4,
}).format(num);
}
function formatDateTime(dateString: string): string {
const date = new Date(dateString);
return date.toLocaleDateString('id-ID', {
day: '2-digit',
month: 'short',
year: 'numeric',
hour: '2-digit',
minute: '2-digit',
});
}
function VariantPhotoPreview({ url, title }: { url: string; title: string }) {
const [open, setOpen] = useState(false);
return (
<>
<button
type="button"
onClick={() => setOpen(true)}
className="block h-10 w-10 overflow-hidden rounded-md border transition-opacity hover:opacity-80"
>
<img
src={url}
alt={title}
className="h-full w-full object-cover"
/>
</button>
<ImagePreviewModal
open={open}
onOpenChange={setOpen}
src={url}
title={title}
/>
</>
);
}
export function PurchaseItemSubRow({
purchase,
}: {
purchase: Purchase;
}) {
const items = purchase.purchase_items ?? [];
const unit =
items[0]?.raw_material_price?.raw_material?.unit ?? '';
return (
<div className="space-y-4 overflow-x-auto">
<Table>
<TableHeader>
<TableRow>
<TableHead className="w-[50px] text-center">
No
</TableHead>
<TableHead className="w-[60px]">Foto</TableHead>
<TableHead>Varian</TableHead>
<TableHead className="text-right">Harga</TableHead>
<TableHead className="text-center">Qty</TableHead>
<TableHead className="text-right">Subtotal</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{items.length === 0 ? (
<TableRow>
<TableCell
colSpan={6}
className="text-center text-muted-foreground"
>
Tidak ada item.
</TableCell>
</TableRow>
) : (
items.map((item, index) => (
<TableRow key={item.id}>
<TableCell className="text-center">
{index + 1}
</TableCell>
<TableCell>
{item.raw_material_price?.photo_url ? (
<VariantPhotoPreview
url={item.raw_material_price.photo_url}
title={item.raw_material_price.variant}
/>
) : (
<div className="flex h-10 w-10 items-center justify-center rounded-md bg-muted text-xs text-muted-foreground">
N/A
</div>
)}
</TableCell>
<TableCell>
{item.raw_material_price?.variant ?? '-'}
</TableCell>
<TableCell className="text-right">
{formatCurrency(item.unit_price)}
</TableCell>
<TableCell className="text-center">
{formatNumber(item.quantity)} {unit}
</TableCell>
<TableCell className="text-right font-medium">
{formatCurrency(item.subtotal)}
</TableCell>
</TableRow>
))
)}
</TableBody>
</Table>
</div>
);
}