86 lines
2.5 KiB
TypeScript
86 lines
2.5 KiB
TypeScript
"use client";
|
|
|
|
import React, { useState, useEffect } from 'react';
|
|
|
|
interface CountdownTimerProps {
|
|
initialDays?: number;
|
|
initialHours?: number;
|
|
initialMinutes?: number;
|
|
initialSeconds?: number;
|
|
size?: 'sm' | 'md' | 'lg';
|
|
className?: string;
|
|
}
|
|
|
|
export const CountdownTimer: React.FC<CountdownTimerProps> = ({
|
|
initialDays = 0,
|
|
initialHours = 0,
|
|
initialMinutes = 0,
|
|
initialSeconds = 0,
|
|
size = 'md',
|
|
className = '',
|
|
}) => {
|
|
const [totalSeconds, setTotalSeconds] = useState(
|
|
initialDays * 86400 + initialHours * 3600 + initialMinutes * 60 + initialSeconds
|
|
);
|
|
|
|
useEffect(() => {
|
|
setTotalSeconds(
|
|
initialDays * 86400 + initialHours * 3600 + initialMinutes * 60 + initialSeconds
|
|
);
|
|
}, [initialDays, initialHours, initialMinutes, initialSeconds]);
|
|
|
|
useEffect(() => {
|
|
const timer = setInterval(() => {
|
|
setTotalSeconds((prev) => (prev > 0 ? prev - 1 : 0));
|
|
}, 1000);
|
|
return () => clearInterval(timer);
|
|
}, []);
|
|
|
|
const days = Math.floor(totalSeconds / 86400);
|
|
const hours = Math.floor((totalSeconds % 86400) / 3600);
|
|
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
const seconds = totalSeconds % 60;
|
|
|
|
const formatNumber = (num: number) => String(num).padStart(2, '0');
|
|
|
|
const gapClass = {
|
|
sm: 'gap-1',
|
|
md: 'gap-1.5',
|
|
lg: 'gap-2',
|
|
}[size];
|
|
|
|
const numClass = {
|
|
sm: 'text-[12px] min-w-[28px] h-7 px-1',
|
|
md: 'text-[15px] min-w-[36px] h-9 px-1.5',
|
|
lg: 'text-[18px] min-w-[44px] h-11 px-2',
|
|
}[size];
|
|
|
|
const units = [
|
|
{ value: days, label: 'Days', pad: false },
|
|
{ value: hours, label: 'Hrs', pad: true },
|
|
{ value: minutes, label: 'Min', pad: true },
|
|
{ value: seconds, label: 'Sec', pad: true },
|
|
];
|
|
|
|
return (
|
|
<div className={`flex items-start justify-center ${gapClass} ${className}`}>
|
|
{units.map((unit, idx) => (
|
|
<React.Fragment key={unit.label}>
|
|
{idx > 0 && (
|
|
<span className="text-[#e11d48] font-bold text-sm pt-2 leading-none">:</span>
|
|
)}
|
|
<div className="flex flex-col items-center">
|
|
<div
|
|
className={`flex items-center justify-center font-bold text-[#e11d48] bg-[#fce8e8] rounded-sm ${numClass}`}
|
|
>
|
|
{unit.pad ? formatNumber(unit.value) : unit.value}
|
|
</div>
|
|
<span className="text-[8px] uppercase tracking-wide text-[#e11d48]/80 mt-1 font-semibold leading-none">
|
|
{unit.label}
|
|
</span>
|
|
</div>
|
|
</React.Fragment>
|
|
))}
|
|
</div>
|
|
);
|
|
};
|