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
4 changes: 4 additions & 0 deletions app/api/user/register/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,8 @@ export async function POST(request: Request) {
const portfolio_link = formData.get("portfolio_link") as string;
const ctf_profile = formData.get("ctf_profile") as string;
const isLooking = formData.get("isLooking") === "true";
const attendedZenith = formData.get("attended_zenith") === "true";
const attendedPBCTF4 = formData.get("attended_pbctf4") === "true";

// Validation
const errors: Record<string, string> = {};
Expand Down Expand Up @@ -442,6 +444,8 @@ export async function POST(request: Request) {
portfolio_link: portfolio_link?.trim(),
ctf_profile: ctf_profile?.trim(),
isLooking: Boolean(isLooking),
attendedZenith: Boolean(attendedZenith),
attendedPBCTF4: Boolean(attendedPBCTF4),
role: "user",
teamCode: undefined,
authProvider: isGoogle ? "google" : "password",
Expand Down
2 changes: 1 addition & 1 deletion app/dashboard/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export default function DashboardLayout({
<main className="relative flex-1 w-full">
<DotPattern />

<div className="relative z-10 mx-auto w-full max-w-[1100px] px-4 sm:px-6 md:px-8 py-8 sm:py-10 md:py-12">
<div className="relative mx-auto w-full max-w-[1100px] px-4 sm:px-6 md:px-8 py-8 sm:py-10 md:py-12">
<div className="flex flex-col gap-6 md:gap-8">
{alert && (
<StickyAlert
Expand Down
13 changes: 11 additions & 2 deletions app/dashboard/resume/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ export default function ResumeViewPage() {
const [iframeLoading, setIframeLoading] = useState(true);
const [iframeError, setIframeError] = useState(false);

const handleBack = () => {
if (window.history.length <= 1) {
window.close();
setTimeout(() => router.push("/dashboard"), 100);
} else {
router.back();
}
};

const proxiedUrl = rawUrl
? `/api/resume/view?url=${encodeURIComponent(rawUrl)}`
: "";
Expand All @@ -30,7 +39,7 @@ export default function ResumeViewPage() {
The resume viewer needs a resume URL passed as the{" "}
<code className="font-mono text-brand">?url=</code> query parameter.
</p>
<Button onClick={() => router.back()} variant="secondary">
<Button onClick={handleBack} variant="secondary">
<ArrowLeft className="w-3.5 h-3.5" />
Go back
</Button>
Expand All @@ -51,7 +60,7 @@ export default function ResumeViewPage() {
</h1>
</div>
<div className="flex items-center gap-2">
<Button onClick={() => router.back()} variant="secondary" size="sm">
<Button onClick={handleBack} variant="secondary" size="sm">
<ArrowLeft className="w-3.5 h-3.5" />
Back
</Button>
Expand Down
2 changes: 1 addition & 1 deletion components/landing/MissionBrief/MissionBrief.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ function FlappyBird({ onExit }) {
function getPipeInterval() { return Math.max(120, BASE_PIPE_INTERVAL - Math.min(score, 25) * 1.5); }

// --- Frame-rate cap: run logic at 70 fps ---
const TARGET_FPS = 70;
const TARGET_FPS = 60;
const FRAME_MS = 1000 / TARGET_FPS;
let lastTime = 0;

Expand Down
72 changes: 7 additions & 65 deletions components/landing/Prizes/Prizes.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,39 +15,26 @@ const TIERS = [
{
id: 'prize-second',
rankNumber: '02',
amount: 15000,
label: 'SECOND PLACE',
modifier: 'second',
color: '#A0E0B0'
},
{
id: 'prize-first',
rankNumber: '01',
amount: 25000,
label: 'FIRST PLACE',
modifier: 'first',
color: 'var(--primary)'
},
{
id: 'prize-third',
rankNumber: '03',
amount: 5000,
label: 'THIRD PLACE',
modifier: 'third',
color: '#A0E0B0'
},
];

/* Total prize pool */
const TOTAL_POOL = TIERS.reduce((sum, t) => sum + t.amount, 0);

/* ---------------------------------------------------------------
Helper: format with ₹ and Indian locale
--------------------------------------------------------------- */
function formatINR(value) {
return '₹' + Math.round(value).toLocaleString('en-IN');
}

/* ---------------------------------------------------------------
Decorative Barcode Element
--------------------------------------------------------------- */
Expand All @@ -63,7 +50,7 @@ function Barcode() {
/* ---------------------------------------------------------------
Interactive Prize Card Component (Data Chip)
--------------------------------------------------------------- */
const PrizeCard = ({ tier, registerRef }) => {
const PrizeCard = ({ tier }) => {
const x = useMotionValue(0);
const y = useMotionValue(0);
const [isHovered, setIsHovered] = useState(false);
Expand Down Expand Up @@ -136,10 +123,10 @@ const PrizeCard = ({ tier, registerRef }) => {
{/* Main Amount */}
<div className="prizes__amount-wrapper">
<p
className="prizes__amount"
ref={(el) => registerRef(tier.id, el)}
className="prizes__amount prize-blur"
style={{ filter: "blur(8px)", userSelect: "none", opacity: 0.8 }}
>
0
??,???
</p>
<p className="prizes__label"><span className="prizes__prompt">&gt;</span> {tier.label}</p>
</div>
Expand All @@ -157,12 +144,6 @@ const PrizeCard = ({ tier, registerRef }) => {
--------------------------------------------------------------- */
export default function Prizes() {
const sectionRef = useRef(null);
const amountRefs = useRef({});
const totalRef = useRef(null);

const registerRef = (id, el) => {
amountRefs.current[id] = el;
};

useGSAP(() => {
const ctx = sectionRef.current;
Expand All @@ -183,45 +164,6 @@ export default function Prizes() {
},
});

/* --- Count-up animation for cards --- */
TIERS.forEach((tier) => {
const el = amountRefs.current[tier.id];
if (!el) return;

const proxy = { val: 0 };
gsap.to(proxy, {
val: tier.amount,
duration: 2.5,
ease: 'power2.out',
delay: tier.modifier === 'first' ? 0.2 : 0.5,
scrollTrigger: {
trigger: ctx,
start: 'top 75%',
},
onUpdate() {
el.textContent = formatINR(proxy.val);
},
});
});

/* --- Count-up for total pool --- */
if (totalRef.current) {
const totalProxy = { val: 0 };
gsap.to(totalProxy, {
val: TOTAL_POOL,
duration: 3,
ease: 'power2.out',
delay: 0.1,
scrollTrigger: {
trigger: ctx,
start: 'top 75%',
},
onUpdate() {
totalRef.current.textContent = Math.round(totalProxy.val).toLocaleString('en-IN');
},
});
}

}, { scope: sectionRef });

return (
Expand All @@ -235,17 +177,17 @@ export default function Prizes() {
{/* Total Prize Pool */}
<div className="prizes__total">
<div className="prizes__total-label">Total Prize Pool</div>
<div className="prizes__total-amount">
<div className="prizes__total-amount prize-blur" style={{ filter: "blur(8px)", userSelect: "none", opacity: 0.8 }}>
<span className="prizes__total-currency">₹</span>
<span ref={totalRef}>0</span>
<span>??,???</span>
</div>
<div className="prizes__total-divider" />
</div>

{/* Tiers */}
<div className="prizes__tiers">
{TIERS.map((tier) => (
<PrizeCard key={tier.id} tier={tier} registerRef={registerRef} />
<PrizeCard key={tier.id} tier={tier} />
))}
</div>

Expand Down
34 changes: 18 additions & 16 deletions components/registration/discover-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -251,22 +251,22 @@ export function DiscoverContainer() {
// Teams looking for members -- only for non-leads who can see the list
shouldFetchLists && !userIsLead
? fetch(
`${API_ENDPOINTS.lookingForMembers}${queryParams}${queryParams ? "&" : "?"}page=${teamsPage}&limit=${ITEMS_PER_PAGE}`,
{ method: "GET", headers },
)
`${API_ENDPOINTS.lookingForMembers}${queryParams}${queryParams ? "&" : "?"}page=${teamsPage}&limit=${ITEMS_PER_PAGE}`,
{ method: "GET", headers },
)
: Promise.resolve(null as any),
// Operators looking for teams
shouldFetchLists
? fetch(
`${API_ENDPOINTS.lookingForTeam}${queryParams}${queryParams ? "&" : "?"}page=${participantsPage}&limit=${ITEMS_PER_PAGE}`,
{ method: "GET", headers },
)
`${API_ENDPOINTS.lookingForTeam}${queryParams}${queryParams ? "&" : "?"}page=${participantsPage}&limit=${ITEMS_PER_PAGE}`,
{ method: "GET", headers },
)
: Promise.resolve(null as any),
// Sent invites by this team -- only if user is the lead of their team
isLeadLocal && user?.teamCode
? fetch(`${API_ENDPOINTS.joinRequest}?teamCode=${user.teamCode}`, {
headers,
})
headers,
})
: Promise.resolve(null as any),
]);
const [teamsSettled, participantsSettled, sentInvitesSettled] = phase2;
Expand Down Expand Up @@ -296,7 +296,7 @@ export function DiscoverContainer() {
if (teamsData.data.pagination) {
setTeamsPagination({
totalPages: teamsData.data.pagination.totalPages || 1,
total: teamsData.data.pagination.total || 0,
total: teamsData.data.pagination.totalTeams || 0,
});
}
} else {
Expand Down Expand Up @@ -339,7 +339,7 @@ export function DiscoverContainer() {
if (participantsData.data.pagination) {
setParticipantsPagination({
totalPages: participantsData.data.pagination.totalPages || 1,
total: participantsData.data.pagination.total || 0,
total: participantsData.data.pagination.totalUsers || 0,
});
}
} else {
Expand Down Expand Up @@ -720,7 +720,7 @@ export function DiscoverContainer() {
<>
{/* HERO. compact operator strip */}
<div className="relative overflow-hidden">
<div className="relative flex items-end justify-between gap-4 flex-wrap">
<div className="relative flex items-end justify-between gap-4 flex-wrap">
<div className="flex flex-col gap-1.5 min-w-0">
<div className="flex items-center gap-2">
<span className="inline-flex w-1.5 h-1.5 rounded-full bg-brand shadow-glow-sm anim-blink" />
Expand Down Expand Up @@ -752,14 +752,14 @@ export function DiscoverContainer() {
</div>
</div>

{userHasTeam && !isTeamLead ? (
{userHasTeam && (!isTeamLead || (isTeamLead && teamCapacity && teamCapacity.current >= teamCapacity.max)) ? (
<Card hudCorners>
<div className="flex flex-col items-center justify-center px-6 py-12 text-center gap-4">
<span className="inline-flex w-12 h-12 items-center justify-center rounded-md bg-brand-soft border border-brand/40">
<Lock className="w-5 h-5 text-brand" />
</span>
<div className="font-mono text-[10.5px] uppercase tracking-[0.22em] text-brand">
&gt; Already enlisted
&gt; {isTeamLead ? "Team Full" : "Already enlisted"}
</div>
<h2 className="font-heading text-[22px] font-bold text-ink leading-tight">
You ride with{" "}
Expand All @@ -768,7 +768,9 @@ export function DiscoverContainer() {
</span>
</h2>
<p className="text-[13px] text-ink-secondary font-body max-w-[44ch] leading-relaxed">
Leave the current squad if you want to scout new ones. Recruitment is locked to leads only.
{isTeamLead
? "Your squad has reached its maximum capacity. You must remove members if you want to recruit new ones."
: "Leave the current squad if you want to scout new ones. Recruitment is locked to leads only."}
</p>
<Button
onClick={() => router.push("/dashboard")}
Expand Down Expand Up @@ -833,7 +835,7 @@ export function DiscoverContainer() {
<div className="px-3 pb-3 pt-1 text-[12px] text-ink-secondary font-body leading-relaxed">
Going public exposes your{" "}
<span className="text-ink">name, bio, organisation, profile picture, resume,
and social links</span>{" "}
and social links</span>{" "}
to other operators. Strip phone numbers, addresses, and personal emails from your resume before publishing.
</div>
</details>
Expand Down Expand Up @@ -1218,7 +1220,7 @@ export function DiscoverContainer() {
}
disabled={
participantsPage >=
participantsPagination.totalPages || isLoading
participantsPagination.totalPages || isLoading
}
className="inline-flex items-center gap-1.5 font-mono text-[11px] uppercase tracking-[0.22em] text-ink-secondary hover:text-brand disabled:opacity-30 disabled:hover:text-ink-secondary disabled:cursor-not-allowed transition-colors px-2 py-1.5 rounded"
>
Expand Down
Loading
Loading