Initial commit

This commit is contained in:
2025-08-04 16:33:07 +03:30
commit f798e8e35c
9595 changed files with 1208683 additions and 0 deletions

View File

@@ -0,0 +1,290 @@
<script setup>
const props = defineProps({
currentStep: {
type: Number,
required: false,
},
checkoutData: {
type: null,
required: true,
},
})
const emit = defineEmits([
'update:currentStep',
'update:checkout-data',
])
const checkoutAddressDataLocal = ref(JSON.parse(JSON.stringify(props.checkoutData)))
const isEditAddressDialogVisible = ref(false)
watch(() => props.checkoutData, value => {
checkoutAddressDataLocal.value = JSON.parse(JSON.stringify(value))
})
const deliveryOptions = [
{
icon: { icon: 'tabler-user' },
title: 'Standard',
desc: 'Get your product in 1 Week.',
value: 'free',
},
{
icon: { icon: 'tabler-star' },
title: 'Express',
desc: 'Get your product in 4 days.',
value: 'express',
},
{
icon: { icon: 'tabler-crown' },
title: 'Overnight',
desc: 'Get your product in 1 day.',
value: 'overnight',
},
]
const resolveAddressBadgeColor = {
home: 'primary',
office: 'success',
}
const resolveDeliveryBadgeData = {
free: {
color: 'success',
price: 0,
text: 'Free',
},
express: {
color: 'secondary',
price: 10,
text: '$10',
},
overnight: {
color: 'secondary',
price: 15,
text: '$15',
},
}
const totalPriceWithDeliveryCharges = computed(() => {
let deliveryCharges = 0
if (checkoutAddressDataLocal.value.deliverySpeed !== 'free')
deliveryCharges = resolveDeliveryBadgeData[checkoutAddressDataLocal.value.deliverySpeed].price
return checkoutAddressDataLocal.value.orderAmount + deliveryCharges
})
const updateAddressData = () => {
checkoutAddressDataLocal.value.deliveryCharges = resolveDeliveryBadgeData[checkoutAddressDataLocal.value.deliverySpeed].price
emit('update:checkout-data', checkoutAddressDataLocal.value)
}
const nextStep = () => {
updateAddressData()
emit('update:currentStep', props.currentStep ? props.currentStep + 1 : 1)
}
watch(() => props.currentStep, updateAddressData)
</script>
<template>
<VRow>
<VCol
cols="12"
md="8"
>
<!-- 👉 Address options -->
<h6 class="text-h6 mb-4">
Select your preferable address
</h6>
<!-- 👉 Address custom input -->
<CustomRadios
v-model:selected-radio="checkoutAddressDataLocal.deliveryAddress"
:radio-content="checkoutAddressDataLocal.addresses"
:grid-column="{ cols: '12', sm: '6' }"
>
<template #default="{ item }">
<div class="w-100">
<div class="d-flex justify-space-between mb-3">
<h6 class="text-base font-weight-medium">
{{ item.title }}
</h6>
<VChip
:color="resolveAddressBadgeColor[item.value]"
label
size="small"
class="text-capitalize"
>
{{ item.value }}
</VChip>
</div>
<p class="mb-0 text-sm">
{{ item.desc }}
</p>
<p class="text-sm mb-3">
Mobile: {{ item.subtitle }}
</p>
<VDivider />
<div class="pt-2">
<a
href="#"
class="me-4"
>Edit</a>
<a href="#">Remove</a>
</div>
</div>
</template>
</CustomRadios>
<!-- 👉 Add New Address -->
<VBtn
variant="tonal"
class="mt-4 mb-6"
@click="isEditAddressDialogVisible = !isEditAddressDialogVisible"
>
Add New Address
</VBtn>
<!-- 👉 Delivery options -->
<h6 class="text-h6 mb-4">
Choose Delivery Speed
</h6>
<!-- 👉 Delivery options custom input -->
<CustomRadiosWithIcon
v-model:selected-radio="checkoutAddressDataLocal.deliverySpeed"
:radio-content="deliveryOptions"
:grid-column="{ cols: '12', sm: '4' }"
>
<template #default="{ item }">
<div class="d-flex flex-column align-center gap-2 w-100">
<div class="d-flex justify-end w-100 mb-n3">
<VChip
:color="resolveDeliveryBadgeData[item.value].color"
size="small"
label
>
{{ resolveDeliveryBadgeData[item.value].text }}
</VChip>
</div>
<VIcon
v-bind="item.icon"
size="28"
/>
<h6 class="text-h6">
{{ item.title }}
</h6>
<p class="text-sm text-center mb-0">
{{ item.desc }}
</p>
</div>
</template>
</CustomRadiosWithIcon>
</VCol>
<VCol
cols="12"
md="4"
>
<VCard
flat
variant="outlined"
>
<!-- 👉 Delivery estimate date -->
<VCardText>
<h6 class="text-h6 mb-4">
Estimated Delivery Date
</h6>
<VList class="card-list">
<VListItem
v-for="product in checkoutAddressDataLocal.cartItems"
:key="product.name"
>
<template #prepend>
<img
height="70"
width="60"
:src="product.image"
class="me-4"
>
</template>
<div class="text-body-1">
{{ product.name }}
</div>
<h6 class="text-h6 text-medium-emphasis">
{{ product.estimatedDelivery }}
</h6>
</VListItem>
</VList>
</VCardText>
<VDivider />
<!-- 👉 Price details -->
<VCardText>
<h6 class="text-h6 mb-4">
Price Details
</h6>
<div class="d-flex align-center justify-space-between mb-2">
<span class="text-high-emphasis">Order Total</span>
<span>${{ checkoutAddressDataLocal.orderAmount }}</span>
</div>
<div class="d-flex align-center justify-space-between">
<span class="text-high-emphasis">Delivery Charges</span>
<div class="text-end">
<div
v-if="checkoutAddressDataLocal.deliverySpeed === 'free'"
class="d-flex align-center"
>
<div class="text-decoration-line-through text-disabled me-2">
$5.00
</div>
<VChip
size="small"
color="success"
>
FREE
</VChip>
</div>
<span v-else>${{ resolveDeliveryBadgeData[checkoutAddressDataLocal.deliverySpeed ].price }}.00</span>
</div>
</div>
</VCardText>
<VDivider />
<VCardText class="d-flex align-center justify-space-between text-high-emphasis">
<span class="text-base font-weight-medium">Total</span>
<span class="text-base font-weight-medium">
${{ totalPriceWithDeliveryCharges }}
</span>
</VCardText>
</VCard>
<VBtn
block
class="mt-4"
@click="nextStep"
>
Place Order
</VBtn>
</VCol>
</VRow>
<AddEditAddressDialog v-model:is-dialog-visible="isEditAddressDialogVisible" />
</template>
<style lang="scss" scoped>
.card-list {
--v-card-list-gap: 1rem;
}
</style>