feat: Translate Overview and Transactions pages
- Add multi-language support to Overview page - Add multi-language support to Transactions page - Translate stats cards, buttons, and filters - All UI text now supports ID/EN switching Remaining: Profile page only
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { useState, useEffect, useMemo } from "react"
|
||||
import { useLanguage } from "@/contexts/LanguageContext"
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
@@ -128,6 +129,7 @@ function formatYAxisValue(value: number): string {
|
||||
}
|
||||
|
||||
export function Overview() {
|
||||
const { t } = useLanguage()
|
||||
const [wallets, setWallets] = useState<Wallet[]>([])
|
||||
const [transactions, setTransactions] = useState<Transaction[]>([])
|
||||
const [exchangeRates, setExchangeRates] = useState<Record<string, number>>({})
|
||||
@@ -571,11 +573,11 @@ export function Overview() {
|
||||
<div className="w-full md:w-fit grid grid-cols-2 gap-3">
|
||||
<Button onClick={() => setWalletDialogOpen(true)}>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
Add Wallet
|
||||
{t.overview.addWallet}
|
||||
</Button>
|
||||
<Button variant="outline" onClick={() => setTransactionDialogOpen(true)}>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
Add Transaction
|
||||
{t.overview.addFirstTransaction}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -586,7 +588,7 @@ export function Overview() {
|
||||
<div className="grid gap-4 lg:grid-cols-3">
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Total Balance</CardTitle>
|
||||
<CardTitle className="text-sm font-medium">{t.overview.totalBalance}</CardTitle>
|
||||
<Wallet className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
@@ -594,14 +596,14 @@ export function Overview() {
|
||||
{formatLargeNumber(totals.totalBalance, 'IDR')}
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Across {wallets.length} wallets
|
||||
{t.overview.acrossWallets.replace('{count}', wallets.length.toString())}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Total Income</CardTitle>
|
||||
<CardTitle className="text-sm font-medium">{t.overview.totalIncome}</CardTitle>
|
||||
<TrendingUp className="h-4 w-4 text-[var(--color-primary)]" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
@@ -609,14 +611,14 @@ export function Overview() {
|
||||
{formatLargeNumber(totals.totalIncome, 'IDR')}
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{getDateRangeLabel(dateRange, customStartDate, customEndDate)} income
|
||||
{getDateRangeLabel(dateRange, customStartDate, customEndDate)} {t.overview.income}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Total Expense</CardTitle>
|
||||
<CardTitle className="text-sm font-medium">{t.overview.totalExpense}</CardTitle>
|
||||
<TrendingDown className="h-4 w-4 text-[var(--color-destructive)]" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
@@ -624,7 +626,7 @@ export function Overview() {
|
||||
{formatLargeNumber(totals.totalExpense, 'IDR')}
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{getDateRangeLabel(dateRange, customStartDate, customEndDate)} expense
|
||||
{getDateRangeLabel(dateRange, customStartDate, customEndDate)} {t.overview.expense}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -635,7 +637,7 @@ export function Overview() {
|
||||
{/* Wallet Breakdown */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Wallet Breakdown</CardTitle>
|
||||
<CardTitle>{t.overview.wallets}</CardTitle>
|
||||
<CardDescription>Balance distribution across wallets</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="px-0">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useState, useEffect, useMemo } from "react"
|
||||
import { useSearchParams } from "react-router-dom"
|
||||
import { toast } from "sonner"
|
||||
import { useLanguage } from "@/contexts/LanguageContext"
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Input } from "@/components/ui/input"
|
||||
@@ -64,6 +65,7 @@ interface Transaction {
|
||||
const API = "/api"
|
||||
|
||||
export function Transactions() {
|
||||
const { t } = useLanguage()
|
||||
const [searchParams] = useSearchParams()
|
||||
const [wallets, setWallets] = useState<Wallet[]>([])
|
||||
const [transactions, setTransactions] = useState<Transaction[]>([])
|
||||
@@ -264,7 +266,7 @@ export function Transactions() {
|
||||
<div className="space-y-4">
|
||||
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold tracking-tight">Transactions</h1>
|
||||
<h1 className="text-3xl font-bold tracking-tight">{t.transactions.title}</h1>
|
||||
<p className="text-muted-foreground">
|
||||
View and manage all your transactions
|
||||
</p>
|
||||
@@ -276,7 +278,7 @@ export function Transactions() {
|
||||
</Button>
|
||||
<Button onClick={() => setTransactionDialogOpen(true)}>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
Add Transaction
|
||||
{t.transactions.addTransaction}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -287,7 +289,7 @@ export function Transactions() {
|
||||
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Total Income</CardTitle>
|
||||
<CardTitle className="text-sm font-medium">{t.transactions.stats.totalIncome}</CardTitle>
|
||||
<TrendingUp className="h-4 w-4 text-[var(--color-primary)]" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
@@ -299,7 +301,7 @@ export function Transactions() {
|
||||
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Total Expense</CardTitle>
|
||||
<CardTitle className="text-sm font-medium">{t.transactions.stats.totalExpense}</CardTitle>
|
||||
<TrendingDown className="h-4 w-4 text-[var(--color-destructive)]" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
@@ -311,7 +313,7 @@ export function Transactions() {
|
||||
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Net Amount</CardTitle>
|
||||
<CardTitle className="text-sm font-medium">{t.transactions.stats.netAmount}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className={`text-2xl font-bold ${stats.netAmount >= 0 ? 'text-green-600' : 'text-red-600'}`}>
|
||||
@@ -326,7 +328,7 @@ export function Transactions() {
|
||||
<Card>
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<CardTitle className="text-base">Filters</CardTitle>
|
||||
<CardTitle className="text-base">{t.common.filter}</CardTitle>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
|
||||
Reference in New Issue
Block a user