Hey is a decentralized and permissionless social media app built with Lens Protocol 馃尶
at main 84 lines 2.3 kB view raw
1import { useCallback, useEffect, useRef, useState } from "react"; 2 3type TimeLeft = { 4 days: number; 5 hours: number; 6 minutes: number; 7 seconds: number; 8}; 9 10interface CountdownTimerProps { 11 targetDate: string; 12} 13 14const CountdownTimer = ({ targetDate }: CountdownTimerProps) => { 15 const intervalRef = useRef<NodeJS.Timeout | null>(null); 16 const targetTimeRef = useRef<number>(new Date(targetDate).getTime() - 30000); 17 18 const calculateTimeLeft = useCallback((): TimeLeft => { 19 const now = new Date().getTime(); 20 const timeDiff = targetTimeRef.current - now; 21 22 if (timeDiff <= 0) { 23 return { days: 0, hours: 0, minutes: 0, seconds: 0 }; 24 } 25 26 const days = Math.floor(timeDiff / (1000 * 60 * 60 * 24)); 27 const hours = Math.floor((timeDiff / (1000 * 60 * 60)) % 24); 28 const minutes = Math.floor((timeDiff / (1000 * 60)) % 60); 29 const seconds = Math.floor((timeDiff / 1000) % 60); 30 31 return { days, hours, minutes, seconds }; 32 }, []); 33 34 const [timeLeft, setTimeLeft] = useState<TimeLeft>(calculateTimeLeft); 35 36 useEffect(() => { 37 targetTimeRef.current = new Date(targetDate).getTime() - 30000; 38 setTimeLeft(calculateTimeLeft()); 39 }, [targetDate, calculateTimeLeft]); 40 41 useEffect(() => { 42 const updateTimer = () => { 43 const newTimeLeft = calculateTimeLeft(); 44 setTimeLeft(newTimeLeft); 45 46 // Stop interval when countdown reaches zero 47 if ( 48 newTimeLeft.days === 0 && 49 newTimeLeft.hours === 0 && 50 newTimeLeft.minutes === 0 && 51 newTimeLeft.seconds === 0 52 ) { 53 if (intervalRef.current) { 54 clearInterval(intervalRef.current); 55 intervalRef.current = null; 56 } 57 } 58 }; 59 60 intervalRef.current = setInterval(updateTimer, 1000); 61 62 return () => { 63 if (intervalRef.current) { 64 clearInterval(intervalRef.current); 65 intervalRef.current = null; 66 } 67 }; 68 }, [calculateTimeLeft]); 69 70 const formatTimeValue = (value: number, label: string): string => { 71 return value > 0 ? `${value}${label} ` : ""; 72 }; 73 74 return ( 75 <span> 76 {formatTimeValue(timeLeft.days, "d")} 77 {formatTimeValue(timeLeft.hours, "h")} 78 {formatTimeValue(timeLeft.minutes, "m")} 79 {formatTimeValue(timeLeft.seconds, "s")} 80 </span> 81 ); 82}; 83 84export default CountdownTimer;