"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 (
{user?.email}
{roles.length > 0 && (No recent activity
Your recent actions will appear here
Password
Last changed: Never
Danger Zone
Account deletion is not available. Contact an administrator for assistance.
{study.name}
{getMemberRole(studyMemberships, study.id)}
No studies yet