Files
goodgo-platform/apps/web/components/khu-cong-nghiep/park-card.tsx
Ho Ngoc Hai 7ce651fce5 feat(web): add khu-cong-nghiep, chuyen-nhuong, and reports pages
Add three new frontend page sections:
- Industrial parks (khu-cong-nghiep): listing, detail, filter bar
- Transfer listings (chuyen-nhuong): search, category tabs, detail
- AI reports dashboard: list, create, viewer with TOC

Includes components, API clients, hooks, server helpers, i18n keys,
navigation links in public and dashboard layouts, and lint fixes.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-16 09:07:45 +07:00

106 lines
4.2 KiB
TypeScript

'use client';
import { Building2, MapPin } from 'lucide-react';
import { Badge } from '@/components/ui/badge';
import { Card, CardContent } from '@/components/ui/card';
import { Link } from '@/i18n/navigation';
import { type IndustrialParkListItem, PARK_STATUS_COLORS, PARK_STATUS_LABELS, REGION_LABELS } from '@/lib/khu-cong-nghiep-api';
interface ParkCardProps {
park: IndustrialParkListItem;
}
export function ParkCard({ park }: ParkCardProps) {
const occupancyColor =
park.occupancyRate >= 90 ? 'text-red-600' :
park.occupancyRate >= 70 ? 'text-amber-600' :
'text-green-600';
return (
<Link href={`/khu-cong-nghiep/${park.slug}`}>
<Card className="group h-full transition-shadow hover:shadow-lg">
<CardContent className="p-5">
{/* Header */}
<div className="mb-3 flex items-start justify-between gap-2">
<div className="min-w-0 flex-1">
<h3 className="line-clamp-1 font-semibold text-foreground group-hover:text-primary">
{park.name}
</h3>
{park.nameEn && (
<p className="line-clamp-1 text-xs text-muted-foreground">{park.nameEn}</p>
)}
</div>
<Badge className={PARK_STATUS_COLORS[park.status]} variant="secondary">
{PARK_STATUS_LABELS[park.status]}
</Badge>
</div>
{/* Location */}
<div className="mb-3 flex items-center gap-1 text-sm text-muted-foreground">
<MapPin className="h-3.5 w-3.5 shrink-0" />
<span className="line-clamp-1">{park.province} &middot; {REGION_LABELS[park.region]}</span>
</div>
{/* Stats grid */}
<div className="mb-3 grid grid-cols-2 gap-3">
<div className="rounded-md bg-muted p-2">
<div className="text-xs text-muted-foreground">Diện tích</div>
<div className="font-semibold">{park.totalAreaHa.toLocaleString()} ha</div>
</div>
<div className="rounded-md bg-muted p-2">
<div className="text-xs text-muted-foreground">Lấp đy</div>
<div className={`font-semibold ${occupancyColor}`}>{park.occupancyRate}%</div>
</div>
<div className="rounded-md bg-muted p-2">
<div className="text-xs text-muted-foreground">Còn trống</div>
<div className="font-semibold">{park.remainingAreaHa.toLocaleString()} ha</div>
</div>
<div className="rounded-md bg-muted p-2">
<div className="text-xs text-muted-foreground">Doanh nghiệp</div>
<div className="font-semibold">{park.tenantCount}</div>
</div>
</div>
{/* Rent info */}
{park.landRentUsdM2Year && (
<div className="mb-3 flex items-center gap-4 text-sm">
<div>
<span className="text-muted-foreground">Thuê đt: </span>
<span className="font-medium text-primary">${park.landRentUsdM2Year}/m²/năm</span>
</div>
{park.rbfRentUsdM2Month && (
<div>
<span className="text-muted-foreground">NX: </span>
<span className="font-medium">${park.rbfRentUsdM2Month}/m²/th</span>
</div>
)}
</div>
)}
{/* Industries */}
<div className="flex flex-wrap gap-1">
{park.targetIndustries.slice(0, 3).map((industry) => (
<Badge key={industry} variant="outline" className="text-xs">
{industry}
</Badge>
))}
{park.targetIndustries.length > 3 && (
<Badge variant="outline" className="text-xs">
+{park.targetIndustries.length - 3}
</Badge>
)}
</div>
{/* Footer */}
<div className="mt-3 flex items-center gap-3 border-t pt-3 text-xs text-muted-foreground">
<div className="flex items-center gap-1">
<Building2 className="h-3 w-3" />
{park.developer}
</div>
</div>
</CardContent>
</Card>
</Link>
);
}