66 lines
1.6 KiB
TypeScript
66 lines
1.6 KiB
TypeScript
import clsx from 'clsx';
|
|
import { useEffect, useReducer } from 'react';
|
|
import { useWindowSize } from 'react-use';
|
|
import Confetti from 'react-confetti';
|
|
|
|
type State = {
|
|
hours: number;
|
|
minutes: number;
|
|
seconds: number;
|
|
};
|
|
|
|
type Action = {
|
|
type: string;
|
|
payload: Partial<State>;
|
|
};
|
|
|
|
function reducer(state: State, action: Action): State {
|
|
switch (action.type) {
|
|
case 'SET_TIME_REMAINING':
|
|
return { ...state, ...action.payload };
|
|
default:
|
|
return state;
|
|
}
|
|
}
|
|
|
|
export function Timer({ targetDate, className }: { targetDate: Date; className?: string }) {
|
|
const { width, height } = useWindowSize();
|
|
|
|
const [timeRemaining, dispatch] = useReducer(reducer, {
|
|
hours: 0,
|
|
minutes: 0,
|
|
seconds: 0
|
|
});
|
|
|
|
useEffect(() => {
|
|
const intervalId = setInterval(() => {
|
|
const timeDifference = targetDate.getTime() - Date.now();
|
|
|
|
const hours = Math.floor(timeDifference / (1000 * 60 * 60));
|
|
const minutes = Math.floor((timeDifference / (1000 * 60)) % 60);
|
|
const seconds = Math.floor((timeDifference / 1000) % 60);
|
|
|
|
dispatch({
|
|
type: 'SET_TIME_REMAINING',
|
|
payload: { hours, minutes, seconds }
|
|
});
|
|
}, 1000);
|
|
|
|
return () => clearInterval(intervalId);
|
|
}, [targetDate]);
|
|
|
|
if (timeRemaining.hours < 0) {
|
|
return (
|
|
<>
|
|
{/* <Confetti width={width} height={height} /> */}
|
|
<span className={clsx(className)}>Terminé</span>
|
|
</>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<span className={clsx(className)}>
|
|
{timeRemaining.hours}h {timeRemaining.minutes}m {timeRemaining.seconds}s
|
|
</span>
|
|
);
|
|
}
|