"use client";
import { useState } from "react";
import { Heart, X, RotateCcw, MapPin, Briefcase } from "lucide-react";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { cn } from "@/lib/utils";
const cards = [
{ id: 1, name: "Alex", age: 28, location: "San Francisco", job: "Product Designer", initials: "AL" },
{ id: 2, name: "Jordan", age: 25, location: "New York", job: "Software Engineer", initials: "JO" },
{ id: 3, name: "Sam", age: 30, location: "Los Angeles", job: "Photographer", initials: "SA" },
];
export const title = "React Dialog Block Card Swipe";
export default function DialogCardSwipe() {
const [open, setOpen] = useState(false);
const [currentIndex, setCurrentIndex] = useState(0);
const [action, setAction] = useState<"like" | "pass" | null>(null);
const [matched, setMatched] = useState(false);
const [history, setHistory] = useState<number[]>([]);
const currentCard = cards[currentIndex];
const hasCards = currentIndex < cards.length;
const handleAction = (type: "like" | "pass") => {
setAction(type);
setTimeout(() => {
if (type === "like" && currentIndex === 1) {
setMatched(true);
} else {
setHistory((h) => [...h, currentIndex]);
setCurrentIndex((i) => i + 1);
}
setAction(null);
}, 200);
};
const handleUndo = () => {
if (history.length > 0) {
const lastIndex = history[history.length - 1];
setHistory((h) => h.slice(0, -1));
setCurrentIndex(lastIndex);
}
};
const handleClose = () => {
setOpen(false);
setTimeout(() => {
setCurrentIndex(0);
setHistory([]);
setMatched(false);
setAction(null);
}, 200);
};
return (
<Dialog open={open} onOpenChange={setOpen}>
<div className="flex min-h-[350px] items-center justify-center">
<DialogTrigger asChild>
<Button variant="outline">
<Heart className="mr-2 h-4 w-4" />
Discover
</Button>
</DialogTrigger>
</div>
<DialogContent style={{ maxWidth: "320px" }} className="p-0 overflow-hidden gap-0">
<DialogTitle className="sr-only">Discover People</DialogTitle>
{matched ? (
<div className="flex flex-col items-center justify-center py-10 px-6 text-center">
<div className="flex -space-x-3">
<div className="rounded-full bg-gradient-to-br from-primary/20 to-primary/5 p-1">
<Avatar className="h-16 w-16 border-2 border-background">
<AvatarFallback>You</AvatarFallback>
</Avatar>
</div>
<div className="rounded-full bg-gradient-to-br from-primary/20 to-primary/5 p-1">
<Avatar className="h-16 w-16 border-2 border-background">
<AvatarFallback>{cards[currentIndex]?.initials}</AvatarFallback>
</Avatar>
</div>
</div>
<h3 className="mt-4 text-xl font-semibold">It's a Match!</h3>
<p className="mt-1 text-sm text-muted-foreground">
You and {cards[currentIndex]?.name} liked each other
</p>
<div className="flex gap-2 mt-6 w-full">
<Button
variant="outline"
className="flex-1"
onClick={() => {
setMatched(false);
setHistory((h) => [...h, currentIndex]);
setCurrentIndex((i) => i + 1);
}}
>
Continue
</Button>
<Button className="flex-1" onClick={handleClose}>
Message
</Button>
</div>
</div>
) : hasCards ? (
<>
{/* Card */}
<div
className={cn(
"p-6 transition-all duration-200",
action === "like" && "bg-primary/5",
action === "pass" && "opacity-50"
)}
>
<div className="flex flex-col items-center text-center">
<div className="rounded-full border-2 border-border p-1">
<Avatar className="h-32 w-32">
<AvatarFallback className="text-4xl">
{currentCard.initials}
</AvatarFallback>
</Avatar>
</div>
<h3 className="mt-4 text-xl font-semibold">
{currentCard.name}, {currentCard.age}
</h3>
<div className="mt-2 flex flex-col gap-1">
<div className="flex items-center justify-center gap-1.5 text-sm text-muted-foreground">
<Briefcase className="h-3.5 w-3.5" />
{currentCard.job}
</div>
<div className="flex items-center justify-center gap-1.5 text-sm text-muted-foreground">
<MapPin className="h-3.5 w-3.5" />
{currentCard.location}
</div>
</div>
</div>
{/* Card counter */}
<div className="flex justify-center gap-1 mt-4">
{cards.map((_, i) => (
<div
key={i}
className={cn(
"h-1 w-6 rounded-full transition-colors",
i === currentIndex ? "bg-primary" : "bg-muted"
)}
/>
))}
</div>
</div>
{/* Actions */}
<div className="flex items-center justify-center gap-4 p-4 border-t">
<Button
variant="outline"
size="icon"
className="h-14 w-14 rounded-full"
onClick={() => handleAction("pass")}
>
<X className="h-6 w-6" />
</Button>
<Button
variant="ghost"
size="icon"
className="h-10 w-10 rounded-full"
onClick={handleUndo}
disabled={history.length === 0}
>
<RotateCcw className="h-4 w-4" />
</Button>
<Button
size="icon"
className="h-14 w-14 rounded-full"
onClick={() => handleAction("like")}
>
<Heart className="h-6 w-6" />
</Button>
</div>
</>
) : (
<div className="flex flex-col items-center justify-center py-12 px-6 text-center">
<Heart className="h-10 w-10 text-muted-foreground" />
<h3 className="mt-4 text-lg font-medium">No more profiles</h3>
<p className="mt-1 text-sm text-muted-foreground">
Check back later for more
</p>
<Button onClick={handleClose} className="mt-6">
Done
</Button>
</div>
)}
</DialogContent>
</Dialog>
);
}