first commit
This commit is contained in:
@@ -0,0 +1,376 @@
|
||||
<script setup>
|
||||
import avatar1 from '@images/avatars/avatar-1.png'
|
||||
|
||||
const accountData = {
|
||||
avatarImg: avatar1,
|
||||
firstName: 'john',
|
||||
lastName: 'Doe',
|
||||
email: 'johnDoe@example.com',
|
||||
org: 'ThemeSelection',
|
||||
phone: '+1 (917) 543-9876',
|
||||
address: '123 Main St, New York, NY 10001',
|
||||
state: 'New York',
|
||||
zip: '10001',
|
||||
country: ['USA'],
|
||||
language: ['English'],
|
||||
timezone: '(GMT-11:00) International Date Line West',
|
||||
currency: 'USD',
|
||||
}
|
||||
|
||||
const refInputEl = ref()
|
||||
const isConfirmDialogOpen = ref(false)
|
||||
const accountDataLocal = ref(structuredClone(accountData))
|
||||
const isAccountDeactivated = ref(false)
|
||||
const validateAccountDeactivation = [v => !!v || 'Please confirm account deactivation']
|
||||
|
||||
const resetForm = () => {
|
||||
accountDataLocal.value = structuredClone(accountData)
|
||||
}
|
||||
|
||||
const changeAvatar = file => {
|
||||
const fileReader = new FileReader()
|
||||
const { files } = file.target
|
||||
if (files && files.length) {
|
||||
fileReader.readAsDataURL(files[0])
|
||||
fileReader.onload = () => {
|
||||
if (typeof fileReader.result === 'string')
|
||||
accountDataLocal.value.avatarImg = fileReader.result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// reset avatar image
|
||||
const resetAvatar = () => {
|
||||
accountDataLocal.value.avatarImg = accountData.avatarImg
|
||||
}
|
||||
|
||||
const timezones = [
|
||||
'(GMT-11:00) International Date Line West',
|
||||
'(GMT-11:00) Midway Island',
|
||||
'(GMT-10:00) Hawaii',
|
||||
'(GMT-09:00) Alaska',
|
||||
'(GMT-08:00) Pacific Time (US & Canada)',
|
||||
'(GMT-08:00) Tijuana',
|
||||
'(GMT-07:00) Arizona',
|
||||
'(GMT-07:00) Chihuahua',
|
||||
'(GMT-07:00) La Paz',
|
||||
'(GMT-07:00) Mazatlan',
|
||||
'(GMT-07:00) Mountain Time (US & Canada)',
|
||||
'(GMT-06:00) Central America',
|
||||
'(GMT-06:00) Central Time (US & Canada)',
|
||||
'(GMT-06:00) Guadalajara',
|
||||
'(GMT-06:00) Mexico City',
|
||||
'(GMT-06:00) Monterrey',
|
||||
'(GMT-06:00) Saskatchewan',
|
||||
'(GMT-05:00) Bogota',
|
||||
'(GMT-05:00) Eastern Time (US & Canada)',
|
||||
'(GMT-05:00) Indiana (East)',
|
||||
'(GMT-05:00) Lima',
|
||||
'(GMT-05:00) Quito',
|
||||
'(GMT-04:00) Atlantic Time (Canada)',
|
||||
'(GMT-04:00) Caracas',
|
||||
'(GMT-04:00) La Paz',
|
||||
'(GMT-04:00) Santiago',
|
||||
'(GMT-03:30) Newfoundland',
|
||||
'(GMT-03:00) Brasilia',
|
||||
'(GMT-03:00) Buenos Aires',
|
||||
'(GMT-03:00) Georgetown',
|
||||
'(GMT-03:00) Greenland',
|
||||
'(GMT-02:00) Mid-Atlantic',
|
||||
'(GMT-01:00) Azores',
|
||||
'(GMT-01:00) Cape Verde Is.',
|
||||
'(GMT+00:00) Casablanca',
|
||||
'(GMT+00:00) Dublin',
|
||||
'(GMT+00:00) Edinburgh',
|
||||
'(GMT+00:00) Lisbon',
|
||||
'(GMT+00:00) London',
|
||||
]
|
||||
|
||||
const currencies = [
|
||||
'USD',
|
||||
'EUR',
|
||||
'GBP',
|
||||
'AUD',
|
||||
'BRL',
|
||||
'CAD',
|
||||
'CNY',
|
||||
'CZK',
|
||||
'DKK',
|
||||
'HKD',
|
||||
'HUF',
|
||||
'INR',
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VRow>
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardText>
|
||||
<div class="d-flex mb-10">
|
||||
<!-- 👉 Avatar -->
|
||||
<VAvatar
|
||||
rounded
|
||||
size="100"
|
||||
class="me-6"
|
||||
:image="accountDataLocal.avatarImg"
|
||||
/>
|
||||
|
||||
<!-- 👉 Upload Photo -->
|
||||
<form class="d-flex flex-column justify-center gap-4">
|
||||
<div class="d-flex flex-wrap gap-4">
|
||||
<VBtn
|
||||
color="primary"
|
||||
@click="refInputEl?.click()"
|
||||
>
|
||||
<VIcon
|
||||
icon="ri-upload-cloud-line"
|
||||
class="d-sm-none"
|
||||
/>
|
||||
<span class="d-none d-sm-block">Upload new photo</span>
|
||||
</VBtn>
|
||||
<input
|
||||
ref="refInputEl"
|
||||
type="file"
|
||||
name="file"
|
||||
accept=".jpeg,.png,.jpg,GIF"
|
||||
hidden
|
||||
@input="changeAvatar"
|
||||
>
|
||||
<VBtn
|
||||
type="reset"
|
||||
color="error"
|
||||
variant="outlined"
|
||||
@click="resetAvatar"
|
||||
>
|
||||
<span class="d-none d-sm-block">Reset</span>
|
||||
<VIcon
|
||||
icon="ri-refresh-line"
|
||||
class="d-sm-none"
|
||||
/>
|
||||
</VBtn>
|
||||
</div>
|
||||
<p class="text-body-1 mb-0">
|
||||
Allowed JPG, GIF or PNG. Max size of 800K
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- 👉 Form -->
|
||||
<VForm>
|
||||
<VRow>
|
||||
<!-- 👉 First Name -->
|
||||
<VCol
|
||||
md="6"
|
||||
cols="12"
|
||||
>
|
||||
<VTextField
|
||||
v-model="accountDataLocal.firstName"
|
||||
placeholder="John"
|
||||
label="First Name"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Last Name -->
|
||||
<VCol
|
||||
md="6"
|
||||
cols="12"
|
||||
>
|
||||
<VTextField
|
||||
v-model="accountDataLocal.lastName"
|
||||
placeholder="Doe"
|
||||
label="Last Name"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Email -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<VTextField
|
||||
v-model="accountDataLocal.email"
|
||||
label="E-mail"
|
||||
placeholder="johndoe@gmail.com"
|
||||
type="email"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Organization -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<VTextField
|
||||
v-model="accountDataLocal.org"
|
||||
label="Organization"
|
||||
placeholder="ThemeSelection"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Phone -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<VTextField
|
||||
v-model="accountDataLocal.phone"
|
||||
label="Phone Number"
|
||||
placeholder="+1 (917) 543-9876"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Address -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<VTextField
|
||||
v-model="accountDataLocal.address"
|
||||
label="Address"
|
||||
placeholder="123 Main St, New York, NY 10001"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 State -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<VTextField
|
||||
v-model="accountDataLocal.state"
|
||||
label="State"
|
||||
placeholder="New York"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Zip Code -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<VTextField
|
||||
v-model="accountDataLocal.zip"
|
||||
label="Zip Code"
|
||||
placeholder="10001"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Country -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<VSelect
|
||||
v-model="accountDataLocal.country"
|
||||
multiple
|
||||
chips
|
||||
closable-chips
|
||||
label="Country"
|
||||
:items="['USA', 'Canada', 'UK', 'India', 'Australia']"
|
||||
placeholder="Select Country"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Language -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<VSelect
|
||||
v-model="accountDataLocal.language"
|
||||
label="Language"
|
||||
multiple
|
||||
chips
|
||||
closable-chips
|
||||
placeholder="Select Language"
|
||||
:items="['English', 'Spanish', 'Arabic', 'Hindi', 'Urdu']"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Timezone -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<VSelect
|
||||
v-model="accountDataLocal.timezone"
|
||||
label="Timezone"
|
||||
placeholder="Select Timezone"
|
||||
:items="timezones"
|
||||
:menu-props="{ maxHeight: 200 }"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Currency -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<VSelect
|
||||
v-model="accountDataLocal.currency"
|
||||
label="Currency"
|
||||
placeholder="Select Currency"
|
||||
:items="currencies"
|
||||
:menu-props="{ maxHeight: 200 }"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Form Actions -->
|
||||
<VCol
|
||||
cols="12"
|
||||
class="d-flex flex-wrap gap-4"
|
||||
>
|
||||
<VBtn>Save changes</VBtn>
|
||||
|
||||
<VBtn
|
||||
color="secondary"
|
||||
variant="outlined"
|
||||
type="reset"
|
||||
@click.prevent="resetForm"
|
||||
>
|
||||
Reset
|
||||
</VBtn>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VForm>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
|
||||
<VCol cols="12">
|
||||
<!-- 👉 Delete Account -->
|
||||
<VCard title="Delete Account">
|
||||
<VCardText>
|
||||
<!-- 👉 Checkbox and Button -->
|
||||
<div>
|
||||
<VCheckbox
|
||||
v-model="isAccountDeactivated"
|
||||
:rules="validateAccountDeactivation"
|
||||
label="I confirm my account deactivation"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<VBtn
|
||||
:disabled="!isAccountDeactivated"
|
||||
color="error"
|
||||
class="mt-3"
|
||||
@click="isConfirmDialogOpen = true"
|
||||
>
|
||||
Deactivate Account
|
||||
</VBtn>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
</VRow>
|
||||
|
||||
<!-- Confirm Dialog -->
|
||||
<ConfirmDialog
|
||||
v-model:isDialogVisible="isConfirmDialogOpen"
|
||||
confirmation-question="Are you sure you want to deactivate your account?"
|
||||
confirm-title="Deactivated!"
|
||||
confirm-msg="Your account has been deactivated successfully."
|
||||
cancel-title="Cancelled"
|
||||
cancel-msg="Account Deactivation Cancelled!"
|
||||
/>
|
||||
</template>
|
@@ -0,0 +1,515 @@
|
||||
<script setup>
|
||||
import BillingHistoryTable from './BillingHistoryTable.vue'
|
||||
import mastercard from '@images/icons/payments/mastercard.png'
|
||||
import visa from '@images/icons/payments/visa.png'
|
||||
|
||||
const selectedPaymentMethod = ref('credit-debit-atm-card')
|
||||
const isPricingPlanDialogVisible = ref(false)
|
||||
const isConfirmDialogVisible = ref(false)
|
||||
const isCardEditDialogVisible = ref(false)
|
||||
const isCardDetailSaveBilling = ref(false)
|
||||
|
||||
const creditCards = [
|
||||
{
|
||||
name: 'Tom McBride',
|
||||
number: '5531234567899856',
|
||||
expiry: '12/23',
|
||||
isPrimary: true,
|
||||
type: 'visa',
|
||||
cvv: '456',
|
||||
image: mastercard,
|
||||
},
|
||||
{
|
||||
name: 'Mildred Wagner',
|
||||
number: '4851234567895896',
|
||||
expiry: '10/27',
|
||||
isPrimary: false,
|
||||
type: 'mastercard',
|
||||
cvv: '123',
|
||||
image: visa,
|
||||
},
|
||||
]
|
||||
|
||||
const countryList = [
|
||||
'United States',
|
||||
'Canada',
|
||||
'United Kingdom',
|
||||
'Australia',
|
||||
'New Zealand',
|
||||
'India',
|
||||
'Russia',
|
||||
'China',
|
||||
'Japan',
|
||||
]
|
||||
|
||||
const currentCardDetails = ref()
|
||||
|
||||
const openEditCardDialog = cardDetails => {
|
||||
currentCardDetails.value = cardDetails
|
||||
isCardEditDialogVisible.value = true
|
||||
}
|
||||
|
||||
const cardNumber = ref(135632156548789)
|
||||
const cardName = ref('john Doe')
|
||||
const cardExpiryDate = ref('05/24')
|
||||
const cardCvv = ref(420)
|
||||
|
||||
const resetPaymentForm = () => {
|
||||
cardNumber.value = 135632156548789
|
||||
cardName.value = 'john Doe'
|
||||
cardExpiryDate.value = '05/24'
|
||||
cardCvv.value = 420
|
||||
selectedPaymentMethod.value = 'credit-debit-atm-card'
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VRow>
|
||||
<!-- 👉 Current Plan -->
|
||||
<VCol cols="12">
|
||||
<VCard title="Current Plan">
|
||||
<VCardText>
|
||||
<VRow>
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<div class="d-flex flex-column gap-y-6">
|
||||
<div class="d-flex flex-column gap-y-1">
|
||||
<h6 class="text-h6">
|
||||
Your Current Plan is Basic
|
||||
</h6>
|
||||
<div>
|
||||
A simple start for everyone
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-column gap-y-1">
|
||||
<h6 class="text-h6">
|
||||
Active until Dec 09, 2021
|
||||
</h6>
|
||||
<div>
|
||||
We will send you a notification upon Subscription expiration
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-column gap-y-1">
|
||||
<div class="d-flex align-center gap-x-2">
|
||||
<h6 class="text-h6">
|
||||
$199 Per Month
|
||||
</h6>
|
||||
<VChip
|
||||
color="primary"
|
||||
size="small"
|
||||
>
|
||||
Popular
|
||||
</VChip>
|
||||
</div>
|
||||
<p class="text-base mb-0">
|
||||
Standard plan for small to medium businesses
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</VCol>
|
||||
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<VAlert
|
||||
type="warning"
|
||||
variant="tonal"
|
||||
title="We need your attention!"
|
||||
text="Your plan requires update"
|
||||
/>
|
||||
|
||||
<!-- progress -->
|
||||
<h6 class="d-flex text-h6 justify-space-between mt-6 mb-1">
|
||||
<div>Days</div>
|
||||
<div>12 of 30 Days</div>
|
||||
</h6>
|
||||
<VProgressLinear
|
||||
color="primary"
|
||||
rounded
|
||||
height="6"
|
||||
model-value="75"
|
||||
/>
|
||||
<p class="text-base mt-1">
|
||||
18 days remaining until your plan requires update
|
||||
</p>
|
||||
</VCol>
|
||||
|
||||
<VCol cols="12">
|
||||
<div class="d-flex flex-wrap gap-4">
|
||||
<VBtn @click="isPricingPlanDialogVisible = true">
|
||||
upgrade plan
|
||||
</VBtn>
|
||||
|
||||
<VBtn
|
||||
color="error"
|
||||
variant="outlined"
|
||||
@click="isConfirmDialogVisible = true"
|
||||
>
|
||||
Cancel Subscription
|
||||
</VBtn>
|
||||
</div>
|
||||
</VCol>
|
||||
</VRow>
|
||||
|
||||
<!-- 👉 Confirm Dialog -->
|
||||
<ConfirmDialog
|
||||
v-model:isDialogVisible="isConfirmDialogVisible"
|
||||
confirmation-question="Are you sure to cancel your subscription?"
|
||||
cancel-msg="Unsubscription Cancelled!!"
|
||||
cancel-title="Cancelled"
|
||||
confirm-msg="Your subscription cancelled successfully."
|
||||
confirm-title="Unsubscribed!"
|
||||
/>
|
||||
|
||||
<!-- 👉 plan and pricing dialog -->
|
||||
<PricingPlanDialog v-model:is-dialog-visible="isPricingPlanDialogVisible" />
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Payment Methods -->
|
||||
<VCol cols="12">
|
||||
<VCard title="Payment Methods">
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<VRow>
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<VRow>
|
||||
<!-- 👉 card type switch -->
|
||||
<VCol cols="12">
|
||||
<VRadioGroup
|
||||
v-model="selectedPaymentMethod"
|
||||
inline
|
||||
>
|
||||
<VRadio
|
||||
value="credit-debit-atm-card"
|
||||
label="Credit/Debit/ATM Card"
|
||||
color="primary"
|
||||
/>
|
||||
<VRadio
|
||||
value="cod-cheque"
|
||||
label="COD/Cheque"
|
||||
color="primary"
|
||||
/>
|
||||
</VRadioGroup>
|
||||
</VCol>
|
||||
|
||||
<VCol cols="12">
|
||||
<VRow v-show="selectedPaymentMethod === 'credit-debit-atm-card'">
|
||||
<!-- 👉 Card Number -->
|
||||
<VCol cols="12">
|
||||
<VTextField
|
||||
v-model="cardNumber"
|
||||
label="Card Number"
|
||||
placeholder="1234 1234 1234 1234"
|
||||
type="number"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Name -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<VTextField
|
||||
v-model="cardName"
|
||||
label="Name"
|
||||
placeholder="John Doe"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Expiry date -->
|
||||
<VCol
|
||||
cols="6"
|
||||
md="3"
|
||||
>
|
||||
<VTextField
|
||||
v-model="cardExpiryDate"
|
||||
label="Expiry Date"
|
||||
placeholder="MM/YY"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Cvv code -->
|
||||
<VCol
|
||||
cols="6"
|
||||
md="3"
|
||||
>
|
||||
<VTextField
|
||||
v-model="cardCvv"
|
||||
type="number"
|
||||
label="CVV Code"
|
||||
placeholder="123"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Future Billing switch -->
|
||||
<VCol cols="12">
|
||||
<VSwitch
|
||||
v-model="isCardDetailSaveBilling"
|
||||
density="compact"
|
||||
label="Save card for future billing?"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Payment method action button -->
|
||||
<VCol
|
||||
cols="12"
|
||||
class="d-flex flex-wrap gap-4"
|
||||
>
|
||||
<VBtn type="submit">
|
||||
Save changes
|
||||
</VBtn>
|
||||
<VBtn
|
||||
color="secondary"
|
||||
variant="outlined"
|
||||
@click="resetPaymentForm"
|
||||
>
|
||||
Reset
|
||||
</VBtn>
|
||||
</VCol>
|
||||
</VRow>
|
||||
|
||||
<p
|
||||
v-show="selectedPaymentMethod === 'cod-cheque'"
|
||||
class="text-base"
|
||||
>
|
||||
Cash on delivery is a mode of payment where you make the payment after the goods/services are received.
|
||||
</p>
|
||||
<p
|
||||
v-show="selectedPaymentMethod === 'cod-cheque'"
|
||||
class="text-base"
|
||||
>
|
||||
You can pay cash or make the payment via debit/credit card directly to the delivery person.
|
||||
</p>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Saved Cards -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<h6 class="text-h6 mb-6">
|
||||
My Cards
|
||||
</h6>
|
||||
|
||||
<div class="d-flex flex-column gap-y-4">
|
||||
<VCard
|
||||
v-for="card in creditCards"
|
||||
:key="card.name"
|
||||
color="rgba(var(--v-theme-on-surface), var(--v-hover-opacity))"
|
||||
flat
|
||||
>
|
||||
<VCardText class="d-flex flex-sm-row flex-column">
|
||||
<div class="text-no-wrap">
|
||||
<img :src="card.image">
|
||||
<div class="d-flex align-center gap-x-4">
|
||||
<h6 class="text-h6 my-2">
|
||||
{{ card.name }}
|
||||
</h6>
|
||||
<VChip
|
||||
v-if="card.isPrimary"
|
||||
color="primary"
|
||||
size="small"
|
||||
>
|
||||
Primary
|
||||
</VChip>
|
||||
</div>
|
||||
<div>**** **** **** {{ card.number.substring(card.number.length - 4) }}</div>
|
||||
</div>
|
||||
|
||||
<VSpacer />
|
||||
|
||||
<div class="d-flex flex-column text-sm-end">
|
||||
<div class="d-flex flex-wrap gap-4 order-sm-0 order-1">
|
||||
<VBtn
|
||||
variant="outlined"
|
||||
@click="openEditCardDialog(card)"
|
||||
>
|
||||
Edit
|
||||
</VBtn>
|
||||
<VBtn
|
||||
color="error"
|
||||
variant="outlined"
|
||||
>
|
||||
Delete
|
||||
</VBtn>
|
||||
</div>
|
||||
<div class="my-4 text-body-2 order-sm-1 order-0">
|
||||
Card expires at {{ card.expiry }}
|
||||
</div>
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</div>
|
||||
|
||||
<!-- 👉 Add Edit Card Dialog -->
|
||||
<CardAddEditDialog
|
||||
v-model:isDialogVisible="isCardEditDialogVisible"
|
||||
:card-details="currentCardDetails"
|
||||
/>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VForm>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Billing Address -->
|
||||
<VCol cols="12">
|
||||
<VCard title="Billing Address">
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<VRow>
|
||||
<!-- 👉 Company name -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<VTextField
|
||||
label="Company Name"
|
||||
placeholder="Themeselection"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Billing Email -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<VTextField
|
||||
label="Billing Email"
|
||||
placeholder="themeselection@email.com"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Tax ID -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<VTextField
|
||||
label="Tax ID"
|
||||
placeholder="123 123 1233"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Vat Number -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<VTextField
|
||||
label="VAT Number"
|
||||
placeholder="121212"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Mobile -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<VTextField
|
||||
dirty
|
||||
label="Phone Number"
|
||||
type="number"
|
||||
prefix="US (+1)"
|
||||
placeholder="+1 123 456 7890"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Country -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<VSelect
|
||||
label="Country"
|
||||
:items="countryList"
|
||||
placeholder="Select Country"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Billing Address -->
|
||||
<VCol cols="12">
|
||||
<VTextField
|
||||
label="Billing Address"
|
||||
placeholder="1234 Main St"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 State -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<VTextField
|
||||
label="State"
|
||||
placeholder="New York"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Zip Code -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<VTextField
|
||||
label="Zip Code"
|
||||
type="number"
|
||||
placeholder="100006"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Actions Button -->
|
||||
<VCol
|
||||
cols="12"
|
||||
class="d-flex flex-wrap gap-4"
|
||||
>
|
||||
<VBtn type="submit">
|
||||
Save changes
|
||||
</VBtn>
|
||||
<VBtn
|
||||
type="reset"
|
||||
color="secondary"
|
||||
variant="outlined"
|
||||
>
|
||||
Reset
|
||||
</VBtn>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VForm>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Billing History -->
|
||||
<VCol cols="12">
|
||||
<BillingHistoryTable />
|
||||
</VCol>
|
||||
</VRow>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.pricing-dialog {
|
||||
.pricing-title {
|
||||
font-size: 1.5rem !important;
|
||||
}
|
||||
|
||||
.v-card {
|
||||
border: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
</style>
|
@@ -0,0 +1,222 @@
|
||||
<script setup>
|
||||
import asana from '@images/icons/brands/asana.png'
|
||||
import behance from '@images/icons/brands/behance.png'
|
||||
import dribbble from '@images/icons/brands/dribbble.png'
|
||||
import facebook from '@images/icons/brands/facebook.png'
|
||||
import github from '@images/icons/brands/github.png'
|
||||
import google from '@images/icons/brands/google.png'
|
||||
import linkedin from '@images/icons/brands/linkedin.png'
|
||||
import mailchimp from '@images/icons/brands/mailchimp.png'
|
||||
import slack from '@images/icons/brands/slack.png'
|
||||
import twitter from '@images/icons/brands/twitter.png'
|
||||
|
||||
const connectedAccounts = ref([
|
||||
{
|
||||
logo: google,
|
||||
name: 'Google',
|
||||
subtitle: 'Calendar and contacts',
|
||||
connected: true,
|
||||
},
|
||||
{
|
||||
logo: slack,
|
||||
name: 'Slack',
|
||||
subtitle: 'Communication',
|
||||
connected: false,
|
||||
},
|
||||
{
|
||||
logo: github,
|
||||
name: 'GitHub',
|
||||
subtitle: 'Manage your Git repositories',
|
||||
connected: true,
|
||||
},
|
||||
{
|
||||
logo: mailchimp,
|
||||
name: 'MailChimp',
|
||||
subtitle: 'Email marketing service',
|
||||
connected: true,
|
||||
},
|
||||
{
|
||||
logo: asana,
|
||||
name: 'Asana',
|
||||
subtitle: 'Task management',
|
||||
connected: false,
|
||||
},
|
||||
])
|
||||
|
||||
const socialAccounts = ref([
|
||||
{
|
||||
logo: facebook,
|
||||
name: 'Facebook',
|
||||
connected: false,
|
||||
},
|
||||
{
|
||||
logo: twitter,
|
||||
name: 'Twitter',
|
||||
links: {
|
||||
username: '@ThemeSelection',
|
||||
link: 'https://twitter.com/Theme_Selection',
|
||||
},
|
||||
connected: true,
|
||||
},
|
||||
{
|
||||
logo: linkedin,
|
||||
name: 'LinkedIn',
|
||||
links: {
|
||||
username: '@ThemeSelection',
|
||||
link: 'https://in.linkedin.com/company/themeselection',
|
||||
},
|
||||
connected: true,
|
||||
},
|
||||
{
|
||||
logo: dribbble,
|
||||
name: 'Dribbble',
|
||||
connected: false,
|
||||
},
|
||||
{
|
||||
logo: behance,
|
||||
name: 'Behance',
|
||||
connected: false,
|
||||
},
|
||||
])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 👉 Connected Accounts -->
|
||||
<VCard>
|
||||
<VRow>
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
class="pe-md-0 pb-0 pb-md-3"
|
||||
>
|
||||
<VCard flat>
|
||||
<VCardItem class="pb-6">
|
||||
<VCardTitle class="mb-1">
|
||||
Connected Accounts
|
||||
</VCardTitle>
|
||||
<VCardSubtitle>Display content from your connected accounts on your site</VCardSubtitle>
|
||||
</VCardItem>
|
||||
|
||||
<VCardText>
|
||||
<VList class="card-list">
|
||||
<VListItem
|
||||
v-for="item in connectedAccounts"
|
||||
:key="item.logo"
|
||||
>
|
||||
<template #prepend>
|
||||
<VAvatar
|
||||
start
|
||||
size="32"
|
||||
rounded
|
||||
>
|
||||
<img
|
||||
:src="item.logo"
|
||||
height="32"
|
||||
width="32"
|
||||
>
|
||||
</VAvatar>
|
||||
</template>
|
||||
|
||||
<VListItemTitle>
|
||||
<h6 class="text-h6">
|
||||
{{ item.name }}
|
||||
</h6>
|
||||
</VListItemTitle>
|
||||
|
||||
<VListItemSubtitle>
|
||||
{{ item.subtitle }}
|
||||
</VListItemSubtitle>
|
||||
|
||||
<template #append>
|
||||
<VListItemAction>
|
||||
<VSwitch
|
||||
v-model="item.connected"
|
||||
density="compact"
|
||||
class="me-1"
|
||||
/>
|
||||
</VListItemAction>
|
||||
</template>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Social Accounts -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
class="ps-md-0 pt-0 pt-md-3"
|
||||
>
|
||||
<VCard flat>
|
||||
<VCardItem class="pb-6">
|
||||
<VCardTitle class="mb-1">
|
||||
Social Accounts
|
||||
</VCardTitle>
|
||||
<VCardSubtitle>Display content from social accounts on your site</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<VList class="card-list">
|
||||
<VListItem
|
||||
v-for="item in socialAccounts"
|
||||
:key="item.logo"
|
||||
>
|
||||
<template #prepend>
|
||||
<VAvatar
|
||||
start
|
||||
rounded="0"
|
||||
size="32"
|
||||
>
|
||||
<img
|
||||
:src="item.logo"
|
||||
height="32"
|
||||
width="32"
|
||||
>
|
||||
</VAvatar>
|
||||
</template>
|
||||
|
||||
<VListItemTitle>
|
||||
<h6 class="text-h6">
|
||||
{{ item.name }}
|
||||
</h6>
|
||||
</VListItemTitle>
|
||||
<VListItemSubtitle
|
||||
v-if="item.links?.link"
|
||||
tag="a"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
:href="item.links?.link"
|
||||
style="opacity: 1;"
|
||||
>
|
||||
{{ item.links?.username }}
|
||||
</VListItemSubtitle>
|
||||
|
||||
<VListItemSubtitle v-else>
|
||||
Not Connected
|
||||
</VListItemSubtitle>
|
||||
<template #append>
|
||||
<VListItemAction>
|
||||
<VBtn
|
||||
icon
|
||||
variant="outlined"
|
||||
:color="item.connected ? 'error' : 'secondary'"
|
||||
rounded
|
||||
>
|
||||
<VIcon :icon="item.connected ? 'ri-delete-bin-line' : 'ri-link' " />
|
||||
</VBtn>
|
||||
</VListItemAction>
|
||||
</template>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.card-list{
|
||||
--v-card-list-gap: 1rem;
|
||||
}
|
||||
</style>
|
@@ -0,0 +1,116 @@
|
||||
<script setup>
|
||||
const recentDevices = 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,
|
||||
},
|
||||
])
|
||||
|
||||
const selectedNotification = ref('Only when I\'m online')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>Recent Devices</VCardTitle>
|
||||
<VCardSubtitle>
|
||||
We need permission from your browser to show notifications.
|
||||
<a href="javascript:void(0)">Request Permission</a>
|
||||
</VCardSubtitle>
|
||||
</VCardItem>
|
||||
|
||||
<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="device in recentDevices"
|
||||
:key="device.type"
|
||||
>
|
||||
<td class="text-high-emphasis">
|
||||
{{ device.type }}
|
||||
</td>
|
||||
<td>
|
||||
<VCheckbox v-model="device.email" />
|
||||
</td>
|
||||
<td>
|
||||
<VCheckbox v-model="device.browser" />
|
||||
</td>
|
||||
<td>
|
||||
<VCheckbox v-model="device.app" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</VTable>
|
||||
<VDivider />
|
||||
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="text-base font-weight-medium mb-6">
|
||||
When should we send you notifications?
|
||||
</div>
|
||||
|
||||
<VRow>
|
||||
<VCol
|
||||
cols="12"
|
||||
sm="6"
|
||||
>
|
||||
<VSelect
|
||||
v-model="selectedNotification"
|
||||
mandatory
|
||||
:items="['Only when I\'m online', 'Anytime']"
|
||||
class="mb-6"
|
||||
/>
|
||||
</VCol>
|
||||
</VRow>
|
||||
|
||||
<div class="d-flex flex-wrap gap-4">
|
||||
<VBtn type="submit">
|
||||
Save Changes
|
||||
</VBtn>
|
||||
<VBtn
|
||||
color="secondary"
|
||||
variant="outlined"
|
||||
type="reset"
|
||||
>
|
||||
Reset
|
||||
</VBtn>
|
||||
</div>
|
||||
</VForm>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
@@ -0,0 +1,401 @@
|
||||
<script setup>
|
||||
import sittingGirlWithLaptopDark from '@images/illustrations/sitting-girl-with-laptop-dark.png'
|
||||
import sittingGirlWithLaptopLight from '@images/illustrations/sitting-girl-with-laptop-light.png'
|
||||
|
||||
const isCurrentPasswordVisible = ref(false)
|
||||
const isNewPasswordVisible = ref(false)
|
||||
const isConfirmPasswordVisible = ref(false)
|
||||
const currentPassword = ref('')
|
||||
const newPassword = ref('')
|
||||
const confirmPassword = ref('')
|
||||
|
||||
const passwordRequirements = [
|
||||
'Minimum 8 characters long - the more, the better',
|
||||
'At least one lowercase character',
|
||||
'At least one number, symbol, or whitespace character',
|
||||
]
|
||||
|
||||
const serverKeys = [
|
||||
{
|
||||
name: 'Server Key 1',
|
||||
key: '23eaf7f0-f4f7-495e-8b86-fad3261282ac',
|
||||
createdOn: '28 Apr 2021, 18:20 GTM+4:10',
|
||||
permission: 'Full Access',
|
||||
},
|
||||
{
|
||||
name: 'Server Key 2',
|
||||
key: 'bb98e571-a2e2-4de8-90a9-2e231b5e99',
|
||||
createdOn: '12 Feb 2021, 10:30 GTM+2:30',
|
||||
permission: 'Read Only',
|
||||
},
|
||||
{
|
||||
name: 'Server Key 3',
|
||||
key: '2e915e59-3105-47f2-8838-6e46bf83b711',
|
||||
createdOn: '28 Dec 2020, 12:21 GTM+4:10',
|
||||
permission: 'Full Access',
|
||||
},
|
||||
]
|
||||
|
||||
const recentDevicesHeaders = [
|
||||
{
|
||||
title: 'BROWSER',
|
||||
key: 'browser',
|
||||
},
|
||||
{
|
||||
title: 'DEVICE',
|
||||
key: 'device',
|
||||
},
|
||||
{
|
||||
title: 'LOCATION',
|
||||
key: 'location',
|
||||
},
|
||||
{
|
||||
title: 'RECENT ACTIVITY',
|
||||
key: 'recentActivity',
|
||||
},
|
||||
]
|
||||
|
||||
const recentDevices = [
|
||||
{
|
||||
browser: 'Chrome on Windows',
|
||||
device: 'HP Spectre 360',
|
||||
location: 'New York, NY',
|
||||
recentActivity: '28 Apr 2022, 18:20',
|
||||
deviceIcon: {
|
||||
icon: 'ri-macbook-line',
|
||||
color: 'primary',
|
||||
},
|
||||
},
|
||||
{
|
||||
browser: 'Chrome on iPhone',
|
||||
device: 'iPhone 12x',
|
||||
location: 'Los Angeles, CA',
|
||||
recentActivity: '20 Apr 2022, 10:20',
|
||||
deviceIcon: {
|
||||
icon: 'ri-android-line',
|
||||
color: 'error',
|
||||
},
|
||||
},
|
||||
{
|
||||
browser: 'Chrome on Android',
|
||||
device: 'Oneplus 9 Pro',
|
||||
location: 'San Francisco, CA',
|
||||
recentActivity: '16 Apr 2022, 04:20',
|
||||
deviceIcon: {
|
||||
icon: 'ri-smartphone-line',
|
||||
color: 'success',
|
||||
},
|
||||
},
|
||||
{
|
||||
browser: 'Chrome on macOS',
|
||||
device: 'Apple iMac',
|
||||
location: 'New York, NY',
|
||||
recentActivity: '28 Apr 2022, 18:20',
|
||||
deviceIcon: {
|
||||
icon: 'ri-mac-line',
|
||||
color: 'secondary',
|
||||
},
|
||||
},
|
||||
{
|
||||
browser: 'Chrome on Windows',
|
||||
device: 'HP Spectre 360',
|
||||
location: 'Los Angeles, CA',
|
||||
recentActivity: '20 Apr 2022, 10:20',
|
||||
deviceIcon: {
|
||||
icon: 'ri-macbook-line',
|
||||
color: 'primary',
|
||||
},
|
||||
},
|
||||
{
|
||||
browser: 'Chrome on Android',
|
||||
device: 'Oneplus 9 Pro',
|
||||
location: 'San Francisco, CA',
|
||||
recentActivity: '16 Apr 2022, 04:20',
|
||||
deviceIcon: {
|
||||
icon: 'ri-android-line',
|
||||
color: 'success',
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
const sittingGirlImg = useGenerateImageVariant(sittingGirlWithLaptopLight, sittingGirlWithLaptopDark)
|
||||
const isOneTimePasswordDialogVisible = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VRow>
|
||||
<!-- SECTION: Change Password -->
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem class="pb-6">
|
||||
<VCardTitle>Change Password</VCardTitle>
|
||||
</VCardItem>
|
||||
<VForm>
|
||||
<VCardText class="pt-0">
|
||||
<!-- 👉 Current Password -->
|
||||
<VRow>
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<!-- 👉 current password -->
|
||||
<VTextField
|
||||
v-model="currentPassword"
|
||||
:type="isCurrentPasswordVisible ? 'text' : 'password'"
|
||||
:append-inner-icon="isCurrentPasswordVisible ? 'ri-eye-off-line' : 'ri-eye-line'"
|
||||
autocomplete="on"
|
||||
label="Current Password"
|
||||
placeholder="············"
|
||||
@click:append-inner="isCurrentPasswordVisible = !isCurrentPasswordVisible"
|
||||
/>
|
||||
</VCol>
|
||||
</VRow>
|
||||
|
||||
<!-- 👉 New Password -->
|
||||
<VRow>
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<!-- 👉 new password -->
|
||||
<VTextField
|
||||
v-model="newPassword"
|
||||
:type="isNewPasswordVisible ? 'text' : 'password'"
|
||||
:append-inner-icon="isNewPasswordVisible ? 'ri-eye-off-line' : 'ri-eye-line'"
|
||||
label="New Password"
|
||||
autocomplete="on"
|
||||
placeholder="············"
|
||||
@click:append-inner="isNewPasswordVisible = !isNewPasswordVisible"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<!-- 👉 confirm password -->
|
||||
<VTextField
|
||||
v-model="confirmPassword"
|
||||
:type="isConfirmPasswordVisible ? 'text' : 'password'"
|
||||
:append-inner-icon="isConfirmPasswordVisible ? 'ri-eye-off-line' : 'ri-eye-line'"
|
||||
autocomplete="on"
|
||||
label="Confirm New Password"
|
||||
placeholder="············"
|
||||
@click:append-inner="isConfirmPasswordVisible = !isConfirmPasswordVisible"
|
||||
/>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VCardText>
|
||||
|
||||
<!-- 👉 Password Requirements -->
|
||||
<VCardText>
|
||||
<h6 class="text-h6 text-medium-emphasis mt-1">
|
||||
Password Requirements:
|
||||
</h6>
|
||||
|
||||
<VList>
|
||||
<VListItem
|
||||
v-for="(item, index) in passwordRequirements"
|
||||
:key="index"
|
||||
class="px-0"
|
||||
>
|
||||
<template #prepend>
|
||||
<VIcon
|
||||
size="8"
|
||||
icon="ri-circle-fill"
|
||||
color="rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity))"
|
||||
/>
|
||||
</template>
|
||||
<VListItemTitle class="text-medium-emphasis text-wrap">
|
||||
{{ item }}
|
||||
</VListItemTitle>
|
||||
</VListItem>
|
||||
</VList>
|
||||
|
||||
<!-- 👉 Action Buttons -->
|
||||
<div class="d-flex flex-wrap gap-4">
|
||||
<VBtn>Save changes</VBtn>
|
||||
|
||||
<VBtn
|
||||
type="reset"
|
||||
color="secondary"
|
||||
variant="outlined"
|
||||
>
|
||||
Reset
|
||||
</VBtn>
|
||||
</div>
|
||||
</VCardText>
|
||||
</VForm>
|
||||
</VCard>
|
||||
</VCol>
|
||||
<!-- !SECTION -->
|
||||
|
||||
<!-- SECTION Two-steps verification -->
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem class="pb-6">
|
||||
<VCardTitle>Two-steps verification</VCardTitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<p>
|
||||
Two factor authentication is not enabled yet.
|
||||
</p>
|
||||
<p class="mb-6">
|
||||
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>
|
||||
|
||||
<VBtn @click="isOneTimePasswordDialogVisible = true">
|
||||
Enable 2FA
|
||||
</VBtn>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
<!-- !SECTION -->
|
||||
|
||||
<VCol cols="12">
|
||||
<!-- SECTION: Create an API key -->
|
||||
<VCard title="Create an API key">
|
||||
<VRow>
|
||||
<!-- 👉 Choose API Key -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="5"
|
||||
order-md="0"
|
||||
order="1"
|
||||
>
|
||||
<VCardText class="pt-7">
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<!-- 👉 Choose API Key -->
|
||||
<VSelect
|
||||
label="Choose the API key type you want to create"
|
||||
placeholder="Select API key type"
|
||||
:items="['Full Control', 'Modify', 'Read & Execute', 'List Folder Contents', 'Read Only', 'Read & Write']"
|
||||
/>
|
||||
|
||||
<!-- 👉 Name the API Key -->
|
||||
<VTextField
|
||||
label="Name the API key"
|
||||
placeholder="Name the API key"
|
||||
class="my-5"
|
||||
/>
|
||||
|
||||
<!-- 👉 Create Key Button -->
|
||||
<VBtn
|
||||
type="submit"
|
||||
block
|
||||
>
|
||||
Create Key
|
||||
</VBtn>
|
||||
</VForm>
|
||||
</VCardText>
|
||||
</VCol>
|
||||
|
||||
<!-- 👉 Lady image -->
|
||||
<VCol
|
||||
cols="12"
|
||||
md="7"
|
||||
order="0"
|
||||
order-md="1"
|
||||
class="d-flex flex-column justify-center align-center"
|
||||
>
|
||||
<VImg
|
||||
:src="sittingGirlImg"
|
||||
:width="310"
|
||||
:style="$vuetify.display.smAndDown ? '' : 'position: absolute; bottom: 0;'"
|
||||
/>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VCard>
|
||||
<!-- !SECTION -->
|
||||
</VCol>
|
||||
|
||||
<VCol cols="12">
|
||||
<!-- SECTION: API Keys List -->
|
||||
<VCard>
|
||||
<VCardItem class="pb-4">
|
||||
<VCardTitle>API Key List & Access</VCardTitle>
|
||||
</VCardItem>
|
||||
|
||||
<VCardText>
|
||||
<p class="mb-6">
|
||||
An API key is a simple encrypted string that identifies an application without any principal. They are useful for accessing public data anonymously, and are used to associate API requests with your project for quota and billing.
|
||||
</p>
|
||||
|
||||
<!-- 👉 Server Status -->
|
||||
<div class="d-flex flex-column gap-y-6">
|
||||
<div
|
||||
v-for="serverKey in serverKeys"
|
||||
:key="serverKey.key"
|
||||
class="bg-var-theme-background pa-4"
|
||||
>
|
||||
<div class="d-flex align-center flex-wrap mb-2 gap-x-3">
|
||||
<h6 class="text-h6">
|
||||
{{ serverKey.name }}
|
||||
</h6>
|
||||
<VChip
|
||||
color="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ serverKey.permission }}
|
||||
</VChip>
|
||||
</div>
|
||||
|
||||
<h6 class="text-h6 d-flex gap-x-3 text-medium-emphasis align-center mb-2">
|
||||
{{ serverKey.key }}
|
||||
<VIcon
|
||||
:size="20"
|
||||
icon="ri-file-copy-line"
|
||||
class="cursor-pointer"
|
||||
/>
|
||||
</h6>
|
||||
<div class="text-disabled">
|
||||
Created on {{ serverKey.createdOn }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
<!-- !SECTION -->
|
||||
</VCol>
|
||||
|
||||
<!-- SECTION Recent Devices -->
|
||||
<VCol cols="12">
|
||||
<!-- 👉 Table -->
|
||||
<VCard
|
||||
title="Recent Devices"
|
||||
class="recentDeviceCard"
|
||||
>
|
||||
<VDataTable
|
||||
:headers="recentDevicesHeaders"
|
||||
:items="recentDevices"
|
||||
hide-default-footer
|
||||
class="text-no-wrap"
|
||||
>
|
||||
<template #item.browser="{ item }">
|
||||
<div class="d-flex gap-x-3">
|
||||
<VIcon
|
||||
size="20"
|
||||
:icon="item.deviceIcon.icon"
|
||||
:color="item.deviceIcon.color"
|
||||
/>
|
||||
<h6 class="text-h6">
|
||||
{{ item.browser }}
|
||||
</h6>
|
||||
</div>
|
||||
</template>
|
||||
<!-- TODO Refactor this after vuetify provides proper solution for removing default footer -->
|
||||
<template #bottom />
|
||||
</VDataTable>
|
||||
</VCard>
|
||||
</VCol>
|
||||
<!-- !SECTION -->
|
||||
</VRow>
|
||||
|
||||
<!-- SECTION Enable One time password -->
|
||||
<TwoFactorAuthDialog v-model:isDialogVisible="isOneTimePasswordDialogVisible" />
|
||||
<!-- !SECTION -->
|
||||
</template>
|
@@ -0,0 +1,407 @@
|
||||
<script setup>
|
||||
const searchQuery = ref('')
|
||||
const selectedStatus = ref()
|
||||
const selectedRows = 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
|
||||
}
|
||||
|
||||
// 👉 headers
|
||||
const headers = [
|
||||
{
|
||||
title: '#',
|
||||
key: 'id',
|
||||
},
|
||||
{
|
||||
title: 'Trending',
|
||||
key: 'trending',
|
||||
sortable: false,
|
||||
},
|
||||
{
|
||||
title: 'Client',
|
||||
key: 'client',
|
||||
},
|
||||
{
|
||||
title: 'Total',
|
||||
key: 'total',
|
||||
},
|
||||
{
|
||||
title: 'Issued Date',
|
||||
key: 'date',
|
||||
},
|
||||
{
|
||||
title: 'Balance',
|
||||
key: 'balance',
|
||||
},
|
||||
{
|
||||
title: 'Action',
|
||||
key: 'actions',
|
||||
sortable: false,
|
||||
},
|
||||
]
|
||||
|
||||
const {
|
||||
data: invoiceData,
|
||||
execute: fetchInvoices,
|
||||
} = await useApi(createUrl('/apps/invoice', {
|
||||
query: {
|
||||
q: searchQuery,
|
||||
status: selectedStatus,
|
||||
itemsPerPage,
|
||||
page,
|
||||
sortBy,
|
||||
orderBy,
|
||||
},
|
||||
}))
|
||||
|
||||
const invoices = computed(() => invoiceData.value.invoices)
|
||||
const totalInvoices = computed(() => invoiceData.value.totalInvoices)
|
||||
|
||||
// 👉 Invoice balance variant resolver
|
||||
const resolveInvoiceBalanceVariant = (balance, total) => {
|
||||
if (balance === total)
|
||||
return {
|
||||
status: 'Unpaid',
|
||||
chip: { color: 'error' },
|
||||
}
|
||||
if (balance === 0)
|
||||
return {
|
||||
status: 'Paid',
|
||||
chip: { color: 'success' },
|
||||
}
|
||||
|
||||
return {
|
||||
status: balance,
|
||||
chip: { variant: 'text' },
|
||||
}
|
||||
}
|
||||
|
||||
const resolveInvoiceStatusVariantAndIcon = status => {
|
||||
if (status === 'Partial Payment')
|
||||
return {
|
||||
variant: 'warning',
|
||||
icon: 'ri-line-chart-line',
|
||||
}
|
||||
if (status === 'Paid')
|
||||
return {
|
||||
variant: 'success',
|
||||
icon: 'ri-check-line',
|
||||
}
|
||||
if (status === 'Downloaded')
|
||||
return {
|
||||
variant: 'info',
|
||||
icon: 'ri-arrow-down-line',
|
||||
}
|
||||
if (status === 'Draft')
|
||||
return {
|
||||
variant: 'secondary',
|
||||
icon: 'ri-save-line',
|
||||
}
|
||||
if (status === 'Sent')
|
||||
return {
|
||||
variant: 'primary',
|
||||
icon: 'ri-mail-line',
|
||||
}
|
||||
if (status === 'Past Due')
|
||||
return {
|
||||
variant: 'error',
|
||||
icon: 'ri-error-warning-line',
|
||||
}
|
||||
|
||||
return {
|
||||
variant: 'secondary',
|
||||
icon: 'ri-close-line',
|
||||
}
|
||||
}
|
||||
|
||||
const computedMoreList = computed(() => {
|
||||
return paramId => [
|
||||
{
|
||||
title: 'Download',
|
||||
value: 'download',
|
||||
prependIcon: 'ri-download-line',
|
||||
},
|
||||
{
|
||||
title: 'Edit',
|
||||
value: 'edit',
|
||||
prependIcon: 'ri-pencil-line',
|
||||
to: {
|
||||
name: 'apps-invoice-edit-id',
|
||||
params: { id: paramId },
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Duplicate',
|
||||
value: 'duplicate',
|
||||
prependIcon: 'ri-stack-line',
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
const deleteInvoice = async id => {
|
||||
await $api(`/apps/invoice/${ id }`, { method: 'DELETE' })
|
||||
fetchInvoices()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section v-if="invoices">
|
||||
<!-- 👉 Invoice Filters -->
|
||||
|
||||
<VCard id="invoice-list">
|
||||
<VCardText class="d-flex align-center flex-wrap gap-4">
|
||||
<!-- 👉 Actions -->
|
||||
<div class="me-3">
|
||||
<!-- 👉 Create invoice -->
|
||||
<VBtn
|
||||
prepend-icon="ri-add-line"
|
||||
:to="{ name: 'apps-invoice-add' }"
|
||||
>
|
||||
Create invoice
|
||||
</VBtn>
|
||||
</div>
|
||||
|
||||
<VSpacer />
|
||||
|
||||
<div class="d-flex align-center flex-wrap gap-4">
|
||||
<!-- 👉 Search -->
|
||||
<div class="invoice-list-search">
|
||||
<VTextField
|
||||
v-model="searchQuery"
|
||||
density="compact"
|
||||
placeholder="Search Invoice"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 👉 Filter Invoice -->
|
||||
|
||||
<VSelect
|
||||
v-model="selectedStatus"
|
||||
density="compact"
|
||||
placeholder="Select Status"
|
||||
clearable
|
||||
clear-icon="ri-close-line"
|
||||
:items="['Downloaded', 'Draft', 'Sent', 'Paid', 'Partial Payment', 'Past Due']"
|
||||
style="inline-size: 12rem;"
|
||||
/>
|
||||
</div>
|
||||
</VCardText>
|
||||
|
||||
<!-- SECTION Datatable -->
|
||||
<VDataTableServer
|
||||
v-model="selectedRows"
|
||||
v-model:items-per-page="itemsPerPage"
|
||||
v-model:page="page"
|
||||
show-select
|
||||
:items-length="totalInvoices"
|
||||
:headers="headers"
|
||||
:items="invoices"
|
||||
item-value="id"
|
||||
class="text-no-wrap billing-history-table"
|
||||
@update:options="updateOptions"
|
||||
>
|
||||
<!-- id -->
|
||||
<template #item.id="{ item }">
|
||||
<RouterLink :to="{ name: 'apps-invoice-preview-id', params: { id: item.id } }">
|
||||
#{{ item.id }}
|
||||
</RouterLink>
|
||||
</template>
|
||||
|
||||
<!-- trending -->
|
||||
<template #item.trending="{ item }">
|
||||
<VTooltip>
|
||||
<template #activator="{ props }">
|
||||
<VAvatar
|
||||
:size="28"
|
||||
v-bind="props"
|
||||
:color="resolveInvoiceStatusVariantAndIcon(item.invoiceStatus).variant"
|
||||
variant="tonal"
|
||||
>
|
||||
<VIcon
|
||||
:size="16"
|
||||
:icon="resolveInvoiceStatusVariantAndIcon(item.invoiceStatus).icon"
|
||||
/>
|
||||
</VAvatar>
|
||||
</template>
|
||||
<p class="mb-0">
|
||||
{{ item.invoiceStatus }}
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Balance: {{ item.balance }}
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Due date: {{ item.dueDate }}
|
||||
</p>
|
||||
</VTooltip>
|
||||
</template>
|
||||
|
||||
<!-- client -->
|
||||
<template #item.client="{ item }">
|
||||
<div class="d-flex align-center">
|
||||
<VAvatar
|
||||
size="34"
|
||||
:color="!item.avatar.length ? resolveInvoiceStatusVariantAndIcon(item.invoiceStatus).variant : undefined"
|
||||
:variant="!item.avatar.length ? 'tonal' : undefined"
|
||||
class="me-3"
|
||||
>
|
||||
<VImg
|
||||
v-if="item.avatar.length"
|
||||
:src="item.avatar"
|
||||
/>
|
||||
<span v-else>{{ avatarText(item.client.name) }}</span>
|
||||
</VAvatar>
|
||||
<div class="d-flex flex-column">
|
||||
<RouterLink
|
||||
:to="{ name: 'pages-user-profile-tab', params: { tab: 'profile' } }"
|
||||
class="client-title font-weight-medium mb-0"
|
||||
>
|
||||
{{ item.client.name }}
|
||||
</RouterLink>
|
||||
<div class="text-body-2">
|
||||
{{ item.client.companyEmail }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Total -->
|
||||
<template #item.total="{ item }">
|
||||
${{ item.total }}
|
||||
</template>
|
||||
|
||||
<!-- Issued Date -->
|
||||
<template #item.date="{ item }">
|
||||
{{ item.issuedDate }}
|
||||
</template>
|
||||
|
||||
<!-- Balance -->
|
||||
<template #item.balance="{ item }">
|
||||
<VChip
|
||||
v-if="typeof ((resolveInvoiceBalanceVariant(item.balance, item.total)).status) === 'string'"
|
||||
:color="resolveInvoiceBalanceVariant(item.balance, item.total).chip.color"
|
||||
size="small"
|
||||
>
|
||||
{{ (resolveInvoiceBalanceVariant(item.balance, item.total)).status }}
|
||||
</VChip>
|
||||
<div
|
||||
v-else
|
||||
class="text-body-1 text-high-emphasis"
|
||||
>
|
||||
{{ Number((resolveInvoiceBalanceVariant(item.balance, item.total)).status) > 0 ? `$${(resolveInvoiceBalanceVariant(item.balance, item.total)).status}` : `-$${Math.abs(Number((resolveInvoiceBalanceVariant(item.balance, item.total)).status))}` }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Actions -->
|
||||
<template #item.actions="{ item }">
|
||||
<IconBtn
|
||||
size="small"
|
||||
icon="ri-delete-bin-7-line"
|
||||
@click="deleteInvoice(item.id)"
|
||||
/>
|
||||
|
||||
<IconBtn
|
||||
:to="{ name: 'apps-invoice-preview-id', params: { id: item.id } }"
|
||||
size="small"
|
||||
>
|
||||
<VIcon icon="ri-eye-line" />
|
||||
</IconBtn>
|
||||
|
||||
<MoreBtn
|
||||
:menu-list="computedMoreList(item.id)"
|
||||
size="small"
|
||||
item-props
|
||||
/>
|
||||
</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 }, totalInvoices) }}
|
||||
</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(totalInvoices / itemsPerPage)"
|
||||
@click="page >= Math.ceil(totalInvoices / itemsPerPage) ? page = Math.ceil(totalInvoices / itemsPerPage) : page++ "
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</VDataTableServer>
|
||||
<!-- !SECTION -->
|
||||
</VCard>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
#invoice-list {
|
||||
.invoice-list-actions {
|
||||
inline-size: 8rem;
|
||||
}
|
||||
|
||||
.invoice-list-search {
|
||||
inline-size: 12rem;
|
||||
}
|
||||
}
|
||||
|
||||
.billing-history-table{
|
||||
&.v-table--density-default{
|
||||
.v-table__wrapper{
|
||||
table{
|
||||
tbody{
|
||||
tr{
|
||||
td{
|
||||
block-size: 60px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.client-title{
|
||||
&:not(:hover){
|
||||
color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity)) !important;
|
||||
}
|
||||
}
|
||||
</style>
|
Reference in New Issue
Block a user