@coursebuilder/analytics 1.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 (56) hide show
  1. package/LICENSE +21 -0
  2. package/dist/api/index.d.ts +158 -0
  3. package/dist/api/index.js +317 -0
  4. package/dist/api/index.js.map +1 -0
  5. package/dist/catalog.d.ts +14 -0
  6. package/dist/catalog.js +209 -0
  7. package/dist/catalog.js.map +1 -0
  8. package/dist/components/index.d.ts +172 -0
  9. package/dist/components/index.js +1258 -0
  10. package/dist/components/index.js.map +1 -0
  11. package/dist/engine.d.ts +20 -0
  12. package/dist/engine.js +350 -0
  13. package/dist/engine.js.map +1 -0
  14. package/dist/index.d.ts +3 -0
  15. package/dist/index.js +353 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/providers/database.d.ts +79 -0
  18. package/dist/providers/database.js +533 -0
  19. package/dist/providers/database.js.map +1 -0
  20. package/dist/providers/derived.d.ts +45 -0
  21. package/dist/providers/derived.js +32 -0
  22. package/dist/providers/derived.js.map +1 -0
  23. package/dist/providers/ga4.d.ts +43 -0
  24. package/dist/providers/ga4.js +220 -0
  25. package/dist/providers/ga4.js.map +1 -0
  26. package/dist/providers/index.d.ts +8 -0
  27. package/dist/providers/index.js +1239 -0
  28. package/dist/providers/index.js.map +1 -0
  29. package/dist/providers/mux.d.ts +103 -0
  30. package/dist/providers/mux.js +241 -0
  31. package/dist/providers/mux.js.map +1 -0
  32. package/dist/providers/survey.d.ts +102 -0
  33. package/dist/providers/survey.js +233 -0
  34. package/dist/providers/survey.js.map +1 -0
  35. package/dist/types.d.ts +303 -0
  36. package/dist/types.js +1 -0
  37. package/dist/types.js.map +1 -0
  38. package/package.json +101 -0
  39. package/src/api/catalog-handler.ts +321 -0
  40. package/src/api/index.ts +4 -0
  41. package/src/api/token-handler.ts +71 -0
  42. package/src/catalog.ts +223 -0
  43. package/src/components/country-chart.tsx +114 -0
  44. package/src/components/index.ts +5 -0
  45. package/src/components/omnibus-dashboard.tsx +1460 -0
  46. package/src/components/revenue-chart.tsx +251 -0
  47. package/src/components/use-chart-colors.ts +75 -0
  48. package/src/engine.ts +201 -0
  49. package/src/index.ts +7 -0
  50. package/src/providers/database.ts +795 -0
  51. package/src/providers/derived.ts +79 -0
  52. package/src/providers/ga4.ts +173 -0
  53. package/src/providers/index.ts +44 -0
  54. package/src/providers/mux.ts +438 -0
  55. package/src/providers/survey.ts +487 -0
  56. package/src/types.ts +333 -0
@@ -0,0 +1,114 @@
1
+ 'use client'
2
+
3
+ import React from 'react'
4
+ import {
5
+ Bar,
6
+ BarChart,
7
+ CartesianGrid,
8
+ ResponsiveContainer,
9
+ Tooltip,
10
+ XAxis,
11
+ YAxis,
12
+ } from 'recharts'
13
+
14
+ import { useChartColors } from './use-chart-colors'
15
+
16
+ interface CountryChartProps {
17
+ data: { country: string; revenue: number; count: number }[]
18
+ }
19
+
20
+ function countryFlag(code: string | null): string {
21
+ if (!code || code.length !== 2) return '🌍'
22
+ const offset = 0x1f1e6
23
+ const a = code.toUpperCase().charCodeAt(0) - 65 + offset
24
+ const b = code.toUpperCase().charCodeAt(1) - 65 + offset
25
+ return String.fromCodePoint(a, b)
26
+ }
27
+
28
+ function formatCurrency(value: number): string {
29
+ if (value >= 1000) return `$${(value / 1000).toFixed(1)}k`
30
+ return `$${value.toFixed(0)}`
31
+ }
32
+
33
+ function CustomTooltip({
34
+ active,
35
+ payload,
36
+ }: {
37
+ active?: boolean
38
+ payload?: {
39
+ value: number
40
+ payload: { country: string; count: number; revenue: number }
41
+ }[]
42
+ label?: string
43
+ }) {
44
+ if (!active || !payload?.length) return null
45
+ const d = payload[0]?.payload
46
+ if (!d) return null
47
+ return (
48
+ <div className="border-border/50 bg-card rounded-lg border px-3 py-2 shadow-xl">
49
+ <p className="text-foreground text-sm font-medium">
50
+ {countryFlag(d.country)} {d.country}
51
+ </p>
52
+ <p className="text-foreground text-lg font-bold tabular-nums">
53
+ $
54
+ {d.revenue.toLocaleString(undefined, {
55
+ minimumFractionDigits: 0,
56
+ maximumFractionDigits: 0,
57
+ })}
58
+ </p>
59
+ <p className="text-muted-foreground text-xs">{d.count} purchases</p>
60
+ </div>
61
+ )
62
+ }
63
+
64
+ export function CountryChart({ data }: CountryChartProps) {
65
+ const colors = useChartColors()
66
+ const chartData = data.slice(0, 10).map((d) => ({
67
+ ...d,
68
+ label: `${countryFlag(d.country)} ${d.country}`,
69
+ }))
70
+
71
+ return (
72
+ <div className="h-[280px] w-full">
73
+ <ResponsiveContainer width="100%" height="100%">
74
+ <BarChart
75
+ data={chartData}
76
+ layout="vertical"
77
+ margin={{ top: 4, right: 8, left: 4, bottom: 4 }}
78
+ >
79
+ <CartesianGrid
80
+ strokeDasharray="3 3"
81
+ stroke={colors.gridLine}
82
+ horizontal={false}
83
+ />
84
+ <XAxis
85
+ type="number"
86
+ tick={{ fill: colors.mutedForeground, fontSize: 11 }}
87
+ axisLine={{ stroke: colors.gridLine }}
88
+ tickLine={false}
89
+ tickFormatter={formatCurrency}
90
+ />
91
+ <YAxis
92
+ type="category"
93
+ dataKey="label"
94
+ tick={{ fill: colors.mutedForeground, fontSize: 12 }}
95
+ axisLine={false}
96
+ tickLine={false}
97
+ width={60}
98
+ />
99
+ <Tooltip
100
+ content={<CustomTooltip />}
101
+ cursor={{ fill: colors.hoverBg }}
102
+ />
103
+ <Bar
104
+ dataKey="revenue"
105
+ radius={[0, 4, 4, 0]}
106
+ maxBarSize={24}
107
+ fill="#22c55e"
108
+ fillOpacity={0.7}
109
+ />
110
+ </BarChart>
111
+ </ResponsiveContainer>
112
+ </div>
113
+ )
114
+ }
@@ -0,0 +1,5 @@
1
+ export { OmnibusDashboard } from './omnibus-dashboard'
2
+ export type { DashboardData, VideoDashboardData } from './omnibus-dashboard'
3
+ export { RevenueChart } from './revenue-chart'
4
+ export { CountryChart } from './country-chart'
5
+ export { useChartColors, type ChartColors } from './use-chart-colors'