301 lines
20 KiB
TypeScript
301 lines
20 KiB
TypeScript
"use client";
|
|
|
|
import { useCompare } from "@/context/CompareContext";
|
|
import { properties } from "@/data/properties";
|
|
import Header from "@/components/Header";
|
|
import Footer from "@/components/Footer";
|
|
import InnerBanner from "@/components/InnerBanner";
|
|
import Image from "next/image";
|
|
import Link from "next/link";
|
|
import { useState } from "react";
|
|
|
|
export default function CompareClient() {
|
|
const { compareList, removeFromCompare, addToCompare } = useCompare();
|
|
const [showAddModal, setShowAddModal] = useState(false);
|
|
|
|
// Get properties not in compare list for adding
|
|
const availableProperties = properties.filter(
|
|
p => !compareList.find(c => c.id === p.id)
|
|
);
|
|
|
|
const handleAddProperty = (property: typeof properties[0]) => {
|
|
addToCompare(property);
|
|
setShowAddModal(false);
|
|
};
|
|
|
|
return (
|
|
<div className="min-h-screen bg-gray-50 dark:bg-black">
|
|
<Header />
|
|
|
|
<InnerBanner
|
|
title="Compare Properties"
|
|
subtitle="Compare up to 4 properties side by side to make an informed decision"
|
|
breadcrumbs={[
|
|
{ label: "Home", href: "/" },
|
|
{ label: "Properties", href: "/projects" },
|
|
{ label: "Compare" }
|
|
]}
|
|
/>
|
|
|
|
<div className="pb-12">
|
|
<div className="max-w-7xl mx-auto px-6 py-12">
|
|
|
|
{compareList.length < 2 ? (
|
|
<div className="text-center py-20">
|
|
<svg className="w-20 h-20 mx-auto text-gray-400 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
|
|
</svg>
|
|
<h3 className="text-xl font-semibold text-gray-700 dark:text-gray-300 mb-2">
|
|
Select at least 2 properties to compare
|
|
</h3>
|
|
<p className="text-gray-500 dark:text-gray-400 mb-6">
|
|
Go to the properties page and click the compare icon on the properties you want to compare
|
|
</p>
|
|
<Link
|
|
href="/projects"
|
|
className="inline-block px-6 py-3 bg-primary text-white rounded-lg hover:bg-blue-700 transition-colors font-semibold"
|
|
>
|
|
Browse Properties
|
|
</Link>
|
|
</div>
|
|
) : (
|
|
<div className="overflow-x-auto">
|
|
<table className="w-full border-collapse">
|
|
<thead>
|
|
<tr className="bg-white dark:bg-gray-900 sticky top-20 z-10 shadow-md">
|
|
<th className="p-4 text-left font-semibold text-foreground border-b-2 border-gray-200 dark:border-gray-800 w-48">
|
|
Features
|
|
</th>
|
|
{compareList.map((property) => (
|
|
<th key={property.id} className="p-4 border-b-2 border-gray-200 dark:border-gray-800 min-w-[280px]">
|
|
<div className="relative">
|
|
<button
|
|
onClick={() => removeFromCompare(property.id)}
|
|
className="absolute -top-2 -right-2 w-8 h-8 bg-red-500 text-white rounded-full flex items-center justify-center hover:bg-red-600 transition-colors shadow-md z-10"
|
|
aria-label="Remove from comparison"
|
|
>
|
|
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
|
</svg>
|
|
</button>
|
|
<div className="relative h-40 rounded-xl overflow-hidden mb-3">
|
|
<Image
|
|
src={property.image}
|
|
alt={property.title}
|
|
fill
|
|
className="object-cover"
|
|
/>
|
|
</div>
|
|
<h3 className="font-bold text-foreground text-lg mb-1">{property.title}</h3>
|
|
<p className="text-sm text-gray-600 dark:text-gray-400">{property.location}</p>
|
|
</div>
|
|
</th>
|
|
))}
|
|
{/* Add Property Slot */}
|
|
{compareList.length < 4 && (
|
|
<th className="p-4 border-b-2 border-gray-200 dark:border-gray-800 min-w-[280px]">
|
|
<button
|
|
onClick={() => setShowAddModal(true)}
|
|
className="w-full h-40 border-2 border-dashed border-gray-300 dark:border-gray-700 rounded-xl flex items-center justify-center hover:border-primary hover:bg-blue-50 dark:hover:bg-blue-900/20 transition-all group"
|
|
>
|
|
<div className="text-center">
|
|
<svg className="w-12 h-12 mx-auto text-gray-400 group-hover:text-primary mb-2 transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" />
|
|
</svg>
|
|
<p className="text-sm text-gray-500 dark:text-gray-400 group-hover:text-primary font-medium transition-colors">Add Property</p>
|
|
</div>
|
|
</button>
|
|
</th>
|
|
)}
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{/* Price */}
|
|
<tr className="bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-800">
|
|
<td className="p-4 font-semibold text-foreground">Price</td>
|
|
{compareList.map((property) => (
|
|
<td key={property.id} className="p-4 text-center">
|
|
<span className="text-2xl font-bold text-primary">{property.price}</span>
|
|
</td>
|
|
))}
|
|
{compareList.length < 4 && <td className="p-4"></td>}
|
|
</tr>
|
|
|
|
{/* Configuration */}
|
|
<tr className="bg-gray-50 dark:bg-gray-900/50 border-b border-gray-200 dark:border-gray-800">
|
|
<td className="p-4 font-semibold text-foreground">Configuration</td>
|
|
{compareList.map((property) => (
|
|
<td key={property.id} className="p-4 text-center text-foreground">{property.overview.bhk}</td>
|
|
))}
|
|
{compareList.length < 4 && <td className="p-4"></td>}
|
|
</tr>
|
|
|
|
{/* Area */}
|
|
<tr className="bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-800">
|
|
<td className="p-4 font-semibold text-foreground">Area</td>
|
|
{compareList.map((property) => (
|
|
<td key={property.id} className="p-4 text-center text-foreground">{property.overview.size}</td>
|
|
))}
|
|
{compareList.length < 4 && <td className="p-4"></td>}
|
|
</tr>
|
|
|
|
{/* Possession */}
|
|
<tr className="bg-gray-50 dark:bg-gray-900/50 border-b border-gray-200 dark:border-gray-800">
|
|
<td className="p-4 font-semibold text-foreground">Possession</td>
|
|
{compareList.map((property) => (
|
|
<td key={property.id} className="p-4 text-center text-foreground">{property.overview.possession}</td>
|
|
))}
|
|
{compareList.length < 4 && <td className="p-4"></td>}
|
|
</tr>
|
|
|
|
{/* Total Units */}
|
|
<tr className="bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-800">
|
|
<td className="p-4 font-semibold text-foreground">Total Units</td>
|
|
{compareList.map((property) => (
|
|
<td key={property.id} className="p-4 text-center text-foreground">{property.overview.totalUnits}</td>
|
|
))}
|
|
{compareList.length < 4 && <td className="p-4"></td>}
|
|
</tr>
|
|
|
|
{/* Category */}
|
|
<tr className="bg-gray-50 dark:bg-gray-900/50 border-b border-gray-200 dark:border-gray-800">
|
|
<td className="p-4 font-semibold text-foreground">Property Type</td>
|
|
{compareList.map((property) => (
|
|
<td key={property.id} className="p-4 text-center text-foreground">{property.category}</td>
|
|
))}
|
|
{compareList.length < 4 && <td className="p-4"></td>}
|
|
</tr>
|
|
|
|
{/* Status */}
|
|
<tr className="bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-800">
|
|
<td className="p-4 font-semibold text-foreground">Status</td>
|
|
{compareList.map((property) => (
|
|
<td key={property.id} className="p-4 text-center">
|
|
<span className={`inline-block px-3 py-1 rounded-full text-sm font-semibold ${property.status === "Sold Out"
|
|
? "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400"
|
|
: property.status === "New Launch"
|
|
? "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400"
|
|
: "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400"
|
|
}`}>
|
|
{property.status}
|
|
</span>
|
|
</td>
|
|
))}
|
|
{compareList.length < 4 && <td className="p-4"></td>}
|
|
</tr>
|
|
|
|
{/* Amenities Header */}
|
|
<tr className="bg-gray-100 dark:bg-gray-800">
|
|
<td colSpan={compareList.length + (compareList.length < 4 ? 2 : 1)} className="p-4 font-bold text-foreground text-lg">
|
|
Amenities
|
|
</td>
|
|
</tr>
|
|
|
|
{/* Amenities - Get all unique amenities */}
|
|
{Array.from(new Set(compareList.flatMap(p => p.amenities))).map((amenity, idx) => (
|
|
<tr key={idx} className={idx % 2 === 0 ? "bg-white dark:bg-gray-900" : "bg-gray-50 dark:bg-gray-900/50"}>
|
|
<td className="p-4 text-foreground">{amenity}</td>
|
|
{compareList.map((property) => (
|
|
<td key={property.id} className="p-4 text-center">
|
|
{property.amenities.includes(amenity) ? (
|
|
<svg className="w-6 h-6 text-green-500 mx-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
|
</svg>
|
|
) : (
|
|
<svg className="w-6 h-6 text-red-500 mx-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
|
</svg>
|
|
)}
|
|
</td>
|
|
))}
|
|
{compareList.length < 4 && <td className="p-4"></td>}
|
|
</tr>
|
|
))}
|
|
|
|
{/* View Details */}
|
|
<tr className="bg-white dark:bg-gray-900">
|
|
<td className="p-4 font-semibold text-foreground">Actions</td>
|
|
{compareList.map((property) => (
|
|
<td key={property.id} className="p-4 text-center">
|
|
<Link
|
|
href={`/properties/${property.id}`}
|
|
className="inline-block px-6 py-2 bg-primary text-white rounded-lg hover:bg-blue-700 transition-colors font-medium"
|
|
>
|
|
View Details
|
|
</Link>
|
|
</td>
|
|
))}
|
|
{compareList.length < 4 && <td className="p-4"></td>}
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Add Property Modal */}
|
|
{showAddModal && (
|
|
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/70 p-4">
|
|
<div className="bg-white dark:bg-gray-900 rounded-2xl max-w-4xl w-full max-h-[80vh] overflow-hidden shadow-2xl">
|
|
{/* Modal Header */}
|
|
<div className="flex items-center justify-between p-6 border-b border-gray-200 dark:border-gray-800">
|
|
<h2 className="text-2xl font-bold text-foreground">Add Property to Compare</h2>
|
|
<button
|
|
onClick={() => setShowAddModal(false)}
|
|
className="p-2 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg transition-colors"
|
|
>
|
|
<svg className="w-6 h-6 text-gray-600 dark:text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
{/* Modal Content */}
|
|
<div className="p-6 overflow-y-auto max-h-[calc(80vh-80px)]">
|
|
{availableProperties.length === 0 ? (
|
|
<div className="text-center py-12">
|
|
<p className="text-gray-600 dark:text-gray-400">All properties are already in comparison</p>
|
|
</div>
|
|
) : (
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
{availableProperties.map((property) => (
|
|
<button
|
|
key={property.id}
|
|
onClick={() => handleAddProperty(property)}
|
|
className="flex gap-4 p-4 border border-gray-200 dark:border-gray-800 rounded-xl hover:border-primary hover:bg-blue-50 dark:hover:bg-blue-900/20 transition-all text-left group"
|
|
>
|
|
<div className="relative w-24 h-24 flex-shrink-0 rounded-lg overflow-hidden">
|
|
<Image
|
|
src={property.image}
|
|
alt={property.title}
|
|
fill
|
|
className="object-cover"
|
|
/>
|
|
</div>
|
|
<div className="flex-1 min-w-0">
|
|
<h3 className="font-bold text-foreground mb-1 group-hover:text-primary transition-colors truncate">
|
|
{property.title}
|
|
</h3>
|
|
<p className="text-sm text-gray-600 dark:text-gray-400 mb-2 truncate">
|
|
{property.location}
|
|
</p>
|
|
<div className="flex items-center justify-between">
|
|
<span className="text-lg font-bold text-primary">{property.price}</span>
|
|
<span className="text-sm text-gray-500 dark:text-gray-400">{property.overview.bhk}</span>
|
|
</div>
|
|
</div>
|
|
</button>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<Footer />
|
|
</div>
|
|
);
|
|
}
|