@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,49 @@
1
+ <script setup lang="ts">
2
+ const LegendPosition = {
3
+ Top: "top",
4
+ Bottom: "bottom",
5
+ Left: "left",
6
+ Right: "right",
7
+ };
8
+
9
+ interface BarChartCategory {
10
+ name: string;
11
+ color: string;
12
+ }
13
+
14
+ defineProps<{
15
+ title: string;
16
+ totalValue: string;
17
+ data: Record<string, string | number>[];
18
+ categories: Record<string, BarChartCategory>;
19
+ yAxis: string[];
20
+ xFormatter: (i: number) => string;
21
+ yFormatter: (i: number) => string;
22
+ }>();
23
+ </script>
24
+ <template>
25
+ <UCard>
26
+ <div class="mb-8">
27
+ <div class="flex items-center justify-between">
28
+ <h3 class="text-base font-normal text-lg text-highlighted mb-1">{{ title }}</h3>
29
+ </div>
30
+ <div class="text-default font-medium dark:font-semibold text-2xl">{{ totalValue }}</div>
31
+ </div>
32
+ <BarChart
33
+ :data="data"
34
+ :height="328"
35
+ :categories="categories"
36
+ :y-axis="yAxis"
37
+ :group-padding="0"
38
+ :bar-padding="0.2"
39
+ :x-num-ticks="6"
40
+ :y-num-ticks="5"
41
+ :radius="4"
42
+ :x-formatter="xFormatter"
43
+ :y-formatter="yFormatter"
44
+ :legend-position="LegendPosition.Bottom"
45
+ :hide-legend="false"
46
+ :y-grid-line="false"
47
+ />
48
+ </UCard>
49
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <p class="text-xs uppercase tracking-wider text-muted font-medium">
3
+ <slot />
4
+ </p>
5
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <div class="font-semibold text-3xl text-highlighted tabular-nums">
3
+ <slot />
4
+ </div>
5
+ </template>
@@ -0,0 +1,41 @@
1
+ <script lang="ts" setup>
2
+ defineProps<{
3
+ metric: string
4
+ current: number | string
5
+ percentChange: number
6
+ }>()
7
+ </script>
8
+
9
+ <template>
10
+ <UCard>
11
+ <div class="space-y-2">
12
+ <VaCardSubtitle>
13
+ {{ metric }}
14
+ </VaCardSubtitle>
15
+
16
+ <div class="flex items-center justify-start gap-4">
17
+ <VaCardTitle>
18
+ {{ current }}
19
+ </VaCardTitle>
20
+
21
+ <div class="flex items-center flex-col items-start text-sm">
22
+ <div class="flex items-center gap-1">
23
+ <UIcon
24
+ :name="
25
+ percentChange > 0 ? 'i-lucide-arrow-up' : 'i-lucide-arrow-down'
26
+ "
27
+ :class="percentChange > 0 ? 'text-success' : 'text-danger'"
28
+ />
29
+ <div
30
+ :class="percentChange > 0 ? 'text-success' : 'text-danger'"
31
+ class="mr-1"
32
+ >
33
+ {{ percentChange }}%
34
+ </div>
35
+ </div>
36
+ <span class="text-dimmed">from previous month</span>
37
+ </div>
38
+ </div>
39
+ </div>
40
+ </UCard>
41
+ </template>
@@ -0,0 +1,135 @@
1
+ <script setup lang="ts">
2
+ import type { BulletLegendItemInterface, ChartData } from './types'
3
+
4
+ defineProps<{
5
+ name: string
6
+ value: number | string
7
+ }>()
8
+
9
+ const categories: Record<string, BulletLegendItemInterface> = {
10
+ users: {
11
+ name: 'Users',
12
+ color: '#00c16a'
13
+ }
14
+ }
15
+
16
+ const data: ChartData[] = [
17
+ {
18
+ date: 'Jan 23',
19
+ users: 234,
20
+ sessions: 1432,
21
+ churn: 5.2
22
+ },
23
+ {
24
+ date: 'Feb 23',
25
+ users: 431,
26
+ sessions: 1032,
27
+ churn: 4.3
28
+ },
29
+ {
30
+ date: 'Mar 23',
31
+ users: 543,
32
+ sessions: 1089,
33
+ churn: 5.1
34
+ },
35
+ {
36
+ date: 'Apr 23',
37
+ users: 489,
38
+ sessions: 988,
39
+ churn: 5.4
40
+ },
41
+ {
42
+ date: 'May 23',
43
+ users: 391,
44
+ sessions: 642,
45
+ churn: 5.5
46
+ },
47
+ {
48
+ date: 'Jun 23',
49
+ users: 582,
50
+ sessions: 786,
51
+ churn: 4.8
52
+ },
53
+ {
54
+ date: 'Jul 23',
55
+ users: 482,
56
+ sessions: 673,
57
+ churn: 4.5
58
+ },
59
+ {
60
+ date: 'Aug 23',
61
+ users: 389,
62
+ sessions: 761,
63
+ churn: 0
64
+ },
65
+ {
66
+ date: 'Sep 23',
67
+ users: 521,
68
+ sessions: 793,
69
+ churn: 0
70
+ },
71
+ {
72
+ date: 'Oct 23',
73
+ users: 434,
74
+ sessions: 543,
75
+ churn: 0
76
+ },
77
+ {
78
+ date: 'Nov 23',
79
+ users: 332,
80
+ sessions: 678,
81
+ churn: 0
82
+ },
83
+ {
84
+ date: 'Dec 23',
85
+ users: 275,
86
+ sessions: 873,
87
+ churn: 0
88
+ }
89
+ ]
90
+ </script>
91
+
92
+ <template>
93
+ <UCard>
94
+ <VaCardHeader>
95
+ <VaCardSubtitle>
96
+ {{ name }}
97
+ </VaCardSubtitle>
98
+ <template #action>
99
+ <UButton
100
+ icon="i-lucide-ellipsis-vertical"
101
+ size="sm"
102
+ variant="subtle"
103
+ />
104
+ </template>
105
+ </VaCardHeader>
106
+ <div class="space-y-2">
107
+ <VaCardTitle>
108
+ {{ value }}
109
+ </VaCardTitle>
110
+ <h5 class="text-sm text-muted">
111
+ {{ name }}
112
+ </h5>
113
+ </div>
114
+ <div class="mt-6">
115
+ <AreaChart
116
+ :data="data"
117
+ :categories="categories"
118
+ :min-max-ticks-only="true"
119
+ :y-num-ticks="1"
120
+ :x-formatter="(i: number) => `${data![i]!.date}`"
121
+ :y-formatter="() => ''"
122
+ :hide-legend="true"
123
+ :hide-x-axis="true"
124
+ :height="80"
125
+ />
126
+ </div>
127
+
128
+ <div>
129
+ <div class="text-sm space-x-1">
130
+ <span class="text-success-600">+20% ($36)</span>
131
+ <span class="text-muted">&bull;</span><span class="text-muted">vs Last Months</span>
132
+ </div>
133
+ </div>
134
+ </UCard>
135
+ </template>
@@ -0,0 +1,26 @@
1
+ <script lang="ts" setup>
2
+ defineProps<{
3
+ title: string
4
+ text: string
5
+ }>()
6
+ </script>
7
+
8
+ <template>
9
+ <UCard
10
+ class="flex items-center relative pb-8"
11
+ variant="soft"
12
+ >
13
+ <div class="mb-16">
14
+ <slot />
15
+ </div>
16
+
17
+ <div class="space-y-1 absolute left-4 bottom-4 right-4">
18
+ <h3 class="font-semibold">
19
+ {{ title }}
20
+ </h3>
21
+ <p class="text-muted">
22
+ {{ text }}
23
+ </p>
24
+ </div>
25
+ </UCard>
26
+ </template>
@@ -0,0 +1,39 @@
1
+ <script lang="ts" setup>
2
+ defineProps<{
3
+ metric: string
4
+ current: number | string
5
+ percentChange: number
6
+ }>()
7
+ </script>
8
+
9
+ <template>
10
+ <UCard>
11
+ <div class="text-xs uppercase tracking-wider text-muted font-medium">
12
+ {{ metric }}
13
+ </div>
14
+
15
+ <div class="mt-2 flex items-center justify-start gap-6">
16
+ <p class="font-semibold text-3xl text-highlighted tracking-wide">
17
+ {{ current }}
18
+ </p>
19
+
20
+ <div class="flex items-center flex-col items-start text-sm">
21
+ <div class="flex items-center gap-1">
22
+ <UIcon
23
+ :name="
24
+ percentChange > 0 ? 'i-lucide-arrow-up' : 'i-lucide-arrow-down'
25
+ "
26
+ :class="percentChange > 0 ? 'text-emerald-500' : 'text-red-500'"
27
+ />
28
+ <div
29
+ :class="percentChange > 0 ? 'text-emerald-500' : 'text-red-500'"
30
+ class="mr-1"
31
+ >
32
+ {{ percentChange }}%
33
+ </div>
34
+ </div>
35
+ <span class="text-(--ui-text-dimmed)">from previous month</span>
36
+ </div>
37
+ </div>
38
+ </UCard>
39
+ </template>
@@ -0,0 +1,34 @@
1
+ <script setup lang="ts">
2
+ interface DashboardItem {
3
+ title: string
4
+ value: number | string
5
+ progress: number
6
+ }
7
+
8
+ defineProps<DashboardItem>()
9
+ </script>
10
+
11
+ <template>
12
+ <UCard
13
+ variant="subtle"
14
+ :ui="{ footer: 'sm:py-3 bg-elevated' }"
15
+ >
16
+ <div class="flex items-center gap-4">
17
+ <div class="transition-transform duration-300 group-hover:scale-105">
18
+ <ProgressCircle
19
+ :value="progress"
20
+ :size="60"
21
+ :stroke-width="5"
22
+ />
23
+ </div>
24
+ <div class="flex-1 space-y-1">
25
+ <div class="text-sm text-toned dark:text-muted">
26
+ {{ title }}
27
+ </div>
28
+ <p class="text-2xl text-highlighted font-semibold">
29
+ {{ value }}
30
+ </p>
31
+ </div>
32
+ </div>
33
+ </UCard>
34
+ </template>
@@ -0,0 +1,11 @@
1
+ export interface BulletLegendItemInterface {
2
+ name: string
3
+ color: string
4
+ }
5
+
6
+ export interface ChartData {
7
+ date: string
8
+ users: number
9
+ sessions: number
10
+ churn: number
11
+ }
@@ -0,0 +1,118 @@
1
+ <script lang="ts" setup>
2
+ import {
3
+ getDailyPerformanceData,
4
+ getWeeklyPerformanceData,
5
+ getMonthlyPerformanceData
6
+ } from '~/data/AppPerformance'
7
+
8
+ defineProps<{
9
+ categories: Record<string, BulletLegendItemInterface>
10
+ }>()
11
+
12
+ const isSettingsOpen = ref<boolean>(false)
13
+
14
+ function toggleSettings() {
15
+ isSettingsOpen.value = !isSettingsOpen.value
16
+ }
17
+
18
+ const dataViewOptions = [
19
+ {
20
+ label: 'Daily',
21
+ value: 'daily'
22
+ },
23
+ {
24
+ label: 'Weekly',
25
+ value: 'weekly'
26
+ },
27
+ {
28
+ label: 'Monthly',
29
+ value: 'monthly'
30
+ }
31
+ ]
32
+
33
+ const selectedDataView = ref('daily')
34
+
35
+ const performanceData = computed(() => {
36
+ switch (selectedDataView.value) {
37
+ case 'weekly':
38
+ return getWeeklyPerformanceData.value
39
+ case 'monthly':
40
+ return getMonthlyPerformanceData.value
41
+ case 'daily':
42
+ default:
43
+ return getDailyPerformanceData.value
44
+ }
45
+ })
46
+
47
+ const xFormatter = (i: number): string =>
48
+ String(performanceData.value[i]?.date ?? '')
49
+
50
+ function handleDataViewChange(value: string) {
51
+ console.log('Data view changed to:', value)
52
+ }
53
+ </script>
54
+
55
+ <template>
56
+ <UCard
57
+ :ui="{
58
+ body: 'sm:p-4 p-0'
59
+ }"
60
+ >
61
+ <template #header>
62
+ <div class="w-full flex items-center justify-between">
63
+ <h2 class="text-lg font-medium text-highlighted">
64
+ App Performance
65
+ </h2>
66
+ <UButton
67
+ variant="ghost"
68
+ :icon="`i-lucide-${!isSettingsOpen ? 'settings' : 'x'}`"
69
+ @click="toggleSettings"
70
+ />
71
+ </div>
72
+ </template>
73
+
74
+ <div
75
+ v-if="isSettingsOpen"
76
+ class="h-[304px] p-4"
77
+ >
78
+ <div class="w-full space-y-4">
79
+ <label class="block text-sm font-medium text-highlighted mb-2">
80
+ Settings
81
+ </label>
82
+ <USelect
83
+ v-model="selectedDataView"
84
+ :items="dataViewOptions"
85
+ placeholder="Select data view"
86
+ class="w-full focus:ring-0"
87
+ @update:model-value="handleDataViewChange"
88
+ />
89
+ <UButton
90
+ variant="soft"
91
+ class="w-full flex items-center justify-center"
92
+ label="Filter data"
93
+ @click="toggleSettings"
94
+ />
95
+ </div>
96
+ </div>
97
+
98
+ <div
99
+ v-if="!isSettingsOpen"
100
+ class="pt-2"
101
+ >
102
+ <BarChart
103
+ :data="performanceData"
104
+ :height="240"
105
+ y-label="Count"
106
+ :x-num-ticks="6"
107
+ :y-num-ticks="5"
108
+ :categories="categories"
109
+ :x-formatter="xFormatter"
110
+ :y-grid-line="false"
111
+ :radius="20"
112
+ :bar-padding="0.35"
113
+ :y-axis="['downloads', 'subscriptions']"
114
+ :legend-position="LegendPosition.TopRight"
115
+ />
116
+ </div>
117
+ </UCard>
118
+ </template>
@@ -0,0 +1,118 @@
1
+ <script lang="ts" setup>
2
+ import {
3
+ getDailyPerformanceData,
4
+ getWeeklyPerformanceData,
5
+ getMonthlyPerformanceData
6
+ } from '~/data/AppPerformance'
7
+
8
+ defineProps<{
9
+ categories: Record<string, BulletLegendItemInterface>
10
+ }>()
11
+
12
+ const isSettingsOpen = ref<boolean>(false)
13
+
14
+ function toggleSettings() {
15
+ isSettingsOpen.value = !isSettingsOpen.value
16
+ }
17
+
18
+ const dataViewOptions = [
19
+ {
20
+ label: 'Daily',
21
+ value: 'daily'
22
+ },
23
+ {
24
+ label: 'Weekly',
25
+ value: 'weekly'
26
+ },
27
+ {
28
+ label: 'Monthly',
29
+ value: 'monthly'
30
+ }
31
+ ]
32
+
33
+ const selectedDataView = ref('daily')
34
+
35
+ const performanceData = computed(() => {
36
+ switch (selectedDataView.value) {
37
+ case 'weekly':
38
+ return getWeeklyPerformanceData.value
39
+ case 'monthly':
40
+ return getMonthlyPerformanceData.value
41
+ case 'daily':
42
+ default:
43
+ return getDailyPerformanceData.value
44
+ }
45
+ })
46
+
47
+ const xFormatter = (i: number): string =>
48
+ String(performanceData.value[i]?.date ?? '')
49
+
50
+ function handleDataViewChange(value: string) {
51
+ console.log('Data view changed to:', value)
52
+ }
53
+ </script>
54
+
55
+ <template>
56
+ <UCard
57
+ :ui="{
58
+ body: 'sm:p-4 p-0'
59
+ }"
60
+ >
61
+ <template #header>
62
+ <div class="w-full flex items-center justify-between">
63
+ <h2 class="text-lg font-medium text-highlighted">
64
+ App Performance
65
+ </h2>
66
+ <UButton
67
+ variant="ghost"
68
+ :icon="`i-lucide-${!isSettingsOpen ? 'settings' : 'x'}`"
69
+ @click="toggleSettings"
70
+ />
71
+ </div>
72
+ </template>
73
+
74
+ <div
75
+ v-if="isSettingsOpen"
76
+ class="h-[304px] p-4"
77
+ >
78
+ <div class="w-full space-y-4">
79
+ <label class="block text-sm font-medium text-highlighted mb-2">
80
+ Settings
81
+ </label>
82
+ <USelect
83
+ v-model="selectedDataView"
84
+ :items="dataViewOptions"
85
+ placeholder="Select data view"
86
+ class="w-full focus:ring-0"
87
+ @update:model-value="handleDataViewChange"
88
+ />
89
+ <UButton
90
+ variant="soft"
91
+ class="w-full flex items-center justify-center"
92
+ label="Filter data"
93
+ @click="toggleSettings"
94
+ />
95
+ </div>
96
+ </div>
97
+
98
+ <div
99
+ v-if="!isSettingsOpen"
100
+ class="pt-2"
101
+ >
102
+ <BarChart
103
+ :data="performanceData"
104
+ :height="240"
105
+ y-label="Count"
106
+ :x-num-ticks="6"
107
+ :y-num-ticks="5"
108
+ :categories="categories"
109
+ :x-formatter="xFormatter"
110
+ :y-grid-line="false"
111
+ :radius="20"
112
+ :bar-padding="0.35"
113
+ :y-axis="['downloads', 'subscriptions']"
114
+ :legend-position="LegendPosition.TopRight"
115
+ />
116
+ </div>
117
+ </UCard>
118
+ </template>