427 lines
16 KiB
TypeScript
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 };
|