Initial commit
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
<script setup>
|
||||
import { useTheme } from 'vuetify'
|
||||
|
||||
const vuetifyTheme = useTheme()
|
||||
const currentTheme = vuetifyTheme.current.value.colors
|
||||
|
||||
const series = [{
|
||||
data: [
|
||||
400,
|
||||
200,
|
||||
650,
|
||||
500,
|
||||
],
|
||||
}]
|
||||
|
||||
const chartOptions = {
|
||||
chart: {
|
||||
type: 'area',
|
||||
toolbar: { show: false },
|
||||
sparkline: { enabled: true },
|
||||
},
|
||||
markers: {
|
||||
colors: 'transparent',
|
||||
strokeColors: 'transparent',
|
||||
},
|
||||
grid: { show: false },
|
||||
colors: [currentTheme.success],
|
||||
fill: {
|
||||
type: 'gradient',
|
||||
gradient: {
|
||||
shadeIntensity: 0.8,
|
||||
opacityFrom: 0.6,
|
||||
opacityTo: 0.1,
|
||||
},
|
||||
},
|
||||
dataLabels: { enabled: false },
|
||||
stroke: {
|
||||
width: 2,
|
||||
curve: 'smooth',
|
||||
},
|
||||
xaxis: {
|
||||
show: true,
|
||||
lines: { show: false },
|
||||
labels: { show: false },
|
||||
stroke: { width: 0 },
|
||||
axisBorder: { show: false },
|
||||
},
|
||||
yaxis: {
|
||||
stroke: { width: 0 },
|
||||
show: false,
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 1387,
|
||||
options: { chart: { height: 80 } },
|
||||
},
|
||||
{
|
||||
breakpoint: 1200,
|
||||
options: { chart: { height: 120 } },
|
||||
},
|
||||
],
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardText>
|
||||
<h5 class="text-h5 mb-3">
|
||||
Average Daily Sales
|
||||
</h5>
|
||||
<p class="mb-0">
|
||||
Total Sales This Month
|
||||
</p>
|
||||
<h4 class="text-h4">
|
||||
$28,450
|
||||
</h4>
|
||||
</VCardText>
|
||||
|
||||
<VueApexCharts
|
||||
:options="chartOptions"
|
||||
:series="series"
|
||||
:height="80"
|
||||
/>
|
||||
</VCard>
|
||||
</template>
|
||||
@@ -0,0 +1,220 @@
|
||||
<script setup>
|
||||
import { useTheme } from 'vuetify'
|
||||
import { hexToRgb } from '@layouts/utils'
|
||||
|
||||
const vuetifyTheme = useTheme()
|
||||
|
||||
const series = [{
|
||||
data: [
|
||||
40,
|
||||
65,
|
||||
50,
|
||||
45,
|
||||
90,
|
||||
55,
|
||||
70,
|
||||
],
|
||||
}]
|
||||
|
||||
const chartOptions = computed(() => {
|
||||
const currentTheme = vuetifyTheme.current.value.colors
|
||||
const variableTheme = vuetifyTheme.current.value.variables
|
||||
|
||||
return {
|
||||
chart: {
|
||||
parentHeightOffset: 0,
|
||||
type: 'bar',
|
||||
toolbar: { show: false },
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
barHeight: '60%',
|
||||
columnWidth: '38%',
|
||||
startingShape: 'rounded',
|
||||
endingShape: 'rounded',
|
||||
borderRadius: 4,
|
||||
distributed: true,
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
top: -30,
|
||||
bottom: 0,
|
||||
left: -10,
|
||||
right: -10,
|
||||
},
|
||||
},
|
||||
colors: [
|
||||
`rgba(${ hexToRgb(currentTheme.primary) },${ variableTheme['dragged-opacity'] })`,
|
||||
`rgba(${ hexToRgb(currentTheme.primary) },${ variableTheme['dragged-opacity'] })`,
|
||||
`rgba(${ hexToRgb(currentTheme.primary) },${ variableTheme['dragged-opacity'] })`,
|
||||
`rgba(${ hexToRgb(currentTheme.primary) },${ variableTheme['dragged-opacity'] })`,
|
||||
`rgba(${ hexToRgb(currentTheme.primary) }, 1)`,
|
||||
`rgba(${ hexToRgb(currentTheme.primary) },${ variableTheme['dragged-opacity'] })`,
|
||||
`rgba(${ hexToRgb(currentTheme.primary) },${ variableTheme['dragged-opacity'] })`,
|
||||
],
|
||||
dataLabels: { enabled: false },
|
||||
legend: { show: false },
|
||||
xaxis: {
|
||||
categories: [
|
||||
'Mo',
|
||||
'Tu',
|
||||
'We',
|
||||
'Th',
|
||||
'Fr',
|
||||
'Sa',
|
||||
'Su',
|
||||
],
|
||||
axisBorder: { show: false },
|
||||
axisTicks: { show: false },
|
||||
labels: {
|
||||
style: {
|
||||
colors: `rgba(${ hexToRgb(currentTheme['on-surface']) },${ variableTheme['disabled-opacity'] })`,
|
||||
fontSize: '13px',
|
||||
fontFamily: 'Public Sans',
|
||||
},
|
||||
},
|
||||
},
|
||||
yaxis: { labels: { show: false } },
|
||||
tooltip: { enabled: false },
|
||||
responsive: [{
|
||||
breakpoint: 1025,
|
||||
options: { chart: { height: 199 } },
|
||||
}],
|
||||
}
|
||||
})
|
||||
|
||||
const earningsReports = [
|
||||
{
|
||||
color: 'primary',
|
||||
icon: 'tabler-currency-dollar',
|
||||
title: 'Earnings',
|
||||
amount: '$545.69',
|
||||
progress: '55',
|
||||
},
|
||||
{
|
||||
color: 'info',
|
||||
icon: 'tabler-chart-pie-2',
|
||||
title: 'Profit',
|
||||
amount: '$256.34',
|
||||
progress: '25',
|
||||
},
|
||||
{
|
||||
color: 'error',
|
||||
icon: 'tabler-brand-paypal',
|
||||
title: 'Expense',
|
||||
amount: '$74.19',
|
||||
progress: '65',
|
||||
},
|
||||
]
|
||||
|
||||
const moreList = [
|
||||
{
|
||||
title: 'View More',
|
||||
value: 'View More',
|
||||
},
|
||||
{
|
||||
title: 'Delete',
|
||||
value: 'Delete',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardItem class="pb-sm-0">
|
||||
<VCardTitle>Earning Reports</VCardTitle>
|
||||
<VCardSubtitle>Weekly Earnings Overview</VCardSubtitle>
|
||||
|
||||
<template #append>
|
||||
<div class="mt-n4 me-n2">
|
||||
<MoreBtn
|
||||
size="small"
|
||||
:menu-list="moreList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</VCardItem>
|
||||
|
||||
<VCardText>
|
||||
<VRow>
|
||||
<VCol
|
||||
cols="12"
|
||||
sm="5"
|
||||
lg="6"
|
||||
class="d-flex flex-column align-self-center"
|
||||
>
|
||||
<div class="d-flex align-center gap-2 mb-3 flex-wrap">
|
||||
<h2 class="text-h2">
|
||||
$468
|
||||
</h2>
|
||||
<VChip
|
||||
label
|
||||
size="small"
|
||||
color="success"
|
||||
>
|
||||
+4.2%
|
||||
</VChip>
|
||||
</div>
|
||||
|
||||
<span class="text-sm text-medium-emphasis">
|
||||
You informed of this week compared to last week
|
||||
</span>
|
||||
</VCol>
|
||||
|
||||
<VCol
|
||||
cols="12"
|
||||
sm="7"
|
||||
lg="6"
|
||||
>
|
||||
<VueApexCharts
|
||||
:options="chartOptions"
|
||||
:series="series"
|
||||
height="161"
|
||||
/>
|
||||
</VCol>
|
||||
</VRow>
|
||||
|
||||
<div class="border rounded mt-5 pa-5">
|
||||
<VRow>
|
||||
<VCol
|
||||
v-for="report in earningsReports"
|
||||
:key="report.title"
|
||||
cols="12"
|
||||
sm="4"
|
||||
>
|
||||
<div class="d-flex align-center">
|
||||
<VAvatar
|
||||
rounded
|
||||
size="26"
|
||||
:color="report.color"
|
||||
variant="tonal"
|
||||
class="me-2"
|
||||
>
|
||||
<VIcon
|
||||
size="18"
|
||||
:icon="report.icon"
|
||||
/>
|
||||
</VAvatar>
|
||||
|
||||
<h6 class="text-base font-weight-regular">
|
||||
{{ report.title }}
|
||||
</h6>
|
||||
</div>
|
||||
<h6 class="text-h4 my-2">
|
||||
{{ report.amount }}
|
||||
</h6>
|
||||
<VProgressLinear
|
||||
:model-value="report.progress"
|
||||
:color="report.color"
|
||||
height="4"
|
||||
rounded
|
||||
rounded-bar
|
||||
/>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
@@ -0,0 +1,131 @@
|
||||
<script setup>
|
||||
const monthlyCampaignState = [
|
||||
{
|
||||
avatarColor: 'success',
|
||||
avatarIcon: 'tabler-mail',
|
||||
title: 'Emails',
|
||||
count: '12,346',
|
||||
stats: '0.3%',
|
||||
statsColor: 'success',
|
||||
},
|
||||
{
|
||||
avatarColor: 'info',
|
||||
avatarIcon: 'tabler-link',
|
||||
title: 'Opened',
|
||||
count: '8,734',
|
||||
stats: '2.1%',
|
||||
statsColor: 'success',
|
||||
},
|
||||
{
|
||||
avatarColor: 'warning',
|
||||
avatarIcon: 'tabler-mouse',
|
||||
title: 'Clicked',
|
||||
count: '967',
|
||||
stats: '1.4%',
|
||||
statsColor: 'error',
|
||||
},
|
||||
{
|
||||
avatarColor: 'primary',
|
||||
avatarIcon: 'tabler-users',
|
||||
title: 'Subscribe',
|
||||
count: '345',
|
||||
stats: '8.5%',
|
||||
statsColor: 'success',
|
||||
},
|
||||
{
|
||||
avatarColor: 'secondary',
|
||||
avatarIcon: 'tabler-alert-triangle',
|
||||
title: 'Complaints',
|
||||
count: '10',
|
||||
stats: '1.5%',
|
||||
statsColor: 'error',
|
||||
},
|
||||
{
|
||||
avatarColor: 'error',
|
||||
avatarIcon: 'tabler-ban',
|
||||
title: 'Unsubscribe',
|
||||
count: '86',
|
||||
stats: '0.8%',
|
||||
statsColor: 'success',
|
||||
},
|
||||
]
|
||||
|
||||
const moreList = [
|
||||
{
|
||||
title: 'Refresh',
|
||||
value: 'refresh',
|
||||
},
|
||||
{
|
||||
title: 'Download',
|
||||
value: 'Download',
|
||||
},
|
||||
{
|
||||
title: 'View All',
|
||||
value: 'View All',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>Monthly Campaign State</VCardTitle>
|
||||
<VCardSubtitle>
|
||||
8.52k Social Visitors
|
||||
</VCardSubtitle>
|
||||
<template #append>
|
||||
<div class="mt-n4 me-n2">
|
||||
<MoreBtn
|
||||
size="small"
|
||||
:menu-list="moreList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</VCardItem>
|
||||
|
||||
<VCardText>
|
||||
<VList class="card-list">
|
||||
<VListItem
|
||||
v-for="state in monthlyCampaignState"
|
||||
:key="state.title"
|
||||
>
|
||||
<template #prepend>
|
||||
<VAvatar
|
||||
:color="state.avatarColor"
|
||||
variant="tonal"
|
||||
size="34"
|
||||
rounded
|
||||
class="me-1"
|
||||
>
|
||||
<VIcon
|
||||
:icon="state.avatarIcon"
|
||||
size="22"
|
||||
/>
|
||||
</VAvatar>
|
||||
</template>
|
||||
|
||||
<VListItemTitle class="font-weight-medium me-4">
|
||||
{{ state.title }}
|
||||
</VListItemTitle>
|
||||
|
||||
<template #append>
|
||||
<div class="d-flex gap-x-4">
|
||||
<div class="text-body-1">
|
||||
{{ state.count }}
|
||||
</div>
|
||||
<div :class="`text-${state.statsColor}`">
|
||||
{{ state.stats }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card-list {
|
||||
--v-card-list-gap: 1.5rem;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,186 @@
|
||||
<script setup>
|
||||
const projectTableHeaders = [
|
||||
{
|
||||
title: 'PROJECT',
|
||||
key: 'project',
|
||||
},
|
||||
{
|
||||
title: 'LEADER',
|
||||
key: 'leader',
|
||||
},
|
||||
{
|
||||
title: 'Team',
|
||||
key: 'team',
|
||||
sortable: false,
|
||||
},
|
||||
{
|
||||
title: 'PROGRESS',
|
||||
key: 'progress',
|
||||
},
|
||||
{
|
||||
title: 'Action',
|
||||
key: 'Action',
|
||||
sortable: false,
|
||||
},
|
||||
]
|
||||
|
||||
const search = ref('')
|
||||
const itemsPerPage = ref(5)
|
||||
const page = ref(1)
|
||||
const sortBy = ref()
|
||||
const orderBy = ref()
|
||||
|
||||
const { data: projectsData } = await useApi(createUrl('/dashboard/analytics/projects', {
|
||||
query: {
|
||||
q: search,
|
||||
itemsPerPage,
|
||||
page,
|
||||
sortBy,
|
||||
orderBy,
|
||||
},
|
||||
}))
|
||||
|
||||
const updateOptions = options => {
|
||||
sortBy.value = options.sortBy[0]?.key
|
||||
orderBy.value = options.sortBy[0]?.order
|
||||
}
|
||||
|
||||
const projects = computed(() => projectsData.value?.projects)
|
||||
const totalProjects = computed(() => projectsData.value?.totalProjects)
|
||||
|
||||
const moreList = [
|
||||
{
|
||||
title: 'Download',
|
||||
value: 'Download',
|
||||
},
|
||||
{
|
||||
title: 'Delete',
|
||||
value: 'Delete',
|
||||
},
|
||||
{
|
||||
title: 'View',
|
||||
value: 'View',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard v-if="projects">
|
||||
<VCardItem class="project-header d-flex flex-wrap justify-space-between gap-4">
|
||||
<VCardTitle>Project List</VCardTitle>
|
||||
|
||||
<template #append>
|
||||
<div style="inline-size: 250px;">
|
||||
<AppTextField
|
||||
v-model="search"
|
||||
placeholder="Search Project"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</VCardItem>
|
||||
|
||||
<VDivider />
|
||||
|
||||
<!-- SECTION Table -->
|
||||
<VDataTableServer
|
||||
v-model:items-per-page="itemsPerPage"
|
||||
v-model:page="page"
|
||||
:items="projects"
|
||||
:items-length="totalProjects"
|
||||
item-value="name"
|
||||
:headers="projectTableHeaders"
|
||||
class="text-no-wrap"
|
||||
show-select
|
||||
@update:options="updateOptions"
|
||||
>
|
||||
<!-- projects -->
|
||||
<template #item.project="{ item }">
|
||||
<div
|
||||
class="d-flex align-center gap-x-3"
|
||||
style="padding-block: 7px;"
|
||||
>
|
||||
<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="26"
|
||||
>
|
||||
<VImg :src="data" />
|
||||
</VAvatar>
|
||||
<VAvatar
|
||||
v-if="item.extraMembers"
|
||||
:color="$vuetify.theme.current.dark ? '#373b50' : '#eeedf0'"
|
||||
:size="26"
|
||||
>
|
||||
<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"
|
||||
color="primary"
|
||||
rounded
|
||||
/>
|
||||
</div>
|
||||
<div class="text-body-1 text-high-emphasis">
|
||||
{{ item.progress }}%
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Action -->
|
||||
<template #item.Action>
|
||||
<MoreBtn :menu-list="moreList" />
|
||||
</template>
|
||||
|
||||
<!-- TODO Refactor this after vuetify provides proper solution for removing default footer -->
|
||||
<template #bottom>
|
||||
<TablePagination
|
||||
v-model:page="page"
|
||||
:items-per-page="itemsPerPage"
|
||||
:total-items="totalProjects"
|
||||
/>
|
||||
</template>
|
||||
</VDataTableServer>
|
||||
<!-- !SECTION -->
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.project-header .v-card-item__append {
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,123 @@
|
||||
<script setup>
|
||||
import auFlag from '@images/icons/countries/au.png'
|
||||
import brFlag from '@images/icons/countries/br.png'
|
||||
import cnFlag from '@images/icons/countries/cn.png'
|
||||
import frFlag from '@images/icons/countries/fr.png'
|
||||
import inFlag from '@images/icons/countries/in.png'
|
||||
import usFlag from '@images/icons/countries/us.png'
|
||||
|
||||
const salesByCountries = [
|
||||
{
|
||||
avatarImg: usFlag,
|
||||
stats: '$8,567k',
|
||||
subtitle: 'United states',
|
||||
profitLoss: 25.8,
|
||||
},
|
||||
{
|
||||
avatarImg: brFlag,
|
||||
stats: '$2,415k',
|
||||
subtitle: 'Brazil',
|
||||
profitLoss: -6.2,
|
||||
},
|
||||
{
|
||||
avatarImg: inFlag,
|
||||
stats: '$865k',
|
||||
subtitle: 'India',
|
||||
profitLoss: 12.4,
|
||||
},
|
||||
{
|
||||
avatarImg: auFlag,
|
||||
stats: '$745k',
|
||||
subtitle: 'Australia',
|
||||
profitLoss: -11.9,
|
||||
},
|
||||
{
|
||||
avatarImg: frFlag,
|
||||
stats: '$45',
|
||||
subtitle: 'France',
|
||||
profitLoss: 16.2,
|
||||
},
|
||||
{
|
||||
avatarImg: cnFlag,
|
||||
stats: '$12k',
|
||||
subtitle: 'China',
|
||||
profitLoss: 14.8,
|
||||
},
|
||||
]
|
||||
|
||||
const moreList = [
|
||||
{
|
||||
title: 'Refresh',
|
||||
value: 'refresh',
|
||||
},
|
||||
{
|
||||
title: 'Download',
|
||||
value: 'Download',
|
||||
},
|
||||
{
|
||||
title: 'View All',
|
||||
value: 'View All',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard
|
||||
title="Sales by Countries"
|
||||
subtitle="Monthly Sales Overview"
|
||||
>
|
||||
<template #append>
|
||||
<div class="mt-n4 me-n2">
|
||||
<MoreBtn
|
||||
size="small"
|
||||
:menu-list="moreList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<VCardText>
|
||||
<VList class="card-list">
|
||||
<VListItem
|
||||
v-for="country in salesByCountries"
|
||||
:key="country.stats"
|
||||
>
|
||||
<template #prepend>
|
||||
<VAvatar
|
||||
size="34"
|
||||
color="secondary"
|
||||
variant="tonal"
|
||||
class="me-1"
|
||||
:image="country.avatarImg"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<VListItemTitle class="font-weight-medium">
|
||||
{{ country.stats }}
|
||||
</VListItemTitle>
|
||||
<VListItemSubtitle>
|
||||
{{ country.subtitle }}
|
||||
</VListItemSubtitle>
|
||||
|
||||
<template #append>
|
||||
<div :class="`d-flex align-center ${country.profitLoss > 0 ? 'text-success' : 'text-error'}`">
|
||||
<VIcon
|
||||
:icon="country.profitLoss > 0 ? 'tabler-chevron-up' : 'tabler-chevron-down'"
|
||||
size="20"
|
||||
class="me-1"
|
||||
/>
|
||||
<div class="font-weight-medium">
|
||||
{{ Math.abs(country.profitLoss) }}%
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card-list {
|
||||
--v-card-list-gap: 1rem;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,110 @@
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardText>
|
||||
<div class="d-flex align-center justify-space-between">
|
||||
<div class="text-body-1">
|
||||
Sales Overview
|
||||
</div>
|
||||
<div class="text-success font-weight-medium">
|
||||
+18.2%
|
||||
</div>
|
||||
</div>
|
||||
<h4 class="text-h4">
|
||||
$42.5k
|
||||
</h4>
|
||||
</VCardText>
|
||||
|
||||
<VCardText>
|
||||
<VRow no-gutters>
|
||||
<VCol cols="5">
|
||||
<div class="py-2">
|
||||
<div class="d-flex align-center mb-3">
|
||||
<VAvatar
|
||||
color="info"
|
||||
variant="tonal"
|
||||
:size="24"
|
||||
rounded
|
||||
class="me-2"
|
||||
>
|
||||
<VIcon
|
||||
size="18"
|
||||
icon="tabler-shopping-cart"
|
||||
/>
|
||||
</VAvatar>
|
||||
<span>Order</span>
|
||||
</div>
|
||||
<h5 class="text-h5">
|
||||
62.2%
|
||||
</h5>
|
||||
<div class="text-body-2 text-disabled">
|
||||
6,440
|
||||
</div>
|
||||
</div>
|
||||
</VCol>
|
||||
|
||||
<VCol cols="2">
|
||||
<div class="d-flex flex-column align-center justify-center h-100">
|
||||
<VDivider
|
||||
vertical
|
||||
class="mx-auto"
|
||||
/>
|
||||
|
||||
<VAvatar
|
||||
size="24"
|
||||
color="rgba(var(--v-theme-on-surface), var(--v-hover-opacity))"
|
||||
class="my-2"
|
||||
>
|
||||
<div class="text-overline text-disabled">
|
||||
VS
|
||||
</div>
|
||||
</VAvatar>
|
||||
|
||||
<VDivider
|
||||
vertical
|
||||
class="mx-auto"
|
||||
/>
|
||||
</div>
|
||||
</VCol>
|
||||
|
||||
<VCol
|
||||
cols="5"
|
||||
class="text-end"
|
||||
>
|
||||
<div class="py-2">
|
||||
<div class="d-flex align-center justify-end mb-3">
|
||||
<span class="me-2">Visits</span>
|
||||
<VAvatar
|
||||
color="primary"
|
||||
variant="tonal"
|
||||
:size="24"
|
||||
rounded
|
||||
>
|
||||
<VIcon
|
||||
size="18"
|
||||
icon="tabler-link"
|
||||
/>
|
||||
</VAvatar>
|
||||
</div>
|
||||
<h5 class="text-h5">
|
||||
25.5%
|
||||
</h5>
|
||||
<div class="text-body-2 text-disabled">
|
||||
12,749
|
||||
</div>
|
||||
</div>
|
||||
</VCol>
|
||||
</VRow>
|
||||
|
||||
<div class="mt-6">
|
||||
<VProgressLinear
|
||||
model-value="72"
|
||||
color="#00CFE8"
|
||||
height="10"
|
||||
bg-color="primary"
|
||||
:rounded-bar="false"
|
||||
rounded
|
||||
/>
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
@@ -0,0 +1,133 @@
|
||||
<script setup>
|
||||
const sourceVisits = [
|
||||
{
|
||||
avatarIcon: 'tabler-shadow',
|
||||
title: 'Direct Source',
|
||||
subtitle: 'Direct link click',
|
||||
stats: '1.2k',
|
||||
profitLoss: 4.2,
|
||||
},
|
||||
{
|
||||
avatarIcon: 'tabler-globe',
|
||||
title: 'Social Network',
|
||||
subtitle: 'Social Channels',
|
||||
stats: '31.5k',
|
||||
profitLoss: 8.2,
|
||||
},
|
||||
{
|
||||
avatarIcon: 'tabler-mail',
|
||||
title: 'Email Newsletter',
|
||||
subtitle: 'Mail Campaigns',
|
||||
stats: '893',
|
||||
profitLoss: 2.4,
|
||||
},
|
||||
{
|
||||
avatarIcon: 'tabler-external-link',
|
||||
title: 'Referrals',
|
||||
subtitle: 'Impact Radius Visits',
|
||||
stats: '342',
|
||||
profitLoss: -0.4,
|
||||
},
|
||||
{
|
||||
avatarIcon: 'tabler-ad',
|
||||
title: 'ADVT',
|
||||
subtitle: 'Google ADVT',
|
||||
stats: '2.15k',
|
||||
profitLoss: 9.1,
|
||||
},
|
||||
{
|
||||
avatarIcon: 'tabler-star',
|
||||
title: 'Other',
|
||||
subtitle: 'Many Sources',
|
||||
stats: '12.5k',
|
||||
profitLoss: 6.2,
|
||||
},
|
||||
]
|
||||
|
||||
const moreList = [
|
||||
{
|
||||
title: 'Refresh',
|
||||
value: 'refresh',
|
||||
},
|
||||
{
|
||||
title: 'Download',
|
||||
value: 'Download',
|
||||
},
|
||||
{
|
||||
title: 'View All',
|
||||
value: 'View All',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>Source Visits</VCardTitle>
|
||||
<VCardSubtitle>
|
||||
38.4k Visitors
|
||||
</VCardSubtitle>
|
||||
<template #append>
|
||||
<div class="mt-n4 me-n2">
|
||||
<MoreBtn
|
||||
size="small"
|
||||
:menu-list="moreList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</VCardItem>
|
||||
|
||||
<VCardText>
|
||||
<VList class="card-list">
|
||||
<VListItem
|
||||
v-for="visit in sourceVisits"
|
||||
:key="visit.title"
|
||||
>
|
||||
<template #prepend>
|
||||
<VAvatar
|
||||
size="38"
|
||||
color="secondary"
|
||||
variant="tonal"
|
||||
class="me-1"
|
||||
rounded
|
||||
>
|
||||
<VIcon
|
||||
:icon="visit.avatarIcon"
|
||||
size="22"
|
||||
/>
|
||||
</VAvatar>
|
||||
</template>
|
||||
|
||||
<VListItemTitle class="font-weight-medium me-4">
|
||||
{{ visit.title }}
|
||||
</VListItemTitle>
|
||||
<VListItemSubtitle class="me-4">
|
||||
{{ visit.subtitle }}
|
||||
</VListItemSubtitle>
|
||||
|
||||
<template #append>
|
||||
<div class="d-flex align-center gap-x-4">
|
||||
<div class="text-body-1">
|
||||
{{ visit.stats }}
|
||||
</div>
|
||||
<VChip
|
||||
label
|
||||
size="small"
|
||||
:color="visit.profitLoss > 0 ? 'success' : 'error'"
|
||||
>
|
||||
{{ visit.profitLoss > 0 ? '+' : '' }}
|
||||
{{ visit.profitLoss }}%
|
||||
</VChip>
|
||||
</div>
|
||||
</template>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card-list {
|
||||
--v-card-list-gap: 1.5rem;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,191 @@
|
||||
<script setup>
|
||||
import { useTheme } from 'vuetify'
|
||||
import { hexToRgb } from '@layouts/utils'
|
||||
|
||||
const vuetifyTheme = useTheme()
|
||||
const series = [85]
|
||||
|
||||
const chartOptions = computed(() => {
|
||||
const currentTheme = vuetifyTheme.current.value.colors
|
||||
const variableTheme = vuetifyTheme.current.value.variables
|
||||
|
||||
return {
|
||||
labels: ['Completed Task'],
|
||||
chart: { type: 'radialBar' },
|
||||
plotOptions: {
|
||||
radialBar: {
|
||||
offsetY: 10,
|
||||
startAngle: -140,
|
||||
endAngle: 130,
|
||||
hollow: { size: '65%' },
|
||||
track: {
|
||||
background: currentTheme.surface,
|
||||
strokeWidth: '100%',
|
||||
},
|
||||
dataLabels: {
|
||||
name: {
|
||||
offsetY: -20,
|
||||
color: `rgba(${ hexToRgb(currentTheme['on-surface']) },${ variableTheme['disabled-opacity'] })`,
|
||||
fontSize: '13px',
|
||||
fontWeight: '400',
|
||||
fontFamily: 'Public Sans',
|
||||
},
|
||||
value: {
|
||||
offsetY: 10,
|
||||
color: `rgba(${ hexToRgb(currentTheme['on-background']) },${ variableTheme['high-emphasis-opacity'] })`,
|
||||
fontSize: '38px',
|
||||
fontWeight: '500',
|
||||
fontFamily: 'Public Sans',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
colors: [currentTheme.primary],
|
||||
fill: {
|
||||
type: 'gradient',
|
||||
gradient: {
|
||||
shade: 'dark',
|
||||
shadeIntensity: 0.5,
|
||||
gradientToColors: [currentTheme.primary],
|
||||
inverseColors: true,
|
||||
opacityFrom: 1,
|
||||
opacityTo: 0.6,
|
||||
stops: [
|
||||
30,
|
||||
70,
|
||||
100,
|
||||
],
|
||||
},
|
||||
},
|
||||
stroke: { dashArray: 10 },
|
||||
grid: {
|
||||
padding: {
|
||||
top: -20,
|
||||
bottom: 5,
|
||||
},
|
||||
},
|
||||
states: {
|
||||
hover: { filter: { type: 'none' } },
|
||||
active: { filter: { type: 'none' } },
|
||||
},
|
||||
responsive: [{
|
||||
breakpoint: 960,
|
||||
options: { chart: { height: 280 } },
|
||||
}],
|
||||
}
|
||||
})
|
||||
|
||||
const supportTicket = [
|
||||
{
|
||||
avatarColor: 'primary',
|
||||
avatarIcon: 'tabler-ticket',
|
||||
title: 'New Tickets',
|
||||
subtitle: '142',
|
||||
},
|
||||
{
|
||||
avatarColor: 'info',
|
||||
avatarIcon: 'tabler-check',
|
||||
title: 'Open Tickets',
|
||||
subtitle: '28',
|
||||
},
|
||||
{
|
||||
avatarColor: 'warning',
|
||||
avatarIcon: 'tabler-clock',
|
||||
title: 'Response Time',
|
||||
subtitle: '1 Day',
|
||||
},
|
||||
]
|
||||
|
||||
const moreList = [
|
||||
{
|
||||
title: 'View More',
|
||||
value: 'View More',
|
||||
},
|
||||
{
|
||||
title: 'Delete',
|
||||
value: 'Delete',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>Support Tracker</VCardTitle>
|
||||
<VCardSubtitle>Last 7 Days</VCardSubtitle>
|
||||
|
||||
<template #append>
|
||||
<div class="mt-n4 me-n2">
|
||||
<MoreBtn
|
||||
size="small"
|
||||
:menu-list="moreList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</VCardItem>
|
||||
|
||||
<VCardText>
|
||||
<VRow>
|
||||
<VCol
|
||||
cols="12"
|
||||
lg="4"
|
||||
md="4"
|
||||
>
|
||||
<div class="mb-lg-6 mb-4 mt-2">
|
||||
<h2 class="text-h2">
|
||||
164
|
||||
</h2>
|
||||
<p class="text-base mb-0">
|
||||
Total Tickets
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<VList class="card-list">
|
||||
<VListItem
|
||||
v-for="ticket in supportTicket"
|
||||
:key="ticket.title"
|
||||
>
|
||||
<VListItemTitle class="font-weight-medium">
|
||||
{{ ticket.title }}
|
||||
</VListItemTitle>
|
||||
<VListItemSubtitle>
|
||||
{{ ticket.subtitle }}
|
||||
</VListItemSubtitle>
|
||||
<template #prepend>
|
||||
<VAvatar
|
||||
rounded
|
||||
size="34"
|
||||
:color="ticket.avatarColor"
|
||||
variant="tonal"
|
||||
class="me-1"
|
||||
>
|
||||
<VIcon
|
||||
size="22"
|
||||
:icon="ticket.avatarIcon"
|
||||
/>
|
||||
</VAvatar>
|
||||
</template>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VCol>
|
||||
<VCol
|
||||
cols="12"
|
||||
lg="8"
|
||||
md="8"
|
||||
>
|
||||
<VueApexCharts
|
||||
:options="chartOptions"
|
||||
:series="series"
|
||||
height="360"
|
||||
/>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card-list {
|
||||
--v-card-list-gap: 16px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,296 @@
|
||||
<script setup>
|
||||
import { useTheme } from 'vuetify'
|
||||
|
||||
const vuetifyTheme = useTheme()
|
||||
|
||||
const series = [
|
||||
{
|
||||
name: 'Earning',
|
||||
data: [
|
||||
15,
|
||||
10,
|
||||
20,
|
||||
8,
|
||||
12,
|
||||
18,
|
||||
12,
|
||||
5,
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Expense',
|
||||
data: [
|
||||
-7,
|
||||
-10,
|
||||
-7,
|
||||
-12,
|
||||
-6,
|
||||
-9,
|
||||
-5,
|
||||
-8,
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
const chartOptions = computed(() => {
|
||||
const currentTheme = vuetifyTheme.current.value.colors
|
||||
|
||||
return {
|
||||
chart: {
|
||||
parentHeightOffset: 0,
|
||||
stacked: true,
|
||||
type: 'bar',
|
||||
toolbar: { show: false },
|
||||
},
|
||||
tooltip: { enabled: false },
|
||||
legend: { show: false },
|
||||
stroke: {
|
||||
curve: 'smooth',
|
||||
width: 6,
|
||||
lineCap: 'round',
|
||||
colors: [currentTheme.surface],
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
horizontal: false,
|
||||
columnWidth: '45%',
|
||||
borderRadius: 8,
|
||||
borderRadiusApplication: 'around',
|
||||
borderRadiusWhenStacked: 'all',
|
||||
},
|
||||
},
|
||||
colors: [
|
||||
'rgba(var(--v-theme-primary),1)',
|
||||
'rgba(var(--v-theme-secondary),1)',
|
||||
],
|
||||
dataLabels: { enabled: false },
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
top: -40,
|
||||
bottom: -20,
|
||||
left: -10,
|
||||
right: -2,
|
||||
},
|
||||
},
|
||||
xaxis: {
|
||||
labels: { show: false },
|
||||
axisTicks: { show: false },
|
||||
axisBorder: { show: false },
|
||||
},
|
||||
yaxis: { labels: { show: false } },
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 1600,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '50%',
|
||||
borderRadius: 8,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 1468,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '60%',
|
||||
borderRadius: 8,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 1279,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '35%',
|
||||
borderRadius: 8,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 1197,
|
||||
options: {
|
||||
chart: { height: 228 },
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 8,
|
||||
columnWidth: '40%',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 912,
|
||||
options: {
|
||||
chart: { height: 232 },
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 8,
|
||||
columnWidth: '55%',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 725,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '70%',
|
||||
borderRadius: 8,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 600,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 8,
|
||||
columnWidth: '40%',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 475,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 8,
|
||||
columnWidth: '50%',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 381,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '60%',
|
||||
borderRadius: 8,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
states: {
|
||||
hover: { filter: { type: 'none' } },
|
||||
active: { filter: { type: 'none' } },
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
const totalEarnings = [
|
||||
{
|
||||
avatar: 'tabler-brand-paypal',
|
||||
avatarColor: 'primary',
|
||||
title: 'Total Revenue',
|
||||
subtitle: 'Client Payment',
|
||||
earning: '+$126',
|
||||
},
|
||||
{
|
||||
avatar: 'tabler-currency-dollar',
|
||||
avatarColor: 'secondary',
|
||||
title: 'Total Sales',
|
||||
subtitle: 'Total Sales',
|
||||
earning: '+$98',
|
||||
},
|
||||
]
|
||||
|
||||
const moreList = [
|
||||
{
|
||||
title: 'View More',
|
||||
value: 'View More',
|
||||
},
|
||||
{
|
||||
title: 'Delete',
|
||||
value: 'Delete',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardItem class="pb-0">
|
||||
<VCardTitle>Total Earning</VCardTitle>
|
||||
|
||||
<div class="d-flex align-center mt-2">
|
||||
<h2 class="text-h2 me-2">
|
||||
87%
|
||||
</h2>
|
||||
<div class="text-success">
|
||||
<VIcon
|
||||
size="20"
|
||||
icon="tabler-chevron-up"
|
||||
/>
|
||||
<span class="text-base">25.8%</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #append>
|
||||
<div class="mt-n10 me-n2">
|
||||
<MoreBtn
|
||||
size="small"
|
||||
:menu-list="moreList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</VCardItem>
|
||||
|
||||
<VCardText>
|
||||
<VueApexCharts
|
||||
:options="chartOptions"
|
||||
:series="series"
|
||||
height="191"
|
||||
class="my-2"
|
||||
/>
|
||||
|
||||
<VList class="card-list">
|
||||
<VListItem
|
||||
v-for="earning in totalEarnings"
|
||||
:key="earning.title"
|
||||
>
|
||||
<VListItemTitle class="font-weight-medium">
|
||||
{{ earning.title }}
|
||||
</VListItemTitle>
|
||||
<VListItemSubtitle>
|
||||
{{ earning.subtitle }}
|
||||
</VListItemSubtitle>
|
||||
<template #prepend>
|
||||
<VAvatar
|
||||
size="38"
|
||||
:color="earning.avatarColor"
|
||||
variant="tonal"
|
||||
rounded
|
||||
class="me-1"
|
||||
>
|
||||
<VIcon
|
||||
:icon="earning.avatar"
|
||||
size="22"
|
||||
/>
|
||||
</VAvatar>
|
||||
</template>
|
||||
|
||||
<template #append>
|
||||
<span class="text-success font-weight-medium">{{ earning.earning }}</span>
|
||||
</template>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card-list {
|
||||
--v-card-list-gap: 16px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,188 @@
|
||||
<script setup>
|
||||
import { VIcon } from 'vuetify/components/VIcon'
|
||||
import sliderBar1 from '@images/illustrations/sidebar-pic-1.png'
|
||||
import sliderBar2 from '@images/illustrations/sidebar-pic-2.png'
|
||||
import sliderBar3 from '@images/illustrations/sidebar-pic-3.png'
|
||||
|
||||
const websiteAnalytics = [
|
||||
{
|
||||
name: 'Traffic',
|
||||
slideImg: sliderBar1,
|
||||
data: [
|
||||
{
|
||||
number: '1.5k',
|
||||
text: 'Sessions',
|
||||
},
|
||||
{
|
||||
number: '3.1k',
|
||||
text: 'Page Views',
|
||||
},
|
||||
{
|
||||
number: '1.2k',
|
||||
text: 'Leads',
|
||||
},
|
||||
{
|
||||
number: '12%',
|
||||
text: 'Conversions',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Spending',
|
||||
slideImg: sliderBar2,
|
||||
data: [
|
||||
{
|
||||
number: '12h',
|
||||
text: 'Spend',
|
||||
},
|
||||
{
|
||||
number: '182',
|
||||
text: 'Order Size',
|
||||
},
|
||||
{
|
||||
number: '127',
|
||||
text: 'Order',
|
||||
},
|
||||
{
|
||||
number: '23k',
|
||||
text: 'Items',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Revenue Sources',
|
||||
slideImg: sliderBar3,
|
||||
data: [
|
||||
{
|
||||
number: '268',
|
||||
text: 'Direct',
|
||||
},
|
||||
{
|
||||
number: '890',
|
||||
text: 'Organic',
|
||||
},
|
||||
{
|
||||
number: '622',
|
||||
text: 'Referral',
|
||||
},
|
||||
{
|
||||
number: '1.2k',
|
||||
text: 'Campaign',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard
|
||||
color="primary"
|
||||
height="260"
|
||||
>
|
||||
<VCarousel
|
||||
cycle
|
||||
:continuous="false"
|
||||
:show-arrows="false"
|
||||
hide-delimiter-background
|
||||
:delimiter-icon="() => h(VIcon, { icon: 'fa-circle', size: '8' })"
|
||||
height="260"
|
||||
class="carousel-delimiter-top-end web-analytics-carousel"
|
||||
>
|
||||
<VCarouselItem
|
||||
v-for="item in websiteAnalytics"
|
||||
:key="item.name"
|
||||
>
|
||||
<VCardText class="position-relative">
|
||||
<VRow>
|
||||
<VCol cols="12">
|
||||
<h5 class="text-h5 text-white">
|
||||
Website Analytics
|
||||
</h5>
|
||||
<p class="text-sm mb-0">
|
||||
Total 28.5% Conversion Rate
|
||||
</p>
|
||||
</VCol>
|
||||
|
||||
<VCol
|
||||
cols="12"
|
||||
sm="6"
|
||||
order="2"
|
||||
order-sm="1"
|
||||
>
|
||||
<VRow>
|
||||
<VCol
|
||||
cols="12"
|
||||
class="pb-0 pt-1"
|
||||
>
|
||||
<h6 class="text-h6 text-white mb-1 mt-5">
|
||||
{{ item.name }}
|
||||
</h6>
|
||||
</VCol>
|
||||
|
||||
<VCol
|
||||
v-for="d in item.data"
|
||||
:key="d.number"
|
||||
cols="6"
|
||||
class="text-no-wrap pb-2"
|
||||
>
|
||||
<VChip
|
||||
label
|
||||
variant="flat"
|
||||
size="default"
|
||||
color="rgb(var(--v-theme-primary-darken-1))"
|
||||
class="font-weight-medium text-white rounded me-2 px-2"
|
||||
style="block-size: 30px;"
|
||||
>
|
||||
<span class="text-base">{{ d.number }}</span>
|
||||
</VChip>
|
||||
<span class="d-inline-block">{{ d.text }}</span>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VCol>
|
||||
|
||||
<VCol
|
||||
cols="12"
|
||||
sm="6"
|
||||
order="1"
|
||||
order-sm="2"
|
||||
class="text-center"
|
||||
>
|
||||
<img
|
||||
:src="item.slideImg"
|
||||
class="card-website-analytics-img"
|
||||
style="filter: drop-shadow(0 4px 60px rgba(0, 0, 0, 50%));"
|
||||
>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VCardText>
|
||||
</VCarouselItem>
|
||||
</VCarousel>
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.card-website-analytics-img {
|
||||
block-size: 150px;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 600px) {
|
||||
.card-website-analytics-img {
|
||||
position: absolute;
|
||||
margin: auto;
|
||||
inset-block-end: 1rem;
|
||||
inset-inline-end: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.web-analytics-carousel {
|
||||
.v-carousel__controls {
|
||||
.v-carousel__controls__item {
|
||||
&.v-btn--active {
|
||||
.v-icon {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
134
resources/js/views/dashboards/crm/CrmActiveProject.vue
Normal file
134
resources/js/views/dashboards/crm/CrmActiveProject.vue
Normal file
@@ -0,0 +1,134 @@
|
||||
<script setup>
|
||||
import bootstrapLogo from '@images/icons/brands/bootstrap-logo.png'
|
||||
import figmaLogo from '@images/icons/brands/figma-logo.png'
|
||||
import laravelLogo from '@images/icons/brands/laravel-logo.png'
|
||||
import reactLogo from '@images/icons/brands/react-logo.png'
|
||||
import sketchLogo from '@images/icons/brands/sketch-logo.png'
|
||||
import vuejsLogo from '@images/icons/brands/vuejs-logo.png'
|
||||
|
||||
const activeProjects = [
|
||||
{
|
||||
avatarImg: laravelLogo,
|
||||
title: 'Laravel',
|
||||
subtitle: 'Ecommerce',
|
||||
stats: '65',
|
||||
progressColor: 'error',
|
||||
},
|
||||
{
|
||||
avatarImg: figmaLogo,
|
||||
title: 'Figma',
|
||||
subtitle: 'App UI Kit',
|
||||
stats: '86',
|
||||
progressColor: 'primary',
|
||||
},
|
||||
{
|
||||
avatarImg: vuejsLogo,
|
||||
title: 'VueJs',
|
||||
subtitle: 'Calendar App',
|
||||
stats: '90',
|
||||
progressColor: 'success',
|
||||
},
|
||||
{
|
||||
avatarImg: reactLogo,
|
||||
title: 'React',
|
||||
subtitle: 'Dashboard',
|
||||
stats: '37',
|
||||
progressColor: 'info',
|
||||
},
|
||||
{
|
||||
avatarImg: bootstrapLogo,
|
||||
title: 'Bootstrap',
|
||||
subtitle: 'Website',
|
||||
stats: '22',
|
||||
progressColor: 'primary',
|
||||
},
|
||||
{
|
||||
avatarImg: sketchLogo,
|
||||
title: 'Sketch',
|
||||
subtitle: 'Website Design',
|
||||
stats: '29',
|
||||
progressColor: 'warning',
|
||||
},
|
||||
]
|
||||
|
||||
const moreList = [
|
||||
{
|
||||
title: 'Refresh',
|
||||
value: 'refresh',
|
||||
},
|
||||
{
|
||||
title: 'Download',
|
||||
value: 'Download',
|
||||
},
|
||||
{
|
||||
title: 'View All',
|
||||
value: 'View All',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>Active Projects</VCardTitle>
|
||||
<VCardSubtitle>
|
||||
Average 72% completed
|
||||
</VCardSubtitle>
|
||||
<template #append>
|
||||
<div class="mt-n4 me-n2">
|
||||
<MoreBtn
|
||||
size="small"
|
||||
:menu-list="moreList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</VCardItem>
|
||||
|
||||
<VCardText>
|
||||
<VList class="card-list">
|
||||
<VListItem
|
||||
v-for="project in activeProjects"
|
||||
:key="project.title"
|
||||
>
|
||||
<template #prepend>
|
||||
<VAvatar
|
||||
size="34"
|
||||
rounded
|
||||
class="me-1"
|
||||
>
|
||||
<img :src="project.avatarImg">
|
||||
</VAvatar>
|
||||
</template>
|
||||
|
||||
<VListItemTitle class="font-weight-medium">
|
||||
{{ project.title }}
|
||||
</VListItemTitle>
|
||||
<VListItemSubtitle class="me-4">
|
||||
{{ project.subtitle }}
|
||||
</VListItemSubtitle>
|
||||
|
||||
<template #append>
|
||||
<div class="d-flex align-center gap-x-4">
|
||||
<div style="inline-size: 4.875rem;">
|
||||
<VProgressLinear
|
||||
:model-value="project.stats"
|
||||
:color="project.progressColor"
|
||||
height="8"
|
||||
rounded-bar
|
||||
rounded
|
||||
/>
|
||||
</div>
|
||||
<span class="text-disabled">{{ project.stats }}%</span>
|
||||
</div>
|
||||
</template>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card-list {
|
||||
--v-card-list-gap: 16px;
|
||||
}
|
||||
</style>
|
||||
180
resources/js/views/dashboards/crm/CrmActivityTimeline.vue
Normal file
180
resources/js/views/dashboards/crm/CrmActivityTimeline.vue
Normal file
@@ -0,0 +1,180 @@
|
||||
<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 pdf from '@images/icons/project-icons/pdf.png'
|
||||
|
||||
const moreList = [
|
||||
{
|
||||
title: 'View More',
|
||||
value: 'View More',
|
||||
},
|
||||
{
|
||||
title: 'Delete',
|
||||
value: 'Delete',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<template #prepend>
|
||||
<VIcon
|
||||
icon="tabler-list-details"
|
||||
size="20"
|
||||
color="high-emphasis"
|
||||
class="me-1"
|
||||
/>
|
||||
</template>
|
||||
<template #append>
|
||||
<div class="mt-n4 me-n2">
|
||||
<MoreBtn
|
||||
size="small"
|
||||
:menu-list="moreList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<VCardTitle>Activity Timeline</VCardTitle>
|
||||
</VCardItem>
|
||||
|
||||
<VCardText>
|
||||
<VTimeline
|
||||
side="end"
|
||||
align="start"
|
||||
line-inset="8"
|
||||
truncate-line="start"
|
||||
density="compact"
|
||||
>
|
||||
<!-- SECTION Timeline Item: Flight -->
|
||||
<VTimelineItem
|
||||
dot-color="primary"
|
||||
size="x-small"
|
||||
>
|
||||
<!-- 👉 Header -->
|
||||
<div class="d-flex justify-space-between align-center gap-2 flex-wrap mb-2">
|
||||
<span class="app-timeline-title">
|
||||
12 Invoices have been paid
|
||||
</span>
|
||||
<span class="app-timeline-meta">12 min ago</span>
|
||||
</div>
|
||||
|
||||
<!-- 👉 Content -->
|
||||
<div class="app-timeline-text mt-1">
|
||||
Invoices have been paid to the company
|
||||
</div>
|
||||
|
||||
<div class="d-inline-flex align-center timeline-chip mt-2">
|
||||
<img
|
||||
:src="pdf"
|
||||
height="20"
|
||||
class="me-2"
|
||||
alt="img"
|
||||
>
|
||||
<span class="app-timeline-text font-weight-medium">
|
||||
invoice.pdf
|
||||
</span>
|
||||
</div>
|
||||
</VTimelineItem>
|
||||
<!-- !SECTION -->
|
||||
|
||||
<!-- SECTION Timeline Item: Interview Schedule -->
|
||||
<VTimelineItem
|
||||
size="x-small"
|
||||
dot-color="success"
|
||||
>
|
||||
<!-- 👉 Header -->
|
||||
<div class="d-flex justify-space-between align-center flex-wrap mb-2">
|
||||
<div class="app-timeline-title">
|
||||
Client Meeting
|
||||
</div>
|
||||
<span class="app-timeline-meta">45 min ago</span>
|
||||
</div>
|
||||
|
||||
<div class="app-timeline-text mt-1">
|
||||
Project meeting with john @10:15am
|
||||
</div>
|
||||
|
||||
<!-- 👉 Person -->
|
||||
<div class="d-flex justify-space-between align-center flex-wrap">
|
||||
<!-- 👉 Avatar & Personal Info -->
|
||||
<div class="d-flex align-center mt-2">
|
||||
<VAvatar
|
||||
size="32"
|
||||
class="me-2"
|
||||
:image="avatar1"
|
||||
/>
|
||||
<div class="d-flex flex-column">
|
||||
<p class="text-sm font-weight-medium text-medium-emphasis mb-0">
|
||||
Lester McCarthy (Client)
|
||||
</p>
|
||||
<span class="text-sm">CEO of Pixinvent</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</VTimelineItem>
|
||||
<!-- !SECTION -->
|
||||
|
||||
<!-- SECTION Design Review -->
|
||||
<VTimelineItem
|
||||
size="x-small"
|
||||
dot-color="info"
|
||||
>
|
||||
<!-- 👉 Header -->
|
||||
<div class="d-flex justify-space-between align-center flex-wrap mb-2">
|
||||
<span class="app-timeline-title">
|
||||
Create a new project for client
|
||||
</span>
|
||||
<span class="app-timeline-meta">2 Day Ago</span>
|
||||
</div>
|
||||
|
||||
<!-- 👉 Content -->
|
||||
<p class="app-timeline-text mt-1 mb-2">
|
||||
6 team members in a project
|
||||
</p>
|
||||
|
||||
<div class="v-avatar-group demo-avatar-group">
|
||||
<VAvatar :size="40">
|
||||
<VImg :src="avatar1" />
|
||||
<VTooltip
|
||||
activator="parent"
|
||||
location="top"
|
||||
>
|
||||
John Doe
|
||||
</VTooltip>
|
||||
</VAvatar>
|
||||
|
||||
<VAvatar :size="40">
|
||||
<VImg :src="avatar2" />
|
||||
<VTooltip
|
||||
activator="parent"
|
||||
location="top"
|
||||
>
|
||||
Jennie Obrien
|
||||
</VTooltip>
|
||||
</VAvatar>
|
||||
|
||||
<VAvatar :size="40">
|
||||
<VImg :src="avatar3" />
|
||||
<VTooltip
|
||||
activator="parent"
|
||||
location="top"
|
||||
>
|
||||
Peter Harper
|
||||
</VTooltip>
|
||||
</VAvatar>
|
||||
|
||||
<VAvatar
|
||||
:size="40"
|
||||
:color="$vuetify.theme.current.dark ? '#3A3B59' : '#F0EFF0'"
|
||||
>
|
||||
+3
|
||||
</VAvatar>
|
||||
</div>
|
||||
</VTimelineItem>
|
||||
<!-- !SECTION -->
|
||||
</VTimeline>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
164
resources/js/views/dashboards/crm/CrmAnalyticsSales.vue
Normal file
164
resources/js/views/dashboards/crm/CrmAnalyticsSales.vue
Normal file
@@ -0,0 +1,164 @@
|
||||
<script setup>
|
||||
import { useTheme } from 'vuetify'
|
||||
import { hexToRgb } from '@layouts/utils'
|
||||
|
||||
const vuetifyTheme = useTheme()
|
||||
|
||||
const series = [
|
||||
{
|
||||
name: 'Sales',
|
||||
data: [
|
||||
32,
|
||||
27,
|
||||
27,
|
||||
30,
|
||||
25,
|
||||
25,
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Visits',
|
||||
data: [
|
||||
25,
|
||||
35,
|
||||
20,
|
||||
20,
|
||||
20,
|
||||
20,
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
const chartOptions = computed(() => {
|
||||
const currentTheme = vuetifyTheme.current.value.colors
|
||||
const variableTheme = vuetifyTheme.current.value.variables
|
||||
const borderColor = `rgba(${ hexToRgb(String(variableTheme['border-color'])) },${ variableTheme['border-opacity'] })`
|
||||
const labelColor = `rgba(${ hexToRgb(currentTheme['on-surface']) },${ variableTheme['disabled-opacity'] })`
|
||||
const legendColor = `rgba(${ hexToRgb(currentTheme['on-background']) },${ variableTheme['medium-emphasis-opacity'] })`
|
||||
|
||||
return {
|
||||
chart: {
|
||||
type: 'radar',
|
||||
toolbar: { show: false },
|
||||
},
|
||||
plotOptions: {
|
||||
radar: {
|
||||
polygons: {
|
||||
strokeColors: borderColor,
|
||||
connectorColors: borderColor,
|
||||
},
|
||||
},
|
||||
},
|
||||
stroke: {
|
||||
show: false,
|
||||
width: 0,
|
||||
},
|
||||
legend: {
|
||||
show: true,
|
||||
fontSize: '13px',
|
||||
position: 'bottom',
|
||||
labels: {
|
||||
colors: legendColor,
|
||||
useSeriesColors: false,
|
||||
},
|
||||
markers: {
|
||||
height: 12,
|
||||
width: 12,
|
||||
offsetX: -8,
|
||||
},
|
||||
itemMargin: { horizontal: 10 },
|
||||
onItemHover: { highlightDataSeries: false },
|
||||
},
|
||||
colors: [
|
||||
currentTheme.primary,
|
||||
currentTheme.info,
|
||||
],
|
||||
fill: {
|
||||
opacity: [
|
||||
1,
|
||||
0.85,
|
||||
],
|
||||
},
|
||||
markers: { size: 0 },
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
top: 0,
|
||||
bottom: -5,
|
||||
},
|
||||
},
|
||||
xaxis: {
|
||||
categories: [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
'Apr',
|
||||
'May',
|
||||
'Jun',
|
||||
],
|
||||
labels: {
|
||||
show: true,
|
||||
style: {
|
||||
colors: [
|
||||
labelColor,
|
||||
labelColor,
|
||||
labelColor,
|
||||
labelColor,
|
||||
labelColor,
|
||||
labelColor,
|
||||
],
|
||||
fontSize: '13px',
|
||||
fontFamily: 'Public Sans',
|
||||
},
|
||||
},
|
||||
},
|
||||
yaxis: {
|
||||
show: false,
|
||||
min: 0,
|
||||
max: 40,
|
||||
tickAmount: 4,
|
||||
},
|
||||
responsive: [{
|
||||
breakpoint: 769,
|
||||
options: { chart: { height: 372 } },
|
||||
}],
|
||||
}
|
||||
})
|
||||
|
||||
const moreList = [
|
||||
{
|
||||
title: 'View More',
|
||||
value: 'View More',
|
||||
},
|
||||
{
|
||||
title: 'Delete',
|
||||
value: 'Delete',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardItem class="pb-4">
|
||||
<VCardTitle>Sales</VCardTitle>
|
||||
<VCardSubtitle>Last 6 Months</VCardSubtitle>
|
||||
|
||||
<template #append>
|
||||
<div class="mt-n4 me-n2">
|
||||
<MoreBtn
|
||||
size="small"
|
||||
:menu-list="moreList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</VCardItem>
|
||||
|
||||
<VCardText>
|
||||
<VueApexCharts
|
||||
:options="chartOptions"
|
||||
:series="series"
|
||||
height="290"
|
||||
/>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
@@ -0,0 +1,627 @@
|
||||
<script setup>
|
||||
import { useTheme } from "vuetify";
|
||||
import { hexToRgb } from "@layouts/utils";
|
||||
|
||||
const vuetifyTheme = useTheme();
|
||||
const currentTab = ref(0);
|
||||
const refVueApexChart = ref();
|
||||
|
||||
const cardBackgroundStyle = computed(() => {
|
||||
const currentTheme = vuetifyTheme.current.value.colors;
|
||||
const primaryColor = currentTheme.primary;
|
||||
|
||||
const createGradientColor = (color, opacity = 0.08) => {
|
||||
if (color.includes("rgba")) {
|
||||
return color.replace(/[\d\.]+\)$/g, `${opacity})`);
|
||||
}
|
||||
if (color.startsWith("#")) {
|
||||
return `rgba(${hexToRgb(color)}, ${opacity})`;
|
||||
}
|
||||
if (color.includes("rgb")) {
|
||||
return color.replace("rgb", "rgba").replace(")", `, ${opacity})`);
|
||||
}
|
||||
return `rgba(${hexToRgb(color)}, ${opacity})`;
|
||||
};
|
||||
|
||||
const gradientColor1 = createGradientColor(primaryColor, 0.12);
|
||||
const gradientColor2 = createGradientColor(primaryColor, 0.04);
|
||||
|
||||
return {
|
||||
background: `linear-gradient(135deg,
|
||||
${gradientColor1} 0%,
|
||||
${gradientColor2} 50%,
|
||||
${gradientColor1} 100%)`,
|
||||
};
|
||||
});
|
||||
|
||||
const chartConfigs = computed(() => {
|
||||
const currentTheme = vuetifyTheme.current.value.colors;
|
||||
const variableTheme = vuetifyTheme.current.value.variables;
|
||||
const labelPrimaryColor = `rgba(${hexToRgb(currentTheme.primary)},${
|
||||
variableTheme["dragged-opacity"]
|
||||
})`;
|
||||
const legendColor = `rgba(${hexToRgb(currentTheme["on-background"])},${
|
||||
variableTheme["high-emphasis-opacity"]
|
||||
})`;
|
||||
const borderColor = `rgba(${hexToRgb(
|
||||
String(variableTheme["border-color"])
|
||||
)},${variableTheme["border-opacity"]})`;
|
||||
const labelColor = `rgba(${hexToRgb(currentTheme["on-surface"])},${
|
||||
variableTheme["disabled-opacity"]
|
||||
})`;
|
||||
|
||||
return [
|
||||
{
|
||||
title: "Orders",
|
||||
icon: "tabler-shopping-cart",
|
||||
chartOptions: {
|
||||
chart: {
|
||||
parentHeightOffset: 0,
|
||||
type: "bar",
|
||||
toolbar: { show: false },
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: "32%",
|
||||
borderRadiusApplication: "end",
|
||||
borderRadius: 4,
|
||||
distributed: true,
|
||||
dataLabels: { position: "top" },
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: -10,
|
||||
right: -10,
|
||||
},
|
||||
},
|
||||
colors: [
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
`rgba(${hexToRgb(currentTheme.primary)}, 1)`,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
],
|
||||
dataLabels: {
|
||||
enabled: true,
|
||||
formatter(val) {
|
||||
return `${val}k`;
|
||||
},
|
||||
offsetY: -25,
|
||||
style: {
|
||||
fontSize: "15px",
|
||||
colors: [legendColor],
|
||||
fontWeight: "600",
|
||||
fontFamily: "Public Sans",
|
||||
},
|
||||
},
|
||||
legend: { show: false },
|
||||
tooltip: { enabled: false },
|
||||
xaxis: {
|
||||
categories: [
|
||||
"Jan",
|
||||
"Feb",
|
||||
"Mar",
|
||||
"Apr",
|
||||
"May",
|
||||
"Jun",
|
||||
"Jul",
|
||||
"Aug",
|
||||
"Sep",
|
||||
],
|
||||
axisBorder: {
|
||||
show: true,
|
||||
color: borderColor,
|
||||
},
|
||||
axisTicks: { show: false },
|
||||
labels: {
|
||||
style: {
|
||||
colors: labelColor,
|
||||
fontSize: "13px",
|
||||
fontFamily: "Public Sans",
|
||||
},
|
||||
},
|
||||
},
|
||||
yaxis: {
|
||||
labels: {
|
||||
offsetX: -15,
|
||||
formatter(val) {
|
||||
return `${val / 1}k`;
|
||||
},
|
||||
style: {
|
||||
fontSize: "13px",
|
||||
colors: labelColor,
|
||||
fontFamily: "Public Sans",
|
||||
},
|
||||
min: 0,
|
||||
max: 60000,
|
||||
tickAmount: 6,
|
||||
},
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 1441,
|
||||
options: { plotOptions: { bar: { columnWidth: "41%" } } },
|
||||
},
|
||||
{
|
||||
breakpoint: 590,
|
||||
options: {
|
||||
plotOptions: { bar: { columnWidth: "61%" } },
|
||||
yaxis: { labels: { show: false } },
|
||||
grid: {
|
||||
padding: {
|
||||
right: 0,
|
||||
left: -20,
|
||||
},
|
||||
},
|
||||
dataLabels: {
|
||||
style: {
|
||||
fontSize: "12px",
|
||||
fontWeight: "400",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: [28, 10, 45, 38, 15, 30, 35, 30, 8],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Sales",
|
||||
icon: "tabler-chart-bar",
|
||||
chartOptions: {
|
||||
chart: {
|
||||
parentHeightOffset: 0,
|
||||
type: "bar",
|
||||
toolbar: { show: false },
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: "32%",
|
||||
borderRadiusApplication: "end",
|
||||
borderRadius: 4,
|
||||
distributed: true,
|
||||
dataLabels: { position: "top" },
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: -10,
|
||||
right: -10,
|
||||
},
|
||||
},
|
||||
colors: [
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
`rgba(${hexToRgb(currentTheme.primary)}, 1)`,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
],
|
||||
dataLabels: {
|
||||
enabled: true,
|
||||
formatter(val) {
|
||||
return `${val}k`;
|
||||
},
|
||||
offsetY: -25,
|
||||
style: {
|
||||
fontSize: "15px",
|
||||
colors: [legendColor],
|
||||
fontWeight: "600",
|
||||
fontFamily: "Public Sans",
|
||||
},
|
||||
},
|
||||
legend: { show: false },
|
||||
tooltip: { enabled: false },
|
||||
xaxis: {
|
||||
categories: [
|
||||
"Jan",
|
||||
"Feb",
|
||||
"Mar",
|
||||
"Apr",
|
||||
"May",
|
||||
"Jun",
|
||||
"Jul",
|
||||
"Aug",
|
||||
"Sep",
|
||||
],
|
||||
axisBorder: {
|
||||
show: true,
|
||||
color: borderColor,
|
||||
},
|
||||
axisTicks: { show: false },
|
||||
labels: {
|
||||
style: {
|
||||
colors: labelColor,
|
||||
fontSize: "13px",
|
||||
fontFamily: "Public Sans",
|
||||
},
|
||||
},
|
||||
},
|
||||
yaxis: {
|
||||
labels: {
|
||||
offsetX: -15,
|
||||
formatter(val) {
|
||||
return `${val / 1}k`;
|
||||
},
|
||||
style: {
|
||||
fontSize: "13px",
|
||||
colors: labelColor,
|
||||
fontFamily: "Public Sans",
|
||||
},
|
||||
min: 0,
|
||||
max: 60000,
|
||||
tickAmount: 6,
|
||||
},
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 1441,
|
||||
options: { plotOptions: { bar: { columnWidth: "41%" } } },
|
||||
},
|
||||
{
|
||||
breakpoint: 590,
|
||||
options: {
|
||||
plotOptions: { bar: { columnWidth: "61%" } },
|
||||
grid: { padding: { right: 0 } },
|
||||
dataLabels: {
|
||||
style: {
|
||||
fontSize: "12px",
|
||||
fontWeight: "400",
|
||||
},
|
||||
},
|
||||
yaxis: { labels: { show: false } },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: [35, 25, 15, 40, 42, 25, 48, 8, 30],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Profit",
|
||||
icon: "tabler-currency-dollar",
|
||||
chartOptions: {
|
||||
chart: {
|
||||
parentHeightOffset: 0,
|
||||
type: "bar",
|
||||
toolbar: { show: false },
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: "32%",
|
||||
borderRadiusApplication: "end",
|
||||
borderRadius: 4,
|
||||
distributed: true,
|
||||
dataLabels: { position: "top" },
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: -10,
|
||||
right: -10,
|
||||
},
|
||||
},
|
||||
colors: [
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
`rgba(${hexToRgb(currentTheme.primary)}, 1)`,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
],
|
||||
dataLabels: {
|
||||
enabled: true,
|
||||
formatter(val) {
|
||||
return `${val}k`;
|
||||
},
|
||||
offsetY: -25,
|
||||
style: {
|
||||
fontSize: "15px",
|
||||
colors: [legendColor],
|
||||
fontWeight: "600",
|
||||
fontFamily: "Public Sans",
|
||||
},
|
||||
},
|
||||
legend: { show: false },
|
||||
tooltip: { enabled: false },
|
||||
xaxis: {
|
||||
categories: [
|
||||
"Jan",
|
||||
"Feb",
|
||||
"Mar",
|
||||
"Apr",
|
||||
"May",
|
||||
"Jun",
|
||||
"Jul",
|
||||
"Aug",
|
||||
"Sep",
|
||||
],
|
||||
axisBorder: {
|
||||
show: true,
|
||||
color: borderColor,
|
||||
},
|
||||
axisTicks: { show: false },
|
||||
labels: {
|
||||
style: {
|
||||
colors: labelColor,
|
||||
fontSize: "13px",
|
||||
fontFamily: "Public Sans",
|
||||
},
|
||||
},
|
||||
},
|
||||
yaxis: {
|
||||
labels: {
|
||||
offsetX: -15,
|
||||
formatter(val) {
|
||||
return `${val / 1}k`;
|
||||
},
|
||||
style: {
|
||||
fontSize: "13px",
|
||||
colors: labelColor,
|
||||
fontFamily: "Public Sans",
|
||||
},
|
||||
min: 0,
|
||||
max: 60000,
|
||||
tickAmount: 6,
|
||||
},
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 1441,
|
||||
options: { plotOptions: { bar: { columnWidth: "41%" } } },
|
||||
},
|
||||
{
|
||||
breakpoint: 590,
|
||||
options: {
|
||||
plotOptions: { bar: { columnWidth: "61%" } },
|
||||
grid: { padding: { right: 0 } },
|
||||
dataLabels: {
|
||||
style: {
|
||||
fontSize: "12px",
|
||||
fontWeight: "400",
|
||||
},
|
||||
},
|
||||
yaxis: { labels: { show: false } },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: [10, 22, 27, 33, 42, 32, 27, 22, 8],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Income",
|
||||
icon: "tabler-chart-pie-2",
|
||||
chartOptions: {
|
||||
chart: {
|
||||
parentHeightOffset: 0,
|
||||
type: "bar",
|
||||
toolbar: { show: false },
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: "32%",
|
||||
borderRadius: 6,
|
||||
distributed: true,
|
||||
borderRadiusApplication: "end",
|
||||
dataLabels: { position: "top" },
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: -10,
|
||||
right: -10,
|
||||
},
|
||||
},
|
||||
colors: [
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
`rgba(${hexToRgb(currentTheme.primary)}, 1)`,
|
||||
],
|
||||
dataLabels: {
|
||||
enabled: true,
|
||||
formatter(val) {
|
||||
return `${val}k`;
|
||||
},
|
||||
offsetY: -25,
|
||||
style: {
|
||||
fontSize: "15px",
|
||||
colors: [legendColor],
|
||||
fontWeight: "600",
|
||||
fontFamily: "Public Sans",
|
||||
},
|
||||
},
|
||||
legend: { show: false },
|
||||
tooltip: { enabled: false },
|
||||
xaxis: {
|
||||
categories: [
|
||||
"Jan",
|
||||
"Feb",
|
||||
"Mar",
|
||||
"Apr",
|
||||
"May",
|
||||
"Jun",
|
||||
"Jul",
|
||||
"Aug",
|
||||
"Sep",
|
||||
],
|
||||
axisBorder: {
|
||||
show: true,
|
||||
color: borderColor,
|
||||
},
|
||||
axisTicks: { show: false },
|
||||
labels: {
|
||||
style: {
|
||||
colors: labelColor,
|
||||
fontSize: "13px",
|
||||
fontFamily: "Public Sans",
|
||||
},
|
||||
},
|
||||
},
|
||||
yaxis: {
|
||||
labels: {
|
||||
offsetX: -15,
|
||||
formatter(val) {
|
||||
return `${val / 1}k`;
|
||||
},
|
||||
style: {
|
||||
fontSize: "13px",
|
||||
colors: labelColor,
|
||||
fontFamily: "Public Sans",
|
||||
},
|
||||
min: 0,
|
||||
max: 60000,
|
||||
tickAmount: 6,
|
||||
},
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 1441,
|
||||
options: { plotOptions: { bar: { columnWidth: "41%" } } },
|
||||
},
|
||||
{
|
||||
breakpoint: 590,
|
||||
options: {
|
||||
plotOptions: { bar: { columnWidth: "50%" } },
|
||||
dataLabels: {
|
||||
style: {
|
||||
fontSize: "12px",
|
||||
fontWeight: "400",
|
||||
},
|
||||
},
|
||||
grid: { padding: { right: 0 } },
|
||||
yaxis: { labels: { show: false } },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: [5, 9, 12, 18, 20, 25, 30, 36, 48],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
const moreList = [
|
||||
{
|
||||
title: "View More",
|
||||
value: "View More",
|
||||
},
|
||||
{
|
||||
title: "Delete",
|
||||
value: "Delete",
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard
|
||||
title="Earning Reports"
|
||||
subtitle="Yearly Earnings Overview"
|
||||
:style="cardBackgroundStyle"
|
||||
>
|
||||
<template #append>
|
||||
<div class="mt-n4 me-n2">
|
||||
<MoreBtn size="small" :menu-list="moreList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<VCardText>
|
||||
<VSlideGroup v-model="currentTab" show-arrows mandatory class="mb-10">
|
||||
<VSlideGroupItem
|
||||
v-for="(report, index) in chartConfigs"
|
||||
:key="report.title"
|
||||
v-slot="{ isSelected, toggle }"
|
||||
:value="index"
|
||||
>
|
||||
<div
|
||||
style="block-size: 100px; inline-size: 110px"
|
||||
:style="
|
||||
isSelected
|
||||
? 'border-color:rgb(var(--v-theme-primary)) !important'
|
||||
: ''
|
||||
"
|
||||
:class="isSelected ? 'border' : 'border border-dashed'"
|
||||
class="d-flex flex-column justify-center align-center cursor-pointer rounded py-4 px-5 me-4"
|
||||
@click="toggle"
|
||||
>
|
||||
<VAvatar
|
||||
rounded
|
||||
size="38"
|
||||
:color="isSelected ? 'primary' : ''"
|
||||
variant="tonal"
|
||||
class="mb-2"
|
||||
>
|
||||
<VIcon size="22" :icon="report.icon" />
|
||||
</VAvatar>
|
||||
<h6 class="text-base font-weight-medium mb-0">
|
||||
{{ report.title }}
|
||||
</h6>
|
||||
</div>
|
||||
</VSlideGroupItem>
|
||||
|
||||
<!-- 👉 slider more -->
|
||||
<VSlideGroupItem>
|
||||
<div
|
||||
style="block-size: 100px; inline-size: 110px"
|
||||
class="d-flex flex-column justify-center align-center rounded border border-dashed py-4 px-5"
|
||||
>
|
||||
<VAvatar rounded size="38" variant="tonal">
|
||||
<VIcon size="22" icon="tabler-plus" />
|
||||
</VAvatar>
|
||||
</div>
|
||||
</VSlideGroupItem>
|
||||
</VSlideGroup>
|
||||
|
||||
<VueApexCharts
|
||||
ref="refVueApexChart"
|
||||
:key="currentTab"
|
||||
:options="chartConfigs[Number(currentTab)].chartOptions"
|
||||
:series="chartConfigs[Number(currentTab)].series"
|
||||
height="230"
|
||||
class="mt-3"
|
||||
/>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
186
resources/js/views/dashboards/crm/CrmOrderBarChart.vue
Normal file
186
resources/js/views/dashboards/crm/CrmOrderBarChart.vue
Normal file
@@ -0,0 +1,186 @@
|
||||
<script setup>
|
||||
const series = [{
|
||||
name: '2020',
|
||||
data: [
|
||||
60,
|
||||
50,
|
||||
20,
|
||||
45,
|
||||
50,
|
||||
30,
|
||||
70,
|
||||
],
|
||||
}]
|
||||
|
||||
const chartOptions = computed(() => {
|
||||
return {
|
||||
chart: {
|
||||
height: 90,
|
||||
parentHeightOffset: 0,
|
||||
type: 'bar',
|
||||
toolbar: { show: false },
|
||||
},
|
||||
tooltip: { enabled: false },
|
||||
plotOptions: {
|
||||
bar: {
|
||||
barHeight: '100%',
|
||||
columnWidth: '30%',
|
||||
startingShape: 'rounded',
|
||||
endingShape: 'rounded',
|
||||
borderRadius: 4,
|
||||
colors: {
|
||||
backgroundBarColors: [
|
||||
'rgba(var(--v-track-bg))',
|
||||
'rgba(var(--v-track-bg))',
|
||||
'rgba(var(--v-track-bg))',
|
||||
'rgba(var(--v-track-bg))',
|
||||
'rgba(var(--v-track-bg))',
|
||||
'rgba(var(--v-track-bg))',
|
||||
'rgba(var(--v-track-bg))',
|
||||
'rgba(var(--v-track-bg))',
|
||||
'rgba(var(--v-track-bg))',
|
||||
'rgba(var(--v-track-bg))',
|
||||
'rgba(var(--v-track-bg))',
|
||||
'rgba(var(--v-track-bg))',
|
||||
'rgba(var(--v-track-bg))',
|
||||
'rgba(var(--v-track-bg))',
|
||||
],
|
||||
backgroundBarRadius: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
colors: ['rgba(var(--v-theme-primary),1)'],
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
top: -30,
|
||||
left: -16,
|
||||
bottom: 0,
|
||||
right: -6,
|
||||
},
|
||||
},
|
||||
dataLabels: { enabled: false },
|
||||
legend: { show: false },
|
||||
xaxis: {
|
||||
categories: [
|
||||
'M',
|
||||
'T',
|
||||
'W',
|
||||
'T',
|
||||
'F',
|
||||
'S',
|
||||
'S',
|
||||
],
|
||||
axisBorder: { show: false },
|
||||
axisTicks: { show: false },
|
||||
labels: { show: false },
|
||||
},
|
||||
yaxis: { labels: { show: false } },
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 1441,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '30%',
|
||||
borderRadius: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 1368,
|
||||
options: { plotOptions: { bar: { columnWidth: '48%' } } },
|
||||
},
|
||||
{
|
||||
breakpoint: 1264,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 6,
|
||||
columnWidth: '30%',
|
||||
colors: { backgroundBarRadius: 6 },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 960,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '15%',
|
||||
borderRadius: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 883,
|
||||
options: { plotOptions: { bar: { columnWidth: '20%' } } },
|
||||
},
|
||||
{
|
||||
breakpoint: 768,
|
||||
options: { plotOptions: { bar: { columnWidth: '25%' } } },
|
||||
},
|
||||
{
|
||||
breakpoint: 600,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '15%',
|
||||
borderRadius: 4,
|
||||
},
|
||||
colors: { backgroundBarRadius: 9 },
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 479,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: { borderRadius: 4 },
|
||||
colors: { backgroundBarRadius: 9 },
|
||||
},
|
||||
grid: {
|
||||
padding: {
|
||||
right: -15,
|
||||
left: -15,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 400,
|
||||
options: { plotOptions: { bar: { borderRadius: 4 } } },
|
||||
},
|
||||
],
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardItem class="pb-3">
|
||||
<VCardTitle>Orders</VCardTitle>
|
||||
<VCardSubtitle>Last Week</VCardSubtitle>
|
||||
</VCardItem>
|
||||
|
||||
<VCardText>
|
||||
<VueApexCharts
|
||||
:options="chartOptions"
|
||||
:series="series"
|
||||
:height="62"
|
||||
/>
|
||||
|
||||
<div class="d-flex align-center justify-space-between gap-x-2 mt-3">
|
||||
<h4 class="text-h4 text-center">
|
||||
124k
|
||||
</h4>
|
||||
<div class="text-sm text-success">
|
||||
+12.6%
|
||||
</div>
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
169
resources/js/views/dashboards/crm/CrmProjectStatus.vue
Normal file
169
resources/js/views/dashboards/crm/CrmProjectStatus.vue
Normal file
@@ -0,0 +1,169 @@
|
||||
<script setup>
|
||||
import { useTheme } from 'vuetify'
|
||||
import { prefixWithPlus } from '@core/utils/formatters'
|
||||
|
||||
|
||||
const vuetifyTheme = useTheme()
|
||||
|
||||
const series = [{
|
||||
data: [
|
||||
2000,
|
||||
2000,
|
||||
4000,
|
||||
4000,
|
||||
3050,
|
||||
3050,
|
||||
2000,
|
||||
2000,
|
||||
3050,
|
||||
3050,
|
||||
4700,
|
||||
4700,
|
||||
2750,
|
||||
2750,
|
||||
5700,
|
||||
5700,
|
||||
],
|
||||
}]
|
||||
|
||||
|
||||
const chartOptions = computed(() => {
|
||||
const currentTheme = vuetifyTheme.current.value.colors
|
||||
|
||||
return {
|
||||
chart: {
|
||||
type: 'area',
|
||||
toolbar: false,
|
||||
},
|
||||
markers: { strokeColor: 'transparent' },
|
||||
dataLabels: { enabled: false },
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
left: -10,
|
||||
right: -5,
|
||||
top: -40,
|
||||
},
|
||||
},
|
||||
stroke: {
|
||||
width: 3,
|
||||
curve: 'straight',
|
||||
},
|
||||
colors: [currentTheme.warning],
|
||||
fill: {
|
||||
type: 'gradient',
|
||||
gradient: {
|
||||
opacityFrom: 0.6,
|
||||
opacityTo: 0.15,
|
||||
stops: [
|
||||
0,
|
||||
95,
|
||||
100,
|
||||
],
|
||||
},
|
||||
},
|
||||
xaxis: {
|
||||
labels: { show: false },
|
||||
axisBorder: { show: false },
|
||||
axisTicks: { show: false },
|
||||
lines: { show: false },
|
||||
},
|
||||
yaxis: {
|
||||
labels: { show: false },
|
||||
min: 1000,
|
||||
max: 6000,
|
||||
tickAmount: 5,
|
||||
},
|
||||
tooltip: { enabled: false },
|
||||
}
|
||||
})
|
||||
|
||||
const projectStatus = [
|
||||
{
|
||||
title: 'Donates',
|
||||
amount: '$756.26',
|
||||
lossProfit: -139.34,
|
||||
},
|
||||
{
|
||||
title: 'Podcasts',
|
||||
amount: '$2,207.03',
|
||||
lossProfit: +576.24,
|
||||
},
|
||||
]
|
||||
|
||||
const moreList = [
|
||||
{
|
||||
title: 'View More',
|
||||
value: 'View More',
|
||||
},
|
||||
{
|
||||
title: 'Delete',
|
||||
value: 'Delete',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard title="Project Status">
|
||||
<template #append>
|
||||
<div class="mt-n4 me-n2">
|
||||
<MoreBtn
|
||||
size="small"
|
||||
:menu-list="moreList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<VCardText>
|
||||
<VList class="card-list mb-6">
|
||||
<VListItem>
|
||||
<VListItemTitle class="font-weight-medium">
|
||||
$4,3742
|
||||
</VListItemTitle>
|
||||
<template #prepend>
|
||||
<VAvatar
|
||||
color="warning"
|
||||
variant="tonal"
|
||||
rounded
|
||||
icon="tabler-currency-dollar"
|
||||
/>
|
||||
</template>
|
||||
<VListItemSubtitle>
|
||||
Your Earnings
|
||||
</VListItemSubtitle>
|
||||
|
||||
<template #append>
|
||||
<span class="text-success font-weight-medium">+10.2%</span>
|
||||
</template>
|
||||
</VListItem>
|
||||
</VList>
|
||||
|
||||
<VueApexCharts
|
||||
:options="chartOptions"
|
||||
:series="series"
|
||||
height="208"
|
||||
/>
|
||||
|
||||
<VList class="card-list">
|
||||
<VListItem
|
||||
v-for="status in projectStatus"
|
||||
:key="status.title"
|
||||
>
|
||||
<VListItemTitle class="font-weight-medium">
|
||||
{{ status.title }}
|
||||
</VListItemTitle>
|
||||
<template #append>
|
||||
<span class="me-4 text-medium-emphasis">{{ status.amount }}</span>
|
||||
<span :class="status.lossProfit > 0 ? 'text-success' : 'text-error'">{{ prefixWithPlus(status.lossProfit) }}</span>
|
||||
</template>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card-list {
|
||||
--v-card-list-gap: 16px;
|
||||
}
|
||||
</style>
|
||||
168
resources/js/views/dashboards/crm/CrmRecentTransactions.vue
Normal file
168
resources/js/views/dashboards/crm/CrmRecentTransactions.vue
Normal file
@@ -0,0 +1,168 @@
|
||||
<script setup>
|
||||
import aeIcon from '@images/icons/payments/ae-icon.png'
|
||||
import mastercardIcon from '@images/icons/payments/mastercard-icon.png'
|
||||
import visaIcon from '@images/icons/payments/visa-icon.png'
|
||||
|
||||
const lastTransitions = [
|
||||
{
|
||||
cardImg: visaIcon,
|
||||
lastDigit: '*4230',
|
||||
cardType: 'Credit',
|
||||
sentDate: '17 Mar 2022',
|
||||
status: 'Verified',
|
||||
trend: '+$1,678',
|
||||
},
|
||||
{
|
||||
cardImg: mastercardIcon,
|
||||
lastDigit: '*5578',
|
||||
cardType: 'Credit',
|
||||
sentDate: '12 Feb 2022',
|
||||
status: 'Rejected',
|
||||
trend: '-$839',
|
||||
},
|
||||
{
|
||||
cardImg: aeIcon,
|
||||
lastDigit: '*4567',
|
||||
cardType: 'Credit',
|
||||
sentDate: '28 Feb 2022',
|
||||
status: 'Verified',
|
||||
trend: '+$435',
|
||||
},
|
||||
{
|
||||
cardImg: visaIcon,
|
||||
lastDigit: '*5699',
|
||||
cardType: 'Credit',
|
||||
sentDate: '8 Jan 2022',
|
||||
status: 'Pending',
|
||||
trend: '+$2,345',
|
||||
},
|
||||
{
|
||||
cardImg: visaIcon,
|
||||
lastDigit: '*5699',
|
||||
cardType: 'Credit',
|
||||
sentDate: '8 Jan 2022',
|
||||
status: 'Rejected',
|
||||
trend: '-$234',
|
||||
},
|
||||
]
|
||||
|
||||
const resolveStatus = {
|
||||
Verified: 'success',
|
||||
Rejected: 'error',
|
||||
Pending: 'secondary',
|
||||
}
|
||||
|
||||
const moreList = [
|
||||
{
|
||||
title: 'Refresh',
|
||||
value: 'refresh',
|
||||
},
|
||||
{
|
||||
title: 'Download',
|
||||
value: 'Download',
|
||||
},
|
||||
{
|
||||
title: 'View All',
|
||||
value: 'View All',
|
||||
},
|
||||
]
|
||||
|
||||
const getPaddingStyle = index => index ? 'padding-block-end: 1.25rem;' : 'padding-block: 1.25rem;'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard title="Last Transaction">
|
||||
<template #append>
|
||||
<div class="me-n2">
|
||||
<MoreBtn
|
||||
size="small"
|
||||
:menu-list="moreList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<VDivider />
|
||||
<VTable class="text-no-wrap transaction-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>CARD</th>
|
||||
<th>DATE</th>
|
||||
<th>STATUS</th>
|
||||
<th>
|
||||
TREND
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="(transition, index) in lastTransitions"
|
||||
:key="index"
|
||||
>
|
||||
<td
|
||||
:style="getPaddingStyle(index)"
|
||||
style="padding-inline-end: 1.5rem;"
|
||||
>
|
||||
<div class="d-flex align-center">
|
||||
<div class="me-4">
|
||||
<VImg
|
||||
:src="transition.cardImg"
|
||||
width="50"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-base mb-0 text-high-emphasis">
|
||||
{{ transition.lastDigit }}
|
||||
</p>
|
||||
<p class="text-sm mb-0">
|
||||
{{ transition.cardType }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
:style="getPaddingStyle(index)"
|
||||
style="padding-inline-end: 1.5rem;"
|
||||
>
|
||||
<p class="text-high-emphasis text-base mb-0">
|
||||
Sent
|
||||
</p>
|
||||
<div class="text-sm">
|
||||
{{ transition.sentDate }}
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
:style="getPaddingStyle(index)"
|
||||
style="padding-inline-end: 1.5rem;"
|
||||
>
|
||||
<VChip
|
||||
label
|
||||
:color="resolveStatus[transition.status]"
|
||||
size="small"
|
||||
>
|
||||
{{ transition.status }}
|
||||
</VChip>
|
||||
</td>
|
||||
<td
|
||||
:style="getPaddingStyle(index)"
|
||||
style="padding-inline-end: 1.5rem;"
|
||||
align="right"
|
||||
>
|
||||
<div class="text-high-emphasis text-base">
|
||||
{{ transition.trend }}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</VTable>
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.transaction-table {
|
||||
&.v-table .v-table__wrapper > table > tbody > tr:not(:last-child) > td,
|
||||
&.v-table .v-table__wrapper > table > tbody > tr:not(:last-child) > th {
|
||||
border-block-end: none !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
200
resources/js/views/dashboards/crm/CrmRevenueGrowth.vue
Normal file
200
resources/js/views/dashboards/crm/CrmRevenueGrowth.vue
Normal file
@@ -0,0 +1,200 @@
|
||||
<script setup>
|
||||
import { useTheme } from 'vuetify'
|
||||
import { hexToRgb } from '@layouts/utils'
|
||||
|
||||
const vuetifyTheme = useTheme()
|
||||
|
||||
const series = [{
|
||||
data: [
|
||||
25,
|
||||
40,
|
||||
55,
|
||||
70,
|
||||
85,
|
||||
70,
|
||||
55,
|
||||
],
|
||||
}]
|
||||
|
||||
const chartOptions = computed(() => {
|
||||
const currentTheme = vuetifyTheme.current.value.colors
|
||||
const variableTheme = vuetifyTheme.current.value.variables
|
||||
const labelSuccessColor = `rgba(${ hexToRgb(currentTheme.success) },0.2)`
|
||||
const labelColor = `rgba(${ hexToRgb(currentTheme['on-surface']) },${ variableTheme['disabled-opacity'] })`
|
||||
|
||||
return {
|
||||
chart: {
|
||||
height: 162,
|
||||
type: 'bar',
|
||||
parentHeightOffset: 0,
|
||||
toolbar: { show: false },
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
barHeight: '80%',
|
||||
columnWidth: '30%',
|
||||
startingShape: 'rounded',
|
||||
endingShape: 'rounded',
|
||||
borderRadius: 6,
|
||||
distributed: true,
|
||||
},
|
||||
},
|
||||
tooltip: { enabled: false },
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
top: -20,
|
||||
bottom: -12,
|
||||
left: -10,
|
||||
right: 0,
|
||||
},
|
||||
},
|
||||
colors: [
|
||||
labelSuccessColor,
|
||||
labelSuccessColor,
|
||||
labelSuccessColor,
|
||||
labelSuccessColor,
|
||||
currentTheme.success,
|
||||
labelSuccessColor,
|
||||
labelSuccessColor,
|
||||
],
|
||||
dataLabels: { enabled: false },
|
||||
legend: { show: false },
|
||||
xaxis: {
|
||||
categories: [
|
||||
'M',
|
||||
'T',
|
||||
'W',
|
||||
'T',
|
||||
'F',
|
||||
'S',
|
||||
'S',
|
||||
],
|
||||
axisBorder: { show: false },
|
||||
axisTicks: { show: false },
|
||||
labels: {
|
||||
style: {
|
||||
colors: labelColor,
|
||||
fontSize: '13px',
|
||||
fontFamily: 'Public sans',
|
||||
},
|
||||
},
|
||||
},
|
||||
yaxis: { labels: { show: false } },
|
||||
states: { hover: { filter: { type: 'none' } } },
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 1640,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '40%',
|
||||
borderRadius: 6,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 1471,
|
||||
options: { plotOptions: { bar: { columnWidth: '50%' } } },
|
||||
},
|
||||
{
|
||||
breakpoint: 1350,
|
||||
options: { plotOptions: { bar: { columnWidth: '57%' } } },
|
||||
},
|
||||
{
|
||||
breakpoint: 1032,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '50%',
|
||||
borderRadius: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 992,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '40%',
|
||||
borderRadius: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 855,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '50%',
|
||||
borderRadius: 6,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 440,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '30%',
|
||||
borderRadius: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 381,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '45%',
|
||||
borderRadius: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardText class="d-flex justify-space-between">
|
||||
<div class="d-flex flex-column">
|
||||
<div class="mb-auto">
|
||||
<h5 class="text-h5 text-no-wrap mb-2">
|
||||
Revenue Growth
|
||||
</h5>
|
||||
<div class="text-body-1">
|
||||
Weekly Report
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h5 class="text-h3 mb-2">
|
||||
$4,673
|
||||
</h5>
|
||||
<VChip
|
||||
label
|
||||
color="success"
|
||||
size="small"
|
||||
>
|
||||
+15.2%
|
||||
</VChip>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<VueApexCharts
|
||||
:options="chartOptions"
|
||||
:series="series"
|
||||
:height="162"
|
||||
/>
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
91
resources/js/views/dashboards/crm/CrmSalesAreaCharts.vue
Normal file
91
resources/js/views/dashboards/crm/CrmSalesAreaCharts.vue
Normal file
@@ -0,0 +1,91 @@
|
||||
<script setup>
|
||||
import { useTheme } from 'vuetify'
|
||||
|
||||
const vuetifyTheme = useTheme()
|
||||
const currentTheme = vuetifyTheme.current.value.colors
|
||||
|
||||
const series = [{
|
||||
name: 'Subscribers',
|
||||
data: [
|
||||
200,
|
||||
55,
|
||||
400,
|
||||
250,
|
||||
],
|
||||
}]
|
||||
|
||||
const chartOptions = {
|
||||
chart: {
|
||||
type: 'area',
|
||||
parentHeightOffset: 0,
|
||||
toolbar: { show: false },
|
||||
sparkline: { enabled: true },
|
||||
},
|
||||
markers: {
|
||||
colors: 'transparent',
|
||||
strokeColors: 'transparent',
|
||||
},
|
||||
grid: { show: false },
|
||||
colors: [currentTheme.success],
|
||||
fill: {
|
||||
type: 'gradient',
|
||||
gradient: {
|
||||
shadeIntensity: 0.9,
|
||||
opacityFrom: 0.5,
|
||||
opacityTo: 0.07,
|
||||
stops: [
|
||||
0,
|
||||
80,
|
||||
100,
|
||||
],
|
||||
},
|
||||
},
|
||||
dataLabels: { enabled: false },
|
||||
stroke: {
|
||||
width: 2,
|
||||
curve: 'smooth',
|
||||
},
|
||||
xaxis: {
|
||||
show: true,
|
||||
lines: { show: false },
|
||||
labels: { show: false },
|
||||
stroke: { width: 0 },
|
||||
axisBorder: { show: false },
|
||||
},
|
||||
yaxis: {
|
||||
stroke: { width: 0 },
|
||||
show: false,
|
||||
},
|
||||
tooltip: { enabled: false },
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardItem class="pb-3">
|
||||
<VCardTitle>
|
||||
Sales
|
||||
</VCardTitle>
|
||||
<VCardSubtitle>
|
||||
Last Year
|
||||
</VCardSubtitle>
|
||||
</VCardItem>
|
||||
|
||||
<VueApexCharts
|
||||
:options="chartOptions"
|
||||
:series="series"
|
||||
:height="68"
|
||||
/>
|
||||
|
||||
<VCardText class="pt-1">
|
||||
<div class="d-flex align-center justify-space-between gap-x-2">
|
||||
<h4 class="text-h4 text-center">
|
||||
175k
|
||||
</h4>
|
||||
<span class="text-sm text-error">
|
||||
-16.2%
|
||||
</span>
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
123
resources/js/views/dashboards/crm/CrmSalesByCountries.vue
Normal file
123
resources/js/views/dashboards/crm/CrmSalesByCountries.vue
Normal file
@@ -0,0 +1,123 @@
|
||||
<script setup>
|
||||
import auFlag from '@images/icons/countries/au.png'
|
||||
import brFlag from '@images/icons/countries/br.png'
|
||||
import cnFlag from '@images/icons/countries/cn.png'
|
||||
import frFlag from '@images/icons/countries/fr.png'
|
||||
import inFlag from '@images/icons/countries/in.png'
|
||||
import usFlag from '@images/icons/countries/us.png'
|
||||
|
||||
const salesByCountries = [
|
||||
{
|
||||
avatarImg: usFlag,
|
||||
stats: '$8,567k',
|
||||
subtitle: 'United states',
|
||||
profitLoss: 25.8,
|
||||
},
|
||||
{
|
||||
avatarImg: brFlag,
|
||||
stats: '$2,415k',
|
||||
subtitle: 'Brazil',
|
||||
profitLoss: -6.2,
|
||||
},
|
||||
{
|
||||
avatarImg: inFlag,
|
||||
stats: '$865k',
|
||||
subtitle: 'India',
|
||||
profitLoss: 12.4,
|
||||
},
|
||||
{
|
||||
avatarImg: auFlag,
|
||||
stats: '$745k',
|
||||
subtitle: 'Australia',
|
||||
profitLoss: -11.9,
|
||||
},
|
||||
{
|
||||
avatarImg: frFlag,
|
||||
stats: '$45',
|
||||
subtitle: 'France',
|
||||
profitLoss: 16.2,
|
||||
},
|
||||
{
|
||||
avatarImg: cnFlag,
|
||||
stats: '$12k',
|
||||
subtitle: 'China',
|
||||
profitLoss: 14.8,
|
||||
},
|
||||
]
|
||||
|
||||
const moreList = [
|
||||
{
|
||||
title: 'Refresh',
|
||||
value: 'refresh',
|
||||
},
|
||||
{
|
||||
title: 'Download',
|
||||
value: 'Download',
|
||||
},
|
||||
{
|
||||
title: 'View All',
|
||||
value: 'View All',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard
|
||||
title="Sales by Countries"
|
||||
subtitle="Monthly Sales Overview"
|
||||
>
|
||||
<template #append>
|
||||
<div class="mt-n4 me-n2">
|
||||
<MoreBtn
|
||||
size="small"
|
||||
:menu-list="moreList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<VCardText>
|
||||
<VList class="card-list">
|
||||
<VListItem
|
||||
v-for="country in salesByCountries"
|
||||
:key="country.stats"
|
||||
>
|
||||
<template #prepend>
|
||||
<VAvatar
|
||||
size="34"
|
||||
color="secondary"
|
||||
variant="tonal"
|
||||
class="me-1"
|
||||
:image="country.avatarImg"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<VListItemTitle class="font-weight-medium">
|
||||
{{ country.stats }}
|
||||
</VListItemTitle>
|
||||
<VListItemSubtitle>
|
||||
{{ country.subtitle }}
|
||||
</VListItemSubtitle>
|
||||
|
||||
<template #append>
|
||||
<div :class="`d-flex align-center font-weight-medium ${country.profitLoss > 0 ? 'text-success' : 'text-error'}`">
|
||||
<VIcon
|
||||
:icon="country.profitLoss > 0 ? 'tabler-chevron-up' : 'tabler-chevron-down'"
|
||||
size="20"
|
||||
class="me-1"
|
||||
/>
|
||||
<div class="font-weight-medium">
|
||||
{{ Math.abs(country.profitLoss) }}%
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card-list {
|
||||
--v-card-list-gap: 1rem;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,206 @@
|
||||
<script setup>
|
||||
import { useTheme } from 'vuetify'
|
||||
import { hexToRgb } from '@layouts/utils'
|
||||
|
||||
const vuetifyTheme = useTheme()
|
||||
|
||||
const series = [
|
||||
{
|
||||
name: 'PRODUCT A',
|
||||
data: [
|
||||
4,
|
||||
3,
|
||||
6,
|
||||
4,
|
||||
3,
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'PRODUCT B',
|
||||
data: [
|
||||
-3,
|
||||
-4,
|
||||
-3,
|
||||
-2,
|
||||
-3,
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
const chartOptions = computed(() => {
|
||||
const currentTheme = vuetifyTheme.current.value.colors
|
||||
|
||||
return {
|
||||
chart: {
|
||||
type: 'bar',
|
||||
parentHeightOffset: 0,
|
||||
stacked: true,
|
||||
toolbar: { show: false },
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'PRODUCT A',
|
||||
data: [
|
||||
4,
|
||||
3,
|
||||
6,
|
||||
4,
|
||||
3,
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'PRODUCT B',
|
||||
data: [
|
||||
-3,
|
||||
-4,
|
||||
-3,
|
||||
-2,
|
||||
-3,
|
||||
],
|
||||
},
|
||||
],
|
||||
plotOptions: {
|
||||
bar: {
|
||||
horizontal: false,
|
||||
columnWidth: '30%',
|
||||
barHeight: '100%',
|
||||
borderRadius: 5,
|
||||
startingShape: 'rounded',
|
||||
endingShape: 'rounded',
|
||||
},
|
||||
},
|
||||
dataLabels: { enabled: false },
|
||||
tooltip: { enabled: false },
|
||||
stroke: {
|
||||
curve: 'smooth',
|
||||
width: 1,
|
||||
lineCap: 'round',
|
||||
colors: [currentTheme.surface],
|
||||
},
|
||||
legend: { show: false },
|
||||
colors: [
|
||||
`rgba(${ hexToRgb(currentTheme.primary) },1)`,
|
||||
`rgba(${ hexToRgb(currentTheme.success) },1)`,
|
||||
],
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
top: -41,
|
||||
right: -5,
|
||||
left: -3,
|
||||
bottom: -15,
|
||||
},
|
||||
},
|
||||
xaxis: {
|
||||
categories: [
|
||||
'Mon',
|
||||
'Tue',
|
||||
'Wed',
|
||||
'Thu',
|
||||
'Fri',
|
||||
'Sat',
|
||||
'Sun',
|
||||
],
|
||||
labels: { show: false },
|
||||
axisBorder: { show: false },
|
||||
axisTicks: { show: false },
|
||||
},
|
||||
yaxis: { show: false },
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 1441,
|
||||
options: { plotOptions: { bar: { columnWidth: '40%' } } },
|
||||
},
|
||||
{
|
||||
breakpoint: 1300,
|
||||
options: { plotOptions: { bar: { columnWidth: '50%' } } },
|
||||
},
|
||||
{
|
||||
breakpoint: 1279,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 6,
|
||||
columnWidth: '20%',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 1025,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 7,
|
||||
columnWidth: '25%',
|
||||
},
|
||||
},
|
||||
chart: { height: 110 },
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 960,
|
||||
options: { plotOptions: { bar: { borderRadius: 6 } } },
|
||||
},
|
||||
{
|
||||
breakpoint: 782,
|
||||
options: { plotOptions: { bar: { columnWidth: '30%' } } },
|
||||
},
|
||||
{
|
||||
breakpoint: 600,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 12,
|
||||
columnWidth: '20%',
|
||||
},
|
||||
},
|
||||
chart: { height: 160 },
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 426,
|
||||
options: { plotOptions: { bar: { borderRadius: 8 } } },
|
||||
},
|
||||
{
|
||||
breakpoint: 376,
|
||||
options: { plotOptions: { bar: { borderRadius: 6 } } },
|
||||
},
|
||||
],
|
||||
states: {
|
||||
hover: { filter: { type: 'none' } },
|
||||
active: { filter: { type: 'none' } },
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardText>
|
||||
<div>
|
||||
<h5 class="text-h5">
|
||||
Sessions
|
||||
</h5>
|
||||
<p class="mb-0 text-sm text-disabled">
|
||||
This Month
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<VueApexCharts
|
||||
:options="chartOptions"
|
||||
:series="series"
|
||||
:height="75"
|
||||
/>
|
||||
|
||||
<div class="d-flex align-center justify-space-between mt-4">
|
||||
<h4 class="text-h4">
|
||||
45.1k
|
||||
</h4>
|
||||
<p class="mb-0 text-sm text-success">
|
||||
+12.6%
|
||||
</p>
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
@@ -0,0 +1,42 @@
|
||||
<script setup>
|
||||
import congoImg from '@images/illustrations/congo-illustration.png'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VRow no-gutters>
|
||||
<VCol cols="8">
|
||||
<VCardText>
|
||||
<h5 class="text-h5 text-no-wrap">
|
||||
Congratulations John! 🎉
|
||||
</h5>
|
||||
<p class="mb-2">
|
||||
Best seller of the month
|
||||
</p>
|
||||
<h4 class="text-h4 text-primary mb-1">
|
||||
$48.9k
|
||||
</h4>
|
||||
<VBtn>View Sales</VBtn>
|
||||
</VCardText>
|
||||
</VCol>
|
||||
|
||||
<VCol cols="4">
|
||||
<VCardText class="pb-0 px-0 position-relative h-100">
|
||||
<VImg
|
||||
:src="congoImg"
|
||||
:height="$vuetify.display.smAndUp ? 147 : 125"
|
||||
class="congo-john-img w-100"
|
||||
/>
|
||||
</VCardText>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.congo-john-img {
|
||||
position: absolute;
|
||||
inset-block-end: 0;
|
||||
inset-inline-end: 1.25rem;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,199 @@
|
||||
<script setup>
|
||||
import { useTheme } from 'vuetify'
|
||||
import { hexToRgb } from '@layouts/utils'
|
||||
|
||||
const vuetifyTheme = useTheme()
|
||||
|
||||
const series = [{
|
||||
data: [
|
||||
40,
|
||||
95,
|
||||
60,
|
||||
45,
|
||||
90,
|
||||
50,
|
||||
75,
|
||||
],
|
||||
}]
|
||||
|
||||
const chartOptions = computed(() => {
|
||||
const currentTheme = vuetifyTheme.current.value.colors
|
||||
const variableTheme = vuetifyTheme.current.value.variables
|
||||
const labelColor = `rgba(${ hexToRgb(currentTheme['on-background']) },${ variableTheme['disabled-opacity'] })`
|
||||
const labelPrimaryColor = `rgba(${ hexToRgb(currentTheme.primary) },0.1)`
|
||||
|
||||
return {
|
||||
chart: {
|
||||
type: 'bar',
|
||||
toolbar: { show: false },
|
||||
},
|
||||
tooltip: { enabled: false },
|
||||
plotOptions: {
|
||||
bar: {
|
||||
barHeight: '60%',
|
||||
columnWidth: '60%',
|
||||
startingShape: 'rounded',
|
||||
endingShape: 'rounded',
|
||||
borderRadius: 4,
|
||||
distributed: true,
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
top: -20,
|
||||
bottom: 0,
|
||||
left: -10,
|
||||
right: -10,
|
||||
},
|
||||
},
|
||||
colors: [
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
`rgba(${ hexToRgb(currentTheme.primary) }, 1)`,
|
||||
labelPrimaryColor,
|
||||
labelPrimaryColor,
|
||||
],
|
||||
dataLabels: { enabled: false },
|
||||
legend: { show: false },
|
||||
xaxis: {
|
||||
categories: [
|
||||
'Mo',
|
||||
'Tu',
|
||||
'We',
|
||||
'Th',
|
||||
'Fr',
|
||||
'Sa',
|
||||
'Su',
|
||||
],
|
||||
axisBorder: { show: false },
|
||||
axisTicks: { show: false },
|
||||
labels: {
|
||||
style: {
|
||||
colors: labelColor,
|
||||
fontSize: '13px',
|
||||
},
|
||||
},
|
||||
},
|
||||
yaxis: { labels: { show: false } },
|
||||
}
|
||||
})
|
||||
|
||||
const earningReports = [
|
||||
{
|
||||
avatarIcon: 'tabler-chart-pie-2',
|
||||
avatarColor: 'primary',
|
||||
title: 'Net Profit',
|
||||
subtitle: '12.4k Sales',
|
||||
earnings: '$1,619',
|
||||
percentage: '18.6%',
|
||||
},
|
||||
{
|
||||
avatarIcon: 'tabler-currency-dollar',
|
||||
avatarColor: 'success',
|
||||
title: 'Total Income',
|
||||
subtitle: 'Sales, Affiliation',
|
||||
earnings: '$3,571',
|
||||
percentage: '39.6%',
|
||||
},
|
||||
{
|
||||
avatarIcon: 'tabler-credit-card',
|
||||
avatarColor: 'secondary',
|
||||
title: 'Total Expenses',
|
||||
subtitle: 'ADVT, Marketing',
|
||||
earnings: '$430',
|
||||
percentage: '52.8%',
|
||||
},
|
||||
]
|
||||
|
||||
const moreList = [
|
||||
{
|
||||
title: 'Refresh',
|
||||
value: 'refresh',
|
||||
},
|
||||
{
|
||||
title: 'Download',
|
||||
value: 'Download',
|
||||
},
|
||||
{
|
||||
title: 'View All',
|
||||
value: 'View All',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard
|
||||
title="Earning Reports"
|
||||
subtitle="Weekly Earnings Overview"
|
||||
>
|
||||
<template #append>
|
||||
<div class="mt-n4 me-n2">
|
||||
<MoreBtn
|
||||
size="small"
|
||||
:menu-list="moreList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<VCardText>
|
||||
<VList class="card-list mb-5">
|
||||
<VListItem
|
||||
v-for="report in earningReports"
|
||||
:key="report.title"
|
||||
>
|
||||
<template #prepend>
|
||||
<VAvatar
|
||||
rounded
|
||||
size="34"
|
||||
variant="tonal"
|
||||
:color="report.avatarColor"
|
||||
class="me-1"
|
||||
>
|
||||
<VIcon
|
||||
:icon="report.avatarIcon"
|
||||
size="22"
|
||||
/>
|
||||
</VAvatar>
|
||||
</template>
|
||||
|
||||
<VListItemTitle class="font-weight-medium me-4">
|
||||
{{ report.title }}
|
||||
</VListItemTitle>
|
||||
<VListItemSubtitle class="me-4">
|
||||
{{ report.subtitle }}
|
||||
</VListItemSubtitle>
|
||||
|
||||
<template #append>
|
||||
<div class="d-flex align-center text-body-2">
|
||||
<span class="me-4">{{ report.earnings }}</span>
|
||||
<VIcon
|
||||
color="success"
|
||||
icon="tabler-chevron-up"
|
||||
size="20"
|
||||
class="me-1"
|
||||
/>
|
||||
<span class="text-disabled">{{ report.percentage }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</VListItem>
|
||||
</VList>
|
||||
|
||||
<div>
|
||||
<VueApexCharts
|
||||
:options="chartOptions"
|
||||
:series="series"
|
||||
:height="196"
|
||||
/>
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card-list {
|
||||
--v-card-list-gap: 1.25rem;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,115 @@
|
||||
<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 },
|
||||
parentHeightOffset: 0,
|
||||
type: 'radialBar',
|
||||
},
|
||||
colors: ['rgba(var(--v-theme-warning), 1)'],
|
||||
plotOptions: {
|
||||
radialBar: {
|
||||
offsetY: 0,
|
||||
startAngle: -90,
|
||||
endAngle: 90,
|
||||
hollow: { size: '65%' },
|
||||
track: {
|
||||
strokeWidth: '45%',
|
||||
background: 'rgba(var(--v-track-bg))',
|
||||
},
|
||||
dataLabels: {
|
||||
name: { show: false },
|
||||
value: {
|
||||
fontSize: '24px',
|
||||
color: `rgba(${ hexToRgb(currentTheme['on-background']) },${ variableTheme['high-emphasis-opacity'] })`,
|
||||
fontWeight: 600,
|
||||
offsetY: -5,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
show: false,
|
||||
padding: { bottom: 5 },
|
||||
},
|
||||
stroke: { lineCap: 'round' },
|
||||
labels: ['Progress'],
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 1442,
|
||||
options: {
|
||||
chart: { height: 140 },
|
||||
plotOptions: {
|
||||
radialBar: {
|
||||
dataLabels: { value: { fontSize: '24px' } },
|
||||
hollow: { size: '60%' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 1370,
|
||||
options: { chart: { height: 120 } },
|
||||
},
|
||||
{
|
||||
breakpoint: 1280,
|
||||
options: {
|
||||
chart: { height: 200 },
|
||||
plotOptions: {
|
||||
radialBar: {
|
||||
dataLabels: { value: { fontSize: '18px' } },
|
||||
hollow: { size: '70%' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 960,
|
||||
options: {
|
||||
chart: { height: 250 },
|
||||
plotOptions: {
|
||||
radialBar: {
|
||||
hollow: { size: '70%' },
|
||||
dataLabels: { value: { fontSize: '24px' } },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardItem class="pb-3">
|
||||
<VCardTitle>
|
||||
82.5K
|
||||
</VCardTitle>
|
||||
<VCardSubtitle>
|
||||
Expenses
|
||||
</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<VueApexCharts
|
||||
:options="chartOptions"
|
||||
:series="series"
|
||||
type="radialBar"
|
||||
:height="135"
|
||||
/>
|
||||
|
||||
<div class="text-sm text-center clamp-text text-disabled mt-3">
|
||||
$21k Expenses more than last month
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
@@ -0,0 +1,447 @@
|
||||
<script setup>
|
||||
import { useDisplay, useTheme } from 'vuetify'
|
||||
import { hexToRgb } from '@layouts/utils'
|
||||
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
donutColors: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
progress: {
|
||||
type: Number,
|
||||
default: 75
|
||||
}
|
||||
})
|
||||
|
||||
const vuetifyTheme = useTheme()
|
||||
const display = useDisplay()
|
||||
const cardRef = ref(null)
|
||||
const cardWidth = ref(0)
|
||||
|
||||
const updateCardWidth = () => {
|
||||
if (cardRef.value) {
|
||||
cardWidth.value = cardRef.value.offsetWidth
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
updateCardWidth()
|
||||
window.addEventListener('resize', updateCardWidth)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', updateCardWidth)
|
||||
})
|
||||
|
||||
const chartSeries = computed(() => [props.progress, 100 - props.progress])
|
||||
|
||||
const processColors = (colors) => {
|
||||
const currentTheme = vuetifyTheme.current.value.colors
|
||||
return colors.map(color => {
|
||||
if (typeof color === 'string' && currentTheme[color]) {
|
||||
return currentTheme[color]
|
||||
}
|
||||
return color
|
||||
})
|
||||
}
|
||||
|
||||
const chartSize = computed(() => {
|
||||
const width = cardWidth.value || 300
|
||||
|
||||
let size
|
||||
if (width < 250) {
|
||||
size = Math.max(120, width * 0.5)
|
||||
} else if (width < 350) {
|
||||
size = Math.max(150, width * 0.5)
|
||||
} else if (width < 450) {
|
||||
size = Math.max(180, width * 0.45)
|
||||
} else if (width < 600) {
|
||||
size = Math.max(200, width * 0.4)
|
||||
} else if (width < 800) {
|
||||
size = Math.max(240, width * 0.35)
|
||||
} else {
|
||||
size = Math.min(300, width * 0.32)
|
||||
}
|
||||
|
||||
if (display.xs.value) size = Math.max(size, 120)
|
||||
if (display.sm.value) size = Math.max(size, 160)
|
||||
if (display.md.value) size = Math.max(size, 200)
|
||||
|
||||
return { width: size, height: size }
|
||||
})
|
||||
|
||||
const textSizes = computed(() => {
|
||||
const width = cardWidth.value || 300
|
||||
|
||||
if (width < 250 || display.xs.value) {
|
||||
return {
|
||||
title: 'text-body-2',
|
||||
subtitle: 'text-caption',
|
||||
mainNumber: 'text-h6',
|
||||
percentage: 'text-body-2'
|
||||
}
|
||||
} else if (width < 350 || display.sm.value) {
|
||||
return {
|
||||
title: 'text-body-1',
|
||||
subtitle: 'text-body-2',
|
||||
mainNumber: 'text-h5',
|
||||
percentage: 'text-body-2'
|
||||
}
|
||||
} else if (width < 450) {
|
||||
return {
|
||||
title: 'text-h6',
|
||||
subtitle: 'text-body-2',
|
||||
mainNumber: 'text-h4',
|
||||
percentage: 'text-body-1'
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
title: display.md.value ? 'text-h5' : 'text-h4',
|
||||
subtitle: 'text-body-1',
|
||||
mainNumber: display.lg.value ? 'text-h2' : 'text-h3',
|
||||
percentage: 'text-body-1'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const chartOptions = computed(() => {
|
||||
const currentTheme = vuetifyTheme.current.value.colors
|
||||
const variableTheme = vuetifyTheme.current.value.variables
|
||||
const width = cardWidth.value || 300
|
||||
|
||||
const defaultDonutColors = [
|
||||
currentTheme.success,
|
||||
]
|
||||
|
||||
const usedDonutColors = props.donutColors.length
|
||||
? processColors(props.donutColors)
|
||||
: defaultDonutColors
|
||||
|
||||
const headingColor = `rgba(${hexToRgb(currentTheme['on-background'])},${variableTheme['high-emphasis-opacity']})`
|
||||
const backgroundCircleColor = `rgba(${hexToRgb(usedDonutColors[0])}, 0.15)`
|
||||
|
||||
const chartSizeValue = chartSize.value.width
|
||||
const valueFontSize = width < 250 ? '1.1rem' :
|
||||
width < 350 ? '1.3rem' :
|
||||
width < 450 ? '1.5rem' :
|
||||
chartSizeValue < 160 ? '1.3rem' :
|
||||
chartSizeValue < 200 ? '1.6rem' :
|
||||
chartSizeValue < 250 ? '1.8rem' : '2rem'
|
||||
|
||||
const labelFontSize = width < 250 ? '0.8rem' :
|
||||
width < 350 ? '0.9rem' :
|
||||
chartSizeValue < 160 ? '0.9rem' :
|
||||
chartSizeValue < 200 ? '1rem' : '1.1rem'
|
||||
|
||||
const donutSize = width < 300 ? '65%' :
|
||||
width < 400 ? '70%' :
|
||||
chartSizeValue < 180 ? '70%' :
|
||||
chartSizeValue < 220 ? '75%' : '80%'
|
||||
|
||||
return {
|
||||
chart: {
|
||||
parentHeightOffset: 0,
|
||||
type: 'donut',
|
||||
sparkline: {
|
||||
enabled: false
|
||||
},
|
||||
},
|
||||
labels: ['Progress', 'Remaining'],
|
||||
colors: [...usedDonutColors, backgroundCircleColor],
|
||||
stroke: {
|
||||
width: 0
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: false
|
||||
},
|
||||
legend: {
|
||||
show: false
|
||||
},
|
||||
tooltip: {
|
||||
enabled: true,
|
||||
theme: 'dark',
|
||||
style: {
|
||||
fontSize: width < 300 ? '12px' : '14px'
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
padding: {
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
left: 0,
|
||||
},
|
||||
},
|
||||
states: {
|
||||
hover: {
|
||||
filter: {
|
||||
type: 'none'
|
||||
}
|
||||
}
|
||||
},
|
||||
plotOptions: {
|
||||
pie: {
|
||||
startAngle: -90,
|
||||
endAngle: 270,
|
||||
donut: {
|
||||
size: donutSize,
|
||||
background: 'transparent',
|
||||
labels: {
|
||||
show: true,
|
||||
value: {
|
||||
show: true,
|
||||
fontSize: valueFontSize,
|
||||
fontFamily: 'Public Sans',
|
||||
color: headingColor,
|
||||
fontWeight: 600,
|
||||
offsetY: chartSizeValue < 140 ? -2 : 0,
|
||||
formatter(val) {
|
||||
return `${Math.round(val)}%`
|
||||
},
|
||||
},
|
||||
name: {
|
||||
show: false
|
||||
},
|
||||
total: {
|
||||
show: true,
|
||||
showAlways: true,
|
||||
color: usedDonutColors[0],
|
||||
fontSize: labelFontSize,
|
||||
label: 'Progress',
|
||||
fontFamily: 'Public Sans',
|
||||
fontWeight: 500,
|
||||
formatter() {
|
||||
return `${props.progress}%`
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 280,
|
||||
options: {
|
||||
chart: {
|
||||
width: 120,
|
||||
height: 120
|
||||
},
|
||||
plotOptions: {
|
||||
pie: {
|
||||
donut: {
|
||||
size: '65%',
|
||||
labels: {
|
||||
value: {
|
||||
fontSize: '1.1rem',
|
||||
offsetY: -2
|
||||
},
|
||||
total: {
|
||||
fontSize: '0.8rem'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 400,
|
||||
options: {
|
||||
chart: {
|
||||
width: 150,
|
||||
height: 150
|
||||
},
|
||||
plotOptions: {
|
||||
pie: {
|
||||
donut: {
|
||||
size: '70%',
|
||||
labels: {
|
||||
value: {
|
||||
fontSize: '1.3rem',
|
||||
offsetY: -1
|
||||
},
|
||||
total: {
|
||||
fontSize: '0.9rem'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 600,
|
||||
options: {
|
||||
chart: {
|
||||
width: 180,
|
||||
height: 180
|
||||
},
|
||||
plotOptions: {
|
||||
pie: {
|
||||
donut: {
|
||||
size: '75%',
|
||||
labels: {
|
||||
value: {
|
||||
fontSize: '1.5rem'
|
||||
},
|
||||
total: {
|
||||
fontSize: '1rem'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 1024,
|
||||
options: {
|
||||
chart: {
|
||||
width: 240,
|
||||
height: 240
|
||||
},
|
||||
plotOptions: {
|
||||
pie: {
|
||||
donut: {
|
||||
size: '80%',
|
||||
labels: {
|
||||
value: {
|
||||
fontSize: '1.8rem'
|
||||
},
|
||||
total: {
|
||||
fontSize: '1.1rem'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
const cardBackgroundStyle = computed(() => {
|
||||
const defaultDonutColors = [
|
||||
vuetifyTheme.current.value.colors.success,
|
||||
]
|
||||
|
||||
const colors = props.donutColors.length ? processColors(props.donutColors) : defaultDonutColors
|
||||
|
||||
const createGradientColor = (color, opacity = 0.08) => {
|
||||
if (color.includes('rgba')) {
|
||||
return color.replace(/[\d\.]+\)$/g, `${opacity})`)
|
||||
}
|
||||
if (color.startsWith('#')) {
|
||||
return `rgba(${hexToRgb(color)}, ${opacity})`
|
||||
}
|
||||
if (color.includes('rgb')) {
|
||||
return color.replace('rgb', 'rgba').replace(')', `, ${opacity})`)
|
||||
}
|
||||
return `rgba(${hexToRgb(color)}, ${opacity})`
|
||||
}
|
||||
|
||||
const gradientColors = colors.map((color, index) =>
|
||||
createGradientColor(color, index === 0 ? 0.12 : 0.04)
|
||||
)
|
||||
|
||||
return {
|
||||
background: `linear-gradient(135deg,
|
||||
${gradientColors[0]} 0%,
|
||||
${gradientColors[1] || gradientColors[0]} 50%,
|
||||
${gradientColors[2] || gradientColors[0]} 100%)`
|
||||
}
|
||||
})
|
||||
|
||||
const layoutClasses = computed(() => {
|
||||
const width = cardWidth.value || 300
|
||||
|
||||
return {
|
||||
cardText: width < 250 ? 'pa-2' :
|
||||
width < 350 ? 'pa-3' :
|
||||
width < 500 ? 'pa-4' : 'pa-5',
|
||||
textSection: width < 250 ? 'me-2' :
|
||||
width < 350 ? 'me-3' :
|
||||
width < 500 ? 'me-4' : 'me-5',
|
||||
chartSection: 'flex-shrink-0',
|
||||
iconSize: width < 250 ? 12 :
|
||||
width < 350 ? 14 :
|
||||
width < 500 ? 16 : 18,
|
||||
spacing: width < 300 ? 'mb-2' :
|
||||
width < 450 ? 'mb-3' : 'mb-4'
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard
|
||||
ref="cardRef"
|
||||
class="overflow-visible"
|
||||
:style="cardBackgroundStyle"
|
||||
>
|
||||
<VCardText
|
||||
class="d-flex align-center justify-space-between"
|
||||
:class="layoutClasses.cardText"
|
||||
>
|
||||
<div
|
||||
class="d-flex flex-column flex-grow-1"
|
||||
:class="layoutClasses.textSection"
|
||||
>
|
||||
<div :class="layoutClasses.spacing">
|
||||
<h5
|
||||
class="text-no-wrap font-weight-medium"
|
||||
:class="textSizes.title"
|
||||
style="line-height: 1.2;"
|
||||
>
|
||||
Generated Leads
|
||||
</h5>
|
||||
<div
|
||||
class="text-medium-emphasis"
|
||||
:class="textSizes.subtitle"
|
||||
style="line-height: 1.1;"
|
||||
>
|
||||
Monthly Report
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3
|
||||
class="font-weight-bold"
|
||||
:class="[textSizes.mainNumber, layoutClasses.spacing]"
|
||||
style="line-height: 1.1;"
|
||||
>
|
||||
4,350
|
||||
</h3>
|
||||
<div class="d-flex align-center">
|
||||
<VIcon
|
||||
icon="tabler-chevron-up"
|
||||
:color="(props.donutColors.length ? processColors(props.donutColors) : [vuetifyTheme.current.value.colors.success])[0]"
|
||||
:size="layoutClasses.iconSize"
|
||||
class="me-1"
|
||||
/>
|
||||
<span
|
||||
class="font-weight-medium"
|
||||
:class="textSizes.percentage"
|
||||
:style="{ color: (props.donutColors.length ? processColors(props.donutColors) : [vuetifyTheme.current.value.colors.success])[0] }"
|
||||
>
|
||||
15.8%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="d-flex align-center justify-center"
|
||||
:class="layoutClasses.chartSection"
|
||||
>
|
||||
<VueApexCharts
|
||||
:options="chartOptions"
|
||||
:series="chartSeries"
|
||||
:height="chartSize.height"
|
||||
:width="chartSize.width"
|
||||
/>
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
@@ -0,0 +1,327 @@
|
||||
<script setup>
|
||||
const searchQuery = ref('')
|
||||
const selectedStatus = ref(null)
|
||||
const selectedRows = ref([])
|
||||
|
||||
// Data table options
|
||||
const itemsPerPage = ref(6)
|
||||
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: 'Status',
|
||||
key: 'status',
|
||||
sortable: false,
|
||||
},
|
||||
{
|
||||
title: 'Total',
|
||||
key: 'total',
|
||||
},
|
||||
{
|
||||
title: 'Issued Date',
|
||||
key: 'date',
|
||||
},
|
||||
{
|
||||
title: 'Balance',
|
||||
key: 'balance',
|
||||
},
|
||||
{
|
||||
title: 'Actions',
|
||||
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: 'tabler-chart-pie-2',
|
||||
}
|
||||
if (status === 'Paid')
|
||||
return {
|
||||
variant: 'success',
|
||||
icon: 'tabler-check',
|
||||
}
|
||||
if (status === 'Downloaded')
|
||||
return {
|
||||
variant: 'info',
|
||||
icon: 'tabler-arrow-down',
|
||||
}
|
||||
if (status === 'Draft')
|
||||
return {
|
||||
variant: 'primary',
|
||||
icon: 'tabler-folder',
|
||||
}
|
||||
if (status === 'Sent')
|
||||
return {
|
||||
variant: 'secondary',
|
||||
icon: 'tabler-mail',
|
||||
}
|
||||
if (status === 'Past Due')
|
||||
return {
|
||||
variant: 'error',
|
||||
icon: 'tabler-help',
|
||||
}
|
||||
|
||||
return {
|
||||
variant: 'secondary',
|
||||
icon: 'tabler-x',
|
||||
}
|
||||
}
|
||||
|
||||
const computedMoreList = computed(() => {
|
||||
return paramId => [
|
||||
{
|
||||
title: 'Download',
|
||||
value: 'download',
|
||||
prependIcon: 'tabler-download',
|
||||
},
|
||||
{
|
||||
title: 'Edit',
|
||||
value: 'edit',
|
||||
prependIcon: 'tabler-pencil',
|
||||
to: {
|
||||
name: 'apps-invoice-edit-id',
|
||||
params: { id: paramId },
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Duplicate',
|
||||
value: 'duplicate',
|
||||
prependIcon: 'tabler-layers-intersect',
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
const deleteInvoice = async id => {
|
||||
await $api(`/apps/invoice/${ id }`, { method: 'DELETE' })
|
||||
fetchInvoices()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard
|
||||
v-if="invoices"
|
||||
id="invoice-list"
|
||||
>
|
||||
<VCardText>
|
||||
<div class="d-flex justify-space-between flex-wrap gap-4">
|
||||
<div class="d-flex gap-4 align-center">
|
||||
<div class="d-flex align-center gap-x-2">
|
||||
<div>
|
||||
Show
|
||||
</div>
|
||||
<AppSelect
|
||||
:model-value="itemsPerPage"
|
||||
:items="[
|
||||
{ value: 6, title: '6' },
|
||||
{ value: 10, title: '10' },
|
||||
{ value: 25, title: '25' },
|
||||
{ value: 50, title: '50' },
|
||||
{ value: 100, title: '100' },
|
||||
{ value: -1, title: 'All' },
|
||||
]"
|
||||
@update:model-value="itemsPerPage = parseInt($event, 10)"
|
||||
/>
|
||||
</div>
|
||||
<!-- 👉 Create invoice -->
|
||||
<VBtn
|
||||
prepend-icon="tabler-plus"
|
||||
:to="{ name: 'apps-invoice-add' }"
|
||||
>
|
||||
Create invoice
|
||||
</VBtn>
|
||||
</div>
|
||||
<div class="d-flex align-center flex-wrap gap-4">
|
||||
<!-- 👉 Search -->
|
||||
<div class="invoice-list-filter">
|
||||
<AppTextField
|
||||
v-model="searchQuery"
|
||||
placeholder="Search Invoice"
|
||||
/>
|
||||
</div>
|
||||
<!-- 👉 Select status -->
|
||||
<div class="invoice-list-filter">
|
||||
<AppSelect
|
||||
v-model="selectedStatus"
|
||||
placeholder="Select Status"
|
||||
clearable
|
||||
clear-icon="tabler-x"
|
||||
single-line
|
||||
:items="['Downloaded', 'Draft', 'Sent', 'Paid', 'Partial Payment', 'Past Due']"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</VCardText>
|
||||
|
||||
<VDivider />
|
||||
|
||||
<!-- 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"
|
||||
@update:options="updateOptions"
|
||||
>
|
||||
<!-- id -->
|
||||
<template #item.id="{ item }">
|
||||
<RouterLink :to="{ name: 'apps-invoice-preview-id', params: { id: item.id } }">
|
||||
#{{ item.id }}
|
||||
</RouterLink>
|
||||
</template>
|
||||
|
||||
<!-- status -->
|
||||
<template #item.status="{ 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>
|
||||
|
||||
<!-- Total -->
|
||||
<template #item.total="{ item }">
|
||||
${{ item.total }}
|
||||
</template>
|
||||
|
||||
<!-- 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"
|
||||
label
|
||||
size="x-small"
|
||||
>
|
||||
{{ (resolveInvoiceBalanceVariant(item.balance, item.total)).status }}
|
||||
</VChip>
|
||||
|
||||
<template v-else>
|
||||
<span class="text-base 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))}` }}
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<!-- Actions -->
|
||||
<template #item.actions="{ item }">
|
||||
<IconBtn @click="deleteInvoice(item.id)">
|
||||
<VIcon icon="tabler-trash" />
|
||||
</IconBtn>
|
||||
|
||||
<IconBtn :to="{ name: 'apps-invoice-preview-id', params: { id: item.id } }">
|
||||
<VIcon icon="tabler-eye" />
|
||||
</IconBtn>
|
||||
|
||||
<MoreBtn
|
||||
:menu-list="computedMoreList(item.id)"
|
||||
item-props
|
||||
color="undefined"
|
||||
size="small"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<!-- pagination -->
|
||||
<template #bottom>
|
||||
<TablePagination
|
||||
v-model:page="page"
|
||||
:items-per-page="itemsPerPage"
|
||||
:total-items="totalInvoices"
|
||||
/>
|
||||
</template>
|
||||
</VDataTableServer>
|
||||
<!-- !SECTION -->
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
#invoice-list {
|
||||
.invoice-list-actions {
|
||||
inline-size: 8rem;
|
||||
}
|
||||
|
||||
.invoice-list-filter {
|
||||
inline-size: 12rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
348
resources/js/views/dashboards/ecommerce/EcommerceOrder.vue
Normal file
348
resources/js/views/dashboards/ecommerce/EcommerceOrder.vue
Normal file
@@ -0,0 +1,348 @@
|
||||
<script setup>
|
||||
const currentTab = ref('New')
|
||||
|
||||
const tabsData = [
|
||||
'New',
|
||||
'Preparing',
|
||||
'Shipping',
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard class="country-order-card">
|
||||
<VCardItem
|
||||
title="Orders by countries"
|
||||
subtitle="62 deliveries in progress"
|
||||
class="pb-4"
|
||||
>
|
||||
<template #append>
|
||||
<MoreBtn size="small" />
|
||||
</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="tabler-circle-check"
|
||||
dot-color="rgba(var(--v-theme-surface))"
|
||||
icon-color="success"
|
||||
fill-dot
|
||||
size="20"
|
||||
:elevation="0"
|
||||
>
|
||||
<div class="text-body-2 text-uppercase text-success">
|
||||
Sender
|
||||
</div>
|
||||
<div class="app-timeline-title">
|
||||
Myrtle Ullrich
|
||||
</div>
|
||||
<div class="app-timeline-text">
|
||||
101 Boulder, California(CA), 95959
|
||||
</div>
|
||||
</VTimelineItem>
|
||||
<VTimelineItem
|
||||
icon="tabler-map-pin"
|
||||
dot-color="rgba(var(--v-theme-surface))"
|
||||
icon-color="primary"
|
||||
fill-dot
|
||||
size="20"
|
||||
:elevation="0"
|
||||
>
|
||||
<div class="text-body-2 text-primary text-uppercase">
|
||||
Receiver
|
||||
</div>
|
||||
<div class="app-timeline-title">
|
||||
Barry Schowalter
|
||||
</div>
|
||||
<div class="app-timeline-text">
|
||||
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="tabler-circle-check"
|
||||
dot-color="rgba(var(--v-theme-surface))"
|
||||
icon-color="success"
|
||||
fill-dot
|
||||
size="20"
|
||||
:elevation="0"
|
||||
>
|
||||
<div class="text-body-2 text-uppercase text-success">
|
||||
Sender
|
||||
</div>
|
||||
<div class="app-timeline-title">
|
||||
Veronica Herman
|
||||
</div>
|
||||
<div class="app-timeline-text">
|
||||
162 Windsor, California(CA), 95492
|
||||
</div>
|
||||
</VTimelineItem>
|
||||
|
||||
<VTimelineItem
|
||||
icon="tabler-map-pin"
|
||||
dot-color="rgba(var(--v-theme-surface))"
|
||||
icon-color="primary"
|
||||
fill-dot
|
||||
size="20"
|
||||
:elevation="0"
|
||||
>
|
||||
<div class="text-body-2 text-primary text-uppercase">
|
||||
Receiver
|
||||
</div>
|
||||
<div class="app-timeline-title">
|
||||
Helen Jacobs
|
||||
</div>
|
||||
<div class="app-timeline-text">
|
||||
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="tabler-circle-check"
|
||||
dot-color="rgba(var(--v-theme-surface))"
|
||||
icon-color="success"
|
||||
fill-dot
|
||||
size="20"
|
||||
:elevation="0"
|
||||
>
|
||||
<div class="text-body-2 text-uppercase text-success">
|
||||
Sender
|
||||
</div>
|
||||
<div class="app-timeline-title">
|
||||
Myrtle Ullrich
|
||||
</div>
|
||||
<div class="app-timeline-text">
|
||||
101 Boulder, California(CA), 95959
|
||||
</div>
|
||||
</VTimelineItem>
|
||||
<VTimelineItem
|
||||
icon="tabler-map-pin"
|
||||
dot-color="rgba(var(--v-theme-surface))"
|
||||
icon-color="primary"
|
||||
fill-dot
|
||||
size="20"
|
||||
:elevation="0"
|
||||
>
|
||||
<div class="text-body-2 text-primary text-uppercase">
|
||||
Receiver
|
||||
</div>
|
||||
<div class="app-timeline-title">
|
||||
Barry Schowalter
|
||||
</div>
|
||||
<div class="app-timeline-text">
|
||||
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="tabler-circle-check"
|
||||
dot-color="rgba(var(--v-theme-surface))"
|
||||
icon-color="success"
|
||||
fill-dot
|
||||
size="20"
|
||||
:elevation="0"
|
||||
>
|
||||
<div class="text-body-2 text-uppercase text-success">
|
||||
Sender
|
||||
</div>
|
||||
<div class="app-timeline-title">
|
||||
Veronica Herman
|
||||
</div>
|
||||
<div class="app-timeline-text">
|
||||
162 Windsor, California(CA), 95492
|
||||
</div>
|
||||
</VTimelineItem>
|
||||
|
||||
<VTimelineItem
|
||||
icon="tabler-map-pin"
|
||||
dot-color="rgba(var(--v-theme-surface))"
|
||||
icon-color="primary"
|
||||
fill-dot
|
||||
size="20"
|
||||
:elevation="0"
|
||||
>
|
||||
<div class="text-body-2 text-primary text-uppercase">
|
||||
Receiver
|
||||
</div>
|
||||
<div class="app-timeline-title">
|
||||
Helen Jacobs
|
||||
</div>
|
||||
<div class="app-timeline-text">
|
||||
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="tabler-circle-check"
|
||||
dot-color="rgba(var(--v-theme-surface))"
|
||||
icon-color="success"
|
||||
fill-dot
|
||||
size="20"
|
||||
:elevation="0"
|
||||
>
|
||||
<div class="text-body-2 text-uppercase text-success">
|
||||
Sender
|
||||
</div>
|
||||
<div class="app-timeline-title">
|
||||
Myrtle Ullrich
|
||||
</div>
|
||||
<div class="app-timeline-text">
|
||||
101 Boulder, California(CA), 95959
|
||||
</div>
|
||||
</VTimelineItem>
|
||||
<VTimelineItem
|
||||
icon="tabler-map-pin"
|
||||
dot-color="rgba(var(--v-theme-surface))"
|
||||
icon-color="primary"
|
||||
fill-dot
|
||||
size="20"
|
||||
:elevation="0"
|
||||
>
|
||||
<div class="text-body-2 text-primary text-uppercase">
|
||||
Receiver
|
||||
</div>
|
||||
<div class="app-timeline-title">
|
||||
Barry Schowalter
|
||||
</div>
|
||||
<div class="app-timeline-text">
|
||||
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="tabler-circle-check"
|
||||
dot-color="rgba(var(--v-theme-surface))"
|
||||
icon-color="success"
|
||||
fill-dot
|
||||
size="20"
|
||||
:elevation="0"
|
||||
>
|
||||
<div class="text-body-2 text-uppercase text-success">
|
||||
Sender
|
||||
</div>
|
||||
<div class="app-timeline-title">
|
||||
Veronica Herman
|
||||
</div>
|
||||
<div class="app-timeline-text">
|
||||
162 Windsor, California(CA), 95492
|
||||
</div>
|
||||
</VTimelineItem>
|
||||
|
||||
<VTimelineItem
|
||||
icon="tabler-map-pin"
|
||||
dot-color="rgba(var(--v-theme-surface))"
|
||||
icon-color="primary"
|
||||
fill-dot
|
||||
size="20"
|
||||
:elevation="0"
|
||||
>
|
||||
<div class="text-body-2 text-primary text-uppercase">
|
||||
Receiver
|
||||
</div>
|
||||
<div class="app-timeline-title">
|
||||
Helen Jacobs
|
||||
</div>
|
||||
<div class="app-timeline-text">
|
||||
487 Sunset, California(CA), 94043
|
||||
</div>
|
||||
</VTimelineItem>
|
||||
</VTimeline>
|
||||
</div>
|
||||
</VWindowItem>
|
||||
</VWindow>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.country-order-card {
|
||||
.v-timeline .v-timeline-divider__dot .v-timeline-divider__inner-dot {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,115 @@
|
||||
<script setup>
|
||||
import amazonEchoDot from '@images/eCommerce/amazon-echo-dot.png'
|
||||
import appleWatch from '@images/eCommerce/apple-watch.png'
|
||||
import headphone from '@images/eCommerce/headphone.png'
|
||||
import iphone from '@images/eCommerce/iphone.png'
|
||||
import nike from '@images/eCommerce/nike.png'
|
||||
import sonyDualsense from '@images/eCommerce/sony-dualsense.png'
|
||||
|
||||
const popularProducts = [
|
||||
{
|
||||
avatarImg: iphone,
|
||||
title: 'Apple iPhone 13',
|
||||
subtitle: 'Item: #FXZ-4567',
|
||||
stats: '$999.29',
|
||||
},
|
||||
{
|
||||
avatarImg: nike,
|
||||
title: 'Nike Air Jordan',
|
||||
subtitle: 'Item: #FXZ-3456',
|
||||
stats: '$72.40',
|
||||
},
|
||||
{
|
||||
avatarImg: headphone,
|
||||
title: 'Beats Studio 2',
|
||||
subtitle: 'Item: #FXZ-9485',
|
||||
stats: '$99',
|
||||
},
|
||||
{
|
||||
avatarImg: appleWatch,
|
||||
title: 'Apple Watch Series 7',
|
||||
subtitle: 'Item: #FXZ-2345',
|
||||
stats: '$249.99',
|
||||
},
|
||||
{
|
||||
avatarImg: amazonEchoDot,
|
||||
title: 'Amazon Echo Dot',
|
||||
subtitle: 'Item: #FXZ-8959',
|
||||
stats: '$79.40',
|
||||
},
|
||||
{
|
||||
avatarImg: sonyDualsense,
|
||||
title: 'Play Station Console',
|
||||
subtitle: 'Item: #FXZ-7892',
|
||||
stats: '$129.48',
|
||||
},
|
||||
]
|
||||
|
||||
const moreList = [
|
||||
{
|
||||
title: 'Refresh',
|
||||
value: 'refresh',
|
||||
},
|
||||
{
|
||||
title: 'Download',
|
||||
value: 'Download',
|
||||
},
|
||||
{
|
||||
title: 'View All',
|
||||
value: 'View All',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard
|
||||
title="Popular Products"
|
||||
subtitle="Total 10.4k Visitors"
|
||||
>
|
||||
<template #append>
|
||||
<div class="mt-n4 me-n2">
|
||||
<MoreBtn
|
||||
size="small"
|
||||
:menu-list="moreList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<VCardText>
|
||||
<VList class="card-list">
|
||||
<VListItem
|
||||
v-for="product in popularProducts"
|
||||
:key="product.title"
|
||||
>
|
||||
<template #prepend>
|
||||
<VAvatar
|
||||
size="46"
|
||||
rounded
|
||||
class="me-1"
|
||||
:image="product.avatarImg"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<VListItemTitle class="font-weight-medium me-4">
|
||||
{{ product.title }}
|
||||
</VListItemTitle>
|
||||
<VListItemSubtitle class="me-4">
|
||||
{{ product.subtitle }}
|
||||
</VListItemSubtitle>
|
||||
|
||||
<template #append>
|
||||
<div class="d-flex align-center">
|
||||
<span class="text-body-1">{{ product.stats }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card-list {
|
||||
--v-card-list-gap: 1.25rem;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,448 @@
|
||||
<script setup>
|
||||
import { useTheme } from 'vuetify'
|
||||
import { hexToRgb } from '@layouts/utils'
|
||||
|
||||
const vuetifyTheme = useTheme()
|
||||
|
||||
const series = {
|
||||
bar: [
|
||||
{
|
||||
name: 'Earning',
|
||||
data: [
|
||||
270,
|
||||
210,
|
||||
180,
|
||||
200,
|
||||
250,
|
||||
280,
|
||||
250,
|
||||
270,
|
||||
150,
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Expense',
|
||||
data: [
|
||||
-140,
|
||||
-160,
|
||||
-180,
|
||||
-150,
|
||||
-100,
|
||||
-60,
|
||||
-80,
|
||||
-100,
|
||||
-180,
|
||||
],
|
||||
},
|
||||
],
|
||||
line: [
|
||||
{
|
||||
name: 'Last Month',
|
||||
data: [
|
||||
20,
|
||||
10,
|
||||
30,
|
||||
16,
|
||||
24,
|
||||
5,
|
||||
40,
|
||||
23,
|
||||
28,
|
||||
5,
|
||||
30,
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'This Month',
|
||||
data: [
|
||||
50,
|
||||
40,
|
||||
60,
|
||||
46,
|
||||
54,
|
||||
35,
|
||||
70,
|
||||
53,
|
||||
58,
|
||||
35,
|
||||
60,
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const chartOptions = computed(() => {
|
||||
const currentTheme = vuetifyTheme.current.value.colors
|
||||
const variableTheme = vuetifyTheme.current.value.variables
|
||||
const labelColor = `rgba(${ hexToRgb(currentTheme['on-surface']) },${ variableTheme['disabled-opacity'] })`
|
||||
const legendColor = `rgba(${ hexToRgb(currentTheme['on-background']) },${ variableTheme['high-emphasis-opacity'] })`
|
||||
const borderColor = `rgba(${ hexToRgb(String(variableTheme['border-color'])) },${ variableTheme['border-opacity'] })`
|
||||
|
||||
return {
|
||||
bar: {
|
||||
chart: {
|
||||
parentHeightOffset: 0,
|
||||
stacked: true,
|
||||
type: 'bar',
|
||||
toolbar: { show: false },
|
||||
},
|
||||
tooltip: { enabled: false },
|
||||
plotOptions: {
|
||||
bar: {
|
||||
horizontal: false,
|
||||
columnWidth: '40%',
|
||||
borderRadius: 8,
|
||||
borderRadiusApplication: 'around',
|
||||
borderRadiusWhenStacked: 'all',
|
||||
},
|
||||
},
|
||||
colors: [
|
||||
'rgba(var(--v-theme-primary),1)',
|
||||
'rgba(var(--v-theme-warning),1)',
|
||||
],
|
||||
dataLabels: { enabled: false },
|
||||
stroke: {
|
||||
curve: 'smooth',
|
||||
width: 6,
|
||||
lineCap: 'round',
|
||||
colors: [currentTheme.surface],
|
||||
},
|
||||
legend: {
|
||||
show: true,
|
||||
horizontalAlign: 'right',
|
||||
position: 'top',
|
||||
fontFamily: 'Public Sans',
|
||||
fontSize: '13px',
|
||||
markers: {
|
||||
height: 12,
|
||||
width: 12,
|
||||
radius: 12,
|
||||
offsetX: -3,
|
||||
offsetY: 2,
|
||||
},
|
||||
labels: { colors: legendColor },
|
||||
itemMargin: { horizontal: 5 },
|
||||
},
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
bottom: -8,
|
||||
top: 20,
|
||||
},
|
||||
},
|
||||
xaxis: {
|
||||
categories: [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
'Apr',
|
||||
'May',
|
||||
'Jun',
|
||||
'Jul',
|
||||
'Aug',
|
||||
'Sep',
|
||||
],
|
||||
labels: {
|
||||
style: {
|
||||
fontSize: '13px',
|
||||
colors: labelColor,
|
||||
fontFamily: 'Public Sans',
|
||||
},
|
||||
},
|
||||
axisTicks: { show: false },
|
||||
axisBorder: { show: false },
|
||||
},
|
||||
yaxis: {
|
||||
labels: {
|
||||
offsetX: -16,
|
||||
style: {
|
||||
fontSize: '13px',
|
||||
colors: labelColor,
|
||||
fontFamily: 'Public Sans',
|
||||
},
|
||||
},
|
||||
min: -200,
|
||||
max: 300,
|
||||
tickAmount: 5,
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 1700,
|
||||
options: { plotOptions: { bar: { columnWidth: '43%' } } },
|
||||
},
|
||||
{
|
||||
breakpoint: 1526,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '52%',
|
||||
borderRadius: 8,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 1359,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '60%',
|
||||
borderRadius: 8,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 1280,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '40%',
|
||||
borderRadius: 10,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 1025,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '40%',
|
||||
borderRadius: 8,
|
||||
},
|
||||
},
|
||||
chart: { height: 390 },
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 991,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '40%',
|
||||
borderRadius: 8,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 850,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '50%',
|
||||
borderRadius: 8,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 776,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '50%',
|
||||
borderRadius: 6,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 731,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '70%',
|
||||
borderRadius: 8,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 599,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '50%',
|
||||
borderRadius: 8,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 500,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '55%',
|
||||
borderRadius: 6,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 449,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '65%',
|
||||
borderRadius: 6,
|
||||
},
|
||||
},
|
||||
chart: { height: 360 },
|
||||
xaxis: { labels: { offsetY: -5 } },
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 394,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '80%',
|
||||
borderRadius: 6,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
states: {
|
||||
hover: { filter: { type: 'none' } },
|
||||
active: { filter: { type: 'none' } },
|
||||
},
|
||||
},
|
||||
line: {
|
||||
chart: {
|
||||
toolbar: { show: false },
|
||||
zoom: { enabled: false },
|
||||
type: 'line',
|
||||
},
|
||||
stroke: {
|
||||
curve: 'smooth',
|
||||
dashArray: [
|
||||
5,
|
||||
0,
|
||||
],
|
||||
width: [
|
||||
1,
|
||||
2,
|
||||
],
|
||||
},
|
||||
legend: { show: false },
|
||||
colors: [
|
||||
borderColor,
|
||||
currentTheme.primary,
|
||||
],
|
||||
grid: {
|
||||
show: false,
|
||||
borderColor,
|
||||
padding: {
|
||||
top: -30,
|
||||
bottom: -15,
|
||||
left: 25,
|
||||
},
|
||||
},
|
||||
markers: { size: 0 },
|
||||
xaxis: {
|
||||
labels: { show: false },
|
||||
axisTicks: { show: false },
|
||||
axisBorder: { show: false },
|
||||
},
|
||||
yaxis: { show: false },
|
||||
tooltip: { enabled: false },
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard class="revenue-report">
|
||||
<VRow no-gutters>
|
||||
<VCol
|
||||
cols="12"
|
||||
sm="8"
|
||||
lg="8"
|
||||
:class="$vuetify.display.smAndUp ? 'border-e' : 'border-b'"
|
||||
>
|
||||
<VCardText>
|
||||
<h6 class="text-h5 mb-sm-n8">
|
||||
Revenue Report
|
||||
</h6>
|
||||
|
||||
<VueApexCharts
|
||||
:options="chartOptions.bar"
|
||||
:series="series.bar"
|
||||
height="365"
|
||||
/>
|
||||
</VCardText>
|
||||
</VCol>
|
||||
|
||||
<VCol
|
||||
cols="12"
|
||||
sm="4"
|
||||
>
|
||||
<VCardText class="d-flex flex-column justify-center align-center text-center h-100">
|
||||
<VBtn
|
||||
variant="tonal"
|
||||
size="small"
|
||||
class="d-flex mx-auto"
|
||||
>
|
||||
<span>2022</span>
|
||||
<template #append>
|
||||
<VIcon
|
||||
size="16"
|
||||
icon="tabler-chevron-down"
|
||||
/>
|
||||
</template>
|
||||
<VMenu activator="parent">
|
||||
<VList>
|
||||
<VListItem
|
||||
v-for="(item, index) in ['2021', '2020', '2019']"
|
||||
:key="index"
|
||||
:value="index"
|
||||
>
|
||||
<VListItemTitle>{{ item }}</VListItemTitle>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VMenu>
|
||||
</VBtn>
|
||||
|
||||
<div class="d-flex flex-column my-8">
|
||||
<h5 class="font-weight-medium text-h3">
|
||||
$25,825
|
||||
</h5>
|
||||
<p class="mb-0">
|
||||
<span class="text-high-emphasis font-weight-medium me-1">Budget:</span>
|
||||
<span>56,800</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<VueApexCharts
|
||||
:options="chartOptions.line"
|
||||
:series="series.line"
|
||||
height="100"
|
||||
/>
|
||||
|
||||
<VBtn class="mt-8">
|
||||
Increase Budget
|
||||
</VBtn>
|
||||
</VCardText>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.revenue-report {
|
||||
.apexcharts-legend {
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
@media (max-width: 599px) {
|
||||
.apexcharts-legend.apx-legend-position-top.apexcharts-align-right {
|
||||
justify-content: flex-start;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,67 @@
|
||||
<script setup>
|
||||
const statistics = [
|
||||
{
|
||||
title: 'Sales',
|
||||
stats: '230k',
|
||||
icon: 'tabler-chart-pie-2',
|
||||
color: 'primary',
|
||||
},
|
||||
{
|
||||
title: 'Customers',
|
||||
stats: '8.549k',
|
||||
icon: 'tabler-users',
|
||||
color: 'info',
|
||||
},
|
||||
{
|
||||
title: 'Products',
|
||||
stats: '1.423k',
|
||||
icon: 'tabler-shopping-cart',
|
||||
color: 'error',
|
||||
},
|
||||
{
|
||||
title: 'Revenue',
|
||||
stats: '$9745',
|
||||
icon: 'tabler-currency-dollar',
|
||||
color: 'success',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard title="Statistics">
|
||||
<template #append>
|
||||
<span class="text-sm text-disabled">Updated 1 month ago</span>
|
||||
</template>
|
||||
|
||||
<VCardText>
|
||||
<VRow>
|
||||
<VCol
|
||||
v-for="item in statistics"
|
||||
:key="item.title"
|
||||
cols="6"
|
||||
md="3"
|
||||
>
|
||||
<div class="d-flex align-center gap-4 mt-md-9 mt-0">
|
||||
<VAvatar
|
||||
:color="item.color"
|
||||
variant="tonal"
|
||||
rounded
|
||||
size="40"
|
||||
>
|
||||
<VIcon :icon="item.icon" />
|
||||
</VAvatar>
|
||||
|
||||
<div class="d-flex flex-column">
|
||||
<h5 class="text-h5">
|
||||
{{ item.stats }}
|
||||
</h5>
|
||||
<div class="text-sm">
|
||||
{{ item.title }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
@@ -0,0 +1,106 @@
|
||||
<script setup>
|
||||
import { useTheme } from 'vuetify'
|
||||
import { hexToRgb } from '@layouts/utils'
|
||||
|
||||
const vuetifyTheme = useTheme()
|
||||
|
||||
const series = [{
|
||||
data: [
|
||||
0,
|
||||
25,
|
||||
10,
|
||||
40,
|
||||
25,
|
||||
55,
|
||||
],
|
||||
}]
|
||||
|
||||
const chartOptions = computed(() => {
|
||||
const currentTheme = vuetifyTheme.current.value.colors
|
||||
const variableTheme = vuetifyTheme.current.value.variables
|
||||
|
||||
return {
|
||||
chart: {
|
||||
height: 90,
|
||||
type: 'line',
|
||||
parentHeightOffset: 0,
|
||||
toolbar: { show: false },
|
||||
},
|
||||
grid: {
|
||||
borderColor: `rgba(${ hexToRgb(String(variableTheme['border-color'])) },${ variableTheme['border-opacity'] })`,
|
||||
strokeDashArray: 6,
|
||||
xaxis: { lines: { show: true } },
|
||||
yaxis: { lines: { show: false } },
|
||||
padding: {
|
||||
top: -18,
|
||||
left: -4,
|
||||
right: 7,
|
||||
bottom: -10,
|
||||
},
|
||||
},
|
||||
colors: [currentTheme.info],
|
||||
stroke: { width: 2 },
|
||||
tooltip: {
|
||||
enabled: false,
|
||||
shared: false,
|
||||
intersect: true,
|
||||
x: { show: false },
|
||||
},
|
||||
xaxis: {
|
||||
labels: { show: false },
|
||||
axisTicks: { show: false },
|
||||
axisBorder: { show: false },
|
||||
},
|
||||
yaxis: { labels: { show: false } },
|
||||
markers: {
|
||||
size: 3.5,
|
||||
fillColor: currentTheme.info,
|
||||
strokeColors: 'transparent',
|
||||
strokeWidth: 3.2,
|
||||
discrete: [{
|
||||
seriesIndex: 0,
|
||||
dataPointIndex: 5,
|
||||
fillColor: currentTheme.surface,
|
||||
strokeColor: currentTheme.info,
|
||||
size: 5,
|
||||
shape: 'circle',
|
||||
}],
|
||||
hover: { size: 5.5 },
|
||||
},
|
||||
responsive: [{
|
||||
breakpoint: 960,
|
||||
options: { chart: { height: 110 } },
|
||||
}],
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardItem class="pb-3">
|
||||
<VCardTitle>
|
||||
Profit
|
||||
</VCardTitle>
|
||||
<VCardSubtitle>
|
||||
Last Month
|
||||
</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<VueApexCharts
|
||||
type="line"
|
||||
:options="chartOptions"
|
||||
:series="series"
|
||||
:height="68"
|
||||
/>
|
||||
|
||||
<div class="d-flex align-center justify-space-between gap-x-2 mt-3">
|
||||
<h4 class="text-h4 text-center font-weight-medium">
|
||||
624k
|
||||
</h4>
|
||||
<span class="text-sm text-success">
|
||||
+8.24%
|
||||
</span>
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
@@ -0,0 +1,134 @@
|
||||
<script setup>
|
||||
const transitions = [
|
||||
{
|
||||
avatarIcon: 'tabler-wallet',
|
||||
avatarColor: 'primary',
|
||||
title: 'Wallet',
|
||||
subtitle: 'Starbucks',
|
||||
stats: '-$75',
|
||||
profit: false,
|
||||
},
|
||||
{
|
||||
avatarIcon: 'tabler-building-bank',
|
||||
avatarColor: 'success',
|
||||
title: 'Bank Transfer',
|
||||
subtitle: 'Add Money',
|
||||
stats: '+$480',
|
||||
profit: true,
|
||||
},
|
||||
{
|
||||
avatarIcon: 'tabler-brand-paypal',
|
||||
avatarColor: 'error',
|
||||
title: 'PayPal',
|
||||
subtitle: 'Client Payment',
|
||||
stats: '+$268',
|
||||
profit: true,
|
||||
},
|
||||
{
|
||||
avatarIcon: 'tabler-credit-card',
|
||||
avatarColor: 'secondary',
|
||||
title: 'Master Card',
|
||||
subtitle: 'Ordered iPhone 13',
|
||||
stats: '-$699',
|
||||
profit: false,
|
||||
},
|
||||
{
|
||||
avatarIcon: 'tabler-currency-dollar',
|
||||
avatarColor: 'info',
|
||||
title: 'Bank Transactions',
|
||||
subtitle: 'Refund',
|
||||
stats: '+$98',
|
||||
profit: true,
|
||||
},
|
||||
{
|
||||
avatarIcon: 'tabler-brand-paypal',
|
||||
avatarColor: 'error',
|
||||
title: 'PayPal',
|
||||
subtitle: 'Client Payment',
|
||||
stats: '+$126',
|
||||
profit: true,
|
||||
},
|
||||
{
|
||||
avatarIcon: 'tabler-building-bank',
|
||||
avatarColor: 'success',
|
||||
title: 'Bank Transfer',
|
||||
subtitle: 'Pay Office Rent',
|
||||
stats: '-$1290',
|
||||
profit: false,
|
||||
},
|
||||
]
|
||||
|
||||
const moreList = [
|
||||
{
|
||||
title: 'Refresh',
|
||||
value: 'refresh',
|
||||
},
|
||||
{
|
||||
title: 'Download',
|
||||
value: 'Download',
|
||||
},
|
||||
{
|
||||
title: 'View All',
|
||||
value: 'View All',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard
|
||||
title="Transactions"
|
||||
subtitle="Total 58 Transactions done in this Month"
|
||||
>
|
||||
<template #append>
|
||||
<div class="mt-n4 me-n2">
|
||||
<MoreBtn
|
||||
size="small"
|
||||
:menu-list="moreList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<VCardText>
|
||||
<VList class="card-list">
|
||||
<VListItem
|
||||
v-for="transition in transitions"
|
||||
:key="transition.title"
|
||||
>
|
||||
<template #prepend>
|
||||
<VAvatar
|
||||
size="34"
|
||||
:color="transition.avatarColor"
|
||||
variant="tonal"
|
||||
class="me-1"
|
||||
rounded
|
||||
>
|
||||
<VIcon
|
||||
:icon="transition.avatarIcon"
|
||||
size="22"
|
||||
/>
|
||||
</VAvatar>
|
||||
</template>
|
||||
|
||||
<VListItemTitle>
|
||||
{{ transition.title }}
|
||||
</VListItemTitle>
|
||||
<VListItemSubtitle>
|
||||
{{ transition.subtitle }}
|
||||
</VListItemSubtitle>
|
||||
|
||||
<template #append>
|
||||
<div class="d-flex align-center">
|
||||
<span :class="`${transition.profit ? 'text-success' : 'text-error'} font-weight-medium`">{{ transition.stats }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card-list {
|
||||
--v-card-list-gap: 16px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user