From 2c6389a67a93aa227238c6088079be3210bec4a9 Mon Sep 17 00:00:00 2001 From: Maulana Sodiqin Date: Sat, 6 Dec 2025 23:31:43 +0700 Subject: [PATCH] feat: add submission deadline with countdown timer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add countdown timer showing days, hours, minutes, seconds - Disable submission after December 7, 2025 23:59 WIB - Show "Submission Closed" screen after deadline 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../src/app/teams/[teamId]/submit/page.tsx | 137 +++++++++++++++++- 1 file changed, 136 insertions(+), 1 deletion(-) diff --git a/apps/hackathon/src/app/teams/[teamId]/submit/page.tsx b/apps/hackathon/src/app/teams/[teamId]/submit/page.tsx index c92c93e..c3a8731 100644 --- a/apps/hackathon/src/app/teams/[teamId]/submit/page.tsx +++ b/apps/hackathon/src/app/teams/[teamId]/submit/page.tsx @@ -1,4 +1,4 @@ -import { FC, ReactElement, useState } from 'react'; +import { FC, ReactElement, useState, useEffect } from 'react'; import { ControlledInputField } from '@imphnen-frontend-service/ui/organisms'; import { Button, Textarea } from '@imphnen-frontend-service/ui/atoms'; import { useNavigate, useParams } from 'react-router'; @@ -14,10 +14,14 @@ import { } from '@imphnen-frontend-service/service'; import { zodResolver } from '@hookform/resolvers/zod'; import { toast } from 'sonner'; +import { Icon } from '@iconify/react'; const MIN_TEAM_MEMBERS = 2; // Minimum members required to submit (including leader) const MAX_FILE_SIZE = 2 * 1024 * 1024; // 2MB +// Submission deadline: 2025-12-07 23:59:00 WIB (UTC+7) +const SUBMISSION_DEADLINE = new Date('2025-12-07T16:59:00Z'); + const SubmitProjectPage: FC = (): ReactElement => { const { teamId } = useParams<{ teamId: string }>(); const navigate = useNavigate(); @@ -25,6 +29,42 @@ const SubmitProjectPage: FC = (): ReactElement => { const [showConfirmModal, setShowConfirmModal] = useState(false); const [confirmText, setConfirmText] = useState(''); const [screenshots, setScreenshots] = useState([]); + const [timeLeft, setTimeLeft] = useState<{ + days: number; + hours: number; + minutes: number; + seconds: number; + } | null>(null); + + // Check if deadline passed + const isDeadlinePassed = new Date() >= SUBMISSION_DEADLINE; + + // Countdown timer + useEffect(() => { + if (isDeadlinePassed) return; + + const calculateTimeLeft = () => { + const now = new Date(); + const difference = SUBMISSION_DEADLINE.getTime() - now.getTime(); + + if (difference <= 0) { + setTimeLeft(null); + return; + } + + const days = Math.floor(difference / (1000 * 60 * 60 * 24)); + const hours = Math.floor((difference / (1000 * 60 * 60)) % 24); + const minutes = Math.floor((difference / 1000 / 60) % 60); + const seconds = Math.floor((difference / 1000) % 60); + + setTimeLeft({ days, hours, minutes, seconds }); + }; + + calculateTimeLeft(); + const timer = setInterval(calculateTimeLeft, 1000); + + return () => clearInterval(timer); + }, [isDeadlinePassed]); const { data: teamData } = useTeamById(teamId || ''); const { data: submissionData } = useTeamSubmission(teamId || '', !!teamId); @@ -85,6 +125,50 @@ const SubmitProjectPage: FC = (): ReactElement => { ); } + // Show deadline passed screen + if (isDeadlinePassed) { + return ( +
+
+
+
+ +
+

+ Submission Closed +

+

+ Project submissions are no longer accepted. +

+
+ +
+

+ The submission deadline was December 7, 2025 at 23:59 WIB. +

+ + + + +
+
+
+ ); + } + const handleScreenshotUpload = async ( e: React.ChangeEvent ) => { @@ -138,6 +222,57 @@ const SubmitProjectPage: FC = (): ReactElement => {
+ {/* Countdown Timer */} + {timeLeft && ( +
+
+ +
+

+ Submission Deadline +

+

+ Submissions close on December 7, 2025 at 23:59 WIB +

+
+
+
+ {timeLeft.days} +
+
+ Days +
+
+
+
+ {timeLeft.hours.toString().padStart(2, '0')} +
+
+ Hours +
+
+
+
+ {timeLeft.minutes.toString().padStart(2, '0')} +
+
+ Minutes +
+
+
+
+ {timeLeft.seconds.toString().padStart(2, '0')} +
+
+ Seconds +
+
+
+
+
+
+ )} + {/* Minimum Members Warning */} {!hasEnoughMembers && (