diff --git a/app/api/interests/route.ts b/app/api/interests/route.ts index a733a23b..a9233da4 100644 --- a/app/api/interests/route.ts +++ b/app/api/interests/route.ts @@ -27,7 +27,7 @@ export async function GET() { cacheStrategy: cacheStrategy, }); - const connection = await prisma.connection.findMany({ + const connections = await prisma.connection.findMany({ select: { id: true, name: true, @@ -38,7 +38,7 @@ export async function GET() { cacheStrategy: cacheStrategy, }); - return NextResponse.json({ interests, causeAreas, connection }); + return NextResponse.json({ interests, causeAreas, connections }); } catch (error) { console.error('Error fetching interests:', error); return NextResponse.json( diff --git a/app/api/profile/route.ts b/app/api/profile/route.ts index 492a42ce..d78ebe1b 100644 --- a/app/api/profile/route.ts +++ b/app/api/profile/route.ts @@ -19,12 +19,17 @@ export async function GET() { intellectualInterests: { include: { interest: true - } - } + }, + }, + desiredConnections: { + include: { + connection: true + }, + }, } } } - }); + }); if (!user) { notFound(); diff --git a/app/api/user/update-profile/route.ts b/app/api/user/update-profile/route.ts index 35068e86..75fcdd65 100644 --- a/app/api/user/update-profile/route.ts +++ b/app/api/user/update-profile/route.ts @@ -14,7 +14,7 @@ export async function POST(req: Request) { } const data = await req.json(); - const { profile, image, name, interests = [] } = data; + const {profile, image, name, interests = [], connections = []} = data; Object.keys(profile).forEach(key => { if (profile[key] === '' || !profile[key]) { @@ -28,10 +28,10 @@ export async function POST(req: Request) { const result = await prisma.$transaction(async (prisma) => { // First, update/create the profile const updatedUser = await prisma.user.update({ - where: { email: session.user.email }, + where: {email: session.user.email}, data: { - ...(image && { image }), - ...(name && { name }), + ...(image && {image}), + ...(name && {name}), profile: { upsert: { create: profile, @@ -49,20 +49,20 @@ export async function POST(req: Request) { // First, find or create all interests const interestOperations = interests.map((interest: { id?: string; name: string }) => prisma.interest.upsert({ - where: { id: interest.id || '' }, - update: { name: interest.name }, - create: { name: interest.name }, + where: {id: interest.id || ''}, + update: {name: interest.name}, + create: {name: interest.name}, }) ); - + const createdInterests = await Promise.all(interestOperations); - + // Get the IDs of all created/updated interests const interestIds = createdInterests.map(interest => interest.id); // First, remove all existing interests for this profile await prisma.profileInterest.deleteMany({ - where: { profileId: updatedUser.profile.id }, + where: {profileId: updatedUser.profile.id}, }); // Then, create new connections @@ -77,6 +77,31 @@ export async function POST(req: Request) { } } + if (connections.length > 0 && updatedUser.profile) { + // First, find or create all interests + const connectionOperations = connections.map((v: { id?: string; name: string }) => + prisma.connection.upsert({ + where: {id: v.id || ''}, + update: {name: v.name}, + create: {name: v.name}, + }) + ); + const createdConnections = await Promise.all(connectionOperations); + const connectionIds = createdConnections.map(v => v.id); + await prisma.profileConnection.deleteMany({ + where: {profileId: updatedUser.profile.id}, + }); + if (connectionIds.length > 0) { + await prisma.profileConnection.createMany({ + data: connectionIds.map(id => ({ + profileId: updatedUser.profile!.id, + connectionId: id, + })), + skipDuplicates: true, + }); + } + } + return updatedUser; }); diff --git a/app/complete-profile/page.tsx b/app/complete-profile/page.tsx index 8bbd451e..43b12213 100644 --- a/app/complete-profile/page.tsx +++ b/app/complete-profile/page.tsx @@ -36,10 +36,15 @@ function RegisterComponent() { const [isUploading, setIsUploading] = useState(false); const [error, setError] = useState(''); const [allInterests, setAllInterests] = useState<{ id: string, name: string }[]>([]); + const [allConnections, setAllConnections] = useState<{ id: string, name: string }[]>([]); const [selectedInterests, setSelectedInterests] = useState>(new Set()); + const [selectedConnections, setSelectedConnections] = useState>(new Set()); const [newInterest, setNewInterest] = useState(''); + const [newConnection, setNewConnection] = useState(''); const dropdownRef = useRef(null); + const dropdownRefC = useRef(null); const [showDropdown, setShowDropdown] = useState(false); + const [showDropdownC, setShowDropdownC] = useState(false); const [isLoading, setIsLoading] = useState(true); const fileInputRef = useRef(null); const router = useRouter(); @@ -74,9 +79,15 @@ function RegisterComponent() { // Set selected interests if any if (profile.intellectualInterests?.length > 0) { - const interestIds = profile.intellectualInterests + const ids = profile.intellectualInterests .map((pi: any) => pi.interest.id); - setSelectedInterests(new Set(interestIds)); + setSelectedInterests(new Set(ids)); + } + + if (profile.desiredConnections?.length > 0) { + const ids = profile.desiredConnections + .map((pi: any) => pi.connection.id); + setSelectedConnections(new Set(ids)); } setImages([]) @@ -127,6 +138,53 @@ function RegisterComponent() { }; }, []); + // Load existing connections + useEffect(() => { + async function fetchConnections() { + try { + const res = await fetch('/api/interests'); + if (res.ok) { + const data = await res.json(); + setAllConnections(data.connections || []); + } + } catch (error) { + console.error('Error loading interests:', error); + } + } + + fetchConnections(); + + // Close dropdown when clicking outside + const handleClickOutside = (event: MouseEvent) => { + if (dropdownRefC.current && !dropdownRefC.current.contains(event.target as Node)) { + setShowDropdownC(false); + } + }; + + document.addEventListener('mousedown', handleClickOutside); + return () => { + document.removeEventListener('mousedown', handleClickOutside); + }; + }, []); + + const toggleConnection = (id: string) => { + setSelectedConnections(prev => { + const newSet = new Set(prev); + if (newSet.has(id)) { + newSet.delete(id); + } else { + newSet.add(id); + } + return newSet; + }); + }; + + const handleKeyDownC = (e: React.KeyboardEvent) => { + if (e.key === 'Escape') { + setShowDropdownC(false); + } + }; + if (isLoading) { return (
@@ -135,6 +193,51 @@ function RegisterComponent() { ); } + const toggleInterest = (interestId: string) => { + setSelectedInterests(prev => { + const newSet = new Set(prev); + if (newSet.has(interestId)) { + newSet.delete(interestId); + } else { + newSet.add(interestId); + } + return newSet; + }); + }; + + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === 'Enter') { + e.preventDefault(); + addNewInterest(); + } else if (e.key === 'Escape') { + setShowDropdown(false); + } + }; + + const addNewInterest = (e?: React.FormEvent) => { + if (e) e.preventDefault(); + const interestToAdd = newInterest.trim(); + if (!interestToAdd) return; + + // Check if interest already exists (case-insensitive) + const existingInterest = allInterests.find( + i => i.name.toLowerCase() === interestToAdd.toLowerCase() + ); + + if (existingInterest) { + // Toggle selection if it exists + toggleInterest(existingInterest.id); + } else { + // Add new interest + const newInterestObj = {id: `new-${Date.now()}`, name: interestToAdd}; + setAllInterests(prev => [...prev, newInterestObj]); + setSelectedInterests(prev => new Set(prev).add(newInterestObj.id)); + } + + setNewInterest(''); + setShowDropdown(false); + }; + const handleImagesUpload = async (e: ChangeEvent) => { return handleImageUpload(e, false); } @@ -193,51 +296,6 @@ function RegisterComponent() { } }; - const toggleInterest = (interestId: string) => { - setSelectedInterests(prev => { - const newSet = new Set(prev); - if (newSet.has(interestId)) { - newSet.delete(interestId); - } else { - newSet.add(interestId); - } - return newSet; - }); - }; - - const handleKeyDown = (e: React.KeyboardEvent) => { - if (e.key === 'Enter') { - e.preventDefault(); - addNewInterest(); - } else if (e.key === 'Escape') { - setShowDropdown(false); - } - }; - - const addNewInterest = (e?: React.FormEvent) => { - if (e) e.preventDefault(); - const interestToAdd = newInterest.trim(); - if (!interestToAdd) return; - - // Check if interest already exists (case-insensitive) - const existingInterest = allInterests.find( - i => i.name.toLowerCase() === interestToAdd.toLowerCase() - ); - - if (existingInterest) { - // Toggle selection if it exists - toggleInterest(existingInterest.id); - } else { - // Add new interest - const newInterestObj = {id: `new-${Date.now()}`, name: interestToAdd}; - setAllInterests(prev => [...prev, newInterestObj]); - setSelectedInterests(prev => new Set(prev).add(newInterestObj.id)); - } - - setNewInterest(''); - setShowDropdown(false); - }; - const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!session?.user?.email) return; @@ -260,10 +318,15 @@ function RegisterComponent() { conflictStyle: conflictStyle as ConflictStyle, images: keys, }, + allConnections, interests: Array.from(selectedInterests).map(id => ({ id: id.startsWith('new-') ? undefined : id, name: allInterests.find(i => i.id === id)?.name || id.replace('new-', '') })), + connections: Array.from(selectedConnections).map(id => ({ + id: id, + name: allConnections.find(i => i.id === id)?.name || id + })), ...(key && {image: key}), ...(name && {name}), }; @@ -436,6 +499,96 @@ function RegisterComponent() { />
+
+ +
+
+ setNewConnection(e.target.value)} + onFocus={() => setShowDropdownC(true)} + onKeyDown={handleKeyDownC} + className="flex-1 min-w-0 block w-full px-3 py-2 rounded-l-md border-0 focus:ring-blue-500 focus:border-blue-500 sm:text-sm" + placeholder="Type to search" + /> + +
+
+ + {(showDropdownC) && (
+ {allConnections + .filter(v => v.name.toLowerCase().includes(newConnection.toLowerCase())) + .map((v) => ( +
{ + toggleConnection(v.id); + setNewConnection(''); + // setNewInterest(''); + }} + > +
+ { + }} + onClick={(e) => e.stopPropagation()} + /> + {v.name} +
+
+ ))} +
+ ) + } +
+ {Array.from(selectedConnections).map(id => { + const v = allConnections.find(i => i.id === id); + if (!v) return null; + return ( + + {v.name} + + + ); + })} +
+
+