Skip to content

Commit e0ca0e9

Browse files
Add PieChart Component and Adjust Design for Responsiveness, Remove Dark Mode Toggle (#66)
* ✨ feat: integrate owned cards management and enhance user experience in collection overview * ✨ feat: add percentage bar chart and enhance overview with owned cards data * ✨ feat: refactor PercentageBarChart component for improved readability and maintainability * ✨ feat: rename PercentageBarChart to BarChart and add footer support; introduce new PieChart component * ✨ feat: enhance BarChart and PieChart components with improved styling and animations; update Overview layout for better visual consistency * ✨ feat: temporarily disable ModeToggle component * ✨ feat: redesign Overview page layout for logout users
1 parent d7775f6 commit e0ca0e9

File tree

7 files changed

+263
-64
lines changed

7 files changed

+263
-64
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
'use client'
2+
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'
3+
import { type ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart'
4+
import { Bar, BarChart, CartesianGrid } from 'recharts'
5+
6+
//Example of a percentage bar chart configuration
7+
/* const chartData = [
8+
{ packName: "Pack1", percentage: 0.1, fill: "#FF5733" }, // Color aleatorio
9+
{ packName: "Pack2", percentage: 0.5, fill: "#33FF57" }, // Color aleatorio
10+
{ packName: "Pack3", percentage: 0.8, fill: "#3357FF" }, // Color aleatorio
11+
]
12+
13+
const chartConfig = {
14+
Pack1: {
15+
label: "Pack 1",
16+
color: "hsl(var(--chart-1))",
17+
},
18+
Pack2: {
19+
label: "Pack 2",
20+
color: "hsl(var(--chart-2))",
21+
},
22+
Pack3: {
23+
label: "Pack 3",
24+
color: "hsl(var(--chart-3))",
25+
},
26+
} satisfies ChartConfig */
27+
28+
interface PercentageBarChartProps {
29+
data: { packName: string; percentage: number; fill: string }[]
30+
config: ChartConfig
31+
footer?: string
32+
}
33+
34+
interface CustomTooltipContentProps {
35+
payload: { value: number; key: string }[]
36+
active: boolean
37+
}
38+
39+
const CustomTooltipContent = (props: CustomTooltipContentProps) => {
40+
const { payload, active } = props
41+
if (active && payload && payload.length) {
42+
const newPayload = payload.map((entry) => {
43+
return {
44+
...entry,
45+
value: `${entry.value * 100}%`,
46+
}
47+
})
48+
return <ChartTooltipContent {...props} payload={newPayload} />
49+
}
50+
return null
51+
}
52+
53+
export function BarChartComponent({ data, config, footer }: PercentageBarChartProps) {
54+
return (
55+
<Card className="border-2 border-solid border-gray-500 rounded-4xl">
56+
<CardHeader className="text-center text-balance">
57+
<CardTitle>Probability getting new card</CardTitle>
58+
</CardHeader>
59+
<CardContent>
60+
<ChartContainer config={config}>
61+
<BarChart accessibilityLayer data={data}>
62+
<CartesianGrid vertical={false} />
63+
<ChartTooltip cursor={false} content={<CustomTooltipContent payload={[]} active={false} />} />
64+
<Bar dataKey="percentage" strokeWidth={2} radius={8} />
65+
</BarChart>
66+
</ChartContainer>
67+
</CardContent>
68+
<CardFooter className="flex-col flex-1 items-center gap-2">{footer}</CardFooter>
69+
</Card>
70+
)
71+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
'use client'
2+
3+
import * as React from 'react'
4+
import { Label, Pie, PieChart } from 'recharts'
5+
6+
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'
7+
import { type ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart'
8+
9+
interface PieChartComponentProps {
10+
data: { packName: string; percentage: number; fill: string }[]
11+
config: ChartConfig
12+
title?: string
13+
description?: string
14+
footer?: string
15+
}
16+
17+
export function PieChartComponent({ data, config, title, description, footer }: PieChartComponentProps) {
18+
const totalPercentage = React.useMemo(() => {
19+
return data.reduce((acc, curr) => acc + curr.percentage, 0)
20+
}, [data])
21+
22+
return (
23+
<Card className="flex flex-col h-full border-2 border-solid border-gray-500 rounded-4xl">
24+
<CardHeader className="items-center pb-0 text-balance text-center">
25+
<CardTitle>{title}</CardTitle>
26+
<CardDescription>{description}</CardDescription>
27+
</CardHeader>
28+
<CardContent className="flex-1 pb-0">
29+
<ChartContainer config={config} className="mx-auto aspect-square max-h-[250px]">
30+
<PieChart>
31+
<ChartTooltip cursor={false} content={<ChartTooltipContent />} />
32+
<Pie data={data} dataKey="percentage" nameKey="packName" innerRadius={60} strokeWidth={5}>
33+
<Label
34+
content={({ viewBox }) => {
35+
if (viewBox && 'cx' in viewBox && 'cy' in viewBox) {
36+
return (
37+
<text x={viewBox.cx} y={viewBox.cy} textAnchor="middle" dominantBaseline="middle">
38+
<tspan x={viewBox.cx} y={viewBox.cy} className="fill-white text-3xl font-bold">
39+
{totalPercentage.toLocaleString()}
40+
</tspan>
41+
<tspan x={viewBox.cx} y={(viewBox.cy || 0) + 24} className="fill-white">
42+
Cards
43+
</tspan>
44+
</text>
45+
)
46+
}
47+
}}
48+
/>
49+
</Pie>
50+
</PieChart>
51+
</ChartContainer>
52+
</CardContent>
53+
<CardFooter className="flex-col gap-2 text-sm">
54+
<div className="flex items-center gap-2 font-medium leading-none">{footer}</div>
55+
</CardFooter>
56+
</Card>
57+
)
58+
}

frontend/src/components/ui/Header.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { ModeToggle } from '@/components/mode-toggle'
21
import { Button } from '@/components/ui/button'
32
import { NavigationMenu, NavigationMenuLink, NavigationMenuList } from '@/components/ui/navigation-menu'
43

@@ -100,7 +99,7 @@ export const Header: FC<Props> = ({ user, setUser }) => (
10099
</Dialog>
101100
)}
102101

103-
<ModeToggle />
102+
{/* <ModeToggle /> */}
104103
</div>
105104
</header>
106105
</>

frontend/src/components/ui/card.tsx

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,7 @@ import * as React from 'react'
33
import { cn } from '@/lib/utils'
44

55
const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(({ className, ...props }, ref) => (
6-
<div
7-
ref={ref}
8-
className={cn(
9-
'rounded-xl border border-neutral-200 bg-white text-neutral-950 shadow dark:border-neutral-800 dark:bg-neutral-950 dark:text-neutral-50',
10-
className,
11-
)}
12-
{...props}
13-
/>
6+
<div ref={ref} className={cn('rounded-xl border bg-white text-neutral-950 shadow dark:bg-neutral-950 dark:text-neutral-50', className)} {...props} />
147
))
158
Card.displayName = 'Card'
169

@@ -30,7 +23,7 @@ const CardDescription = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HT
3023
CardDescription.displayName = 'CardDescription'
3124

3225
const CardContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(({ className, ...props }, ref) => (
33-
<div ref={ref} className={cn('p-6 pt-0', className)} {...props} />
26+
<div ref={ref} className={cn('p-6 pt-0 content-center', className)} {...props} />
3427
))
3528
CardContent.displayName = 'CardContent'
3629

frontend/src/components/ui/chart.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ const ChartContainer = React.forwardRef<
4545
data-chart={chartId}
4646
ref={ref}
4747
className={cn(
48-
"flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none",
48+
"flex aspect-square justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-white/70 [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none",
4949
className,
5050
)}
5151
{...props}
@@ -179,16 +179,16 @@ const ChartTooltipContent = React.forwardRef<
179179
) : (
180180
!hideIndicator && (
181181
<div
182-
className={cn('shrink-0 rounded-[2px] border-[--color-border] bg-[--color-bg]', {
182+
className={cn('shrink-0 rounded-[2px] bg-[var(--color-bg)] border-[var(--color-border)]', {
183183
'h-2.5 w-2.5': indicator === 'dot',
184184
'w-1': indicator === 'line',
185185
'w-0 border-[1.5px] border-dashed bg-transparent': indicator === 'dashed',
186186
'my-0.5': nestLabel && indicator === 'dashed',
187187
})}
188188
style={
189189
{
190-
'--color-bg': indicatorColor,
191-
'--color-border': indicatorColor,
190+
'--color-bg': indicatorColor || '#EDC12A',
191+
'--color-border': indicatorColor || '#EDC12A',
192192
} as React.CSSProperties
193193
}
194194
/>

frontend/src/index.css

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,27 @@
66
@layer base {
77
:root {
88
--radius: 0.5rem;
9+
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
910
}
11+
1012
.dark body {
1113
background-color: #000;
1214
color: #fff;
1315
}
16+
17+
@keyframes fadeInUp {
18+
from {
19+
opacity: 0;
20+
transform: translateY(20px);
21+
}
22+
23+
to {
24+
opacity: 1;
25+
transform: translateY(0);
26+
}
27+
}
28+
29+
.fade-in-up {
30+
animation: fadeInUp 0.4s ease-out;
31+
}
1432
}

0 commit comments

Comments
 (0)