Skip to content

Commit 01f3472

Browse files
committed
feat: add live hackathon countdown state hook
1 parent 02fd7aa commit 01f3472

1 file changed

Lines changed: 43 additions & 0 deletions

File tree

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { TableCellValue } from 'mobx-lark';
2+
import { useEffect, useEffectEvent, useMemo, useState } from 'react';
3+
4+
import { CountdownWindow, firstTextOf, resolveCountdownState, timeOf } from './utility';
5+
6+
export const useLiveCountdownState = <T extends CountdownWindow>(
7+
items: T[],
8+
startTime?: TableCellValue,
9+
endTime?: TableCellValue,
10+
) => {
11+
const [referenceTime, setReferenceTime] = useState<number | null>(null);
12+
const refreshReferenceTime = useEffectEvent(() => setReferenceTime(Date.now()));
13+
14+
useEffect(() => refreshReferenceTime(), [refreshReferenceTime]);
15+
16+
const countdownState = useMemo(
17+
() =>
18+
referenceTime === null
19+
? {
20+
nextItem: undefined as T | undefined,
21+
countdownTo: firstTextOf(startTime) || firstTextOf(endTime) || undefined,
22+
}
23+
: resolveCountdownState(items, referenceTime, startTime, endTime),
24+
[endTime, items, referenceTime, startTime],
25+
);
26+
27+
useEffect(() => {
28+
if (referenceTime === null) return;
29+
30+
const targetTime = timeOf(countdownState.countdownTo);
31+
32+
if (!Number.isFinite(targetTime)) return;
33+
34+
const timer = window.setTimeout(
35+
refreshReferenceTime,
36+
Math.max(1000, targetTime - Date.now() + 1000),
37+
);
38+
39+
return () => window.clearTimeout(timer);
40+
}, [countdownState.countdownTo, referenceTime, refreshReferenceTime]);
41+
42+
return countdownState;
43+
};

0 commit comments

Comments
 (0)