refactor: streamline product type definitions and enhance ProductGroupedTable.vue for improved data display

This commit is contained in:
Yoga Pangestu 2026-06-24 00:26:14 +07:00
parent 3f510f3d58
commit e0e38c1298
2 changed files with 45 additions and 90 deletions

View File

@ -1,12 +1,11 @@
<script setup lang="ts">
import { Link } from '@inertiajs/vue3';
import { computed } from 'vue';
import { DataTableEmpty } from '@/components/data-table';
import DataTableToolbar from '@/components/data-table/DataTableToolbar.vue';
import { formatRupiah } from '@/lib/rupiah';
import MediaThumbnailCell from '@/components/media/MediaThumbnailCell.vue';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { DataTableEmpty } from '@/components/data-table';
import {
Table,
TableBody,
@ -96,12 +95,12 @@ function rowNumber(index: number): number {
<div class="flex flex-wrap items-center gap-x-4 gap-y-1 text-sm">
<span>
Total stok bagus <strong class="text-primary">
{{ product.variants.reduce((acc, v) => acc + v.stock, 0) }}
{{product.variants.reduce((acc, v) => acc + v.stock, 0)}}
</strong>
</span>
<span>
Total stok reject <strong class="text-destructive">
{{ product.variants.reduce((acc, v) => acc + v.reject_stock, 0) }}
{{product.variants.reduce((acc, v) => acc + v.reject_stock, 0)}}
</strong>
</span>
</div>

View File

@ -1,89 +1,4 @@
import type { MediaItem, MediaUploadState } from '@/types/media';
export type EnumOption = {
value: string;
label: string;
};
export type CategoryOption = {
value: number;
label: string;
};
export type ProductPriceItem = {
id: number;
variant_id: number;
type: string;
price: number;
price_formatted: string;
price_input: string;
};
export type ProductCategoryItem = {
id: number;
name: string;
};
export type ProductVariantItem = {
id: number;
name: string;
stock: number;
reject_stock: number;
prices: ProductPriceItem[];
images?: MediaItem[];
};
export type ProductListItem = {
id: number;
name: string;
is_active: boolean;
categories: ProductCategoryItem[];
variants: ProductVariantItem[];
};
export type ProductVariantFormItem = {
client_id: string;
id?: number;
name: string;
stock: string;
media: MediaUploadState;
};
export type ProductFormData = {
name: string;
description: string;
category_ids: number[];
variants: Array<{
id?: number;
name: string;
stock: number;
}>;
};
export type ProductFilters = {
search: string;
sort?: string;
direction?: 'asc' | 'desc' | null;
is_active?: string;
category_id?: string;
stock_status?: string;
};
export type PaginatedProducts = {
data: ProductListItem[];
current_page: number;
last_page: number;
per_page: number;
total: number;
links: Array<{
url: string | null;
label: string;
active: boolean;
}>;
};
export const PRICE_TYPES = [
'harga_modal',
'distributor',
'agent',
'sub_agent',
@ -91,12 +6,12 @@ export const PRICE_TYPES = [
'ecer',
'tiktok',
'shopee',
'harga_modal',
] as const;
export type PriceType = (typeof PRICE_TYPES)[number];
export const PRICE_TYPE_LABELS: Record<PriceType, string> = {
harga_modal: 'Harga Modal',
distributor: 'Distributor',
agent: 'Agen',
sub_agent: 'Sub Agen',
@ -104,4 +19,45 @@ export const PRICE_TYPE_LABELS: Record<PriceType, string> = {
ecer: 'Eceran',
tiktok: 'TikTok',
shopee: 'Shopee',
harga_modal: 'Harga Modal',
};
export interface Price {
id: number;
variant_id: number;
type: string;
price: number;
price_formatted: string;
type_label: string;
}
export interface MediaItem {
id: number;
url: string;
thumb_url: string;
}
export interface Variant {
id: number;
product_id: number;
name: string;
stock: number;
prices: Price[];
images: MediaItem[];
}
export interface Category {
id: number;
name: string;
slug: string;
}
export interface Product {
id: number;
name: string;
slug: string;
description: string | null;
is_active: boolean;
categories: Category[];
variants: Variant[];
}