"use client";
import { useState } from "react";
import { Receipt, Check } from "lucide-react";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { cn } from "@/lib/utils";
type Item = {
id: string;
name: string;
price: number;
assignedTo: string[];
};
const people = [
{ id: "1", name: "You", initials: "YO" },
{ id: "2", name: "Alex", initials: "AL" },
{ id: "3", name: "Sam", initials: "SA" },
];
const initialItems: Item[] = [
{ id: "a", name: "Margherita Pizza", price: 18.0, assignedTo: ["1", "2"] },
{ id: "b", name: "Caesar Salad", price: 12.0, assignedTo: ["3"] },
{ id: "c", name: "Pasta Carbonara", price: 22.0, assignedTo: ["1"] },
{ id: "d", name: "Tiramisu", price: 10.0, assignedTo: ["2", "3"] },
];
export const title = "React Dialog Block Split Bill";
export default function DialogSplitBill() {
const [open, setOpen] = useState(false);
const [items, setItems] = useState<Item[]>(initialItems);
const [done, setDone] = useState(false);
const toggleAssignment = (itemId: string, personId: string) => {
setItems((prev) =>
prev.map((item) => {
if (item.id !== itemId) return item;
const assigned = item.assignedTo.includes(personId);
return {
...item,
assignedTo: assigned
? item.assignedTo.filter((id) => id !== personId)
: [...item.assignedTo, personId],
};
})
);
};
const getPersonTotal = (personId: string) => {
let total = 0;
items.forEach((item) => {
if (item.assignedTo.includes(personId) && item.assignedTo.length > 0) {
total += item.price / item.assignedTo.length;
}
});
return total * 1.26; // includes 8% tax + 18% tip
};
const handleClose = () => {
setOpen(false);
setTimeout(() => {
setItems(initialItems);
setDone(false);
}, 200);
};
if (done) {
return (
<Dialog open={open} onOpenChange={setOpen}>
<div className="flex min-h-[350px] items-center justify-center">
<DialogTrigger asChild>
<Button variant="outline">
<Receipt className="mr-2 h-4 w-4" />
Split Bill
</Button>
</DialogTrigger>
</div>
<DialogContent style={{ maxWidth: "384px" }}>
<div className="flex flex-col items-center justify-center py-6 text-center">
<Check className="h-8 w-8 text-primary" />
<h3 className="mt-4 text-lg font-medium">Bill Split</h3>
<p className="mt-1 text-sm text-muted-foreground">
Everyone knows what they owe.
</p>
</div>
<div className="space-y-2">
{people.map((person) => (
<div
key={person.id}
className="flex items-center justify-between p-2 rounded-md border"
>
<div className="flex items-center gap-2">
<Avatar className="h-6 w-6">
<AvatarFallback className="text-xs">
{person.initials}
</AvatarFallback>
</Avatar>
<span className="text-sm">{person.name}</span>
</div>
<span className="font-mono font-medium">
${getPersonTotal(person.id).toFixed(2)}
</span>
</div>
))}
</div>
<DialogFooter>
<Button onClick={handleClose} className="w-full">
Done
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}
return (
<Dialog open={open} onOpenChange={setOpen}>
<div className="flex min-h-[350px] items-center justify-center">
<DialogTrigger asChild>
<Button variant="outline">
<Receipt className="mr-2 h-4 w-4" />
Split Bill
</Button>
</DialogTrigger>
</div>
<DialogContent style={{ maxWidth: "384px" }}>
<DialogHeader>
<DialogTitle>Split Bill</DialogTitle>
<DialogDescription>Assign items to each person.</DialogDescription>
</DialogHeader>
<div className="py-4 space-y-2">
{items.map((item) => (
<div
key={item.id}
className="flex items-center justify-between p-2 rounded-md border"
>
<div className="min-w-0">
<p className="text-sm font-medium truncate">{item.name}</p>
<p className="text-xs text-muted-foreground">
${item.price.toFixed(2)}
{item.assignedTo.length > 1 && (
<span>
{" "}· ${(item.price / item.assignedTo.length).toFixed(2)} ea
</span>
)}
</p>
</div>
<div className="flex gap-1 ml-2">
{people.map((person) => (
<button
key={person.id}
onClick={() => toggleAssignment(item.id, person.id)}
className={cn(
"h-7 w-7 rounded-full text-[10px] font-medium transition-colors",
item.assignedTo.includes(person.id)
? "bg-primary text-primary-foreground"
: "bg-muted text-muted-foreground"
)}
>
{person.initials}
</button>
))}
</div>
</div>
))}
<p className="text-xs text-muted-foreground pt-2">
Includes 8% tax + 18% tip
</p>
</div>
<DialogFooter>
<Button variant="outline" onClick={handleClose}>
Cancel
</Button>
<Button onClick={() => setDone(true)}>Done</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}