199 lines
13 KiB
TypeScript
199 lines
13 KiB
TypeScript
"use client";
|
|
|
|
import { useState, useRef } from "react";
|
|
import Link from "next/link";
|
|
import { properties } from "@/data/properties";
|
|
|
|
type Category = "Apartments" | "Premium Homes" | "Luxury";
|
|
|
|
interface PropertiesProps {
|
|
layout?: "slider" | "grid";
|
|
}
|
|
|
|
export default function Properties({ layout = "slider" }: PropertiesProps) {
|
|
const [activeTab, setActiveTab] = useState<Category | "All">("All");
|
|
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
|
|
|
const filteredProperties = activeTab === "All"
|
|
? properties
|
|
: properties.filter((property) => property.category === activeTab);
|
|
|
|
const scroll = (direction: "left" | "right") => {
|
|
if (scrollContainerRef.current) {
|
|
const container = scrollContainerRef.current;
|
|
const scrollAmount = direction === "left" ? -400 : 400;
|
|
container.scrollBy({ left: scrollAmount, behavior: "smooth" });
|
|
}
|
|
};
|
|
|
|
return (
|
|
<section id="projects" className="py-24 bg-white dark:bg-black overflow-hidden">
|
|
<div className="max-w-7xl mx-auto px-6">
|
|
<div className="text-center mb-12">
|
|
<h2 className="text-3xl md:text-4xl font-bold tracking-tight text-foreground mb-4">
|
|
Our Signature Projects
|
|
</h2>
|
|
<p className="text-lg text-gray-600 dark:text-gray-400">
|
|
Discover a home that complements your lifestyle.
|
|
</p>
|
|
</div>
|
|
|
|
{/* Tabs */}
|
|
<div className="flex justify-center mb-12">
|
|
<div className="inline-flex bg-secondary dark:bg-gray-800 p-1 rounded-full flex-wrap justify-center gap-1">
|
|
{(["All", "Apartments", "Premium Homes", "Luxury"] as const).map((category) => (
|
|
<button
|
|
key={category}
|
|
onClick={() => setActiveTab(category)}
|
|
className={`px-4 py-2.5 rounded-full text-sm font-medium transition-all duration-300 ${activeTab === category
|
|
? "bg-white dark:bg-gray-700 text-foreground shadow-sm"
|
|
: "text-gray-500 dark:text-gray-400 hover:text-foreground"
|
|
}`}
|
|
>
|
|
{category}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{layout === "slider" ? (
|
|
/* Slider Layout - 3 cards for All, 1 card for specific tabs */
|
|
<div className="relative">
|
|
{/* Navigation Buttons */}
|
|
<button
|
|
onClick={() => scroll("left")}
|
|
className="absolute left-0 md:left-4 top-1/2 -translate-y-1/2 z-10 bg-white dark:bg-gray-800 p-3 rounded-full shadow-lg hover:scale-110 transition-all duration-300"
|
|
aria-label="Previous project"
|
|
>
|
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor" className="w-5 h-5 text-foreground">
|
|
<path strokeLinecap="round" strokeLinejoin="round" d="M15.75 19.5L8.25 12l7.5-7.5" />
|
|
</svg>
|
|
</button>
|
|
|
|
<button
|
|
onClick={() => scroll("right")}
|
|
className="absolute right-0 md:right-4 top-1/2 -translate-y-1/2 z-10 bg-white dark:bg-gray-800 p-3 rounded-full shadow-lg hover:scale-110 transition-all duration-300"
|
|
aria-label="Next project"
|
|
>
|
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor" className="w-5 h-5 text-foreground">
|
|
<path strokeLinecap="round" strokeLinejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" />
|
|
</svg>
|
|
</button>
|
|
|
|
{/* Scrollable Area */}
|
|
<div
|
|
ref={scrollContainerRef}
|
|
className={`flex gap-6 overflow-x-auto pb-8 snap-x snap-mandatory hide-scrollbar ${activeTab === "All" ? "px-4" : "px-4 md:px-16"
|
|
}`}
|
|
style={{ scrollbarWidth: 'none', msOverflowStyle: 'none' }}
|
|
>
|
|
{filteredProperties.map((property, index) => {
|
|
// Show only first card for specific tabs
|
|
if (activeTab !== "All" && index > 0) return null;
|
|
|
|
return (
|
|
<div
|
|
key={property.id}
|
|
className={activeTab === "All"
|
|
? "flex-shrink-0 snap-center w-full md:w-[calc(50%-12px)] lg:w-[calc(33.333%-16px)]"
|
|
: "flex-shrink-0 w-full max-w-md mx-auto snap-center"
|
|
}
|
|
>
|
|
<Link
|
|
href={`/residential-real-estate/${property.slug}`}
|
|
className="group/card block bg-white dark:bg-gray-900 rounded-2xl overflow-hidden border border-gray-100 dark:border-gray-800 hover:border-gray-200 dark:hover:border-gray-700 shadow-lg hover:shadow-2xl transition-all duration-300 h-full flex flex-col"
|
|
>
|
|
{/* Image */}
|
|
<div className={activeTab === "All" ? "h-64 w-full relative overflow-hidden" : "h-80 w-full relative overflow-hidden"}>
|
|
<div className={`absolute inset-0 ${property.image.startsWith('/') ? '' : property.image}`} />
|
|
{property.image.startsWith('/') && (
|
|
<img src={property.image} alt={property.title} className="w-full h-full object-cover transition-transform duration-500 group-hover/card:scale-110" />
|
|
)}
|
|
|
|
<div className="absolute top-4 left-4 bg-white/90 dark:bg-black/80 backdrop-blur-sm px-3 py-1 rounded-full text-xs font-semibold text-foreground uppercase tracking-wider">
|
|
{property.status}
|
|
</div>
|
|
<div className="absolute inset-0 bg-black/0 group-hover/card:bg-black/5 transition-colors duration-300" />
|
|
</div>
|
|
|
|
{/* Content */}
|
|
<div className={activeTab === "All" ? "p-6 flex flex-col flex-grow" : "p-8 flex flex-col flex-grow"}>
|
|
<div className={activeTab === "All" ? "flex items-center justify-between mb-2" : "flex items-center justify-between mb-3"}>
|
|
<span className={activeTab === "All"
|
|
? "text-xs font-medium text-primary bg-blue-50 dark:bg-blue-900/30 px-2 py-1 rounded-md"
|
|
: "text-sm font-medium text-primary bg-blue-50 dark:bg-blue-900/30 px-3 py-1.5 rounded-md"
|
|
}>
|
|
{property.location}
|
|
</span>
|
|
</div>
|
|
<h3 className={activeTab === "All" ? "text-xl font-bold text-foreground mb-2" : "text-2xl font-bold text-foreground mb-3"}>
|
|
{property.title}
|
|
</h3>
|
|
<p className={activeTab === "All"
|
|
? "text-gray-600 dark:text-gray-400 text-sm mb-6 flex-grow line-clamp-2"
|
|
: "text-gray-600 dark:text-gray-400 text-base mb-6 flex-grow line-clamp-3"
|
|
}>
|
|
{property.description}
|
|
</p>
|
|
|
|
<div className={activeTab === "All"
|
|
? "w-full py-3 text-center text-sm font-medium text-foreground border border-gray-200 dark:border-gray-700 rounded-xl group-hover/card:bg-foreground group-hover/card:text-white dark:group-hover/card:bg-white dark:group-hover/card:text-black transition-colors"
|
|
: "w-full py-3 text-center text-base font-medium text-foreground border-2 border-gray-200 dark:border-gray-700 rounded-xl group-hover/card:bg-foreground group-hover/card:text-white dark:group-hover/card:bg-white dark:group-hover/card:text-black transition-colors"
|
|
}>
|
|
View Details
|
|
</div>
|
|
</div>
|
|
</Link>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
) : (
|
|
/* Grid Layout */
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
|
{filteredProperties.map((property) => (
|
|
<Link
|
|
href={`/residential-real-estate/${property.slug}`}
|
|
key={property.id}
|
|
className="group bg-white dark:bg-gray-900 rounded-2xl overflow-hidden border border-gray-100 dark:border-gray-800 hover:border-gray-200 dark:hover:border-gray-700 shadow-sm hover:shadow-xl transition-all duration-300 flex flex-col"
|
|
>
|
|
{/* Image Placeholder */}
|
|
<div className={`h-64 w-full relative overflow-hidden`}>
|
|
<div className={`absolute inset-0 ${property.image.startsWith('/') ? '' : property.image}`} />
|
|
{property.image.startsWith('/') && (
|
|
<img src={property.image} alt={property.title} className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-110" />
|
|
)}
|
|
|
|
<div className="absolute top-4 left-4 bg-white/90 dark:bg-black/80 backdrop-blur-sm px-3 py-1 rounded-full text-xs font-semibold text-foreground uppercase tracking-wider">
|
|
{property.status}
|
|
</div>
|
|
<div className="absolute inset-0 bg-black/0 group-hover:bg-black/5 transition-colors duration-300" />
|
|
</div>
|
|
|
|
<div className="p-6 flex flex-col flex-grow">
|
|
<div className="flex items-center justify-between mb-2">
|
|
<span className="text-xs font-medium text-primary bg-blue-50 dark:bg-blue-900/30 px-2 py-1 rounded-md">
|
|
{property.location}
|
|
</span>
|
|
</div>
|
|
<h3 className="text-xl font-bold text-foreground mb-2">
|
|
{property.title}
|
|
</h3>
|
|
<p className="text-gray-600 dark:text-gray-400 text-sm mb-6 flex-grow line-clamp-2">
|
|
{property.description}
|
|
</p>
|
|
|
|
<div className="w-full py-3 text-center text-sm font-medium text-foreground border border-gray-200 dark:border-gray-700 rounded-xl group-hover:bg-foreground group-hover:text-white dark:group-hover:bg-white dark:group-hover:text-black transition-colors">
|
|
View Details
|
|
</div>
|
|
</div>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|