184 lines
9.0 KiB
TypeScript
184 lines
9.0 KiB
TypeScript
import { Head, Link } from '@inertiajs/react';
|
|
import { ArrowLeft } from 'lucide-react';
|
|
import { ImagePreviewButton } from '@/components/dialogs';
|
|
import { Badge } from '@/components/ui/badge';
|
|
import { Button } from '@/components/ui/button';
|
|
import {
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableHead,
|
|
TableHeader,
|
|
TableRow,
|
|
} from '@/components/ui/table';
|
|
import { formatNumber } from '@/lib/format';
|
|
import { index as cuttingIndex } from '@/routes/admin/manage/cuttings';
|
|
import type { Cutting } from './columns';
|
|
import { CuttingItemSubRow } from './cutting-sub-row';
|
|
|
|
type Props = {
|
|
cutting: Cutting;
|
|
};
|
|
|
|
const STATUS_BADGE_CLASSES: Record<string, string> = {
|
|
completed: 'bg-green-100 text-green-800 hover:bg-green-100',
|
|
cancelled: 'bg-red-100 text-red-800 hover:bg-red-100',
|
|
in_progress: 'bg-yellow-100 text-yellow-800 hover:bg-yellow-100',
|
|
};
|
|
|
|
export default function CuttingShow({ cutting }: Props) {
|
|
const items = cutting.cutting_materials ?? [];
|
|
const result = cutting.cutting_results?.[0];
|
|
const totalUsage = items.reduce(
|
|
(sum, item) => sum + Number(item.material_usage),
|
|
0,
|
|
);
|
|
const statusBadgeClass =
|
|
STATUS_BADGE_CLASSES[cutting.status] ?? STATUS_BADGE_CLASSES.in_progress;
|
|
|
|
return (
|
|
<>
|
|
<Head title={`Cutting #${cutting.id}`} />
|
|
|
|
<div className="mx-auto max-w-3xl px-4 py-8 sm:px-6 lg:px-8">
|
|
<div className="mb-8 text-center">
|
|
<h1 className="text-2xl font-bold tracking-tight">
|
|
Detail Cutting
|
|
</h1>
|
|
<p className="mt-1 text-muted-foreground">
|
|
Rincian data proses cutting
|
|
</p>
|
|
</div>
|
|
|
|
<div className="overflow-hidden rounded-lg border bg-card shadow-sm">
|
|
<div className="border-b bg-muted/30 p-6">
|
|
<div className="flex flex-wrap items-center gap-3">
|
|
<h2 className="text-xl font-semibold">
|
|
Cutting #{cutting.id}
|
|
</h2>
|
|
<Badge variant="secondary" className={statusBadgeClass}>
|
|
{cutting.status === 'completed'
|
|
? 'Selesai'
|
|
: cutting.status === 'cancelled'
|
|
? 'Dibatalkan'
|
|
: 'Dikerjakan'}
|
|
</Badge>
|
|
</div>
|
|
<div className="mt-3 space-y-1 text-sm text-muted-foreground">
|
|
<p>{cutting.formatted_created_at}</p>
|
|
<p>
|
|
Oleh{' '}
|
|
<span className="font-medium text-foreground">
|
|
{cutting.created_by?.user_profile?.full_name ?? '-'}
|
|
</span>
|
|
</p>
|
|
</div>
|
|
{cutting.description && (
|
|
<p className="mt-3 text-sm">{cutting.description}</p>
|
|
)}
|
|
|
|
{cutting.photo_url && (
|
|
<div className="mt-4">
|
|
<ImagePreviewButton
|
|
srcs={[cutting.photo_conversion_url ?? cutting.photo_url]}
|
|
modalSrc={cutting.photo_url}
|
|
title={result?.product_name ?? `Cutting #${cutting.id}`}
|
|
description={cutting.description ?? ''}
|
|
/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{result && (
|
|
<div className="border-b p-6">
|
|
<h3 className="mb-3 text-sm font-semibold">Hasil Produk</h3>
|
|
<div className="overflow-x-auto rounded-md border">
|
|
<Table>
|
|
<TableHeader>
|
|
<TableRow>
|
|
<TableHead>Produk</TableHead>
|
|
<TableHead className="text-right">Hasil</TableHead>
|
|
<TableHead className="text-right">Sample</TableHead>
|
|
<TableHead className="text-right">Diluar Sample</TableHead>
|
|
</TableRow>
|
|
</TableHeader>
|
|
<TableBody>
|
|
<TableRow>
|
|
<TableCell>{result.product_name ?? '-'}</TableCell>
|
|
<TableCell className="text-right tabular-nums">
|
|
{result.cutting_result ?? '-'} pcs
|
|
</TableCell>
|
|
<TableCell className="text-right tabular-nums">
|
|
{result.sample ?? '-'} pcs
|
|
</TableCell>
|
|
<TableCell className="text-right tabular-nums">
|
|
{result.original_outside_sample ?? '-'} pcs
|
|
</TableCell>
|
|
</TableRow>
|
|
</TableBody>
|
|
</Table>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{items.length > 0 && (
|
|
<div className="border-b p-6">
|
|
<h3 className="mb-3 text-sm font-semibold">Bahan Baku</h3>
|
|
|
|
<div className="pb-2">
|
|
<div className="grid gap-4 sm:grid-cols-2">
|
|
<div className="rounded-lg border p-3">
|
|
<p className="text-xs text-muted-foreground">Total Pemakaian</p>
|
|
<p className="mt-1 text-lg font-semibold text-primary">
|
|
{formatNumber(totalUsage)}
|
|
</p>
|
|
</div>
|
|
{result?.cutting_result && (
|
|
<div className="rounded-lg border p-3">
|
|
<p className="text-xs text-muted-foreground">Total Hasil Cutting</p>
|
|
<p className="mt-1 text-lg font-semibold text-primary">
|
|
{formatNumber(result.cutting_result)} pcs
|
|
</p>
|
|
</div>
|
|
)}
|
|
{cutting.formatted_cost_per_unit && (
|
|
<div className="rounded-lg border p-3">
|
|
<p className="text-xs text-muted-foreground">Biaya Per Produk</p>
|
|
<p className="mt-1 text-lg font-semibold text-primary">
|
|
{cutting.formatted_cost_per_unit}
|
|
</p>
|
|
</div>
|
|
)}
|
|
{cutting.formatted_total_material_cost && (
|
|
<div className="rounded-lg border p-3">
|
|
<p className="text-xs text-muted-foreground">Total Biaya Bahan</p>
|
|
<p className="mt-1 text-lg font-semibold text-primary">
|
|
{cutting.formatted_total_material_cost}
|
|
</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
<i className="text-xs md:hidden">Geser kesamping untuk melihat lebih banyak</i>
|
|
<CuttingItemSubRow cutting={cutting} />
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="mt-6 flex items-center justify-between">
|
|
<Button variant="outline" asChild>
|
|
<Link href={cuttingIndex.url()}>
|
|
<ArrowLeft className="mr-2 h-4 w-4" />
|
|
Kembali
|
|
</Link>
|
|
</Button>
|
|
<p className="text-xs text-muted-foreground">
|
|
Data ini dibagikan dari sistem DST Collection
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|