"use client"; import { useEffect, useState } from "react"; // "투표 종료까지" 카운트다운 (D7). 마감 = 킥오프 정각(lockAt). // 서버/클라 hydration mismatch 방지: 시간 계산은 마운트 후 useEffect에서만. export default function Countdown({ to, label = "투표 종료까지", }: { to: string; label?: string; }) { const [left, setLeft] = useState(null); useEffect(() => { const target = new Date(to).getTime(); const tick = () => setLeft(Math.max(0, target - Date.now())); tick(); const id = setInterval(tick, 1000); return () => clearInterval(id); }, [to]); const ended = left !== null && left <= 0; return (
{ended ? "투표가 마감되었습니다" : label} {!ended && ( {left === null ? "--:--:--" : fmt(left)} )}
); } function fmt(ms: number): string { const s = Math.floor(ms / 1000); const d = Math.floor(s / 86400); const h = Math.floor((s % 86400) / 3600); const m = Math.floor((s % 3600) / 60); const sec = s % 60; const pad = (n: number) => String(n).padStart(2, "0"); if (d > 0) return `${d}일 ${pad(h)}:${pad(m)}:${pad(sec)}`; return `${pad(h)}:${pad(m)}:${pad(sec)}`; }