fitur fitur darkmode dan foto foto

This commit is contained in:
2026-05-19 10:47:55 +07:00
parent 7e1cb94689
commit 6c36f7565e
57 changed files with 7867 additions and 236 deletions
+39 -6
View File
@@ -1,7 +1,7 @@
<template>
<section class="container-page py-10">
<RouterLink to="/marketplace" class="mb-6 inline-flex text-sm font-bold text-brand-700">
Kembali ke Marketplace
<- Kembali ke Marketplace
</RouterLink>
<div v-if="loading" class="card p-10 text-center">
@@ -9,8 +9,23 @@
</div>
<div v-else-if="product" class="grid gap-8 lg:grid-cols-2">
<div class="card overflow-hidden">
<img :src="getProductImageUrl(product.image)" :alt="product.title" class="aspect-[4/3] w-full object-cover" />
<div class="grid gap-4 sm:grid-cols-[88px_1fr]">
<div class="order-2 flex gap-3 overflow-x-auto sm:order-1 sm:grid sm:max-h-[520px] sm:overflow-y-auto">
<button
v-for="(image, index) in productImages"
:key="`${image}-${index}`"
type="button"
class="h-20 w-20 shrink-0 overflow-hidden rounded-xl border-2 bg-white"
:class="selectedImage === image ? 'border-brand-600' : 'border-slate-200'"
@click="selectedImage = image"
>
<img :src="getProductImageUrl(image)" :alt="`${product.title} ${index + 1}`" class="h-full w-full object-cover" />
</button>
</div>
<div class="card order-1 overflow-hidden sm:order-2">
<img :src="getProductImageUrl(selectedImage)" :alt="product.title" class="aspect-[4/3] w-full object-cover" />
</div>
</div>
<div>
@@ -45,7 +60,7 @@
</div>
<div class="mt-8 flex flex-wrap gap-3">
<a :href="waLink" target="_blank" class="btn-WA">Hubungi via WhatsApp</a>
<a :href="waLink" target="_blank" class="btn-primary">Hubungi via WhatsApp</a>
<button class="btn-secondary" @click="toggleSave">
{{ saved ? "Hapus dari Tersimpan" : "Simpan Barang" }}
</button>
@@ -61,7 +76,7 @@
</template>
<script setup>
import { computed, onMounted, ref } from "vue"
import { computed, onMounted, ref, watch } from "vue"
import { useRoute } from "vue-router"
import { products as defaultProducts } from "../data/products"
import { fetchProduct, formatRupiah, getProductImageUrl, getSavedProducts, setSavedProducts } from "../utils"
@@ -70,6 +85,23 @@ const route = useRoute()
const id = Number(route.params.id)
const product = ref(null)
const loading = ref(true)
const selectedImage = ref("")
const productImages = computed(() => {
if (!product.value) return []
const images = product.value.images?.length ? product.value.images : [product.value.image]
return [...new Set(images.filter(Boolean))]
})
watch(
productImages,
(images) => {
if (!images.includes(selectedImage.value)) {
selectedImage.value = images[0] || ""
}
},
{ immediate: true }
)
const savedIds = ref(getSavedProducts())
const saved = computed(() => savedIds.value.includes(id))
@@ -95,7 +127,8 @@ async function loadProduct() {
const data = await fetchProduct(id)
product.value = data.product
} catch {
product.value = defaultProducts.find((item) => Number(item.id) === id) || null
const fallbackProduct = defaultProducts.find((item) => Number(item.id) === id) || null
product.value = fallbackProduct ? { ...fallbackProduct, images: [fallbackProduct.image] } : null
} finally {
loading.value = false
}