71 lines
1.7 KiB
TypeScript
Executable File
71 lines
1.7 KiB
TypeScript
Executable File
import { useEffect, useState } from 'react';
|
|
|
|
export interface ICountDown {
|
|
m: number;
|
|
s: number;
|
|
}
|
|
/**
|
|
*
|
|
* @param minutes how many minutes.
|
|
* @param autoplay by default true. if you want play coundDown after an action, you can set it to false and manually play it.
|
|
* @param onEnd you can pass a callback function that will trigger at the END.
|
|
* @returns
|
|
*/
|
|
|
|
export function useCountDown(minutes: number, autoplay = true, onEnd = () => {}) {
|
|
|
|
const [countDown, setCountDown] = useState<ICountDown>({m: minutes, s: 0});
|
|
const [stop, setStop] = useState<boolean>(!autoplay);
|
|
|
|
useEffect(() => {
|
|
const handler = setTimeout(() => {
|
|
if (countDown.m !== 0 || countDown.s !== 0) {
|
|
setCountDown(calculateCountDown(countDown));
|
|
} else {
|
|
onEnd();
|
|
}
|
|
}, 1000);
|
|
|
|
return () => {
|
|
clearTimeout(handler);
|
|
};
|
|
}, [countDown]);
|
|
|
|
const reset = () => {
|
|
setCountDown({m: minutes, s: 0});
|
|
};
|
|
const pause = () => {
|
|
setStop(true);
|
|
};
|
|
const play = () => {
|
|
setStop(false);
|
|
setCountDown({...countDown});
|
|
};
|
|
|
|
const calculateCountDown = (st: ICountDown): ICountDown => {
|
|
if (stop) {
|
|
return countDown;
|
|
}
|
|
const timeLeft = { m: 0, s: 0 };
|
|
const remain = st.m * 60 + st.s - 1;
|
|
if (remain > 0) {
|
|
timeLeft.m = Math.floor((remain) / 60);
|
|
timeLeft.s = remain - timeLeft.m * 60;
|
|
return timeLeft;
|
|
} else {
|
|
if (remain === 0 && countDown.s === 1) {
|
|
return timeLeft;
|
|
} else {
|
|
return countDown;
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
return {
|
|
value: `${countDown.m > 9 ? countDown.m : '0' + countDown.m}:${countDown.s > 9 ? countDown.s : '0' + countDown.s}`,
|
|
reset,
|
|
pause,
|
|
play
|
|
};
|
|
} |