sky-and-soil/src/components/CompareClient.tsx

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>
);
}