Files
reui-blocks/blocks/settings-profile4.tsx
T

465 lines
20 KiB
TypeScript

"use client";
import {
Camera,
ChevronRight,
Globe,
Link2,
Mail,
MapPin,
Phone,
Settings,
User,
X,
} from "lucide-react";
import { useState } from "react";
import {
FileUpload,
FileUploadDropzone,
FileUploadItem,
FileUploadItemDelete,
FileUploadItemPreview,
FileUploadList,
FileUploadTrigger,
} from "@/components/diceui/file-upload";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Separator } from "@/components/ui/separator";
import { Textarea } from "@/components/ui/textarea";
import { cn } from "@/lib/utils";
interface ProfileData {
name: string;
username: string;
email: string;
avatar?: string;
bio?: string;
phone?: string;
location?: string;
website?: string;
twitter?: string;
linkedin?: string;
github?: string;
timezone?: string;
language?: string;
}
interface SettingsProfile4Props {
defaultValues?: Partial<ProfileData>;
className?: string;
}
const sections = [
{ id: "personal", label: "اطلاعات پایه", icon: User },
{ id: "contact", label: "اطلاعات تماس", icon: Mail },
{ id: "social", label: "لینک‌های حرفه‌ای", icon: Link2 },
{ id: "preferences", label: "ترجیحات حساب", icon: Settings },
];
const SettingsProfile4 = ({
defaultValues = {
name: "الهام میرزایی",
username: "elah.mirzaei",
email: "alex.morgan@email.com",
avatar:
"/block-media/shadcnblocks/block/avatar/avatar8.jpg",
bio: "مدیر موفقیت مشتری با تمرکز روی ماندگاری حساب و رشد گسترش. علاقه‌مند به آنبوردینگ و سنجش سلامت مشتری.",
phone: "+98 912 345 6789",
location: "تهران، ایران",
website: "https://alexmorgan.design",
twitter: "alexmorgan",
linkedin: "alexmorgan",
github: "alexmorgan",
timezone: "America/Los_Angeles",
language: "en",
},
className,
}: SettingsProfile4Props) => {
const [activeSection, setActiveSection] = useState("personal");
const [avatarFiles, setAvatarFiles] = useState<File[]>([]);
const initials = defaultValues.name
?.split(" ")
.map((n) => n[0])
.join("")
.toUpperCase();
const avatarPreview =
avatarFiles.length > 0
? URL.createObjectURL(avatarFiles[0])
: defaultValues.avatar;
return (
<section dir="rtl" lang="fa" className={cn("w-full py-32", className)}>
<div className="w-full px-4 sm:px-6 lg:px-8">
<div className="flex w-full flex-col gap-8">
{/* Header */}
<div className="mb-6">
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<span>تنظیمات حساب</span>
<ChevronRight className="size-4 rtl:rotate-180" />
<span className="text-foreground">ویرایش پروفایل</span>
</div>
<h1 className="mt-2 text-xl font-semibold">ویرایش پروفایل</h1>
<p className="text-muted-foreground">
اطلاعات پروفایل و ترجیحات حساب خود را مدیریت کنید
</p>
</div>
<div className="flex flex-col gap-8 lg:flex-row">
{/* Sidebar Navigation */}
<aside className="lg:w-56 lg:shrink-0">
<nav className="space-y-1">
{sections.map((section) => {
const Icon = section.icon;
return (
<button
key={section.id}
onClick={() => setActiveSection(section.id)}
className={cn(
"flex w-full items-center gap-3 rounded-lg px-3 py-2 text-start text-sm transition-colors",
activeSection === section.id
? "bg-primary text-primary-foreground"
: "text-muted-foreground hover:bg-muted hover:text-foreground",
)}
>
<Icon className="size-4" />
{section.label}
</button>
);
})}
</nav>
</aside>
{/* Main Content */}
<main className="min-w-0 flex-1">
<div className="rounded-xl border bg-card shadow-sm">
{/* Personal Info Section */}
{activeSection === "personal" && (
<div className="p-6">
<h2 className="text-lg font-semibold">اطلاعات شخصی</h2>
<p className="text-sm text-muted-foreground">
عکس و مشخصات پایه پروفایل را به‌روز کنید
</p>
<div className="mt-6 space-y-6">
{/* Avatar */}
<FileUpload
value={avatarFiles}
onValueChange={setAvatarFiles}
accept="image/*"
maxFiles={1}
maxSize={2 * 1024 * 1024}
>
<div className="flex flex-col gap-4 sm:flex-row sm:items-start">
<Avatar className="size-24 shrink-0">
<AvatarImage
src={avatarPreview}
alt={`آواتار ${defaultValues.name}`}
className="object-cover"
/>
<AvatarFallback className="text-xl">
{initials}
</AvatarFallback>
</Avatar>
<div className="flex-1 space-y-3">
<FileUploadDropzone className="flex flex-col items-center justify-center gap-2 rounded-lg border-2 border-dashed p-6 text-center transition-colors hover:border-primary/50 hover:bg-muted/50">
<div className="flex size-10 items-center justify-center rounded-full bg-muted">
<Camera className="size-5 text-muted-foreground" />
</div>
<div className="space-y-1">
<p className="text-sm font-medium">
<FileUploadTrigger asChild>
<Button variant="link" className="h-auto p-0">
برای بارگذاری کلیک کنید
</Button>
</FileUploadTrigger>{" "}
یا فایل را اینجا رها کنید
</p>
<p className="text-xs text-muted-foreground">
JPG، PNG یا WEBP (حداکثر ۲ مگابایت)
</p>
</div>
</FileUploadDropzone>
{avatarFiles.length > 0 && (
<FileUploadList>
{avatarFiles.map((file, index) => (
<FileUploadItem
key={index}
value={file}
className="flex items-center gap-3 rounded-lg border bg-muted/30 p-3"
>
<FileUploadItemPreview className="size-10 shrink-0 rounded-md" />
<div className="min-w-0 flex-1">
<p className="truncate text-sm font-medium">
{file.name}
</p>
<p className="text-xs text-muted-foreground">
{(file.size / 1024).toLocaleString("fa-IR", {
maximumFractionDigits: 1,
})}{" "}
کیلوبایت
</p>
</div>
<FileUploadItemDelete asChild>
<Button
variant="ghost"
size="icon"
className="size-8 shrink-0"
>
<X className="size-4" />
</Button>
</FileUploadItemDelete>
</FileUploadItem>
))}
</FileUploadList>
)}
</div>
</div>
</FileUpload>
<Separator />
<div className="grid gap-6 sm:grid-cols-2">
<div className="space-y-2">
<Label htmlFor="name">نام و نام خانوادگی</Label>
<Input id="name" defaultValue={defaultValues.name} />
</div>
<div className="space-y-2">
<Label htmlFor="username">نام کاربری</Label>
<div className="flex">
<span className="inline-flex items-center rounded-s-md border border-e-0 bg-muted px-3 text-sm text-muted-foreground">
@
</span>
<Input
id="username"
className="rounded-s-none"
defaultValue={defaultValues.username}
/>
</div>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="bio">معرفی کوتاه</Label>
<Textarea
id="bio"
rows={4}
defaultValue={defaultValues.bio}
placeholder="نقش و تمرکز کاری خود را بنویسید"
/>
<p className="text-xs text-muted-foreground">
در پروفایل فضای کاری نمایش داده می‌شود
</p>
</div>
</div>
</div>
)}
{/* Contact Section */}
{activeSection === "contact" && (
<div className="p-6">
<h2 className="text-lg font-semibold">اطلاعات تماس</h2>
<p className="text-sm text-muted-foreground">
راه‌های تماس شما در فضای کاری چگونه باشد؟
</p>
<div className="mt-6 space-y-6">
<div className="space-y-2">
<Label htmlFor="email">ایمیل کاری</Label>
<div className="relative">
<Mail className="absolute top-1/2 start-3 size-4 -translate-y-1/2 text-muted-foreground" />
<Input
id="email"
type="email"
className="ps-10"
defaultValue={defaultValues.email}
/>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="phone">شماره موبایل</Label>
<div className="relative">
<Phone className="absolute top-1/2 start-3 size-4 -translate-y-1/2 text-muted-foreground" />
<Input
id="phone"
type="tel"
className="ps-10"
defaultValue={defaultValues.phone}
/>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="location">موقعیت مکانی</Label>
<div className="relative">
<MapPin className="absolute top-1/2 start-3 size-4 -translate-y-1/2 text-muted-foreground" />
<Input
id="location"
className="ps-10"
defaultValue={defaultValues.location}
placeholder="شهر، کشور"
/>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="website">وب‌سایت</Label>
<div className="relative">
<Globe className="absolute top-1/2 start-3 size-4 -translate-y-1/2 text-muted-foreground" />
<Input
id="website"
type="url"
className="ps-10"
defaultValue={defaultValues.website}
placeholder="https://yourwebsite.com"
/>
</div>
</div>
</div>
</div>
)}
{/* Social Links Section */}
{activeSection === "social" && (
<div className="p-6">
<h2 className="text-lg font-semibold">لینک‌های حرفه‌ای</h2>
<p className="text-sm text-muted-foreground">
پروفایل‌های حرفه‌ای خود را لینک کنید
</p>
<div className="mt-6 space-y-6">
<div className="space-y-2">
<Label htmlFor="twitter">X / توییتر</Label>
<div className="flex">
<span className="inline-flex items-center rounded-s-md border border-e-0 bg-muted px-3 text-sm text-muted-foreground">
x.com/
</span>
<Input
id="twitter"
className="rounded-s-none"
defaultValue={defaultValues.twitter}
placeholder="نام کاربری"
/>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="linkedin">لینکدین</Label>
<div className="flex">
<span className="inline-flex items-center rounded-s-md border border-e-0 bg-muted px-3 text-sm text-muted-foreground">
linkedin.com/in/
</span>
<Input
id="linkedin"
className="rounded-s-none"
defaultValue={defaultValues.linkedin}
placeholder="نام کاربری"
/>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="github">گیت‌هاب</Label>
<div className="flex">
<span className="inline-flex items-center rounded-s-md border border-e-0 bg-muted px-3 text-sm text-muted-foreground">
github.com/
</span>
<Input
id="github"
className="rounded-s-none"
defaultValue={defaultValues.github}
placeholder="نام کاربری"
/>
</div>
</div>
</div>
</div>
)}
{/* Preferences Section */}
{activeSection === "preferences" && (
<div className="p-6">
<h2 className="text-lg font-semibold">ترجیحات حساب</h2>
<p className="text-sm text-muted-foreground">
زبان رابط و منطقه زمانی را شخصی‌سازی کنید
</p>
<div className="mt-6 space-y-6">
<div className="space-y-2">
<Label htmlFor="language">زبان رابط</Label>
<Select defaultValue={defaultValues.language}>
<SelectTrigger id="language">
<SelectValue placeholder="انتخاب زبان رابط" />
</SelectTrigger>
<SelectContent>
<SelectItem value="fa">فارسی</SelectItem>
<SelectItem value="en">انگلیسی</SelectItem>
<SelectItem value="es">اسپانیایی</SelectItem>
<SelectItem value="fr">فرانسوی</SelectItem>
<SelectItem value="de">آلمانی</SelectItem>
<SelectItem value="ja">ژاپنی</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label htmlFor="timezone">منطقه زمانی</Label>
<Select defaultValue={defaultValues.timezone}>
<SelectTrigger id="timezone">
<SelectValue placeholder="انتخاب منطقه زمانی" />
</SelectTrigger>
<SelectContent>
<SelectItem value="America/New_York">
وقت شرقی آمریکا (ET)
</SelectItem>
<SelectItem value="America/Chicago">
وقت مرکزی آمریکا (CT)
</SelectItem>
<SelectItem value="America/Denver">
وقت کوهستانی آمریکا (MT)
</SelectItem>
<SelectItem value="America/Los_Angeles">
وقت اقیانوس آرام (PT)
</SelectItem>
<SelectItem value="Europe/London">وقت گرینویچ (GMT)</SelectItem>
<SelectItem value="Europe/Paris">
وقت اروپای مرکزی (CET)
</SelectItem>
<SelectItem value="Asia/Tehran">
وقت ایران (IRST)
</SelectItem>
</SelectContent>
</Select>
</div>
</div>
</div>
)}
{/* Footer with actions */}
<div className="flex items-center justify-end gap-3 border-t px-6 py-4">
<Button variant="outline">انصراف</Button>
<Button>ذخیره تغییرات</Button>
</div>
</div>
</main>
</div>
</div>
</div>
</section>
);
};
export { SettingsProfile4 };