<script setup lang="ts"> import type { CheckoutData } from './types' interface Props { currentStep?: number checkoutData: CheckoutData } interface Emit { (e: 'update:currentStep', value: number): void (e: 'update:checkout-data', value: CheckoutData): void } const props = defineProps<Props>() const emit = defineEmits<Emit>() const checkoutAddressDataLocal = ref<CheckoutData>(JSON.parse(JSON.stringify(props.checkoutData))) const isEditAddressDialogVisible = ref(false) watch(() => props.checkoutData, value => { checkoutAddressDataLocal.value = JSON.parse(JSON.stringify(value)) }) const deliveryOptions = [ { icon: 'ri-user-line', title: 'Standard', desc: 'Get your product in 1 Week.', value: 'free', }, { icon: 'ri-star-smile-line', title: 'Express', desc: 'Get your product in 3-4 days.', value: 'express', }, { icon: 'ri-vip-crown-line', title: 'Overnight', desc: 'Get your product in 1 day.', value: 'overnight', }, ] const resolveAddressBadgeColor: any = { home: 'primary', office: 'success', } const resolveDeliveryBadgeData: any = { 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 --> <div class="text-body-1 text-high-emphasis font-weight-medium mb-4"> Select your preferable address </div> <!-- 👉 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-4"> <div class="text-body-1 text-high-emphasis"> {{ item.title }} </div> <VChip :color="resolveAddressBadgeColor[item.value]" size="small" class="text-capitalize" > {{ item.value }} </VChip> </div> <p class="text-body-2 mb-0"> {{ item.desc }} </p> <p class="text-body-2 mb-0"> Mobile: {{ item.subtitle }} </p> <p class="text-body-2 mb-3"> Cash/Card on delivery available </p> <VDivider class="pb-2" /> <div class="d-flex gap-x-4 py-2"> <a href="javascript:void(0)" class="text-base" >Edit</a> <a href="javascript:void(0)" class="text-base" >Remove</a> </div> </div> </template> </CustomRadios> <!-- 👉 Add New Address --> <VBtn variant="outlined" class="mt-4 mb-6" size="small" @click="isEditAddressDialogVisible = !isEditAddressDialogVisible" > Add New Address </VBtn> <!-- 👉 Delivery options --> <div class="text-body-1 text-high-emphasis font-weight-medium mb-4"> Choose Delivery Speed </div> <!-- 👉 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" > {{ resolveDeliveryBadgeData[item.value].text }} </VChip> </div> <VIcon size="28" :icon="item.icon" class="text-high-emphasis" /> <h6 class="text-h6"> {{ item.title }} </h6> <p class="text-body-2 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> <VImg width="54" height="70" :src="product.image" class="me-2" /> </template> <div class="text-body-1"> {{ product.name }} </div> <div class="text-body-1 font-weight-medium"> {{ product.estimatedDelivery }} </div> </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 text-sm mb-2"> <div class="text-high-emphasis text-body-1"> Order Total </div> <div class="text-body-1"> ${{ checkoutAddressDataLocal.orderAmount }} </div> </div> <div class="d-flex justify-space-between"> <div class="text-body-1 text-high-emphasis"> Delivery Charges </div> <div class="d-flex gap-x-2"> <div class="text-body-1 text-disabled"> $5.00 </div> <VChip size="small" color="success" > Free </VChip> </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:isDialogVisible="isEditAddressDialogVisible" /> </template> <style lang="scss" scoped> .card-list { --v-card-list-gap: 16px; } </style>