98 lines
4.0 KiB
TypeScript
98 lines
4.0 KiB
TypeScript
"use client";
|
|
|
|
import { motion, AnimatePresence } from "framer-motion";
|
|
import { Search, Compass, TrendingUp, Hash } from "lucide-react";
|
|
import { MOCK_POSTS } from "@/lib/mock-data";
|
|
import { PostCard } from "@/components/feed/PostCard";
|
|
import { useState } from "react";
|
|
|
|
const TRENDING_TAGS = ["#streetwear", "#architecture", "#minimalism", "#neonLights", "#coffeeArt"];
|
|
const CATEGORIES = ["For You", "Photography", "Fashion", "Tech", "Travel", "Art"];
|
|
|
|
export default function ExplorePage() {
|
|
const [searchFocused, setSearchFocused] = useState(false);
|
|
|
|
return (
|
|
<div className="w-full flex flex-col pt-6 pb-24 px-4 min-h-screen" suppressHydrationWarning>
|
|
|
|
{/* Header & Search */}
|
|
<div className="sticky top-0 z-40 bg-background/80 backdrop-blur-md pt-2 pb-6 flex flex-col gap-6">
|
|
<h1 className="text-4xl font-extrabold flex items-center gap-3">
|
|
<Compass className="w-10 h-10 text-primary" />
|
|
Explore
|
|
</h1>
|
|
|
|
<div className="relative w-full max-w-2xl">
|
|
<motion.div
|
|
animate={{ scale: searchFocused ? 1.02 : 1 }}
|
|
className={`flex items-center w-full rounded-2xl border transition-all glass ${
|
|
searchFocused ? "border-primary ring-4 ring-primary/20 bg-background/80" : "border-border bg-muted/30"
|
|
}`}
|
|
>
|
|
<Search className="w-6 h-6 ml-4 text-muted-foreground object-fill" />
|
|
<input
|
|
type="text"
|
|
placeholder="Search posts, tags, or topics..."
|
|
onFocus={() => setSearchFocused(true)}
|
|
onBlur={() => setSearchFocused(false)}
|
|
className="w-full bg-transparent px-4 py-4 outline-none font-medium placeholder:text-muted-foreground"
|
|
/>
|
|
</motion.div>
|
|
|
|
<AnimatePresence>
|
|
{searchFocused && (
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 10 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
exit={{ opacity: 0, y: 10 }}
|
|
className="absolute top-full left-0 right-0 mt-4 p-4 glass-panel rounded-2xl shadow-2xl border border-border"
|
|
>
|
|
<div className="mb-4">
|
|
<span className="flex items-center gap-2 text-sm font-bold text-muted-foreground uppercase tracking-wider mb-2">
|
|
<TrendingUp className="w-4 h-4" /> Trending Searches
|
|
</span>
|
|
<div className="flex flex-wrap gap-2">
|
|
{TRENDING_TAGS.map(tag => (
|
|
<span key={tag} className="px-3 py-1.5 rounded-full bg-muted text-sm font-medium hover:bg-primary hover:text-primary-foreground cursor-pointer transition-colors flex items-center gap-1">
|
|
<Hash className="w-3 h-3" /> {tag.replace("#", "")}
|
|
</span>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
)}
|
|
</AnimatePresence>
|
|
</div>
|
|
|
|
{/* Categories */}
|
|
<div className="flex overflow-x-auto no-scrollbar gap-3 pb-2">
|
|
{CATEGORIES.map((cat, i) => (
|
|
<button
|
|
key={cat}
|
|
className={`px-6 py-2.5 rounded-full font-bold whitespace-nowrap transition-all active:scale-95 ${
|
|
i === 0 ? "bg-primary text-primary-foreground shadow-md shadow-primary/30" : "glass hover:bg-white/40 dark:hover:bg-black/40"
|
|
}`}
|
|
>
|
|
{cat}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Masonry Grid (Reused Post Cards with mixed sizes for discovery layout) */}
|
|
<motion.div
|
|
layout
|
|
className="columns-1 sm:columns-2 lg:columns-3 xl:columns-4 gap-6 space-y-6 mt-6"
|
|
>
|
|
{/* Shuffle the mock posts slightly to look different from Home Feed */}
|
|
{[...MOCK_POSTS].reverse().map((post) => (
|
|
<PostCard key={`explore-${post.id}`} post={post} />
|
|
))}
|
|
{MOCK_POSTS.map((post) => (
|
|
<PostCard key={`explore-2-${post.id}`} post={post} />
|
|
))}
|
|
</motion.div>
|
|
</div>
|
|
);
|
|
}
|