- 웹훅 URL을 https://admin.youtooplay.com/webhook로 변경 - Nginx 리버스 프록시 설정 파일 추가 - 배포 가이드 업데이트
This commit is contained in:
63
views/dashboard/AnalyticsCongratulations.vue
Normal file
63
views/dashboard/AnalyticsCongratulations.vue
Normal file
@@ -0,0 +1,63 @@
|
||||
<script setup lang="ts">
|
||||
import { useTheme } from 'vuetify'
|
||||
import illustrationJohnDark from '@images/cards/illustration-john-dark.png'
|
||||
import illustrationJohnLight from '@images/cards/illustration-john-light.png'
|
||||
|
||||
const { global } = useTheme()
|
||||
const illustrationJohn = computed(() => global.name.value === 'dark' ? illustrationJohnDark : illustrationJohnLight)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard class="text-center text-sm-start">
|
||||
<VRow no-gutters>
|
||||
<VCol
|
||||
cols="12"
|
||||
sm="8"
|
||||
order="2"
|
||||
order-sm="1"
|
||||
>
|
||||
<VCardItem class="pb-3">
|
||||
<VCardTitle class="text-primary">
|
||||
Congratulations John! 🎉
|
||||
</VCardTitle>
|
||||
</VCardItem>
|
||||
|
||||
<VCardText>
|
||||
You have done 72% more sales today.
|
||||
<br>
|
||||
Check your new raising badge in your profile.
|
||||
<br>
|
||||
<VBtn
|
||||
variant="tonal"
|
||||
class="mt-6"
|
||||
size="small"
|
||||
>
|
||||
View Badges
|
||||
</VBtn>
|
||||
</VCardText>
|
||||
</VCol>
|
||||
|
||||
<VCol
|
||||
cols="12"
|
||||
sm="4"
|
||||
order="1"
|
||||
order-sm="2"
|
||||
class="text-center"
|
||||
>
|
||||
<img
|
||||
:src="illustrationJohn"
|
||||
:height="$vuetify.display.xs ? '150' : '182'"
|
||||
:class="$vuetify.display.xs ? 'mt-6 mb-n2' : 'position-absolute'"
|
||||
class="john-illustration flip-in-rtl"
|
||||
>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.john-illustration {
|
||||
inset-block-end: -0.125rem;
|
||||
inset-inline-end: 3.5rem;
|
||||
}
|
||||
</style>
|
||||
240
views/dashboard/AnalyticsFinanceTab.vue
Normal file
240
views/dashboard/AnalyticsFinanceTab.vue
Normal file
@@ -0,0 +1,240 @@
|
||||
<script setup lang="ts">
|
||||
import { useTheme } from 'vuetify'
|
||||
import statsVerticalChart from '@images/cards/chart-success.png'
|
||||
import statsVerticalPaypal from '@images/cards/paypal-error.png'
|
||||
import statsVerticalWallet from '@images/cards/wallet-primary.png'
|
||||
|
||||
import { hexToRgb } from '@layouts/utils'
|
||||
|
||||
const vuetifyTheme = useTheme()
|
||||
|
||||
interface statistics {
|
||||
avatar: string
|
||||
title: string
|
||||
stats: string
|
||||
profitLoss: number
|
||||
profitLossAmount: string
|
||||
compareToLastWeek: string
|
||||
}
|
||||
|
||||
interface TabsData {
|
||||
income: statistics
|
||||
expenses: statistics
|
||||
profit: statistics
|
||||
}
|
||||
|
||||
const series = {
|
||||
income: [{ data: [24, 21, 30, 22, 42, 26, 35, 29] }],
|
||||
expenses: [{ data: [24, 21, 30, 25, 42, 26, 35, 29] }],
|
||||
profit: [{ data: [24, 21, 30, 22, 42, 26, 35, 35] }],
|
||||
}
|
||||
|
||||
const currentTab = ref <keyof TabsData> ('income')
|
||||
|
||||
const tabData = computed(() => {
|
||||
const data: TabsData = {
|
||||
income: {
|
||||
avatar: statsVerticalWallet,
|
||||
title: 'Total Income',
|
||||
stats: '$459.1k',
|
||||
profitLoss: 65,
|
||||
profitLossAmount: '6.5',
|
||||
compareToLastWeek: '$39k',
|
||||
|
||||
},
|
||||
expenses: {
|
||||
avatar: statsVerticalPaypal,
|
||||
title: 'Total Expenses',
|
||||
stats: '$316.5k',
|
||||
profitLoss: 27.8,
|
||||
profitLossAmount: '7.2',
|
||||
compareToLastWeek: '$16k',
|
||||
},
|
||||
profit: {
|
||||
avatar: statsVerticalChart,
|
||||
title: 'Total Profit',
|
||||
stats: '$147.9k',
|
||||
profitLoss: 35.1,
|
||||
profitLossAmount: '4.5',
|
||||
compareToLastWeek: '$28k',
|
||||
},
|
||||
}
|
||||
|
||||
return data[currentTab.value]
|
||||
})
|
||||
|
||||
const chartConfig = computed(() => {
|
||||
const currentTheme = vuetifyTheme.current.value.colors
|
||||
const variableTheme = vuetifyTheme.current.value.variables
|
||||
|
||||
const disabledTextColor = `rgba(${hexToRgb(String(currentTheme['on-surface']))},${variableTheme['disabled-opacity']})`
|
||||
const borderColor = `rgba(${hexToRgb(String(variableTheme['border-color']))},${variableTheme['border-opacity']})`
|
||||
|
||||
return {
|
||||
chart: {
|
||||
parentHeightOffset: 0,
|
||||
toolbar: { show: false },
|
||||
},
|
||||
dataLabels: { enabled: false },
|
||||
stroke: {
|
||||
width: 3,
|
||||
curve: 'smooth',
|
||||
},
|
||||
grid: {
|
||||
strokeDashArray: 4.5,
|
||||
borderColor,
|
||||
padding: {
|
||||
left: 0,
|
||||
top: -20,
|
||||
right: 11,
|
||||
bottom: 7,
|
||||
},
|
||||
},
|
||||
fill: {
|
||||
type: 'gradient',
|
||||
gradient: {
|
||||
opacityTo: 0.25,
|
||||
opacityFrom: 0.5,
|
||||
stops: [0, 95, 100],
|
||||
shadeIntensity: 0.6,
|
||||
colorStops: [
|
||||
[
|
||||
{
|
||||
offset: 0,
|
||||
opacity: 0.4,
|
||||
color: currentTheme.primary,
|
||||
},
|
||||
{
|
||||
offset: 100,
|
||||
opacity: 0.2,
|
||||
color: currentTheme.surface,
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
theme: {
|
||||
monochrome: {
|
||||
enabled: true,
|
||||
shadeTo: 'light',
|
||||
shadeIntensity: 1,
|
||||
color: currentTheme.primary,
|
||||
},
|
||||
},
|
||||
xaxis: {
|
||||
axisTicks: { show: false },
|
||||
axisBorder: { show: false },
|
||||
categories: ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'],
|
||||
offsetY: 20,
|
||||
offsetX: -24,
|
||||
labels: {
|
||||
style: {
|
||||
fontSize: '14px',
|
||||
colors: disabledTextColor,
|
||||
fontFamily: 'Public Sans',
|
||||
},
|
||||
},
|
||||
},
|
||||
yaxis: {
|
||||
min: 10,
|
||||
max: 50,
|
||||
show: false,
|
||||
tickAmount: 4,
|
||||
},
|
||||
markers: {
|
||||
size: 8,
|
||||
strokeWidth: 6,
|
||||
strokeOpacity: 1,
|
||||
offsetX: -10,
|
||||
hover: { size: 8 },
|
||||
colors: ['transparent'],
|
||||
strokeColors: 'transparent',
|
||||
discrete: [
|
||||
{
|
||||
size: 8,
|
||||
seriesIndex: 0,
|
||||
fillColor: '#fff',
|
||||
strokeColor: currentTheme.primary,
|
||||
dataPointIndex: series[currentTab.value][0].data.length - 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardText>
|
||||
<VTabs
|
||||
v-model="currentTab"
|
||||
class="v-tabs-pill"
|
||||
>
|
||||
<VTab value="income">
|
||||
Income
|
||||
</VTab>
|
||||
<VTab value="expenses">
|
||||
Expenses
|
||||
</VTab>
|
||||
<VTab value="profit">
|
||||
Profit
|
||||
</VTab>
|
||||
</VTabs>
|
||||
</VCardText>
|
||||
|
||||
<VCardText class="d-flex align-center gap-3">
|
||||
<VAvatar
|
||||
size="48"
|
||||
rounded
|
||||
:image="tabData.avatar"
|
||||
/>
|
||||
|
||||
<div>
|
||||
<p class="mb-0">
|
||||
{{ tabData.title }}
|
||||
</p>
|
||||
<div class="d-flex align-center gap-2">
|
||||
<h6 class="text-h6">
|
||||
{{ tabData.stats }}
|
||||
</h6>
|
||||
<span
|
||||
class="text-sm"
|
||||
:class="tabData.profitLoss > 0 ? 'text-success' : 'text-error'"
|
||||
>
|
||||
<VIcon
|
||||
size="24"
|
||||
icon="bx-chevron-up"
|
||||
/>
|
||||
{{ tabData.profitLoss }}%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</VCardText>
|
||||
|
||||
<VCardText>
|
||||
<VueApexCharts
|
||||
type="area"
|
||||
:height="230"
|
||||
:options="chartConfig"
|
||||
:series="series[currentTab]"
|
||||
/>
|
||||
</VCardText>
|
||||
|
||||
<VCardText class="d-flex align-center justify-center pt-2 gap-4">
|
||||
<VProgressCircular
|
||||
size="45"
|
||||
color="primary"
|
||||
:model-value="tabData.profitLoss"
|
||||
>
|
||||
<span class="text-overline text-medium-emphasis">${{ tabData.profitLossAmount }}</span>
|
||||
</VProgressCircular>
|
||||
|
||||
<div>
|
||||
<h6 class="text-base font-weight-regular">
|
||||
<span class="text-capitalize d-inline-block">{{ currentTab }} this week</span>
|
||||
</h6>
|
||||
<span class="text-sm d-inline-block">{{ tabData.compareToLastWeek }} less than last week</span>
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
108
views/dashboard/AnalyticsOrder.vue
Normal file
108
views/dashboard/AnalyticsOrder.vue
Normal file
@@ -0,0 +1,108 @@
|
||||
<script setup lang="ts">
|
||||
import { useTheme } from 'vuetify'
|
||||
|
||||
const vuetifyTheme = useTheme()
|
||||
|
||||
const series = [{ data: [30, 70, 35, 55, 45, 70] }]
|
||||
|
||||
const chartOptions = computed(() => {
|
||||
const currentTheme = vuetifyTheme.current.value.colors
|
||||
|
||||
return {
|
||||
chart: {
|
||||
parentHeightOffset: 0,
|
||||
toolbar: { show: false },
|
||||
},
|
||||
tooltip: { enabled: false },
|
||||
dataLabels: { enabled: false },
|
||||
stroke: {
|
||||
width: 2,
|
||||
curve: 'smooth',
|
||||
lineCap: 'round',
|
||||
},
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
left: 0,
|
||||
top: -32,
|
||||
right: 17,
|
||||
},
|
||||
},
|
||||
fill: {
|
||||
type: 'gradient',
|
||||
gradient: {
|
||||
opacityTo: 0.7,
|
||||
opacityFrom: 0.5,
|
||||
shadeIntensity: 1,
|
||||
stops: [0, 90, 100],
|
||||
colorStops: [
|
||||
[
|
||||
{
|
||||
offset: 0,
|
||||
opacity: 0.6,
|
||||
color: currentTheme.success,
|
||||
},
|
||||
{
|
||||
offset: 100,
|
||||
opacity: 0.1,
|
||||
color: currentTheme.surface,
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
theme: {
|
||||
monochrome: {
|
||||
enabled: true,
|
||||
shadeTo: 'light',
|
||||
shadeIntensity: 1,
|
||||
color: currentTheme.success,
|
||||
},
|
||||
},
|
||||
xaxis: {
|
||||
labels: { show: false },
|
||||
axisTicks: { show: false },
|
||||
axisBorder: { show: false },
|
||||
},
|
||||
yaxis: { show: false },
|
||||
markers: {
|
||||
size: 1,
|
||||
offsetY: 2,
|
||||
offsetX: -5,
|
||||
strokeWidth: 3,
|
||||
strokeOpacity: 1,
|
||||
colors: ['transparent'],
|
||||
strokeColors: 'transparent',
|
||||
discrete: [
|
||||
{
|
||||
size: 6,
|
||||
seriesIndex: 0,
|
||||
fillColor: '#fff',
|
||||
strokeColor: currentTheme.success,
|
||||
dataPointIndex: series[0].data.length - 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardText class="pb-4">
|
||||
<div class="text-base">
|
||||
Order
|
||||
</div>
|
||||
<h4 class="text-h4">
|
||||
276k
|
||||
</h4>
|
||||
</VCardText>
|
||||
|
||||
<VueApexCharts
|
||||
type="area"
|
||||
:height="104"
|
||||
:options="chartOptions"
|
||||
:series="series"
|
||||
/>
|
||||
</VCard>
|
||||
</template>
|
||||
194
views/dashboard/AnalyticsOrderStatistics.vue
Normal file
194
views/dashboard/AnalyticsOrderStatistics.vue
Normal file
@@ -0,0 +1,194 @@
|
||||
<script setup lang="ts">
|
||||
import { useTheme } from 'vuetify'
|
||||
import { hexToRgb } from '@core/utils/colorConverter'
|
||||
|
||||
const vuetifyTheme = useTheme()
|
||||
|
||||
const series = [45, 80, 20, 40]
|
||||
|
||||
const chartOptions = computed(() => {
|
||||
const currentTheme = vuetifyTheme.current.value.colors
|
||||
const variableTheme = vuetifyTheme.current.value.variables
|
||||
|
||||
const secondaryTextColor = `rgba(${hexToRgb(String(currentTheme['on-surface']))},${variableTheme['medium-emphasis-opacity']})`
|
||||
const primaryTextColor = `rgba(${hexToRgb(String(currentTheme['on-surface']))},${variableTheme['high-emphasis-opacity']})`
|
||||
|
||||
return {
|
||||
chart: {
|
||||
sparkline: { enabled: true },
|
||||
animations: { enabled: false },
|
||||
},
|
||||
stroke: {
|
||||
width: 6,
|
||||
colors: [currentTheme.surface],
|
||||
},
|
||||
legend: { show: false },
|
||||
tooltip: { enabled: false },
|
||||
dataLabels: { enabled: false },
|
||||
labels: ['Fashion', 'Electronic', 'Sports', 'Decor'],
|
||||
colors: [
|
||||
currentTheme.success,
|
||||
currentTheme.primary,
|
||||
currentTheme.secondary,
|
||||
currentTheme.info,
|
||||
],
|
||||
grid: {
|
||||
padding: {
|
||||
top: -7,
|
||||
bottom: 5,
|
||||
},
|
||||
},
|
||||
states: {
|
||||
hover: {
|
||||
filter: { type: 'none' },
|
||||
},
|
||||
active: {
|
||||
filter: { type: 'none' },
|
||||
},
|
||||
},
|
||||
plotOptions: {
|
||||
pie: {
|
||||
expandOnClick: false,
|
||||
donut: {
|
||||
size: '75%',
|
||||
labels: {
|
||||
show: true,
|
||||
name: {
|
||||
offsetY: 17,
|
||||
fontSize: '13px',
|
||||
color: secondaryTextColor,
|
||||
fontFamily: 'Public Sans',
|
||||
},
|
||||
value: {
|
||||
offsetY: -17,
|
||||
fontSize: '18px',
|
||||
color: primaryTextColor,
|
||||
fontFamily: 'Public Sans',
|
||||
fontWeight: 500,
|
||||
},
|
||||
total: {
|
||||
show: true,
|
||||
label: 'Weekly',
|
||||
fontSize: '13px',
|
||||
lineHeight: '18px',
|
||||
formatter: () => '38%',
|
||||
color: secondaryTextColor,
|
||||
fontFamily: 'Public Sans',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
const orders = [
|
||||
{
|
||||
amount: '82.5k',
|
||||
title: 'Electronic',
|
||||
avatarColor: 'primary',
|
||||
subtitle: 'Mobile, Earbuds, TV',
|
||||
avatarIcon: 'bx-mobile-alt',
|
||||
},
|
||||
{
|
||||
amount: '23.8k',
|
||||
title: 'Fashion',
|
||||
avatarColor: 'success',
|
||||
subtitle: 'Tshirt, Jeans, Shoes',
|
||||
avatarIcon: 'bx-closet',
|
||||
},
|
||||
{
|
||||
amount: 849,
|
||||
title: 'Decor',
|
||||
avatarColor: 'info',
|
||||
subtitle: 'Fine Art, Dining',
|
||||
avatarIcon: 'bx-home',
|
||||
},
|
||||
{
|
||||
amount: 99,
|
||||
title: 'Sports',
|
||||
avatarColor: 'secondary',
|
||||
subtitle: 'Football, Cricket Kit',
|
||||
avatarIcon: 'bx-football',
|
||||
},
|
||||
]
|
||||
|
||||
const moreList = [
|
||||
{ title: 'Share', value: 'Share' },
|
||||
{ title: 'Refresh', value: 'Refresh' },
|
||||
{ title: 'Update', value: 'Update' },
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>
|
||||
Order Statistics
|
||||
</VCardTitle>
|
||||
<VCardSubtitle>42.82k Total Sales</VCardSubtitle>
|
||||
|
||||
<template #append>
|
||||
<MoreBtn :menu-list="moreList" />
|
||||
</template>
|
||||
</VCardItem>
|
||||
|
||||
<VCardText>
|
||||
<div class="d-flex align-center justify-space-between mb-6">
|
||||
<div class="">
|
||||
<h3 class="text-h3 mb-1">
|
||||
8,258
|
||||
</h3>
|
||||
<div class="text-caption text-medium-emphasis">
|
||||
Total Orders
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<VueApexCharts
|
||||
type="donut"
|
||||
:height="120"
|
||||
width="100"
|
||||
:options="chartOptions"
|
||||
:series="series"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<VList class="card-list">
|
||||
<VListItem
|
||||
v-for="order in orders"
|
||||
:key="order.title"
|
||||
>
|
||||
<template #prepend>
|
||||
<VAvatar
|
||||
size="40"
|
||||
rounded
|
||||
variant="tonal"
|
||||
:color="order.avatarColor"
|
||||
>
|
||||
<VIcon :icon="order.avatarIcon" />
|
||||
</VAvatar>
|
||||
</template>
|
||||
|
||||
<VListItemTitle class="font-weight-medium">
|
||||
{{ order.title }}
|
||||
</VListItemTitle>
|
||||
<VListItemSubtitle class="text-body-2">
|
||||
{{ order.subtitle }}
|
||||
</VListItemSubtitle>
|
||||
|
||||
<template #append>
|
||||
<span>{{ order.amount }}</span>
|
||||
</template>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.card-list {
|
||||
--v-card-list-gap: 1.25rem;
|
||||
}
|
||||
</style>
|
||||
115
views/dashboard/AnalyticsProfitReport.vue
Normal file
115
views/dashboard/AnalyticsProfitReport.vue
Normal file
@@ -0,0 +1,115 @@
|
||||
<script setup lang="ts">
|
||||
import { useDisplay, useTheme } from 'vuetify'
|
||||
import { hexToRgb } from '@core/utils/colorConverter'
|
||||
|
||||
const vuetifyTheme = useTheme()
|
||||
const display = useDisplay()
|
||||
|
||||
const series = [{ data: [30, 58, 35, 53, 50, 68] }]
|
||||
|
||||
const chartOptions = computed(() => {
|
||||
const currentTheme = vuetifyTheme.current.value.colors
|
||||
|
||||
return {
|
||||
chart: {
|
||||
parentHeightOffset: 0,
|
||||
toolbar: { show: false },
|
||||
dropShadow: {
|
||||
top: 12,
|
||||
blur: 4,
|
||||
left: 0,
|
||||
enabled: true,
|
||||
opacity: 0.12,
|
||||
color: currentTheme.warning,
|
||||
},
|
||||
},
|
||||
tooltip: { enabled: false },
|
||||
colors: [`rgba(${hexToRgb(String(currentTheme.warning))}, 1)`],
|
||||
stroke: {
|
||||
width: 4,
|
||||
curve: 'smooth',
|
||||
lineCap: 'round',
|
||||
},
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
top: -21,
|
||||
left: -5,
|
||||
bottom: -8,
|
||||
},
|
||||
},
|
||||
xaxis: {
|
||||
labels: { show: false },
|
||||
axisTicks: { show: false },
|
||||
axisBorder: { show: false },
|
||||
},
|
||||
yaxis: {
|
||||
labels: { show: false },
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: display.thresholds.value.lg,
|
||||
options: {
|
||||
chart: {
|
||||
height: 151,
|
||||
width: '100%',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: display.thresholds.value.md,
|
||||
options: {
|
||||
chart: {
|
||||
height: 131,
|
||||
width: '100%',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardText class="d-flex justify-space-between h-100">
|
||||
<div class="d-flex flex-column justify-space-between gap-y-4">
|
||||
<div>
|
||||
<h5 class="text-h5 mb-1">
|
||||
Profile Report
|
||||
</h5>
|
||||
<VChip
|
||||
color="warning"
|
||||
size="small"
|
||||
>
|
||||
Year 2022
|
||||
</VChip>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="d-flex gap-1 align-center text-success">
|
||||
<VIcon
|
||||
icon="bx-up-arrow-alt"
|
||||
size="20"
|
||||
/>
|
||||
<span class="text-base d-inline-block">68.2%</span>
|
||||
</div>
|
||||
|
||||
<h4 class="text-h4">
|
||||
$84,686k
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="h-100 d-flex align-center">
|
||||
<VueApexCharts
|
||||
type="line"
|
||||
:height="131"
|
||||
width="80%"
|
||||
:options="chartOptions"
|
||||
:series="series"
|
||||
/>
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
96
views/dashboard/AnalyticsRevenue.vue
Normal file
96
views/dashboard/AnalyticsRevenue.vue
Normal file
@@ -0,0 +1,96 @@
|
||||
<script setup lang="ts">
|
||||
import { useTheme } from 'vuetify'
|
||||
import { hexToRgb } from '@core/utils/colorConverter'
|
||||
|
||||
const vuetifyTheme = useTheme()
|
||||
|
||||
const series = [{ data: [23, 81, 70, 31, 99, 46, 73] }]
|
||||
|
||||
const chartOptions = computed(() => {
|
||||
const currentTheme = vuetifyTheme.current.value.colors
|
||||
const variableTheme = vuetifyTheme.current.value.variables
|
||||
const disabledText = `rgba(${hexToRgb(String(currentTheme['on-surface']))},${variableTheme['disabled-opacity']})`
|
||||
|
||||
return {
|
||||
chart: {
|
||||
parentHeightOffset: 0,
|
||||
toolbar: { show: false },
|
||||
|
||||
// offsetY: -30,
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 2,
|
||||
distributed: true,
|
||||
columnWidth: '65%',
|
||||
endingShape: 'rounded',
|
||||
startingShape: 'rounded',
|
||||
},
|
||||
},
|
||||
legend: { show: false },
|
||||
tooltip: { enabled: false },
|
||||
dataLabels: { enabled: false },
|
||||
colors: [
|
||||
`rgba(${hexToRgb(String(currentTheme.primary))}, 0.16)`,
|
||||
`rgba(${hexToRgb(String(currentTheme.primary))}, 0.16)`,
|
||||
`rgba(${hexToRgb(String(currentTheme.primary))}, 0.16)`,
|
||||
`rgba(${hexToRgb(String(currentTheme.primary))}, 0.16)`,
|
||||
`rgba(${hexToRgb(String(currentTheme.primary))}, 1)`,
|
||||
`rgba(${hexToRgb(String(currentTheme.primary))}, 0.16)`,
|
||||
`rgba(${hexToRgb(String(currentTheme.primary))}, 0.16)`,
|
||||
],
|
||||
states: {
|
||||
hover: {
|
||||
filter: { type: 'none' },
|
||||
},
|
||||
active: {
|
||||
filter: { type: 'none' },
|
||||
},
|
||||
},
|
||||
xaxis: {
|
||||
categories: ['M', 'T', 'W', 'T', 'F', 'S', 'S'],
|
||||
axisTicks: { show: false },
|
||||
axisBorder: { show: false },
|
||||
tickPlacement: 'on',
|
||||
offsetY: -10,
|
||||
labels: {
|
||||
style: {
|
||||
fontSize: '11px',
|
||||
colors: disabledText,
|
||||
fontFamily: 'Public Sans',
|
||||
},
|
||||
},
|
||||
},
|
||||
yaxis: { show: false },
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
left: 0,
|
||||
top: -10,
|
||||
right: 7,
|
||||
bottom: -3,
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardText class="pb-0">
|
||||
<div class="text-base">
|
||||
Revenue
|
||||
</div>
|
||||
<h4 class="text-h4 font-weight-medium">
|
||||
425k
|
||||
</h4>
|
||||
</VCardText>
|
||||
|
||||
<VueApexCharts
|
||||
type="bar"
|
||||
:height="110"
|
||||
:options="chartOptions"
|
||||
:series="series"
|
||||
/>
|
||||
</VCard>
|
||||
</template>
|
||||
349
views/dashboard/AnalyticsTotalRevenue.vue
Normal file
349
views/dashboard/AnalyticsTotalRevenue.vue
Normal file
@@ -0,0 +1,349 @@
|
||||
<script setup lang="ts">
|
||||
import { useDisplay, useTheme } from 'vuetify'
|
||||
import { hexToRgb } from '@core/utils/colorConverter'
|
||||
|
||||
const vuetifyTheme = useTheme()
|
||||
const display = useDisplay()
|
||||
|
||||
const series = [
|
||||
{ name: `${new Date().getFullYear() - 1}`, data: [18, 10, 15, 29, 18, 12, 9] },
|
||||
{ name: `${new Date().getFullYear() - 2}`, data: [-13, -18, -9, -14, -8, -17, -15] },
|
||||
]
|
||||
|
||||
const chartOptions = computed(() => {
|
||||
const currentTheme = vuetifyTheme.current.value.colors
|
||||
const variableTheme = vuetifyTheme.current.value.variables
|
||||
|
||||
const disabledTextColor = `rgba(${hexToRgb(String(currentTheme['on-surface']))},${variableTheme['disabled-opacity']})`
|
||||
const primaryTextColor = `rgba(${hexToRgb(String(currentTheme['on-surface']))},${variableTheme['high-emphasis-opacity']})`
|
||||
const secondaryTextColor = `rgba(${hexToRgb(String(currentTheme['on-surface']))},${variableTheme['medium-emphasis-opacity']})`
|
||||
const borderColor = `rgba(${hexToRgb(String(variableTheme['border-color']))},${variableTheme['border-opacity']})`
|
||||
|
||||
return {
|
||||
bar: {
|
||||
chart: {
|
||||
stacked: true,
|
||||
parentHeightOffset: 6,
|
||||
offsetX: -12,
|
||||
toolbar: { show: false },
|
||||
},
|
||||
dataLabels: { enabled: false },
|
||||
stroke: {
|
||||
width: 6,
|
||||
lineCap: 'round',
|
||||
colors: [currentTheme.surface],
|
||||
},
|
||||
colors: [`rgba(${hexToRgb(String(currentTheme.primary))}, 1)`, `rgba(${hexToRgb(String(currentTheme.info))}, 1)`],
|
||||
legend: {
|
||||
offsetX: -22,
|
||||
offsetY: -1,
|
||||
position: 'top',
|
||||
fontSize: '13px',
|
||||
horizontalAlign: 'left',
|
||||
fontFamily: 'Public Sans',
|
||||
labels: {
|
||||
colors: currentTheme.secondary,
|
||||
},
|
||||
itemMargin: {
|
||||
vertical: 4,
|
||||
horizontal: 10,
|
||||
},
|
||||
markers: {
|
||||
width: 11,
|
||||
height: 11,
|
||||
radius: 10,
|
||||
offsetX: -2,
|
||||
},
|
||||
},
|
||||
states: {
|
||||
hover: {
|
||||
filter: { type: 'none' },
|
||||
},
|
||||
active: {
|
||||
filter: { type: 'none' },
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
strokeDashArray: 6,
|
||||
borderColor,
|
||||
padding: {
|
||||
bottom: 5,
|
||||
},
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 9,
|
||||
columnWidth: '30%',
|
||||
borderRadiusApplication: 'around',
|
||||
borderRadiusWhenStacked: 'all',
|
||||
},
|
||||
},
|
||||
xaxis: {
|
||||
axisTicks: { show: false },
|
||||
crosshairs: { opacity: 0 },
|
||||
axisBorder: { show: false },
|
||||
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'],
|
||||
labels: {
|
||||
style: {
|
||||
fontSize: '13px',
|
||||
colors: disabledTextColor,
|
||||
fontFamily: 'Public Sans',
|
||||
},
|
||||
},
|
||||
},
|
||||
yaxis: {
|
||||
labels: {
|
||||
style: {
|
||||
fontSize: '13px',
|
||||
colors: disabledTextColor,
|
||||
fontFamily: 'Public Sans',
|
||||
},
|
||||
},
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 1980,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: { columnWidth: '32%', borderRadius: 8 },
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: display.thresholds.value.xl,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: { columnWidth: '43%', borderRadius: 8 },
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: display.thresholds.value.lg,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: { columnWidth: '50%', borderRadius: 7 },
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: display.thresholds.value.md,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: { columnWidth: '48%', borderRadius: 8 },
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: display.thresholds.value.sm,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: { columnWidth: '44%', borderRadius: 6 },
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 599,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: { columnWidth: '44%', borderRadius: 8 },
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 420,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: { columnWidth: '55%', borderRadius: 6 },
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
radial: {
|
||||
chart: {
|
||||
sparkline: { enabled: true },
|
||||
},
|
||||
labels: ['Growth'],
|
||||
stroke: { dashArray: 5 },
|
||||
colors: [`rgba(${hexToRgb(String(currentTheme.primary))}, 1)`],
|
||||
states: {
|
||||
hover: {
|
||||
filter: { type: 'none' },
|
||||
},
|
||||
active: {
|
||||
filter: { type: 'none' },
|
||||
},
|
||||
},
|
||||
fill: {
|
||||
type: 'gradient',
|
||||
gradient: {
|
||||
shade: 'dark',
|
||||
opacityTo: 0.6,
|
||||
opacityFrom: 1,
|
||||
shadeIntensity: 0.5,
|
||||
stops: [30, 70, 100],
|
||||
inverseColors: false,
|
||||
gradientToColors: [currentTheme.primary],
|
||||
},
|
||||
},
|
||||
plotOptions: {
|
||||
radialBar: {
|
||||
endAngle: 150,
|
||||
startAngle: -140,
|
||||
hollow: { size: '55%' },
|
||||
track: { background: 'transparent' },
|
||||
dataLabels: {
|
||||
name: {
|
||||
offsetY: 25,
|
||||
fontWeight: 500,
|
||||
fontSize: '15px',
|
||||
color: secondaryTextColor,
|
||||
fontFamily: 'Public Sans',
|
||||
},
|
||||
value: {
|
||||
offsetY: -15,
|
||||
fontWeight: 500,
|
||||
fontSize: '24px',
|
||||
color: primaryTextColor,
|
||||
fontFamily: 'Public Sans',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 900,
|
||||
options: {
|
||||
chart: { height: 200 },
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 735,
|
||||
options: {
|
||||
chart: { height: 200 },
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 660,
|
||||
options: {
|
||||
chart: { height: 200 },
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 600,
|
||||
options: {
|
||||
chart: { height: 200 },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
const balanceData = [
|
||||
{ icon: 'bx-dollar', amount: '$2.54k', year: '2023', color: 'primary' },
|
||||
{ icon: 'bx-wallet', amount: '$4.21k', year: '2022', color: 'info' },
|
||||
]
|
||||
|
||||
const moreList = [
|
||||
{ title: 'Share', value: 'Share' },
|
||||
{ title: 'Refresh', value: 'Refresh' },
|
||||
{ title: 'Update', value: 'Update' },
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard>
|
||||
<VRow no-gutters>
|
||||
<VCol
|
||||
cols="12"
|
||||
sm="7"
|
||||
xl="8"
|
||||
:class="$vuetify.display.smAndUp ? 'border-e' : 'border-b'"
|
||||
>
|
||||
<VCardItem class="pb-0">
|
||||
<VCardTitle>Total Revenue</VCardTitle>
|
||||
|
||||
<template #append>
|
||||
<MoreBtn :menu-list="moreList" />
|
||||
</template>
|
||||
</VCardItem>
|
||||
|
||||
<!-- bar chart -->
|
||||
<VCardText class="pb-0">
|
||||
<VueApexCharts
|
||||
type="bar"
|
||||
:height="335"
|
||||
:options="chartOptions.bar"
|
||||
:series="series"
|
||||
/>
|
||||
</VCardText>
|
||||
</VCol>
|
||||
|
||||
<VCol
|
||||
cols="12"
|
||||
sm="5"
|
||||
xl="4"
|
||||
>
|
||||
<VCardText class="text-center pt-10">
|
||||
<VBtn
|
||||
variant="tonal"
|
||||
class="mb-2"
|
||||
append-icon="bx-chevron-down"
|
||||
>
|
||||
2023
|
||||
<VMenu activator="parent">
|
||||
<VList>
|
||||
<VListItem
|
||||
v-for="(item, index) in ['2023', '2022', '2021']"
|
||||
:key="index"
|
||||
:value="item"
|
||||
>
|
||||
<VListItemTitle>{{ item }}</VListItemTitle>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VMenu>
|
||||
</VBtn>
|
||||
|
||||
<!-- radial chart -->
|
||||
<VueApexCharts
|
||||
type="radialBar"
|
||||
:height="200"
|
||||
:options="chartOptions.radial"
|
||||
:series="[78]"
|
||||
/>
|
||||
|
||||
<h6 class="text-h6 text-medium-emphasis mb-8 mt-1">
|
||||
62% Company Growth
|
||||
</h6>
|
||||
<div class="d-flex align-center justify-center flex-wrap gap-x-6 gap-y-3">
|
||||
<div
|
||||
v-for="data in balanceData"
|
||||
:key="data.year"
|
||||
class="d-flex align-center gap-2"
|
||||
>
|
||||
<VAvatar
|
||||
:icon="data.icon"
|
||||
:color="data.color"
|
||||
size="38"
|
||||
rounded
|
||||
variant="tonal"
|
||||
/>
|
||||
|
||||
<div class="text-start">
|
||||
<span class="text-sm"> {{ data.year }}</span>
|
||||
<h6 class="text-h6">
|
||||
{{ data.amount }}
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@use "@core/scss/template/libs/apex-chart.scss"
|
||||
</style>
|
||||
105
views/dashboard/AnalyticsTransactions.vue
Normal file
105
views/dashboard/AnalyticsTransactions.vue
Normal file
@@ -0,0 +1,105 @@
|
||||
<script setup lang="ts">
|
||||
import chartInfo from '@images/cards/chart-info.png'
|
||||
import creditCardSuccess from '@images/cards/credit-card-success.png'
|
||||
import creditCardWarning from '@images/cards/credit-card-warning.png'
|
||||
import paypalError from '@images/cards/paypal-error.png'
|
||||
import walletPrimary from '@images/cards/wallet-primary.png'
|
||||
|
||||
const transactions = [
|
||||
{
|
||||
amount: +82.6,
|
||||
paymentMethod: 'PayPal',
|
||||
description: 'Send money',
|
||||
icon: paypalError,
|
||||
color: 'error',
|
||||
},
|
||||
{
|
||||
paymentMethod: 'Wallet',
|
||||
amount: +270.69,
|
||||
description: 'Mac\'D',
|
||||
icon: walletPrimary,
|
||||
color: 'primary',
|
||||
},
|
||||
{
|
||||
amount: +637.91,
|
||||
paymentMethod: 'Transfer',
|
||||
description: 'Refund',
|
||||
icon: chartInfo,
|
||||
color: 'info',
|
||||
},
|
||||
{
|
||||
paymentMethod: 'Credit Card',
|
||||
amount: -838.71,
|
||||
description: 'Ordered Food',
|
||||
icon: creditCardSuccess,
|
||||
color: 'success',
|
||||
},
|
||||
{
|
||||
paymentMethod: 'Wallet',
|
||||
amount: +203.33,
|
||||
description: 'Starbucks',
|
||||
icon: walletPrimary,
|
||||
color: 'primary',
|
||||
},
|
||||
{
|
||||
paymentMethod: 'Mastercard',
|
||||
amount: -92.45,
|
||||
description: 'Ordered Food',
|
||||
icon: creditCardWarning,
|
||||
color: 'warning',
|
||||
},
|
||||
]
|
||||
|
||||
const moreList = [
|
||||
{ title: 'Share', value: 'Share' },
|
||||
{ title: 'Refresh', value: 'Refresh' },
|
||||
{ title: 'Update', value: 'Update' },
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard title="Transactions">
|
||||
<template #append>
|
||||
<MoreBtn :menu-list="moreList" />
|
||||
</template>
|
||||
|
||||
<VCardText>
|
||||
<VList class="card-list">
|
||||
<VListItem
|
||||
v-for="item in transactions"
|
||||
:key="item.paymentMethod"
|
||||
>
|
||||
<template #prepend>
|
||||
<VAvatar
|
||||
rounded
|
||||
variant="tonal"
|
||||
:color="item.color"
|
||||
:image="item.icon"
|
||||
size="40"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<VListItemSubtitle>
|
||||
{{ item.paymentMethod }}
|
||||
</VListItemSubtitle>
|
||||
<VListItemTitle>
|
||||
{{ item.description }}
|
||||
</VListItemTitle>
|
||||
|
||||
<template #append>
|
||||
<VListItemAction>
|
||||
<span class="me-2">{{ item.amount > 0 ? `+$${Math.abs(item.amount)}` : `-$${Math.abs(item.amount)}` }}</span>
|
||||
<span class="text-disabled">USD</span>
|
||||
</VListItemAction>
|
||||
</template>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card-list {
|
||||
--v-card-list-gap: 1.5rem;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user