Seed: real-estate template (18 files)
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
import { useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { Search, Bed, Bath, Maximize, MapPin, Heart, Home } from "lucide-react";
|
||||
import Header from "@/components/Header";
|
||||
import Footer from "@/components/Footer";
|
||||
|
||||
const listings = [
|
||||
{ id: 1, name: "Skyline Penthouse", price: "$2,100,000", beds: "3", baths: "3", sqft: "2,800", addr: "200 Central Park W, NYC", status: "For Sale", gradient: "from-emerald-800/40 to-stone-700/40" },
|
||||
{ id: 2, name: "Harbor View Loft", price: "$3,800/mo", beds: "2", baths: "2", sqft: "1,600", addr: "15 Harbor Ln, Boston", status: "For Rent", gradient: "from-stone-700/40 to-amber-800/40" },
|
||||
{ id: 3, name: "Sunset Ridge Estate", price: "$3,950,000", beds: "5", baths: "4", sqft: "5,200", addr: "88 Ridge Rd, Malibu", status: "For Sale", gradient: "from-amber-800/40 to-emerald-900/40" },
|
||||
{ id: 4, name: "Maple Grove House", price: "$780,000", beds: "4", baths: "3", sqft: "3,000", addr: "22 Maple St, Denver", status: "For Sale", gradient: "from-emerald-900/40 to-stone-800/40" },
|
||||
{ id: 5, name: "Urban Studio Plus", price: "$2,200/mo", beds: "1", baths: "1", sqft: "850", addr: "45 Market St, SF", status: "For Rent", gradient: "from-stone-800/40 to-emerald-800/40" },
|
||||
{ id: 6, name: "Colonial Revival", price: "$1,250,000", beds: "5", baths: "4", sqft: "4,100", addr: "10 Elm Ave, Greenwich", status: "For Sale", gradient: "from-emerald-700/40 to-amber-900/40" },
|
||||
];
|
||||
|
||||
export default function PropertiesPage() {
|
||||
const [liked, setLiked] = useState<Set<number>>(new Set());
|
||||
|
||||
const toggleLike = (id: number) => {
|
||||
setLiked((prev) => {
|
||||
const next = new Set(prev);
|
||||
next.has(id) ? next.delete(id) : next.add(id);
|
||||
return next;
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background text-foreground antialiased">
|
||||
<Header />
|
||||
|
||||
{/* ── HERO ── */}
|
||||
<section className="pt-32 pb-12 bg-gradient-to-b from-stone-950 via-emerald-950/20 to-background">
|
||||
<div className="mx-auto max-w-7xl px-6 text-center animate-fade-up">
|
||||
<Badge className="bg-emerald-600/20 text-emerald-400 border-emerald-600/30 mb-4">Our Listings</Badge>
|
||||
<h1 className="text-4xl sm:text-5xl font-bold text-white mb-4">Browse Properties</h1>
|
||||
<p className="text-stone-400 max-w-lg mx-auto">Find the perfect property from our extensive portfolio of premium listings.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── FILTERS ── */}
|
||||
<section className="py-8 bg-background border-b border-stone-200 dark:border-stone-800 sticky top-[72px] z-40 backdrop-blur-xl bg-background/90">
|
||||
<div className="mx-auto max-w-7xl px-6">
|
||||
<div className="grid grid-cols-2 md:grid-cols-5 gap-3">
|
||||
<Input placeholder="Location..." className="rounded-xl" />
|
||||
<Select>
|
||||
<SelectTrigger className="rounded-xl"><SelectValue placeholder="Property Type" /></SelectTrigger>
|
||||
<SelectContent>
|
||||
{["House", "Apartment", "Condo", "Villa"].map((t) => <SelectItem key={t} value={t.toLowerCase()}>{t}</SelectItem>)}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Select>
|
||||
<SelectTrigger className="rounded-xl"><SelectValue placeholder="Price Range" /></SelectTrigger>
|
||||
<SelectContent>
|
||||
{["$0-$250K", "$250K-$500K", "$500K-$1M", "$1M+"].map((t) => <SelectItem key={t} value={t}>{t}</SelectItem>)}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Select>
|
||||
<SelectTrigger className="rounded-xl"><SelectValue placeholder="Bedrooms" /></SelectTrigger>
|
||||
<SelectContent>
|
||||
{["1+", "2+", "3+", "4+", "5+"].map((t) => <SelectItem key={t} value={t}>{t} Beds</SelectItem>)}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Button className="bg-emerald-600 hover:bg-emerald-700 text-white rounded-xl active:scale-[0.97] transition-all">
|
||||
<Search className="h-4 w-4 mr-2" />Search
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── GRID ── */}
|
||||
<section className="py-16 bg-background">
|
||||
<div className="mx-auto max-w-7xl px-6">
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
{listings.map((p, i) => (
|
||||
<Card key={p.id} className="overflow-hidden border-stone-200 dark:border-stone-800 bg-white dark:bg-stone-900/50 backdrop-blur rounded-2xl shadow-md hover:shadow-xl hover:-translate-y-1 transition-all duration-300 group animate-fade-up" style={{ animationDelay: `\${i * 80}ms` }}>
|
||||
<div className={`h-56 bg-gradient-to-br \${p.gradient} flex items-center justify-center relative`}>
|
||||
<Home className="h-12 w-12 text-white/20" />
|
||||
<Badge className="absolute top-4 left-4 bg-emerald-600 text-white border-0">{p.status}</Badge>
|
||||
<button onClick={() => toggleLike(p.id)} className={`absolute top-4 right-4 p-2 rounded-full backdrop-blur-sm transition-all \${liked.has(p.id) ? "bg-red-500/20 text-red-400" : "bg-white/10 text-white/60 hover:text-red-400"}`}>
|
||||
<Heart className={`h-4 w-4 \${liked.has(p.id) ? "fill-current" : ""}`} />
|
||||
</button>
|
||||
</div>
|
||||
<CardContent className="p-5">
|
||||
<div className="text-2xl font-bold text-emerald-600">{p.price}</div>
|
||||
<Link to={`/properties/\${p.id}`} className="text-base font-semibold text-stone-800 dark:text-white mt-1 block hover:text-emerald-600 transition-colors">{p.name}</Link>
|
||||
<div className="flex items-center gap-1 text-sm text-stone-500 dark:text-stone-400 mt-1"><MapPin className="h-3 w-3" />{p.addr}</div>
|
||||
<div className="flex items-center gap-4 mt-3 pt-3 border-t border-stone-100 dark:border-stone-800 text-sm text-stone-500 dark:text-stone-400">
|
||||
<span className="flex items-center gap-1"><Bed className="h-4 w-4" />{p.beds}</span>
|
||||
<span className="flex items-center gap-1"><Bath className="h-4 w-4" />{p.baths}</span>
|
||||
<span className="flex items-center gap-1"><Maximize className="h-4 w-4" />{p.sqft} sqft</span>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="text-center mt-12">
|
||||
<Button variant="outline" className="rounded-full px-8 border-emerald-600 text-emerald-600 hover:bg-emerald-600 hover:text-white transition-all">
|
||||
Load More Properties
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user