import { useEffect, useState, type ChangeEvent } from "react";
import { BadgeCheck, Briefcase, CalendarDays, Mail, Phone, Shield, User } from "lucide-react";
import { Badge } from "../components/ui/badge";
import { Button } from "../components/ui/button";
import { Card, CardContent } from "../components/ui/card";
import {
Dialog,
DialogContent,
DialogFooter,
DialogHeader,
DialogTitle,
} from "../components/ui/dialog";
import { Input } from "../components/ui/input";
import { Textarea } from "../components/ui/textarea";
import { FileUpload } from "../components/ui/file-upload";
import { getMyProfile } from "../api/users.api";
import { updateTeamMember } from "../api/team.api";
import { uploadImageFile } from "../api/files.api";
import { SpinnerIcon } from "../components/ui/spinner-icon";
import type { UpdateTeamMemberRequest } from "../types/team.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",
});
}
interface TeamMeProfile {
id: number
first_name: string
last_name: string
email: string
phone_number: string
team_role: string
department: string
job_title: string
employment_type: string
hire_date: string
bio: string
status: string
email_verified: boolean
permissions: string[]
last_login: string | null
created_at: string
emergency_contact?: string
work_phone?: string
profile_picture_url?: string
}
function LoadingSkeleton() {
return (
{[1, 2, 3].map((i) => (
{[1, 2, 3, 4].map((j) => (
))}
))}
);
}
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 [profilePictureFile, setProfilePictureFile] = useState(null);
const [editForm, setEditForm] = useState({
first_name: "",
last_name: "",
phone_number: "",
profile_picture_url: "",
bio: "",
});
useEffect(() => {
const fetchProfile = async () => {
try {
const res = await getMyProfile();
setProfile((res.data?.data ?? null) as unknown as TeamMeProfile | null);
} 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;
const nextForm: UpdateTeamMemberRequest = {
first_name: profile.first_name ?? "",
last_name: profile.last_name ?? "",
phone_number: profile.phone_number ?? "",
profile_picture_url: profile.profile_picture_url ?? "",
bio: profile.bio ?? "",
};
setEditForm(nextForm);
setProfilePictureFile(null);
setEditing(true);
};
const cancelEditing = () => {
setProfilePictureFile(null);
setEditing(false);
};
const updateField = (field: keyof UpdateTeamMemberRequest, value: string) => {
setEditForm((prev) => ({ ...prev, [field]: value }));
};
const handleSave = async () => {
if (!profile) return;
let nextProfilePictureUrl = editForm.profile_picture_url ?? "";
if (profilePictureFile) {
try {
const uploadRes = await uploadImageFile(profilePictureFile);
const uploadedUrl = uploadRes.data?.data?.url?.trim();
if (!uploadedUrl) throw new Error("Missing uploaded image url");
nextProfilePictureUrl = uploadedUrl;
} catch (err) {
console.error("Failed to upload profile picture:", err);
toast.error("Failed to upload profile picture");
return;
}
}
const payload: UpdateTeamMemberRequest = {
bio: editForm.bio ?? "",
first_name: editForm.first_name ?? "",
last_name: editForm.last_name ?? "",
phone_number: editForm.phone_number ?? "",
profile_picture_url: nextProfilePictureUrl,
};
setSaving(true);
try {
await updateTeamMember(profile.id, payload);
const refreshed = await getMyProfile();
setProfile((refreshed.data?.data ?? null) as unknown as TeamMeProfile | null);
setEditing(false);
setProfilePictureFile(null);
toast.success("Profile updated successfully");
} catch (err) {
console.error("Failed to update team member profile", err);
toast.error("Failed to update profile");
} finally {
setSaving(false);
}
};
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 initials = `${profile.first_name?.[0] ?? ""}${profile.last_name?.[0] ?? ""}`.toUpperCase();
return (
Summary
{profile.job_title || "Role-focused work item"}
{profile.team_role || "Team responsibility"}
{profile.email}
{profile.phone_number || "No phone number"}
Employment
{profile.department || "Department not set"}
Employment type: {profile.employment_type || "—"}
More about me
Status {profile.status}
Email {profile.email_verified ? "verified" : "not verified"}
Joined {formatDate(profile.created_at)}
Last login {formatDateTime(profile.last_login)}
First Name
{profile.first_name}
Last Name
{profile.last_name}
Department
{profile.department || "—"}
Team Role
{profile.team_role || "—"}
Job Title
{profile.job_title || "—"}
Hire Date
{formatDate(profile.hire_date) || "—"}
Phone Number
{profile.phone_number || "—"}
);
}