Files
reui-blocks/blocks/settings-profile6.tsx

427 lines
16 KiB
TypeScript

"use client";
import { Check, ChevronLeft, ChevronRight, Upload } from "lucide-react";
import { useState } from "react";
import { FileUpload, FileUploadTrigger } from "@/components/diceui/file-upload";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { cn } from "@/lib/utils";
interface ProfileData {
name: string;
username: string;
avatar?: string;
bio?: string;
email?: string;
phone?: string;
location?: string;
website?: string;
twitter?: string;
linkedin?: string;
}
interface SettingsProfile6Props {
defaultValues?: Partial<ProfileData>;
className?: string;
}
const steps = [
{ id: 1, title: "اطلاعات پایه", description: "نام و عکس پروفایل" },
{ id: 2, title: "اطلاعات تماس", description: "ایمیل و شماره تماس" },
{ id: 3, title: "لینک‌های حرفه‌ای", description: "وب‌سایت و شبکه‌ها" },
{ id: 4, title: "بازبینی", description: "تأیید نهایی" },
];
const SettingsProfile6 = ({
defaultValues = {
name: "",
username: "",
avatar: "",
bio: "",
email: "",
phone: "",
location: "",
website: "",
twitter: "",
linkedin: "",
},
className,
}: SettingsProfile6Props) => {
const [currentStep, setCurrentStep] = useState(1);
const [avatarFiles, setAvatarFiles] = useState<File[]>([]);
const [formData, setFormData] = useState<ProfileData>({
name: defaultValues.name || "",
username: defaultValues.username || "",
avatar: defaultValues.avatar || "",
bio: defaultValues.bio || "",
email: defaultValues.email || "",
phone: defaultValues.phone || "",
location: defaultValues.location || "",
website: defaultValues.website || "",
twitter: defaultValues.twitter || "",
linkedin: defaultValues.linkedin || "",
});
const updateField = (field: keyof ProfileData, value: string) => {
setFormData((prev) => ({ ...prev, [field]: value }));
};
const nextStep = () => setCurrentStep((prev) => Math.min(prev + 1, 4));
const prevStep = () => setCurrentStep((prev) => Math.max(prev - 1, 1));
const avatarPreview =
avatarFiles.length > 0
? URL.createObjectURL(avatarFiles[0])
: formData.avatar;
const initials = formData.name
?.split(" ")
.map((n) => n[0])
.join("")
.toUpperCase();
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-8 text-center">
<h1 className="text-xl font-semibold">تکمیل پروفایل</h1>
<p className="text-muted-foreground">
پروفایل خود را کامل کنید تا همکاران راحت‌تر با شما هماهنگ شوند
</p>
</div>
{/* Progress Steps */}
<div className="mb-8">
<div className="flex items-center justify-between">
{steps.map((step, index) => (
<div key={step.id} className="flex items-center">
<div className="flex flex-col items-center">
<div
className={cn(
"flex size-10 items-center justify-center rounded-full border-2 text-sm font-medium transition-colors",
currentStep > step.id
? "border-primary bg-primary text-primary-foreground"
: currentStep === step.id
? "border-primary text-primary"
: "border-muted text-muted-foreground",
)}
>
{currentStep > step.id ? (
<Check className="size-5" />
) : (
step.id.toLocaleString("fa-IR")
)}
</div>
<div className="mt-2 text-center">
<p
className={cn(
"text-sm font-medium",
currentStep >= step.id
? "text-foreground"
: "text-muted-foreground",
)}
>
{step.title}
</p>
<p className="hidden text-xs text-muted-foreground sm:block">
{step.description}
</p>
</div>
</div>
{index < steps.length - 1 && (
<div
className={cn(
"mx-2 h-0.5 w-12 sm:w-20",
currentStep > step.id ? "bg-primary" : "bg-muted",
)}
/>
)}
</div>
))}
</div>
</div>
{/* Step Content */}
<Card>
<CardContent className="p-6">
{/* Step 1: Basic Info */}
{currentStep === 1 && (
<div className="space-y-6">
<FileUpload
value={avatarFiles}
onValueChange={setAvatarFiles}
accept="image/*"
maxFiles={1}
maxSize={2 * 1024 * 1024}
>
<div className="flex flex-col items-center gap-4">
<Avatar className="size-24">
<AvatarImage
src={avatarPreview}
alt={
formData.name
? `آواتار ${formData.name}`
: "عکس پروفایل"
}
className="object-cover"
/>
<AvatarFallback className="text-xl">
{initials || "?"}
</AvatarFallback>
</Avatar>
<FileUploadTrigger asChild>
<Button variant="outline" size="sm">
<Upload className="me-2 size-4" />
بارگذاری عکس
</Button>
</FileUploadTrigger>
</div>
</FileUpload>
<div className="space-y-4">
<div className="space-y-2">
<Label htmlFor="name">نام و نام خانوادگی *</Label>
<Input
id="name"
value={formData.name}
onChange={(e) => updateField("name", e.target.value)}
placeholder="مثال: سارا محمدی"
/>
</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"
value={formData.username}
onChange={(e) =>
updateField("username", e.target.value)
}
placeholder="sarah.m"
/>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="bio">معرفی کوتاه</Label>
<Textarea
id="bio"
rows={3}
value={formData.bio}
onChange={(e) => updateField("bio", e.target.value)}
placeholder="نقش و تیم خود را بنویسید"
/>
</div>
</div>
</div>
)}
{/* Step 2: Contact */}
{currentStep === 2 && (
<div className="space-y-4">
<div className="space-y-2">
<Label htmlFor="email">ایمیل کاری *</Label>
<Input
id="email"
type="email"
value={formData.email}
onChange={(e) => updateField("email", e.target.value)}
placeholder="you@company.com"
/>
</div>
<div className="space-y-2">
<Label htmlFor="phone">شماره موبایل</Label>
<Input
id="phone"
type="tel"
value={formData.phone}
onChange={(e) => updateField("phone", e.target.value)}
placeholder="۰۹۱۲ ۳۴۵ ۶۷۸۹"
/>
</div>
<div className="space-y-2">
<Label htmlFor="location">موقعیت مکانی</Label>
<Input
id="location"
value={formData.location}
onChange={(e) => updateField("location", e.target.value)}
placeholder="شهر، کشور"
/>
</div>
</div>
)}
{/* Step 3: Social */}
{currentStep === 3 && (
<div className="space-y-4">
<div className="space-y-2">
<Label htmlFor="website">وب‌سایت</Label>
<Input
id="website"
type="url"
value={formData.website}
onChange={(e) => updateField("website", e.target.value)}
placeholder="https://yourwebsite.com"
/>
</div>
<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"
value={formData.twitter}
onChange={(e) => updateField("twitter", e.target.value)}
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"
value={formData.linkedin}
onChange={(e) => updateField("linkedin", e.target.value)}
placeholder="نام کاربری"
/>
</div>
</div>
</div>
)}
{/* Step 4: Review */}
{currentStep === 4 && (
<div className="space-y-6">
<div className="flex items-center gap-4">
<Avatar className="size-16">
<AvatarImage
src={avatarPreview}
alt={
formData.name
? `آواتار ${formData.name}`
: "عکس پروفایل"
}
className="object-cover"
/>
<AvatarFallback>{initials || "?"}</AvatarFallback>
</Avatar>
<div>
<h3 className="font-semibold">
{formData.name || "نام ثبت نشده"}
</h3>
<p className="text-sm text-muted-foreground">
@{formData.username || "نام‌کاربری"}
</p>
</div>
</div>
{formData.bio && (
<p className="text-sm text-muted-foreground">
{formData.bio}
</p>
)}
<div className="grid gap-4 rounded-lg border p-4 sm:grid-cols-2">
<div>
<p className="text-xs font-medium text-muted-foreground">
ایمیل کاری
</p>
<p className="text-sm">{formData.email || "ثبت نشده"}</p>
</div>
<div>
<p className="text-xs font-medium text-muted-foreground">
موبایل
</p>
<p className="text-sm">{formData.phone || "ثبت نشده"}</p>
</div>
<div>
<p className="text-xs font-medium text-muted-foreground">
موقعیت مکانی
</p>
<p className="text-sm">{formData.location || "ثبت نشده"}</p>
</div>
<div>
<p className="text-xs font-medium text-muted-foreground">
وب‌سایت
</p>
<p className="text-sm">{formData.website || "ثبت نشده"}</p>
</div>
</div>
<div className="rounded-lg bg-muted/50 p-4">
<p className="text-sm text-muted-foreground">
اطلاعات را بازبینی کنید. برای ذخیره روی «تکمیل پروفایل» بزنید یا برای اصلاح به مرحله قبل برگردید.
</p>
</div>
</div>
)}
</CardContent>
</Card>
{/* Navigation */}
<div className="mt-6 flex items-center justify-between">
<Button
variant="outline"
onClick={prevStep}
disabled={currentStep === 1}
>
<ChevronLeft className="me-2 size-4 rtl:rotate-180" />
مرحله قبل
</Button>
{currentStep < 4 ? (
<Button onClick={nextStep}>
ادامه
<ChevronRight className="ms-2 size-4 rtl:rotate-180" />
</Button>
) : (
<Button>
<Check className="me-2 size-4" />
تکمیل پروفایل
</Button>
)}
</div>
{/* Skip option */}
{currentStep < 4 && (
<p className="mt-4 text-center text-sm text-muted-foreground">
<button
onClick={() => setCurrentStep(4)}
className="underline hover:text-foreground"
>
رفتن به بازبینی
</button>
</p>
)}
</div>
</div>
</section>
);
};
export { SettingsProfile6 };