"use client"; import * as React from "react"; import { redirect } from "next/navigation"; import Link from "next/link"; import { useSession } from "~/lib/auth-client"; import { api } from "~/trpc/react"; import { toast } from "sonner"; import { format } from "date-fns"; import { User, Mail, Shield, Lock, Settings, Building, Calendar, ChevronRight, Loader2, Save, X, Crown, FlaskConical, Eye, UserCheck, } from "lucide-react"; import { Button } from "~/components/ui/button"; import { Input } from "~/components/ui/input"; import { Label } from "~/components/ui/label"; import { Badge } from "~/components/ui/badge"; import { Separator } from "~/components/ui/separator"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "~/components/ui/card"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "~/components/ui/dialog"; interface Membership { studyId: string; role: string; joinedAt: Date; } function getMemberRole(memberships: Membership[], studyId: string): string { const membership = memberships.find((m) => m.studyId === studyId); return membership?.role ?? "observer"; } function ProfilePageContent() { const { data: session } = useSession(); const utils = api.useUtils(); const [isEditing, setIsEditing] = React.useState(false); const [name, setName] = React.useState(session?.user?.name ?? ""); const [email, setEmail] = React.useState(session?.user?.email ?? ""); const [passwordOpen, setPasswordOpen] = React.useState(false); const [currentPassword, setCurrentPassword] = React.useState(""); const [newPassword, setNewPassword] = React.useState(""); const [confirmPassword, setConfirmPassword] = React.useState(""); const { data: userData } = api.users.get.useQuery( { id: session?.user?.id ?? "" }, { enabled: !!session?.user?.id }, ); const { data: userStudies } = api.studies.list.useQuery({ memberOnly: true, limit: 10, }); const { data: membershipsData } = api.studies.getMyMemberships.useQuery(); const studyMemberships = membershipsData ?? []; const updateProfile = api.users.update.useMutation({ onSuccess: () => { toast.success("Profile updated successfully"); void utils.users.get.invalidate(); setIsEditing(false); }, onError: (error) => { toast.error("Failed to update profile", { description: error.message }); }, }); const changePassword = api.users.changePassword.useMutation({ onSuccess: () => { toast.success("Password changed successfully"); setPasswordOpen(false); setCurrentPassword(""); setNewPassword(""); setConfirmPassword(""); }, onError: (error) => { toast.error("Failed to change password", { description: error.message }); }, }); const handleSave = () => { if (!name.trim()) { toast.error("Name is required"); return; } updateProfile.mutate({ id: session?.user?.id ?? "", name, email }); }; const handlePasswordChange = (e: React.FormEvent) => { e.preventDefault(); if (newPassword !== confirmPassword) { toast.error("Passwords don't match"); return; } if (newPassword.length < 8) { toast.error("Password must be at least 8 characters"); return; } changePassword.mutate({ currentPassword, newPassword, }); }; const user = userData ?? session?.user; const roles = (userData as any)?.systemRoles ?? []; const initials = (user?.name ?? user?.email ?? "U").charAt(0).toUpperCase(); return (
{/* Header */}
{initials}

{user?.name ?? "User"}

{user?.email}

{roles.length > 0 && (
{roles.map((role: any) => ( {role.role} ))}
)}
{isEditing ? ( <> ) : ( )}
{/* Main Content */}
{/* Left Column - Profile Info */}
{/* Personal Information */} Personal Information Your public profile information
{isEditing ? ( setName(e.target.value)} placeholder="Your name" /> ) : (
{name || "Not set"}
)}
{isEditing ? ( setEmail(e.target.value)} placeholder="you@example.com" /> ) : (
{email}
)}
{user?.id ?? session?.user?.id}
{/* Recent Activity */} Recent Activity Your recent actions across the platform

No recent activity

Your recent actions will appear here

{/* Right Column - Settings */}
{/* Security */} Security

Password

Last changed: Never

Change Password Enter your current password and choose a new one.
setCurrentPassword(e.target.value)} required />
setNewPassword(e.target.value)} required minLength={8} />
setConfirmPassword(e.target.value)} required />

Danger Zone

Account deletion is not available. Contact an administrator for assistance.

{/* Studies Access */} Studies Access Studies you have access to {userStudies?.studies.slice(0, 5).map((study) => (
{(study.name ?? "S").charAt(0).toUpperCase()}

{study.name}

{getMemberRole(studyMemberships, study.id)}

))} {(!userStudies?.studies.length) && (

No studies yet

)} {userStudies && userStudies.studies.length > 5 && ( )}
); } export default function ProfilePage() { const { data: session, isPending } = useSession(); if (isPending) { return (
); } if (!session?.user) { redirect("/auth/signin"); } return ; }