Skip to content

Commit e86b08e

Browse files
authored
Merge pull request #47 from KaiBelmo/feat/create-typeracing
#7 | feat: add type racer
2 parents ce6eff6 + f2c31aa commit e86b08e

File tree

2 files changed

+105
-0
lines changed

2 files changed

+105
-0
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import React from 'react'
2+
3+
interface displayCodeProps {
4+
code: string;
5+
errors: number[];
6+
}
7+
8+
export default function DisplayedCode({ code, errors }: displayCodeProps) {
9+
return (
10+
<p className="text-gray-600 mb-4">
11+
{code.split("").map((char, index) => (
12+
<span
13+
key={index}
14+
className={`${
15+
errors.includes(index) ? "text-red-500" : "opacity-100"
16+
}`}
17+
>
18+
{char}
19+
</span>
20+
))}
21+
</p>
22+
)
23+
}

src/components/typing/typingCode.tsx

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
"use client";
2+
import { useState, useEffect } from "react";
3+
import DisplayedCode from "./displayedCode";
4+
5+
const code = 'printf("hello world")';
6+
7+
export default function TypingCode() {
8+
const [input, setInput] = useState("");
9+
const [startTime, setStartTime] = useState<Date | null>(null);
10+
const [endTime, setEndTime] = useState<Date | null>(null);
11+
const [errors, setErrors] = useState<number[]>([]);
12+
const [isTyping, setIsTyping] = useState(false);
13+
14+
useEffect(() => {
15+
if (startTime && endTime) {
16+
const timeTaken: number =
17+
(endTime.getTime() - startTime.getTime()) / 1000;
18+
19+
console.log("Time taken:", timeTaken);
20+
}
21+
}, [endTime, startTime]);
22+
23+
const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
24+
setInput(event.target.value);
25+
26+
if (!isTyping && event.target.value.length > 0) {
27+
setStartTime(new Date());
28+
setIsTyping(true);
29+
} else if (event.target.value === code) {
30+
setEndTime(new Date());
31+
setIsTyping(false);
32+
} else {
33+
setErrors(() => {
34+
const currentText: string = code.substring(
35+
0,
36+
event.target.value.length
37+
);
38+
const newErrors: number[] = Array.from(event.target.value)
39+
.map((char, index) => (char !== currentText[index] ? index : -1))
40+
.filter((index) => index !== -1);
41+
return newErrors;
42+
});
43+
}
44+
};
45+
46+
const handleRestart = () => {
47+
setInput("");
48+
setIsTyping(false);
49+
setStartTime(null);
50+
setEndTime(null);
51+
setErrors([]);
52+
};
53+
54+
return (
55+
<div className="w-3/4 p-8 bg-gray-100 rounded-md">
56+
<h1 className="text-2xl font-bold mb-4">Type this code:</h1>
57+
<DisplayedCode code={code} errors={errors} />
58+
<input
59+
type="text"
60+
value={input}
61+
onChange={handleInputChange}
62+
disabled={endTime !== null}
63+
className="w-full p-2 border border-gray-300 rounded mb-4"
64+
/>
65+
{endTime && (
66+
<div>
67+
<p className="mb-2">
68+
Time taken: {(endTime.getTime() - startTime!.getTime()) / 1000}{" "}
69+
seconds
70+
</p>
71+
<p className="mb-4">Errors: {errors.length}</p>
72+
</div>
73+
)}
74+
<button
75+
onClick={handleRestart}
76+
className="bg-black text-white py-2 px-4 rounded"
77+
>
78+
Restart
79+
</button>
80+
</div>
81+
);
82+
}

0 commit comments

Comments
 (0)