Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions app/profile/labs/new/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import Link from "next/link";
import { ChevronDown } from "lucide-react";

type LabOption = {
id: string;
name: string;
};

const fallbackLabs: LabOption[] = [
{ id: "xu-computational-neuroscience-lab", name: "Xu Computational Neuroscience Lab" },
{ id: "cognitive-systems-core", name: "Cognitive Systems Core" },
{ id: "bioengineering-shared-facility", name: "Bioengineering Shared Facility" },
];

export default function AddLabAffiliationPage() {
const labOptions = fallbackLabs;

return (
<main className="min-h-screen bg-[#f7f6f2] text-[#111111]">
<div className="mx-auto flex min-h-screen max-w-[1512px] items-center justify-center px-6 py-14 sm:px-10">
<section className="w-full max-w-[760px] rounded-[24px] border border-[#d9dee6] bg-white p-8 shadow-[0_18px_40px_rgba(15,23,42,0.08)] sm:p-12">
<div className="mb-10 space-y-3">
<h1 className="text-4xl font-semibold tracking-[-0.03em] text-[#111111]">
Add Lab Affiliation
</h1>
<p className="max-w-[520px] text-sm leading-6 text-[#69707a] sm:text-base">
Choose a lab, add your role, and record when you joined so it can
appear on your profile page.
</p>
</div>

<form className="space-y-7">
<div className="space-y-3">
<label
htmlFor="labName"
className="block text-sm font-semibold text-[#222222]"
>
Lab Name
</label>
<div className="relative">
<select
id="labName"
name="labName"
defaultValue=""
className="h-14 w-full appearance-none rounded-xl border border-[#d9dee6] bg-white px-4 text-base text-[#111111] outline-none transition focus:border-[#245f86] focus:ring-2 focus:ring-[#245f86]/20"
>
<option value="" disabled>
Select a lab from the database
</option>
{labOptions.map((lab) => (
<option key={lab.id} value={lab.id}>
{lab.name}
</option>
))}
</select>
<ChevronDown className="pointer-events-none absolute right-4 top-1/2 h-5 w-5 -translate-y-1/2 text-[#7f8a95]" />
</div>
</div>

<div className="space-y-3">
<label
htmlFor="labRole"
className="block text-sm font-semibold text-[#222222]"
>
Lab Role
</label>
<input
id="labRole"
name="labRole"
type="text"
placeholder="e.g., Research Assistant, Lab Manager"
className="h-14 w-full rounded-xl border border-[#d9dee6] bg-white px-4 text-base text-[#111111] outline-none transition placeholder:text-[#98a0aa] focus:border-[#245f86] focus:ring-2 focus:ring-[#245f86]/20"
/>
</div>

<div className="space-y-3">
<label
htmlFor="dateJoined"
className="block text-sm font-semibold text-[#222222]"
>
Date Joined
</label>
<input
id="dateJoined"
name="dateJoined"
type="date"
className="h-14 w-full rounded-xl border border-[#d9dee6] bg-white px-4 text-base text-[#111111] outline-none transition focus:border-[#245f86] focus:ring-2 focus:ring-[#245f86]/20"
/>
</div>

<div className="flex flex-col-reverse gap-3 pt-3 sm:flex-row sm:justify-end">
<Link
href="/profile?labs=empty"
className="inline-flex h-12 items-center justify-center rounded-xl border border-[#d9dee6] bg-white px-6 text-sm font-semibold text-[#222222] transition hover:bg-[#f7f9fb]"
>
Cancel
</Link>
<button
type="submit"
className="inline-flex h-12 items-center justify-center rounded-xl bg-[#245f86] px-6 text-sm font-semibold text-white transition hover:bg-[#1d4d6d]"
>
Add Lab
</button>
</div>
</form>
</section>
</div>
</main>
);
}
120 changes: 101 additions & 19 deletions app/profile/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,41 @@ import {
CalendarDays,
FlaskConical,
Mail,
Phone,
Plus,
UserRound,
} from "lucide-react";

type Affiliation = {
id: string;
labName: string;
role: string;
joined: string;
};

const profile = {
name: "Dr. Xu",
pronouns: "He/him",
bio: "Experienced principal investigator at a lab specializing in computational neuroscience. Our lab focuses on developing innovative techniques for analysis in computational neuroscience.",
email: "Xu@ucsd.edu",
phone: "(xxx) xxx-xxxx",
labName: "Xu Computational Neuroscience Lab",
role: "Principal Investigator (PI)",
joined: "March 2026",
status: "Active",
};

const sampleAffiliations: Affiliation[] = [
{
id: "xu-comp-neuro",
labName: "Xu Computational Neuroscience Lab",
role: "Principal Investigator (PI)",
joined: "March 2026",
},
{
id: "cognitive-systems-core",
labName: "Cognitive Systems Core",
role: "Lab Advisor",
joined: "January 2025",
},
];

function InfoCard({
icon,
title,
Expand All @@ -35,7 +54,7 @@ function InfoCard({
<div className="text-[#ff5a00]">{icon}</div>
<h2 className="text-2xl font-semibold tracking-[-0.02em] text-[#111111]">{title}</h2>
</div>
<div className="space-y-8">{children}</div>
{children}
</section>
);
}
Expand All @@ -55,7 +74,78 @@ function InfoRow({
);
}

export default function ProfilePage() {
function LabAffiliationsCard({
affiliations,
}: Readonly<{
affiliations: Affiliation[];
}>) {
if (affiliations.length === 0) {
return (
<InfoCard
icon={<FlaskConical className="h-10 w-10" strokeWidth={1.8} />}
title="Lab and Affiliation"
>
<div className="flex min-h-[220px] flex-col items-center justify-center gap-6 text-center">
<p className="max-w-[280px] text-sm leading-6 text-[#444444]">
You don&apos;t have a lab listed yet. Add your affiliation to connect
with other researchers and manage your equipment listings.
</p>
<Link
href="/profile/labs/new"
className="inline-flex items-center justify-center rounded-xl bg-[#245f86] px-7 py-3 text-sm font-semibold text-white transition-colors hover:bg-[#1d4d6d]"
>
Add Lab
</Link>
</div>
</InfoCard>
);
}

return (
<InfoCard
icon={<FlaskConical className="h-10 w-10" strokeWidth={1.8} />}
title="Lab and Affiliation"
>
<div className="space-y-7">
{affiliations.map((affiliation, index) => (
<div
key={affiliation.id}
className={index === affiliations.length - 1 ? "" : "border-b border-[#d7dbe1] pb-7"}
>
<div className="space-y-6">
<InfoRow label="Laboratory name" value={affiliation.labName} />
<InfoRow label="Role at lab" value={affiliation.role} />
<div className="flex items-center gap-4 pt-1 text-[#111111]">
<CalendarDays className="h-8 w-8 text-[#2d2d2d]" strokeWidth={1.8} />
<p className="text-xl font-medium">Joined {affiliation.joined}.</p>
</div>
</div>
</div>
))}

<div className="pt-1">
<Link
href="/profile/labs/new"
className="inline-flex items-center gap-2 rounded-xl border border-[#cdd7df] bg-white px-4 py-2 text-sm font-semibold text-[#245f86] transition-colors hover:bg-[#f4f9fc]"
>
<Plus className="h-4 w-4" />
Add another lab
</Link>
</div>
</div>
</InfoCard>
);
}

export default async function ProfilePage({
searchParams,
}: Readonly<{
searchParams?: Promise<{ labs?: string }>;
}>) {
const resolvedParams = searchParams ? await searchParams : undefined;
const affiliations =
resolvedParams?.labs === "empty" ? [] : sampleAffiliations;

return (
<main className="min-h-screen bg-[#f7f6f2] text-[#111111]">
<div className="border-b border-[#ece4bd] bg-gradient-to-r from-[#f9f2c5] via-[#f7f3d5] to-[#f8f1c9]">
Expand Down Expand Up @@ -102,21 +192,13 @@ export default function ProfilePage() {
icon={<Mail className="h-10 w-10" strokeWidth={1.8} />}
title="Contact Information"
>
<InfoRow label="Email address" value={profile.email} />
<InfoRow label="Phone number" value={profile.phone} />
</InfoCard>

<InfoCard
icon={<FlaskConical className="h-10 w-10" strokeWidth={1.8} />}
title="Lab and Affiliation"
>
<InfoRow label="Laboratory name" value={profile.labName} />
<InfoRow label="Role at lab" value={profile.role} />
<div className="flex items-center gap-4 pt-2 text-[#111111]">
<CalendarDays className="h-9 w-9 text-[#2d2d2d]" strokeWidth={1.8} />
<p className="text-2xl font-medium">Joined {profile.joined}.</p>
<div className="space-y-8">
<InfoRow label="Email address" value={profile.email} />
<InfoRow label="Phone number" value={profile.phone} />
</div>
</InfoCard>

<LabAffiliationsCard affiliations={affiliations} />
</div>

<div className="flex justify-end">
Expand Down
Loading