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,235 @@
<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)
const customerData = {
id: props.customerData.id,
fullName: props.customerData.customer,
firstName: props.customerData.customer.split(' ')[0],
lastName: props.customerData.customer.split(' ')[1],
company: '',
role: '',
username: props.customerData.customer,
country: props.customerData.country,
contact: props.customerData.contact,
email: props.customerData.email,
currentPlan: '',
status: props.customerData.status,
avatar: '',
taskDone: null,
projectDone: null,
taxId: 'Tax-8894',
language: 'English',
}
</script>
<template>
<VRow>
<!-- SECTION Customer Details -->
<VCol cols="12">
<VCard v-if="props.customerData">
<VCardText class="text-center pt-12">
<!-- 👉 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"
>
{{ avatarText(props.customerData.customer) }}
</span>
</VAvatar>
<!-- 👉 Customer fullName -->
<h5 class="text-h5 mt-4">
{{ props.customerData.customer }}
</h5>
<div class="text-body-1">
Customer ID #{{ props.customerData.customerId }}
</div>
<div class="d-flex justify-space-evenly gap-x-5 mt-6">
<div class="d-flex align-center">
<VAvatar
variant="tonal"
color="primary"
rounded
class="me-4"
>
<VIcon icon="tabler-shopping-cart" />
</VAvatar>
<div class="d-flex flex-column align-start">
<h5 class="text-h5">
{{ props.customerData.order }}
</h5>
<div class="text-body-1">
Order
</div>
</div>
</div>
<div class="d-flex align-center">
<VAvatar
variant="tonal"
color="primary"
rounded
class="me-3"
>
<VIcon icon="tabler-currency-dollar" />
</VAvatar>
<div class="d-flex flex-column align-start">
<h5 class="text-h5">
${{ props.customerData.totalSpent }}
</h5>
<div class="text-body-1">
Spent
</div>
</div>
</div>
</div>
</VCardText>
<!-- 👉 Customer Details -->
<VCardText>
<h5 class="text-h5">
Details
</h5>
<VDivider class="my-4" />
<VList class="card-list mt-2">
<VListItem>
<h6 class="text-h6">
Username:
<span class="text-body-1 d-inline-block">
{{ props.customerData.customer }}
</span>
</h6>
</VListItem>
<VListItem>
<h6 class="text-h6">
Billing Email:
<span class="text-body-1 d-inline-block">
{{ props.customerData.email }}
</span>
</h6>
</VListItem>
<VListItem>
<div class="d-flex gap-x-2 align-center">
<h6 class="text-h6">
Status:
</h6>
<VChip
label
color="success"
size="small"
>
{{ props.customerData.status }}
</VChip>
</div>
</VListItem>
<VListItem>
<h6 class="text-h6">
Contact:
<span class="text-body-1 d-inline-block">
{{ props.customerData.contact }}
</span>
</h6>
</VListItem>
<VListItem>
<h6 class="text-h6">
Country:
<span class="text-body-1 d-inline-block">
{{ props.customerData.country }}
</span>
</h6>
</VListItem>
</VList>
</VCardText>
<VCardText class="text-center">
<VBtn
block
@click="isUserInfoEditDialogVisible = !isUserInfoEditDialogVisible"
>
Edit Details
</VBtn>
</VCardText>
</VCard>
</VCol>
<!-- !SECTION -->
<!-- SECTION Upgrade to Premium -->
<VCol cols="12">
<VCard
flat
class="current-plan"
>
<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:is-dialog-visible="isUserInfoEditDialogVisible"
:user-data="customerData"
/>
<UserUpgradePlanDialog v-model:is-dialog-visible="isUpgradePlanDialogVisible" />
</template>
<style lang="scss" scoped>
.card-list {
--v-card-list-gap: 0.5rem;
}
.current-plan {
background: linear-gradient(45deg, rgb(var(--v-theme-primary)) 0%, #9e95f5 100%);
color: #fff;
}
</style>

View File

@@ -0,0 +1,161 @@
<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 => {
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 justify-space-between flex-wrap align-center gap-4">
<h5 class="text-h5">
Orders placed
</h5>
<div>
<AppTextField
v-model="searchQuery"
placeholder="Search Order"
style=" max-inline-size: 200px; min-inline-size: 200px;"
/>
</div>
</div>
</VCardText>
<VDivider />
<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"
@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
label
:color="resolveStatus(item.status)?.color"
size="small"
>
{{ item.status }}
</VChip>
</template>
<!-- Spent -->
<template #item.spent="{ item }">
${{ item.spent }}
</template>
<!-- Actions -->
<template #item.actions="{ item }">
<IconBtn>
<VIcon icon="tabler-dots-vertical" />
<VMenu activator="parent">
<VList>
<VListItem
value="view"
:to="{ name: 'apps-ecommerce-order-details-id', params: { id: item.order } }"
>
View
</VListItem>
<VListItem
value="delete"
@click="deleteOrder(item.id)"
>
Delete
</VListItem>
</VList>
</VMenu>
</IconBtn>
</template>
<!-- pagination -->
<template #bottom>
<TablePagination
v-model:page="page"
:items-per-page="itemsPerPage"
:total-items="totalOrder"
/>
</template>
</VDataTableServer>
</VCard>
</template>

View File

@@ -0,0 +1,396 @@
<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 currentCardDetails = {
number: '1234567890123456',
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,
city: 'Brisbane',
}
const show = ref([
false,
true,
false,
])
const paymentShow = ref([
false,
true,
false,
])
const isEditAddressDialogVisible = ref(false)
const isCardAddDialogVisible = ref(false)
const isNewEditAddressDialogVisible = ref(false)
const isNewCardAddDialogVisible = ref(false)
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: 'Expires Apr 2028',
isDefaultMethod: false,
image: mastercard,
},
{
title: 'American Express',
subtitle: 'Expires 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-6 flex-wrap align-center gap-y-4 gap-x-6">
<h5 class="text-h5">
Address Book
</h5>
<VBtn
variant="tonal"
size="small"
@click="isNewEditAddressDialogVisible = !isNewEditAddressDialogVisible"
>
Add new Address
</VBtn>
</div>
<template
v-for="(address, index) in addressData"
:key="index"
>
<div>
<div class="d-flex justify-space-between py-3 gap-y-2 flex-wrap align-center">
<div class="d-flex align-center gap-x-4">
<VIcon
:icon="show[index] ? 'tabler-chevron-down' : 'tabler-chevron-right'"
class="flip-in-rtl text-high-emphasis"
size="24"
@click="show[index] = !show[index]"
/>
<div>
<div class="d-flex align-center gap-x-2 mb-1">
<h6 class="text-h6">
{{ address.title }}
</h6>
<VChip
v-if="address.defaultAddress"
color="success"
label
size="small"
>
Default Address
</VChip>
</div>
<div class="text-body-1">
{{ address.subtitle }}
</div>
</div>
</div>
<div class="ms-5">
<IconBtn @click="isEditAddressDialogVisible = !isEditAddressDialogVisible">
<VIcon
icon="tabler-edit"
class="flip-in-rtl"
/>
</IconBtn>
<IconBtn>
<VIcon
icon="tabler-trash"
class="flip-in-rtl"
/>
</IconBtn>
<IconBtn>
<VIcon
icon="tabler-dots-vertical"
class="flip-in-rtl"
/>
</IconBtn>
</div>
</div>
<VExpandTransition>
<div v-show="show[index]">
<div class="px-10 pb-3">
<h6 class="mb-1 text-h6">
{{ address.owner }}
</h6>
<div
class="text-body-1"
v-html="address.address"
/>
</div>
</div>
</VExpandTransition>
<VDivider v-if="index !== addressData.length - 1" />
</div>
</template>
</VCardText>
</VCard>
<!-- 👉 Payment Methods -->
<VCard>
<VCardText>
<div class="d-flex justify-space-between mb-6 flex-wrap align-center gap-y-4 gap-x-6">
<h5 class="text-h5">
Payment Methods
</h5>
<VBtn
variant="tonal"
size="small"
@click="isNewCardAddDialogVisible = !isNewCardAddDialogVisible"
>
Add Payment Methods
</VBtn>
</div>
<template
v-for="(payment, index) in paymentData"
:key="index"
>
<div>
<div class="d-flex justify-space-between py-3 gap-y-2 flex-wrap align-center">
<div class="d-flex align-center gap-x-4">
<VIcon
:icon="paymentShow[index] ? 'tabler-chevron-down' : 'tabler-chevron-right'"
size="24"
class="flip-in-rtl text-high-emphasis"
@click="paymentShow[index] = !paymentShow[index]"
/>
<VImg
:src="payment.image"
height="30"
width="50"
/>
<div>
<div class="d-flex gap-x-2 mb-1">
<h6 class="text-h6">
{{ payment.title }}
</h6>
<VChip
v-if="payment.isDefaultMethod"
color="success"
label
size="small"
>
Default Method
</VChip>
</div>
<div class="text-body-1">
{{ payment.subtitle }}
</div>
</div>
</div>
<div class="ms-5">
<IconBtn @click="isCardAddDialogVisible = !isCardAddDialogVisible">
<VIcon
icon="tabler-edit"
class="flip-in-rtl"
/>
</IconBtn>
<IconBtn>
<VIcon
icon="tabler-trash"
class="flip-in-rtl"
/>
</IconBtn>
<IconBtn>
<VIcon
icon="tabler-dots-vertical"
class="flip-in-rtl"
/>
</IconBtn>
</div>
</div>
<VExpandTransition>
<div v-show="paymentShow[index]">
<div class="px-10 pb-3">
<VRow>
<VCol
cols="12"
md="6"
>
<VTable>
<tr>
<td>Name </td>
<td class="font-weight-medium text-high-emphasis">
Violet Mendoza
</td>
</tr>
<tr>
<td>Number </td>
<td class="font-weight-medium text-high-emphasis">
**** 4487
</td>
</tr>
<tr>
<td>Expires </td>
<td class="font-weight-medium text-high-emphasis">
08/2028
</td>
</tr>
<tr>
<td>Type </td>
<td class="font-weight-medium text-high-emphasis">
Master Card
</td>
</tr>
<tr>
<td>Issuer </td>
<td class="font-weight-medium text-high-emphasis">
VICBANK
</td>
</tr>
<tr>
<td>ID </td>
<td class="font-weight-medium text-high-emphasis">
DH73DJ8
</td>
</tr>
</VTable>
</VCol>
<VCol
cols="12"
md="6"
>
<VTable>
<tr>
<td>Billing </td>
<td class="font-weight-medium text-high-emphasis">
United Kingdom
</td>
</tr>
<tr>
<td>Number</td>
<td class="font-weight-medium text-high-emphasis">
+7634 983 637
</td>
</tr>
<tr>
<td>Email</td>
<td class="font-weight-medium text-high-emphasis">
vafgot@vultukir.org
</td>
</tr>
<tr>
<td>Origin</td>
<td class="d-flex">
<div class="me-2 font-weight-medium text-high-emphasis">
United States
</div>
<img
:src="usFlag"
height="20"
width="20"
>
</td>
</tr>
<tr>
<td>CVC Check</td>
<td class="d-flex">
<div class="me-2 font-weight-medium text-high-emphasis">
Passed
</div>
<VAvatar
variant="tonal"
color="success"
size="20"
inline
>
<VIcon
icon="tabler-check"
color="success"
size="12"
/>
</VAvatar>
</td>
</tr>
</VTable>
</VCol>
</VRow>
</div>
</div>
</VExpandTransition>
<VDivider v-if="index !== paymentData.length - 1" />
</div>
</template>
</VCardText>
</VCard>
<AddEditAddressDialog
v-model:is-dialog-visible="isEditAddressDialogVisible"
:billing-address="editBillingData"
/>
<AddEditAddressDialog v-model:is-dialog-visible="isNewEditAddressDialogVisible" />
<CardAddEditDialog
v-model:is-dialog-visible="isCardAddDialogVisible"
:card-details="currentCardDetails"
/>
<CardAddEditDialog v-model:is-dialog-visible="isNewCardAddDialogVisible" />
</template>

View File

@@ -0,0 +1,93 @@
<script setup>
const notifications = ref([
{
type: 'New for you',
email: true,
browser: true,
app: true,
},
{
type: 'Account activity',
email: true,
browser: true,
app: true,
},
{
type: 'A new browser used to sign in',
email: true,
browser: true,
app: false,
},
{
type: 'A new device is linked',
email: true,
browser: false,
app: false,
},
])
</script>
<template>
<VCard class="user-tab-notification">
<VCardItem>
<VCardTitle class="mb-1">
Notifications
</VCardTitle>
<VCardSubtitle class="text-body-1 text-wrap">
You will receive notification for the below selected items.
</VCardSubtitle>
</VCardItem>
<VCardText class="px-0">
<VDivider />
<VTable class="text-no-wrap">
<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, index) in notifications"
:key="notification.type"
:class="index % 2 === 0 ? 'table-colored-raw' : ''"
>
<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>
<VCardText class="d-flex flex-wrap gap-4">
<VBtn>Save changes</VBtn>
<VBtn
color="secondary"
variant="tonal"
>
Discard
</VBtn>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,127 @@
<script setup>
import CustomerOrderTable from './CustomerOrderTable.vue'
</script>
<template>
<VRow>
<VCol
cols="12"
md="6"
>
<VCard>
<VCardText class="d-flex gap-y-2 flex-column">
<VAvatar
variant="tonal"
color="primary"
icon="tabler-currency-dollar"
rounded
/>
<h5 class="text-h5">
Account Balance
</h5>
<div>
<h5 class="text-h5 text-primary mb-1">
$7480
<span class="text-body-1 d-inline-block">Credit Left</span>
</h5>
<p class="mb-0">
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="tabler-gift"
rounded
/>
<h5 class="text-h5">
Loyalty Program
</h5>
<div>
<VChip
color="success"
class="mb-2"
label
size="small"
>
Platinum member
</VChip>
<p class="mb-0">
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="tabler-star"
rounded
/>
<h5 class="text-h5">
Wishlist
</h5>
<div>
<h5 class="text-h5 text-warning mb-1">
15
<span class="text-body-1 d-inline-block">Items in wishlist</span>
</h5>
<p class="mb-0">
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="tabler-discount"
rounded
/>
<h5 class="text-h5">
Coupons
</h5>
<div>
<h5 class="text-h5 text-info mb-1">
21
<span class="text-body-1 d-inline-block">Coupons you win</span>
</h5>
<p class="mb-0">
Use coupon on next purchase
</p>
</div>
</VCardText>
</VCard>
</VCol>
<VCol>
<CustomerOrderTable />
</VCol>
</VRow>
</template>

View File

@@ -0,0 +1,203 @@
<script setup>
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: 'tabler-brand-windows',
color: 'info',
device: 'HP Specter 360',
location: 'Switzerland',
activity: '10, July 2021 20:07',
},
{
browser: 'Chrome on iPhone',
logo: 'tabler-device-mobile',
color: 'error',
device: 'iPhone 12x',
location: 'Australia',
activity: '13, July 2021 10:10',
},
{
browser: 'Chrome on Android',
logo: 'tabler-brand-android',
color: 'success',
device: 'OnePlus 9 Pro',
location: 'Dubai',
activity: '4, July 2021 15:15',
},
{
browser: 'Chrome on macOS',
logo: 'tabler-brand-apple',
color: 'secondary',
device: 'Apple iMac',
location: 'India',
activity: '20, July 2021 21:01',
},
{
browser: 'Chrome on Windows',
logo: 'tabler-brand-windows',
color: 'info',
device: 'HP Specter 360',
location: 'Switzerland',
activity: '10, July 2021 20:07',
},
{
browser: 'Chrome on Android',
logo: 'tabler-brand-android',
color: 'success',
device: 'OnePlus 9 Pro',
location: 'Dubai',
activity: '4, July 2021 15:15',
},
]
</script>
<template>
<VRow>
<VCol cols="12">
<!-- 👉 Change password -->
<VCard title="Change Password">
<VCardText>
<VAlert
variant="tonal"
color="warning"
title="Ensure that these requirements are met"
text="Minimum 8 characters long, uppercase & symbol"
class="mb-4"
closable
/>
<VForm @submit.prevent="() => {}">
<VRow>
<VCol
cols="12"
md="6"
>
<AppTextField
label="New Password"
placeholder="············"
:type="isNewPasswordVisible ? 'text' : 'password'"
:append-inner-icon="isNewPasswordVisible ? 'tabler-eye-off' : 'tabler-eye'"
@click:append-inner="isNewPasswordVisible = !isNewPasswordVisible"
/>
</VCol>
<VCol
cols="12"
md="6"
>
<AppTextField
label="Confirm Password"
autocomplete="confirm-password"
placeholder="············"
:type="isConfirmPasswordVisible ? 'text' : 'password'"
:append-inner-icon="isConfirmPasswordVisible ? 'tabler-eye-off' : 'tabler-eye'"
@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-steps verification"
subtitle="Keep your account secure with authentication step."
>
<VCardText>
<div class="text-h6 mb-1">
SMS
</div>
<AppTextField placeholder="+1(968) 819-2547">
<template #append>
<IconBtn>
<VIcon
icon="tabler-edit"
size="22"
/>
</IconBtn>
<IconBtn>
<VIcon
icon="tabler-user-plus"
size="22"
/>
</IconBtn>
</template>
</AppTextField>
<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">
<VDivider />
<VDataTable
:items="recentDevices"
:headers="recentDeviceHeader"
hide-default-footer
class="text-no-wrap"
>
<template #item.browser="{ item }">
<div class="d-flex align-center gap-x-4">
<VIcon
:icon="item.logo"
:color="item.color"
size="22"
/>
<div class="text-body-1 text-high-emphasis">
{{ item.browser }}
</div>
</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:is-dialog-visible="isTwoFactorDialogOpen"
:sms-code="smsVerificationNumber"
/>
</template>