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,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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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 &amp; 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>

View File

@@ -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>

View File

@@ -0,0 +1,39 @@
<script setup>
import { useTheme } from 'vuetify'
const { global } = useTheme()
const authProviders = [
{
icon: 'bxl-facebook',
color: '#4267b2',
colorInDark: '#4267b2',
},
{
icon: 'bxl-twitter',
color: '#1da1f2',
colorInDark: '#1da1f2',
},
{
icon: 'bxl-github',
color: '#272727',
colorInDark: '#fff',
},
{
icon: 'bxl-google',
color: '#db4437',
colorInDark: '#db4437',
},
]
</script>
<template>
<VBtn
v-for="link in authProviders"
:key="link.icon"
:icon="link.icon"
variant="text"
size="small"
:color="global.name.value === 'dark' ? link.colorInDark : link.color"
/>
</template>

View File

@@ -0,0 +1,137 @@
<script setup>
import avatar1 from '@images/avatars/avatar-1.png'
import avatar6 from '@images/avatars/avatar-6.png'
import avatar8 from '@images/avatars/avatar-8.png'
import timelineCardHeader from '@images/cards/timeline-card-header.png'
import pdf from '@images/icons/project-icons/pdf.png'
</script>
<template>
<VCard>
<VImg
cover
height="210"
:src="timelineCardHeader"
/>
<VCardItem>
<VCardTitle>Activity Timeline</VCardTitle>
</VCardItem>
<VCardText>
<VTimeline
side="end"
align="start"
line-inset="8"
truncate-line="start"
density="compact"
>
<VTimelineItem
dot-color="primary"
size="x-small"
>
<!-- 👉 Header -->
<div class="d-flex justify-space-between align-center gap-2 flex-wrap mb-3">
<div class="app-timeline-title align-self-start">
12 Invoices have been paid
</div>
<div class="app-timeline-meta">
12 min ago
</div>
</div>
<p class="app-timeline-text mb-2">
Invoices have been paid to the company.
</p>
<div class="d-inline-flex align-center timeline-chip mb-4">
<img
:src="pdf"
height="20"
class="me-3"
alt="img"
>
<h6 class="text-h6 text-medium-emphasis">
invoice.pdf
</h6>
</div>
</VTimelineItem>
<VTimelineItem
dot-color="success"
size="x-small"
>
<!-- 👉 Header -->
<div class="d-flex justify-space-between align-center gap-2 flex-wrap mb-3">
<div class="app-timeline-title align-self-start">
Client Meeting
</div>
<div class="app-timeline-meta">
45 min ago
</div>
</div>
<p class="app-timeline-text mb-2">
Project meeting with john @10:15am
</p>
<div class="d-flex align-center mb-2">
<VAvatar
size="32"
:image="avatar1"
class="me-3"
/>
<div>
<div class="text-body-2 font-weight-medium">
Lester McCarthy (Client)
</div>
<div class="text-body-2">
CEO of ThemeSelection
</div>
</div>
</div>
</VTimelineItem>
<VTimelineItem
dot-color="info"
size="x-small"
>
<div class="d-flex justify-space-between align-center gap-2 flex-wrap mb-3">
<div class="app-timeline-title align-self-start">
Create a new project for client
</div>
<div class="app-timeline-meta">
2 Day Ago
</div>
</div>
<p class="mb-0 app-timeline-text mb-2">
6 team members in a project
</p>
<div class="v-avatar-group">
<VAvatar
:size="40"
:image="avatar1"
/>
<VAvatar
:size="40"
:image="avatar8"
/>
<VAvatar
:size="40"
:image="avatar6"
/>
<VAvatar
:color="$vuetify.theme.current.dark ? '#3A3B59' : '#F0EFF0'"
:size="40"
>
+3
</VAvatar>
</div>
</VTimelineItem>
</VTimeline>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,86 @@
<script setup>
import message from '@images/cards/comment-alt-lines.svg'
import chart from '@images/cards/graph-bar.svg'
import heart from '@images/cards/heart-medical.svg'
import user from '@images/cards/user.svg'
const analytics = [
{
title: '42.8k',
subtitle: 'Number of like',
img: heart,
color: 'primary',
},
{
title: '21.2k',
subtitle: 'Number of Followers',
img: chart,
color: 'warning',
},
{
title: '2.4k',
subtitle: 'Number of Comments',
img: message,
color: 'info',
},
{
title: '389.50k',
subtitle: 'Number of Visits',
img: user,
color: 'success',
},
]
</script>
<template>
<VCard>
<VCardItem>
<VCardTitle>
Analytics
</VCardTitle>
<template #append>
<div class="me-n3">
<MoreBtn />
</div>
</template>
</VCardItem>
<VCardText>
<VList class="card-list">
<VListItem
v-for="item in analytics"
:key="item.title"
>
<template #prepend>
<VAvatar
size="40"
:color="item.color"
variant="tonal"
>
<component :is="item.img" />
</VAvatar>
</template>
<VListItemTitle>
<h5 class="text-h5">
{{ item.title }}
</h5>
</VListItemTitle>
<VListItemSubtitle>
<div class="text-body-1">
{{ item.subtitle }}
</div>
</VListItemSubtitle>
</VListItem>
</VList>
</VCardText>
</VCard>
</template>
<style lang="scss" scoped>
.card-list {
--v-card-list-gap: 24px;
}
</style>

View File

@@ -0,0 +1,59 @@
<script setup>
import cafeBadilico from '@images/cards/cafe-badilico.png'
</script>
<template>
<VCard>
<VImg
cover
height="168"
:src="cafeBadilico"
/>
<VCardText>
<div class="d-flex justify-space-between align-center mb-2">
<h5 class="text-h5">
Cafe Badilico
</h5>
<MoreBtn density="compact" />
</div>
<div class="d-flex gap-x-2 align-center mb-5">
<VRating
:model-value="4"
:size="24"
background-color="warning"
/>
<div class="text-body-1">
4 Star (12.4k)
</div>
</div>
<p>Italian Cafe</p>
<p>
The refrigerated dairy aisle of your local grocery store can be a great source tasty, convenient selections for your.
</p>
<VDivider />
<p class="my-4">
Tonight's availability
</p>
<div class="d-flex gap-x-2 mb-5">
<VChip size="small">
5:30PM
</VChip>
<VChip size="small">
7:00PM
</VChip>
<VChip size="small">
7:15PM
</VChip>
</div>
<VBtn block>
Book Now
</VBtn>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,206 @@
<script setup>
import americanBank from '@images/logos/american-bank.png'
import aws from '@images/logos/aws.png'
import citiBank from '@images/logos/citi-bank.png'
import digitalOcean from '@images/logos/digital-ocean.png'
import github from '@images/logos/github.png'
import google from '@images/logos/google.png'
import gumroad from '@images/logos/gumroad.png'
import mastercardLabel from '@images/logos/mastercard-label.png'
import slack from '@images/logos/slack.png'
import stripe from '@images/logos/stripe.png'
const deposits = [
{
title: 'Gumroad Account',
subtitle: 'Sell UI Kit',
amount: '+$4,650',
logo: gumroad,
},
{
title: 'Mastercard',
subtitle: 'Wallet deposit',
amount: '+$92,705',
logo: mastercardLabel,
},
{
title: 'Stripe Account',
subtitle: 'iOS Application',
amount: '+$957',
logo: stripe,
},
{
title: 'American Bank',
subtitle: 'American Bank',
amount: '+$6,837',
logo: americanBank,
},
{
title: 'Bank Account',
subtitle: 'Wallet deposit',
amount: '+$8,934',
logo: citiBank,
},
{
title: 'Gumroad Account',
subtitle: 'Sell Admin template',
amount: '+$8,190',
logo: gumroad,
},
]
const withdraws = [
{
title: 'Google Adsense',
subtitle: 'PayPal deposit',
amount: '-$145',
logo: google,
},
{
title: 'GitHub Enterprise',
subtitle: 'Security & compliance',
amount: '-$1870',
logo: github,
},
{
title: 'Upgrade Slack Plan',
subtitle: 'Debit card deposit',
amount: '-$450',
logo: slack,
},
{
title: 'DigitalOcean',
subtitle: 'Cloud Hosting',
amount: '-$540',
logo: digitalOcean,
},
{
title: 'AWS Account',
subtitle: 'Choosing a Cloud Platform',
amount: '-$21',
logo: aws,
},
{
title: 'DigitalOcean',
subtitle: 'Cloud Hosting',
amount: '-$1030',
logo: digitalOcean,
},
]
</script>
<template>
<VCard>
<VRow no-gutters>
<VCol
cols="12"
md="6"
>
<VCardItem>
<VCardTitle>Deposit</VCardTitle>
<template #append>
<h6 class="text-h6">
<a
href="javascript:void(0)"
class="text-primary"
>View All</a>
</h6>
</template>
</VCardItem>
<VCardText>
<VList class="card-list">
<VListItem
v-for="deposit in deposits"
:key="deposit.logo"
>
<template #prepend>
<div class="me-4">
<VImg
:height="30"
:width="30"
:src="deposit.logo"
/>
</div>
</template>
<VListItemTitle class="font-weight-medium">
{{ deposit.title }}
</VListItemTitle>
<VListItemSubtitle class="text-body-1">
{{ deposit.subtitle }}
</VListItemSubtitle>
<template #append>
<VListItemAction class="text-success font-weight-medium">
{{ deposit.amount }}
</VListItemAction>
</template>
</VListItem>
</VList>
</VCardText>
</VCol>
<VDivider :vertical="$vuetify.display.mdAndUp" />
<VCol
cols="12"
md="6"
>
<VCardItem>
<VCardTitle>Withdraw</VCardTitle>
<template #append>
<h6 class="text-h6">
<a
href="javascript:void(0)"
class="text-primary"
>View All</a>
</h6>
</template>
</VCardItem>
<VCardText>
<VList class="card-list">
<VListItem
v-for="withdraw in withdraws"
:key="withdraw.logo"
>
<template #prepend>
<div class="me-4">
<VImg
:height="30"
:width="30"
:src="withdraw.logo"
/>
</div>
</template>
<VListItemTitle class="font-weight-medium">
{{ withdraw.title }}
</VListItemTitle>
<VListItemSubtitle class="text-body-1 me-1">
{{ withdraw.subtitle }}
</VListItemSubtitle>
<template #append>
<VListItemAction>
<span class="text-error font-weight-medium">
{{ withdraw.amount }}
</span>
</VListItemAction>
</template>
</VListItem>
</VList>
</VCardText>
</VCol>
</VRow>
</VCard>
</template>
<style lang="scss" scoped>
.card-list {
--v-card-list-gap: 1.25rem;
}
</style>

View File

@@ -0,0 +1,133 @@
<script setup>
import cardMeetup from '@images/cards/meetup-img.png'
const developerMeetup = [
{
icon: 'ri-time-line',
title: 'Tuesday, 24 january, 10:20 - 12:30',
subtitle: 'After 1 week',
},
{
icon: 'ri-map-pin-line',
title: 'The Richard NYC',
subtitle: '1305 Lexington Ave, New York',
},
]
</script>
<template>
<VCard>
<VImg
cover
:height="160"
:src="cardMeetup"
/>
<VCardText>
<div class="d-flex align-center pb-4">
<div class="me-4">
<VAvatar
rounded
size="58"
color="primary"
variant="tonal"
>
<div class="py-2">
<div class="text-body-1 text-primary">
Jan
</div>
<h5 class="text-h5 text-primary">
24
</h5>
</div>
</VAvatar>
</div>
<div>
<h6 class="text-h6 mb-1">
Developer Meetup
</h6>
<div class="text-body-2">
The WordPress open source,free software project is the community behind the
</div>
</div>
</div>
<VDivider />
<div class="d-flex justify-space-between align-center my-4">
<div class="text-center">
<VIcon
size="24"
icon="ri-star-smile-line"
/>
<div class="text-body-1">
Interested
</div>
</div>
<div class="text-center">
<VIcon
size="24"
icon="ri-check-double-line"
/>
<div class="text-body-1">
Joined
</div>
</div>
<div class="text-center">
<VIcon
size="24"
icon="ri-group-line"
color="primary"
/>
<div class="text-body-1 text-primary">
Invited
</div>
</div>
<div class="text-center">
<div class="mb-1">
<VIcon
size="24"
icon="ri-more-line"
/>
</div>
<span class="text-xs text-no-wrap">
More
</span>
</div>
</div>
<VDivider class="mb-4" />
<div
v-for="(meetup, index) in developerMeetup"
:key="meetup.icon"
class="d-flex align-start gap-x-2"
:class="index !== developerMeetup.length - 1 ? 'mb-2' : ''"
>
<VIcon
:icon="meetup.icon"
size="20"
/>
<div>
<div>{{ meetup.title }}</div>
<div>{{ meetup.subtitle }}</div>
</div>
</div>
</VCardText>
</VCard>
</template>
<style lang="scss">
.text-two-line-ellipsis {
/* stylelint-disable-next-line value-no-vendor-prefix */
display: -webkit-box;
overflow: hidden;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
text-overflow: ellipsis;
}
</style>

View File

@@ -0,0 +1,110 @@
<script setup>
import avatar6 from '@images/avatars/avatar-6.png'
import avatar7 from '@images/avatars/avatar-7.png'
import avatar8 from '@images/avatars/avatar-8.png'
</script>
<template>
<VCard>
<VCardItem>
<VCardTitle>Finance Summary</VCardTitle>
<VCardSubtitle>Check out each Column for more details</VCardSubtitle>
<template #append>
<VAvatar
size="44"
color="primary"
variant="tonal"
>
<VIcon
size="28"
icon="ri-question-line"
/>
</VAvatar>
</template>
</VCardItem>
<VCardText>
<div class="d-flex flex-column gap-y-6">
<div class="d-flex flex-wrap gap-y-4">
<div style="min-inline-size: 210px;">
<div class="mb-1">
Annual Companies Taxes
</div>
<h5 class="text-h5">
$1450.35
</h5>
</div>
<div>
<div class="mb-1">
Next Tax Review Date
</div>
<h5 class="text-h5">
July 14, 2021
</h5>
</div>
</div>
<div class="d-flex flex-wrap gap-y-4">
<div style="min-inline-size: 210px;">
<div class="mb-1">
Average Product Price
</div>
<h5 class="text-h5">
$85.50
</h5>
</div>
<div>
<div class="mb-1">
Satisfaction Rate
</div>
<div
class="d-flex align-center gap-5"
style="inline-size: 130px;"
>
<div class="flex-grow-1">
<VProgressLinear
color="primary"
rounded
rounded-bar
:model-value="75"
:height="6"
/>
</div>
<span>75%</span>
</div>
</div>
</div>
<div class="d-flex justify-space-between align-center">
<div class="v-avatar-group">
<VAvatar
:size="40"
:image="avatar7"
/>
<VAvatar
:size="40"
:image="avatar8"
/>
<VAvatar
:size="40"
:image="avatar6"
/>
<VAvatar
:color="$vuetify.theme.current.dark ? '#3A3B59' : '#F0EFF0'"
:size="40"
>
+3
</VAvatar>
</div>
<VChip
color="primary"
size="small"
>
5 days Ago
</VChip>
</div>
</div>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,128 @@
<script setup>
import avatar1 from '@images/avatars/avatar-1.png'
import avatar2 from '@images/avatars/avatar-2.png'
import avatar3 from '@images/avatars/avatar-3.png'
import avatar4 from '@images/avatars/avatar-4.png'
import avatar7 from '@images/avatars/avatar-7.png'
import avatar8 from '@images/avatars/avatar-8.png'
const meetingSchedules = [
{
profile: avatar4,
with: 'Call with Woods',
dateTime: '21 Jul | 08:20-10:30',
type: 'Business',
},
{
profile: avatar8,
with: 'Call with hilda',
dateTime: '24 Jul | 11:30-12:00',
type: 'Meditation',
},
{
profile: avatar7,
with: 'Conference call',
dateTime: '28 Jul | 05:00-6:45',
type: 'Dinner',
},
{
profile: avatar3,
with: 'Meeting with Mark',
dateTime: '03 Aug | 07:00-8:30',
type: 'Meetup',
},
{
profile: avatar2,
with: 'Meeting in Oakland',
dateTime: '14 Aug | 04:15-05:30',
type: 'Dinner',
},
{
profile: avatar1,
with: 'Meeting with Carl',
dateTime: '05 Oct | 10:00-12:45',
type: 'Business',
},
]
const meetingTypeUiColors = {
Business: 'primary',
Meditation: 'success',
Meetup: 'secondary',
Dinner: 'error',
}
</script>
<template>
<VCard>
<!-- SECTION Card Header and Menu -->
<VCardItem>
<!-- 👉 Title -->
<VCardTitle>Meeting Schedule</VCardTitle>
<!-- 👉 menu -->
<template #append>
<div class="me-n3">
<MoreBtn />
</div>
</template>
</VCardItem>
<!-- !SECTION -->
<!-- SECTION Meting Schedule -->
<VCardText>
<VList
lines="two"
class="card-list"
>
<VListItem
v-for="meeting in meetingSchedules"
:key="meeting.type"
>
<!-- 👉 Avatar -->
<template #prepend>
<VAvatar
start
:size="38"
:image="meeting.profile"
/>
</template>
<!-- 👉 Title and Subtitle -->
<VListItemTitle class="font-weight-medium mb-1">
{{ meeting.with }}
</VListItemTitle>
<VListItemSubtitle class="me-2">
<VIcon
size="16"
start
icon="ri-calendar-line"
/>
{{ meeting.dateTime }}
</VListItemSubtitle>
<!-- 👉 Business Types -->
<template #append>
<VListItemAction>
<VChip
size="small"
:color="meetingTypeUiColors[meeting.type]"
>
{{ meeting.type }}
</VChip>
</VListItemAction>
</template>
</VListItem>
</VList>
</VCardText>
<!-- !SECTION -->
</VCard>
</template>
<style lang="scss" scoped>
.card-list {
--v-card-list-gap: 1.5rem;
}
</style>

View File

@@ -0,0 +1,125 @@
<script setup>
const salesByCountries = [
{
abbr: 'US',
amount: '$8,656k',
country: 'United states of america',
change: '+25.8%',
sales: '894k',
color: 'success',
},
{
abbr: 'UK',
amount: '$2,415k',
country: 'United kingdom',
change: '-6.2%',
sales: '645k',
color: 'error',
},
{
abbr: 'IN',
amount: '$865k',
country: 'India',
change: '+12.4%',
sales: '148k',
color: 'warning',
},
{
abbr: 'JA',
amount: '$745k',
country: 'Japan',
change: '-11.9%',
sales: '86k',
color: 'secondary',
},
{
abbr: 'KO',
amount: '$45k',
country: 'Korea',
change: '+16.2%',
sales: '42k',
color: 'error',
},
{
abbr: 'CH',
amount: '$12k',
country: 'China',
change: '+14.8%',
sales: '8k',
color: 'info',
},
]
</script>
<template>
<VCard>
<VCardItem>
<VCardTitle>Sales by Countries</VCardTitle>
<template #append>
<div class="me-n3">
<MoreBtn />
</div>
</template>
</VCardItem>
<VCardText>
<VList class="card-list">
<VListItem
v-for="data in salesByCountries"
:key="data.country"
>
<template #prepend>
<VAvatar
:color="data.color"
variant="tonal"
size="40"
>
{{ data.abbr }}
</VAvatar>
</template>
<VListItemTitle class="mb-1 d-flex align-center">
<h6 class="text-h6">
{{ data.amount }}
</h6>
<VIcon
size="24"
:color="data.change.charAt(0) === '+' ? 'success' : 'error'"
class="mx-1"
>
{{ data.change.charAt(0) === '+' ? 'ri-arrow-up-s-line' : 'ri-arrow-down-s-line' }}
</VIcon>
<div
:class="`${data.change.charAt(0) === '+' ? 'text-success' : 'text-error'}`"
class="text-body-1"
>
{{ data.change.slice(1) }}
</div>
</VListItemTitle>
<VListItemSubtitle class="text-body-1 me-2">
{{ data.country }}
</VListItemSubtitle>
<template #append>
<div>
<h6 class="text-h6 mb-1">
{{ data.sales }}
</h6>
<div class="text-body-2 text-disabled">
Sales
</div>
</div>
</template>
</VListItem>
</VList>
</VCardText>
</VCard>
</template>
<style lang="scss" scoped>
.card-list {
--v-card-list-gap: 1.5rem;
}
</style>

View File

@@ -0,0 +1,215 @@
<script setup>
import avatar1 from '@images/avatars/avatar-1.png'
import avatar2 from '@images/avatars/avatar-2.png'
import avatar3 from '@images/avatars/avatar-3.png'
import avatar5 from '@images/avatars/avatar-5.png'
import avatar8 from '@images/avatars/avatar-8.png'
const teamMembers = [
{
profilePic: avatar1,
name: 'Dean Hogan',
designation: 'IOS developer',
project: 'Zipper',
projectIndication: 'primary',
task: '87/135',
progress: 65,
},
{
profilePic: avatar8,
name: 'Hilda Rice',
designation: 'Laravel developer',
project: 'Brandi',
projectIndication: 'success',
task: '340/420',
progress: 75,
},
{
profilePic: avatar5,
name: 'Andrew O\'Brien',
designation: 'React developer',
project: 'Payers',
projectIndication: 'warning',
task: '50/82',
progress: 55,
},
{
profilePic: avatar2,
name: 'Eleanor Price',
designation: 'Angular developer',
project: 'Citibank',
projectIndication: 'error',
task: '98/260',
progress: 60,
},
{
profilePic: avatar3,
name: 'Carl Oliver',
designation: 'VueJs developer',
project: 'Aviator',
projectIndication: 'secondary',
task: '12/25',
progress: 60,
},
]
</script>
<template>
<VCard>
<!-- SECTION Card Header and Menu -->
<VCardItem>
<!-- 👉 Title -->
<VCardTitle>Team Members</VCardTitle>
<!-- 👉 menu -->
<template #append>
<div class="me-n3">
<MoreBtn />
</div>
</template>
</VCardItem>
<!-- !SECTION -->
<!-- TODO try to remove table border -->
<VTable class="text-no-wrap team-members-table">
<thead>
<tr>
<th scope="col">
Name
</th>
<th scope="col">
Project
</th>
<th scope="col">
Tasks
</th>
<th scope="col">
Progress
</th>
</tr>
</thead>
<tbody>
<tr
v-for="member in teamMembers"
:key="member.name"
>
<td>
<div class="d-flex align-center">
<div class="me-3">
<VAvatar
size="38"
:image="member.profilePic"
/>
</div>
<div>
<h6 class="text-h6">
{{ member.name }}
</h6>
<div class="text-body-1">
{{ member.designation }}
</div>
</div>
</div>
</td>
<td>
<VChip
:color="member.projectIndication"
size="small"
>
{{ member.project }}
</VChip>
</td>
<td>
<div class="d-flex font-weight-medium">
<div class="text-primary">
{{ member.task.split('/')[0] }}
</div>
<div class="text-primary">
/
</div>
<h6 class="text-h6 text-medium-emphasis">
{{ member.task.split('/')[1] }}
</h6>
</div>
</td>
<td class="text-center">
<VProgressCircular
:color="member.projectIndication"
:model-value="member.progress"
/>
</td>
</tr>
</tbody>
</VTable>
</VCard>
</template>
<style lang="scss">
.team-members-table {
&.v-table{
--v-table-header-height: 2rem;
.v-table__wrapper{
table{
thead{
tr{
th{
background: none !important;
border-block-end: 1px solid rgba(var(--v-border-color), var(--v-border-opacity)) !important;
margin-block-end: 0.75rem !important;
&:first-child{
padding-inline-start: 1.25rem;
}
&:last-child{
padding-inline-end: 1.25rem;
}
}
}
}
tbody{
tr{
td{
padding-block: 0.5rem;
padding-inline: 1rem;
&:first-child{
padding-inline-start: 1.25rem;
}
&:last-child{
padding-inline-end: 1.25rem;
}
}
&:not(:last-child){
td{
border-block-end: none ;
}
}
&:last-child{
td{
padding-block-end: 1.25rem;
}
}
&:first-child{
td{
padding-block-start: 1.25rem;
}
}
}
}
}
}
}
}
</style>

View File

@@ -0,0 +1,99 @@
<script setup>
import aviato from '@images/logos/aviato.png'
import bitbank from '@images/logos/bitbank.png'
import zipcar from '@images/logos/zipcar.png'
const earnings = [
{
avatar: zipcar,
title: 'Zipcar',
subtitle: 'Vuejs, React & HTML',
amount: '$24,895.65',
progress: 'primary',
},
{
avatar: bitbank,
title: 'Bitbank',
subtitle: 'Sketch, Figma & XD',
amount: '$8,6500.20',
progress: 'info',
},
{
avatar: aviato,
title: 'Aviato',
subtitle: 'HTML & Anguler',
amount: '$1,2450.80',
progress: 'secondary',
},
]
</script>
<template>
<VCard>
<VCardItem>
<VCardTitle>Total Earning</VCardTitle>
<template #append>
<div class="me-n3">
<MoreBtn />
</div>
</template>
</VCardItem>
<VCardText>
<div class="d-flex align-center">
<h3 class="text-h3">
$24,895
</h3>
<VIcon
size="24"
icon="ri-arrow-up-s-line"
color="success"
/>
<div class="text-success">
10%
</div>
</div>
<div class="text-body-1 mb-6">
Compared to $84,325 last year
</div>
<VList class="card-list">
<VListItem
v-for="earning in earnings"
:key="earning.title"
>
<template #prepend>
<VAvatar
rounded
:image="earning.avatar"
variant="tonal"
/>
</template>
<VListItemTitle class="font-weight-medium">
{{ earning.title }}
</VListItemTitle>
<VListItemSubtitle class="text-body-1">
{{ earning.subtitle }}
</VListItemSubtitle>
<template #append>
<div>
<h6 class="text-h6 mb-2">
{{ earning.amount }}
</h6>
<VProgressLinear
:color="earning.progress"
model-value="80"
rounded
rounded-bar
/>
</div>
</template>
</VListItem>
</VList>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,140 @@
<script setup>
import { kFormatter } from '@core/utils/formatters'
import arrowGrowth from '@images/cards/arrow-growth.png'
import atmCard from '@images/cards/atm-card.png'
import creditCard from '@images/cards/credit-card.png'
import paypal from '@images/cards/paypal.png'
import wallet from '@images/cards/wallet.png'
const transactions = [
{
gateway: 'PayPal',
for: 'Received Money',
amount: 2482,
img: paypal,
imgHeight: 22,
},
{
gateway: 'Credit Card',
for: 'DigitalOcean',
amount: -1250,
img: creditCard,
imgHeight: 15,
},
{
gateway: 'Mastercard',
for: 'Netflix',
amount: -99,
img: atmCard,
imgHeight: 15,
},
{
gateway: 'Wallet',
for: 'Mac\'D',
amount: -82,
img: wallet,
imgHeight: 18,
},
{
gateway: 'Transfer',
for: 'Refund',
amount: 8934,
img: arrowGrowth,
imgHeight: 12,
},
{
gateway: 'Wallet',
for: 'Buy Apple Watch',
amount: -399,
img: wallet,
imgHeight: 18,
},
]
const transactionsColors = {
'PayPal': 'error',
'Credit Card': 'success',
'Mastercard': 'warning',
'Wallet': 'primary',
'Transfer': 'info',
}
const formateAmount = amount => {
return Math.sign(amount) === 1 ? `+${ kFormatter(amount) }` : `-${ Math.abs(amount) }`
}
</script>
<template>
<VCard>
<!-- SECTION Card Header and Menu -->
<VCardItem>
<!-- 👉 Title -->
<VCardTitle>Transactions</VCardTitle>
<!-- 👉 menu -->
<template #append>
<div class="me-n3">
<MoreBtn />
</div>
</template>
</VCardItem>
<!-- !SECTION -->
<!-- SECTION Transactions List -->
<VCardText>
<VList class="card-list">
<VListItem
v-for="transaction in transactions"
:key="transaction.for"
>
<!-- 👉 Avatar -->
<template #prepend>
<VAvatar
rounded
variant="tonal"
:color="transactionsColors[transaction.gateway]"
>
<img
:src="transaction.img"
:height="transaction.imgHeight"
>
</VAvatar>
</template>
<!-- 👉 Title and Subtitle -->
<VListItemTitle>
<h6 class="text-h6">
{{ transaction.gateway }}
</h6>
</VListItemTitle>
<VListItemSubtitle>
<div class="text-body-1 me-2">
{{ transaction.for }}
</div>
</VListItemSubtitle>
<!-- 👉 Amounts -->
<template #append>
<VListItemAction>
<h6 class="text-h6 me-2">
{{ formateAmount(transaction.amount) }}
</h6>
<VIcon
:size="24"
:color="Math.sign(transaction.amount) === 1 ? 'success' : 'error'"
:icon="Math.sign(transaction.amount) === 1 ? 'ri-arrow-up-s-line' : 'ri-arrow-down-s-line'"
/>
</VListItemAction>
</template>
</VListItem>
</VList>
</VCardText>
<!-- !SECTION -->
</VCard>
</template>
<style lang="scss" scoped>
.card-list {
--v-card-list-gap: 1.5rem;
}
</style>

View File

@@ -0,0 +1,157 @@
<script setup>
import briefcase from '@images/cards/briefcase.png'
import logoCreditCard2 from '@images/cards/logo-credit-card-2.png'
import logoMastercardSmall from '@images/cards/logo-mastercard-small.png'
const savedCards = [
{
logo: logoMastercardSmall,
type: 'Credit card',
number: '2566 xxxx xxxx 8908',
},
{
logo: logoCreditCard2,
type: 'Credit card',
number: '8990 xxxx xxxx 6852',
},
]
</script>
<template>
<VCard>
<!-- SECTION Card Header and Menu -->
<VCardItem>
<!-- 👉 Title -->
<VCardTitle>Upgrade Your Plan</VCardTitle>
<!-- 👉 menu -->
<template #append>
<div class="me-n3">
<MoreBtn />
</div>
</template>
</VCardItem>
<!-- !SECTION -->
<VCardText>
<p class="text-body-2">
Please make the payment to start enjoying all the features of our premium plan as soon as possible.
</p>
<!-- SECTION Upgrade plan banner -->
<div class="plan-upgrade-banner pa-4 d-flex rounded align-center">
<VAvatar
rounded
size="40"
class="plan-details me-2 border-opacity-100 border-primary"
>
<VImg
:src="briefcase"
alt="briefcase"
height="20"
/>
</VAvatar>
<div class="d-flex flex-column">
<h6 class="text-h6">
Platinum
</h6>
<span class="text-primary text-body-2">Upgrade Plan</span>
</div>
<VSpacer />
<div class="d-flex align-center">
<sup>
<div class="text-body-2 text-high-emphasis">$</div>
</sup>
<h4 class="text-h4">
5250
</h4>
<sub>
<div class="text-body-2 text-high-emphasis">/Year</div>
</sub>
</div>
</div>
<!-- !SECTION -->
<!-- SECTION Payment Details -->
<VList class="card-list mt-1">
<h6 class="text-h6 my-2">
Payment details
</h6>
<VListItem
v-for="card in savedCards"
:key="card.logo"
class="mb-2"
>
<!-- 👉 Avatar -->
<template #prepend>
<img
:src="card.logo"
height="30"
width="42"
class="me-3"
>
</template>
<!-- 👉 Title and Subtitle -->
<VListItemTitle class="font-weight-medium mb-1">
{{ card.type }}
</VListItemTitle>
<VListItemSubtitle class="me-2">
{{ card.number }}
</VListItemSubtitle>
<!-- 👉 Action -->
<template #append>
<VListItemAction>
<VTextField
density="compact"
label="CVV"
placeholder="123"
style="inline-size: 5rem;"
/>
</VListItemAction>
</template>
</VListItem>
<!-- 👉 Add Payment -->
<VListItem class="mb-3 text-body-1">
<a href="javascript:void(0)">Add Payment Method</a>
</VListItem>
</VList>
<!-- !SECTION -->
<!-- 👉 Email -->
<VForm>
<VRow>
<VCol cols="12">
<VTextField
placeholder="Email Address"
density="compact"
class="mb-3"
/>
<VBtn block>
Contact Now
</VBtn>
</VCol>
</VRow>
</VForm>
</VCardText>
</VCard>
</template>
<style lang="scss" scoped>
.plan-upgrade-banner {
.plan-details {
border: 1px solid rgb(var(--v-theme-primary));
}
background-color: rgba(var(--v-theme-primary), 0.16);
}
.card-list {
--v-card-list-gap: 0;
}
</style>

View File

@@ -0,0 +1,155 @@
<script setup>
const chartOptions = {
chart: {
type: 'bar',
parentHeightOffset: 0,
toolbar: { show: false },
sparkline: { enabled: true },
},
grid: { show: false },
colors: ['rgba(var(--v-theme-primary))'],
plotOptions: {
bar: {
barHeight: '85%',
columnWidth: '35px',
borderRadius: 3,
distributed: true,
},
},
legend: { show: false },
dataLabels: { enabled: false },
xaxis: {
labels: { show: false },
axisBorder: { show: false },
axisTicks: { show: false },
},
yaxis: { show: false },
tooltip: { enabled: false },
}
const series = [{
name: '2020',
data: [
50,
40,
110,
80,
40,
60,
40,
],
}]
const websiteStatistics = [
{
title: 'Direct',
color: 'success',
traffic: '86,471',
percentage: '-15',
},
{
title: 'Organic Search',
color: 'primary',
traffic: '57,484',
percentage: '+85',
},
{
title: 'Referral',
color: 'warning',
traffic: '2,534',
percentage: '+48',
},
{
title: 'Mail',
color: 'error',
traffic: '977',
percentage: '-36',
},
{
title: 'Social',
color: 'info',
traffic: '92',
percentage: '+55',
},
{
title: 'Other',
color: 'secondary',
traffic: '28',
percentage: '+12',
},
]
</script>
<template>
<VCard>
<VCardItem>
<VCardTitle>Transactions</VCardTitle>
<template #append>
<div class="me-n3">
<MoreBtn />
</div>
</template>
</VCardItem>
<VCardText class="pt-3">
<div class="d-flex align-center justify-space-between mb-5">
<div>
<h1 class="text-h1 mb-2">
4,590
</h1>
<div class="text-body-2">
Total Traffic
</div>
</div>
<div>
<VueApexCharts
:options="chartOptions"
:series="series"
height="80"
width="120"
/>
</div>
</div>
<div
v-for="(data, index) in websiteStatistics"
:key="data.title"
>
<div class="d-flex py-3 align-center">
<div
class="bubble"
:class="`bg-${data.color}`"
/>
<div class="text-body-1 text-high-emphasis">
{{ data.title }}
</div>
<VSpacer />
<h6 class="text-h6 me-6">
{{ data.traffic }}
</h6>
<h6 class="text-h6 me-1">
{{ data.percentage.slice(1) }}%
</h6>
<VIcon
:size="24"
:color="data.percentage.charAt(0) === '+' ? 'success' : 'error'"
>
{{ data.percentage.charAt(0) === '+' ? 'ri-arrow-up-s-line' : 'ri-arrow-down-s-line' }}
</VIcon>
</div>
<VDivider v-if="index !== websiteStatistics.length - 1" />
</div>
</VCardText>
</VCard>
</template>
<style lang="scss" scoped>
.bubble {
border-radius: 50%;
block-size: 1rem;
inline-size: 1rem;
margin-inline-end: 0.5rem;
}
</style>

View File

@@ -0,0 +1,86 @@
<script setup>
const assignmentData = [
{
title: 'User Experience Design',
tasks: 120,
progress: 72,
color: 'primary',
},
{
title: 'Basic fundamentals',
tasks: 32,
progress: 48,
color: 'success',
},
{
title: 'React Native components',
tasks: 182,
progress: 15,
color: 'error',
},
{
title: 'Basic of music theory',
tasks: 56,
progress: 24,
color: 'info',
},
]
</script>
<template>
<VCard>
<VCardItem title="Assignment progress">
<template #append>
<MoreBtn />
</template>
</VCardItem>
<VCardText>
<VList class="card-list">
<VListItem
v-for="assignment in assignmentData"
:key="assignment.title"
>
<template #prepend>
<VProgressCircular
v-model="assignment.progress"
:size="54"
class="me-4"
:color="assignment.color"
>
<h6 class="text-h6">
{{ assignment.progress }}%
</h6>
</VProgressCircular>
</template>
<template #title>
<div class="text-h6 me-4 mb-2 text-truncate">
{{ assignment.title }}
</div>
</template>
<VListItemSubtitle>{{ assignment.tasks }} Tasks</VListItemSubtitle>
<template #append>
<VBtn
variant="tonal"
color="secondary"
class="rounded"
size="34"
>
<VIcon
icon="ri-arrow-right-s-line"
size="20"
class="flip-in-rtl"
/>
</VBtn>
</template>
</VListItem>
</VList>
</VCardText>
</VCard>
</template>
<style lang="scss" scoped>
.card-list {
--v-card-list-gap: 1.5rem;
}
</style>

View File

@@ -0,0 +1,103 @@
<script setup>
const deliveryData = [
{
title: 'Packages in transit',
value: '10k',
change: 25.8,
icon: 'ri-gift-line',
color: 'primary',
},
{
title: 'Packages out for delivery',
value: '5k',
change: 4.3,
icon: 'ri-car-line',
color: 'info',
},
{
title: 'Packages delivered',
value: '15k',
change: -12.5,
icon: 'ri-check-line',
color: 'success',
},
{
title: 'Delivery success rate',
value: '95%',
change: 35.6,
icon: 'ri-home-line',
color: 'warning',
},
{
title: 'Average delivery time',
value: '2.5 Days',
change: -2.15,
icon: 'ri-timer-line',
color: 'secondary',
},
{
title: 'Customer satisfaction',
value: '4.5/5',
change: 5.7,
icon: 'ri-user-line',
color: 'error',
},
]
</script>
<template>
<VCard>
<VCardItem
title="Delivery performance"
subtitle="12% increase in this month"
>
<template #append>
<MoreBtn class="mt-n5" />
</template>
</VCardItem>
<VCardText>
<VList class="card-list">
<VListItem
v-for="(data, index) in deliveryData"
:key="index"
>
<template #prepend>
<VAvatar
:color="data.color"
variant="tonal"
rounded
size="42"
>
<VIcon
:icon="data.icon"
size="26"
/>
</VAvatar>
</template>
<VListItemTitle class="me-1">
{{ data.title }}
</VListItemTitle>
<VListItemSubtitle>
<div
:class="data.change > 0 ? 'text-success' : 'text-error'"
class="d-flex align-center"
>
<VIcon
:icon="data.change > 0 ? 'ri-arrow-up-s-line' : 'ri-arrow-down-s-line'"
size="24"
class="me-1"
/>
<span>{{ data.change }}%</span>
</div>
</VListItemSubtitle>
<template #append>
<span class="text-high-emphasis text-body-1 font-weight-medium">
{{ data.value }}
</span>
</template>
</VListItem>
</VList>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,347 @@
<script setup>
const currentTab = ref('New')
const tabsData = [
'New',
'Preparing',
'Shipping',
]
</script>
<template>
<VCard>
<VCardItem
title="Orders by countries"
subtitle="62 deliveries in progress"
>
<template #append>
<MoreBtn class="mt-n5" />
</template>
</VCardItem>
<VTabs
v-model="currentTab"
grow
class="disable-tab-transition"
>
<VTab
v-for="(tab, index) in tabsData"
:key="index"
>
{{ tab }}
</VTab>
</VTabs>
<VCardText>
<VWindow v-model="currentTab">
<VWindowItem>
<div>
<VTimeline
align="start"
truncate-line="both"
side="end"
density="compact"
line-thickness="1"
class="v-timeline--variant-outlined"
>
<VTimelineItem
icon="ri-checkbox-circle-line"
dot-color="rgba(var(--v-theme-surface))"
icon-color="success"
fill-dot
size="20"
:elevation="0"
>
<div class="text-caption text-uppercase text-success">
Sender
</div>
<div class="app-timeline-title">
Myrtle Ullrich
</div>
<div class="text-body-2 mb-1">
101 Boulder, California(CA), 95959
</div>
</VTimelineItem>
<VTimelineItem
icon="ri-map-pin-line"
dot-color="rgba(var(--v-theme-surface))"
icon-color="primary"
fill-dot
size="20"
:elevation="0"
>
<div class="text-caption text-primary text-uppercase">
Receiver
</div>
<div class="app-timeline-title">
Barry Schowalter
</div>
<div class="text-body-2">
939 Orange, California(CA), 92118
</div>
</VTimelineItem>
</VTimeline>
<VDivider
class="my-4"
style="border-style: dashed;"
/>
<VTimeline
align="start"
truncate-line="both"
side="end"
density="compact"
line-thickness="1"
class="v-timeline--variant-outlined"
>
<VTimelineItem
icon="ri-checkbox-circle-line"
dot-color="rgba(var(--v-theme-surface))"
icon-color="success"
fill-dot
size="20"
:elevation="0"
>
<div class="text-caption text-uppercase text-success">
Sender
</div>
<div class="app-timeline-title">
Veronica Herman
</div>
<div class="text-body-2 mb-1">
162 Windsor, California(CA), 95492
</div>
</VTimelineItem>
<VTimelineItem
icon="ri-map-pin-line"
dot-color="rgba(var(--v-theme-surface))"
icon-color="primary"
fill-dot
size="20"
:elevation="0"
>
<div class="text-caption text-primary text-uppercase">
Receiver
</div>
<div class="app-timeline-title">
Helen Jacobs
</div>
<div class="text-body-2">
487 Sunset, California(CA), 94043
</div>
</VTimelineItem>
</VTimeline>
</div>
</VWindowItem>
<VWindowItem>
<div>
<VTimeline
align="start"
truncate-line="both"
side="end"
density="compact"
line-thickness="1"
class="v-timeline--variant-outlined"
>
<VTimelineItem
icon="ri-checkbox-circle-line"
dot-color="rgba(var(--v-theme-surface))"
icon-color="success"
fill-dot
size="20"
:elevation="0"
>
<div class="text-caption text-uppercase text-success">
Sender
</div>
<div class="app-timeline-title">
Barry Schowalter
</div>
<div class="text-body-2">
939 Orange, California(CA), 92118
</div>
</VTimelineItem>
<VTimelineItem
icon="ri-map-pin-line"
dot-color="rgba(var(--v-theme-surface))"
icon-color="primary"
fill-dot
size="20"
:elevation="0"
>
<div class="text-caption text-primary text-uppercase">
Receiver
</div>
<div class="app-timeline-title">
Myrtle Ullrich
</div>
<div class="text-body-2">
101 Boulder, California(CA), 95959
</div>
</VTimelineItem>
</VTimeline>
<VDivider
class="my-4"
style="border-style: dashed;"
/>
<VTimeline
align="start"
truncate-line="both"
side="end"
density="compact"
line-thickness="1"
class="v-timeline--variant-outlined"
>
<VTimelineItem
icon="ri-checkbox-circle-line"
dot-color="rgba(var(--v-theme-surface))"
icon-color="success"
fill-dot
size="20"
:elevation="0"
>
<div class="text-caption text-uppercase text-success">
Sender
</div>
<div class="app-timeline-title">
Veronica Herman
</div>
<div class="text-body-2">
162 Windsor, California(CA), 95492
</div>
</VTimelineItem>
<VTimelineItem
icon="ri-map-pin-line"
dot-color="rgba(var(--v-theme-surface))"
icon-color="primary"
fill-dot
size="20"
:elevation="0"
>
<div class="text-caption text-primary text-uppercase">
Receiver
</div>
<div class="app-timeline-title">
Helen Jacobs
</div>
<div class="text-body-2">
487 Sunset, California(CA), 94043
</div>
</VTimelineItem>
</VTimeline>
</div>
</VWindowItem>
<VWindowItem>
<div>
<VTimeline
align="start"
truncate-line="both"
side="end"
density="compact"
line-thickness="1"
class="v-timeline--variant-outlined"
>
<VTimelineItem
icon="ri-checkbox-circle-line"
dot-color="rgba(var(--v-theme-surface))"
icon-color="success"
fill-dot
size="20"
:elevation="0"
>
<div class="text-caption text-uppercase text-success">
Sender
</div>
<div class="app-timeline-title">
Myrtle Ullrich
</div>
<div class="text-body-2">
101 Boulder, California(CA), 95959
</div>
</VTimelineItem>
<VTimelineItem
icon="ri-map-pin-line"
dot-color="rgba(var(--v-theme-surface))"
icon-color="primary"
fill-dot
size="20"
:elevation="0"
>
<div class="text-caption text-primary text-uppercase">
Receiver
</div>
<div class="app-timeline-title">
Barry Schowalter
</div>
<div class="text-body-2">
939 Orange, California(CA), 92118
</div>
</VTimelineItem>
</VTimeline>
<VDivider
class="my-4"
style="border-style: dashed;"
/>
<VTimeline
align="start"
truncate-line="both"
side="end"
density="compact"
line-thickness="1"
class="v-timeline--variant-outlined"
>
<VTimelineItem
icon="ri-checkbox-circle-line"
dot-color="rgba(var(--v-theme-surface))"
icon-color="success"
fill-dot
size="20"
:elevation="0"
>
<div class="text-caption text-uppercase text-success">
Sender
</div>
<div class="app-timeline-title">
Veronica Herman
</div>
<div class="text-body-2">
162 Windsor, California(CA), 95492
</div>
</VTimelineItem>
<VTimelineItem
icon="ri-map-pin-line"
dot-color="rgba(var(--v-theme-surface))"
icon-color="primary"
fill-dot
size="20"
:elevation="0"
>
<div class="text-caption text-primary text-uppercase">
Receiver
</div>
<div class="app-timeline-title">
Helen Jacobs
</div>
<div class="text-body-2">
487 Sunset, California(CA), 94043
</div>
</VTimelineItem>
</VTimeline>
</div>
</VWindowItem>
</VWindow>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,66 @@
<script setup>
import avatar1 from '@images/avatars/avatar-1.png'
import avatar2 from '@images/avatars/avatar-2.png'
import avatar3 from '@images/avatars/avatar-3.png'
import avatar4 from '@images/avatars/avatar-4.png'
import avatar5 from '@images/avatars/avatar-5.png'
import avatar6 from '@images/avatars/avatar-6.png'
</script>
<template>
<VCard>
<VCardItem title="Popular Instructors">
<template #append>
<MoreBtn />
</template>
</VCardItem>
<VDivider />
<div class="text-overline d-flex justify-space-between px-5 py-4">
<div>instructors</div>
<div>Courses</div>
</div>
<VDivider />
<VCardText>
<VList class="card-list">
<VListItem
v-for="instructor in [
{ name: 'Jordan Stevenson', profession: 'Business Intelligence', totalCourses: 33, avatar: avatar1 },
{ name: 'Bentlee Emblin', profession: 'Digital Marketing', totalCourses: 52, avatar: avatar2 },
{ name: 'Benedetto Rossiter', profession: 'UI/UX Design', totalCourses: 12, avatar: avatar3 },
{ name: 'Beverlie Krabbe', profession: 'Vue', totalCourses: 8, avatar: avatar4 },
{ name: 'Benette Rose', profession: 'React', totalCourses: 20, avatar: avatar5 },
{ name: 'John Doe', profession: 'Public speaking', totalCourses: 30, avatar: avatar6 },
]"
:key="instructor.name"
>
<template #prepend>
<VAvatar
size="34"
:image="instructor.avatar"
/>
</template>
<h6 class="text-h6">
{{ instructor.name }}
</h6>
<div class="text-caption text-medium-emphasis">
{{ instructor.profession }}
</div>
<template #append>
<h6 class="text-h6">
{{ instructor.totalCourses }}
</h6>
</template>
</VListItem>
</VList>
</VCardText>
</VCard>
</template>
<style lang="scss" scoped>
.card-list{
--v-card-list-gap: 16px;
}
</style>

View File

@@ -0,0 +1,81 @@
<script setup>
const coursesData = [
{
title: 'Videography Basic Design Course',
views: '1.2k',
icon: 'ri-video-download-line',
color: 'primary',
},
{
title: 'Basic Front-end Development Course',
views: '834',
icon: 'ri-code-view',
color: 'info',
},
{
title: 'Basic Fundamentals of Photography',
views: '3.7k',
icon: 'ri-image-2-line',
color: 'success',
},
{
title: 'Advance Dribble Base Visual Design',
views: '2.5k',
icon: 'ri-palette-line',
color: 'warning',
},
{
title: 'Your First Singing Lesson',
views: '948',
icon: 'ri-music-2-line',
color: 'error',
},
]
</script>
<template>
<VCard>
<VCardItem title="Top Courses">
<template #append>
<MoreBtn />
</template>
</VCardItem>
<VCardText>
<VList class="card-list">
<VListItem
v-for="(course, index) in coursesData"
:key="index"
>
<template #prepend>
<VAvatar
rounded
variant="tonal"
:color="course.color"
>
<VIcon
:icon="course.icon"
size="24"
/>
</VAvatar>
</template>
<template #title>
<div class="text-h6 clamp-text text-wrap me-4">
{{ course.title }}
</div>
</template>
<template #append>
<VChip
variant="tonal"
size="small"
>
{{ course.views }} Views
</VChip>
</template>
</VListItem>
</VList>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,51 @@
<script setup>
import girlWithLaptop from '@images/pages/pose-fs-9.png'
</script>
<template>
<VCard>
<VCardText>
<div class="d-flex justify-center align-start pb-0 px-3 pt-3 mb-4 bg-light-primary rounded">
<VImg
:src="girlWithLaptop"
width="145"
height="140"
/>
</div>
<div>
<h5 class="text-h5 mb-2">
Upcoming Webinar
</h5>
<div class="text-body-1">
Next Generation Frontend Architecture Using Layout Engine And Vue.
</div>
<div class="d-flex justify-space-between my-4 gap-4 flex-wrap">
<div
v-for="{ icon, title, value } in [{ icon: 'ri-calendar-line', title: '17 Nov 23', value: 'Date' }, { icon: 'ri-time-line', title: '32 Minutes', value: 'Duration' }]"
:key="title"
class="d-flex gap-x-4 align-center"
>
<VAvatar
color="primary"
variant="tonal"
rounded
>
<VIcon :icon="icon" />
</VAvatar>
<div>
<h6 class="text-h6">
{{ title }}
</h6>
<div class="text-body-1">
{{ value }}
</div>
</div>
</div>
</div>
<VBtn block>
Join the event
</VBtn>
</div>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,473 @@
<script setup>
import avatar1 from '@images/avatars/avatar-1.png'
import avatar2 from '@images/avatars/avatar-2.png'
import avatar3 from '@images/avatars/avatar-3.png'
import avatar4 from '@images/avatars/avatar-4.png'
import eCommerce2 from '@images/eCommerce/2.png'
import pages1 from '@images/pages/1.png'
import pages2 from '@images/pages/2.png'
import pages3 from '@images/pages/3.png'
import pages5 from '@images/pages/5.jpg'
import pages6 from '@images/pages/6.jpg'
const avatars = [
avatar1,
avatar2,
avatar3,
avatar4,
]
const isCardDetailsVisible = ref(false)
</script>
<template>
<VRow>
<!-- 👉 Influencing The Influencer -->
<VCol
cols="12"
sm="6"
md="4"
>
<VCard>
<VImg
:src="pages1"
cover
/>
<VCardItem>
<VCardTitle>Influencing The Influencer</VCardTitle>
</VCardItem>
<VCardText>
Cancun is back, better than ever! Over a hundred Mexico resorts have reopened and the state tourism minister predicts Cancun will draw as many visitors in 2006 as it did two years ago.
</VCardText>
</VCard>
</VCol>
<!-- 👉 Robert Meyer -->
<VCol
cols="12"
sm="6"
md="4"
>
<VCard>
<VImg :src="pages2" />
<VCardText class="position-relative">
<!-- User Avatar -->
<VAvatar
size="75"
class="avatar-center"
:image="avatar1"
/>
<!-- Title, Subtitle & Action Button -->
<div class="d-flex justify-space-between flex-wrap pt-8">
<div class="me-2 mb-2">
<VCardTitle class="pa-0">
Robert Meyer
</VCardTitle>
<VCardSubtitle class="text-caption pa-0">
London, UK
</VCardSubtitle>
</div>
<VBtn>send request</VBtn>
</div>
<!-- Mutual Friends -->
<div class="d-flex justify-space-between align-center mt-8">
<span class="font-weight-medium">18 mutual friends</span>
<div class="v-avatar-group">
<VAvatar
v-for="avatar in avatars"
:key="avatar"
:image="avatar"
size="40"
/>
</div>
</div>
</VCardText>
</VCard>
</VCol>
<!-- 👉 Popular Uses Of The Internet -->
<VCol
cols="12"
md="4"
sm="6"
>
<VCard>
<VImg :src="pages3" />
<VCardItem>
<VCardTitle>Popular Uses Of The Internet</VCardTitle>
</VCardItem>
<VCardText>
Although cards can support multiple actions, UI controls, and an overflow menu.
</VCardText>
<VCardActions>
<VBtn @click="isCardDetailsVisible = !isCardDetailsVisible">
Details
</VBtn>
<VSpacer />
<VBtn
icon
size="small"
@click="isCardDetailsVisible = !isCardDetailsVisible"
>
<VIcon :icon="isCardDetailsVisible ? 'ri-arrow-up-s-line' : 'ri-arrow-down-s-line'" />
</VBtn>
</VCardActions>
<VExpandTransition>
<div v-show="isCardDetailsVisible">
<VDivider />
<VCardText>
I'm a thing. But, like most politicians, he promised more than he could deliver. You won't have time for sleeping, soldier, not with all the bed making you'll be doing. Then we'll go with that data file! Hey, you add a one and two zeros to that or we walk! You're going to do his laundry? I've got to find a way to escape.
</VCardText>
</div>
</VExpandTransition>
</VCard>
</VCol>
<!-- 👉 Apple iPhone 11 Pro -->
<VCol
sm="6"
cols="12"
>
<VCard>
<div class="d-flex justify-space-between flex-wrap flex-md-nowrap flex-column flex-md-row">
<div class="ma-auto pa-5">
<VImg
width="137"
height="176"
:src="eCommerce2"
/>
</div>
<VDivider :vertical="$vuetify.display.mdAndUp" />
<div>
<VCardItem>
<VCardTitle>Apple iPhone 11 Pro</VCardTitle>
</VCardItem>
<VCardText>
Apple iPhone 11 Pro smartphone. Announced Sep 2019. Features 5.8 display Apple A13 Bionic
</VCardText>
<VCardText class="text-body-1">
<span>Price :</span> <span class="font-weight-medium">$899</span>
</VCardText>
<VCardActions class="justify-space-between">
<VBtn>
<VIcon icon="ri-shopping-cart-line" />
<span class="ms-2">Add to cart</span>
</VBtn>
<VBtn
color="secondary"
icon="ri-share-line"
size="small"
/>
</VCardActions>
</div>
</div>
</VCard>
</VCol>
<!-- 👉 Stump town Roasters. -->
<VCol
sm="6"
cols="12"
>
<VCard>
<div class="d-flex flex-column-reverse flex-md-row">
<div>
<VCardItem>
<VCardTitle>Stumptown Roasters</VCardTitle>
</VCardItem>
<VCardText class="d-flex align-center flex-wrap text-body-1">
<VRating
:model-value="5"
readonly
class="me-3"
density="compact"
/>
<span>5 Star | 98 reviews</span>
</VCardText>
<VCardText>
Before there was a United States of America, there were coffee houses, because how are you supposed to build.
</VCardText>
<VCardActions>
<VBtn>Location</VBtn>
<VBtn>Reviews</VBtn>
</VCardActions>
</div>
<div class="ma-auto pa-5">
<VImg
:width="176"
:src="pages5"
class="rounded"
/>
</div>
</div>
</VCard>
</VCol>
<!-- 👉 Apple Watch card -->
<VCol
lg="4"
sm="6"
cols="12"
>
<VCard>
<VImg :src="pages6" />
<VCardItem>
<VCardTitle>Apple Watch</VCardTitle>
</VCardItem>
<VCardText>
<p class="font-weight-medium text-base">
$249.40
</p>
<p class="mb-0">
3.1GHz 6-core 10th-generation Intel Core i5 processor, Turbo Boost up to 4.5GHz
</p>
</VCardText>
<VBtn
block
class="rounded-t-0"
>
Add to cart
</VBtn>
</VCard>
</VCol>
<!-- 👉 Lifetime Membership -->
<VCol
md="6"
lg="8"
cols="12"
>
<VCard>
<VRow no-gutters>
<VCol
cols="12"
sm="8"
md="12"
lg="7"
order="2"
order-lg="1"
>
<VCardItem>
<VCardTitle>Lifetime Membership</VCardTitle>
</VCardItem>
<VCardText>
Here, I focus on a range of items and features that we use in life without giving them a second thought such as Coca Cola, body muscles and holding ones own breath. Though, most of these notes are not fundamentally necessary, they are such that you can use them for a good laugh, at a drinks party or for picking up women or men.
</VCardText>
<VCardText>
<VDivider />
</VCardText>
<VCardText class="d-flex justify-center">
<div class="me-auto pe-4">
<p class="d-flex align-center mb-6">
<VIcon
color="primary"
icon="ri-lock-unlock-line"
/>
<span class="ms-3">Full Access</span>
</p>
<p class="d-flex align-center mb-0">
<VIcon
color="primary"
icon="ri-user-line"
/>
<span class="ms-3">15 Members</span>
</p>
</div>
<VDivider
v-if="$vuetify.display.smAndUp"
vertical
inset
/>
<div class="ms-auto ps-4">
<p class="d-flex align-center mb-6">
<VIcon
color="primary"
icon="ri-star-line"
/>
<span class="ms-3">Access all Features</span>
</p>
<p class="d-flex align-center mb-0">
<VIcon
color="primary"
icon="ri-pulse-line"
/>
<span class="ms-3">Lifetime Free Update</span>
</p>
</div>
</VCardText>
</VCol>
<VCol
cols="12"
sm="4"
md="12"
lg="5"
order="1"
order-lg="2"
class="member-pricing-bg text-center"
>
<div class="membership-pricing d-flex flex-column align-center py-14 h-100 justify-center">
<p class="mb-5">
<sub class="text-h5">$</sub>
<sup class="text-h2 font-weight-medium">899</sup>
<sub class="text-h5">USD</sub>
</p>
<p class="text-sm">
5 Tips For Offshore <br> Software Development
</p>
<VBtn class="mt-8">
Contact Now
</VBtn>
</div>
</VCol>
</VRow>
</VCard>
</VCol>
<!-- 👉 Influencing The Influencer -->
<VCol
cols="12"
lg="4"
md="6"
>
<VCard title="Influencing The Influencer">
<VCardText>
Computers have become ubiquitous in almost every facet of our lives. At work, desk jockeys spend hours in front of their desktops, while delivery people scan bar codes with handhelds and workers in the field stay in touch.
</VCardText>
<VCardText>
If you're in the market for new desktops, notebooks, or PDAs, there are a myriad of choices. Here's a rundown of some of the best systems available.
</VCardText>
<VCardActions>
<VBtn>Read More</VBtn>
</VCardActions>
</VCard>
</VCol>
<!-- 👉 The Best Answers -->
<VCol
cols="12"
lg="4"
md="6"
>
<VCard title="The Best Answers">
<VCardText class="d-flex align-center flex-wrap">
<VRating
:model-value="5"
readonly
density="compact"
class="me-3"
/>
<span class="text-subtitle-2">5 Star | 98 reviews</span>
</VCardText>
<VCardText>
If you are looking for a new way to promote your business that won't cost you more money, maybe printing is one of the options you won't resist.
</VCardText>
<VCardText>
become fast, easy and simple. If you want your promotional material to be an eye-catching
</VCardText>
<VCardActions>
<VBtn>Location</VBtn>
<VBtn>Reviews</VBtn>
</VCardActions>
</VCard>
</VCol>
<!-- 👉 Support -->
<VCol
cols="12"
md="6"
lg="4"
>
<VCard class="text-center">
<VCardText class="d-flex flex-column justify-center align-center">
<VAvatar
color="primary"
variant="tonal"
size="50"
class="mb-4"
>
<VIcon
size="2rem"
icon="ri-question-line"
/>
</VAvatar>
<h6 class="text-h6">
Support
</h6>
</VCardText>
<VCardText>
<p>
According to us blisters are a very common thing and we come across them very often in our daily lives. It is a very common occurrence like cold or fever depending upon your lifestyle.
</p>
</VCardText>
<VCardText>
<VBtn>Contact Now</VBtn>
</VCardText>
</VCard>
</VCol>
</VRow>
</template>
<style lang="scss" scoped>
.avatar-center {
position: absolute;
border: 3px solid rgb(var(--v-theme-surface));
inset-block-start: -2rem;
inset-inline-start: 1rem;
}
// membership pricing
.member-pricing-bg {
position: relative;
background-color: rgba(var(--v-theme-on-surface), var(--v-hover-opacity));
}
.membership-pricing {
sup {
inset-block-start: 9px;
}
}
</style>

View File

@@ -0,0 +1,94 @@
<script setup>
const navigationTab = ref('ITEM ONE')
const navigationTab2 = ref('ITEM ONE')
const tabItems = [
'ITEM ONE',
'ITEM TWO',
'ITEM THREE',
]
const tabContent = 'Although cards can support multiple actions, UI controls, and an overflow menu, use restraint and remember that cards...'
</script>
<template>
<VRow>
<VCol
md="6"
cols="12"
>
<VCard>
<VTabs v-model="navigationTab">
<VTab
v-for="item in tabItems"
:key="item"
:value="item"
>
{{ item }}
</VTab>
</VTabs>
<!-- tabs content -->
<VWindow v-model="navigationTab">
<VWindowItem
v-for="item in tabItems"
:key="item"
:value="item"
>
<VCardItem>
<VCardTitle>Navigation Card</VCardTitle>
</VCardItem>
<VCardText>
{{ tabContent }}
</VCardText>
<VCardText>
<VBtn>Learn More</VBtn>
</VCardText>
</VWindowItem>
</VWindow>
</VCard>
</VCol>
<VCol
md="6"
cols="12"
>
<VCard>
<VTabs
v-model="navigationTab2"
align-tabs="center"
>
<VTab
v-for="item in tabItems"
:key="item"
:value="item"
>
{{ item }}
</VTab>
</VTabs>
<!-- tabs content -->
<VWindow v-model="navigationTab2">
<VWindowItem
v-for="item in tabItems"
:key="item"
:value="item"
class="text-center"
>
<VCardItem>
<VCardTitle>Navigation Card</VCardTitle>
</VCardItem>
<VCardText>{{ tabContent }}</VCardText>
<VCardText>
<VBtn>Learn More</VBtn>
</VCardText>
</VWindowItem>
</VWindow>
</VCard>
</VCol>
</VRow>
</template>

View File

@@ -0,0 +1,97 @@
<script setup>
import avatar1 from '@images/avatars/avatar-1.png'
import avatar4 from '@images/avatars/avatar-4.png'
import avatar8 from '@images/avatars/avatar-8.png'
const solidCardData = [
{
cardBg: '#16B1FF',
title: 'Twitter Card',
icon: 'ri-twitter-line',
text: '"Turns out semicolon-less style is easier and safer in TS because most gotcha edge cases are type invalid as well."',
avatarImg: avatar4,
avatarName: 'Mary Vaughn',
likes: '1.2k',
share: '80',
},
{
cardBg: '#3B5998',
title: 'Facebook Card',
icon: 'ri-facebook-circle-line',
text: 'You\'ve read about the importance of being courageous, rebellious and imaginative. These are all vital ingredients.',
avatarImg: avatar1,
avatarName: 'Eugene Clarke',
likes: '3.2k',
share: '49',
},
{
cardBg: '#007BB6',
title: 'LinkedIn Card',
icon: 'ri-linkedin-box-line',
text: 'With the Internet spreading like wildfire and reaching every part of our daily life, more and more traffic is directed.',
avatarImg: avatar8,
avatarName: 'Anne Burke1',
likes: '1.2k',
share: '80',
},
]
</script>
<template>
<VRow>
<VCol
v-for="data in solidCardData"
:key="data.icon"
cols="12"
md="6"
lg="4"
>
<VCard :color="data.cardBg">
<VCardItem>
<template #prepend>
<VIcon
size="1.9rem"
color="white"
:icon="data.icon"
/>
</template>
<VCardTitle class="text-white">
{{ data.title }}
</VCardTitle>
</VCardItem>
<VCardText>
<p class="clamp-text text-white mb-0">
{{ data.text }}
</p>
</VCardText>
<VCardText class="d-flex justify-space-between align-center flex-wrap">
<div class="text-no-wrap">
<VAvatar
size="34"
:image="data.avatarImg"
/>
<span class="text-white ms-2">{{ data.avatarName }}</span>
</div>
<div class="d-flex align-center">
<IconBtn
icon="ri-heart-fill"
color="white"
class="me-1"
/>
<span class="text-body-2 text-white me-4">{{ data.likes }}</span>
<IconBtn
icon="ri-share-line"
color="white"
class="me-1"
/>
<span class="text-body-2 text-white">{{ data.share }}</span>
</div>
</VCardText>
</VCard>
</VCol>
</VRow>
</template>

View File

@@ -0,0 +1,110 @@
<script setup>
const logisticData = ref([
{
icon: 'ri-car-line',
color: 'primary',
title: 'On route vehicles',
value: 42,
change: 18.2,
isHover: false,
},
{
icon: 'ri-alert-line',
color: 'warning',
title: 'Vehicles with errors',
value: 8,
change: -8.7,
isHover: false,
},
{
icon: 'ri-stackshare-line',
color: 'error',
title: 'Deviated from route',
value: 27,
change: 4.3,
isHover: false,
},
{
icon: 'ri-timer-line',
color: 'info',
title: 'Late vehicles',
value: 13,
change: -2.5,
isHover: false,
},
])
</script>
<template>
<VRow>
<VCol
v-for="(data, index) in logisticData"
:key="index"
cols="12"
md="3"
sm="6"
>
<div>
<VCard
class="logistics-card-statistics cursor-pointer"
:style="data.isHover ? `border-block-end-color: rgb(var(--v-theme-${data.color}))` : `border-block-end-color: rgba(var(--v-theme-${data.color}),0.7)`"
@mouseenter="data.isHover = true"
@mouseleave="data.isHover = false"
>
<VCardText>
<div class="d-flex align-center gap-x-4 mb-2">
<VAvatar
variant="tonal"
:color="data.color"
rounded
>
<VIcon
:icon="data.icon"
size="24"
/>
</VAvatar>
<h4 class="text-h4">
{{ data.value }}
</h4>
</div>
<h6 class="text-h6 font-weight-regular">
{{ data.title }}
</h6>
<div class="d-flex align-center">
<div class="text-body-1 font-weight-medium me-2">
{{ data.change }}%
</div>
<span class="text-sm text-disabled">than last week</span>
</div>
</VCardText>
</VCard>
</div>
</VCol>
</VRow>
</template>
<style lang="scss" scoped>
@use "@core-scss/base/mixins" as mixins;
.logistics-card-statistics {
border-block-end-style: solid;
border-block-end-width: 2px;
&:hover {
border-block-end-width: 3px;
margin-block-end: -1px;
@include mixins.elevation(10);
transition: all 0.1s ease-out;
}
}
.skin--bordered{
.logistics-card-statistics {
&:hover {
margin-block-end: -2px;
}
}
}
</style>

View File

@@ -0,0 +1,93 @@
<script setup>
import { useTheme } from 'vuetify'
const vuetifyTheme = useTheme()
const currentTheme = computed(() => vuetifyTheme.current.value.colors)
const series = [{
name: '2020',
data: [
45,
85,
65,
50,
70,
],
}]
const chartOptions = computed(() => {
const backgroundColor = currentTheme.value['track-bg']
return {
chart: {
type: 'bar',
stacked: false,
parentHeightOffset: 0,
toolbar: { show: false },
},
grid: {
show: false,
padding: {
top: -10,
left: -7,
right: 0,
bottom: 5,
},
},
colors: [
currentTheme.value.error,
currentTheme.value.primary,
currentTheme.value.error,
currentTheme.value.primary,
currentTheme.value.primary,
],
plotOptions: {
bar: {
horizontal: false,
columnWidth: '20%',
borderRadius: 4,
distributed: true,
colors: {
backgroundBarColors: [
backgroundColor,
backgroundColor,
backgroundColor,
backgroundColor,
backgroundColor,
],
backgroundBarRadius: 5,
},
},
},
legend: { show: false },
dataLabels: { enabled: false },
xaxis: {
labels: { show: false },
axisBorder: { show: false },
axisTicks: { show: false },
},
yaxis: { show: false },
tooltip: { enabled: false },
}
})
</script>
<template>
<VCard>
<VCardText>
<h4 class="text-h4">
2,856
</h4>
<VueApexCharts
:options="chartOptions"
:series="series"
:height="110"
/>
<h6 class="text-h6 text-center">
Sessions
</h6>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,139 @@
<script setup>
import { useTheme } from 'vuetify'
const vuetifyTheme = useTheme()
const currentTheme = computed(() => vuetifyTheme.current.value.colors)
const series = [
{
name: 'Earning',
data: [
180,
120,
284,
180,
102,
],
},
{
name: 'Expense',
data: [
-100,
-130,
-100,
-60,
-120,
],
},
]
const chartOptions = computed(() => {
return {
chart: {
type: 'bar',
stacked: true,
parentHeightOffset: 0,
toolbar: { show: false },
},
grid: {
show: false,
padding: {
top: -10,
left: -15,
right: 0,
bottom: 5,
},
yaxis: { lines: { show: false } },
},
xaxis: {
labels: { show: false },
axisTicks: { show: false },
axisBorder: { show: false },
categories: [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
],
},
legend: { show: false },
dataLabels: { enabled: false },
colors: [
currentTheme.value['on-background'],
currentTheme.value.error,
],
plotOptions: {
bar: {
borderRadius: 4,
columnWidth: '25%',
borderRadiusApplication: 'around',
borderRadiusWhenStacked: 'all',
},
},
states: {
hover: { filter: { type: 'none' } },
active: { filter: { type: 'none' } },
},
yaxis: { labels: { show: false } },
stroke: { lineCap: 'round' },
tooltip: { enabled: false },
responsive: [{
breakpoint: 600,
options: {
chart: { height: 200 },
grid: {
padding: {
top: -12,
left: -15,
right: 0,
bottom: -10,
},
},
plotOptions: {
bar: {
borderRadius: 4,
columnWidth: '20%',
borderRadiusApplication: 'around',
borderRadiusWhenStacked: 'all',
},
},
},
}],
}
})
</script>
<template>
<VCard>
<VCardText>
<h4 class="text-h4">
4,350
</h4>
<VueApexCharts
id="sessions-chart"
:options="chartOptions"
:series="series"
:height="110"
/>
<h6 class="text-h6 text-center">
Sessions
</h6>
</VCardText>
</VCard>
</template>
<style lang="scss">
#sessions-chart {
.apexcharts-series {
&[seriesName="Earning"] {
transform: scaleY(0.965);
}
&[seriesName="Expense"] {
transform: scaleY(1.035);
}
}
}
</style>

View File

@@ -0,0 +1,89 @@
<script setup>
import { useTheme } from 'vuetify'
const vuetifyTheme = useTheme()
const currentTheme = vuetifyTheme.current.value.colors
const series = [{
name: 'Subscribers',
data: [
28,
40,
36,
52,
38,
60,
55,
],
}]
const chartOptions = {
chart: {
parentHeightOffset: 0,
toolbar: { show: false },
sparkline: { enabled: true },
},
grid: { show: false },
dataLabels: { enabled: false },
stroke: {
curve: 'smooth',
width: 2.5,
},
fill: {
type: 'gradient',
gradient: {
shadeIntensity: 0.9,
opacityFrom: 0.5,
opacityTo: 0.1,
stops: [
0,
80,
100,
],
},
},
xaxis: {
type: 'numeric',
lines: { show: false },
axisBorder: { show: false },
labels: { show: false },
},
yaxis: [{
y: 0,
offsetX: 0,
offsetY: 0,
padding: {
left: 0,
right: 0,
},
}],
tooltip: { enabled: false },
theme: {
monochrome: {
enabled: true,
color: currentTheme.success,
shadeTo: 'light',
shadeIntensity: 0.65,
},
},
}
</script>
<template>
<VCard>
<VCardText>
<h4 class="text-h4">
42.5k
</h4>
<VueApexCharts
type="area"
:options="chartOptions"
:series="series"
:height="110"
/>
<h6 class="text-h6 text-center">
Total Growth
</h6>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,90 @@
<script setup>
import { useTheme } from 'vuetify'
import { hexToRgb } from '@layouts/utils'
const vuetifyTheme = useTheme()
const series = [{
data: [
0,
20,
5,
30,
15,
45,
],
}]
const chartOptions = computed(() => {
const currentTheme = vuetifyTheme.current.value.colors
const variableTheme = vuetifyTheme.current.value.variables
return {
chart: {
parentHeightOffset: 0,
toolbar: { show: false },
},
tooltip: { enabled: false },
grid: {
borderColor: `rgba(${ hexToRgb(String(variableTheme['border-color'])) },${ variableTheme['border-opacity'] })`,
strokeDashArray: 6,
xaxis: { lines: { show: true } },
yaxis: { lines: { show: false } },
padding: {
top: -10,
left: -7,
right: 5,
bottom: 5,
},
},
stroke: {
width: 3,
lineCap: 'butt',
curve: 'straight',
},
colors: [currentTheme.primary],
markers: {
size: 6,
offsetY: 4,
offsetX: -2,
strokeWidth: 3,
colors: ['transparent'],
strokeColors: 'transparent',
discrete: [{
size: 5.5,
seriesIndex: 0,
strokeColor: currentTheme.primary,
fillColor: currentTheme.surface,
dataPointIndex: series[0].data.length - 1,
}],
hover: { size: 7 },
},
xaxis: {
labels: { show: false },
axisTicks: { show: false },
axisBorder: { show: false },
},
yaxis: { labels: { show: false } },
}
})
</script>
<template>
<VCard>
<VCardText>
<h4 class="text-h4">
$86.4k
</h4>
<VueApexCharts
type="line"
:options="chartOptions"
:series="series"
:height="110"
/>
<h6 class="text-h6 text-center">
Total Profit
</h6>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,87 @@
<script setup>
import { useTheme } from 'vuetify'
const vuetifyTheme = useTheme()
const series = [{
data: [
28,
58,
40,
68,
],
}]
const chartOptions = computed(() => {
const currentTheme = vuetifyTheme.current.value.colors
return {
grid: {
show: false,
padding: {
left: -2,
top: -10,
},
},
chart: {
parentHeightOffset: 0,
type: 'line',
offsetX: -8,
dropShadow: {
enabled: true,
top: 10,
blur: 4,
color: currentTheme.primary,
opacity: 0.09,
},
toolbar: { show: false },
},
markers: {
size: 6,
colors: 'transparent',
strokeColors: 'transparent',
strokeWidth: 4,
discrete: [{
seriesIndex: 0,
dataPointIndex: series[0].data.length - 1,
fillColor: currentTheme.surface,
strokeColor: currentTheme.primary,
size: 6,
}],
hover: { size: 7 },
},
stroke: {
width: 5,
curve: 'smooth',
lineCap: 'round',
},
xaxis: {
axisBorder: { show: false },
axisTicks: { show: false },
labels: { show: false },
},
yaxis: { labels: { show: false } },
tooltip: { enabled: false },
colors: [currentTheme.primary],
}
})
</script>
<template>
<VCard>
<VCardText>
<h4 class="text-h4">
$35.4k
</h4>
<VueApexCharts
:options="chartOptions"
:series="series"
:height="110"
/>
<h6 class="text-h6 text-center">
Total Revenue
</h6>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,68 @@
<script setup>
import { useTheme } from 'vuetify'
import { hexToRgb } from '@layouts/utils'
const vuetifyTheme = useTheme()
const series = [78]
const chartOptions = computed(() => {
const currentTheme = vuetifyTheme.current.value.colors
const variableTheme = vuetifyTheme.current.value.variables
return {
chart: { sparkline: { enabled: true } },
colors: [currentTheme.info],
plotOptions: {
radialBar: {
startAngle: -90,
endAngle: 90,
hollow: { size: '65%' },
dataLabels: {
name: { show: false },
value: {
fontSize: '1.25rem',
fontWeight: '500',
offsetY: 0,
color: `rgba(${ hexToRgb(currentTheme['on-surface']) },${ variableTheme['high-emphasis-opacity'] })`,
},
},
track: { background: currentTheme['track-bg'] },
},
},
stroke: { lineCap: 'round' },
}
})
</script>
<template>
<VCard>
<VCardText>
<h4 class="text-h4">
135k
</h4>
<VueApexCharts
id="stats-radial-bar-chart"
:options="chartOptions"
:series="series"
type="radialBar"
:height="150"
/>
<h6 class="text-h6 text-center mt-6">
Total sales
</h6>
</VCardText>
</VCard>
</template>
<style lang="scss">
#stats-radial-bar-chart {
.apexcharts-canvas {
.apexcharts-text {
&.apexcharts-datalabel-value {
font-weight: 600;
}
}
}
}
</style>

View File

@@ -0,0 +1,123 @@
<script setup>
import { useTheme } from 'vuetify'
import { hexToRgb } from '@layouts/utils'
const vuetifyTheme = useTheme()
const currentTheme = computed(() => vuetifyTheme.current.value.colors)
const chartOptions = computed(() => {
const variableTheme = ref(vuetifyTheme.current.value.variables)
const secondaryTextColor = `rgba(${ hexToRgb(currentTheme.value['on-surface']) },${ variableTheme.value['medium-emphasis-opacity'] })`
const primaryTextColor = `rgba(${ hexToRgb(currentTheme.value['on-surface']) },${ variableTheme.value['high-emphasis-opacity'] })`
return {
chart: {
sparkline: { enabled: true },
animations: { enabled: false },
},
stroke: {
width: 5,
colors: [currentTheme.value.surface],
},
legend: { show: false },
tooltip: { enabled: true },
dataLabels: { enabled: false },
colors: [
currentTheme.value.primary,
currentTheme.value.info,
currentTheme.value.warning,
currentTheme.value.error,
],
labels: [
'Comments',
'Replies',
'Shares',
'Likes',
],
series: [
45,
10,
18,
27,
],
grid: {
padding: {
top: -7,
bottom: 5,
},
},
states: {
hover: { filter: { type: 'none' } },
active: { filter: { type: 'none' } },
},
plotOptions: {
pie: {
expandOnClick: false,
donut: {
size: '75%',
labels: {
show: true,
value: {
fontSize: '1.15rem',
fontFamily: 'Inter',
fontWeight: 500,
offsetY: -18,
color: primaryTextColor,
formatter: o => `${ Number.parseInt(o) }%`,
},
name: {
offsetY: 18,
fontFamily: 'Inter',
},
total: {
label: '1 Quarter',
show: true,
color: secondaryTextColor,
fontSize: '0.75rem',
fontWeight: 400,
formatter: () => '28%',
},
},
},
},
},
}
})
</script>
<template>
<VCard class="overflow-visible">
<VCardText class="d-flex justify-space-between align-center gap-3">
<div>
<h5 class="text-h5 mb-1">
Total Sales
</h5>
<div class="text-body-1 mb-3">
Calculated in last 7 days
</div>
<div class="d-flex align-center flex-wrap">
<h4 class="text-h4">
$25,980
</h4>
<div class="d-flex align-center">
<VIcon
icon="ri-arrow-up-s-line"
size="24"
color="success"
/>
<span class="text-body-1 text-success">15.6%</span>
</div>
</div>
</div>
<VueApexCharts
type="donut"
:options="chartOptions"
:height="120"
:series="[45, 10, 18, 27]"
:width="110"
/>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,71 @@
<script setup>
const statistics = [
{
title: 'Sales',
stats: '245k',
icon: 'ri-pie-chart-2-line',
color: 'primary',
},
{
title: 'Customers',
stats: '12.5k',
icon: 'ri-group-line',
color: 'success',
},
{
title: 'Product',
stats: '1.54k',
icon: 'ri-macbook-line',
color: 'warning',
},
{
title: 'Revenue',
stats: '$88k',
icon: 'ri-money-dollar-circle-line',
color: 'info',
},
]
</script>
<template>
<VCard title="Transactions">
<template #subtitle>
<p class="text-body-1 mb-0">
<span class="d-inline-block font-weight-medium text-high-emphasis">Total 48.5% Growth</span> <span class="text-high-emphasis">😎</span> this month
</p>
</template>
<VCardText>
<VRow>
<VCol
v-for="item in statistics"
:key="item.title"
cols="6"
md="3"
>
<div class="d-flex align-center">
<VAvatar
:color="item.color"
rounded
size="40"
class="elevation-2 me-3"
>
<VIcon
size="24"
:icon="item.icon"
/>
</VAvatar>
<div class="d-flex flex-column">
<div class="text-body-1">
{{ item.title }}
</div>
<h5 class="text-h5">
{{ item.stats }}
</h5>
</div>
</div>
</VCol>
</VRow>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,126 @@
<script setup>
import avatar1 from '@images/avatars/avatar-1.png'
import avatar6 from '@images/avatars/avatar-6.png'
import avatar8 from '@images/avatars/avatar-8.png'
import pdf from '@images/icons/project-icons/pdf.png'
</script>
<template>
<VCard title="Activity Timeline">
<VCardText>
<VTimeline
side="end"
align="start"
line-inset="8"
truncate-line="start"
density="compact"
>
<VTimelineItem
dot-color="primary"
size="x-small"
>
<!-- 👉 Header -->
<div class="d-flex justify-space-between align-center gap-2 flex-wrap mb-3">
<div class="app-timeline-title align-self-start">
12 Invoices have been paid
</div>
<div class="app-timeline-meta">
12 min ago
</div>
</div>
<p class="app-timeline-text mb-2">
Invoices have been paid to the company.
</p>
<div class="d-inline-flex align-center timeline-chip mb-4">
<img
:src="pdf"
height="20"
class="me-3"
alt="img"
>
<h6 class="text-h6 text-medium-emphasis">
invoice.pdf
</h6>
</div>
</VTimelineItem>
<VTimelineItem
dot-color="success"
size="x-small"
>
<!-- 👉 Header -->
<div class="d-flex justify-space-between align-center gap-2 flex-wrap mb-3">
<div class="app-timeline-title align-self-start">
Client Meeting
</div>
<div class="app-timeline-meta">
45 min ago
</div>
</div>
<p class="app-timeline-text mb-2">
Project meeting with john @10:15am
</p>
<div class="d-flex align-center mb-2">
<VAvatar
size="32"
:image="avatar1"
class="me-3"
/>
<div>
<div class="text-body-2 font-weight-medium">
Lester McCarthy (Client)
</div>
<div class="text-body-2">
CEO of ThemeSelection
</div>
</div>
</div>
</VTimelineItem>
<VTimelineItem
dot-color="info"
size="x-small"
>
<div class="d-flex justify-space-between align-center gap-2 flex-wrap mb-3">
<div class="app-timeline-title align-self-start">
Create a new project for client
</div>
<div class="app-timeline-meta">
2 Day Ago
</div>
</div>
<p class="mb-0 app-timeline-text mb-2">
6 team members in a project
</p>
<div class="v-avatar-group">
<VAvatar
:size="40"
:image="avatar1"
/>
<VAvatar
:size="40"
:image="avatar8"
/>
<VAvatar
:size="40"
:image="avatar6"
/>
<VAvatar
:color="$vuetify.theme.current.dark ? '#3A3B59' : '#F0EFF0'"
:size="40"
>
+3
</VAvatar>
</div>
</VTimelineItem>
</VTimeline>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,230 @@
<script setup>
import {
useDisplay,
useTheme,
} from 'vuetify'
import { hexToRgb } from '@layouts/utils'
const vuetifyTheme = useTheme()
const { thresholds } = useDisplay()
const options = computed(() => {
const currentTheme = ref(vuetifyTheme.current.value.colors)
const variableTheme = ref(vuetifyTheme.current.value.variables)
const borderColor = `rgba(${ hexToRgb(String(variableTheme.value['border-color'])) },${ variableTheme.value['border-opacity'] })`
return {
chart: {
offsetY: -25,
stacked: true,
parentHeightOffset: 0,
toolbar: { show: false },
},
plotOptions: {
bar: {
borderRadius: 8,
columnWidth: '35%',
borderRadiusApplication: 'around',
borderRadiusWhenStacked: 'all',
},
},
legend: { show: false },
grid: {
xaxis: { lines: { show: false } },
borderColor,
strokeDashArray: 10,
padding: {
left: -15,
right: -5,
},
},
dataLabels: { enabled: false },
stroke: {
width: 6,
curve: 'smooth',
lineCap: 'round',
colors: [currentTheme.value.surface],
},
colors: [
currentTheme.value.success,
currentTheme.value.secondary,
currentTheme.value.warning,
],
xaxis: {
labels: { show: false },
axisTicks: { show: false },
crosshairs: { opacity: 0 },
axisBorder: { show: false },
},
yaxis: { labels: { show: false } },
states: {
hover: { filter: { type: 'none' } },
active: { filter: { type: 'none' } },
},
responsive: [
{
breakpoint: 1560,
options: {
plotOptions: {
bar: {
columnWidth: '40%',
borderRadius: 6,
},
},
},
},
{
breakpoint: thresholds.value.lg,
options: { plotOptions: { bar: { columnWidth: '40%' } } },
},
{
breakpoint: thresholds.value.md,
options: {
plotOptions: {
bar: {
columnWidth: '45%',
borderRadius: 8,
},
},
},
},
{
breakpoint: 768,
options: {
plotOptions: {
bar: {
columnWidth: '55%',
borderRadius: 6,
},
},
},
},
{
breakpoint: thresholds.value.sm,
options: { plotOptions: { bar: { columnWidth: '35%' } } },
},
{
breakpoint: 460,
options: { plotOptions: { bar: { columnWidth: '45%' } } },
},
{
breakpoint: 400,
options: {
plotOptions: {
bar: {
columnWidth: '45%',
borderRadius: 6,
},
},
},
},
],
}
})
const series = [
{
name: 'Product A',
data: [
16000,
12000,
16000,
18000,
15000,
35000,
16000,
],
},
{
name: 'Product B',
data: [
10000,
12000,
10000,
0,
10000,
10000,
10000,
],
},
{
name: 'Product C',
data: [
0,
15000,
0,
0,
12000,
0,
10000,
],
},
]
const analytics = [
{
title: 'Revenue',
amount: '$845k',
percentage: '82%',
profit: true,
},
{
title: 'Transactions',
amount: '$12.5k',
percentage: '52%',
profit: false,
},
{
title: 'Total Profit',
amount: '$27.6k',
percentage: '42%',
profit: true,
},
]
</script>
<template>
<VCard>
<VCardItem>
<VCardTitle>Analytics</VCardTitle>
<template #append>
<div class="me-n3">
<MoreBtn />
</div>
</template>
</VCardItem>
<VCardText>
<VueApexCharts
type="bar"
:options="options"
:series="series"
:height="210"
/>
<div
v-for="(item, index) in analytics"
:key="item.title"
class="d-flex align-center"
:class="index > 0 ? 'mt-3' : ''"
>
<h6 class="text-h6">
{{ item.title }}
</h6>
<VSpacer />
<div class="text-body-1 me-4 mb-0">
{{ item.amount }}
</div>
<h6 class="text-h6 me-4">
{{ item.percentage }}
</h6>
<VIcon
:color="item.profit ? 'success' : 'error'"
:icon="item.profit ? 'ri-arrow-up-s-line' : 'ri-arrow-down-s-line'"
size="24"
/>
</div>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,115 @@
<script setup>
const chartColors = {
donut: {
series1: '#56ca00',
series2: '#56ca00cc',
series3: '#56ca0099',
series4: '#56ca0066',
},
}
const headingColor = 'rgba(var(--v-theme-on-background), var(--v-high-emphasis-opacity))'
const labelColor = 'rgba(var(--v-theme-on-background), var(--v-medium-emphasis-opacity))'
const deliveryExceptionsChartSeries = [
13,
25,
22,
40,
]
const deliveryExceptionsChartConfig = {
labels: [
'Incorrect address',
'Weather conditions',
'Federal Holidays',
'Damage during transit',
],
colors: [
chartColors.donut.series1,
chartColors.donut.series2,
chartColors.donut.series3,
chartColors.donut.series4,
],
stroke: { width: 0 },
dataLabels: {
enabled: false,
formatter(val) {
return `${ Number.parseInt(val) }%`
},
},
legend: {
show: true,
position: 'bottom',
offsetY: 10,
markers: {
width: 8,
height: 8,
offsetX: -3,
},
itemMargin: {
horizontal: 15,
vertical: 5,
},
fontSize: '13px',
fontWeight: 400,
labels: {
colors: headingColor,
useSeriesColors: false,
},
},
tooltip: { theme: false },
grid: { padding: { top: 15 } },
plotOptions: {
pie: {
donut: {
size: '75%',
labels: {
show: true,
value: {
fontSize: '26px',
color: headingColor,
fontWeight: 500,
offsetY: -15,
formatter(val) {
return `${ Number.parseInt(val) }%`
},
},
name: { offsetY: 30 },
total: {
show: true,
fontSize: '1rem',
label: 'AVG. Exceptions',
color: labelColor,
formatter() {
return '30%'
},
},
},
},
},
},
responsive: [{
breakpoint: 420,
options: { chart: { height: 400 } },
}],
}
</script>
<template>
<VCard>
<VCardItem title="Delivery exceptions">
<template #append>
<MoreBtn />
</template>
</VCardItem>
<VCardText>
<VueApexCharts
type="donut"
height="400"
:options="deliveryExceptionsChartConfig"
:series="deliveryExceptionsChartSeries"
/>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,135 @@
<script setup>
import { useTheme } from 'vuetify'
import { hexToRgb } from '@layouts/utils'
const vuetifyTheme = useTheme()
const options = computed(() => {
const currentTheme = ref(vuetifyTheme.current.value.colors)
const variableTheme = ref(vuetifyTheme.current.value.variables)
const secondaryTextColor = `rgba(${ hexToRgb(currentTheme.value['on-surface']) },${ variableTheme.value['medium-emphasis-opacity'] })`
const disabledColor = `rgba(${ hexToRgb(currentTheme.value['on-surface']) },${ variableTheme.value['disabled-opacity'] })`
const borderColor = `rgba(${ hexToRgb(String(variableTheme.value['border-color'])) },${ variableTheme.value['border-opacity'] })`
return {
chart: {
parentHeightOffset: 0,
toolbar: { show: false },
},
colors: [
currentTheme.value.primary,
currentTheme.value.info,
],
plotOptions: {
radar: {
size: 110,
polygons: {
strokeColors: borderColor,
connectorColors: borderColor,
},
},
},
legend: {
labels: { colors: secondaryTextColor },
fontSize: '15px',
markers: {
width: '10px',
height: '10px',
},
},
fill: {
type: 'gradient',
gradient: {
shade: 'dark',
gradientToColors: [
currentTheme.value.primary,
currentTheme.value.info,
],
shadeIntensity: 1,
type: 'vertical',
opacityFrom: 1,
opacityTo: 0.9,
stops: [
0,
100,
],
},
},
labels: [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
],
markers: { size: 0 },
xaxis: {
labels: {
show: true,
style: {
fontSize: '13px',
colors: [
disabledColor,
disabledColor,
disabledColor,
disabledColor,
disabledColor,
disabledColor,
],
},
},
},
yaxis: { show: false },
grid: { show: false },
}
})
const series = [
{
name: 'Income',
data: [
70,
90,
90,
90,
80,
90,
],
},
{
name: 'Net Worth',
data: [
120,
80,
100,
80,
100,
80,
],
},
]
</script>
<template>
<VCard>
<VCardItem>
<VCardTitle>Performance</VCardTitle>
<template #append>
<div class="me-n3">
<MoreBtn />
</div>
</template>
</VCardItem>
<VCardText>
<VueApexCharts
type="radar"
:options="options"
:series="series"
:height="295"
/>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,208 @@
<script setup>
import { useTheme } from 'vuetify'
import { hexToRgb } from '@layouts/utils'
const vuetifyTheme = useTheme()
const options = computed(() => {
const currentTheme = ref(vuetifyTheme.current.value.colors)
const variableTheme = ref(vuetifyTheme.current.value.variables)
const secondaryTextColor = `rgba(${ hexToRgb(currentTheme.value['on-surface']) },${ variableTheme.value['medium-emphasis-opacity'] })`
return {
chart: {
stacked: true,
parentHeightOffset: 0,
toolbar: { show: false },
},
grid: {
yaxis: { lines: { show: false } },
xaxis: { lines: { show: false } },
padding: {
left: 0,
right: 0,
},
},
legend: {
offsetY: 8,
fontSize: '15px',
markers: {
radius: 15,
width: 10,
height: 10,
},
labels: { colors: secondaryTextColor },
},
stroke: {
width: 2,
colors: [currentTheme.value.surface],
},
dataLabels: { enabled: false },
colors: [
currentTheme.value.success,
currentTheme.value.secondary,
],
plotOptions: {
bar: {
borderRadius: 6,
columnWidth: '45%',
borderRadiusApplication: 'around',
borderRadiusWhenStacked: 'all',
},
},
states: {
hover: { filter: { type: 'none' } },
active: { filter: { type: 'none' } },
},
xaxis: {
categories: [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
],
crosshairs: { opacity: 0 },
labels: { show: false },
axisTicks: { show: false },
axisBorder: { show: false },
},
yaxis: { labels: { show: false } },
tooltip: { enabled: false },
responsive: [
{
breakpoint: 1560,
options: {
plotOptions: {
bar: {
columnWidth: '50%',
borderRadius: 6,
},
},
},
},
{
breakpoint: 1380,
options: {
plotOptions: {
bar: {
columnWidth: '60%',
borderRadius: 6,
},
},
},
},
{
breakpoint: 1080,
options: { plotOptions: { bar: { borderRadius: 4 } } },
},
{
breakpoint: 960,
options: {
plotOptions: {
bar: {
columnWidth: '45%',
borderRadius: 4,
},
},
},
},
{
breakpoint: 768,
options: {
plotOptions: {
bar: {
columnWidth: '55%',
borderRadius: 4,
},
},
},
},
{
breakpoint: 600,
options: {
plotOptions: {
bar: {
columnWidth: '30%',
borderRadius: 6,
},
},
},
},
{
breakpoint: 460,
options: { plotOptions: { bar: { columnWidth: '45%' } } },
},
{
breakpoint: 400,
options: {
plotOptions: {
bar: {
columnWidth: '35%',
borderRadius: 4,
},
},
},
},
],
}
})
const series = [
{
name: 'Earning',
data: [
95,
177,
284,
256,
105,
63,
168,
218,
72,
],
},
{
name: 'Expense',
data: [
-145,
-80,
-60,
-180,
-100,
-60,
-85,
-75,
-100,
],
},
]
</script>
<template>
<VCard>
<VCardItem>
<VCardTitle>Revenue Report</VCardTitle>
<template #append>
<div class="me-n3">
<MoreBtn />
</div>
</template>
</VCardItem>
<VCardText>
<VueApexCharts
type="bar"
:options="options"
:series="series"
:height="240"
/>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,162 @@
<script setup>
import { useTheme } from 'vuetify'
import { hexToRgb } from '@layouts/utils'
const vuetifyTheme = useTheme()
const options = computed(() => {
const currentTheme = ref(vuetifyTheme.current.value.colors)
const variableTheme = ref(vuetifyTheme.current.value.variables)
const secondaryTextColor = `rgba(${ hexToRgb(currentTheme.value['on-surface']) },${ variableTheme.value['medium-emphasis-opacity'] })`
const primaryTextColor = `rgba(${ hexToRgb(currentTheme.value['on-surface']) },${ variableTheme.value['high-emphasis-opacity'] })`
return {
chart: { sparkline: { enabled: true } },
colors: [
'rgba(var(--v-theme-primary),1)',
'rgba(var(--v-theme-primary), 0.7)',
'rgba(var(--v-theme-primary), 0.5)',
currentTheme.value['track-bg'],
],
stroke: { width: 0 },
legend: { show: false },
dataLabels: { enabled: false },
labels: [
'Apparel',
'Electronics',
'FMCG',
'Other Sales',
],
states: {
hover: { filter: { type: 'none' } },
active: { filter: { type: 'none' } },
},
plotOptions: {
pie: {
customScale: 0.9,
donut: {
size: '70%',
labels: {
show: true,
name: {
offsetY: 25,
color: secondaryTextColor,
},
value: {
offsetY: -15,
fontWeight: 500,
fontSize: '24px',
color: primaryTextColor,
formatter: value => `${ value }k`,
},
total: {
show: true,
label: 'Weekly Sales',
fontSize: '15px',
color: secondaryTextColor,
formatter: value => `${ value.globals.seriesTotals.reduce((total, num) => total + num) }k`,
},
},
},
},
},
}
})
const series = [
12,
25,
13,
50,
]
const salesOverviews = [
{
product: 'Apparel',
sales: '$1,840',
},
{
product: 'Electronic',
sales: '$11,420',
},
{
product: 'FMCG',
sales: '$1,840',
},
{
product: 'Other Sales',
sales: '$11,420',
},
]
</script>
<template>
<VCard>
<VCardItem>
<VCardTitle>Sales Overview</VCardTitle>
<template #append>
<div class="me-n3">
<MoreBtn />
</div>
</template>
</VCardItem>
<VCardText class="pt-5">
<div class="d-flex gap-4 flex-lg-row flex-column">
<div class="mx-auto">
<VueApexCharts
type="donut"
:options="options"
:series="series"
:height="220"
:width="220"
/>
</div>
<div>
<div class="d-flex align-center">
<div class="me-3">
<VAvatar
rounded
color="primary"
variant="tonal"
>
<VIcon icon="ri-wallet-line" />
</VAvatar>
</div>
<div>
<p class="mb-0">
Number of Sales
</p>
<h5 class="text-h5">
$86,400
</h5>
</div>
</div>
<VDivider class="my-6" />
<VRow>
<VCol
v-for="sale in salesOverviews"
:key="sale.product"
cols="6"
>
<div class="d-flex align-center mb-1">
<VIcon
icon="ri-circle-fill"
color="primary"
size="10"
class="me-2"
/>
<div>{{ sale.product }}</div>
</div>
<h6 class="text-h6 text-medium-emphasis">
{{ sale.sales }}
</h6>
</VCol>
</VRow>
</div>
</div>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,122 @@
<script setup>
import { useTheme } from 'vuetify'
const vuetifyTheme = useTheme()
const options = computed(() => {
const currentTheme = ref(vuetifyTheme.current.value.colors)
return {
chart: {
offsetY: -30,
parentHeightOffset: 0,
toolbar: { show: false },
},
tooltip: { enabled: false },
dataLabels: { enabled: false },
stroke: {
width: 5,
curve: 'smooth',
},
grid: {
show: false,
padding: {
left: 0,
top: -40,
right: 0,
},
},
fill: {
type: 'gradient',
gradient: {
opacityTo: 0.7,
opacityFrom: 0.5,
shadeIntensity: 1,
stops: [
0,
100,
],
colorStops: [[
{
offset: 0,
opacity: 0.6,
color: currentTheme.value.primary,
},
{
offset: 100,
opacity: 0.1,
color: currentTheme.value.surface,
},
]],
},
},
theme: {
monochrome: {
enabled: true,
shadeTo: 'light',
shadeIntensity: 1,
color: currentTheme.value.primary,
},
},
xaxis: {
type: 'numeric',
labels: { show: false },
axisTicks: { show: false },
axisBorder: { show: false },
},
yaxis: { show: false },
markers: {
size: 1,
offsetY: 1,
offsetX: -10,
strokeWidth: 5,
colors: ['transparent'],
strokeColors: 'transparent',
discrete: [{
size: 8,
seriesIndex: 0,
dataPointIndex: 5,
strokeColor: currentTheme.value.primary,
fillColor: currentTheme.value.surface,
}],
},
}
})
const series = [{
name: 'Traffic Rate',
data: [
35,
180,
100,
300,
220,
400,
],
}]
</script>
<template>
<VCard>
<VCardText>
<div class="d-flex justify-space-between">
<div>
<h5 class="text-h5">
Sales State
</h5>
<div class="text-body-1">
Total $42,580 Sales
</div>
</div>
<MoreBtn />
</div>
</VCardText>
<VueApexCharts
type="area"
:options="options"
:series="series"
:height="295"
/>
</VCard>
</template>

View File

@@ -0,0 +1,350 @@
<script setup>
import { useTheme } from 'vuetify'
import { hexToRgb } from '@layouts/utils'
const vuetifyTheme = useTheme()
const options = computed(() => {
const currentTheme = ref(vuetifyTheme.current.value.colors)
const variableTheme = ref(vuetifyTheme.current.value.variables)
const disabledColor = `rgba(${ hexToRgb(currentTheme.value['on-surface']) },${ variableTheme.value['disabled-opacity'] })`
const borderColor = `rgba(${ hexToRgb(String(variableTheme.value['border-color'])) },${ variableTheme.value['border-opacity'] })`
return {
chart: {
stacked: true,
parentHeightOffset: 0,
toolbar: { show: false },
},
plotOptions: {
bar: {
borderRadius: 8,
columnWidth: '30%',
borderRadiusApplication: 'around',
borderRadiusWhenStacked: 'all',
},
},
xaxis: {
axisTicks: { show: false },
crosshairs: { opacity: 0 },
axisBorder: { show: false },
categories: [
2015,
2016,
2017,
2018,
2019,
2020,
2021,
],
labels: {
style: {
fontSize: '13px',
colors: disabledColor,
fontFamily: 'inter',
},
},
},
yaxis: {
labels: {
style: {
fontSize: '13px',
colors: disabledColor,
fontFamily: 'inter',
},
formatter: value => value > 999 ? `${ (value / 1000).toFixed(0) }k` : `${ value }`,
},
},
colors: [
'rgba(var(--v-theme-primary),1)',
currentTheme.value.success,
currentTheme.value.secondary,
],
grid: {
xaxis: { lines: { show: false } },
borderColor,
strokeDashArray: 7,
padding: { bottom: -10 },
},
legend: { show: false },
dataLabels: { enabled: false },
stroke: {
width: 6,
curve: 'smooth',
lineCap: 'round',
colors: [currentTheme.value.surface],
},
states: {
hover: { filter: { type: 'none' } },
active: { filter: { type: 'none' } },
},
responsive: [
{
breakpoint: 1560,
options: { plotOptions: { bar: { columnWidth: '35%' } } },
},
{
breakpoint: 1441,
options: {
plotOptions: {
bar: {
columnWidth: '40%',
borderRadius: 8,
},
},
},
},
{
breakpoint: 1280,
charts: { height: 200 },
options: {
plotOptions: {
bar: {
columnWidth: '40%',
borderRadius: 8,
},
},
},
},
{
breakpoint: 1160,
options: {
plotOptions: {
bar: {
columnWidth: '40%',
borderRadius: 6,
},
},
},
},
{
breakpoint: 960,
options: {
plotOptions: {
bar: {
columnWidth: '30%',
borderRadius: 6,
},
},
},
},
{
breakpoint: 800,
chart: {
height: 250,
offsetX: -10,
},
options: { plotOptions: { bar: { columnWidth: '40%' } } },
},
{
breakpoint: 650,
options: {
plotOptions: {
bar: {
columnWidth: '50%',
borderRadius: 6,
},
},
},
},
{
breakpoint: 600,
options: {
plotOptions: {
bar: {
columnWidth: '35%',
borderRadius: 6,
},
},
},
},
{
breakpoint: 480,
options: {
chart: {
height: 250,
offsetX: -10,
},
plotOptions: { bar: { columnWidth: '45%' } },
xaxis: {
labels: {
rotate: 315,
rotateAlways: true,
},
},
},
},
{
breakpoint: 420,
options: { plotOptions: { bar: { columnWidth: '60%' } } },
},
],
}
})
const series = [
{
name: 'Revenue',
data: [
29000,
22000,
25000,
18500,
29000,
20000,
34500,
],
},
{
name: 'Transactions',
data: [
0,
16000,
11000,
15500,
0,
12500,
9500,
],
},
{
name: 'Total Profit',
data: [
0,
0,
0,
14000,
0,
11500,
12000,
],
},
]
const lastThreeTransactions = [
{
avatar: {
icon: 'ri-pie-chart-2-line',
color: 'success',
},
title: '$48,568.20',
subtitle: 'Total Profit',
},
{
avatar: {
icon: 'ri-money-dollar-circle-line',
color: 'primary',
},
title: '$38,453.25',
subtitle: 'Total Income',
},
{
avatar: {
icon: 'ri-bank-card-line',
color: 'secondary',
},
title: '$2,453.45',
subtitle: 'Total Expense',
},
]
</script>
<template>
<VCard>
<VRow no-gutters>
<VCol
cols="12"
sm="8"
class="responsive-border"
>
<VCardText>
<h5 class="text-h5">
Total Profit
</h5>
<VueApexCharts
type="bar"
:options="options"
:series="series"
:height="280"
/>
</VCardText>
</VCol>
<VCol
cols="12"
sm="4"
>
<VCardItem>
<VCardTitle>
$482.85k
</VCardTitle>
<VCardSubtitle>Last month balance $234.40k</VCardSubtitle>
<template #append>
<div class="mt-n7 me-n3">
<MoreBtn density="compact" />
</div>
</template>
</VCardItem>
<VCardText class="pt-1">
<VList class="card-list mt-2">
<VListItem
v-for="transaction in lastThreeTransactions"
:key="transaction.title"
>
<template #prepend>
<VAvatar
:color="transaction.avatar.color"
variant="tonal"
rounded
>
<VIcon :icon="transaction.avatar.icon" />
</VAvatar>
</template>
<VListItemTitle class="font-weight-medium">
{{ transaction.title }}
</VListItemTitle>
<VListItemSubtitle>
<div class="text-body-1">
{{ transaction.subtitle }}
</div>
</VListItemSubtitle>
</VListItem>
</VList>
<VBtn
block
class="mt-4"
>
View Report
</VBtn>
</VCardText>
</VCol>
</VRow>
</VCard>
</template>
<style lang="scss">
$responsive-border: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
@media screen and (min-width: 600px) {
.responsive-border {
border-inline-end: $responsive-border;
}
}
@media screen and (max-width: 599px) {
.responsive-border {
border-block-end: $responsive-border;
}
}
</style>
<style lang="scss" scoped>
.card-list {
--v-card-list-gap: 1rem;
}
</style>

View File

@@ -0,0 +1,79 @@
<script setup>
import { useTheme } from 'vuetify'
import { hexToRgb } from '@layouts/utils'
const vuetifyTheme = useTheme()
const options = computed(() => {
const currentTheme = ref(vuetifyTheme.current.value.colors)
const variableTheme = ref(vuetifyTheme.current.value.variables)
const primaryTextColor = `rgba(${ hexToRgb(currentTheme.value['on-surface']) },${ variableTheme.value['high-emphasis-opacity'] })`
return {
chart: { sparkline: { enabled: true } },
stroke: { dashArray: 5 },
colors: ['rgba(var(--v-theme-primary),1)'],
states: {
hover: { filter: { type: 'none' } },
active: { filter: { type: 'none' } },
},
plotOptions: {
radialBar: {
endAngle: 90,
startAngle: -90,
hollow: { size: '55%' },
track: { background: currentTheme.value['track-bg'] },
dataLabels: {
name: { show: false },
value: {
offsetY: -5,
fontSize: '18px',
fontWeight: 500,
color: primaryTextColor,
formatter: val => {
const num = val * 35250 / 100
return num > 999 ? `${ (num / 1000).toFixed(1) }k` : `${ num }`
},
},
},
},
},
}
})
const series = [80]
</script>
<template>
<VCard>
<VCardItem>
<VCardTitle>Total Profit</VCardTitle>
<template #append>
<div class="me-n3">
<MoreBtn />
</div>
</template>
</VCardItem>
<VueApexCharts
type="radialBar"
:options="options"
:series="series"
/>
<VCardText class="text-center">
<div class="mt-5">
<p class="text-body-1 mb-2">
18k new sales
</p>
<VChip
color="primary"
size="small"
>
This Year
</VChip>
</div>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,142 @@
<script setup>
import { useTheme } from 'vuetify'
import { hexToRgb } from '@layouts/utils'
const vuetifyTheme = useTheme()
const options = computed(() => {
const currentTheme = ref(vuetifyTheme.current.value.colors)
const variableTheme = ref(vuetifyTheme.current.value.variables)
const secondaryTextColor = `rgba(${ hexToRgb(currentTheme.value['on-surface']) },${ variableTheme.value['medium-emphasis-opacity'] })`
const primaryTextColor = `rgba(${ hexToRgb(currentTheme.value['on-surface']) },${ variableTheme.value['high-emphasis-opacity'] })`
return {
chart: { sparkline: { enabled: true } },
labels: [
'Returning',
'New Users',
'Referrals',
],
legend: { show: false },
stroke: { lineCap: 'round' },
colors: [
'rgba(var(--v-theme-primary),1)',
currentTheme.value.success,
currentTheme.value.warning,
],
states: {
hover: { filter: { type: 'none' } },
active: { filter: { type: 'none' } },
},
plotOptions: {
radialBar: {
hollow: { size: '40%' },
track: {
background: 'transparent',
margin: 10,
},
dataLabels: {
name: {
offsetY: 28,
color: secondaryTextColor,
},
value: {
fontSize: '1.75rem',
offsetY: -12,
color: primaryTextColor,
formatter(value) {
return `${ value }k`
},
},
total: {
show: true,
label: `${ new Date().getFullYear() }`,
color: secondaryTextColor,
fontSize: '13px',
fontWeight: 400,
formatter(value) {
return `${ value.globals.seriesTotals.reduce((total, num) => total + num) }k`
},
},
},
},
},
}
})
const series = [
71,
78,
86,
]
const revenueData = [
{
title: 'New User',
value: 856,
color: 'success',
},
{
title: 'Returning',
value: 345,
color: 'primary',
},
{
title: 'Referrals',
value: 258,
color: 'warning',
},
]
</script>
<template>
<VCard>
<VCardItem>
<VCardTitle>Total Revenue</VCardTitle>
<template #append>
<div class="me-n3">
<MoreBtn />
</div>
</template>
</VCardItem>
<VCardText>
<VueApexCharts
type="radialBar"
:options="options"
:series="series"
:height="243"
/>
<div class="d-flex justify-space-around mt-4">
<template
v-for="(item, index) in revenueData"
:key="index"
>
<div>
<div class="d-flex align-center">
<VIcon
size="10"
:color="item.color"
icon="ri-circle-fill"
class="me-2"
/>
<h6 class="text-h6">
{{ item.value }}
</h6>
</div>
<div class="text-base">
{{ item.title }}
</div>
</div>
<VDivider
v-if="index !== revenueData.length - 1"
vertical
/>
</template>
</div>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,101 @@
<script setup>
import { useTheme } from 'vuetify'
import { hexToRgb } from '@layouts/utils'
const vuetifyTheme = useTheme()
const options = computed(() => {
const currentTheme = ref(vuetifyTheme.current.value.colors)
const variableTheme = ref(vuetifyTheme.current.value.variables)
const secondaryTextColor = `rgba(${ hexToRgb(currentTheme.value['on-surface']) },${ variableTheme.value['medium-emphasis-opacity'] })`
return {
chart: {
parentHeightOffset: 0,
toolbar: { show: false },
},
fill: {
type: 'gradient',
gradient: {
opacityTo: 0.2,
opacityFrom: 1,
shadeIntensity: 0,
type: 'horizontal',
stops: [
0,
100,
100,
],
},
},
stroke: {
width: 5,
curve: 'smooth',
lineCap: 'round',
},
legend: { show: false },
colors: [currentTheme.value.success],
grid: {
show: false,
padding: {
left: 0,
right: 0,
bottom: -10,
},
},
xaxis: {
axisTicks: { show: false },
axisBorder: { show: false },
categories: [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
],
labels: { style: { colors: secondaryTextColor } },
},
yaxis: { labels: { show: false } },
tooltip: { enabled: false },
}
})
const series = [{
name: 'Total Sales',
data: [
0,
258,
30,
240,
150,
400,
],
}]
</script>
<template>
<VCard>
<VCardItem>
<VCardTitle class="mb-1">
Total Sales
</VCardTitle>
<VCardSubtitle>$21,845</VCardSubtitle>
<template #append>
<div class="mt-n7 me-n3">
<MoreBtn />
</div>
</template>
</VCardItem>
<VCardText>
<VueApexCharts
type="line"
:options="options"
:series="series"
:height="206"
/>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,101 @@
<script setup>
import { useTheme } from 'vuetify'
import { hexToRgb } from '@layouts/utils'
const vuetifyTheme = useTheme()
const options = computed(() => {
const currentTheme = ref(vuetifyTheme.current.value.colors)
const variableTheme = ref(vuetifyTheme.current.value.variables)
const secondaryTextColor = `rgba(${ hexToRgb(currentTheme.value['on-surface']) },${ variableTheme.value['medium-emphasis-opacity'] })`
const primaryTextColor = `rgba(${ hexToRgb(currentTheme.value['on-surface']) },${ variableTheme.value['high-emphasis-opacity'] })`
return {
colors: [
'rgba(var(--v-theme-primary),1)',
'rgba(var(--v-theme-primary), 0.7)',
'rgba(var(--v-theme-primary), 0.5)',
currentTheme.value['track-bg'],
],
stroke: { width: 0 },
dataLabels: { enabled: false },
legend: {
show: true,
position: 'bottom',
markers: {
width: 10,
height: 10,
},
labels: { colors: secondaryTextColor },
},
labels: [
'FR',
'UK',
'ESP',
'USA',
],
states: {
hover: { filter: { type: 'none' } },
active: { filter: { type: 'none' } },
},
plotOptions: {
pie: {
customScale: 0.9,
donut: {
size: '70%',
labels: {
show: true,
name: {
offsetY: 25,
color: secondaryTextColor,
},
value: {
offsetY: -15,
fontWeight: 500,
fontSize: '24px',
color: primaryTextColor,
formatter: value => `${ value }%`,
},
total: {
show: true,
label: 'Weekly Visits',
fontSize: '15px',
color: secondaryTextColor,
formatter: value => `${ value.globals.seriesTotals.reduce((total, num) => total + num) }%`,
},
},
},
},
},
}
})
const series = [
12,
25,
13,
50,
]
</script>
<template>
<VCard>
<VCardItem>
<VCardTitle>Total Visitors</VCardTitle>
<template #append>
<div class="me-n3">
<MoreBtn density="compact" />
</div>
</template>
</VCardItem>
<VCardText>
<VueApexCharts
type="donut"
:options="options"
:series="series"
:height="292"
/>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,100 @@
<script setup>
import { useTheme } from 'vuetify'
import { hexToRgb } from '@layouts/utils'
const vuetifyTheme = useTheme()
const options = computed(() => {
const currentTheme = ref(vuetifyTheme.current.value.colors)
const variableTheme = ref(vuetifyTheme.current.value.variables)
const secondaryTextColor = `rgba(${ hexToRgb(currentTheme.value['on-surface']) },${ variableTheme.value['medium-emphasis-opacity'] })`
const primaryTextColor = `rgba(${ hexToRgb(currentTheme.value['on-surface']) },${ variableTheme.value['high-emphasis-opacity'] })`
return {
chart: { sparkline: { enabled: true } },
labels: ['Cricket'],
stroke: { lineCap: 'round' },
grid: { padding: { top: -10 } },
colors: [currentTheme.value.info],
fill: {
type: 'gradient',
gradient: {
shade: 'light',
type: 'horizontal',
shadeIntensity: 0.2,
inverseColors: false,
opacityFrom: 1,
opacityTo: 0.1,
stops: [
0,
90,
],
},
},
states: {
hover: { filter: { type: 'none' } },
active: { filter: { type: 'none' } },
},
plotOptions: {
radialBar: {
endAngle: 180,
startAngle: -180,
inverseOrder: true,
hollow: { size: '62%' },
track: { background: currentTheme.value['track-bg'] },
dataLabels: {
name: { offsetY: 26 },
value: {
offsetY: -14,
fontSize: '24px',
fontWeight: 500,
color: primaryTextColor,
formatter: value => `${ value }k`,
},
total: {
show: true,
label: 'Growth',
fontSize: '15px',
fontWeight: 500,
color: secondaryTextColor,
},
},
},
},
}
})
const series = [78]
</script>
<template>
<VCard>
<VCardItem>
<VCardTitle>Total Visits</VCardTitle>
<template #append>
<div class="me-n3">
<MoreBtn density="compact" />
</div>
</template>
</VCardItem>
<VueApexCharts
type="radialBar"
:options="options"
:series="series"
:height="199"
/>
<VCardText class="text-center pt-0">
<div class="text-body-1 mb-2">
42.2k new visits
</div>
<VChip
color="info"
size="small"
>
This year
</VChip>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,137 @@
<script setup>
import { useTheme } from 'vuetify'
import { hexToRgb } from '@layouts/utils'
const vuetifyTheme = useTheme()
const options = computed(() => {
const currentTheme = ref(vuetifyTheme.current.value.colors)
const variableTheme = ref(vuetifyTheme.current.value.variables)
const disabledColor = `rgba(${ hexToRgb(currentTheme.value['on-surface']) },${ variableTheme.value['disabled-opacity'] })`
const borderColor = `rgba(${ hexToRgb(String(variableTheme.value['border-color'])) },${ variableTheme.value['border-opacity'] })`
return {
chart: {
offsetY: -10,
offsetX: -15,
parentHeightOffset: 0,
toolbar: { show: false },
},
plotOptions: {
bar: {
borderRadius: 6,
distributed: true,
columnWidth: '30%',
},
},
stroke: {
width: 2,
colors: [currentTheme.value.surface],
},
legend: { show: false },
grid: {
borderColor,
strokeDashArray: 7,
xaxis: { lines: { show: false } },
},
dataLabels: { enabled: false },
colors: [
currentTheme.value['track-bg'],
currentTheme.value['track-bg'],
currentTheme.value['track-bg'],
'rgba(var(--v-theme-primary),1)',
currentTheme.value['track-bg'],
currentTheme.value['track-bg'],
],
states: {
hover: { filter: { type: 'none' } },
active: { filter: { type: 'none' } },
},
xaxis: {
categories: [
'Sun',
'Mon',
'Tue',
'Wed',
'Thu',
'Fri',
'Sat',
],
tickPlacement: 'on',
labels: { show: false },
crosshairs: { opacity: 0 },
axisTicks: { show: false },
axisBorder: { show: false },
},
yaxis: {
show: true,
tickAmount: 4,
labels: {
style: {
colors: disabledColor,
fontSize: '13px',
},
formatter: value => `${ value > 999 ? `${ (value / 1000).toFixed(0) }` : value }k`,
},
},
responsive: [
{
breakpoint: 1560,
options: { plotOptions: { bar: { columnWidth: '35%' } } },
},
{
breakpoint: 1380,
options: { plotOptions: { bar: { columnWidth: '45%' } } },
},
],
}
})
const series = [{
data: [
37,
57,
45,
75,
57,
40,
65,
],
}]
</script>
<template>
<VCard>
<VCardItem>
<VCardTitle>Weekly Overview</VCardTitle>
<template #append>
<div class="me-n3">
<MoreBtn />
</div>
</template>
</VCardItem>
<VCardText>
<VueApexCharts
type="bar"
:options="options"
:series="series"
:height="200"
/>
<div class="d-flex align-center mb-3 gap-x-4">
<h4 class="text-h4">
45%
</h4>
<p class="mb-0">
Your sales performance is 45% <span class="text-high-emphasis">😎</span> better compared to last month
</p>
</div>
<VBtn block>
Details
</VBtn>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,155 @@
<script setup>
import { useTheme } from 'vuetify'
import { hexToRgb } from '@layouts/utils'
const vuetifyTheme = useTheme()
const options = computed(() => {
const currentTheme = ref(vuetifyTheme.current.value.colors)
const variableTheme = ref(vuetifyTheme.current.value.variables)
const secondaryColor = `rgba(${ hexToRgb(currentTheme.value['on-surface']) },${ variableTheme.value['medium-emphasis-opacity'] })`
return {
chart: {
parentHeightOffset: 0,
toolbar: { show: false },
},
plotOptions: {
bar: {
borderRadius: 4,
distributed: true,
columnWidth: '60%',
},
},
legend: { show: false },
dataLabels: { enabled: false },
colors: [
'rgba(var(--v-theme-primary), 0.16)',
'rgba(var(--v-theme-primary), 0.16)',
'rgba(var(--v-theme-primary), 0.16)',
'rgba(var(--v-theme-primary), 0.16)',
'rgba(var(--v-theme-primary),1)',
'rgba(var(--v-theme-primary), 0.16)',
'rgba(var(--v-theme-primary), 0.16)',
],
states: {
hover: { filter: { type: 'none' } },
active: { filter: { type: 'none' } },
},
xaxis: {
categories: [
'S',
'M',
'T',
'W',
'T',
'F',
'S',
],
axisTicks: { show: false },
crosshairs: { opacity: 0 },
axisBorder: { show: false },
tickPlacement: 'on',
labels: {
style: {
fontSize: '13px',
colors: secondaryColor,
},
},
},
yaxis: { show: false },
grid: {
show: false,
padding: {
top: -15,
left: -10,
right: -10,
},
},
tooltip: { enabled: false },
}
})
const series = [{
data: [
40,
60,
50,
60,
90,
40,
50,
],
}]
const weeklySalesData = [
{
avatar: {
icon: 'ri-pie-chart-2-line',
color: 'primary',
},
title: '34.6k',
subtitle: 'Sales',
},
{
avatar: {
icon: 'ri-money-dollar-circle-line',
color: 'success',
},
title: '$482k',
subtitle: 'Total Profit',
},
]
</script>
<template>
<VCard>
<VCardItem>
<VCardTitle>Weekly Sales</VCardTitle>
<VCardSubtitle>Total 85.4k Sales</VCardSubtitle>
<template #append>
<div class="mt-n7 me-n3">
<MoreBtn density="compact" />
</div>
</template>
</VCardItem>
<VCardText>
<VueApexCharts
type="bar"
:options="options"
:series="series"
:height="203"
/>
</VCardText>
<VCardText class="d-flex justify-space-around">
<div
v-for="data in weeklySalesData"
:key="data.title"
class="d-flex align-center me-3"
>
<div>
<VAvatar
rounded
:color="data.avatar.color"
variant="tonal"
class="me-3"
>
<VIcon :icon="data.avatar.icon" />
</VAvatar>
</div>
<div>
<h6 class="text-h6">
{{ data.title }}
</h6>
<div class="text-base text-no-wrap">
{{ data.subtitle }}
</div>
</div>
</div>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,238 @@
<script setup>
const borderColor = 'rgba(var(--v-border-color), var(--v-border-opacity))'
// Topics Charts config
const topicsChartConfig = {
chart: {
height: 270,
type: 'bar',
toolbar: { show: false },
},
plotOptions: {
bar: {
horizontal: true,
barHeight: '70%',
distributed: true,
borderRadius: 7,
borderRadiusApplication: 'end',
},
},
colors: [
'rgba(var(--v-theme-primary),1)',
'#16B1FF',
'#56CA00',
'#8A8D93',
'#FF4C51',
'#FFB400',
],
grid: {
borderColor,
strokeDashArray: 10,
xaxis: { lines: { show: true } },
yaxis: { lines: { show: false } },
padding: {
top: -35,
bottom: -12,
},
},
dataLabels: {
enabled: true,
style: {
colors: ['#fff'],
fontWeight: 200,
fontSize: '13px',
},
offsetX: 0,
dropShadow: { enabled: false },
formatter(val, opt) {
return topicsChartConfig.labels[opt.dataPointIndex]
},
},
labels: [
'UI Design',
'UX Design',
'Music',
'Animation',
'Vue',
'SEO',
],
xaxis: {
categories: [
'6',
'5',
'4',
'3',
'2',
'1',
],
axisBorder: { show: false },
axisTicks: { show: false },
labels: {
style: {
colors: 'rgba(var(--v-theme-on-background), var(--v-disabled-opacity))',
fontSize: '13px',
},
formatter(val) {
return `${ val }%`
},
},
},
yaxis: {
max: 35,
labels: {
style: {
colors: 'rgba(var(--v-theme-on-background), var(--v-disabled-opacity))',
fontSize: '13px',
},
},
},
tooltip: {
enabled: true,
style: { fontSize: '12px' },
onDatasetHover: { highlightDataSeries: false },
},
legend: { show: false },
}
const topicsChartSeries = [{
data: [
35,
20,
14,
12,
10,
9,
],
}]
const topicsData = [
{
title: 'UI Design',
value: 35,
color: 'primary',
},
{
title: 'UX Design',
value: 20,
color: 'info',
},
{
title: 'Music',
value: 14,
color: 'success',
},
]
const moreTopics = [
{
title: 'Animation',
value: 12,
color: 'secondary',
},
{
title: 'Vue',
value: 10,
color: 'error',
},
{
title: 'SEO',
value: 9,
color: 'warning',
},
]
</script>
<template>
<VCard class="topicCard">
<VCardItem title="Topic you are interested in">
<template #append>
<MoreBtn />
</template>
</VCardItem>
<VCardText>
<VRow>
<VCol
cols="12"
lg="6"
>
<VueApexCharts
type="bar"
height="300"
:options="topicsChartConfig"
:series="topicsChartSeries"
class="mb-md-0 mb-6"
/>
</VCol>
<VCol class="d-flex justify-space-around align-center">
<div class="d-flex flex-column gap-y-12">
<div
v-for="topic in topicsData"
:key="topic.title"
class="d-flex gap-x-2"
>
<VBadge
inline
dot
:color="topic.color"
class="mt-1"
/>
<div>
<div
class="text-body-1"
style="min-inline-size: 90px;"
>
{{ topic.title }}
</div>
<h5 class="text-h5">
{{ topic.value }}%
</h5>
</div>
</div>
</div>
<div class="d-flex flex-column gap-y-12">
<div
v-for="topic in moreTopics"
:key="topic.title"
class="d-flex gap-x-2"
>
<VBadge
inline
dot
:color="topic.color"
class="mt-1"
/>
<div>
<div
class="text-body-1"
style="min-inline-size: 90px;"
>
{{ topic.title }}
</div>
<h5 class="text-h5">
{{ topic.value }}%
</h5>
</div>
</div>
</div>
</VCol>
</VRow>
</VCardText>
</VCard>
</template>
<style lang="scss">
@use "@core-scss/template/libs/apex-chart.scss";
.topicCard{
.v-badge.v-badge--dot{
.v-badge__badge{
border-radius: 6px;
block-size: 12px;
inline-size: 12px;
}
}
}
</style>

View File

@@ -0,0 +1,49 @@
<script setup>
import trophy from '@images/misc/trophy.png'
</script>
<template>
<VCard class="position-relative">
<VCardText>
<div class="mb-3">
<h5 class="text-h5">
Congratulations John! <span class="text-high-emphasis">🎉</span>
</h5>
<div class="text-body-1">
Best seller of the month
</div>
</div>
<h4 class="text-h4 text-primary">
$42.8k
</h4>
<div class="text-body-1 mb-3">
78% of target <span class="text-high-emphasis">🚀</span>
</div>
<VBtn size="small">
View Sales
</VBtn>
</VCardText>
<!-- Trophy -->
<VImg
:src="trophy"
class="trophy"
/>
</VCard>
</template>
<style lang="scss">
.v-card .triangle-bg {
position: absolute;
inline-size: 10.375rem;
inset-block-end: 0;
inset-inline-end: 0;
}
.v-card .trophy {
position: absolute;
inline-size: 5.188rem;
inset-block-end: 1rem;
inset-inline-end: 1rem;
}
</style>

View File

@@ -0,0 +1,53 @@
<script setup>
import illustrationJohn2 from '@images/cards/illustration-john-2.png'
</script>
<template>
<VCard class="overflow-visible">
<VRow no-gutters>
<VCol
cols="12"
sm="6"
order="2"
order-sm="1"
>
<VCardItem>
<VCardTitle>
<h4 class="text-h4 text-wrap">
Congratulations <strong>John!</strong> <span class="text-high-emphasis">🎉</span>
</h4>
</VCardTitle>
</VCardItem>
<VCardText class="pt-4">
<div class="mb-0 text-body-1 me-2">
You have done 72% <span class="text-high-emphasis">😎</span> more sales today.
Check your new raising badge in your profile.
</div>
</VCardText>
</VCol>
<VCol
cols="12"
sm="6"
order="1"
order-sm="2"
class="text-center"
>
<img
:src="illustrationJohn2"
:height="$vuetify.display.xs ? '165' : '200'"
:class="$vuetify.display.xs ? 'position-relative' : 'position-absolute'"
class="john-illustration flip-in-rtl mt-6 mt-sm-0"
>
</VCol>
</VRow>
</VCard>
</template>
<style lang="scss" scoped>
.john-illustration {
inset-block-end: -0.0625rem;
inset-inline-end: 0;
}
</style>

View File

@@ -0,0 +1,49 @@
<script setup>
import poseM9 from '@images/cards/pose-m-9.png'
</script>
<template>
<VCard class="position-relative">
<VCardText>
<div class="mb-3">
<h5 class="text-h5">
Upgrade Account <span class="text-high-emphasis">😀</span>
</h5>
<div class="text-body-1">
Add 15 team members
</div>
</div>
<h4 class="text-h4 text-primary">
$199
</h4>
<div class="text-body-1 mb-3">
40% OFF <span class="text-high-emphasis">😍</span>
</div>
<VBtn size="small">
Upgrade Plan
</VBtn>
</VCardText>
<!-- Trophy -->
<VImg
:src="poseM9"
class="illustration flip-in-rtl"
/>
</VCard>
</template>
<style lang="scss">
.v-card .triangle-bg {
position: absolute;
inline-size: 10.375rem;
inset-block-end: 0;
inset-inline-end: 0;
}
.v-card .illustration {
position: absolute;
inline-size: 3rem;
inset-block-end: 1rem;
inset-inline-end: 3rem;
}
</style>

View File

@@ -0,0 +1,56 @@
<script setup>
import illustrationJohn from '@images/cards/illustration-john.png'
</script>
<template>
<VCard class="overflow-visible">
<VRow no-gutters>
<VCol
cols="12"
sm="6"
>
<VCardItem>
<VCardTitle>
<h4 class="text-h4 text-wrap">
Welcome back <strong>John!</strong> <span class="text-high-emphasis">🥳</span>
</h4>
</VCardTitle>
</VCardItem>
<VCardText class="pt-4">
<div class="text-body-1 me-2">
You have 4 tasks to finish today,
You already completed 68% <span class="text-high-emphasis">😍</span> tasks. Good job!
</div>
</VCardText>
</VCol>
<VCol
cols="12"
sm="6"
class="text-center"
>
<img
:src="illustrationJohn"
class="john-illustration"
:height="$vuetify.display.xs ? '165' : '200'"
:class="$vuetify.display.xs ? 'position-relative' : 'position-absolute'"
>
</VCol>
</VRow>
</VCard>
</template>
<style lang="scss" scoped>
.john-illustration {
inset-block-end: 0;
inset-inline-end: 0;
}
@media (max-width: 600px) {
.john-illustration {
inset-block-end: -0.375rem;
inset-inline-end: 0;
}
}
</style>

View File

@@ -0,0 +1,56 @@
<script setup>
import { VNodeRenderer } from '@layouts/components/VNodeRenderer'
const props = defineProps({
articles: {
type: Array,
required: true,
},
})
</script>
<template>
<VRow>
<VCol
v-for="article in props.articles"
:key="article.title"
cols="12"
md="4"
>
<VCard
flat
border
>
<VCardText class="text-center">
<VNodeRenderer :nodes="h('div', { class: 'help-center-article-icon', innerHTML: article.img })" />
<h5 class="text-h5 my-3">
{{ article.title }}
</h5>
<p class="clamp-text text-body-1 mb-3 mx-auto">
{{ article.subtitle }}
</p>
<VBtn
variant="outlined"
:to="{
name: 'front-pages-help-center-article-title',
params: {
title: 'how-to-add-product-in-cart',
},
}"
>
Read More
</VBtn>
</VCardText>
</VCard>
</VCol>
</VRow>
</template>
<style lang="scss">
.help-center-article-icon svg {
block-size: 58px;
inline-size: 58px;
}
</style>

View File

@@ -0,0 +1,19 @@
<template>
<div
class="text-center"
style="padding-block: 6.25rem;"
>
<h4 class="text-h4 text-center mb-4">
Still need help?
</h4>
<p class="text-body-1">
Our specialists are always happy to help.
<br>
Contact us during standard business hours or email us 24/7 and we'll get back to you.
</p>
<div class="d-flex justify-center gap-4 flex-wrap">
<VBtn>Visit our community</VBtn>
<VBtn>Contact us</VBtn>
</div>
</div>
</template>

View File

@@ -0,0 +1,97 @@
<script setup>
const props = defineProps({
categories: {
type: Array,
required: true,
},
})
</script>
<template>
<VRow>
<VCol
v-for="article in props.categories"
:key="article.title"
cols="12"
sm="6"
lg="4"
>
<VCard>
<VCardItem class="pb-6">
<div class="d-flex align-center">
<VAvatar
rounded
color="primary"
variant="tonal"
class="me-3"
size="32"
>
<VIcon
:icon="article.icon"
size="20"
/>
</VAvatar>
<VCardTitle>{{ article.title }}</VCardTitle>
</div>
</VCardItem>
<VCardText>
<VList class="card-list">
<VListItem
v-for="(item, index) in article.articles"
:key="index"
>
<RouterLink
:to="{
name: 'front-pages-help-center-article-title',
params: {
title: 'how-to-add-product-in-cart',
},
}"
class="text-high-emphasis"
>
{{ item.title }}
</RouterLink>
<template #append>
<VIcon
icon="ri-arrow-right-s-line"
size="20"
class="text-disabled"
/>
</template>
</VListItem>
</VList>
<div class="text-base font-weight-medium mt-4 d-flex align-center gap-x-3">
<RouterLink
:to="{
name: 'front-pages-help-center-article-title',
params: {
title: 'how-to-add-product-in-cart',
},
}"
>
<div class="d-flex align-center gap-x-3">
<div>
See all {{ article.articles.length }} Articles
</div>
<VIcon
icon="ri-arrow-right-line"
size="18"
color="primary"
/>
</div>
</RouterLink>
</div>
</VCardText>
</VCard>
</VCol>
</VRow>
</template>
<style lang="scss">
.card-list {
--v-card-list-gap: 0.5rem;
}
</style>

View File

@@ -0,0 +1,47 @@
<template>
<VCard title="Headlines">
<VCardText class="d-flex flex-column gap-y-8">
<div>
<h1 class="text-h1">
Heading 1
</h1>
<span>font-size: 2.875rem / line-height: 4.25rem / font-weight: 500</span>
</div>
<div>
<h2 class="text-h2">
Heading 2
</h2>
<span>font-size: 2.375rem / line-height: 3.5rem / font-weight: 500</span>
</div>
<div>
<h3 class="text-h3">
Heading 3
</h3>
<span>font-size: 1.75rem / line-height: 2.625rem / font-weight: 500</span>
</div>
<div>
<h4 class="text-h4">
Heading 4
</h4>
<span>font-size: 1.5rem / line-height: 2.375rem / font-weight: 500</span>
</div>
<div>
<h5 class="text-h5">
Heading 5
</h5>
<span>font-size: 1.125rem / line-height: 1.75rem / font-weight: 500</span>
</div>
<div>
<h6 class="text-h6">
Heading 6
</h6>
<span>font-size: 0.9375rem / line-height: 1.75rem / font-weight: 500</span>
</div>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,121 @@
<template>
<VCard title="Texts">
<VCardText>
<VRow no-gutters>
<VCol
cols="12"
md="2"
>
<p class="text-subtitle-1 text-no-wrap">
text-subtitle-1
</p>
</VCol>
<VCol
cols="12"
md="10"
class="mb-6"
>
<p class="text-subtitle-1 text-truncate mb-1">
Cupcake ipsum dolor sit amet fruitcake donut chocolate.
</p>
<span>font-size: 0.9375rem / line-height: 1.5rem / font-weight: 500</span>
</VCol>
<VCol
cols="12"
md="2"
>
<p class="text-subtitle-2 text-no-wrap">
text-subtitle-2
</p>
</VCol>
<VCol
cols="12"
md="10"
class="mb-6"
>
<p class="text-subtitle-2 mb-1">
Cupcake ipsum dolor sit amet fruitcake donut chocolate.
</p>
<span>font-size: 0.8125rem / line-height: 1.25rem / font-weight: 500</span>
</VCol>
<VCol
cols="12"
md="2"
>
<p class="text-body-1 text-no-wrap">
text-body-1
</p>
</VCol>
<VCol
cols="12"
md="10"
class="mb-6"
>
<p class="text-body-1 mb-1">
Cupcake ipsum dolor sit amet fruitcake donut chocolate.
</p>
<span>font-size: 0.9375rem / line-height: 1.375rem / font-weight: 400</span>
</VCol>
<VCol
cols="12"
md="2"
>
<p class="text-body-2 text-no-wrap">
text-body-2
</p>
</VCol>
<VCol
cols="12"
md="10"
class="mb-6"
>
<p class="text-body-2 mb-1">
Cupcake ipsum dolor sit amet fruitcake donut chocolate.
</p>
<span>font-size: 0.8125rem / line-height: 1.25rem / font-weight: 400</span>
</VCol>
<VCol
cols="12"
md="2"
>
<p class="text-caption">
text-caption
</p>
</VCol>
<VCol
cols="12"
md="10"
class="mb-6"
>
<p class="text-caption mb-1">
Cupcake ipsum dolor sit amet fruitcake donut chocolate.
</p>
<span>font-size: 0.8125rem / line-height: 1.125rem / font-weight: 400</span>
</VCol>
<VCol
cols="12"
md="2"
>
<p class="text-overline text-no-wrap">
text-overline
</p>
</VCol>
<VCol
cols="12"
md="10"
class="mb-6"
>
<p class="text-overline mb-1">
Cupcake ipsum dolor sit amet fruitcake donut chocolate.
</p>
<span>font-size: 0.75rem / line-height: 0.875rem / font-weight: 400</span>
</VCol>
</VRow>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,94 @@
<script setup>
const profileHeaderData = ref()
const { data, error } = await useApi('/pages/profile/header')
if (error.value) {
console.log(error.value)
} else {
if (data.value)
profileHeaderData.value = data.value
}
</script>
<template>
<VCard v-if="profileHeaderData">
<VImg
:src="profileHeaderData.coverImg"
min-height="125"
max-height="250"
cover
/>
<VCardText class="d-flex align-bottom flex-sm-row flex-column justify-center gap-x-6">
<div class="d-flex h-0">
<VAvatar
rounded
size="130"
:image="profileHeaderData.profileImg"
class="user-profile-avatar mx-auto"
>
<VImg
:src="profileHeaderData.profileImg"
height="120"
width="120"
/>
</VAvatar>
</div>
<div class="user-profile-info w-100 mt-16 pt-6 pt-sm-0 mt-sm-0">
<h4 class="text-h4 text-center text-sm-start mb-2">
{{ profileHeaderData.fullName }}
</h4>
<div class="d-flex align-center justify-center justify-sm-space-between flex-wrap gap-4">
<div class="d-flex flex-wrap justify-center justify-sm-start flex-grow-1 gap-6">
<div class="d-flex align-center gap-x-2">
<VIcon
size="24"
icon="ri-palette-line"
/>
<div class="text-body-1 font-weight-medium">
{{ profileHeaderData.designation }}
</div>
</div>
<div class="d-flex align-center gap-x-2">
<VIcon
size="24"
icon="ri-map-pin-line"
/>
<div class="text-body-1 font-weight-medium">
{{ profileHeaderData.location }}
</div>
</div>
<div class="d-flex align-center gap-x-2">
<VIcon
size="24"
icon="ri-calendar-line"
/>
<div class="text-body-1 font-weight-medium">
{{ profileHeaderData.joiningDate }}
</div>
</div>
</div>
<VBtn prepend-icon="ri-user-follow-line">
Connected
</VBtn>
</div>
</div>
</VCardText>
</VCard>
</template>
<style lang="scss">
.user-profile-avatar {
border: 5px solid rgb(var(--v-theme-surface));
background-color: rgb(var(--v-theme-surface)) !important;
inset-block-start: -3rem;
.v-img__img {
border-radius: 0.375rem;
}
}
</style>

View File

@@ -0,0 +1,135 @@
<script setup>
const router = useRoute('pages-user-profile-tab')
const connectionData = ref([])
const fetchProjectData = async () => {
if (router.params.tab === 'connections') {
const data = await $api('/pages/profile', { query: { tab: router.params.tab } }).catch(err => console.log(err))
connectionData.value = data
}
}
watch(router, fetchProjectData, { immediate: true })
const moreBtnList = [
{
title: 'Share connection',
value: 'Share connection',
},
{
title: 'Block connection',
value: 'Block connection',
},
{
type: 'divider',
class: 'my-2',
},
{
title: 'Delete',
value: 'Delete',
class: 'text-error',
},
]
</script>
<template>
<VRow>
<VCol
v-for="data in connectionData"
:key="data.name"
sm="6"
lg="4"
cols="12"
>
<VCard>
<div class="vertical-more">
<MoreBtn
item-props
:menu-list="moreBtnList"
/>
</div>
<VCardText>
<div class="d-flex flex-column align-center justify-center">
<VAvatar
size="100"
:image="data.avatar"
class="mb-6"
/>
<h5 class="text-h5">
{{ data.name }}
</h5>
<div class="text-body-1">
{{ data.designation }}
</div>
<div class="d-flex align-center flex-wrap gap-4 my-6">
<VChip
v-for="chip in data.chips"
:key="chip.title"
:color="chip.color"
size="small"
>
{{ chip.title }}
</VChip>
</div>
</div>
<div class="d-flex justify-space-around">
<div class="text-center">
<h5 class="text-h5">
{{ data.projects }}
</h5>
<div class="text-body-1">
Projects
</div>
</div>
<div class="text-center">
<h5 class="text-h5">
{{ data.tasks }}
</h5>
<div class="text-body-1">
Tasks
</div>
</div>
<div class="text-center">
<h5 class="text-h5">
{{ data.connections }}
</h5>
<div class="text-body-1">
Connections
</div>
</div>
</div>
<div class="d-flex justify-center gap-4 mt-6">
<VBtn
:prepend-icon="data.isConnected ? 'ri-user-follow-line' : 'ri-user-add-line'"
:variant="data.isConnected ? 'elevated' : 'outlined'"
>
{{ data.isConnected ? 'connected' : 'connect' }}
</VBtn>
<IconBtn
color="secondary"
variant="outlined"
rounded
>
<VIcon icon="ri-mail-open-line" />
</IconBtn>
</div>
</VCardText>
</VCard>
</VCol>
</VRow>
</template>
<style lang="scss">
.vertical-more {
position: absolute;
inset-block-start: 1rem;
inset-inline-end: 0.5rem;
}
</style>

View File

@@ -0,0 +1,109 @@
<script setup>
const props = defineProps({
data: {
type: null,
required: true,
},
})
</script>
<template>
<VCard class="mb-4">
<VCardText>
<div class="text-body-2 mb-4 text-disabled">
ABOUT
</div>
<div class="d-flex flex-column gap-y-4">
<div
v-for="item in props.data.about"
:key="item.property"
class="d-flex align-center gap-x-2"
>
<VIcon
:icon="item.icon"
size="24"
/>
<div class="font-weight-medium">
{{ item.property }}:
</div>
<div>
{{ item.value }}
</div>
</div>
</div>
<div class="text-body-2 text-disabled mt-6 mb-4">
CONTACTS
</div>
<div class="d-flex flex-column gap-y-4">
<div
v-for="item in props.data.contacts"
:key="item.property"
class="d-flex align-center gap-x-2"
>
<VIcon
:icon="item.icon"
size="24"
/>
<div class="font-weight-medium">
{{ item.property }}:
</div>
<div class="text-truncate">
{{ item.value }}
</div>
</div>
</div>
<div class="text-body-2 text-disabled mt-6 mb-4">
TEAMS
</div>
<div class="d-flex flex-column gap-y-4">
<div
v-for="item in props.data.teams"
:key="item.property"
>
<div class="d-flex align-center gap-x-2">
<div class="font-weight-medium text-no-wrap">
{{ item.property }}:
</div>
<div class="text-no-wrap text-truncate">
{{ item.value }}
</div>
</div>
</div>
</div>
</VCardText>
</VCard>
<VCard>
<VCardText>
<div class="text-body-2 text-disabled mb-4">
OVERVIEW
</div>
<div class="d-flex flex-column gap-y-4">
<div
v-for="item in props.data.overview"
:key="item.property"
class="d-flex gap-x-2 align-center"
>
<VIcon
:icon="item.icon"
size="24"
/>
<div class="font-weight-medium">
{{ item.property }}:
</div>
<div>{{ item.value }}</div>
</div>
</div>
</VCardText>
</VCard>
</template>
<style lang="scss" scoped>
.card-list {
--v-card-list-gap: 16px;
}
</style>

View File

@@ -0,0 +1,137 @@
<script setup>
import avatar1 from '@images/avatars/avatar-1.png'
import avatar6 from '@images/avatars/avatar-6.png'
import avatar8 from '@images/avatars/avatar-8.png'
import pdf from '@images/icons/project-icons/pdf.png'
</script>
<template>
<VCard>
<VCardItem>
<template #prepend>
<VIcon
icon="ri-bar-chart-2-line"
size="24"
/>
</template>
<VCardTitle>Activity Timeline</VCardTitle>
</VCardItem>
<VCardText>
<VTimeline
side="end"
align="start"
line-inset="8"
truncate-line="start"
density="compact"
>
<VTimelineItem
dot-color="primary"
size="x-small"
>
<!-- 👉 Header -->
<div class="d-flex justify-space-between align-center gap-2 flex-wrap mb-3">
<div class="app-timeline-title align-self-start">
12 Invoices have been paid
</div>
<div class="app-timeline-meta">
12 min ago
</div>
</div>
<p class="app-timeline-text mb-2">
Invoices have been paid to the company.
</p>
<div class="d-inline-flex align-center timeline-chip mb-4">
<img
:src="pdf"
height="20"
class="me-3"
alt="img"
>
<h6 class="text-h6 text-medium-emphasis">
invoice.pdf
</h6>
</div>
</VTimelineItem>
<VTimelineItem
dot-color="success"
size="x-small"
>
<!-- 👉 Header -->
<div class="d-flex justify-space-between align-center gap-2 flex-wrap mb-3">
<div class="app-timeline-title align-self-start">
Client Meeting
</div>
<div class="app-timeline-meta">
45 min ago
</div>
</div>
<p class="app-timeline-text mb-2">
Project meeting with john @10:15am
</p>
<div class="d-flex align-center mb-2">
<VAvatar
size="32"
:image="avatar1"
class="me-3"
/>
<div>
<div class="text-body-2 font-weight-medium">
Lester McCarthy (Client)
</div>
<div class="text-body-2">
CEO of ThemeSelection
</div>
</div>
</div>
</VTimelineItem>
<VTimelineItem
dot-color="info"
size="x-small"
>
<div class="d-flex justify-space-between align-center gap-2 flex-wrap mb-3">
<div class="app-timeline-title align-self-start">
Create a new project for client
</div>
<div class="app-timeline-meta">
2 Day Ago
</div>
</div>
<p class="mb-0 app-timeline-text mb-2">
6 team members in a project
</p>
<div class="v-avatar-group">
<VAvatar
:size="40"
:image="avatar1"
/>
<VAvatar
:size="40"
:image="avatar8"
/>
<VAvatar
:size="40"
:image="avatar6"
/>
<VAvatar
:color="$vuetify.theme.current.dark ? '#3A3B59' : '#F0EFF0'"
:size="40"
>
+3
</VAvatar>
</div>
</VTimelineItem>
</VTimeline>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,104 @@
<script setup>
const props = defineProps({
connectionsData: {
type: Array,
required: true,
},
})
const moreList = [
{
title: 'Share connections',
value: 'Share connections',
},
{
title: 'Suggest edits',
value: 'Suggest edits',
},
{
title: 'Report Bug',
value: 'Report Bug',
},
]
</script>
<template>
<VCard
title="Connection"
class="connectionCard"
>
<template #append>
<div class="me-n2">
<MoreBtn
:menu-list="moreList"
density="compact"
/>
</div>
</template>
<VCardText>
<VList class="card-list">
<VListItem
v-for="data in props.connectionsData"
:key="data.name"
>
<template #prepend>
<VAvatar
size="38"
:image="data.avatar"
/>
</template>
<VListItemTitle class="font-weight-medium mb-1">
{{ data.name }}
</VListItemTitle>
<VListItemSubtitle>{{ data.connections }} Connections</VListItemSubtitle>
<template #append>
<VBtn
icon
class="rounded"
:variant="data.isFriend ? 'elevated' : 'outlined' "
>
<VIcon
size="24"
:icon="data.isFriend ? 'ri-user-line' : 'ri-user-add-line'"
/>
</VBtn>
</template>
</VListItem>
<VListItem>
<VListItemTitle>
<VBtn
block
variant="text"
>
View all connections
</VBtn>
</VListItemTitle>
</VListItem>
</VList>
</VCardText>
</VCard>
</template>
<style lang="scss" scoped>
.card-list {
--v-card-list-gap: 16px;
}
</style>
<style lang="scss">
.connectionCard{
.v-list{
.v-list-item{
&__prepend{
.v-list-item__spacer{
inline-size: 8px !important;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,266 @@
<script setup>
import avatar1 from '@images/avatars/avatar-1.png'
import avatar2 from '@images/avatars/avatar-2.png'
import avatar3 from '@images/avatars/avatar-3.png'
import avatar4 from '@images/avatars/avatar-4.png'
import avatar5 from '@images/avatars/avatar-5.png'
import avatar6 from '@images/avatars/avatar-6.png'
import avatar7 from '@images/avatars/avatar-7.png'
import avatar8 from '@images/avatars/avatar-8.png'
import figma from '@images/icons/project-icons/figma.png'
import html5 from '@images/icons/project-icons/html5.png'
import python from '@images/icons/project-icons/python.png'
import react from '@images/icons/project-icons/react.png'
import sketch from '@images/icons/project-icons/sketch.png'
import vue from '@images/icons/project-icons/vue.png'
import xamarin from '@images/icons/project-icons/xamarin.png'
// Project Table Header
const projectTableHeaders = [
{
title: 'PROJECT',
key: 'project',
},
{
title: 'LEADER',
key: 'leader',
},
{
title: 'Team',
key: 'team',
},
{
title: 'PROGRESS',
key: 'progress',
},
{
title: 'Action',
key: 'Action',
sortable: false,
},
]
const projects = [
{
logo: react,
name: 'BGC eCommerce App',
project: 'React Project',
leader: 'Eileen',
progress: 78,
hours: '18:42',
team: [
avatar1,
avatar8,
avatar6,
],
extraMembers: 3,
},
{
logo: figma,
name: 'Falcon Logo Design',
project: 'Figma Project',
leader: 'Owen',
progress: 25,
hours: '20:42',
team: [
avatar5,
avatar2,
],
},
{
logo: vue,
name: 'Dashboard Design',
project: 'Vuejs Project',
leader: 'Keith',
progress: 62,
hours: '120:87',
team: [
avatar8,
avatar2,
avatar1,
],
},
{
logo: xamarin,
name: 'Foodista mobile app',
project: 'Xamarin Project',
leader: 'Merline',
progress: 8,
hours: '120:87',
team: [
avatar3,
avatar4,
avatar7,
],
extraMembers: 8,
},
{
logo: python,
name: 'Dojo Email App',
project: 'Python Project',
leader: 'Harmonia',
progress: 51,
hours: '230:10',
team: [
avatar4,
avatar3,
avatar1,
],
extraMembers: 5,
},
{
logo: sketch,
name: 'Blockchain Website',
project: 'Sketch Project',
leader: 'Allyson',
progress: 92,
hours: '342:41',
team: [
avatar1,
avatar8,
],
},
{
logo: html5,
name: 'Hoffman Website',
project: 'HTML Project',
leader: 'Georgie',
progress: 80,
hours: '12:45',
team: [
avatar1,
avatar8,
avatar6,
],
},
]
const moreList = [
{
title: 'Download',
value: 'Download',
},
{
title: 'Delete',
value: 'Delete',
},
{
title: 'View',
value: 'View',
},
]
</script>
<template>
<VCard
title="Project List"
class="projectList"
>
<!-- 👉 User Project List Table -->
<!-- SECTION Datatable -->
<VDataTable
:headers="projectTableHeaders"
:items="projects"
hide-default-footer
show-select
item-value="name"
>
<!-- projects -->
<template #item.project="{ item }">
<div class="d-flex align-center gap-x-3">
<VAvatar
:size="34"
:image="item.logo"
/>
<div>
<h6 class="text-h6 text-no-wrap">
{{ item.name }}
</h6>
<div class="text-body-2">
{{ item.project }}
</div>
</div>
</div>
</template>
<template #item.leader="{ item }">
<div class="text-base text-high-emphasis">
{{ item.leader }}
</div>
</template>
<!-- Team -->
<template #item.team="{ item }">
<div class="d-flex">
<div class="v-avatar-group">
<VAvatar
v-for="(data, index) in item.team"
:key="index"
size="30"
>
<VImg :src="data" />
</VAvatar>
<VAvatar
v-if="item.extraMembers"
:color="$vuetify.theme.current.dark ? '#3A3B59' : '#F0EFF0'"
:size="30"
>
<div class="text-caption text-high-emphasis">
+{{ item.extraMembers }}
</div>
</VAvatar>
</div>
</div>
</template>
<!-- Progress -->
<template #item.progress="{ item }">
<div class="d-flex align-center gap-3">
<div class="flex-grow-1">
<VProgressLinear
:height="6"
:model-value="item.progress"
rounded
/>
</div>
<div class="text-high-emphasis">
{{ item.progress }}%
</div>
</div>
</template>
<!-- Action -->
<template #item.Action>
<MoreBtn
:menu-list="moreList"
density="compact"
/>
</template>
<!-- TODO Refactor this after vuetify provides proper solution for removing default footer -->
<template #bottom />
</VDataTable>
<!-- !SECTION -->
</VCard>
</template>
<style lang="scss">
.projectList{
.v-table{
&--density-default{
.v-table__wrapper{
table{
tbody{
tr{
td{
block-size: 56px;
}
}
}
}
}
}
}
}
</style>

View File

@@ -0,0 +1,100 @@
<script setup>
const props = defineProps({
teamsData: {
type: Array,
required: true,
},
})
const moreList = [
{
title: 'Share connections',
value: 'Share connections',
},
{
title: 'Suggest edits',
value: 'Suggest edits',
},
{
title: 'Report Bug',
value: 'Report Bug',
},
]
</script>
<template>
<VCard
title="Teams"
class="teamsCard"
>
<template #append>
<div class="me-n2">
<MoreBtn
:menu-list="moreList"
density="compact"
/>
</div>
</template>
<VCardText>
<VList class="card-list">
<VListItem
v-for="data in props.teamsData"
:key="data.title"
>
<template #prepend>
<VAvatar
size="38"
:image="data.avatar"
/>
</template>
<VListItemTitle class="font-weight-medium mb-1">
{{ data.title }}
</VListItemTitle>
<VListItemSubtitle>{{ data.members }} Members</VListItemSubtitle>
<template #append>
<VChip
:color="data.ChipColor"
size="small"
>
{{ data.chipText }}
</VChip>
</template>
</VListItem>
<VListItem>
<VListItemTitle>
<VBtn
block
variant="text"
>
View all teams
</VBtn>
</VListItemTitle>
</VListItem>
</VList>
</VCardText>
</VCard>
</template>
<style lang="scss" scoped>
.card-list {
--v-card-list-gap: 16px;
}
</style>
<style lang="scss">
.teamsCard{
.v-list{
.v-list-item{
&__prepend{
.v-list-item__spacer{
inline-size: 8px !important;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,60 @@
<script setup>
import About from './About.vue'
import ActivityTimeline from './ActivityTimeline.vue'
import Connection from './Connection.vue'
import ProjectList from './ProjectList.vue'
import Teams from './Teams.vue'
const router = useRoute('pages-user-profile-tab')
const profileTabData = ref()
const fetchAboutData = async () => {
if (router.params.tab === 'profile') {
const data = await $api('/pages/profile', { query: { tab: router.params.tab } }).catch(err => console.log(err))
profileTabData.value = data
}
}
watch(router, fetchAboutData, { immediate: true })
</script>
<template>
<VRow v-if="profileTabData">
<VCol
md="4"
cols="12"
>
<About :data="profileTabData" />
</VCol>
<VCol
cols="12"
md="8"
>
<VRow>
<VCol cols="12">
<ActivityTimeline />
</VCol>
<VCol
cols="12"
md="6"
>
<Connection :connections-data="profileTabData.connections" />
</VCol>
<VCol
cols="12"
md="6"
>
<Teams :teams-data="profileTabData.teamsTech" />
</VCol>
<VCol cols="12">
<ProjectList />
</VCol>
</VRow>
</VCol>
</VRow>
</template>

View File

@@ -0,0 +1,154 @@
<script setup>
const router = useRoute('pages-user-profile-tab')
const projectData = ref([])
const fetchProjectData = async () => {
if (router.params.tab === 'projects') {
const data = await $api('/pages/profile', { query: { tab: router.params.tab } }).catch(err => console.log(err))
projectData.value = data
}
}
watch(router, fetchProjectData, { immediate: true })
const moreList = [
{
title: 'Rename Project',
value: 'Rename Project',
},
{
title: 'View Details',
value: 'View Details',
},
{
title: 'Add to favorites',
value: 'Add to favorites',
},
{
type: 'divider',
class: 'my-2',
},
{
title: 'Leave Project',
value: 'Leave Project',
class: 'text-error',
},
]
</script>
<template>
<VRow v-if="projectData">
<VCol
v-for="data in projectData"
:key="data.title"
cols="12"
sm="6"
lg="4"
>
<VCard>
<VCardItem class="pb-4">
<template #prepend>
<VAvatar
:image="data.avatar"
size="38"
/>
</template>
<VCardTitle>{{ data.title }}</VCardTitle>
<div>
<span class="font-weight-medium">Client:</span>
{{ data.client }}
</div>
<template #append>
<div>
<MoreBtn
item-props
:menu-list="moreList"
density="compact"
/>
</div>
</template>
</VCardItem>
<VCardText>
<div class="d-flex align-center justify-space-between flex-wrap gap-x-2 gap-y-4">
<div class="py-2 px-3 bg-var-theme-background rounded">
<div>
<span class="text-high-emphasis font-weight-medium">{{ data.budgetSpent }}</span>/{{ data.budget }}
</div>
<div>Total Budget</div>
</div>
<div>
<div>
<span class="text-high-emphasis font-weight-medium">Start Date:</span> {{ data.startDate }}
</div>
<h6 class="text-base font-weight-medium">
Deadline: <span class="text-body-1">{{ data.deadline }}</span>
</h6>
</div>
</div>
<p class="mt-4 mb-0 clamp-text">
{{ data.description }}
</p>
</VCardText>
<VDivider />
<VCardText>
<div class="d-flex align-center justify-space-between flex-wrap gap-2">
<div>
<span class="font-weight-medium text-high-emphasis">All Hours:</span> {{ data.hours }}
</div>
<VChip
:color="data.chipColor"
size="small"
>
{{ data.chipText }}
</VChip>
</div>
<div class="d-flex align-center justify-space-between flex-wrap text-caption text-medium-emphasis mt-4 mb-2">
<div>Task: {{ data.tasks }}</div>
<div>{{ Math.round((data.completedTask / data.totalTask) * 100) }}% Completed</div>
</div>
<VProgressLinear
rounded
height="8"
:model-value="data.completedTask"
:max="data.totalTask"
color="primary"
/>
<div class="d-flex align-center justify-space-between flex-wrap gap-2 mt-4">
<div class="d-flex align-center">
<div class="v-avatar-group me-2">
<VAvatar
v-for="avatar in data.avatarGroup"
:key="avatar.name"
:image="avatar.avatar"
:size="32"
/>
</div>
<div class="text-sm">
{{ data.members }}
</div>
</div>
<div class="d-flex gap-x-1 align-center text-disabled">
<VIcon
icon="ri-wechat-line"
size="24"
/>
<div>{{ data.comments }}</div>
</div>
</div>
</VCardText>
</VCard>
</VCol>
</VRow>
</template>

View File

@@ -0,0 +1,122 @@
<script setup>
const router = useRoute('pages-user-profile-tab')
const teamData = ref([])
const fetchTeamData = async () => {
if (router.params.tab === 'teams') {
const data = await $api('/pages/profile', { query: { tab: router.params.tab } }).catch(err => console.log(err))
teamData.value = data
}
}
watch(router, fetchTeamData, { immediate: true })
const moreList = [
{
title: 'Rename Project',
value: 'Rename Project',
},
{
title: 'View Details',
value: 'View Details',
},
{
title: 'Add to favorites',
value: 'Add to favorites',
},
{
type: 'divider',
class: 'my-2',
},
{
title: 'Leave Project',
value: 'Leave Project',
class: 'text-error',
},
]
</script>
<template>
<VRow v-if="teamData">
<VCol
v-for="team in teamData"
:key="team.title"
cols="12"
md="6"
lg="4"
>
<VCard>
<VCardItem class="pb-4">
<template #prepend>
<VAvatar
size="38"
:image="team?.avatar"
/>
</template>
<VCardTitle>{{ team.title }}</VCardTitle>
<template #append>
<div class="me-n3">
<IconBtn>
<VIcon
icon="ri-star-line"
color="disabled"
/>
</IconBtn>
<MoreBtn
item-props
:menu-list="moreList"
color="disabled"
/>
</div>
</template>
</VCardItem>
<VCardText>
<div class="text-base mb-4">
{{ team.description }}
</div>
<div class="d-flex">
<div class="v-avatar-group">
<VAvatar
v-for="data in team.avatarGroup"
:key="data.name"
size="32"
>
<VImg :src="data.avatar" />
<VTooltip
activator="parent"
location="top"
>
{{ data.name }}
</VTooltip>
</VAvatar>
<VAvatar
v-if="team.extraMembers"
:color="$vuetify.theme.current.dark ? '#3A3B59' : '#F0EFF0'"
:size="32"
>
<div class="text-body-2 text-high-emphasis font-weight-medium">
+{{ team.extraMembers }}
</div>
</VAvatar>
</div>
<VSpacer />
<div class="d-flex align-center gap-2">
<VChip
v-for="data in team.chips"
:key="data.title"
:color="data.color"
size="small"
>
{{ data.title }}
</VChip>
</div>
</div>
</VCardText>
</VCard>
</VCol>
</VRow>
</template>