feat(web): centralise Vietnamese price formatting across all pages
Create a single `currency.ts` utility with `formatPrice`, `formatVND`, `formatPricePerM2`, and `parseVND` to replace 9+ duplicated inline formatters. This fixes inconsistent decimal handling (1.5M was truncated to "1 triệu") and standardises price/m² display. Integrated across property cards, listing detail, dashboard, analytics, payments, pricing, and admin moderation pages with 19 new unit tests. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -13,15 +13,9 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from '@/components/ui/table';
|
||||
import { formatVND } from '@/lib/currency';
|
||||
import { useTransactions } from '@/lib/hooks/use-payments';
|
||||
|
||||
function formatVND(amount: string | number): string {
|
||||
const num = typeof amount === 'string' ? Number(amount) : amount;
|
||||
if (num >= 1_000_000_000) return `${(num / 1_000_000_000).toFixed(1)} tỷ đ`;
|
||||
if (num >= 1_000_000) return `${(num / 1_000_000).toFixed(0)} triệu đ`;
|
||||
return num.toLocaleString('vi-VN') + ' đ';
|
||||
}
|
||||
|
||||
const STATUS_LABELS: Record<string, { label: string; variant: 'default' | 'secondary' | 'destructive' | 'outline' }> = {
|
||||
PENDING: { label: 'Chờ xử lý', variant: 'secondary' },
|
||||
PROCESSING: { label: 'Đang xử lý', variant: 'secondary' },
|
||||
@@ -66,14 +60,14 @@ export default function PaymentsPage() {
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold">Thanh toán</h1>
|
||||
<h1 className="text-2xl font-bold sm:text-3xl">Thanh toán</h1>
|
||||
<p className="mt-2 text-muted-foreground">
|
||||
Lịch sử giao dịch và quản lý thanh toán
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Summary cards */}
|
||||
<div className="grid gap-4 sm:grid-cols-3">
|
||||
<div className="grid grid-cols-2 gap-4 sm:grid-cols-3">
|
||||
<Card>
|
||||
<CardHeader className="pb-2">
|
||||
<CardDescription>Tổng giao dịch</CardDescription>
|
||||
@@ -104,12 +98,12 @@ export default function PaymentsPage() {
|
||||
|
||||
{/* Transactions table */}
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between">
|
||||
<CardHeader className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
||||
<div>
|
||||
<CardTitle className="text-lg">Lịch sử giao dịch</CardTitle>
|
||||
<CardDescription>Tất cả giao dịch thanh toán của bạn</CardDescription>
|
||||
</div>
|
||||
<div className="w-40">
|
||||
<div className="w-full sm:w-40">
|
||||
<Select
|
||||
value={statusFilter}
|
||||
onChange={(e) => {
|
||||
|
||||
Reference in New Issue
Block a user