|
3 | 3 | import { useEffect, useMemo, useState, type ReactElement } from "react" |
4 | 4 | import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" |
5 | 5 | import { ChartContainer, ChartTooltip, ChartTooltipContent } from "@/components/ui/chart" |
6 | | -import { BarChart, Bar, LineChart, Line, XAxis, YAxis, CartesianGrid } from "recharts" |
| 6 | +import { BarChart, Bar, LineChart, Line, XAxis, YAxis, CartesianGrid, Rectangle } from "recharts" |
7 | 7 | import { useTranslations } from "next-intl" |
8 | 8 | import { |
9 | 9 | Select, |
@@ -207,6 +207,39 @@ export default function DashboardPage() { |
207 | 207 | </div> |
208 | 208 | ) |
209 | 209 |
|
| 210 | + // Create a Bar shape function with dynamic rounded corners |
| 211 | + // Determine the topmost field with a value based on the data point, and set rounded corners for the corresponding Bar |
| 212 | + const createStackedBarShape = (dataKey: string, fill: string) => { |
| 213 | + // Bar order from bottom to top: completed -> inProgress -> pending -> failed |
| 214 | + const order = ["completed", "inProgress", "pending", "failed"] |
| 215 | + |
| 216 | + // eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 217 | + const ShapeComponent = (props: any) => { |
| 218 | + const { payload, ...rest } = props |
| 219 | + |
| 220 | + // Check the order from bottom to top, find the last field with a value |
| 221 | + let topDataKey: string | null = null |
| 222 | + if (payload) { |
| 223 | + for (let i = order.length - 1; i >= 0; i--) { |
| 224 | + const key = order[i] |
| 225 | + const value = payload[key as keyof typeof payload] |
| 226 | + if (typeof value === "number" && value > 0) { |
| 227 | + topDataKey = key |
| 228 | + break |
| 229 | + } |
| 230 | + } |
| 231 | + } |
| 232 | + |
| 233 | + // If the current Bar is the topmost field with a value, set rounded corners |
| 234 | + const radius: [number, number, number, number] = topDataKey === dataKey ? [4, 4, 0, 0] : [0, 0, 0, 0] |
| 235 | + |
| 236 | + return <Rectangle {...rest} fill={fill} radius={radius} /> |
| 237 | + } |
| 238 | + |
| 239 | + ShapeComponent.displayName = `StackedBarShape-${dataKey}` |
| 240 | + return ShapeComponent |
| 241 | + } |
| 242 | + |
210 | 243 | return ( |
211 | 244 | <div className="container mx-auto p-6 space-y-6"> |
212 | 245 | {/* Page header with title and time range selector */} |
@@ -313,28 +346,28 @@ export default function DashboardPage() { |
313 | 346 | stackId="a" |
314 | 347 | fill="#10b981" |
315 | 348 | name={t("completed")} |
316 | | - radius={[0, 0, 0, 0]} |
| 349 | + shape={createStackedBarShape("completed", "#10b981")} |
317 | 350 | /> |
318 | 351 | <Bar |
319 | 352 | dataKey="inProgress" |
320 | 353 | stackId="a" |
321 | 354 | fill="#3b82f6" |
322 | 355 | name={t("inProgress")} |
323 | | - radius={[0, 0, 0, 0]} |
| 356 | + shape={createStackedBarShape("inProgress", "#3b82f6")} |
324 | 357 | /> |
325 | 358 | <Bar |
326 | 359 | dataKey="pending" |
327 | 360 | stackId="a" |
328 | 361 | fill="#f59e0b" |
329 | 362 | name={t("pending")} |
330 | | - radius={[0, 0, 0, 0]} |
| 363 | + shape={createStackedBarShape("pending", "#f59e0b")} |
331 | 364 | /> |
332 | 365 | <Bar |
333 | 366 | dataKey="failed" |
334 | 367 | stackId="a" |
335 | 368 | fill="#ef4444" |
336 | 369 | name={t("failed")} |
337 | | - radius={[4, 4, 0, 0]} |
| 370 | + shape={createStackedBarShape("failed", "#ef4444")} |
338 | 371 | /> |
339 | 372 | </BarChart> |
340 | 373 | ) |
|
0 commit comments