87 lines
5.1 KiB
TypeScript
87 lines
5.1 KiB
TypeScript
import { useState } from "react";
|
|
import { Badge } from "@/components/ui/badge";
|
|
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
|
|
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
|
import { useSaas } from "@/hooks/use-tygarun";
|
|
import Header from "@/components/Header";
|
|
import Footer from "@/components/Footer";
|
|
|
|
const categories = ["All", "Wedding", "Portrait", "Commercial", "Fashion", "Nature"];
|
|
|
|
const photos = [
|
|
{ title: "First Dance", category: "Wedding", img: "https://images.unsplash.com/photo-1519741497674-611481863552?w=800&h=600&fit=crop", tall: true },
|
|
{ title: "Quiet Confidence", category: "Portrait", img: "https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=600&h=600&fit=crop", tall: false },
|
|
{ title: "Brand Essence", category: "Commercial", img: "https://images.unsplash.com/photo-1441986300917-64674bd600d8?w=600&h=400&fit=crop", tall: false },
|
|
{ title: "Avant Garde", category: "Fashion", img: "https://images.unsplash.com/photo-1469334031218-e382a71b716b?w=600&h=800&fit=crop", tall: true },
|
|
{ title: "Morning Mist", category: "Nature", img: "https://images.unsplash.com/photo-1472214103451-9374bd1c798e?w=800&h=600&fit=crop", tall: false },
|
|
{ title: "The Vow", category: "Wedding", img: "https://images.unsplash.com/photo-1511285560929-80b456fea0bc?w=600&h=600&fit=crop", tall: false },
|
|
{ title: "Inner Light", category: "Portrait", img: "https://images.unsplash.com/photo-1531746020798-e6953c6e8e04?w=600&h=800&fit=crop", tall: true },
|
|
{ title: "Studio Session", category: "Commercial", img: "https://images.unsplash.com/photo-1556761175-5973dc0f32e7?w=600&h=400&fit=crop", tall: false },
|
|
{ title: "Editorial Gaze", category: "Fashion", img: "https://images.unsplash.com/photo-1509631179647-0177331693ae?w=600&h=600&fit=crop", tall: false },
|
|
{ title: "Wilderness", category: "Nature", img: "https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?w=800&h=600&fit=crop", tall: true },
|
|
{ title: "Sunset Ceremony", category: "Wedding", img: "https://images.unsplash.com/photo-1606216794074-735e91aa2c92?w=600&h=400&fit=crop", tall: false },
|
|
{ title: "Timeless", category: "Portrait", img: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=600&h=600&fit=crop", tall: false },
|
|
];
|
|
|
|
export default function PortfolioPage() {
|
|
const [active, setActive] = useState("All");
|
|
|
|
// Gallery is media-backed via tyga.run file-management (seed images until the library is live)
|
|
const { data: media } = useSaas("file-management", "/list");
|
|
const livePhotos = Array.isArray(media) && media.length
|
|
? media.map((m: any) => ({
|
|
title: m.title || m.name || "Untitled",
|
|
category: m.category || "All",
|
|
img: m.url || m.src || m.signedUrl,
|
|
tall: !!m.tall,
|
|
}))
|
|
: photos;
|
|
|
|
const filtered = active === "All" ? livePhotos : livePhotos.filter((p) => p.category === active);
|
|
|
|
return (
|
|
<div className="min-h-screen bg-zinc-950 text-white antialiased">
|
|
<Header />
|
|
|
|
<section className="pt-32 pb-12 px-6">
|
|
<div className="mx-auto max-w-7xl">
|
|
<h1 className="text-4xl md:text-6xl font-serif font-light tracking-tight mb-4 animate-fade-up">Portfolio</h1>
|
|
<p className="text-zinc-500 max-w-xl mb-10">Each image is a story. Browse by category or explore the full collection.</p>
|
|
|
|
<Tabs value={active} onValueChange={setActive}>
|
|
<TabsList className="bg-zinc-900 border border-zinc-800">
|
|
{categories.map((cat) => (
|
|
<TabsTrigger key={cat} value={cat} className="text-xs tracking-wider data-[state=active]:bg-white data-[state=active]:text-zinc-900">
|
|
{cat}
|
|
</TabsTrigger>
|
|
))}
|
|
</TabsList>
|
|
</Tabs>
|
|
</div>
|
|
</section>
|
|
|
|
<section className="pb-24 px-6">
|
|
<div className="mx-auto max-w-7xl columns-1 sm:columns-2 lg:columns-3 gap-4 space-y-4 stagger">
|
|
{filtered.map((photo, i) => (
|
|
<Dialog key={i}>
|
|
<DialogTrigger asChild>
|
|
<div className={`group relative overflow-hidden cursor-pointer break-inside-avoid \${photo.tall ? "aspect-[3/4]" : "aspect-square"}`}>
|
|
<img src={photo.img} alt={photo.title} className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-110" />
|
|
<div className="absolute inset-0 bg-black/0 group-hover:bg-black/50 transition-all duration-500 flex flex-col items-center justify-center opacity-0 group-hover:opacity-100">
|
|
<p className="text-white font-light text-lg tracking-wide mb-2">{photo.title}</p>
|
|
<Badge variant="secondary" className="bg-white/20 text-white border-0 backdrop-blur-sm text-xs">{photo.category}</Badge>
|
|
</div>
|
|
</div>
|
|
</DialogTrigger>
|
|
<DialogContent className="max-w-4xl p-0 bg-transparent border-0">
|
|
<img src={photo.img} alt={photo.title} className="w-full rounded-lg" />
|
|
</DialogContent>
|
|
</Dialog>
|
|
))}
|
|
</div>
|
|
</section>
|
|
|
|
<Footer />
|
|
</div>
|
|
);
|
|
} |