feat(04-02): add locale prop and custom currency tooltips to chart components
- Add locale?: string prop to ExpenseBreakdown and AvailableBalance - Replace bare <Tooltip /> in ExpenseBreakdown with custom content renderer - Add Tooltip import and custom content renderer to AvailableBalance - Pass locale to formatCurrency in AvailableBalance center text - Tooltip styled with shadcn design tokens (bg-background, border-border/50, shadow-xl)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { PieChart, Pie, Cell, ResponsiveContainer } from 'recharts'
|
||||
import { PieChart, Pie, Cell, ResponsiveContainer, Tooltip } from 'recharts'
|
||||
import type { BudgetDetail } from '@/lib/api'
|
||||
import { formatCurrency } from '@/lib/format'
|
||||
import { palette, headerGradient, type CategoryType } from '@/lib/palette'
|
||||
@@ -8,9 +8,10 @@ import { cn } from '@/lib/utils'
|
||||
|
||||
interface Props {
|
||||
budget: BudgetDetail
|
||||
locale?: string
|
||||
}
|
||||
|
||||
export function AvailableBalance({ budget }: Props) {
|
||||
export function AvailableBalance({ budget, locale = 'en' }: Props) {
|
||||
const { t } = useTranslation()
|
||||
const { totals } = budget
|
||||
|
||||
@@ -48,11 +49,25 @@ export function AvailableBalance({ budget }: Props) {
|
||||
<Cell key={index} fill={palette[entry.categoryType]?.base ?? palette.carryover.base} />
|
||||
))}
|
||||
</Pie>
|
||||
<Tooltip
|
||||
content={({ active, payload }) => {
|
||||
if (!active || !payload?.length) return null
|
||||
const item = payload[0]
|
||||
return (
|
||||
<div className="rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl">
|
||||
<p className="font-medium text-foreground">{item.name}</p>
|
||||
<p className="font-mono tabular-nums text-muted-foreground">
|
||||
{formatCurrency(Number(item.value), budget.currency, locale)}
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</PieChart>
|
||||
</ResponsiveContainer>
|
||||
<div className="absolute inset-0 flex flex-col items-center justify-center">
|
||||
<span className={cn('text-3xl font-bold tabular-nums', available >= 0 ? 'text-success' : 'text-destructive')}>
|
||||
{formatCurrency(available, budget.currency)}
|
||||
{formatCurrency(available, budget.currency, locale)}
|
||||
</span>
|
||||
<span className="text-xs text-muted-foreground">{t('dashboard.available', 'Available')}</span>
|
||||
</div>
|
||||
|
||||
@@ -2,13 +2,15 @@ import { useTranslation } from 'react-i18next'
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { PieChart, Pie, Cell, ResponsiveContainer, Tooltip } from 'recharts'
|
||||
import type { BudgetDetail } from '@/lib/api'
|
||||
import { formatCurrency } from '@/lib/format'
|
||||
import { palette, headerGradient, type CategoryType } from '@/lib/palette'
|
||||
|
||||
interface Props {
|
||||
budget: BudgetDetail
|
||||
locale?: string
|
||||
}
|
||||
|
||||
export function ExpenseBreakdown({ budget }: Props) {
|
||||
export function ExpenseBreakdown({ budget, locale = 'en' }: Props) {
|
||||
const { t } = useTranslation()
|
||||
const expenses = budget.items
|
||||
.filter((i) => i.category_type === 'variable_expense' && i.actual_amount > 0)
|
||||
@@ -41,7 +43,20 @@ export function ExpenseBreakdown({ budget }: Props) {
|
||||
<Cell key={index} fill={palette[entry.categoryType]?.base ?? palette.carryover.base} />
|
||||
))}
|
||||
</Pie>
|
||||
<Tooltip />
|
||||
<Tooltip
|
||||
content={({ active, payload }) => {
|
||||
if (!active || !payload?.length) return null
|
||||
const item = payload[0]
|
||||
return (
|
||||
<div className="rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl">
|
||||
<p className="font-medium text-foreground">{item.name}</p>
|
||||
<p className="font-mono tabular-nums text-muted-foreground">
|
||||
{formatCurrency(Number(item.value), budget.currency, locale)}
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</PieChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user