feat: add neighborhood detail workspace

This commit is contained in:
2026-06-24 13:40:24 +08:00
parent 6ca67e7555
commit ff6e41a6e5
6 changed files with 551 additions and 26 deletions

View File

@@ -69,6 +69,34 @@ export type NeighborhoodScore = {
available_units: number;
};
export type Neighborhood = {
neighborhood_id: string;
area_id: string;
area_name: string;
district: string;
name: string;
built_year: number | null;
property_type: string;
metro_distance_m: number | null;
school_quality: string | null;
notes: string;
};
export type NeighborhoodMonthlyMetric = {
neighborhood_id: string;
month: string;
transaction_count: number;
transaction_price_psm: number;
listing_count: number;
listing_price_psm: number;
rent_price_psm: number;
median_days_on_market: number;
available_units: number;
source: string;
ingestion_run_id: number | null;
raw_artifact_id: number | null;
};
export type WatchlistItem = {
watchlist_item_id: number;
neighborhood_id: string | null;
@@ -253,6 +281,13 @@ export type AreaDetail = {
neighborhood_scores: NeighborhoodScore[];
};
export type NeighborhoodDetail = {
profile: Neighborhood;
current_score: NeighborhoodScore | null;
monthly_metrics: NeighborhoodMonthlyMetric[];
watchlist_items: WatchlistItem[];
};
const API_BASE_URL =
process.env.NEXT_PUBLIC_API_BASE_URL?.replace(/\/$/, "") ?? "http://127.0.0.1:8080";
@@ -274,6 +309,15 @@ export async function fetchNeighborhoodScores(month: string): Promise<Neighborho
return fetchJson(`/api/v1/neighborhoods/scores?month=${encodeURIComponent(month)}`);
}
export async function fetchNeighborhoodDetail(
neighborhoodId: string,
month: string,
): Promise<NeighborhoodDetail> {
return fetchJson(
`/api/v1/neighborhoods/${encodeURIComponent(neighborhoodId)}/detail?month=${encodeURIComponent(month)}`,
);
}
export async function fetchWatchlistItems(): Promise<WatchlistItem[]> {
return fetchJson("/api/v1/watchlist");
}