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

View File

@ -14,6 +14,7 @@ const props = defineProps<{
maxVisible?: number; maxVisible?: number;
title?: string; title?: string;
allUrls?: string[]; allUrls?: string[];
allTitles?: string[];
}>(); }>();
const previewOpen = ref(false); const previewOpen = ref(false);
@ -120,5 +121,5 @@ function openGallery() {
</DialogContent> </DialogContent>
</Dialog> </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> </template>

View File

@ -59,6 +59,12 @@ function allVariantImageUrls(product: ProductListItem): string[] {
return product.variants.flatMap((variant) => (variant.images ?? []).map((img) => img.url)); 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 verificationModalOpen = ref(false);
const selectedRequestId = ref<number | null>(null); const selectedRequestId = ref<number | null>(null);
@ -152,7 +158,7 @@ function openVerificationDetail(requestId: number | undefined) {
{{ variant.name }} {{ variant.name }}
</TableCell> </TableCell>
<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>
<TableCell class="tabular-nums"> <TableCell class="tabular-nums">
{{ variant.stock_formatted }} {{ 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)); 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 verificationModalOpen = ref(false);
const selectedRequestId = ref<number | null>(null); const selectedRequestId = ref<number | null>(null);
@ -144,7 +150,7 @@ function openVerificationDetail(requestId: number | undefined) {
{{ price.variant }} {{ price.variant }}
</TableCell> </TableCell>
<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>
<TableCell class="tabular-nums"> <TableCell class="tabular-nums">
{{ price.stock_formatted }} {{ price.stock_formatted }}