timer.tsx 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. import { useEffect, useRef, useState } from "react";
  2. export function Timer({
  3. isRunning,
  4. initialSeconds = 0,
  5. onChange,
  6. }: {
  7. isRunning: boolean;
  8. initialSeconds?: number;
  9. onChange?: (seconds: number) => void;
  10. }) {
  11. const [seconds, setSeconds] = useState(initialSeconds);
  12. const intervalRef = useRef<NodeJS.Timeout | null>(null);
  13. useEffect(() => {
  14. setSeconds(initialSeconds);
  15. }, [initialSeconds]);
  16. useEffect(() => {
  17. if (isRunning) {
  18. intervalRef.current = setInterval(() => {
  19. setSeconds((s) => {
  20. const next = s + 1;
  21. onChange?.(next);
  22. return next;
  23. });
  24. }, 1000);
  25. } else if (intervalRef.current) {
  26. clearInterval(intervalRef.current);
  27. intervalRef.current = null;
  28. }
  29. return () => {
  30. if (intervalRef.current) clearInterval(intervalRef.current);
  31. };
  32. }, [isRunning, onChange]);
  33. // Format mm:ss ou hh:mm:ss
  34. const format = () => {
  35. const h = Math.floor(seconds / 3600);
  36. const m = Math.floor((seconds % 3600) / 60);
  37. const s = seconds % 60;
  38. if (h > 0) return `${h.toString().padStart(2, "0")}:${m.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}`;
  39. return `${m.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}`;
  40. };
  41. return <span>{format()}</span>;
  42. }