import { useEffect, useState } from "react";
import {
Calendar,
CheckCircle2,
Clock,
Globe,
Loader2,
Mail,
MapPin,
Pencil,
Phone,
Save,
Shield,
User,
X,
XCircle,
Briefcase,
BookOpen,
Target,
Languages,
Heart,
MessageCircle,
} from "lucide-react";
import { Badge } from "../components/ui/badge";
import { Button } from "../components/ui/button";
import { Card, CardContent } from "../components/ui/card";
import { Input } from "../components/ui/input";
import { Select } from "../components/ui/select";
import { cn } from "../lib/utils";
import { getMyProfile, updateProfile } from "../api/users.api";
import type { UserProfileData, UpdateProfileRequest } from "../types/user.types";
import { toast } from "sonner";
function formatDate(dateStr: string | null | undefined): string {
if (!dateStr) return "—";
return new Date(dateStr).toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
});
}
function formatDateTime(dateStr: string | null | undefined): string {
if (!dateStr) return "—";
return new Date(dateStr).toLocaleString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
hour: "2-digit",
minute: "2-digit",
});
}
function LoadingSkeleton() {
return (
{[1, 2, 3].map((i) => (
{[1, 2, 3, 4].map((j) => (
))}
))}
);
}
function VerifiedIcon({ verified }: { verified: boolean }) {
return verified ? (
) : (
);
}
function ProgressRing({ percent }: { percent: number }) {
const radius = 18;
const circumference = 2 * Math.PI * radius;
const offset = circumference - (percent / 100) * circumference;
return (
{percent}%
);
}
function DetailItem({
icon: Icon,
label,
value,
extra,
editNode,
editing,
}: {
icon: typeof User;
label: string;
value: string;
extra?: React.ReactNode;
editNode?: React.ReactNode;
editing?: boolean;
}) {
return (
{label}
{editing && editNode ? (
{editNode}
) : (
)}
);
}
export function ProfilePage() {
const [profile, setProfile] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [editing, setEditing] = useState(false);
const [saving, setSaving] = useState(false);
const [editForm, setEditForm] = useState({});
useEffect(() => {
const fetchProfile = async () => {
try {
const res = await getMyProfile();
setProfile(res.data.data);
} catch (err) {
console.error("Failed to fetch profile", err);
setError("Failed to load profile. Please try again later.");
} finally {
setLoading(false);
}
};
fetchProfile();
}, []);
const startEditing = () => {
if (!profile) return;
setEditForm({
first_name: profile.first_name ?? "",
last_name: profile.last_name ?? "",
nick_name: profile.nick_name ?? "",
gender: profile.gender ?? "",
birth_day: profile.birth_day ?? "",
age_group: profile.age_group ?? "",
education_level: profile.education_level ?? "",
country: profile.country ?? "",
region: profile.region ?? "",
occupation: profile.occupation ?? "",
learning_goal: profile.learning_goal ?? "",
language_goal: profile.language_goal ?? "",
language_challange: profile.language_challange ?? "",
favoutite_topic: profile.favoutite_topic ?? "",
preferred_language: profile.preferred_language ?? "",
});
setEditing(true);
};
const cancelEditing = () => {
setEditing(false);
setEditForm({});
};
const handleSave = async () => {
setSaving(true);
try {
await updateProfile(editForm);
const res = await getMyProfile();
setProfile(res.data.data);
setEditing(false);
setEditForm({});
toast.success("Profile updated successfully");
} catch (err) {
console.error("Failed to update profile", err);
toast.error("Failed to update profile. Please try again.");
} finally {
setSaving(false);
}
};
const updateField = (field: keyof UpdateProfileRequest, value: string) => {
setEditForm((prev) => ({ ...prev, [field]: value }));
};
if (loading) return ;
if (error || !profile) {
return (
{error || "Profile not available"}
Please check your connection and try again.
);
}
const fullName = `${profile.first_name} ${profile.last_name}`;
const completionPct = profile.profile_completion_percentage ?? 0;
return (
{/* ─── Hero Card ─── */}
{/* Tall dark gradient banner with content inside */}
Hello {profile.first_name}
Track your account status, keep profile details up to date, and manage your learning preferences from one place.
{profile.role}
Last login {formatDate(profile.last_login)}
{completionPct}% complete
{!editing ? (
) : (
)}
{/* Identity info below banner */}
{editing ? (
updateField("first_name", e.target.value)}
placeholder="First name"
/>
updateField("last_name", e.target.value)}
placeholder="Last name"
/>
#{profile.id}
) : (
{fullName}
{profile.nick_name && (
@{profile.nick_name}
)}
#{profile.id}
)}
{/* Badges row */}
{profile.role}
{profile.status}
Joined {formatDate(profile.created_at)}
{/* ─── Detail Cards Grid ─── */}
{/* ── Contact & Personal ── */}
{/* Personal */}
Personal
updateField("birth_day", e.target.value)}
/>
}
/>
updateField("gender", e.target.value)}
>
}
/>
updateField("age_group", e.target.value)}
>
}
/>
updateField("occupation", e.target.value)}
placeholder="Occupation"
/>
}
/>
updateField("education_level", e.target.value)}
placeholder="Education level"
/>
}
/>
{/* ── Right Sidebar ── */}
{/* Profile Completion */}
Profile Completion
{completionPct === 100 ? "All set!" : "Complete your profile for the best experience."}
{/* Activity */}
Activity
Last Login
{formatDateTime(profile.last_login)}
Account Created
{formatDateTime(profile.created_at)}
{/* Quick Account Info */}
Account
Role
{profile.role}
Status
{profile.status}
Email
{profile.email}
Phone
{profile.phone_number || "—"}
{/* ─── Learning & Goals Card ─── */}
updateField("learning_goal", e.target.value)}
placeholder="Your learning goal"
/>
}
/>
updateField("language_goal", e.target.value)}
placeholder="Language goal"
/>
}
/>
updateField("language_challange", e.target.value)}
placeholder="Language challenge"
/>
}
/>
updateField("favoutite_topic", e.target.value)}
placeholder="Favourite topic"
/>
}
/>
);
}