feat: enhance media components by adding support for multiple titles in MediaPreviewDialog and related updates in MediaThumbnailCell
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (8.3) (push) Waiting to run
tests / ci (8.4) (push) Waiting to run
tests / ci (8.5) (push) Waiting to run

This commit is contained in:
Yoga Pangestu 2026-07-08 11:14:24 +07:00
parent 5e57317d8f
commit 452c1a4209
4 changed files with 28 additions and 4 deletions

View File

@ -21,13 +21,16 @@ const props = withDefaults(
url: string | null;
urls?: string[];
title?: string;
titles?: string[];
}>(),
{
urls: () => [],
title: 'Pratinjau Foto',
titles: () => [],
}
);
const activeUrl = ref<string | null>(props.url);
watch(
@ -63,6 +66,14 @@ const currentIndex = computed(() => {
const hasMultiple = computed(() => allUrls.value.length > 1);
const activeTitle = computed(() => {
if (props.titles && props.titles.length > 0 && currentIndex.value >= 0) {
return props.titles[currentIndex.value] ?? props.title ?? 'Pratinjau Foto';
}
return props.title ?? 'Pratinjau Foto';
});
function nextImage() {
if (!hasMultiple.value) {
return;
@ -130,7 +141,7 @@ function handleTouchEnd(e: TouchEvent) {
<Dialog v-model:open="open">
<DialogContent class="sm:max-w-2xl p-4 overflow-hidden gap-4">
<DialogHeader class="pb-2 border-b">
<DialogTitle class="text-base font-semibold">{{ title ?? 'Pratinjau Gambar' }}</DialogTitle>
<DialogTitle class="text-base font-semibold">{{ activeTitle }}</DialogTitle>
</DialogHeader>
<div class="relative flex items-center justify-center min-h-[300px] select-none"

View File

@ -14,6 +14,7 @@ const props = defineProps<{
maxVisible?: number;
title?: string;
allUrls?: string[];
allTitles?: string[];
}>();
const previewOpen = ref(false);
@ -120,5 +121,5 @@ function openGallery() {
</DialogContent>
</Dialog>
<MediaPreviewDialog v-model:open="previewOpen" v-model:url="previewUrl" :urls="allUrls ?? items.map(item => item.url)" :title="title" @close="onPreviewClose" />
<MediaPreviewDialog v-model:open="previewOpen" v-model:url="previewUrl" :urls="allUrls ?? items.map(item => item.url)" :title="title" :titles="allTitles" @close="onPreviewClose" />
</template>

View File

@ -59,6 +59,12 @@ function allVariantImageUrls(product: ProductListItem): string[] {
return product.variants.flatMap((variant) => (variant.images ?? []).map((img) => img.url));
}
function allVariantImageTitles(product: ProductListItem): string[] {
return product.variants.flatMap((variant) =>
(variant.images ?? []).map(() => `${product.name} - ${variant.name}`)
);
}
const verificationModalOpen = ref(false);
const selectedRequestId = ref<number | null>(null);
@ -152,7 +158,7 @@ function openVerificationDetail(requestId: number | undefined) {
{{ variant.name }}
</TableCell>
<TableCell>
<MediaThumbnailCell :items="variant.images ?? []" :max-visible="1" :title="`${product.name} - ${variant.name}`" :all-urls="allVariantImageUrls(product)" />
<MediaThumbnailCell :items="variant.images ?? []" :max-visible="1" :title="`${product.name} - ${variant.name}`" :all-urls="allVariantImageUrls(product)" :all-titles="allVariantImageTitles(product)" />
</TableCell>
<TableCell class="tabular-nums">
{{ variant.stock_formatted }}

View File

@ -53,6 +53,12 @@ function allVariantImageUrls(material: RawMaterialListItem): string[] {
return material.prices.flatMap((price) => (price.images ?? []).map((img) => img.url));
}
function allVariantImageTitles(material: RawMaterialListItem): string[] {
return material.prices.flatMap((price) =>
(price.images ?? []).map(() => `${material.name} - ${price.variant}`)
);
}
const verificationModalOpen = ref(false);
const selectedRequestId = ref<number | null>(null);
@ -144,7 +150,7 @@ function openVerificationDetail(requestId: number | undefined) {
{{ price.variant }}
</TableCell>
<TableCell>
<MediaThumbnailCell :items="price.images ?? []" :max-visible="1" :title="`${material.name} - ${price.variant}`" :all-urls="allVariantImageUrls(material)" />
<MediaThumbnailCell :items="price.images ?? []" :max-visible="1" :title="`${material.name} - ${price.variant}`" :all-urls="allVariantImageUrls(material)" :all-titles="allVariantImageTitles(material)" />
</TableCell>
<TableCell class="tabular-nums">
{{ price.stock_formatted }}