import { useEffect, useState } from 'react'; import { Loader2, Check, AlertTriangle } from 'lucide-react'; import { Button } from './ui/button'; import { Card, CardContent, CardHeader, CardTitle } from './ui/card'; import { Input } from './ui/input'; import { Label } from './ui/label'; import { authClient, useSession, signOut, updateUser } from '../lib/auth-client'; import { validatePhoneOrEmail } from '../lib/validators'; export function ProfileSettings() { const { data: session } = useSession(); const [userName, setUserName] = useState(''); const [savingName, setSavingName] = useState(false); const [nameSaved, setNameSaved] = useState(false); const [nameError, setNameError] = useState(''); const [piFirstName, setPiFirstName] = useState(''); const [bldgCode, setBldgCode] = useState(''); const [lab, setLab] = useState(''); const [contact, setContact] = useState(''); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [error, setError] = useState(''); const [saved, setSaved] = useState(false); const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); const [deleting, setDeleting] = useState(false); const [deleteError, setDeleteError] = useState(''); useEffect(() => { if (session?.user.name) setUserName(session.user.name); }, [session?.user.name]); useEffect(() => { fetch('/api/profile', { credentials: 'include' }) .then(r => (r.ok ? r.json() : null)) .then(data => { if (data) { setPiFirstName(data.pi_first_name || ''); setBldgCode(data.bldg_code || ''); setLab(data.lab || ''); setContact(data.contact || ''); } }) .finally(() => setLoading(false)); }, []); async function handleSaveName() { setNameError(''); setNameSaved(false); const trimmed = userName.trim(); setSavingName(true); const res = await fetch('/api/account/name', { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify({ name: trimmed || null }), }); setSavingName(false); if (!res.ok) { const data = await res.json().catch(() => ({})); setNameError(data.error || 'Failed to save name.'); } else { await authClient.getSession({ fetchOptions: { cache: 'no-store' } }); setNameSaved(true); setTimeout(() => setNameSaved(false), 3000); } } async function handleSubmit(e: React.FormEvent) { e.preventDefault(); setError(''); setSaved(false); if (contact.trim() && !validatePhoneOrEmail(contact.trim())) { setError('Contact must be a valid phone number or email address.'); return; } setSaving(true); const res = await fetch('/api/profile', { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify({ pi_first_name: piFirstName.trim(), bldg_code: bldgCode.trim(), lab: lab.trim(), contact: contact.trim() || undefined, }), }); setSaving(false); if (res.ok) { setSaved(true); setTimeout(() => setSaved(false), 3000); } else { const data = await res.json().catch(() => ({})); setError(data.error || 'Failed to save profile.'); } } if (loading) { return (
); } return (

Profile settings

Update your account details and lab defaults.

Account
setUserName(e.target.value)} placeholder="Your name" />

{session?.user.email || '—'}

{nameError &&

{nameError}

} {nameSaved && (

Name saved

)}
Lab defaults
setPiFirstName(e.target.value)} placeholder="e.g. Smith" />
setBldgCode(e.target.value)} placeholder="e.g. EER" />
setLab(e.target.value)} placeholder="e.g. 3.822" />
setContact(e.target.value)} placeholder="Phone (e.g. 555-123-4567) or email" />
{error &&

{error}

} {saved && (

Saved

)}
Delete account {!showDeleteConfirm ? ( <>

Permanently delete your account and all associated data including chemicals and protocols. This action cannot be undone.

) : ( <>

Are you sure? All your data will be permanently deleted.

{deleteError && (

{deleteError}

)}
)}

Privacy Policy

); }