@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.
Files changed (136) hide show
  1. package/README.md +42 -0
  2. package/app/app.vue +7 -0
  3. package/app/assets/css/v-app.css +313 -0
  4. package/app/components/V/A/Badge.vue +75 -0
  5. package/app/components/V/A/Btn/Add.vue +17 -0
  6. package/app/components/V/A/Btn/Back.vue +25 -0
  7. package/app/components/V/A/Btn/ConfirmDelete.vue +45 -0
  8. package/app/components/V/A/Btn/Edit.vue +35 -0
  9. package/app/components/V/A/Btn/Export.vue +28 -0
  10. package/app/components/V/A/Btn/Refresh.vue +21 -0
  11. package/app/components/V/A/Btn/Submit.vue +45 -0
  12. package/app/components/V/A/Btn/View.vue +23 -0
  13. package/app/components/V/A/Card.legacy.vue +291 -0
  14. package/app/components/V/A/Card.vue +108 -0
  15. package/app/components/V/A/CompanyMenu.vue +83 -0
  16. package/app/components/V/A/Data/KeyValue.vue +98 -0
  17. package/app/components/V/A/Data/StatusBadge.vue +44 -0
  18. package/app/components/V/A/DataField.vue +140 -0
  19. package/app/components/V/A/DataGrid.vue +43 -0
  20. package/app/components/V/A/DataTable.vue +144 -0
  21. package/app/components/V/A/EmptyState.vue +154 -0
  22. package/app/components/V/A/Fmt/Currency.vue +36 -0
  23. package/app/components/V/A/Fmt/DateTime.vue +34 -0
  24. package/app/components/V/A/Fmt/Percent.vue +47 -0
  25. package/app/components/V/A/LoadingState.vue +140 -0
  26. package/app/components/V/A/MetricCard.vue +129 -0
  27. package/app/components/V/A/Modal/Base.vue +195 -0
  28. package/app/components/V/A/Modal/Confirm.vue +92 -0
  29. package/app/components/V/A/Modal/Form.vue +105 -0
  30. package/app/components/V/A/Navigation.vue +110 -0
  31. package/app/components/V/A/QuickActions.vue +169 -0
  32. package/app/components/V/A/Slide.vue +109 -0
  33. package/app/components/V/A/Slideover.vue +259 -0
  34. package/app/components/V/A/State/Empty.vue +20 -0
  35. package/app/components/V/A/State/Error.vue +34 -0
  36. package/app/components/V/A/State/Loading.vue +33 -0
  37. package/app/components/V/A/StatsCard.vue +215 -0
  38. package/app/components/V/A/StatusBadge.vue +215 -0
  39. package/app/components/V/A/Table.vue +674 -0
  40. package/app/components/V/A/UserMenu.vue +127 -0
  41. package/app/components/V/A/WelcomeHeader.vue +96 -0
  42. package/app/components/V/Modal.vue +36 -0
  43. package/app/components/Va/Blocks/VaBlockGridCharts.vue +32 -0
  44. package/app/components/Va/Blocks/VaBlockGridKPI.vue +32 -0
  45. package/app/components/Va/Blocks/VaBlockGridTables.vue +23 -0
  46. package/app/components/Va/Blocks/VaBlockKpiGrid.vue +8 -0
  47. package/app/components/Va/Blocks/VaBlockSessionFilterBar.vue +8 -0
  48. package/app/components/Va/Cards/VaCardDonutChart.vue +59 -0
  49. package/app/components/Va/Cards/VaCardHeader.vue +10 -0
  50. package/app/components/Va/Cards/VaCardKpi.vue +17 -0
  51. package/app/components/Va/Cards/VaCardKpi2.vue +55 -0
  52. package/app/components/Va/Cards/VaCardLatestOrders.vue +82 -0
  53. package/app/components/Va/Cards/VaCardPopularProducts.vue +88 -0
  54. package/app/components/Va/Cards/VaCardRevenueBarChart.vue +49 -0
  55. package/app/components/Va/Cards/VaCardSubtitle.vue +5 -0
  56. package/app/components/Va/Cards/VaCardTitle.vue +5 -0
  57. package/app/components/Va/Cards/VaCardWithActiveUsers.vue +41 -0
  58. package/app/components/Va/Cards/VaCardWithChart.vue +135 -0
  59. package/app/components/Va/Cards/VaCardWithChartBlock.vue +26 -0
  60. package/app/components/Va/Cards/VaCardWithIndicator.vue +39 -0
  61. package/app/components/Va/Cards/VaCardWithProgressCircle.vue +34 -0
  62. package/app/components/Va/Cards/types.ts +11 -0
  63. package/app/components/Va/Charts/VaChartAppPerformanceBar.vue +118 -0
  64. package/app/components/Va/Charts/VaChartAppPerformanceBarChart.vue +118 -0
  65. package/app/components/Va/Charts/VaChartAreaMini.vue +127 -0
  66. package/app/components/Va/Charts/VaChartBarMini.vue +68 -0
  67. package/app/components/Va/Charts/VaChartCardinalMulti.vue +108 -0
  68. package/app/components/Va/Charts/VaChartColorBarChart.vue +78 -0
  69. package/app/components/Va/Charts/VaChartDonutHalf.vue +35 -0
  70. package/app/components/Va/Charts/VaChartDonutMini.vue +77 -0
  71. package/app/components/Va/Charts/VaChartExpensesBar.vue +58 -0
  72. package/app/components/Va/Charts/VaChartFinanceSummary.vue +96 -0
  73. package/app/components/Va/Charts/VaChartGoogleSearchConsole.vue +90 -0
  74. package/app/components/Va/Charts/VaChartIncomeBar.vue +82 -0
  75. package/app/components/Va/Charts/VaChartLegend.vue +25 -0
  76. package/app/components/Va/Charts/VaChartLineMini.vue +205 -0
  77. package/app/components/Va/Charts/VaChartRealtimeTraffic.vue +182 -0
  78. package/app/components/Va/Charts/VaChartRevenue.vue +43 -0
  79. package/app/components/Va/Charts/VaChartRevenueLine.vue +42 -0
  80. package/app/components/Va/Charts/VaChartRevenuevsCost.vue +84 -0
  81. package/app/components/Va/Charts/VaChartSearchIntent.vue +179 -0
  82. package/app/components/Va/Charts/VaChartSpendingTrend.vue +127 -0
  83. package/app/components/Va/Charts/VaChartStackedHorizontal.vue +64 -0
  84. package/app/components/Va/Charts/VaChartStepMinimal.vue +109 -0
  85. package/app/components/Va/Charts/VaChartStockComparisonLine.vue +86 -0
  86. package/app/components/Va/Charts/VaChartStocksPortfolioLine.vue +161 -0
  87. package/app/components/Va/Charts/VaChartStocksSectorLine.vue +223 -0
  88. package/app/components/Va/Charts/VaChartTasksCategories.vue +96 -0
  89. package/app/components/Va/Charts/VaChartTasksProgress.vue +130 -0
  90. package/app/components/Va/Charts/VaChartTrafficOverview.vue +112 -0
  91. package/app/components/Va/Charts/VaChartWebPerformanceLineChart.vue +114 -0
  92. package/app/components/Va/Charts/VaChartWinLostBar.vue +110 -0
  93. package/app/components/Va/Charts/VaChartWinLostDonut.vue +107 -0
  94. package/app/components/Va/Charts/VaChartWinLostLine.vue +111 -0
  95. package/app/components/Va/Charts/types.ts +10 -0
  96. package/app/components/Va/Dashboard/Navigation/types.ts +8 -0
  97. package/app/components/Va/Dashboard/VaDashboardKPICard.vue +31 -0
  98. package/app/components/Va/Dashboard/VaDashboardNavigation.vue +50 -0
  99. package/app/components/Va/Dashboard/VaDashboardPricePlan.vue +102 -0
  100. package/app/components/Va/Dashboard/VaDashboardUsageChart.vue +84 -0
  101. package/app/components/Va/Dashboard/VaDashboardUsageRequestChart.vue +46 -0
  102. package/app/components/Va/Layout/NotificationsSlideover.vue +169 -0
  103. package/app/components/Va/Layout/SideNav/types.ts +5 -0
  104. package/app/components/Va/Layout/SideNav.vue +108 -0
  105. package/app/components/Va/Layout/TeamsMenu.vue +57 -0
  106. package/app/components/Va/Layout/UserMenu.vue +57 -0
  107. package/app/composables/useDashboard.ts +25 -0
  108. package/app/composables/useVAAnimation.ts +324 -0
  109. package/app/composables/useVAUtils.ts +118 -0
  110. package/app/composables/useVCrud.ts +647 -0
  111. package/app/composables/useVFetch.ts +46 -0
  112. package/app/composables/useVFileUpload.ts +45 -0
  113. package/app/composables/useVToast.ts +73 -0
  114. package/app/composables/useXATableColumns.ts +456 -0
  115. package/app/data/BillingStats.ts +65 -0
  116. package/app/data/SearchData.ts +58 -0
  117. package/app/data/TasksData.ts +101 -0
  118. package/app/data/dashboardData.ts +113 -0
  119. package/app/layouts/default.vue +171 -0
  120. package/app/layouts/legacy.vue +61 -0
  121. package/app/pages/playground/base.vue +498 -0
  122. package/app/pages/playground/blocks.vue +108 -0
  123. package/app/pages/playground/buttons.vue +237 -0
  124. package/app/pages/playground/cards.vue +326 -0
  125. package/app/pages/playground/charts.vue +338 -0
  126. package/app/pages/playground/dashboard.vue +315 -0
  127. package/app/pages/playground/formatters.vue +329 -0
  128. package/app/pages/playground/index.vue +109 -0
  129. package/app/pages/playground/layout.vue +159 -0
  130. package/app/pages/playground/modals.vue +606 -0
  131. package/app/pages/playground/states.vue +282 -0
  132. package/app/pages/playground/tables.vue +618 -0
  133. package/app/pages/test-layout.vue +10 -0
  134. package/nuxt.config.ts +12 -0
  135. package/package.json +71 -0
  136. 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>