@veristone/nuxt-v-app 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -0
- package/app/app.vue +7 -0
- package/app/assets/css/v-app.css +313 -0
- package/app/components/V/A/Badge.vue +75 -0
- package/app/components/V/A/Btn/Add.vue +17 -0
- package/app/components/V/A/Btn/Back.vue +25 -0
- package/app/components/V/A/Btn/ConfirmDelete.vue +45 -0
- package/app/components/V/A/Btn/Edit.vue +35 -0
- package/app/components/V/A/Btn/Export.vue +28 -0
- package/app/components/V/A/Btn/Refresh.vue +21 -0
- package/app/components/V/A/Btn/Submit.vue +45 -0
- package/app/components/V/A/Btn/View.vue +23 -0
- package/app/components/V/A/Card.legacy.vue +291 -0
- package/app/components/V/A/Card.vue +108 -0
- package/app/components/V/A/CompanyMenu.vue +83 -0
- package/app/components/V/A/Data/KeyValue.vue +98 -0
- package/app/components/V/A/Data/StatusBadge.vue +44 -0
- package/app/components/V/A/DataField.vue +140 -0
- package/app/components/V/A/DataGrid.vue +43 -0
- package/app/components/V/A/DataTable.vue +144 -0
- package/app/components/V/A/EmptyState.vue +154 -0
- package/app/components/V/A/Fmt/Currency.vue +36 -0
- package/app/components/V/A/Fmt/DateTime.vue +34 -0
- package/app/components/V/A/Fmt/Percent.vue +47 -0
- package/app/components/V/A/LoadingState.vue +140 -0
- package/app/components/V/A/MetricCard.vue +129 -0
- package/app/components/V/A/Modal/Base.vue +195 -0
- package/app/components/V/A/Modal/Confirm.vue +92 -0
- package/app/components/V/A/Modal/Form.vue +105 -0
- package/app/components/V/A/Navigation.vue +110 -0
- package/app/components/V/A/QuickActions.vue +169 -0
- package/app/components/V/A/Slide.vue +109 -0
- package/app/components/V/A/Slideover.vue +259 -0
- package/app/components/V/A/State/Empty.vue +20 -0
- package/app/components/V/A/State/Error.vue +34 -0
- package/app/components/V/A/State/Loading.vue +33 -0
- package/app/components/V/A/StatsCard.vue +215 -0
- package/app/components/V/A/StatusBadge.vue +215 -0
- package/app/components/V/A/Table.vue +674 -0
- package/app/components/V/A/UserMenu.vue +127 -0
- package/app/components/V/A/WelcomeHeader.vue +96 -0
- package/app/components/V/Modal.vue +36 -0
- package/app/components/Va/Blocks/VaBlockGridCharts.vue +32 -0
- package/app/components/Va/Blocks/VaBlockGridKPI.vue +32 -0
- package/app/components/Va/Blocks/VaBlockGridTables.vue +23 -0
- package/app/components/Va/Blocks/VaBlockKpiGrid.vue +8 -0
- package/app/components/Va/Blocks/VaBlockSessionFilterBar.vue +8 -0
- package/app/components/Va/Cards/VaCardDonutChart.vue +59 -0
- package/app/components/Va/Cards/VaCardHeader.vue +10 -0
- package/app/components/Va/Cards/VaCardKpi.vue +17 -0
- package/app/components/Va/Cards/VaCardKpi2.vue +55 -0
- package/app/components/Va/Cards/VaCardLatestOrders.vue +82 -0
- package/app/components/Va/Cards/VaCardPopularProducts.vue +88 -0
- package/app/components/Va/Cards/VaCardRevenueBarChart.vue +49 -0
- package/app/components/Va/Cards/VaCardSubtitle.vue +5 -0
- package/app/components/Va/Cards/VaCardTitle.vue +5 -0
- package/app/components/Va/Cards/VaCardWithActiveUsers.vue +41 -0
- package/app/components/Va/Cards/VaCardWithChart.vue +135 -0
- package/app/components/Va/Cards/VaCardWithChartBlock.vue +26 -0
- package/app/components/Va/Cards/VaCardWithIndicator.vue +39 -0
- package/app/components/Va/Cards/VaCardWithProgressCircle.vue +34 -0
- package/app/components/Va/Cards/types.ts +11 -0
- package/app/components/Va/Charts/VaChartAppPerformanceBar.vue +118 -0
- package/app/components/Va/Charts/VaChartAppPerformanceBarChart.vue +118 -0
- package/app/components/Va/Charts/VaChartAreaMini.vue +127 -0
- package/app/components/Va/Charts/VaChartBarMini.vue +68 -0
- package/app/components/Va/Charts/VaChartCardinalMulti.vue +108 -0
- package/app/components/Va/Charts/VaChartColorBarChart.vue +78 -0
- package/app/components/Va/Charts/VaChartDonutHalf.vue +35 -0
- package/app/components/Va/Charts/VaChartDonutMini.vue +77 -0
- package/app/components/Va/Charts/VaChartExpensesBar.vue +58 -0
- package/app/components/Va/Charts/VaChartFinanceSummary.vue +96 -0
- package/app/components/Va/Charts/VaChartGoogleSearchConsole.vue +90 -0
- package/app/components/Va/Charts/VaChartIncomeBar.vue +82 -0
- package/app/components/Va/Charts/VaChartLegend.vue +25 -0
- package/app/components/Va/Charts/VaChartLineMini.vue +205 -0
- package/app/components/Va/Charts/VaChartRealtimeTraffic.vue +182 -0
- package/app/components/Va/Charts/VaChartRevenue.vue +43 -0
- package/app/components/Va/Charts/VaChartRevenueLine.vue +42 -0
- package/app/components/Va/Charts/VaChartRevenuevsCost.vue +84 -0
- package/app/components/Va/Charts/VaChartSearchIntent.vue +179 -0
- package/app/components/Va/Charts/VaChartSpendingTrend.vue +127 -0
- package/app/components/Va/Charts/VaChartStackedHorizontal.vue +64 -0
- package/app/components/Va/Charts/VaChartStepMinimal.vue +109 -0
- package/app/components/Va/Charts/VaChartStockComparisonLine.vue +86 -0
- package/app/components/Va/Charts/VaChartStocksPortfolioLine.vue +161 -0
- package/app/components/Va/Charts/VaChartStocksSectorLine.vue +223 -0
- package/app/components/Va/Charts/VaChartTasksCategories.vue +96 -0
- package/app/components/Va/Charts/VaChartTasksProgress.vue +130 -0
- package/app/components/Va/Charts/VaChartTrafficOverview.vue +112 -0
- package/app/components/Va/Charts/VaChartWebPerformanceLineChart.vue +114 -0
- package/app/components/Va/Charts/VaChartWinLostBar.vue +110 -0
- package/app/components/Va/Charts/VaChartWinLostDonut.vue +107 -0
- package/app/components/Va/Charts/VaChartWinLostLine.vue +111 -0
- package/app/components/Va/Charts/types.ts +10 -0
- package/app/components/Va/Dashboard/Navigation/types.ts +8 -0
- package/app/components/Va/Dashboard/VaDashboardKPICard.vue +31 -0
- package/app/components/Va/Dashboard/VaDashboardNavigation.vue +50 -0
- package/app/components/Va/Dashboard/VaDashboardPricePlan.vue +102 -0
- package/app/components/Va/Dashboard/VaDashboardUsageChart.vue +84 -0
- package/app/components/Va/Dashboard/VaDashboardUsageRequestChart.vue +46 -0
- package/app/components/Va/Layout/NotificationsSlideover.vue +169 -0
- package/app/components/Va/Layout/SideNav/types.ts +5 -0
- package/app/components/Va/Layout/SideNav.vue +108 -0
- package/app/components/Va/Layout/TeamsMenu.vue +57 -0
- package/app/components/Va/Layout/UserMenu.vue +57 -0
- package/app/composables/useDashboard.ts +25 -0
- package/app/composables/useVAAnimation.ts +324 -0
- package/app/composables/useVAUtils.ts +118 -0
- package/app/composables/useVCrud.ts +647 -0
- package/app/composables/useVFetch.ts +46 -0
- package/app/composables/useVFileUpload.ts +45 -0
- package/app/composables/useVToast.ts +73 -0
- package/app/composables/useXATableColumns.ts +456 -0
- package/app/data/BillingStats.ts +65 -0
- package/app/data/SearchData.ts +58 -0
- package/app/data/TasksData.ts +101 -0
- package/app/data/dashboardData.ts +113 -0
- package/app/layouts/default.vue +171 -0
- package/app/layouts/legacy.vue +61 -0
- package/app/pages/playground/base.vue +498 -0
- package/app/pages/playground/blocks.vue +108 -0
- package/app/pages/playground/buttons.vue +237 -0
- package/app/pages/playground/cards.vue +326 -0
- package/app/pages/playground/charts.vue +338 -0
- package/app/pages/playground/dashboard.vue +315 -0
- package/app/pages/playground/formatters.vue +329 -0
- package/app/pages/playground/index.vue +109 -0
- package/app/pages/playground/layout.vue +159 -0
- package/app/pages/playground/modals.vue +606 -0
- package/app/pages/playground/states.vue +282 -0
- package/app/pages/playground/tables.vue +618 -0
- package/app/pages/test-layout.vue +10 -0
- package/nuxt.config.ts +12 -0
- package/package.json +71 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
interface DailyData {
|
|
3
|
+
day: string
|
|
4
|
+
Income: number
|
|
5
|
+
Expense: number
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const chartData = ref<DailyData[]>([
|
|
9
|
+
{
|
|
10
|
+
day: 'Jan',
|
|
11
|
+
Income: 8500,
|
|
12
|
+
Expense: 4000
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
day: 'Feb',
|
|
16
|
+
Income: 6500,
|
|
17
|
+
Expense: 9000
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
day: 'Mar',
|
|
21
|
+
Income: 7500,
|
|
22
|
+
Expense: 3500
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
day: 'Apr',
|
|
26
|
+
Income: 5800,
|
|
27
|
+
Expense: 7000
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
day: 'May',
|
|
31
|
+
Income: 9200,
|
|
32
|
+
Expense: 6500
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
day: 'Jun',
|
|
36
|
+
Income: 9800,
|
|
37
|
+
Expense: 4500
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
day: 'Jul',
|
|
41
|
+
Income: 5000,
|
|
42
|
+
Expense: 8500
|
|
43
|
+
}
|
|
44
|
+
])
|
|
45
|
+
|
|
46
|
+
const chartCategories: Record<string, BulletLegendItemInterface> = {
|
|
47
|
+
Income: {
|
|
48
|
+
name: 'Income',
|
|
49
|
+
color: '#10b981'
|
|
50
|
+
},
|
|
51
|
+
Expense: {
|
|
52
|
+
name: 'Expense',
|
|
53
|
+
color: '#f59e0b'
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const xAxisFormatter = (tick: number): string => {
|
|
58
|
+
// tick is the index of the data point
|
|
59
|
+
const months = chartData.value.map(item => item.day)
|
|
60
|
+
return months[tick] || ''
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const { height } = useResponsiveHeight({
|
|
64
|
+
default: 120,
|
|
65
|
+
sm: 240
|
|
66
|
+
})
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<template>
|
|
70
|
+
<LineChart
|
|
71
|
+
:data="chartData"
|
|
72
|
+
:categories="chartCategories"
|
|
73
|
+
:y-axis="['Income', 'Expense']"
|
|
74
|
+
:x-formatter="xAxisFormatter"
|
|
75
|
+
:height="height"
|
|
76
|
+
:stacked="false"
|
|
77
|
+
:radius="3"
|
|
78
|
+
:group-padding="0.2"
|
|
79
|
+
:bar-padding="0.2"
|
|
80
|
+
:x-grid-line="true"
|
|
81
|
+
:y-grid-line="true"
|
|
82
|
+
:y-num-ticks="4"
|
|
83
|
+
/>
|
|
84
|
+
</template>
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import type { TabsItem } from '#ui/types'
|
|
3
|
+
|
|
4
|
+
const tabItems: TabsItem[] = [
|
|
5
|
+
{
|
|
6
|
+
label: '24 hours',
|
|
7
|
+
value: '24h'
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
label: '7 days',
|
|
11
|
+
value: '7d'
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
label: '28 days',
|
|
15
|
+
value: '28d'
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
const selectedPeriod = ref('24h')
|
|
20
|
+
|
|
21
|
+
const searchIntentDataByPeriod = {
|
|
22
|
+
'24h': [
|
|
23
|
+
{
|
|
24
|
+
name: 'Informational',
|
|
25
|
+
percentage: 42.5,
|
|
26
|
+
count: 850
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'Navigational',
|
|
30
|
+
percentage: 28.3,
|
|
31
|
+
count: 566
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: 'Commercial',
|
|
35
|
+
percentage: 18.7,
|
|
36
|
+
count: 374
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'Transactional',
|
|
40
|
+
percentage: 10.5,
|
|
41
|
+
count: 210
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
'7d': [
|
|
45
|
+
{
|
|
46
|
+
name: 'Informational',
|
|
47
|
+
percentage: 38.2,
|
|
48
|
+
count: 5890
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'Navigational',
|
|
52
|
+
percentage: 31.5,
|
|
53
|
+
count: 4860
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: 'Commercial',
|
|
57
|
+
percentage: 20.1,
|
|
58
|
+
count: 3100
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'Transactional',
|
|
62
|
+
percentage: 10.2,
|
|
63
|
+
count: 1570
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
'28d': [
|
|
67
|
+
{
|
|
68
|
+
name: 'Informational',
|
|
69
|
+
percentage: 40.8,
|
|
70
|
+
count: 24500
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: 'Navigational',
|
|
74
|
+
percentage: 29.7,
|
|
75
|
+
count: 17850
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: 'Commercial',
|
|
79
|
+
percentage: 19.5,
|
|
80
|
+
count: 11700
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: 'Transactional',
|
|
84
|
+
percentage: 10.0,
|
|
85
|
+
count: 6000
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const searchIntentCategories = {
|
|
91
|
+
informational: {
|
|
92
|
+
name: 'Informational',
|
|
93
|
+
color: 'var(--color-amber-400)'
|
|
94
|
+
},
|
|
95
|
+
navigational: {
|
|
96
|
+
name: 'Navigational',
|
|
97
|
+
color: 'var(--ui-primary)'
|
|
98
|
+
},
|
|
99
|
+
commercial: {
|
|
100
|
+
name: 'Commercial',
|
|
101
|
+
color: 'var(--color-indigo-400)'
|
|
102
|
+
},
|
|
103
|
+
transactional: {
|
|
104
|
+
name: 'Transactional',
|
|
105
|
+
color: 'var(--color-orange-400)'
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const searchIntentLabels = computed(() => {
|
|
110
|
+
return searchIntentDataByPeriod[selectedPeriod.value as keyof typeof searchIntentDataByPeriod]
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
const searchIntentData = computed(() => searchIntentLabels.value.map(i => i.percentage))
|
|
114
|
+
|
|
115
|
+
const getCategoryColor = (index: number) => {
|
|
116
|
+
const categories = Object.values(searchIntentCategories)
|
|
117
|
+
return categories[index]?.color || 'var(--ui-text-muted)'
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const handleTabChange = (value: string | number) => {
|
|
121
|
+
selectedPeriod.value = value as string
|
|
122
|
+
}
|
|
123
|
+
</script>
|
|
124
|
+
|
|
125
|
+
<template>
|
|
126
|
+
<UCard :ui="{ footer: 'bg-elevated' }">
|
|
127
|
+
<template #header>
|
|
128
|
+
<CardsTitle>Intent</CardsTitle>
|
|
129
|
+
</template>
|
|
130
|
+
|
|
131
|
+
<DonutChart
|
|
132
|
+
:data="searchIntentData"
|
|
133
|
+
:height="140"
|
|
134
|
+
:type="DonutType.Full"
|
|
135
|
+
:radius="5"
|
|
136
|
+
:arc-width="20"
|
|
137
|
+
:pad-angle="0.1"
|
|
138
|
+
:categories="searchIntentCategories"
|
|
139
|
+
:hide-legend="true"
|
|
140
|
+
/>
|
|
141
|
+
|
|
142
|
+
<div class="space-y-3 mt-6">
|
|
143
|
+
<div
|
|
144
|
+
v-for="(item, index) in searchIntentLabels"
|
|
145
|
+
:key="index"
|
|
146
|
+
class="flex items-center justify-between"
|
|
147
|
+
>
|
|
148
|
+
<div class="flex items-center gap-3">
|
|
149
|
+
<div
|
|
150
|
+
class="w-2 h-2 rounded-full flex-shrink-0"
|
|
151
|
+
:style="{ backgroundColor: getCategoryColor(index) }"
|
|
152
|
+
/>
|
|
153
|
+
<div>
|
|
154
|
+
<div class="font-medium">
|
|
155
|
+
{{ item.name }}
|
|
156
|
+
</div>
|
|
157
|
+
<div class="text-muted text-xs">
|
|
158
|
+
{{ item.count.toLocaleString() }} queries
|
|
159
|
+
</div>
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
162
|
+
|
|
163
|
+
<div class="font-semibold text-sm">
|
|
164
|
+
{{ item.percentage }}%
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
|
|
169
|
+
<UTabs
|
|
170
|
+
v-model="selectedPeriod"
|
|
171
|
+
:items="tabItems"
|
|
172
|
+
:content="false"
|
|
173
|
+
size="sm"
|
|
174
|
+
color="neutral"
|
|
175
|
+
class="mt-6"
|
|
176
|
+
@update:model-value="handleTabChange"
|
|
177
|
+
/>
|
|
178
|
+
</UCard>
|
|
179
|
+
</template>
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
interface SpendingData {
|
|
3
|
+
month: number
|
|
4
|
+
currentYear: number
|
|
5
|
+
lastYear: number
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const chartData = ref<SpendingData[]>([
|
|
9
|
+
{
|
|
10
|
+
month: 1,
|
|
11
|
+
currentYear: 2500,
|
|
12
|
+
lastYear: 2000
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
month: 2,
|
|
16
|
+
currentYear: 1500,
|
|
17
|
+
lastYear: 1200
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
month: 3,
|
|
21
|
+
currentYear: 3000,
|
|
22
|
+
lastYear: 2800
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
month: 4,
|
|
26
|
+
currentYear: 4000,
|
|
27
|
+
lastYear: 3500
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
month: 5,
|
|
31
|
+
currentYear: 4500,
|
|
32
|
+
lastYear: 4200
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
month: 6,
|
|
36
|
+
currentYear: 2800,
|
|
37
|
+
lastYear: 2500
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
month: 7,
|
|
41
|
+
currentYear: 3500,
|
|
42
|
+
lastYear: 3100
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
month: 8,
|
|
46
|
+
currentYear: 3800,
|
|
47
|
+
lastYear: 3600
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
month: 9,
|
|
51
|
+
currentYear: 2000,
|
|
52
|
+
lastYear: 1800
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
month: 10,
|
|
56
|
+
currentYear: 4200,
|
|
57
|
+
lastYear: 4000
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
month: 11,
|
|
61
|
+
currentYear: 2200,
|
|
62
|
+
lastYear: 2100
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
month: 12,
|
|
66
|
+
currentYear: 1800,
|
|
67
|
+
lastYear: 1600
|
|
68
|
+
}
|
|
69
|
+
])
|
|
70
|
+
|
|
71
|
+
const categories: Record<string, any> = {
|
|
72
|
+
currentYear: {
|
|
73
|
+
name: 'Current Year',
|
|
74
|
+
color: '#6366f1'
|
|
75
|
+
},
|
|
76
|
+
lastYear: {
|
|
77
|
+
name: 'Last Year',
|
|
78
|
+
color: '#94a3b8'
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const formatCurrency = (value: number) => {
|
|
83
|
+
return new Intl.NumberFormat('en-US', {
|
|
84
|
+
style: 'currency',
|
|
85
|
+
currency: 'USD',
|
|
86
|
+
minimumFractionDigits: 0,
|
|
87
|
+
maximumFractionDigits: 0
|
|
88
|
+
}).format(value)
|
|
89
|
+
}
|
|
90
|
+
</script>
|
|
91
|
+
|
|
92
|
+
<template>
|
|
93
|
+
<UCard>
|
|
94
|
+
<div class="space-y-6">
|
|
95
|
+
<div class="flex items-center justify-between">
|
|
96
|
+
<h2 class="text-lg font-medium text-highlighted">
|
|
97
|
+
Revenue Trend
|
|
98
|
+
</h2>
|
|
99
|
+
<div class="text-sm text-toned">
|
|
100
|
+
Year over Year
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
|
|
104
|
+
<AreaChart
|
|
105
|
+
:data="chartData"
|
|
106
|
+
:height="240"
|
|
107
|
+
:categories="categories"
|
|
108
|
+
:y-axis="['amount']"
|
|
109
|
+
:y-num-ticks="3"
|
|
110
|
+
:y-grid-line="true"
|
|
111
|
+
:curve-type="CurveType.MonotoneX"
|
|
112
|
+
:legend-position="LegendPosition.TopRight"
|
|
113
|
+
:x-formatter="
|
|
114
|
+
(i: number) =>
|
|
115
|
+
new Date(`2025-${chartData[i]?.month}-02`).toLocaleDateString(
|
|
116
|
+
'en-US',
|
|
117
|
+
{
|
|
118
|
+
month: 'short'
|
|
119
|
+
}
|
|
120
|
+
)
|
|
121
|
+
"
|
|
122
|
+
:y-formatter="formatCurrency"
|
|
123
|
+
y-label="Revenue"
|
|
124
|
+
/>
|
|
125
|
+
</div>
|
|
126
|
+
</UCard>
|
|
127
|
+
</template>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
const RevenueData = [
|
|
3
|
+
{
|
|
4
|
+
month: 'January',
|
|
5
|
+
desktop: 186,
|
|
6
|
+
mobile: 80
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
month: 'February',
|
|
10
|
+
desktop: 305,
|
|
11
|
+
mobile: 200
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
month: 'March',
|
|
15
|
+
desktop: 237,
|
|
16
|
+
mobile: 120
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
month: 'April',
|
|
20
|
+
desktop: 73,
|
|
21
|
+
mobile: 190
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
const RevenueCategoriesMultple = {
|
|
25
|
+
desktop: {
|
|
26
|
+
name: 'Desktop',
|
|
27
|
+
color: '#6366f1'
|
|
28
|
+
},
|
|
29
|
+
mobile: {
|
|
30
|
+
name: 'Mobile',
|
|
31
|
+
color: '#10b981'
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const yFormatter = (i: number): string => `${i}`
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<template>
|
|
39
|
+
<UCard>
|
|
40
|
+
<div class="space-y-4">
|
|
41
|
+
<h2 class="text-lg font-medium text-highlighted">
|
|
42
|
+
Revenue Monitoring
|
|
43
|
+
</h2>
|
|
44
|
+
|
|
45
|
+
<BarChart
|
|
46
|
+
:data="RevenueData"
|
|
47
|
+
:stacked="true"
|
|
48
|
+
:height="200"
|
|
49
|
+
:categories="RevenueCategoriesMultple"
|
|
50
|
+
:y-axis="['desktop', 'mobile']"
|
|
51
|
+
:group-padding="0"
|
|
52
|
+
:bar-padding="0.2"
|
|
53
|
+
:x-num-ticks="6"
|
|
54
|
+
:radius="4"
|
|
55
|
+
:orientation="Orientation.Horizontal"
|
|
56
|
+
:x-formatter="yFormatter"
|
|
57
|
+
:y-formatter="(i: number): string => `${RevenueData[i]?.month}`"
|
|
58
|
+
:legend-position="LegendPosition.TopRight"
|
|
59
|
+
:hide-legend="false"
|
|
60
|
+
:x-grid-line="true"
|
|
61
|
+
/>
|
|
62
|
+
</div>
|
|
63
|
+
</UCard>
|
|
64
|
+
</template>
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
const colorMode = useColorMode()
|
|
3
|
+
|
|
4
|
+
interface MetricDataItem {
|
|
5
|
+
time: string
|
|
6
|
+
cpu: number
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const MetricData: MetricDataItem[] = [
|
|
10
|
+
{
|
|
11
|
+
time: '00:00',
|
|
12
|
+
cpu: 45
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
time: '02:00',
|
|
16
|
+
cpu: 38
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
time: '04:00',
|
|
20
|
+
cpu: 52
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
time: '06:00',
|
|
24
|
+
cpu: 47
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
time: '08:00',
|
|
28
|
+
cpu: 78
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
time: '10:00',
|
|
32
|
+
cpu: 71
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
time: '12:00',
|
|
36
|
+
cpu: 65
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
time: '14:00',
|
|
40
|
+
cpu: 73
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
time: '16:00',
|
|
44
|
+
cpu: 82
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
time: '18:00',
|
|
48
|
+
cpu: 68
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
time: '20:00',
|
|
52
|
+
cpu: 58
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
time: '22:00',
|
|
56
|
+
cpu: 43
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
time: '24:00',
|
|
60
|
+
cpu: 41
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
const MetricCategories = computed(() => ({
|
|
65
|
+
cpu: {
|
|
66
|
+
name: 'CPU Usage',
|
|
67
|
+
color: colorMode.value === 'dark' ? '#f97316' : '#ea580c'
|
|
68
|
+
}
|
|
69
|
+
}))
|
|
70
|
+
|
|
71
|
+
const xFormatter = (i: number): string => `${MetricData[i]?.time}`
|
|
72
|
+
const yFormatter = (value: number): string => `${value}%`
|
|
73
|
+
</script>
|
|
74
|
+
|
|
75
|
+
<template>
|
|
76
|
+
<UCard>
|
|
77
|
+
<div class="space-y-6">
|
|
78
|
+
<div class="flex items-center justify-between">
|
|
79
|
+
<h2 class="text-lg font-medium text-highlighted">
|
|
80
|
+
System Performance
|
|
81
|
+
</h2>
|
|
82
|
+
<div class="text-sm text-toned">
|
|
83
|
+
Last 24 hours
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<LineChart
|
|
88
|
+
:key="colorMode.value"
|
|
89
|
+
:data="MetricData"
|
|
90
|
+
:height="240"
|
|
91
|
+
:categories="MetricCategories"
|
|
92
|
+
:x-formatter="xFormatter"
|
|
93
|
+
:y-formatter="yFormatter"
|
|
94
|
+
:curve-type="CurveType.Step"
|
|
95
|
+
:legend-position="LegendPosition.TopRight"
|
|
96
|
+
:hide-legend="false"
|
|
97
|
+
:x-grid-line="true"
|
|
98
|
+
:y-grid-line="true"
|
|
99
|
+
:x-domain-line="false"
|
|
100
|
+
:y-domain-line="false"
|
|
101
|
+
:hide-tooltip="false"
|
|
102
|
+
:y-num-ticks="5"
|
|
103
|
+
:x-num-ticks="6"
|
|
104
|
+
x-label="Time (24h)"
|
|
105
|
+
y-label="CPU %"
|
|
106
|
+
/>
|
|
107
|
+
</div>
|
|
108
|
+
</UCard>
|
|
109
|
+
</template>
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
interface StockData {
|
|
3
|
+
day: string
|
|
4
|
+
stockA: number
|
|
5
|
+
stockB: number
|
|
6
|
+
stockC: number
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface BulletLegendItemInterface {
|
|
10
|
+
name: string
|
|
11
|
+
color: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const generateStockPrices = (
|
|
15
|
+
initialPriceA: number,
|
|
16
|
+
initialPriceB: number,
|
|
17
|
+
initialPriceC: number,
|
|
18
|
+
numDays: number
|
|
19
|
+
) => {
|
|
20
|
+
const data = []
|
|
21
|
+
let currentPriceA = initialPriceA
|
|
22
|
+
let currentPriceB = initialPriceB
|
|
23
|
+
let currentPriceC = initialPriceC
|
|
24
|
+
|
|
25
|
+
for (let i = 0; i < numDays; i++) {
|
|
26
|
+
// Stock A: General upward trend with some volatility
|
|
27
|
+
currentPriceA += Math.random() * 5 - 2 // +/- 2.5
|
|
28
|
+
currentPriceA = Math.max(currentPriceA, initialPriceA * 0.9) // Don't go too low
|
|
29
|
+
|
|
30
|
+
// Stock B: More volatile, but also generally upward
|
|
31
|
+
currentPriceB += Math.random() * 8 - 3 // +/- 4
|
|
32
|
+
currentPriceB = Math.max(currentPriceB, initialPriceB * 0.8)
|
|
33
|
+
|
|
34
|
+
// Stock C: Steady growth
|
|
35
|
+
currentPriceC += Math.random() * 3 - 1 // +/- 1.5
|
|
36
|
+
currentPriceC = Math.max(currentPriceC, initialPriceC * 0.95)
|
|
37
|
+
|
|
38
|
+
data.push({
|
|
39
|
+
day: `Day ${i + 1}`,
|
|
40
|
+
stockA: Math.round(currentPriceA),
|
|
41
|
+
stockB: Math.round(currentPriceB),
|
|
42
|
+
stockC: Math.round(currentPriceC)
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
return data
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const chartData = ref<StockData[]>(
|
|
49
|
+
generateStockPrices(100, 70, 120, 30)
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
const chartCategories: Record<string, BulletLegendItemInterface> = {
|
|
53
|
+
stockA: {
|
|
54
|
+
name: 'Tech Innovators Inc.',
|
|
55
|
+
color: '#3b82f6' // blue-500
|
|
56
|
+
},
|
|
57
|
+
stockC: {
|
|
58
|
+
name: 'Health Solutions Ltd.',
|
|
59
|
+
color: '#06b6d4' // cyan-500
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const xAxisFormatter = (tick: number): string => {
|
|
64
|
+
const days = chartData.value.map(item => item.day)
|
|
65
|
+
return days[tick] || ''
|
|
66
|
+
}
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<template>
|
|
70
|
+
<LineChart
|
|
71
|
+
:data="chartData"
|
|
72
|
+
:categories="chartCategories"
|
|
73
|
+
:y-axis="['stockA', 'stockB', 'stockC']"
|
|
74
|
+
:x-formatter="xAxisFormatter"
|
|
75
|
+
:height="220"
|
|
76
|
+
:radius="3"
|
|
77
|
+
:group-padding="0.2"
|
|
78
|
+
:bar-padding="0.2"
|
|
79
|
+
:x-grid-line="true"
|
|
80
|
+
:y-grid-line="true"
|
|
81
|
+
:x-domain-line="true"
|
|
82
|
+
:y-domain-line="true"
|
|
83
|
+
:hide-legend="false"
|
|
84
|
+
:y-num-ticks="4"
|
|
85
|
+
/>
|
|
86
|
+
</template>
|