From 55835bb80d3b0f929c52e13c07ea3cfc40dc1a52 Mon Sep 17 00:00:00 2001 From: zp6 <373669493@qq.com> Date: Sat, 16 May 2026 02:17:11 +0800 Subject: [PATCH] feat: countdown timer component --- .../src/components/bounty/CountdownTimer.tsx | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 frontend/src/components/bounty/CountdownTimer.tsx diff --git a/frontend/src/components/bounty/CountdownTimer.tsx b/frontend/src/components/bounty/CountdownTimer.tsx new file mode 100644 index 000000000..ae6bf44e9 --- /dev/null +++ b/frontend/src/components/bounty/CountdownTimer.tsx @@ -0,0 +1,95 @@ +import React, { useState, useEffect } from 'react'; +import { motion } from 'framer-motion'; + +interface CountdownTimerProps { + deadline: string | Date; + onComplete?: () => void; + className?: string; +} + +interface TimeLeft { + days: number; + hours: number; + minutes: number; + seconds: number; + total: number; +} + +function getTimeLeft(deadline: string | Date): TimeLeft { + const target = new Date(deadline).getTime(); + const now = Date.now(); + const total = target - now; + + if (total <= 0) { + return { days: 0, hours: 0, minutes: 0, seconds: 0, total: 0 }; + } + + return { + days: Math.floor(total / (1000 * 60 * 60 * 24)), + hours: Math.floor((total / (1000 * 60 * 60)) % 24), + minutes: Math.floor((total / (1000 * 60)) % 60), + seconds: Math.floor((total / 1000) % 60), + total, + }; +} + +function TimeUnit({ value, label, urgent }: { value: number; label: string; urgent: boolean }) { + return ( +