first commit

This commit is contained in:
Inshal
2024-05-29 22:34:28 +05:00
commit e63fc41a20
1470 changed files with 174828 additions and 0 deletions

View File

@@ -0,0 +1,197 @@
<script setup>
import rocketImg from '@images/eCommerce/rocket.png'
const props = defineProps({
customerData: {
type: null,
required: true,
},
})
const isUserInfoEditDialogVisible = ref(false)
const isUpgradePlanDialogVisible = ref(false)
</script>
<template>
<VRow>
<!-- SECTION Customer Details -->
<VCol cols="12">
<VCard v-if="props.customerData">
<VCardText class="text-center pt-15">
<!-- 👉 Avatar -->
<VAvatar
rounded
:size="120"
:color="!props.customerData.customer ? 'primary' : undefined"
:variant="!props.customerData.avatar ? 'tonal' : undefined"
>
<VImg
v-if="props.customerData.avatar"
:src="props.customerData.avatar"
/>
<span
v-else
class="text-5xl font-weight-medium"
>
User Not Availaable
</span>
</VAvatar>
<!-- 👉 Customer fullName -->
<h6 class="text-h5 mt-4">
{{ props.customerData.customer }}
</h6>
<p class="text-body-1 mb-0">
Customer ID #{{ props.customerData.customerId }}
</p>
<div class="d-flex justify-space-evenly gap-x-12 mt-6">
<div class="d-flex align-center">
<VAvatar
variant="tonal"
color="primary"
rounded
class="me-4"
>
<VIcon icon="ri-shopping-cart-line" />
</VAvatar>
<div class="d-flex flex-column align-start">
<h5 class="text-h5">
{{ props.customerData.order }}
</h5>
<span class="text-body-1">Orders</span>
</div>
</div>
<div class="d-flex align-center">
<VAvatar
variant="tonal"
color="primary"
rounded
class="me-4"
>
<VIcon icon="ri-money-dollar-circle-line" />
</VAvatar>
<div class="d-flex flex-column align-start">
<h5 class="text-h5">
{{ Math.round(props.customerData.totalSpent) }}
</h5>
<span class="text-body-1">Spent</span>
</div>
</div>
</div>
</VCardText>
<!-- 👉 Customer Details -->
<VCardText>
<h5 class="text-h5">
Details
</h5>
<VDivider class="my-4" />
<VList class="card-list mt-2">
<VListItem>
<VListItemTitle>
<span class="font-weight-medium me-2">Username:</span>
<span class="text-body-1">
{{ props.customerData.customer }}
</span>
</VListItemTitle>
</VListItem>
<VListItem>
<VListItemTitle>
<span class="font-weight-medium me-2">Billing Email:</span>
<span class="text-body-1">
{{ props.customerData.email }}
</span>
</VListItemTitle>
</VListItem>
<VListItem>
<VListItemTitle>
<span class="font-weight-medium me-2">Status:</span>
<span class="text-body-1">
{{ props.customerData.status }}
</span>
</VListItemTitle>
</VListItem>
<VListItem>
<VListItemTitle>
<span class="font-weight-medium me-2">Contact:</span>
<span class="text-body-1">
{{ props.customerData.contact }}
</span>
</VListItemTitle>
</VListItem>
<VListItem>
<VListItemTitle>
<span class="font-weight-medium me-2">Country:</span>
<span class="text-body-1">
{{ props.customerData.country }}
</span>
</VListItemTitle>
</VListItem>
</VList>
<div class="mt-6 text-center">
<VBtn
block
@click="isUserInfoEditDialogVisible = !isUserInfoEditDialogVisible"
>
Edit Details
</VBtn>
</div>
</VCardText>
</VCard>
</VCol>
<!-- !SECTION -->
<!-- SECTION Upgrade to Premium -->
<VCol cols="12">
<VCard
flat
class="current-plan"
color="primary"
>
<VCardText>
<div class="d-flex align-center">
<div>
<h5 class="text-h5 text-white mb-4">
Upgrade to premium
</h5>
<p class="mb-6 text-wrap">
Upgrade customer to premium membership to access pro features.
</p>
</div>
<div>
<VImg
:src="rocketImg"
height="108"
width="108"
/>
</div>
</div>
<VBtn
color="#fff"
class="text-primary"
block
@click="isUpgradePlanDialogVisible = !isUpgradePlanDialogVisible"
>
Upgrade to Premium
</VBtn>
</VCardText>
</VCard>
</VCol>
<!-- !SECTION -->
</VRow>
<UserInfoEditDialog v-model:isDialogVisible="isUserInfoEditDialogVisible" />
<UserUpgradePlanDialog v-model:isDialogVisible="isUpgradePlanDialogVisible" />
</template>
<style lang="scss" scoped>
.card-list {
--v-card-list-gap: 0.5rem;
}
</style>

View File

@@ -0,0 +1,194 @@
<script setup>
const searchQuery = ref('')
// Data table options
const itemsPerPage = ref(10)
const page = ref(1)
const sortBy = ref()
const orderBy = ref()
const updateOptions = options => {
page.value = options.page
sortBy.value = options.sortBy[0]?.key
orderBy.value = options.sortBy[0]?.order
}
const headers = [
{
title: 'Order',
key: 'order',
},
{
title: 'Date',
key: 'date',
},
{
title: 'Status',
key: 'status',
},
{
title: 'Spent',
key: 'spent',
},
{
title: 'Actions',
key: 'actions',
sortable: false,
},
]
const resolveStatus = status => {
if (status === 'Delivered')
return { color: 'success' }
if (status === 'Out for Delivery')
return { color: 'primary' }
if (status === 'Ready to Pickup')
return { color: 'info' }
if (status === 'Dispatched')
return { color: 'warning' }
}
const {
data: ordersData,
execute: fetchOrders,
} = await useApi(createUrl('/apps/ecommerce/orders', {
query: {
q: searchQuery,
page,
itemsPerPage,
sortBy,
orderBy,
},
}))
const orders = computed(() => ordersData.value?.orders || [])
const totalOrder = computed(() => ordersData.value?.total || 0)
const deleteOrder = async id => {
await $api(`/apps/ecommerce/orders/${ id }`, { method: 'DELETE' })
fetchOrders()
}
</script>
<template>
<VCard>
<VCardText>
<div class="d-flex align-center justify-sm-space-between justify-start flex-wrap gap-4">
<div class="text-h5">
Orders placed
</div>
<VTextField
v-model="searchQuery"
placeholder="Search Order"
density="compact"
style=" max-inline-size: 250px; min-inline-size: 200px;"
/>
</div>
</VCardText>
<VDataTableServer
v-model:items-per-page="itemsPerPage"
v-model:page="page"
:headers="headers"
:items="orders"
item-value="id"
:items-length="totalOrder"
class="text-no-wrap rounded-0"
@update:options="updateOptions"
>
<!-- Order ID -->
<template #item.order="{ item }">
<RouterLink :to="{ name: 'apps-ecommerce-order-details-id', params: { id: item.order } }">
#{{ item.order }}
</RouterLink>
</template>
<!-- Date -->
<template #item.date="{ item }">
{{ new Date(item.date).toDateString() }}
</template>
<!-- Status -->
<template #item.status="{ item }">
<VChip
size="small"
:color="resolveStatus(item.status)?.color"
>
{{ item.status }}
</VChip>
</template>
<!-- Spent -->
<template #item.spent="{ item }">
${{ item.spent }}
</template>
<!-- Actions -->
<template #item.actions="{ item }">
<IconBtn size="small">
<VIcon icon="ri-more-2-fill" />
<VMenu activator="parent">
<VList>
<VListItem value="view">
<RouterLink
:to="{ name: 'apps-ecommerce-order-details-id', params: { id: item.order } }"
class="text-high-emphasis"
>
View
</RouterLink>
</VListItem>
<VListItem
value="delete"
@click="deleteOrder(item.id)"
>
Delete
</VListItem>
</VList>
</VMenu>
</IconBtn>
</template>
<!-- Pagination -->
<template #bottom>
<VDivider />
<div class="d-flex justify-end flex-wrap gap-x-6 px-2 py-1">
<div class="d-flex align-center gap-x-2 text-medium-emphasis text-base">
Rows Per Page:
<VSelect
v-model="itemsPerPage"
class="per-page-select"
variant="plain"
:items="[10, 20, 25, 50, 100]"
/>
</div>
<p class="d-flex align-center text-base text-high-emphasis me-2 mb-0">
{{ paginationMeta({ page, itemsPerPage }, totalOrder) }}
</p>
<div class="d-flex gap-x-2 align-center me-2">
<VBtn
class="flip-in-rtl"
icon="ri-arrow-left-s-line"
variant="text"
density="comfortable"
color="high-emphasis"
:disabled="page <= 1"
@click="page <= 1 ? page = 1 : page--"
/>
<VBtn
class="flip-in-rtl"
icon="ri-arrow-right-s-line"
density="comfortable"
variant="text"
color="high-emphasis"
:disabled="page >= Math.ceil(totalOrder / itemsPerPage)"
@click="page >= Math.ceil(totalOrder / itemsPerPage) ? page = Math.ceil(totalOrder / itemsPerPage) : page++ "
/>
</div>
</div>
</template>
</VDataTableServer>
</VCard>
</template>

View File

@@ -0,0 +1,427 @@
<script setup>
import usFlag from '@images/icons/countries/us.png'
import americanExpress from '@images/icons/payments/img/american-express.png'
import mastercard from '@images/icons/payments/img/mastercard.png'
import visa from '@images/icons/payments/img/visa-light.png'
const show = ref([
true,
false,
false,
])
const paymentShow = ref([
true,
false,
false,
])
const isEditAddressDialogVisible = ref(false)
const isCardAddDialogVisible = ref(false)
const isNewEditAddressDialogVisible = ref(false)
const isNewCardAddDialogVisible = ref(false)
const currentCardDetails = {
number: '1234 5678 9012 3456',
name: 'John Doe',
expiry: '12/2028',
cvv: '123',
isPrimary: false,
type: '',
}
const editBillingData = {
firstName: 'Gertrude',
lastName: 'Jennings',
selectedCountry: 'USA',
addressLine1: '100 Water Plant Avenue',
addressLine2: 'Building 1303 Wake Island',
landmark: 'Near Wake Island',
contact: '+1(609) 933-44-22',
country: 'USA',
state: 'Queensland',
zipCode: 403114,
}
const addressData = [
{
title: 'Home',
subtitle: '23 Shatinon Mekalan',
owner: 'Violet Mendoza',
defaultAddress: true,
address: ` 23 Shatinon Mekalan,
<br>
Melbourne, VIC 3000,
<br>
LondonUK`,
},
{
title: 'Office',
subtitle: '45 Rocker Terrace',
owner: 'Violet Mendoza',
defaultAddress: false,
address: ` 45 Rocker Terrace,
<br>
Latheronwheel,
<br>
KW5 8NW, London,
<br>
UK`,
},
{
title: 'Family',
subtitle: '512 Water Plant',
owner: 'Violet Mendoza',
defaultAddress: false,
address: ` 512 Water Plant,
<br>
Melbourne, VIC 3000,
<br>
LondonUK`,
},
]
const paymentData = [
{
title: 'Mastercard',
subtitle: 'Expries Apr 2028',
isDefaultMethod: false,
image: mastercard,
},
{
title: 'American Express',
subtitle: 'Expries Apr 2028',
isDefaultMethod: false,
image: americanExpress,
},
{
title: 'Visa',
subtitle: '45 Roker Terrace',
isDefaultMethod: true,
image: visa,
},
]
</script>
<template>
<!-- eslint-disable vue/no-v-html -->
<!-- 👉 Address Book -->
<VCard class="mb-6">
<VCardText>
<div class="d-flex justify-space-between mb-5 flex-wrap align-center gap-y-4 gap-x-6">
<h5 class="text-h5">
Address Book
</h5>
<VBtn
variant="outlined"
size="small"
@click="isNewEditAddressDialogVisible = !isNewEditAddressDialogVisible"
>
Add new Address
</VBtn>
</div>
<template
v-for="(address, index) in addressData"
:key="index"
>
<div class="d-flex justify-space-between mb-3 gap-y-2 flex-wrap align-center">
<div class="d-flex align-center gap-x-2">
<IconBtn
density="comfortable"
@click="show[index] = !show[index]"
>
<VIcon
:icon="show[index] ? 'ri-arrow-down-s-line' : 'ri-arrow-right-s-line'"
class="flip-in-rtl text-high-emphasis"
/>
</IconBtn>
<div>
<div class="d-flex align-center mb-1">
<h6 class="text-h6 me-2">
{{ address.title }}
</h6>
<VChip
v-if="address.defaultAddress"
color="success"
size="small"
>
Default Address
</VChip>
</div>
<span class="text-body-1">{{ address.subtitle }}</span>
</div>
</div>
<div class="ms-11">
<IconBtn @click="isEditAddressDialogVisible = true">
<VIcon
icon="ri-edit-box-line"
class="flip-in-rtl"
/>
</IconBtn>
<IconBtn>
<VIcon
icon="ri-delete-bin-7-line"
class="flip-in-rtl"
/>
</IconBtn>
<IconBtn>
<VIcon
icon="ri-more-2-fill"
class="flip-in-rtl"
/>
</IconBtn>
</div>
</div>
<VExpandTransition>
<div
v-show="show[index]"
class="ps-12"
>
<div class="mb-1 font-weight-medium text-high-emphasis">
{{ address.owner }}
</div>
<div v-html="address.address" />
</div>
</VExpandTransition>
<VDivider
v-if="index !== addressData.length - 1"
class="my-3"
/>
</template>
</VCardText>
</VCard>
<!-- 👉 Payment Methods -->
<VCard>
<VCardText>
<div class="d-flex justify-space-between mb-5 flex-wrap align-center gap-y-4 gap-x-6">
<h5 class="text-h5">
Payment Methods
</h5>
<VBtn
variant="outlined"
size="small"
@click="isNewCardAddDialogVisible = !isNewCardAddDialogVisible"
>
Add Payment Methods
</VBtn>
</div>
<template
v-for="(payment, index) in paymentData"
:key="index"
>
<div class="d-flex justify-space-between mb-4 gap-y-2 flex-wrap align-center">
<div class="d-flex align-center gap-2">
<IconBtn
density="comfortable"
@click="paymentShow[index] = !paymentShow[index]"
>
<VIcon
:icon="paymentShow[index] ? 'ri-arrow-down-s-line' : 'ri-arrow-right-s-line'"
class="flip-in-rtl text-high-emphasis"
/>
</IconBtn>
<VImg
:src="payment.image"
height="30"
width="50"
class="me-4"
/>
<div>
<div class="d-flex flex-wrap mb-1">
<h6 class="text-h6 me-2">
{{ payment.title }}
</h6>
<VChip
v-if="payment.isDefaultMethod"
color="success"
density="comfortable"
>
Default Method
</VChip>
</div>
<span class="text-body-1">{{ payment.subtitle }}</span>
</div>
</div>
<div class="ms-11">
<IconBtn @click="isCardAddDialogVisible = true">
<VIcon
icon="ri-edit-box-line"
class="flip-in-rtl"
/>
</IconBtn>
<IconBtn>
<VIcon
icon="ri-delete-bin-7-line"
class="flip-in-rtl"
/>
</IconBtn>
<IconBtn>
<VIcon
icon="ri-more-2-fill"
class="flip-in-rtl"
/>
</IconBtn>
</div>
</div>
<VExpandTransition>
<div
v-show="paymentShow[index]"
class="ps-12"
>
<VRow>
<VCol
cols="12"
md="6"
>
<VTable>
<tr>
<td
class="text-sm pb-1"
style="inline-size: 100px;"
>
Name
</td>
<td class="text-sm text-high-emphasis font-weight-medium">
Violet Mendoza
</td>
</tr>
<tr>
<td class="text-sm pb-1">
Number
</td>
<td class="text-sm text-high-emphasis font-weight-medium">
**** 4487
</td>
</tr>
<tr>
<td class="text-sm pb-1">
Expires
</td>
<td class="text-sm text-high-emphasis font-weight-medium">
08/2028
</td>
</tr>
<tr>
<td class="text-sm pb-1">
Type
</td>
<td class="text-sm text-high-emphasis font-weight-medium">
Master Card
</td>
</tr>
<tr>
<td class="text-sm pb-1">
Issuer
</td>
<td class="text-sm text-high-emphasis font-weight-medium">
VICBANK
</td>
</tr>
<tr>
<td class="text-sm pb-1">
ID
</td>
<td class="text-sm text-high-emphasis font-weight-medium">
DH73DJ8
</td>
</tr>
</VTable>
</VCol>
<VCol
cols="12"
md="6"
>
<VTable>
<tr>
<td
class="text-sm pb-1"
style="inline-size: 100px;"
>
Billing
</td>
<td class="text-sm text-high-emphasis font-weight-medium">
United Kingdom
</td>
</tr>
<tr>
<td class="text-sm pb-1">
Number
</td>
<td class="text-sm text-high-emphasis font-weight-medium">
+7634 983 637
</td>
</tr>
<tr>
<td class="text-sm pb-1">
Email
</td>
<td class="text-sm text-high-emphasis font-weight-medium">
vafgot@vultukir.org
</td>
</tr>
<tr>
<td class="text-sm pb-1">
Origin
</td>
<td class="d-flex">
<div class="text-body-2 font-weight-medium text-high-emphasis me-2">
United States
</div>
<img
:src="usFlag"
height="20"
width="20"
>
</td>
</tr>
<tr>
<td class="text-sm pb-1">
CVC
</td>
<td class="d-flex">
<div class="text-body-2 font-weight-medium text-high-emphasis me-2">
Passed
</div>
<VAvatar
variant="tonal"
color="success"
size="20"
inline
>
<VIcon
icon="ri-check-line"
color="success"
size="12"
/>
</VAvatar>
</td>
</tr>
</VTable>
</VCol>
</VRow>
</div>
</VExpandTransition>
<VDivider
v-if="index !== paymentData.length - 1"
class="my-4"
/>
</template>
</VCardText>
</VCard>
<AddEditAddressDialog
v-model:isDialogVisible="isEditAddressDialogVisible"
:billing-address="editBillingData"
/>
<AddEditAddressDialog v-model:isDialogVisible="isNewEditAddressDialogVisible" />
<CardAddEditDialog
v-model:isDialogVisible="isCardAddDialogVisible"
:card-details="currentCardDetails"
/>
<CardAddEditDialog v-model:isDialogVisible="isNewCardAddDialogVisible" />
</template>

View File

@@ -0,0 +1,89 @@
<script setup>
const notifications = ref([
{
type: 'New for you',
email: true,
browser: false,
app: false,
},
{
type: 'Account activity',
email: false,
browser: true,
app: true,
},
{
type: 'A new browser used to sign in',
email: true,
browser: true,
app: true,
},
{
type: 'A new device is linked',
email: false,
browser: true,
app: false,
},
])
</script>
<template>
<VCard title="Notifications">
<VDivider />
<VCardText>
<h6 class="text-h6">
You will receive notification for the below selected items.
</h6>
</VCardText>
<VTable class="text-no-wrap rounded-0">
<thead>
<tr>
<th scope="col">
TYPE
</th>
<th scope="col">
EMAIL
</th>
<th scope="col">
BROWSER
</th>
<th scope="col">
APP
</th>
</tr>
</thead>
<tbody>
<tr
v-for="notification in notifications"
:key="notification.type"
>
<td class="text-high-emphasis">
{{ notification.type }}
</td>
<td>
<VCheckbox v-model="notification.email" />
</td>
<td>
<VCheckbox v-model="notification.browser" />
</td>
<td>
<VCheckbox v-model="notification.app" />
</td>
</tr>
</tbody>
</VTable>
<VDivider />
<VCardText class="d-flex flex-wrap gap-4">
<VBtn>Save changes</VBtn>
<VBtn
color="secondary"
variant="outlined"
>
Discard
</VBtn>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,127 @@
<script setup>
import CustomerOrderTable from './CustomerOrderTable.vue'
</script>
<template>
<VRow class="match-height">
<VCol
cols="12"
md="6"
>
<VCard>
<VCardText class="d-flex gap-y-2 flex-column">
<VAvatar
variant="tonal"
color="primary"
icon="ri-money-dollar-circle-line"
rounded
/>
<h6 class="text-lg font-weight-medium">
Account Balance
</h6>
<div class="text-base">
<p class="mb-0">
<span class="text-primary font-weight-medium text-lg me-1">$7480</span>
Credit Left
</p>
<p class="mb-0 text-base">
Account balance for next purchase
</p>
</div>
</VCardText>
</VCard>
</VCol>
<VCol
cols="12"
md="6"
>
<VCard>
<VCardText class="d-flex gap-y-2 flex-column">
<VAvatar
variant="tonal"
color="success"
icon="ri-gift-line"
rounded
/>
<h6 class="text-lg font-weight-medium">
Loyalty Program
</h6>
<div>
<VChip
color="success"
size="small"
class="mb-2"
>
Platinum Member
</VChip>
<p class="mb-0 text-base">
3000 points to next tier
</p>
</div>
</VCardText>
</VCard>
</VCol>
<VCol
cols="12"
md="6"
>
<VCard>
<VCardText class="d-flex gap-y-2 flex-column">
<VAvatar
variant="tonal"
color="warning"
icon="ri-star-smile-line"
rounded
/>
<h6 class="text-lg font-weight-medium">
Wishlist
</h6>
<div>
<p class=" mb-0">
<span class="text-warning font-weight-medium text-lg me-1">15</span>
items in wishlist
</p>
<p class="mb-0 text-base">
Receive notification when items go on sale
</p>
</div>
</VCardText>
</VCard>
</VCol>
<VCol
cols="12"
md="6"
>
<VCard>
<VCardText class="d-flex gap-y-2 flex-column">
<VAvatar
variant="tonal"
color="info"
icon="ri-vip-crown-line"
rounded
/>
<h6 class="text-lg font-weight-medium">
Coupons
</h6>
<div>
<p class="mb-0">
<span class="text-info text-lg me-2">21</span>
Coupons you win
</p>
<p class="mb-0 text-base">
Use coupon on next purchase
</p>
</div>
</VCardText>
</VCard>
</VCol>
<VCol>
<CustomerOrderTable />
</VCol>
</VRow>
</template>

View File

@@ -0,0 +1,201 @@
<script setup>
import chrome from '@images/logos/chrome.png'
const isNewPasswordVisible = ref(false)
const isConfirmPasswordVisible = ref(false)
const smsVerificationNumber = ref('+1(968) 819-2547')
const isTwoFactorDialogOpen = ref(false)
const recentDeviceHeader = [
{
title: 'BROWSER',
key: 'browser',
},
{
title: 'DEVICE',
key: 'device',
},
{
title: 'LOCATION',
key: 'location',
},
{
title: 'RECENT ACTIVITY',
key: 'activity',
},
]
const recentDevices = [
{
browser: 'Chrome on Windows',
logo: chrome,
device: 'Dell XPS 15',
location: 'United States',
activity: '10, Jan 2020 20:07',
},
{
browser: 'Chrome on Android',
logo: chrome,
device: 'Google Pixel 3a',
location: 'Ghana',
activity: '11, Jan 2020 10:16',
},
{
browser: 'Chrome on macOS',
logo: chrome,
device: 'Apple iMac',
location: 'Mayotte',
activity: '11, Jan 2020 12:10',
},
{
browser: 'Chrome on iPhone',
logo: chrome,
device: 'Apple iPhone XR',
location: 'Mauritania',
activity: '12, Jan 2020 8:29',
},
]
</script>
<template>
<VRow>
<VCol cols="12">
<!-- 👉 Change password -->
<VCard title="Change Password">
<VCardText>
<VAlert
variant="tonal"
color="warning"
closable
class="mb-4"
>
<VAlertTitle>Ensure that these requirements are met</VAlertTitle>
<span>Minimum 8 characters long, uppercase & symbol</span>
</VAlert>
<VForm @submit.prevent="() => {}">
<VRow>
<VCol
cols="12"
md="6"
>
<VTextField
label="New Password"
placeholder="············"
:type="isNewPasswordVisible ? 'text' : 'password'"
:append-inner-icon="isNewPasswordVisible ? 'ri-eye-off-line' : 'ri-eye-line'"
@click:append-inner="isNewPasswordVisible = !isNewPasswordVisible"
/>
</VCol>
<VCol
cols="12"
md="6"
>
<VTextField
label="Confirm Password"
placeholder="············"
:type="isConfirmPasswordVisible ? 'text' : 'password'"
:append-inner-icon="isConfirmPasswordVisible ? 'ri-eye-off-line' : 'ri-eye-line'"
@click:append-inner="isConfirmPasswordVisible = !isConfirmPasswordVisible"
/>
</VCol>
<VCol cols="12">
<VBtn type="submit">
Change Password
</VBtn>
</VCol>
</VRow>
</VForm>
</VCardText>
</VCard>
</VCol>
<VCol cols="12">
<!-- 👉 Two step verification -->
<VCard
title="Two-step verification"
subtitle="Keep your account secure with authentication step."
>
<VCardText>
<div>
<h4 class="font-weight-medium mb-1">
SMS
</h4>
<VTextField
density="compact"
variant="outlined"
:model-value="smsVerificationNumber"
readonly
>
<template #append>
<VBtn
icon
rounded
variant="outlined"
color="secondary"
class="me-2"
>
<VIcon
icon="ri-edit-box-line"
size="24"
@click="isTwoFactorDialogOpen = true"
/>
</VBtn>
<VBtn
icon
rounded
variant="outlined"
color="secondary"
>
<VIcon
size="24"
icon="ri-user-add-line"
/>
</VBtn>
</template>
</VTextField>
</div>
<p class="mb-0 mt-4">
Two-factor authentication adds an additional layer of security to your account by requiring more than just a password to log in. <a
href="javascript:void(0)"
class="text-decoration-none"
>Learn more</a>.
</p>
</VCardText>
</VCard>
</VCol>
<VCol cols="12">
<!-- 👉 Recent devices -->
<VCard title="Recent devices">
<VDataTable
:items="recentDevices"
:headers="recentDeviceHeader"
hide-default-footer
class="text-no-wrap rounded-0"
>
<template #item.browser="{ item }">
<div class="d-flex text-high-emphasis">
<VAvatar
:image="item.logo"
:size="22"
class="me-4"
/>
{{ item.browser }}
</div>
</template>
<!-- TODO Refactor this after vuetify provides proper solution for removing default footer -->
<template #bottom />
</VDataTable>
</VCard>
</VCol>
</VRow>
<!-- 👉 Enable One Time Password Dialog -->
<TwoFactorAuthDialog
v-model:isDialogVisible="isTwoFactorDialogOpen"
:sms-code="smsVerificationNumber"
/>
</template>