Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | 38x 38x 38x 38x 11x 38x 11x 11x 11x 38x 13x 13x 13x 9x 9x 9x 13x 38x 8x 8x 8x 8x 8x 8x 10x 38x 2x 2x 2x 2x 38x 1x 1x 1x 1x 38x 1x 2x 38x 2x 2x 2x 1x 1x 38x | import { useState, useEffect, useRef, useCallback } from 'react'
import { createTimerTick, clearTimerInterval } from './timerUtils'
export interface Timer {
id: string
label: string
duration: number // seconds
remaining: number // seconds
isRunning: boolean
}
export interface UseTimersReturn {
timers: Timer[]
addTimer: (label: string, duration: number, autoStart?: boolean) => string
startTimer: (id: string) => void
pauseTimer: (id: string) => void
resetTimer: (id: string) => void
deleteTimer: (id: string) => void
toggleTimer: (id: string) => void
}
export function useTimers(onTimerComplete?: (timer: Timer) => void): UseTimersReturn {
const [timers, setTimers] = useState<Timer[]>([])
const intervalsRef = useRef<Map<string, number>>(new Map())
const onCompleteRef = useRef(onTimerComplete)
useEffect(() => {
onCompleteRef.current = onTimerComplete
}, [onTimerComplete])
useEffect(() => {
const intervals = intervalsRef.current
return () => {
intervals.forEach((intervalId) => clearInterval(intervalId))
}
}, [])
const addTimer = useCallback((label: string, duration: number, autoStart: boolean = true): string => {
const id = crypto.randomUUID()
setTimers((prev) => [
...prev,
{ id, label, duration, remaining: duration, isRunning: autoStart },
])
if (autoStart) {
const tick = createTimerTick(id, intervalsRef, onCompleteRef, setTimers)
const intervalId = window.setInterval(tick, 1000)
intervalsRef.current.set(id, intervalId)
}
return id
}, [])
const startTimer = useCallback((id: string) => {
clearTimerInterval(id, intervalsRef)
const tick = createTimerTick(id, intervalsRef, onCompleteRef, setTimers)
const intervalId = window.setInterval(tick, 1000)
intervalsRef.current.set(id, intervalId)
setTimers((prev) =>
prev.map((timer) =>
timer.id === id ? { ...timer, isRunning: true } : timer
)
)
}, [])
const pauseTimer = useCallback((id: string) => {
clearTimerInterval(id, intervalsRef)
setTimers((prev) =>
prev.map((timer) =>
timer.id === id ? { ...timer, isRunning: false } : timer
)
)
}, [])
const resetTimer = useCallback((id: string) => {
clearTimerInterval(id, intervalsRef)
setTimers((prev) =>
prev.map((timer) =>
timer.id === id
? { ...timer, remaining: timer.duration, isRunning: false }
: timer
)
)
}, [])
const deleteTimer = useCallback((id: string) => {
clearTimerInterval(id, intervalsRef)
setTimers((prev) => prev.filter((timer) => timer.id !== id))
}, [])
const toggleTimer = useCallback(
(id: string) => {
const timer = timers.find((t) => t.id === id)
Iif (!timer) return
if (timer.isRunning) {
pauseTimer(id)
} else {
startTimer(id)
}
},
[timers, pauseTimer, startTimer]
)
return { timers, addTimer, startTimer, pauseTimer, resetTimer, deleteTimer, toggleTimer }
}
// Re-export utilities for consumers
export { detectTimes, formatTimerDisplay } from './timerUtils'
|