refactor(web): dedup tỷ/triệu compact formatters (GOO-206)
- Add `formatCompact` as an exported alias for `formatPrice` in lib/currency.ts - Replace 5 inline copies of the tỷ/triệu compact formatter: - components/map/listing-map.tsx (local `formatPrice` fn) - components/agents/agent-profile-client.tsx (local `fmtVND` fn) - app/(dashboard)/dashboard/saved-searches/page.tsx (local `formatPrice` fn) - app/(public)/page.tsx (local `formatVnd` fn + `vndFmt` Intl instance) - components/listings/price-history-chart.tsx (local `formatMillions` + `priceToMillions`) All call sites now import from the canonical lib/currency module. PriceHistoryChart now stores raw VND in chart data (was: millions) so formatCompact emits correct tỷ/triệu labels using canonical thresholds. Pre-existing test failures in inquiry/lead/AVM specs are unrelated to this change. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -39,6 +39,7 @@ import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
|
||||
import { Link } from '@/i18n/navigation';
|
||||
import type { AgentPublicProfile, AgentReviewItem } from '@/lib/agents-api';
|
||||
import { formatCompact } from '@/lib/currency';
|
||||
import { shimmerBlurDataURL } from '@/lib/image-blur';
|
||||
import type { ListingDetail } from '@/lib/listings-api';
|
||||
|
||||
@@ -48,12 +49,6 @@ import type { ListingDetail } from '@/lib/listings-api';
|
||||
|
||||
const VND = new Intl.NumberFormat('vi-VN');
|
||||
|
||||
function fmtVND(value: string | number | bigint): string {
|
||||
const n = typeof value === 'bigint' ? Number(value) : Number(value);
|
||||
if (n >= 1_000_000_000) return `${(n / 1_000_000_000).toFixed(1)} tỷ`;
|
||||
if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(0)} tr`;
|
||||
return VND.format(n);
|
||||
}
|
||||
|
||||
function qualityLabel(score: number): string {
|
||||
if (score >= 80) return 'Xuất sắc';
|
||||
@@ -145,7 +140,7 @@ const listingColumns: DataTableColumn<ListingDetail>[] = [
|
||||
sortValue: (row) => Number(row.priceVND),
|
||||
cell: (row) => (
|
||||
<span className="text-xs font-semibold tabular-nums text-primary">
|
||||
{fmtVND(row.priceVND)}
|
||||
{formatCompact(row.priceVND)}
|
||||
</span>
|
||||
),
|
||||
width: '12%',
|
||||
@@ -160,7 +155,7 @@ const listingColumns: DataTableColumn<ListingDetail>[] = [
|
||||
cell: (row) =>
|
||||
row.pricePerM2 != null ? (
|
||||
<span className="text-xs tabular-nums text-foreground-muted">
|
||||
{fmtVND(row.pricePerM2)}
|
||||
{formatCompact(row.pricePerM2)}
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-xs text-foreground-dim">—</span>
|
||||
@@ -384,7 +379,7 @@ export function AgentProfileClient({
|
||||
/>
|
||||
<KpiCard
|
||||
label="Giá TB"
|
||||
value={avgPriceVND != null ? fmtVND(avgPriceVND) : '—'}
|
||||
value={avgPriceVND != null ? formatCompact(avgPriceVND) : '—'}
|
||||
icon={<BarChart2 className="h-4 w-4" />}
|
||||
footnote="Danh mục hiện tại"
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user