'use client' import { useState } from 'react' import { useRouter } from 'next/navigation' import { toast } from 'sonner' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Textarea } from '@/components/ui/textarea' import { updateMyProfile, discloseAffiliations, requestEmailChange } from '@/lib/actions' export type ProfileInitial = { email: string display_name: string handle: string phone: string bio: string skills: string[] interests: string[] willing_to: string[] affiliations: string[] } const toList = (s: string): string[] => s.split(',').map(x => x.trim()).filter(Boolean) const sameList = (a: string[], b: string[]) => a.length === b.length && a.every((x, i) => x === b[i]) export function ProfileForm({ initial }: { initial: ProfileInitial }) { const router = useRouter() const [busy, setBusy] = useState(false) const [emailBusy, setEmailBusy] = useState(false) const [newEmail, setNewEmail] = useState('') const [displayName, setDisplayName] = useState(initial.display_name) const [handle, setHandle] = useState(initial.handle) const [phone, setPhone] = useState(initial.phone) const [bio, setBio] = useState(initial.bio) const [skills, setSkills] = useState(initial.skills.join(', ')) const [interests, setInterests] = useState(initial.interests.join(', ')) const [willingTo, setWillingTo] = useState(initial.willing_to.join(', ')) const [affiliations, setAffiliations] = useState(initial.affiliations.join(', ')) async function save() { if (!displayName.trim()) return toast.error('Display name is required.') setBusy(true) const res = await updateMyProfile({ display_name: displayName.trim(), handle: handle.trim() || null, phone: phone.trim() || null, bio: bio.trim() || null, skills: toList(skills), interests: toList(interests), willing_to: toList(willingTo), }) if ('error' in res && res.error) { setBusy(false) return toast.error(res.error) } // Only re-disclose affiliations when they actually changed, so the // conflict-of-interest disclosure timestamp is not reset on every save. const nextAffiliations = toList(affiliations) if (!sameList(nextAffiliations, initial.affiliations)) { const aff = await discloseAffiliations({ affiliations: nextAffiliations }) if ('error' in aff && aff.error) { setBusy(false) return toast.error(aff.error) } } setBusy(false) toast.success('Profile saved.') router.refresh() } async function changeEmail() { const e = newEmail.trim() if (!e) return toast.error('Enter the new email address.') setEmailBusy(true) const res = await requestEmailChange({ email: e }) setEmailBusy(false) if ('error' in res && res.error) return toast.error(res.error) setNewEmail('') toast.success( 'Confirmation sent. Check BOTH your current and new email to finish the change.', ) } return (
Login email
{initial.email || 'not set'}
You must confirm via links sent to both your current and new address.