- Add proper Vietnamese diacritics to all valuation components (form, results, history) and their test assertions - Fix valuation API client to use /analytics/valuation endpoint - Return empty history gracefully (no server endpoint yet) Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
95 lines
2.6 KiB
TypeScript
95 lines
2.6 KiB
TypeScript
import { apiClient } from './api-client';
|
|
|
|
// ─── Types ──────────────────────────────────────────────
|
|
|
|
export interface ValuationRequest {
|
|
propertyType: string;
|
|
area: number;
|
|
district: string;
|
|
city: string;
|
|
bedrooms?: number;
|
|
bathrooms?: number;
|
|
floors?: number;
|
|
frontage?: number;
|
|
roadWidth?: number;
|
|
yearBuilt?: number;
|
|
hasLegalPaper?: boolean;
|
|
latitude?: number;
|
|
longitude?: number;
|
|
}
|
|
|
|
export interface ValuationComparable {
|
|
id: string;
|
|
title: string;
|
|
address: string;
|
|
district: string;
|
|
priceVND: string;
|
|
areaM2: number;
|
|
pricePerM2: number;
|
|
similarity: number;
|
|
latitude?: number;
|
|
longitude?: number;
|
|
}
|
|
|
|
export interface PriceDriver {
|
|
feature: string;
|
|
impact: number;
|
|
direction: 'positive' | 'negative';
|
|
}
|
|
|
|
export interface ValuationResult {
|
|
id: string;
|
|
estimatedPriceVND: number;
|
|
confidence: number;
|
|
pricePerM2: number;
|
|
priceRangeLow: number;
|
|
priceRangeHigh: number;
|
|
comparables: ValuationComparable[];
|
|
priceDrivers: PriceDriver[];
|
|
modelVersion: string;
|
|
createdAt: string;
|
|
}
|
|
|
|
export interface ValuationHistoryItem {
|
|
id: string;
|
|
propertyType: string;
|
|
district: string;
|
|
city: string;
|
|
area: number;
|
|
estimatedPriceVND: number;
|
|
confidence: number;
|
|
createdAt: string;
|
|
}
|
|
|
|
export interface ValuationHistoryResponse {
|
|
data: ValuationHistoryItem[];
|
|
total: number;
|
|
page: number;
|
|
limit: number;
|
|
}
|
|
|
|
// ─── API ────────────────────────────────────────────────
|
|
|
|
export const valuationApi = {
|
|
/** Request AVM estimate via GET /analytics/valuation */
|
|
predict: (data: ValuationRequest) => {
|
|
const params = new URLSearchParams();
|
|
if (data.latitude) params.set('latitude', String(data.latitude));
|
|
if (data.longitude) params.set('longitude', String(data.longitude));
|
|
if (data.area) params.set('areaM2', String(data.area));
|
|
if (data.propertyType) params.set('propertyType', data.propertyType);
|
|
const qs = params.toString();
|
|
return apiClient.get<ValuationResult>(`/analytics/valuation${qs ? `?${qs}` : ''}`);
|
|
},
|
|
|
|
/** History is not available server-side — return empty result */
|
|
getHistory: (_page = 1, _limit = 10): Promise<ValuationHistoryResponse> =>
|
|
Promise.resolve({ data: [], total: 0, page: _page, limit: _limit }),
|
|
|
|
getById: (id: string) =>
|
|
apiClient.get<ValuationResult>(`/analytics/valuation?propertyId=${id}`),
|
|
|
|
predictForListing: (listingId: string) =>
|
|
apiClient.get<ValuationResult>(`/analytics/valuation?propertyId=${listingId}`),
|
|
};
|