feat(web): add industrial compare page, listing search, and Mapbox park map

- Add interactive Mapbox map to /khu-cong-nghiep landing page with park markers and popups
- Build compare page at /khu-cong-nghiep/so-sanh with recharts RadarChart and detailed comparison table
- Build listing search page at /khu-cong-nghiep/cho-thue with filters for property type, lease type, area, and price
- Add IndustrialListing types, API client functions, and React Query hooks

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Ho Ngoc Hai
2026-04-16 12:40:35 +07:00
parent 28cdd92846
commit 5810f0be56
9 changed files with 964 additions and 1 deletions

View File

@@ -0,0 +1,11 @@
import type { Metadata } from 'next';
import { ListingSearchClient } from '@/components/khu-cong-nghiep/listing-search-client';
export const metadata: Metadata = {
title: 'Cho Thuê Bất Động Sản Công Nghiệp — GoodGo',
description: 'Tìm kiếm nhà xưởng, kho bãi, đất công nghiệp cho thuê tại các khu công nghiệp Việt Nam.',
};
export default function IndustrialListingsPage() {
return <ListingSearchClient />;
}

View File

@@ -1,9 +1,10 @@
'use client';
import { Factory } from 'lucide-react';
import { Factory, Map } from 'lucide-react';
import * as React from 'react';
import { ParkCard } from '@/components/khu-cong-nghiep/park-card';
import { ParkFilterBar } from '@/components/khu-cong-nghiep/park-filter-bar';
import { ParkMap } from '@/components/khu-cong-nghiep/park-map';
import { Button } from '@/components/ui/button';
import { useIndustrialParksSearch } from '@/lib/hooks/use-khu-cong-nghiep';
import type { SearchIndustrialParksParams } from '@/lib/khu-cong-nghiep-api';
@@ -15,6 +16,7 @@ export default function KhuCongNghiepPage() {
page: 1,
limit: PAGE_SIZE,
});
const [showMap, setShowMap] = React.useState(false);
const { data, isLoading, isError } = useIndustrialParksSearch(filters);
@@ -41,6 +43,26 @@ export default function KhuCongNghiepPage() {
{/* Filters */}
<ParkFilterBar params={filters} onChange={handleFilterChange} />
{/* Map toggle */}
<div className="mt-4 flex justify-end">
<Button
variant={showMap ? 'default' : 'outline'}
size="sm"
className="gap-2"
onClick={() => setShowMap(!showMap)}
>
<Map className="h-4 w-4" />
{showMap ? 'Ẩn bản đồ' : 'Xem bản đồ'}
</Button>
</div>
{/* Park Map */}
{showMap && data && data.data.length > 0 && (
<div className="mt-4">
<ParkMap parks={data.data} />
</div>
)}
{/* Results */}
<div className="mt-6">
{isLoading ? (

View File

@@ -0,0 +1,11 @@
import type { Metadata } from 'next';
import { ParkCompareClient } from '@/components/khu-cong-nghiep/park-compare-client';
export const metadata: Metadata = {
title: 'So Sánh Khu Công Nghiệp — GoodGo',
description: 'So sánh chi tiết giữa các khu công nghiệp tại Việt Nam: diện tích, giá thuê, tỷ lệ lấp đầy, hạ tầng và kết nối.',
};
export default function ParkComparePage() {
return <ParkCompareClient />;
}