store/resources/js/components/admin/master/MasterOutOfStockCatalogSection.vue

104 lines
4.2 KiB
Vue

<script setup lang="ts">
import { router } from '@inertiajs/vue3';
import { ChevronDown, PackageX } from '@lucide/vue';
import { computed, ref } from 'vue';
import PosCatalogCard from '@/components/admin/manage/PosCatalogCard.vue';
import PosCatalogVariantThumb from '@/components/admin/manage/PosCatalogVariantThumb.vue';
import { Badge } from '@/components/ui/badge';
import { Card, CardContent } from '@/components/ui/card';
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from '@/components/ui/collapsible';
import {
Empty,
EmptyDescription,
EmptyHeader,
EmptyTitle,
} from '@/components/ui/empty';
import type { MasterOutOfStockGroup } from '@/types/master-inventory';
const props = defineProps<{
title: string;
description?: string;
groups: MasterOutOfStockGroup[];
}>();
const open = ref(true);
const variantCount = computed(() => props.groups.reduce(
(total, group) => total + group.variants.length,
0,
));
function visitEdit(url: string): void {
router.visit(url);
}
</script>
<template>
<Collapsible v-model:open="open">
<Card>
<CollapsibleTrigger
class="flex w-full items-center justify-between gap-3 px-6 py-4 text-left transition-colors hover:bg-muted/30">
<div class="min-w-0 space-y-1">
<div class="flex items-center gap-2">
<PackageX class="size-4 shrink-0 text-red-600 dark:text-red-400" />
<h3 class="font-semibold leading-tight">
{{ title }}
</h3>
<Badge v-if="variantCount > 0" variant="destructive">
{{ variantCount }}
</Badge>
</div>
<p v-if="description" class="text-xs text-muted-foreground">
{{ description }}
</p>
</div>
<ChevronDown class="size-4 shrink-0 text-muted-foreground transition-transform duration-200"
:class="open ? 'rotate-180' : ''" />
</CollapsibleTrigger>
<CollapsibleContent>
<CardContent class="pt-0">
<div v-if="groups.length" class="columns-1 gap-4 sm:columns-2 xl:columns-3">
<PosCatalogCard v-for="group in groups" :key="group.id" :title="group.name" :show-cover="false"
class="cursor-pointer transition-shadow hover:shadow-md" @click="visitEdit(group.edit_url)">
<template v-if="group.unit_label" #header-extra>
<Badge variant="secondary" class="mt-1.5">
{{ group.unit_label }}
</Badge>
</template>
<div v-for="variant in group.variants" :key="variant.id"
class="flex items-center gap-2.5 px-3 py-2.5 transition-colors hover:bg-muted/30"
@click.stop="visitEdit(group.edit_url)">
<PosCatalogVariantThumb :items="variant.images" />
<div class="min-w-0 flex-1">
<p class="truncate text-sm font-medium">
{{ variant.name }}
</p>
<p class="text-xs font-medium tabular-nums text-red-600 dark:text-red-400">
{{ variant.stock_formatted }}
</p>
</div>
</div>
</PosCatalogCard>
</div>
<Empty v-else class="py-8">
<EmptyHeader>
<EmptyTitle>Tidak ada stok habis</EmptyTitle>
<EmptyDescription>
Semua varian masih memiliki stok tersedia.
</EmptyDescription>
</EmptyHeader>
</Empty>
</CardContent>
</CollapsibleContent>
</Card>
</Collapsible>
</template>