Skip to content

Commit 0b7175e

Browse files
committed
started vibecoding
1 parent e13a7db commit 0b7175e

File tree

1 file changed

+237
-98
lines changed

1 file changed

+237
-98
lines changed

pages/profile/[username].tsx

Lines changed: 237 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import InternalLink from "../../components/Link";
2525
import EmailIcon from "../../public/profile/email.svg";
2626
import LinkedInIcon from "../../public/profile/linkedin.svg";
2727
import NavbarBuilder from "../../components/NavBar";
28+
import { FieldOfStudy, Year } from "../../constants/profile";
29+
import MemberBadges from "../../components/MemberBadges";
2830

2931
// Username included separately
3032
export type Profile = {
@@ -101,9 +103,9 @@ const UserProfile: NextPage = () => {
101103
);
102104

103105
useEffect(() => {
104-
document.body.classList.add("bg-gray-800");
106+
document.body.classList.add("bg-gray-50");
105107
return () => {
106-
document.body.classList.remove("bg-gray-800");
108+
document.body.classList.remove("bg-gray-50");
107109
};
108110
}, []);
109111

@@ -233,7 +235,7 @@ const UserProfile: NextPage = () => {
233235
}
234236

235237
return (
236-
<div className="h-screen">
238+
<div className="min-h-screen bg-gray-50">
237239
<NavbarBuilder />
238240
<Formik
239241
enableReinitialize // to update when resetting initialProfile after submit
@@ -242,122 +244,259 @@ const UserProfile: NextPage = () => {
242244
onSubmit={saveProfile}
243245
>
244246
{({ values, isSubmitting }) => (
245-
<div className="bg-gray-800 min-w-screen p-4 md:p-8 md:pl-16 flex items-center text-white">
247+
<div className="py-10">
246248
<Head title={profileUsername} />
247249
<Form>
248-
{values.avatar && (
249-
<div className="flex flex-col md:flex-row justify-around items-center">
250-
<div className="m-4 mx-0 flex flex-row justify-between items-center">
251-
<ViewAvatar avatar={values.avatar} />
252-
<h2 className="text-2xl ml-4">
253-
<b>{values.name}</b> ({profileUsername})
254-
<div className="flex flex-row gap-x-5 p-0 py-2">
255-
<InternalLink
256-
href={`mailto:${values.email}`}
257-
target="_blank"
258-
rel="noopener noreferrer"
259-
>
260-
<EmailIcon className="h-6 w-6 fill-white" />
261-
</InternalLink>
262-
<InternalLink
263-
href={values.linkedin ?? ""}
264-
target="_blank"
265-
>
250+
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
251+
<div className="bg-white shadow-sm rounded-lg overflow-hidden">
252+
{/* Header Section with Avatar and Basic Info */}
253+
<div className="bg-gradient-to-r from-gray-100 to-gray-200 px-6 py-8">
254+
<div className="flex flex-col md:flex-row items-center">
255+
<div className="relative">
256+
{values.avatar ? (
257+
<div className="relative">
258+
<ViewAvatar avatar={values.avatar} />
259+
{editMode && (
260+
<div className="absolute -bottom-2 -right-2">
261+
<EditAvatar />
262+
</div>
263+
)}
264+
</div>
265+
) : (
266+
<div className="h-32 w-32 rounded-full bg-gray-300 flex items-center justify-center text-gray-500">
267+
{values.name ? values.name.charAt(0).toUpperCase() : "?"}
268+
</div>
269+
)}
270+
</div>
271+
272+
<div className="mt-6 md:mt-0 md:ml-8 text-center md:text-left">
273+
<h1 className="text-3xl font-bold text-gray-900">{values.name}</h1>
274+
<p className="text-gray-600">@{profileUsername}</p>
275+
276+
{/* Social links */}
277+
<div className="flex items-center justify-center md:justify-start space-x-4 mt-3">
278+
<a
279+
href={`mailto:${values.email}`}
280+
target="_blank"
281+
rel="noopener noreferrer"
282+
className="text-gray-600 hover:text-gray-900"
283+
>
284+
<EmailIcon className="h-5 w-5 fill-current" />
285+
</a>
266286
{values.linkedin && (
267-
<LinkedInIcon className="h-6 w-6 fill-white" />
287+
<a
288+
href={values.linkedin}
289+
target="_blank"
290+
rel="noopener noreferrer"
291+
className="text-gray-600 hover:text-gray-900"
292+
>
293+
<LinkedInIcon className="h-5 w-5 fill-current" />
294+
</a>
295+
)}
296+
{values.website && /^https?:\/\//.test(values.website) && (
297+
<a
298+
href={values.website}
299+
target="_blank"
300+
rel="noopener noreferrer"
301+
className="text-gray-600 hover:text-gray-900"
302+
>
303+
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
304+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9" />
305+
</svg>
306+
</a>
268307
)}
269-
</InternalLink>
308+
</div>
309+
</div>
310+
311+
{/* Edit button for small screens */}
312+
<div className="mt-6 md:hidden w-full">
313+
{!editMode && isCurrentUser && (
314+
<button
315+
className="w-full py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
316+
onClick={() => {
317+
ReactGA.event({
318+
category: "Profile",
319+
action: "Entered edit mode",
320+
});
321+
setEditMode(true);
322+
}}
323+
type="button"
324+
>
325+
Edit Profile
326+
</button>
327+
)}
270328
</div>
271-
</h2>
329+
330+
{/* Edit button for larger screens */}
331+
<div className="hidden md:block md:ml-auto">
332+
{!editMode && isCurrentUser && (
333+
<button
334+
className="inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
335+
onClick={() => {
336+
ReactGA.event({
337+
category: "Profile",
338+
action: "Entered edit mode",
339+
});
340+
setEditMode(true);
341+
}}
342+
type="button"
343+
>
344+
<svg className="-ml-1 mr-2 h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
345+
<path d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z" />
346+
</svg>
347+
Edit Profile
348+
</button>
349+
)}
350+
</div>
351+
</div>
272352
</div>
273-
<div className="flex-1">{editMode && <EditAvatar />}</div>
274-
</div>
275-
)}
276353

277-
{/* Not allowing name or username changes for now */}
278-
{/* <h2 className="text-2xl my-4">
279-
<b>{values.name}</b> ({profileUsername})
280-
</h2> */}
281-
{editMode ? (
282-
<EditProfile profile={values} />
283-
) : (
284-
<ViewProfile profile={values} />
285-
)}
354+
{/* Profile Content */}
355+
<div className="px-6 py-6">
356+
{/* Main content area */}
357+
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
358+
{/* Left column - Personal info */}
359+
<div className="md:col-span-2">
360+
{/* Bio section */}
361+
<div className="mb-6">
362+
<h2 className="text-lg font-medium text-gray-900 mb-2">About</h2>
363+
<div className="prose max-w-none text-gray-700">
364+
{editMode ? (
365+
<EditProfile profile={values} />
366+
) : (
367+
<>
368+
{values.bio ? (
369+
<p>{values.bio}</p>
370+
) : (
371+
<p className="text-gray-400 italic">No bio provided</p>
372+
)}
373+
</>
374+
)}
375+
</div>
376+
</div>
286377

287-
{/* Don't want to show resume on public profile */}
288-
{editMode && (
289-
<div className="grid grid-cols-6 gap-6 pb-4 justify-center items-center pt-4">
290-
{values.resume && (
291-
<div className="col-span-6 sm:col-span-3">
292-
<ViewResume resume={values.resume} />
378+
{/* Resume section - Only in edit mode */}
379+
{editMode && (
380+
<div className="mb-6 border-t border-gray-200 pt-6">
381+
<h2 className="text-lg font-medium text-gray-900 mb-2">Resume</h2>
382+
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 items-center">
383+
{values.resume && (
384+
<div className="col-span-1">
385+
<ViewResume resume={values.resume} />
386+
</div>
387+
)}
388+
<div className="col-span-1">
389+
<EditResume label="Upload your resume" />
390+
</div>
391+
</div>
392+
</div>
393+
)}
394+
395+
{/* Partner sharing consent - Only in edit mode */}
396+
{editMode && (
397+
<div className="mb-6 border-t border-gray-200 pt-6">
398+
<PartnerSharingConsentField />
399+
</div>
400+
)}
401+
</div>
402+
403+
{/* Right column - Education & Skills */}
404+
<div className="md:col-span-1">
405+
<div className="bg-gray-50 rounded-lg p-4">
406+
{/* Education info */}
407+
<div className="mb-4">
408+
<h2 className="text-lg font-medium text-gray-900 mb-2">Education</h2>
409+
{values.year && (
410+
<div className="mb-1 flex">
411+
<span className="text-gray-500 w-20">Year:</span>
412+
<span className="text-gray-900">{Year[values.year]}</span>
413+
</div>
414+
)}
415+
{values.fields_of_study && values.fields_of_study.majors.length > 0 && (
416+
<div className="mb-1 flex flex-wrap">
417+
<span className="text-gray-500 w-20">Major{values.fields_of_study.majors.length > 1 ? 's' : ''}:</span>
418+
<span className="text-gray-900">
419+
{values.fields_of_study.majors
420+
.map((majorKey) => FieldOfStudy[majorKey])
421+
.join(", ")}
422+
</span>
423+
</div>
424+
)}
425+
{values.fields_of_study && values.fields_of_study.minors && values.fields_of_study.minors.length > 0 && (
426+
<div className="mb-1 flex flex-wrap">
427+
<span className="text-gray-500 w-20">Minor{values.fields_of_study.minors.length > 1 ? 's' : ''}:</span>
428+
<span className="text-gray-900">
429+
{values.fields_of_study.minors
430+
.map((minorKey) => FieldOfStudy[minorKey])
431+
.join(", ")}
432+
</span>
433+
</div>
434+
)}
435+
</div>
436+
437+
{/* Interests & roles */}
438+
{(values.interests?.length > 0 || values.roles?.length > 0) && (
439+
<div>
440+
<h2 className="text-lg font-medium text-gray-900 mb-2">Interests & Skills</h2>
441+
<div className="mt-2">
442+
{values.interests && (
443+
<div className="pt-1">
444+
<MemberBadges roles={values.roles} interests={values.interests} />
445+
</div>
446+
)}
447+
</div>
448+
</div>
449+
)}
450+
</div>
451+
</div>
293452
</div>
294-
)}
295-
<div className="col-span-6 sm:col-span-3">
296-
<EditResume label="Upload your resume" />
297453
</div>
298-
</div>
299-
)}
300-
301-
{editMode && <PartnerSharingConsentField />}
302454

303-
{dataFetchErrors.map((error) => (
304-
<p key={error} className="text-red-500">
305-
{error}
306-
</p>
307-
))}
455+
{/* Error Messages */}
456+
{(dataFetchErrors.length > 0 || formSubmitErrors.length > 0) && (
457+
<div className="bg-red-50 px-6 py-4 border-t border-red-200">
458+
{dataFetchErrors.map((error) => (
459+
<p key={error} className="text-red-600 text-sm">
460+
{error}
461+
</p>
462+
))}
463+
{formSubmitErrors.map((error) => (
464+
<p key={error} className="text-red-600 text-sm">
465+
{error}
466+
</p>
467+
))}
468+
</div>
469+
)}
308470

309-
<div className="mt-8 flex">
310-
{editMode ? (
311-
<>
312-
<button
313-
className="btn-gold-gradient"
314-
onClick={() => {
315-
ReactGA.event({
316-
category: "Profile",
317-
action: "Exited edit mode",
318-
});
319-
setEditMode(false);
320-
}}
321-
disabled={isSubmitting}
322-
type="button"
323-
>
324-
Cancel
325-
</button>
326-
&nbsp;&nbsp;
327-
<button
328-
className="btn-gold-gradient"
329-
disabled={
330-
isSubmitting || isObjectEqual(values, initialProfile)
331-
}
332-
type="submit"
333-
>
334-
{isSubmitting ? "Saving..." : "Save Profile"}
335-
</button>
336-
{formSubmitErrors.map((error) => (
337-
<p key={error} className="text-red-500">
338-
{error}
339-
</p>
340-
))}
341-
</>
342-
) : (
343-
<>
344-
{isCurrentUser && (
471+
{/* Edit Mode Footer */}
472+
{editMode && (
473+
<div className="bg-gray-50 px-6 py-4 border-t border-gray-200 flex justify-end space-x-3">
345474
<button
346-
className="btn-gold-gradient"
475+
className="py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
347476
onClick={() => {
348477
ReactGA.event({
349478
category: "Profile",
350-
action: "Entered edit mode",
479+
action: "Exited edit mode",
351480
});
352-
setEditMode(true);
481+
setEditMode(false);
353482
}}
483+
disabled={isSubmitting}
354484
type="button"
355485
>
356-
Edit Profile
486+
Cancel
357487
</button>
358-
)}
359-
</>
360-
)}
488+
<button
489+
className="py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
490+
disabled={
491+
isSubmitting || isObjectEqual(values, initialProfile)
492+
}
493+
type="submit"
494+
>
495+
{isSubmitting ? "Saving..." : "Save Profile"}
496+
</button>
497+
</div>
498+
)}
499+
</div>
361500
</div>
362501
</Form>
363502
</div>

0 commit comments

Comments
 (0)