From 2c66802cd7b3fbe3c284ec7e5575c23b2c0b9294 Mon Sep 17 00:00:00 2001 From: Xenon010101 Date: Fri, 5 Jun 2026 01:41:59 +0530 Subject: [PATCH 1/4] fix: replace hardcoded program deadlines with dynamic computation (#999) --- .../student/opensource/ProgramTrackerPage.tsx | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/client/src/module/student/opensource/ProgramTrackerPage.tsx b/client/src/module/student/opensource/ProgramTrackerPage.tsx index f14207747..a2685ff37 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, From 02374f9bcedf0a0ecf0c41a0a1093eb6729e2cc0 Mon Sep 17 00:00:00 2001 From: Xenon010101 Date: Fri, 5 Jun 2026 01:42:36 +0530 Subject: [PATCH 2/4] fix: compute GSoC year filter end year dynamically instead of hardcoding (#1001) --- client/src/module/student/opensource/GSoCReposPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 476eb4afd4a08f568d71336a7619d9052264ba6b Mon Sep 17 00:00:00 2001 From: Xenon010101 Date: Fri, 5 Jun 2026 01:49:04 +0530 Subject: [PATCH 3/4] fix: show URL format hint and improve parseGithubRepoUrl edge cases (#1002) --- .../module/student/opensource/SuggestRepoModal.tsx | 6 +++++- .../module/student/opensource/_shared/repo-utils.ts | 13 +++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/client/src/module/student/opensource/SuggestRepoModal.tsx b/client/src/module/student/opensource/SuggestRepoModal.tsx index 142e0701c..fb1bdc0c5 100644 --- a/client/src/module/student/opensource/SuggestRepoModal.tsx +++ b/client/src/module/student/opensource/SuggestRepoModal.tsx @@ -276,10 +276,14 @@ export function SuggestRepoModal({ open, onClose }: SuggestRepoModalProps) { aria-invalid={!!urlError} aria-describedby={urlError ? "suggest-url-error" : undefined} /> - {urlError && ( + {urlError ? (

{urlError}

+ ) : ( +

+ Format: https://github.com/owner/repo — we'll auto-fill the rest +

)} diff --git a/client/src/module/student/opensource/_shared/repo-utils.ts b/client/src/module/student/opensource/_shared/repo-utils.ts index da8ff6dfd..47483e080 100644 --- a/client/src/module/student/opensource/_shared/repo-utils.ts +++ b/client/src/module/student/opensource/_shared/repo-utils.ts @@ -29,6 +29,19 @@ export function difficultyBadge(d: OpenSourceRepo["difficulty"]) { export function parseGithubRepoUrl(raw: string): { owner: string; name: string } | null { const trimmed = raw.trim(); if (!trimmed) return null; + + // Support SSH format: git@github.com:owner/repo.git + const sshMatch = trimmed.match(/^git@github\.com:(.+)$/); + if (sshMatch) { + const segments = sshMatch[1].split("/").filter(Boolean); + if (segments.length < 2) return null; + const [owner, rawName] = segments; + const name = rawName.replace(/\.git$/i, ""); + const nameRe = /^[A-Za-z0-9._-]+$/; + if (!nameRe.test(owner) || !nameRe.test(name)) return null; + return { owner, name }; + } + let url: URL; try { url = new URL(trimmed); From 4f3953701544c3b7d610525ca47707a71444cfb5 Mon Sep 17 00:00:00 2001 From: Xenon010101 Date: Fri, 5 Jun 2026 01:53:27 +0530 Subject: [PATCH 4/4] feat: add urgent deadline badges to Program Tracker cards (#1007) --- .../student/opensource/ProgramTrackerPage.tsx | 49 ++++++++++++++++--- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/client/src/module/student/opensource/ProgramTrackerPage.tsx b/client/src/module/student/opensource/ProgramTrackerPage.tsx index a2685ff37..7664a76c5 100644 --- a/client/src/module/student/opensource/ProgramTrackerPage.tsx +++ b/client/src/module/student/opensource/ProgramTrackerPage.tsx @@ -612,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", @@ -635,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; @@ -701,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 (
+ {urgency?.level === "critical" && ( +
+ CLOSING SOON +
+ )} {/* Header */}
-
-
- {program.short} -
+
+ {urgency?.level === "closed" && ( + + Closed + + )} +
+ {program.short} +

{program.name}