aboutsummaryrefslogtreecommitdiff
path: root/src/components/Timer.tsx
blob: c3bc5556ee653e7764494f0534cb729ba2ed6415 (plain)
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
import React, { useState, useEffect } from 'react';
import convertTimeToString from '../utils/convertTimeToString';

enum Mode {
  'idle',
  'countdown',
  'running' ,
  'over',
};

const helperText = {
  [Mode.idle]: (
    <>
      <span>Hold </span>
      <code>SPACE</code>
      <span> to start countdown</span>
    </>
  ),
  [Mode.countdown]: (
    <>
      <span>Release </span>
      <code>SPACE</code>
      <span> to begin</span>
    </>
  ),
  [Mode.running]: 'Go fast!',
  [Mode.over]: 'You are too late!',
};

// TODO: add to props
const registerResult = (result: string): void => {
  console.log(result)
};

const Timer: React.FC = () => {
  const KEY_CODE = 32; // Space key
  const maxCountdown = 15000;

  const [mode, setMode] = useState<Mode>(Mode.idle);
  const [displayTime, setDisplayTime] = useState<string>('00:00:00');

  useEffect(() => {
    const timestamp = Date.now();

    if (mode === Mode.countdown) {
      const repeater = setInterval(() => {
        const timeDelta = maxCountdown - (Date.now() - timestamp);
        if (timeDelta <= 0) setMode(Mode.over);
        setDisplayTime(convertTimeToString(timeDelta));
      }, 10);
      return (): void => clearInterval(repeater);
    }

    if (mode === Mode.running) {
      const repeater = setInterval(() => {
        setDisplayTime(convertTimeToString(Date.now() - timestamp));
      }, 10);
      return (): void => clearInterval(repeater);
    }

    if (mode === Mode.over) {
      setDisplayTime('00:00:00');
    }
  }, [mode]);

  const handleKeyPress = (event: KeyboardEvent): void => {
    event.preventDefault();
    if (event.keyCode === KEY_CODE && mode === Mode.idle) setMode(Mode.countdown);
  };

  const handleKeyUp = (event: KeyboardEvent): void => {
    if (event.keyCode === KEY_CODE) {
      if (mode === Mode.running) {
        registerResult(displayTime);
        setMode(Mode.idle);
      } else if (mode === Mode.over) {
        setMode(Mode.idle);
      } else {
        setMode(Mode.running);
      }
    }
  };

  useEffect(() => {
    window.addEventListener('keyup', handleKeyUp);
    window.addEventListener('keypress', handleKeyPress);

    return () => {
      window.removeEventListener('keyup', handleKeyUp);
      window.removeEventListener('keypress', handleKeyPress);
    };
  });

  return (
    <>
      <b>{ displayTime }</b>
      <p>{ helperText[mode] }</p>
    </>
  );
};

export default Timer;