Create product view section

This commit is contained in:
marzban-dev
2024-12-13 23:47:50 +03:30
parent f3c5f91669
commit 2c9de38aca
10 changed files with 283 additions and 1 deletions
+1
View File
@@ -114,6 +114,7 @@
--breakpoint-2xs: 400px;
--breakpoint-xs: 480px;
/* ANIMATIONS */
--animate-marquee: marquee 3s linear infinite;
@@ -0,0 +1,36 @@
<script lang="ts" setup>
// types
import ColorCircle from "~/components/ui/ColorCircle.vue";
type Props = {
colors: string[];
selectedColor: string;
}
// props
defineProps<Props>();
// emit
defineEmits(["update:selectedColor"]);
</script>
<template>
<div>
<span>
Color : {{ selectedColor}}
</span>
<div>
<ColorCircle
v-for="color in colors"
:key="color"
:color="color"
:selected="selectedColor === color"
/>
</div>
</div>
</template>
@@ -0,0 +1,20 @@
<script lang="ts" setup>
</script>
<template>
<div class="flex items-center justify-between w-full bg-slate-100 border-[1.5px] border-slate-200 rounded-100 p-6">
<div class="flex items-start gap-3">
<div class="flex p-1 items-center justify-center rounded-full bg-success-500">
<Icon name="ci:check" class="size-4 **:stroke-white"/>
</div>
<div class="flex flex-col gap-1">
<span class="typo-label-sm whitespace-nowrap">Pick up from Store</span>
<span class="typo-p-sm whitespace-nowrap">Usually ready in 2 hours</span>
</div>
</div>
<span class="typo-p-xs">
Check availability at other stores
</span>
</div>
</template>
@@ -0,0 +1,58 @@
<script lang="ts" setup>
// types
type Props = {
modelValue: number;
max: number;
}
// props
const props = defineProps<Props>();
const { modelValue } = toRefs(props);
// emit
const emit = defineEmits(["update:modelValue"]);
// state
const currentQuantity = ref(modelValue.value);
// methods
const onInput = (e: any) => {
currentQuantity.value = Number(e.target.value);
};
// watch
watch(() => currentQuantity.value, (newValue) => {
emit("update:modelValue", newValue);
});
</script>
<template>
<div class="">
<NumberFieldRoot
class="rounded-full border-slate-200 border-[1.5px] flex items-center bg-white gap-4 p-4"
v-model="currentQuantity"
:min="1"
:max="max"
>
<NumberFieldIncrement class="cursor-pointer">
<Icon name="ci:plus" class="**:stroke-slate-500 size-5" />
</NumberFieldIncrement>
<NumberFieldInput
@input="onInput"
class="field-sizing-content bg-transparent outline-none typo-label-md text-black"
/>
<NumberFieldDecrement class="cursor-pointer">
<Icon name="ci:minus" class="**:stroke-slate-500 size-5" />
</NumberFieldDecrement>
</NumberFieldRoot>
</div>
</template>
@@ -0,0 +1,33 @@
<script lang="ts">
</script>
<template>
<div class="flex items-center gap-2">
<span class="typo-p-sm">
5.0
</span>
<div class="flex items-center gap-1">
<Icon
name="ci:star-solid"
class="size-4.5 **:fill-yellow-500"
/>
<Icon
name="ci:star-solid"
class="size-4.5 **:fill-yellow-500"
/>
<Icon
name="ci:star-solid"
class="size-4.5 **:fill-yellow-500"
/>
<Icon
name="ci:star-solid"
class="size-4.5 **:fill-yellow-500"
/>
<Icon
name="ci:star-solid"
class="size-4.5 **:fill-yellow-500"
/>
</div>
</div>
</template>
@@ -0,0 +1,28 @@
<script lang="ts" setup>
// types
type Props = {
quantity: number;
}
// props
defineProps<Props>();
</script>
<template>
<div class="flex flex-col gap-2 w-full items-end">
<p class="typo-p-sm text-slate-500">
Hurry, only
<span class="text-black">
{{ quantity }}
</span>
items left in stock
</p>
<div class="h-2 rounded-full relative bg-slate-200 w-full">
<div class="w-[85%] h-full absolute left-0 rounded-full bg-black" />
</div>
</div>
</template>
@@ -0,0 +1,23 @@
<template>
<div class="flex items-center gap-6">
<span class="typo-p-md text-black">
Share:
</span>
<div class="flex items-center gap-3">
<NuxtLink>
<Icon name="ci:instagram" class="**:stroke-slate-500 size-6" />
</NuxtLink>
<NuxtLink>
<Icon name="ci:facebook" class="**:stroke-slate-500 size-6" />
</NuxtLink>
<NuxtLink>
<Icon name="ci:tiktok" class="**:stroke-slate-500 size-6" />
</NuxtLink>
<NuxtLink>
<Icon name="ci:youtube" class="**:stroke-slate-500 size-6" />
</NuxtLink>
</div>
</div>
</template>
<script setup lang="ts">
</script>
@@ -0,0 +1,55 @@
<script lang="ts" setup>
// state
const quantity = ref(1);
const maxQuantity = ref(10);
</script>
<template>
<div class="flex gap-12">
<div class="w-[800px] flex flex-col items-end gap-3 mt-12">
<span class="typo-label-sm">
Nova
</span>
<h1 class="typo-h-2">
Nova
</h1>
<div class="flex w-full items-center justify-between">
<Rating />
<span class="typo-p-2xl">
$689.00
</span>
</div>
<p class="typo-p-md text-slate-500 text-left">
Compact, stylish, and engineered for the future, Eco Tunes are more than just headphones; they're a
statement. Hear the future, save the planet.
</p>
<div class="w-full flex flex-col gap-6 mt-4">
<RemainQuantity :quantity="maxQuantity" />
<div class="w-full flex gap-3 flex-col">
<div class="w-full flex gap-3">
<Button
class="w-full"
end-icon="ci:plus"
>
Add to cart
</Button>
<QuantityCounter v-model="quantity" :max="maxQuantity" />
</div>
<Button
class="w-full"
variant="outlined"
>
Buy it now
</Button>
</div>
<InfoCard />
<Share />
</div>
</div>
<div class="bg-red-300 w-full h-[500px] rounded-200">
</div>
</div>
</template>
+22 -1
View File
@@ -1,3 +1,24 @@
<script lang="ts" setup>
// types
type Props = {
color: string;
selected ?: boolean;
}
// props
defineProps<Props>();
</script>
<template>
<div class="size-[30px] rounded-full shadow-black/30 shadow-inner"></div>
<div
class="size-[30px] ring ring-offset-1 rounded-full shadow-black/30 shadow-inner"
:class="selected ? 'ring-black' : 'ring-transparent'"
:style="{
backgroundColor: color,
}"
/>
</template>
+7
View File
@@ -0,0 +1,7 @@
<script lang="ts" setup>
</script>
<template>
<ProductView />
</template>