diff --git a/client/src/module/student/opensource/GSoCReposPage.tsx b/client/src/module/student/opensource/GSoCReposPage.tsx index 75516ba31..830362f0c 100644 --- a/client/src/module/student/opensource/GSoCReposPage.tsx +++ b/client/src/module/student/opensource/GSoCReposPage.tsx @@ -626,7 +626,7 @@ export default function GSoCReposPage() { - 2016-2026 years + 2016-{new Date().getFullYear()} years diff --git a/client/src/module/student/opensource/ProgramTrackerPage.tsx b/client/src/module/student/opensource/ProgramTrackerPage.tsx index f14207747..7664a76c5 100644 --- a/client/src/module/student/opensource/ProgramTrackerPage.tsx +++ b/client/src/module/student/opensource/ProgramTrackerPage.tsx @@ -6,6 +6,13 @@ import { } from "lucide-react"; import { Button } from "../../../components/ui/button"; +function nextDate(month: number, day: number, hour = 23, minute = 59): string { + const now = new Date(); + const d = new Date(Date.UTC(now.getFullYear(), month - 1, day, hour, minute, 0)); + if (d <= now) d.setUTCFullYear(d.getUTCFullYear() + 1); + return d.toISOString(); +} + // ─── Data ────────────────────────────────────────────────────── interface Program { id: number; @@ -83,7 +90,7 @@ const PROGRAMS: Program[] = [ "Write a detailed proposal (problem statement, timeline, milestones)", "Submit via the GSoC portal before the deadline", ], - applicationDeadline: "2026-04-19T23:59:00Z", + applicationDeadline: nextDate(4, 19), }, { id: 2, @@ -129,7 +136,7 @@ const PROGRAMS: Program[] = [ "Complete any take-home tasks if requested", "Wait for mentor selection notification", ], - applicationDeadline: "2026-05-15T23:59:00Z", + applicationDeadline: nextDate(5, 15), }, { id: 3, @@ -230,8 +237,8 @@ const PROGRAMS: Program[] = [ "Make contributions to 1–2 projects during the contribution period", "Submit a final application with your contribution summary", ], - applicationStart: "2026-02-06T16:00:00Z", - applicationDeadline: "2026-02-13T16:00:00Z", + applicationStart: nextDate(2, 6, 16, 0), + applicationDeadline: nextDate(2, 13, 16, 0), }, { id: 5, @@ -605,11 +612,21 @@ function getCountdown( (new Date(program.deadline + "T23:59:59").getTime() - now) / 86400000, ); if (days < 0) return null; - if (days <= 7) + if (days < 3) return { text: `${days} days left!`, className: "text-red-500 font-semibold", }; + if (days < 7) + return { + text: `${days} days left`, + className: "text-amber-500 font-semibold", + }; + if (days < 30) + return { + text: `${days} days remaining`, + className: "text-blue-500 font-medium", + }; return { text: `Closes in ${days} days`, className: "text-lime-600 font-medium", @@ -628,6 +645,20 @@ function getCountdown( return null; } +function getUrgency( + program: Program, +): { level: "closed" | "critical" | "urgent" | "normal" | "none"; days: number } | null { + if (!program.deadline) return null; + const days = Math.ceil( + (new Date(program.deadline + "T23:59:59").getTime() - Date.now()) / 86400000, + ); + if (days < 0) return { level: "closed", days }; + if (days < 3) return { level: "critical", days }; + if (days < 7) return { level: "urgent", days }; + if (days < 30) return { level: "normal", days }; + return { level: "none", days }; +} + const getBrowserCurrencyConfig = (): LocalCurrencyConfig | null => { if (typeof Intl === "undefined") return null; @@ -694,20 +725,31 @@ const getGoogleCalendarUrl = (program: Program) => { function ProgramCard({ program }: { program: Program }) { const [expanded, setExpanded] = useState(false); const localStipendEstimate = program.stipendPaid ? getLocalStipendEstimate(program.stipend) : null; + const urgency = getUrgency(program); return (
{urlError}
+ ) : ( ++ Format: https://github.com/owner/repo — we'll auto-fill the rest +
)}