feat: Translate Wallets page to multi-language

- Add useLanguage hook to Wallets page
- Translate all UI text (buttons, labels, table headers)
- Translate filter options and placeholders
- Translate delete confirmation dialog
- Support both Indonesian and English
This commit is contained in:
dwindown
2025-10-12 08:53:30 +07:00
parent 371b5e0a66
commit bfd009368a

View File

@@ -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 { Input } from "@/components/ui/input"
@@ -49,6 +50,7 @@ interface Wallet {
const API = "/api"
export function Wallets() {
const { t } = useLanguage()
const [wallets, setWallets] = useState<Wallet[]>([])
const [loading, setLoading] = useState(true)
const [searchTerm, setSearchTerm] = useState("")
@@ -165,7 +167,7 @@ export function Wallets() {
</Button>
<Button onClick={() => setWalletDialogOpen(true)}>
<Plus className="mr-2 h-4 w-4" />
Add Wallet
{t.wallets.addWallet}
</Button>
</div>
</div>
@@ -175,7 +177,7 @@ export function Wallets() {
<div className="grid gap-4 grid-cols-2 lg:grid-cols-4">
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Total Wallets</CardTitle>
<CardTitle className="text-sm font-medium">{t.wallets.title}</CardTitle>
<Wallet className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
@@ -185,7 +187,7 @@ export function Wallets() {
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Money Wallets</CardTitle>
<CardTitle className="text-sm font-medium">{t.wallets.moneyWallets}</CardTitle>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{stats.moneyWallets}</div>
@@ -194,7 +196,7 @@ export function Wallets() {
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Asset Wallets</CardTitle>
<CardTitle className="text-sm font-medium">{t.wallets.assetWallets}</CardTitle>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{stats.assetWallets}</div>
@@ -203,7 +205,7 @@ export function Wallets() {
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Currencies</CardTitle>
<CardTitle className="text-sm font-medium">{t.wallets.currency}</CardTitle>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{stats.currencyCount}</div>
@@ -216,12 +218,12 @@ export function Wallets() {
<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"
onClick={clearFilters}
className="h-8 text-xs"
className="h-7 px-2"
>
<X className="h-3 w-3 mr-1" />
Clear All
@@ -233,11 +235,11 @@ export function Wallets() {
<div className="grid gap-3 md:grid-cols-3">
{/* Search */}
<div className="space-y-2">
<Label className="text-xs font-medium text-muted-foreground">Search Wallet</Label>
<Label className="text-xs font-medium text-muted-foreground">{t.common.search}</Label>
<div className="relative">
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
<Input
placeholder="Search wallets..."
placeholder={t.wallets.searchPlaceholder}
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="pl-9 h-9"
@@ -247,28 +249,28 @@ export function Wallets() {
{/* Type Filter */}
<div className="space-y-2">
<Label className="text-xs font-medium text-muted-foreground">Type</Label>
<Label className="text-xs font-medium text-muted-foreground">{t.wallets.type}</Label>
<Select value={kindFilter} onValueChange={setKindFilter}>
<SelectTrigger className="h-9">
<SelectValue placeholder="All types" />
<SelectValue placeholder={t.common.all} />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">All Types</SelectItem>
<SelectItem value="money">Money</SelectItem>
<SelectItem value="asset">Asset</SelectItem>
<SelectItem value="all">{t.common.all}</SelectItem>
<SelectItem value="money">{t.wallets.money}</SelectItem>
<SelectItem value="asset">{t.wallets.asset}</SelectItem>
</SelectContent>
</Select>
</div>
{/* Currency Filter */}
<div className="space-y-2">
<Label className="text-xs font-medium text-muted-foreground">Currency/Unit</Label>
<Label className="text-xs font-medium text-muted-foreground">{t.wallets.currency}/{t.wallets.unit}</Label>
<Select value={currencyFilter} onValueChange={setCurrencyFilter}>
<SelectTrigger className="h-9">
<SelectValue placeholder="All currencies" />
<SelectValue placeholder={t.common.all} />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">All Currencies/Units</SelectItem>
<SelectItem value="all">{t.common.all}</SelectItem>
{availableCurrencies.map(currency => (
<SelectItem key={currency} value={currency}>
{currency}
@@ -316,7 +318,7 @@ export function Wallets() {
{/* Wallets Table */}
<Card>
<CardHeader>
<CardTitle>Wallets ({filteredWallets.length})</CardTitle>
<CardTitle>{t.wallets.title} ({filteredWallets.length})</CardTitle>
<CardDescription>
{filteredWallets.length !== wallets.length
? `Filtered from ${wallets.length} total wallets`
@@ -328,11 +330,11 @@ export function Wallets() {
<Table>
<TableHeader>
<TableRow>
<TableHead>Name</TableHead>
<TableHead>Currency/Unit</TableHead>
<TableHead>Type</TableHead>
<TableHead>Created</TableHead>
<TableHead className="text-right">Actions</TableHead>
<TableHead>{t.wallets.name}</TableHead>
<TableHead>{t.wallets.currency}/{t.wallets.unit}</TableHead>
<TableHead>{t.wallets.type}</TableHead>
<TableHead>{t.common.date}</TableHead>
<TableHead className="text-right">{t.common.actions}</TableHead>
</TableRow>
</TableHeader>
<TableBody>
@@ -340,8 +342,8 @@ export function Wallets() {
<TableRow>
<TableCell colSpan={5} className="text-center py-8">
{filteredWallets.length !== wallets.length
? "No wallets match your filters"
: "No wallets found. Create your first wallet!"
? t.wallets.noWallets
: t.wallets.createFirst
}
</TableCell>
</TableRow>
@@ -380,15 +382,15 @@ export function Wallets() {
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Delete Wallet</AlertDialogTitle>
<AlertDialogTitle>{t.common.delete} {t.wallets.title}</AlertDialogTitle>
<AlertDialogDescription>
Are you sure you want to delete "{wallet.name}"? This action cannot be undone.
{t.wallets.deleteConfirm}
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogCancel>{t.common.cancel}</AlertDialogCancel>
<AlertDialogAction onClick={() => deleteWallet(wallet.id)}>
Delete
{t.common.delete}
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>