Files
reui-blocks/blocks/address-book1.tsx
T

594 lines
22 KiB
TypeScript

"use client";
import {
MapPin,
MoreVertical,
Pencil,
Plus,
Save,
Trash2,
X,
} from "lucide-react";
import { useState } from "react";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { cn } from "@/lib/utils";
interface Address {
id: string;
name: string;
street: string;
city: string;
state: string;
zip: string;
country: string;
phone: string;
isDefault: boolean;
type: "خانه" | "سرکار" | "سایر";
}
const DEFAULT_ADDRESSES: Address[] = [
{
id: "1",
name: "علی رضایی",
street: "123 Main Street, Apt 4B",
city: "New York",
state: "NY",
zip: "10001",
country: "ایران",
phone: "(212) 555-1234",
isDefault: true,
type: "خانه",
},
{
id: "2",
name: "علی رضایی",
street: "456 Business Ave, Suite 100",
city: "New York",
state: "NY",
zip: "10018",
country: "ایران",
phone: "(212) 555-5678",
isDefault: false,
type: "سرکار",
},
];
interface AddressBook1Props {
addresses?: Address[];
className?: string;
}
const AddressBook1 = ({
addresses: initialAddresses = DEFAULT_ADDRESSES,
className,
}: AddressBook1Props) => {
const [addresses, setAddresses] = useState(initialAddresses);
const [selectedId, setSelectedId] = useState(
addresses.find((a) => a.isDefault)?.id || addresses[0]?.id,
);
const [editingId, setEditingId] = useState<string | null>(null);
const [isAddingNew, setIsAddingNew] = useState(false);
const [editForm, setEditForm] = useState<Partial<Address>>({});
const startEditing = (address: Address) => {
setEditingId(address.id);
setEditForm({ ...address });
};
const cancelEditing = () => {
setEditingId(null);
setEditForm({});
};
const saveEdit = () => {
if (
editingId &&
editForm.name &&
editForm.street &&
editForm.city &&
editForm.state &&
editForm.zip &&
editForm.country &&
editForm.phone &&
editForm.type
) {
setAddresses((prev) =>
prev.map((addr) =>
addr.id === editingId
? ({
...addr,
...editForm,
} as Address)
: addr,
),
);
setEditingId(null);
setEditForm({});
}
};
const startAddingNew = () => {
setIsAddingNew(true);
setEditForm({
name: "",
street: "",
city: "",
state: "",
zip: "",
country: "ایران",
phone: "",
type: "خانه",
isDefault: false,
});
};
const cancelAddingNew = () => {
setIsAddingNew(false);
setEditForm({});
};
const saveNewAddress = () => {
if (
editForm.name &&
editForm.street &&
editForm.city &&
editForm.state &&
editForm.zip &&
editForm.country &&
editForm.phone &&
editForm.type
) {
const newAddress: Address = {
id: Date.now().toString(),
name: editForm.name,
street: editForm.street,
city: editForm.city,
state: editForm.state,
zip: editForm.zip,
country: editForm.country,
phone: editForm.phone,
type: editForm.type as "خانه" | "سرکار" | "سایر",
isDefault: addresses.length === 0,
};
setAddresses((prev) => [...prev, newAddress]);
setIsAddingNew(false);
setEditForm({});
if (addresses.length === 0) {
setSelectedId(newAddress.id);
}
}
};
const deleteAddress = (id: string) => {
setAddresses((prev) => prev.filter((addr) => addr.id !== id));
if (selectedId === id && addresses.length > 1) {
setSelectedId(addresses.find((a) => a.id !== id)?.id || "");
}
if (editingId === id) {
setEditingId(null);
setEditForm({});
}
};
return (
<section className={cn("w-full py-16 md:py-24 ", className)}>
<div className="w-full px-6 ">
{/* Header */}
<div className="mb-6 flex justify-between ">
<div>
<h1 className="text-xl font-semibold tracking-tight md:text-3xl">
آدرس‌های من
</h1>
<p className="mt-1 text-muted-foreground">
آدرس‌های ذخیره‌شده خود را مدیریت کنید.
</p>
</div>
<Button onClick={startAddingNew}>
<Plus className="mr-2 size-4" />
افزودن آدرس
</Button>
</div>
{/* Address List */}
<RadioGroup value={selectedId} onValueChange={setSelectedId}>
<div className="space-y-4 ">
{addresses.map((address) => (
<Card
key={address.id}
className={cn(
"cursor-pointer gap-0 p-0 transition-colors ",
selectedId === address.id && "border-primary",
editingId === address.id && "border-primary",
)}
onClick={() =>
editingId !== address.id && setSelectedId(address.id)
}
>
<CardContent className="p-4 ">
{editingId === address.id ? (
<div className="space-y-4">
<div className="flex items-center justify-between ">
<h3 className="font-semibold">ویرایش آدرس</h3>
<div className="flex gap-2">
<Button
variant="ghost"
size="sm"
onClick={(e) => {
e.stopPropagation();
cancelEditing();
}}
>
<X className="size-4" />
</Button>
<Button
size="sm"
onClick={(e) => {
e.stopPropagation();
saveEdit();
}}
>
<Save className="mr-2 size-4" />
ذخیره
</Button>
</div>
</div>
<div className="grid gap-4 sm:grid-cols-2">
<div className="space-y-2">
<Label htmlFor={`name-${address.id}`}>
نام کامل
</Label>
<Input
id={`name-${address.id}`}
value={editForm.name || ""}
onChange={(e) =>
setEditForm({ ...editForm, name: e.target.value })
}
onClick={(e) => e.stopPropagation()}
/>
</div>
<div className="space-y-2">
<Label htmlFor={`phone-${address.id}`}>تلفن</Label>
<Input
id={`phone-${address.id}`}
value={editForm.phone || ""}
onChange={(e) =>
setEditForm({
...editForm,
phone: e.target.value,
})
}
onClick={(e) => e.stopPropagation()}
/>
</div>
<div className="space-y-2 sm:col-span-2">
<Label htmlFor={`street-${address.id}`}>
آدرس خیابان
</Label>
<Input
id={`street-${address.id}`}
value={editForm.street || ""}
onChange={(e) =>
setEditForm({
...editForm,
street: e.target.value,
})
}
onClick={(e) => e.stopPropagation()}
/>
</div>
<div className="space-y-2">
<Label htmlFor={`city-${address.id}`}>شهر</Label>
<Input
id={`city-${address.id}`}
value={editForm.city || ""}
onChange={(e) =>
setEditForm({ ...editForm, city: e.target.value })
}
onClick={(e) => e.stopPropagation()}
/>
</div>
<div className="space-y-2">
<Label htmlFor={`state-${address.id}`}>وضعیت</Label>
<Input
id={`state-${address.id}`}
value={editForm.state || ""}
onChange={(e) =>
setEditForm({
...editForm,
state: e.target.value,
})
}
onClick={(e) => e.stopPropagation()}
/>
</div>
<div className="space-y-2">
<Label htmlFor={`zip-${address.id}`}>کد پستی</Label>
<Input
id={`zip-${address.id}`}
value={editForm.zip || ""}
onChange={(e) =>
setEditForm({ ...editForm, zip: e.target.value })
}
onClick={(e) => e.stopPropagation()}
/>
</div>
<div className="space-y-2">
<Label htmlFor={`country-${address.id}`}>
کشور
</Label>
<Input
id={`country-${address.id}`}
value={editForm.country || ""}
onChange={(e) =>
setEditForm({
...editForm,
country: e.target.value,
})
}
onClick={(e) => e.stopPropagation()}
/>
</div>
<div className="space-y-2">
<Label htmlFor={`type-${address.id}`}>نوع</Label>
<Select
value={editForm.type || "خانه"}
onValueChange={(value: "خانه" | "سرکار" | "سایر") =>
setEditForm({ ...editForm, type: value })
}
>
<SelectTrigger
id={`type-${address.id}`}
onClick={(e) => e.stopPropagation()}
>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="خانه">خانه</SelectItem>
<SelectItem value="سرکار">سرکار</SelectItem>
<SelectItem value="سایر">سایر</SelectItem>
</SelectContent>
</Select>
</div>
</div>
</div>
) : (
<div className="flex gap-4 flex-row-reverse">
<RadioGroupItem
value={address.id}
id={address.id}
className="mt-1 "
/>
<div className="flex-1">
<div className="flex justify-between gap-2 flex-row-reverse">
<div>
<div className="flex items-center gap-2">
<span className="font-semibold">
{address.name}
</span>
{address.isDefault && (
<Badge
variant="secondary"
className="text-xs font-normal"
>
پیش‌فرض
</Badge>
)}
<Badge
variant="outline"
className="text-xs capitalize"
>
{address.type}
</Badge>
</div>
</div>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
size="icon"
className="size-8"
onClick={(e) => e.stopPropagation()}
>
<MoreVertical className="size-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem
onClick={(e) => {
e.stopPropagation();
startEditing(address);
}}
>
<Pencil className="mr-2 size-4" />
ویرایش
</DropdownMenuItem>
<DropdownMenuItem
className="text-destructive"
onClick={(e) => {
e.stopPropagation();
deleteAddress(address.id);
}}
>
<Trash2 className="mr-2 size-4" />
حذف
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
<div className="mt-2 text-sm text-muted-foreground text-end">
<p>{address.street}</p>
<p>
{address.city}, {address.state} {address.zip}
</p>
<p>{address.country}</p>
<p className="mt-1">{address.phone}</p>
</div>
</div>
</div>
)}
</CardContent>
</Card>
))}
{isAddingNew && (
<Card className="gap-0 border-primary p-0">
<CardContent className="p-4">
<div className="space-y-4">
<div className="flex items-center justify-between flex-row-reverse">
<h3 className="font-semibold "> افزودن آدرس جدید</h3>
<div className="flex gap-2">
<Button
variant="ghost"
size="sm"
onClick={cancelAddingNew}
>
<X className="size-4" />
</Button>
<Button size="sm" onClick={saveNewAddress}>
<Save className="mr-2 size-4" />
ذخیره
</Button>
</div>
</div>
<div className="grid gap-4 sm:grid-cols-2 ">
<div className="space-y-2">
<Label htmlFor="new-name">نام کامل</Label>
<Input
id="new-name"
value={editForm.name || ""}
onChange={(e) =>
setEditForm({ ...editForm, name: e.target.value })
}
/>
</div>
<div className="space-y-2">
<Label htmlFor="new-phone">تلفن</Label>
<Input
id="new-phone"
value={editForm.phone || ""}
onChange={(e) =>
setEditForm({ ...editForm, phone: e.target.value })
}
/>
</div>
<div className="space-y-2 sm:col-span-2">
<Label htmlFor="new-street">آدرس خیابان</Label>
<Input
id="new-street"
value={editForm.street || ""}
onChange={(e) =>
setEditForm({ ...editForm, street: e.target.value })
}
/>
</div>
<div className="space-y-2">
<Label htmlFor="new-city">شهر</Label>
<Input
id="new-city"
value={editForm.city || ""}
onChange={(e) =>
setEditForm({ ...editForm, city: e.target.value })
}
/>
</div>
<div className="space-y-2">
<Label htmlFor="new-state">شهرستان</Label>
<Input
id="new-state"
value={editForm.state || ""}
onChange={(e) =>
setEditForm({ ...editForm, state: e.target.value })
}
/>
</div>
<div className="space-y-2">
<Label htmlFor="new-zip">کد پستی</Label>
<Input
id="new-zip"
value={editForm.zip || ""}
onChange={(e) =>
setEditForm({ ...editForm, zip: e.target.value })
}
/>
</div>
<div className="space-y-2">
<Label htmlFor="new-country">کشور</Label>
<Input
id="new-country"
value={editForm.country || ""}
onChange={(e) =>
setEditForm({
...editForm,
country: e.target.value,
})
}
/>
</div>
<div className="space-y-2 sm:col-span-2">
<Label htmlFor="new-type">نوع</Label>
<Select
value={editForm.type || "خانه"}
onValueChange={(value: "خانه" | "سرکار" | "سایر") =>
setEditForm({ ...editForm, type: value })
}
>
<SelectTrigger id="new-type">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="خانه">خانه</SelectItem>
<SelectItem value="سرکار">سرکار</SelectItem>
<SelectItem value="سایر">سایر</SelectItem>
</SelectContent>
</Select>
</div>
</div>
</div>
</CardContent>
</Card>
)}
</div>
</RadioGroup>
{addresses.length === 0 && (
<Card className="p-0">
<CardContent className="flex flex-col items-center justify-center py-12">
<MapPin className="mb-4 size-12 text-muted-foreground" />
<h2 className="text-xl font-semibold">آدرسی ذخیره نشد</h2>
<p className="mt-2 text-muted-foreground">
برای سریع‌تر شدن فرایند خرید، یک آدرس جدید اضافه کنید.
</p>
<Button className="mt-4" onClick={startAddingNew}>
<Plus className="mr-2 size-4" />
اضافه کردن آدرس
</Button>
</CardContent>
</Card>
)}
</div>
</section>
);
};
export { AddressBook1 };