fix: store customer-product
This commit is contained in:
@@ -1,75 +1,84 @@
|
||||
<template>
|
||||
<component :is="Default || 'div'">
|
||||
<div class="">
|
||||
<div class="flex md:flex-row flex-col justify-between gap-8 my-6">
|
||||
<div class="flex-1">
|
||||
<div class="bg-gray-100 dark:bg-gray-800 rounded-lg p-8 flex items-center justify-center min-h-[300px] ">
|
||||
<img :src="selectedColor?.image || productData.image" :alt="productData.name"
|
||||
class="max-w-full h-auto object-contain" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1 flex flex-col gap-4">
|
||||
<h1 class="text-2xl font-bold text-gray-900 dark:text-white">
|
||||
{{ productData.name }}
|
||||
</h1>
|
||||
<p class="text-gray-600 dark:text-gray-300">
|
||||
{{ productData.description }}
|
||||
</p>
|
||||
<div class="text-3xl font-bold text-(--text-sky-light) dark:text-(--text-sky-dark)">
|
||||
{{ productData.price }}
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<div class="flex gap-2">
|
||||
<span class="text-gray-500 dark:text-gray-400">Dimensions:</span>
|
||||
<p class="font-medium dark:text-white">{{ productData.dimensions }}</p>
|
||||
<div class="">
|
||||
<div class="flex md:flex-row flex-col justify-between gap-8 my-6">
|
||||
<div class="flex-1">
|
||||
<div
|
||||
class="bg-gray-100 dark:bg-gray-800 rounded-lg p-8 flex items-center justify-center min-h-[300px] ">
|
||||
<img :src="selectedColor?.image || productData.image" :alt="productData.name"
|
||||
class="max-w-full h-auto object-contain" />
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<span class="text-gray-500 dark:text-gray-400">Seat Height:</span>
|
||||
<p class="font-medium dark:text-white">{{ productData.seatHeight }}</p>
|
||||
</div>
|
||||
<div class="flex-1 flex flex-col gap-4">
|
||||
<div class="flex justify-between items-center">
|
||||
<h1 class="text-2xl font-bold text-gray-900 dark:text-white">
|
||||
{{ productData.name }}
|
||||
</h1>
|
||||
|
||||
<UIcon name="material-symbols:favorite"
|
||||
class="cursor-pointer text-2xl transition hover:scale-110"
|
||||
:class="productData.is_favorite ? 'text-red-500' : 'text-gray-400'"
|
||||
@click="toggleFavorite" />
|
||||
</div>
|
||||
<p class="text-gray-600 dark:text-gray-300">
|
||||
{{ productData.description }}
|
||||
</p>
|
||||
<div class="text-3xl font-bold text-(--text-sky-light) dark:text-(--text-sky-dark)">
|
||||
{{ productData.price }}
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<div class="flex gap-2">
|
||||
<span class="text-gray-500 dark:text-gray-400">Dimensions:</span>
|
||||
<p class="font-medium dark:text-white">{{ productData.dimensions }}</p>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<span class="text-gray-500 dark:text-gray-400">Seat Height:</span>
|
||||
<p class="font-medium dark:text-white">{{ productData.seatHeight }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex md:flex-row flex-col justify-between md:items-end items-start gap-5 md:gap-0 md:mb-8 mb-4">
|
||||
<div class="flex flex-col gap-3">
|
||||
<span class="text-sm text-(--text-sky-light) dark:text-(--text-sky-dark) ">Colors:</span>
|
||||
<div class="flex gap-2">
|
||||
<button v-for="color in productData.colors" :key="color.id" @click="selectedColor = color"
|
||||
class="w-10 h-10 border-2 transition-all" :class="selectedColor?.id === color.id
|
||||
? 'border-(--accent-blue-light) ring-2 ring-blue-600 ring-offset-2'
|
||||
: 'border-gray-300 dark:border-gray-600 hover:border-gray-400'"
|
||||
:style="{ backgroundColor: color.hex }" :title="color.name" />
|
||||
<div class="flex md:flex-row flex-col justify-between md:items-end items-start gap-5 md:gap-0 md:mb-8 mb-4">
|
||||
<div class="flex flex-col gap-3">
|
||||
<span class="text-sm text-(--text-sky-light) dark:text-(--text-sky-dark) ">Colors:</span>
|
||||
<div class="flex gap-2">
|
||||
<button v-for="color in productData.colors" :key="color.id" @click="selectedColor = color"
|
||||
class="w-10 h-10 border-2 transition-all" :class="selectedColor?.id === color.id
|
||||
? 'border-(--accent-blue-light) ring-2 ring-blue-600 ring-offset-2'
|
||||
: 'border-gray-300 dark:border-gray-600 hover:border-gray-400'"
|
||||
:style="{ backgroundColor: color.hex }" :title="color.name" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-5 items-end">
|
||||
<UInputNumber v-model="value" />
|
||||
<UButton color="primary"
|
||||
class="px-14! bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) text-white">
|
||||
Add to Cart
|
||||
</UButton>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-5 items-end">
|
||||
<UInputNumber v-model="value" />
|
||||
<UButton color="primary" class="px-14! bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) text-white">
|
||||
Add to Cart
|
||||
</UButton>
|
||||
<ProductCustomization />
|
||||
<hr class="border-t border-(--border-light) dark:border-(--border-dark) mb-8" />
|
||||
<div class="mb-6 w-[100%] xl:w-[60%]">
|
||||
<div class="grid grid-cols-2 lg:grid-cols-4 gap-10 mb-8">
|
||||
<UButton v-for="tab in tabs" :key="tab.id" @click="activeTab = tab.id" :class="[
|
||||
'px-15 py-2 cursor-pointer sm:text-nowrap flex items-center! justify-center!',
|
||||
activeTab === tab.id
|
||||
? 'bg-blue-600 hover:text-black hover:dark:text-white text-white'
|
||||
: 'text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700'
|
||||
]" variant="ghost">
|
||||
{{ tab.label }}
|
||||
</UButton>
|
||||
</div>
|
||||
<div class="py-5 px-3 bg-(--second-light) dark:bg-(--main-dark) rounded-md">
|
||||
<p class="dark:text-white whitespace-pre-line">
|
||||
{{ activeTabContent }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="border-t border-(--border-light) dark:border-(--border-dark) mb-8" />
|
||||
<ProductVariants />
|
||||
</div>
|
||||
<ProductCustomization />
|
||||
<hr class="border-t border-(--border-light) dark:border-(--border-dark) mb-8" />
|
||||
<div class="mb-6 w-[100%] xl:w-[60%]">
|
||||
<div class="grid grid-cols-2 lg:grid-cols-4 gap-10 mb-8">
|
||||
<UButton v-for="tab in tabs" :key="tab.id" @click="activeTab = tab.id" :class="[
|
||||
'px-15 py-2 cursor-pointer sm:text-nowrap flex items-center! justify-center!',
|
||||
activeTab === tab.id
|
||||
? 'bg-blue-600 hover:text-black hover:dark:text-white text-white'
|
||||
: 'text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700'
|
||||
]" variant="ghost">
|
||||
{{ tab.label }}
|
||||
</UButton>
|
||||
</div>
|
||||
<div class="py-5 px-3 bg-(--second-light) dark:bg-(--main-dark) rounded-md">
|
||||
<p class="dark:text-white whitespace-pre-line">
|
||||
{{ activeTabContent }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="border-t border-(--border-light) dark:border-(--border-dark) mb-8" />
|
||||
<ProductVariants />
|
||||
</div>
|
||||
</component>
|
||||
</template>
|
||||
|
||||
@@ -78,6 +87,8 @@ import { ref, computed } from 'vue'
|
||||
import ProductCustomization from './components/ProductCustomization.vue'
|
||||
import ProductVariants from './components/ProductVariants.vue'
|
||||
import Default from '@/layouts/default.vue'
|
||||
import { useFetchJson } from '@/composable/useFetchJson'
|
||||
import { useRoute } from 'vue-router'
|
||||
interface Color {
|
||||
id: string
|
||||
name: string
|
||||
@@ -97,6 +108,7 @@ interface ProductData {
|
||||
howToUseText: string
|
||||
productDetailsText: string
|
||||
documentsText: string
|
||||
is_favorite: boolean
|
||||
}
|
||||
|
||||
const activeTab = ref('description')
|
||||
@@ -157,6 +169,24 @@ const activeTabContent = computed(() => {
|
||||
if (productData.colors.length > 0) {
|
||||
selectedColor.value = productData.colors[0] as Color
|
||||
}
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
async function toggleFavorite() {
|
||||
const url = `/api/v1/restricted/product/favorite/${route.params.product_id}`
|
||||
|
||||
try {
|
||||
if (!productData.is_favorite) {
|
||||
await useFetchJson(url, { method: 'POST' })
|
||||
} else {
|
||||
await useFetchJson(url, { method: 'DELETE' })
|
||||
}
|
||||
|
||||
productData.is_favorite = !productData.is_favorite
|
||||
} catch (e: unknown) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
Reference in New Issue
Block a user