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:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user