@stoker-platform/web-app 0.5.189 → 0.5.190

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/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # @stoker-platform/web-app
2
2
 
3
+ ## 0.5.190
4
+
5
+ ### Patch Changes
6
+
7
+ - feat: add chart currency option
8
+ - @stoker-platform/node-client@0.5.76
9
+ - @stoker-platform/utils@0.5.67
10
+ - @stoker-platform/web-client@0.5.78
11
+
3
12
  ## 0.5.189
4
13
 
5
14
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stoker-platform/web-app",
3
- "version": "0.5.189",
3
+ "version": "0.5.190",
4
4
  "type": "module",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "scripts": {
@@ -51,9 +51,9 @@
51
51
  "@radix-ui/react-tooltip": "^1.2.8",
52
52
  "@react-google-maps/api": "^2.20.8",
53
53
  "@sentry/react": "^10.56.0",
54
- "@stoker-platform/node-client": "0.5.75",
55
- "@stoker-platform/utils": "0.5.66",
56
- "@stoker-platform/web-client": "0.5.77",
54
+ "@stoker-platform/node-client": "0.5.76",
55
+ "@stoker-platform/utils": "0.5.67",
56
+ "@stoker-platform/web-client": "0.5.78",
57
57
  "@tanstack/react-table": "^8.21.3",
58
58
  "@types/react": "18.3.13",
59
59
  "@types/react-dom": "18.3.1",
@@ -140,8 +140,8 @@ export const DashboardChart = ({ chart, title, collection }: DashboardChartProps
140
140
  const existingInterval = chartData.find((item) => item.date === date)
141
141
  if (existingInterval) {
142
142
  existingInterval.metric1 += metric1
143
- if (existingInterval.metric2 && metric2) {
144
- existingInterval.metric2 += metric2
143
+ if (metric2) {
144
+ existingInterval.metric2 = (existingInterval.metric2 ?? 0) + metric2
145
145
  }
146
146
  } else {
147
147
  chartData.push({ date, metric1, metric2 })
@@ -171,8 +171,8 @@ export const DashboardChart = ({ chart, title, collection }: DashboardChartProps
171
171
  const existingInterval = chartData.find((item) => item.date === date)
172
172
  if (existingInterval) {
173
173
  existingInterval.metric1 += metric1
174
- if (existingInterval.metric2 && metric2) {
175
- existingInterval.metric2 += metric2
174
+ if (metric2) {
175
+ existingInterval.metric2 = (existingInterval.metric2 ?? 0) + metric2
176
176
  }
177
177
  } else {
178
178
  chartData.push({ date, metric1, metric2 })
@@ -246,6 +246,16 @@ export const DashboardChart = ({ chart, title, collection }: DashboardChartProps
246
246
  metricField2?.name ||
247
247
  "Total"
248
248
 
249
+ const hasMetric2 = !!(metricField2 || chart.formula2)
250
+
251
+ const currency = tryFunction(chart.currency)
252
+ const formatChartValue = (value: number) => {
253
+ if (currency) {
254
+ return `${currency}${value.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`
255
+ }
256
+ return value.toLocaleString()
257
+ }
258
+
249
259
  const chartConfig = {
250
260
  visitors: {
251
261
  label: metricTitle,
@@ -328,6 +338,31 @@ export const DashboardChart = ({ chart, title, collection }: DashboardChartProps
328
338
  }
329
339
  }}
330
340
  indicator="dot"
341
+ valueFormatter={
342
+ currency
343
+ ? (value) => formatChartValue(Number(value))
344
+ : undefined
345
+ }
346
+ footer={
347
+ hasMetric2
348
+ ? (payload) => {
349
+ const total = payload.reduce(
350
+ (sum, item) => sum + (Number(item.value) || 0),
351
+ 0,
352
+ )
353
+ return (
354
+ <div className="flex w-full justify-between gap-x-2 leading-none items-center">
355
+ <span className="text-muted-foreground">
356
+ Total
357
+ </span>
358
+ <span className="font-mono font-medium tabular-nums text-foreground">
359
+ {formatChartValue(total)}
360
+ </span>
361
+ </div>
362
+ )
363
+ }
364
+ : undefined
365
+ }
331
366
  />
332
367
  }
333
368
  />
@@ -339,7 +374,7 @@ export const DashboardChart = ({ chart, title, collection }: DashboardChartProps
339
374
  stackId="a"
340
375
  isAnimationActive={chart.animate ?? true}
341
376
  />
342
- {(metricField2 || chart.formula2) && (
377
+ {hasMetric2 && (
343
378
  <Area
344
379
  dataKey="metric2"
345
380
  type="natural"
package/src/List.tsx CHANGED
@@ -111,6 +111,7 @@ interface AreaMetricChartProps {
111
111
  timezone: string
112
112
  showMetric2: boolean
113
113
  showLegend: boolean
114
+ currency?: string
114
115
  }
115
116
 
116
117
  const AreaMetricChart = ({
@@ -120,7 +121,14 @@ const AreaMetricChart = ({
120
121
  timezone,
121
122
  showMetric2,
122
123
  showLegend,
124
+ currency,
123
125
  }: AreaMetricChartProps) => {
126
+ const formatChartValue = (value: number) => {
127
+ if (currency) {
128
+ return `${currency}${value.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`
129
+ }
130
+ return value.toLocaleString()
131
+ }
124
132
  const filteredData = useMemo(() => {
125
133
  return chartData?.filter((item) => {
126
134
  const date = new Date(item.date)
@@ -177,6 +185,7 @@ const AreaMetricChart = ({
177
185
  })
178
186
  }}
179
187
  indicator="dot"
188
+ valueFormatter={currency ? (value) => formatChartValue(Number(value)) : undefined}
180
189
  />
181
190
  }
182
191
  />
@@ -1413,8 +1422,8 @@ export function List({
1413
1422
  const existingInterval = chartData.find((item) => item.date === date)
1414
1423
  if (existingInterval) {
1415
1424
  existingInterval.metric1 += metric1
1416
- if (existingInterval.metric2 && metric2) {
1417
- existingInterval.metric2 += metric2
1425
+ if (metric2) {
1426
+ existingInterval.metric2 = (existingInterval.metric2 ?? 0) + metric2
1418
1427
  }
1419
1428
  } else {
1420
1429
  chartData.push({ date, metric1, metric2 })
@@ -1626,6 +1635,8 @@ export function List({
1626
1635
  },
1627
1636
  } satisfies ChartConfig
1628
1637
 
1638
+ const currency = tryFunction(metric.currency)
1639
+
1629
1640
  return (
1630
1641
  <div key={`metric-${index}`} className="grid gap-3 flex-1 min-w-0">
1631
1642
  <Card className="pt-0 w-full" key={`metric-${index}`}>
@@ -1675,6 +1686,7 @@ export function List({
1675
1686
  timezone={timezone}
1676
1687
  showMetric2={!!metricField2}
1677
1688
  showLegend={!!(metricField1 && metricField2)}
1689
+ currency={currency}
1678
1690
  />
1679
1691
  </CardContent>
1680
1692
  </div>
@@ -89,6 +89,8 @@ ${colorConfig
89
89
 
90
90
  const ChartTooltip = RechartsPrimitive.Tooltip
91
91
 
92
+ type ChartTooltipPayload = NonNullable<React.ComponentProps<typeof RechartsPrimitive.Tooltip>["payload"]>
93
+
92
94
  const ChartTooltipContent = React.forwardRef<
93
95
  HTMLDivElement,
94
96
  React.ComponentProps<typeof RechartsPrimitive.Tooltip> &
@@ -98,6 +100,8 @@ const ChartTooltipContent = React.forwardRef<
98
100
  indicator?: "line" | "dot" | "dashed"
99
101
  nameKey?: string
100
102
  labelKey?: string
103
+ footer?: React.ReactNode | ((payload: ChartTooltipPayload) => React.ReactNode)
104
+ valueFormatter?: (value: number | string) => React.ReactNode
101
105
  }
102
106
  >(
103
107
  (
@@ -115,6 +119,8 @@ const ChartTooltipContent = React.forwardRef<
115
119
  color,
116
120
  nameKey,
117
121
  labelKey,
122
+ footer,
123
+ valueFormatter,
118
124
  },
119
125
  ref,
120
126
  ) => {
@@ -213,9 +219,11 @@ const ChartTooltipContent = React.forwardRef<
213
219
  {itemConfig?.label || item.name}
214
220
  </span>
215
221
  </div>
216
- {item.value && (
222
+ {item.value !== undefined && item.value !== null && (
217
223
  <span className="font-mono font-medium tabular-nums text-foreground">
218
- {item.value.toLocaleString()}
224
+ {valueFormatter
225
+ ? valueFormatter(item.value as number | string)
226
+ : item.value.toLocaleString()}
219
227
  </span>
220
228
  )}
221
229
  </div>
@@ -225,6 +233,11 @@ const ChartTooltipContent = React.forwardRef<
225
233
  )
226
234
  })}
227
235
  </div>
236
+ {footer ? (
237
+ <div className="border-t border-border/50 pt-1.5">
238
+ {typeof footer === "function" ? footer(payload) : footer}
239
+ </div>
240
+ ) : null}
228
241
  </div>
229
242
  )
230
243
  },