Skip to content
61 changes: 38 additions & 23 deletions app/apply/page.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,45 @@
import Link from "next/link";
import PublicLayout from "@/components/layout/PublicLayout";
import { useState } from "react";
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can remove useState import


export default function ApplyPage() {
const cards = [
{ id: "startup", label: "STARTUP\nAPPLICATION", href: "/apply/startup" },
{ id: "org", label: "ORG/COMPANY\nPROJECT FORM", href: "/apply/org" },
{ id: "student", label: "STUDENT/PRODUCT\nTEAM SKILLS FORM [Mock for now]", href: "#" },
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove [Mock for now] and add the href to /apply/team

];

export default function StrategicLeadersPage() {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe rename to ApplyPage()? I think StrategicLeadersPage function name might have been copy-pasted from another file

return (
<PublicLayout>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a reason this isn't wrapped in PublicLayout anymore? Did I mess up the merge conflict resolutions or something else

<div className="mx-auto max-w-4xl px-6 py-12">
<h1 className="text-4xl font-semibold tracking-tight">Apply</h1>
<p className="text-gray-700 leading-relaxed mt-3">
Choose the application you want to start.
<div className="relative min-h-screen bg-white overflow-hidden flex flex-col items-center px-6 py-16">

<div className="absolute top-0 left-0 w-64 h-64 bg-rose-100 rounded-full -translate-x-1/3 -translate-y-1/4 opacity-70" />
<div className="absolute bottom-0 right-0 w-56 h-56 bg-rose-100 rounded-full translate-x-1/4 translate-y-1/4 opacity-70" />

<div className="relative z-10 text-center max-w-2xl mb-4">
<h1 className="text-4xl font-black text-black leading-tight mb-3">
Apply to Join a Private<br />
<span className="relative inline-block">
Network of Strategic Leaders
<span className="absolute left-0 -bottom-1 w-full h-0.5 bg-cyan-400" />
</span>
</h1>
<p className="text-gray-500 text-lg mt-4 leading-relaxed">
Learn from our executive strategy playbook<br />
and get access to our network of strategic leaders.
</p>
</div>

<section className="mt-10">
<h2 className="text-2xl font-semibold mb-3">Application Types</h2>
<div className="flex flex-col gap-4">
<Link href="/apply/startup" className="underline text-gray-700 hover:text-black">
Startup Application
</Link>
<Link href="/apply/org" className="underline text-gray-700 hover:text-black">
Org Application
</Link>
<Link href="/apply/team" className="underline text-gray-700 hover:text-black">
Team Application
</Link>
</div>
</section>
<div className="relative z-10 flex flex-col sm:flex-row gap-6 mt-10 w-full max-w-4xl justify-center">
{cards.map((card) => (
<a
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use from next/link instead of <a> for internal routes. Raw <a> tags trigger a full page reload and skip client-side routing and prefetching.

key={card.id}
href={card.href}
className="flex-1 min-h-96 bg-sky-100 rounded-3xl flex items-start justify-start p-6 hover:bg-sky-200 hover:shadow-md transition-all duration-200 group"
>
<span className="text-black font-bold text-lg uppercase tracking-wide leading-snug whitespace-pre-line group-hover:text-cyan-700 transition-colors">
{card.label}
</span>
</a>
))}
</div>
</PublicLayout>
</div>
);
}
35 changes: 33 additions & 2 deletions app/apply/startup/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,45 @@ export default function StartupApplyPage() {
fundingSiteUrl: "",
contact: "",
});
const [loading, setLoading] = useState(false);
const [status, setStatus] = useState<"idle" | "success" | "error">("idle");

function updateField<K extends keyof StartupFormState>(key: K, value: StartupFormState[K]) {
setForm((prev) => ({ ...prev, [key]: value }));
}

function handleSubmit(e: React.FormEvent) {
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
console.log("Startup application form:", form);
setLoading(true);
setStatus("idle");

try {
const res = await fetch("/api/applications/startup", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
StartupName : form.name,
StartupDescription : form.description,
StartupFundingGoal : form.fundingGoal,
StartupContact : form.contact,
}),
Comment on lines +44 to +49
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

submitterEmail: StartupContact?.email ?? StartupContact?.Email ?? null,

Make startup contact as:

  StartupContact: {
    email: form.contact,
    name: form.name,
  },

StartupContact is sent as a plain string but the API derives submitterEmail as StartupContact?.email
So send StartupContact as an object (email: form.contact, form: form.name} so the API can correctly populate subitterEmail and submitterName

Comment on lines +44 to +49
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also the form has 6 fields including deckURL and fundingSiteURL
but it is never included in the request body and seem to just be silently dropped.
So add StartupDeckUrl: form.deckUrl and StartupFundingSiteUrl: form.fundingSiteUrl to the payload

});
if (!res.ok) {
throw new Error("Failed to submit application");
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: for debugging purposes you can parse the response body as the API would return {error: "..."}

so inside the condition you can do something like this:

  const data = await res.json().catch(() => ({}));
  throw new Error((data as { error?: string }).error ?? "Failed to submit application");

basically awaiting the response and displaying the specific error

}
setStatus("success");
setForm({
name: "",
description: "",
fundingGoal: "",
contact: "",
Comment on lines +55 to +59
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add deckUrl and fundingSiteUrl if we are adding this as inputs as I mentioned above

});
} catch (err) {
console.error(err);
setStatus("error");
} finally {
setLoading(false);
}
}

return (
Expand Down
3 changes: 2 additions & 1 deletion app/leaders/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use client';
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you can remove 'use client' here ..


import React from 'react';
import LeaderCard2 from '@/components/ui/LeaderCard2';
import PublicLayout from '@/components/layout/PublicLayout';
Expand Down Expand Up @@ -55,7 +57,6 @@ const team = [

export default function Leaders() {
return (
<PublicLayout>
<div style={{
minHeight: '100vh',
backgroundColor: '#ffffff',
Expand Down
7 changes: 4 additions & 3 deletions components/ui/LeaderCard2.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react';
import Image from 'next/image';

interface LeaderCardProps {
name: string;
Expand Down Expand Up @@ -37,13 +36,15 @@ export default function LeaderCard2({ name, title, bio, image, reverse = false }
marginRight: reverse ? '-10px' : '20px',
}}
>
<Image
<img
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should use Image from next/Image .. it provides better optimizations .. it looks like you use to use it but it got removed? is there a reason for that? or did I mess up something in the merge conflict resolutions?

src={image}
alt={name}
fill
style={{
width: '100%',
height: '100%',
objectFit: 'cover',
borderRadius: '14px',
display: 'block',
}}
/>
</div>
Expand Down