store/resources/js/pages/admin/manage/cuttings/Share.vue

358 lines
16 KiB
Vue

<script setup lang="ts">
import { computed } from 'vue';
import MediaThumbnailCell from '@/components/media/MediaThumbnailCell.vue';
import { Badge } from '@/components/ui/badge';
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/components/ui/table';
import { cuttingStatusBadgeVariant } from '@/constants/cutting-status';
import type { CuttingListItem } from '@/types/cutting';
const props = defineProps<{
cutting: CuttingListItem;
}>();
interface GroupedMaterials {
key: number;
name: string;
unitLabel?: string;
items: typeof props.cutting.materials;
isCombination?: boolean;
}
interface GroupedResults {
key: number;
name: string;
items: typeof props.cutting.results;
}
const groupedMaterials = computed<GroupedMaterials[]>(() => {
// First, group by combination_id
const combinationGroups: Record<number, typeof props.cutting.materials> = {};
const nonCombinationItems: typeof props.cutting.materials = [];
props.cutting.materials.forEach((item) => {
if (item.combination_id) {
if (!combinationGroups[item.combination_id]) {
combinationGroups[item.combination_id] = [];
}
combinationGroups[item.combination_id].push(item);
} else {
nonCombinationItems.push(item);
}
});
const result: GroupedMaterials[] = [];
// Add combination groups
Object.entries(combinationGroups).forEach(([combinationId, items]) => {
result.push({
key: Number(combinationId) * -1,
name: 'Kombinasi',
items,
isCombination: true,
});
});
// Group non-combination items by raw material
const groups: Record<number, GroupedMaterials> = {};
nonCombinationItems.forEach((item) => {
const key = item.raw_material_id ?? 0;
const name = item.raw_material_name || 'Bahan Baku Tidak Diketahui';
if (!groups[key]) {
groups[key] = {
key,
name,
unitLabel: item.raw_material_unit_label,
items: [],
};
}
groups[key].items.push(item);
});
result.push(...Object.values(groups));
return result;
});
const groupedResults = computed<GroupedResults[]>(() => {
const groups: Record<number, GroupedResults> = {};
props.cutting.results.forEach((item) => {
const product = item.product_variant?.product;
const key = product?.id ?? 0;
const name = product?.name ?? 'Produk Tidak Diketahui';
if (!groups[key]) {
groups[key] = { key, name, items: [] };
}
groups[key].items.push(item);
});
return Object.values(groups);
});
</script>
<template>
<div class="min-h-screen bg-background">
<div class="mx-auto max-w-3xl px-4 py-8 sm:px-6 lg:px-8">
<!-- Header -->
<div class="mb-8 text-center">
<h1 class="text-2xl font-bold tracking-tight">
Detail Cutting
</h1>
<p class="mt-1 text-muted-foreground">
Rincian data proses cutting
</p>
</div>
<!-- Main Card -->
<div class="overflow-hidden rounded-lg border bg-card shadow-sm">
<!-- Cutting Info Header -->
<div class="border-b bg-muted/30 p-6">
<div class="flex flex-wrap items-center gap-3">
<h2 class="text-xl font-semibold">
Cutting #{{ cutting.id }}
</h2>
<Badge
:variant="cuttingStatusBadgeVariant(cutting.status)"
>
{{ cutting.status_label }}
</Badge>
</div>
<div class="mt-3 space-y-1 text-sm text-muted-foreground">
<p>{{ cutting.created_at_formatted }}</p>
<p>
Oleh
{{
cutting.created_by?.profile?.full_name ??
cutting.created_by?.username
}}
</p>
</div>
<p v-if="cutting.description" class="mt-3 text-sm">
{{ cutting.description }}
</p>
</div>
<!-- Results Section -->
<div v-if="cutting.results.length" class="border-b p-6">
<h3 class="mb-3 text-sm font-semibold">Hasil Produk</h3>
<div class="overflow-hidden rounded-md border">
<Table>
<TableHeader>
<TableRow>
<TableHead>Varian</TableHead>
<TableHead>Foto</TableHead>
<TableHead class="text-right"
>Hasil</TableHead
>
<TableHead class="text-right"
>Sample</TableHead
>
<TableHead class="text-right"
>Diluar Sample</TableHead
>
</TableRow>
</TableHeader>
<TableBody>
<template
v-for="(group, groupIndex) in groupedResults"
:key="group.key"
>
<TableRow
class="bg-muted/20 hover:bg-muted/20"
>
<TableCell
colspan="5"
class="font-semibold"
>
{{ groupIndex + 1 }}. {{ group.name }}
</TableCell>
</TableRow>
<TableRow
v-for="result in group.items"
:key="result.id"
>
<TableCell class="pl-6">
{{ result.product_variant?.name }}
</TableCell>
<TableCell>
<MediaThumbnailCell
:items="
result.product_variant
?.images ?? []
"
:max-visible="1"
/>
</TableCell>
<TableCell
class="text-right tabular-nums"
>
{{ result.cutting_result }} pcs
</TableCell>
<TableCell
class="text-right tabular-nums"
>
{{ result.sample }} pcs
</TableCell>
<TableCell
class="text-right tabular-nums"
>
{{ result.original_outside_sample }}
pcs
</TableCell>
</TableRow>
</template>
</TableBody>
</Table>
</div>
</div>
<!-- Materials Section -->
<div v-if="cutting.materials.length" class="border-b p-6">
<h3 class="mb-3 text-sm font-semibold">Bahan Baku</h3>
<div class="overflow-hidden rounded-md border">
<Table>
<TableHeader>
<TableRow>
<TableHead>Varian</TableHead>
<TableHead>Foto</TableHead>
<TableHead class="text-right"
>Pemakaian</TableHead
>
<TableHead class="text-right"
>Hasil</TableHead
>
</TableRow>
</TableHeader>
<TableBody>
<template
v-for="(group, groupIndex) in groupedMaterials"
:key="group.key"
>
<TableRow
class="bg-muted/20 hover:bg-muted/20"
>
<TableCell
colspan="4"
class="font-semibold"
>
<template v-if="group.isCombination">
<span class="text-primary">{{ groupIndex + 1 }}. {{ group.name }}</span>
<Badge
variant="default"
class="ml-2 font-normal"
>
{{ group.items.length }} bahan
</Badge>
<Badge
v-if="group.items[0]?.combination_material_result !== null && group.items[0]?.combination_material_result !== undefined"
variant="secondary"
class="ml-2 font-normal"
>
Hasil: {{ group.items[0].combination_material_result }} pcs
</Badge>
</template>
<template v-else>
{{ groupIndex + 1 }}. {{ group.name }}
<Badge
v-if="group.unitLabel"
variant="secondary"
class="ml-2 font-normal"
>
{{ group.unitLabel }}
</Badge>
</template>
</TableCell>
</TableRow>
<TableRow
v-for="material in group.items"
:key="material.id"
>
<TableCell class="pl-6">
{{ material.variant }}
</TableCell>
<TableCell>
<MediaThumbnailCell
:items="material.images ?? []"
:max-visible="1"
/>
</TableCell>
<TableCell
class="text-right tabular-nums"
>
{{
material.material_usage_formatted
}}
</TableCell>
<TableCell
class="text-right tabular-nums"
>
<template v-if="group.isCombination && material.combination_material_result !== null && material.combination_material_result !== undefined">
{{ material.combination_material_result }} pcs
</template>
<template v-else-if="!group.isCombination && material.material_result !== null && material.material_result !== undefined">
{{ material.material_result }} pcs
</template>
<template v-else>
-
</template>
</TableCell>
</TableRow>
</template>
</TableBody>
</Table>
</div>
</div>
<!-- Summary -->
<div class="p-6">
<h3 class="mb-3 text-sm font-semibold">Ringkasan</h3>
<div class="grid gap-4 sm:grid-cols-2">
<div class="rounded-lg border p-3">
<p class="text-xs text-muted-foreground">
Total Hasil Cutting
</p>
<p class="mt-1 text-lg font-semibold text-primary">
{{ cutting.total_result_pieces ?? 0 }} pcs
</p>
</div>
<div
v-if="
cutting.total_material_usage_summary_formatted
"
class="rounded-lg border p-3"
>
<p class="text-xs text-muted-foreground">
Total Pemakaian Bahan
</p>
<p class="mt-1 text-lg font-semibold text-primary">
{{
cutting.total_material_usage_summary_formatted
}}
</p>
</div>
</div>
</div>
</div>
<!-- Footer -->
<div class="mt-6 text-center text-xs text-muted-foreground">
<p>Data ini dibagikan dari sistem DST Collection</p>
</div>
</div>
</div>
</template>