167 lines
7.5 KiB
Vue
167 lines
7.5 KiB
Vue
<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>
|
|
<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 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>
|
|
<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>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, computed } from 'vue'
|
|
import ProductCustomization from './components/ProductCustomization.vue'
|
|
import ProductVariants from './components/ProductVariants.vue'
|
|
import Default from '@/layouts/default.vue'
|
|
interface Color {
|
|
id: string
|
|
name: string
|
|
hex: string
|
|
image: string
|
|
}
|
|
|
|
interface ProductData {
|
|
name: string
|
|
description: string
|
|
price: string
|
|
dimensions: string
|
|
seatHeight: string
|
|
image: string
|
|
colors: Color[]
|
|
descriptionText: string
|
|
howToUseText: string
|
|
productDetailsText: string
|
|
documentsText: string
|
|
}
|
|
|
|
const activeTab = ref('description')
|
|
const value = ref(5)
|
|
const selectedColor = ref<Color | null>(null)
|
|
|
|
const productData: ProductData = {
|
|
name: 'Larger Corner Sofa',
|
|
description: 'The large corner sofa is a comfortable seating solution for young children. It is upholstered with phthalate-free PVC-coated material intended for medical products, making it very easy to clean and disinfect. The product is available in a wide range of colours (13 colours), allowing it to fit into any interior.',
|
|
price: 'PLN 519.00 (VAT 23%)',
|
|
dimensions: '65 x 65 x 120 cm',
|
|
seatHeight: '45-55 cm',
|
|
image: '/placeholder-chair.jpg',
|
|
colors: [
|
|
{ id: 'black', name: 'Black', hex: '#1a1a1a', image: '/chair-black.jpg' },
|
|
{ id: 'gray', name: 'Gray', hex: '#6b7280', image: '/chair-gray.jpg' },
|
|
{ id: 'blue', name: 'Blue', hex: '#3b82f6', image: '/chair-blue.jpg' },
|
|
{ id: 'brown', name: 'Brown', hex: '#92400e', image: '/chair-brown.jpg' },
|
|
],
|
|
descriptionText: 'The large corner sofa is a comfortable seating solution for young children. It is upholstered with phthalate-free PVC-coated material intended for medical products, making it very easy to clean and disinfect. The product is available in a wide range of colours (13 colours), allowing it to fit into any interior',
|
|
howToUseText: '1. Adjust the seat height using the lever under the seat.\n2. Set the lumbar support to your preferred position.\n3. Adjust the armrests for optimal arm support.\n4. Use the recline tension knob to adjust the backrest resistance.\n5. Lock the recline position when needed.',
|
|
productDetailsText: '• Material: Mesh, Foam, Plastic\n• Max Load: 150 kg\n• Weight: 18 kg\n• Warranty: 2 years\n• Certifications: BIFMA, EN 1335',
|
|
documentsText: '• Assembly Instructions (PDF)\n• User Manual (PDF)\n• Warranty Terms (PDF)\n• Safety Certificate (PDF)',
|
|
}
|
|
|
|
const tabs = [
|
|
{ id: 'description', label: 'Description' },
|
|
{ id: 'howToUse', label: 'How to Use' },
|
|
{ id: 'productDetails', label: 'Product Details' },
|
|
{ id: 'documents', label: 'Documents' },
|
|
]
|
|
|
|
const userActions = [
|
|
'View detailed product information',
|
|
'Browse product images and available colors',
|
|
'Check product dimensions and specifications',
|
|
'Select a product variant',
|
|
'Select quantity',
|
|
'Add the product to the cart',
|
|
'Navigate between product description, usage instructions, and product details',
|
|
]
|
|
|
|
const activeTabContent = computed(() => {
|
|
switch (activeTab.value) {
|
|
case 'description':
|
|
return productData.descriptionText
|
|
case 'howToUse':
|
|
return productData.howToUseText
|
|
case 'productDetails':
|
|
return productData.productDetailsText
|
|
case 'documents':
|
|
return productData.documentsText
|
|
default:
|
|
return ''
|
|
}
|
|
})
|
|
|
|
if (productData.colors.length > 0) {
|
|
selectedColor.value = productData.colors[0] as Color
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.product-card-full {
|
|
font-family: inherit;
|
|
}
|
|
</style>
|