summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/base.css2
-rw-r--r--src/main.tsx1
-rw-r--r--src/pages/HomePage.tsx145
-rw-r--r--src/styles.css42
4 files changed, 115 insertions, 75 deletions
diff --git a/src/base.css b/src/base.css
index d5afb78..dc8d1f0 100644
--- a/src/base.css
+++ b/src/base.css
@@ -180,4 +180,4 @@ button:hover::after {
.container {
padding: 15px 10px;
}
-}
+} \ No newline at end of file
diff --git a/src/main.tsx b/src/main.tsx
index bef5202..4aff025 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -1,6 +1,5 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
-import './index.css'
import App from './App.tsx'
createRoot(document.getElementById('root')!).render(
diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx
index 5892c8c..7b726a6 100644
--- a/src/pages/HomePage.tsx
+++ b/src/pages/HomePage.tsx
@@ -203,83 +203,110 @@ const HomePage = () => {
return morseMap[char] || '';
};
+ // Reset game to initial state
+ const resetGame = () => {
+ setGameStarted(false);
+ setScore(0);
+ setTotalPlayed(0);
+ setCurrentChar('');
+ setOptions([]);
+
+ // Clear score tracker
+ const scoreTracker = document.getElementById('scoreTracker');
+ if (scoreTracker) {
+ scoreTracker.innerHTML = '';
+ }
+
+ // Stop any playing audio
+ if (actxRef.current) {
+ try {
+ actxRef.current.close();
+ actxRef.current = null;
+ } catch (error) {
+ console.error('Error closing audio context:', error);
+ }
+ }
+ };
+
return (
<div className="container">
- <h1><Link to="/" className="title-link">Morse Hero</Link></h1>
+ <h1 onClick={resetGame} className="title-link">Morse Hero</h1>
- {!gameStarted ? (
- <div id="startScreen">
- <p>Learn Morse code the fun way!</p>
- <button id="startButton" className="start-button" onClick={startGame}>Start</button>
- <div className="chart-link">
- <Link to="/chart">View Morse Code Chart</Link>
+ {
+ !gameStarted ? (
+ <div id="startScreen">
+ <p>Learn Morse code the fun way!</p>
+ <button id="startButton" className="start-button" onClick={startGame}>Start</button>
+ <div className="chart-link">
+ <Link to="/chart">View Morse Code Chart</Link>
+ </div>
</div>
- </div>
- ) : (
- <div id="gameArea" style={{ display: 'block' }}>
- <div className="score-container">
- <div className="score-widget">
- <div className="score-info">
- <div className="score-label">Score:</div>
- <div className="score-value">
- <span id="score">{score}</span> / <span id="total">{totalPlayed}</span>
+ ) : (
+ <div id="gameArea" style={{ display: 'block' }}>
+ <div className="score-container">
+ <div className="score-widget">
+ <div className="score-info">
+ <div className="score-label">Score:</div>
+ <div className="score-value">
+ <span id="score">{score}</span> / <span id="total">{totalPlayed}</span>
+ </div>
</div>
+ <div className="score-tracker" id="scoreTracker"></div>
</div>
- <div className="score-tracker" id="scoreTracker"></div>
</div>
- </div>
- <div className="game-container">
- <div className="options">
- {options.map((option, index) => (
- <button
- key={index}
- className="option-button"
- ref={el => {
- optionButtonsRef.current[index] = el;
- }}
- onClick={() => checkAnswer(option)}
- >
- <span className="char-display">{option}</span>
- {showHints && <span className="morse-hint">{getMorseCode(option)}</span>}
- </button>
- ))}
- </div>
+ <div className="game-container">
+ <div className="options">
+ {options.map((option, index) => (
+ <button
+ key={index}
+ className="option-button"
+ ref={el => {
+ optionButtonsRef.current[index] = el;
+ }}
+ onClick={() => checkAnswer(option)}
+ >
+ <span className="char-display">{option}</span>
+ {showHints && <span className="morse-hint">{getMorseCode(option)}</span>}
+ </button>
+ ))}
+ </div>
- <div className="settings">
- <label htmlFor="wpmSelect">Speed:</label>
- <select
- id="wpmSelect"
- value={wpm}
- onChange={(e) => setWpm(parseInt(e.target.value))}
- >
- <option value="10">10 WPM</option>
- <option value="15">15 WPM</option>
- <option value="20">20 WPM</option>
- <option value="25">25 WPM</option>
- <option value="30">30 WPM</option>
- </select>
- <div className="hint-setting">
- <input
- type="checkbox"
- id="hintMode"
- name="hintMode"
- checked={showHints}
- onChange={(e) => setShowHints(e.target.checked)}
- />
- <label htmlFor="hintMode">Show Hints</label>
+ <div className="settings">
+ <label htmlFor="wpmSelect">Speed:</label>
+ <select
+ id="wpmSelect"
+ value={wpm}
+ onChange={(e) => setWpm(parseInt(e.target.value))}
+ >
+ <option value="10">10 WPM</option>
+ <option value="15">15 WPM</option>
+ <option value="20">20 WPM</option>
+ <option value="25">25 WPM</option>
+ <option value="30">30 WPM</option>
+ </select>
+ <div className="hint-setting">
+ <input
+ type="checkbox"
+ id="hintMode"
+ name="hintMode"
+ checked={showHints}
+ onChange={(e) => setShowHints(e.target.checked)}
+ />
+ <label htmlFor="hintMode">Show Hints</label>
+ </div>
</div>
</div>
</div>
- </div>
- )}
+ )
+ }
<footer className="footer">
<p>Need help? View the <Link to="/chart">Morse Code Chart</Link>. </p>
<p>Created with <a href="https://www.mastercw.com/cw.js/">CW.js</a>. For a complete and professional
Morse Code training solution visit <a href="https://www.mastercw.com">Master CW</a>.</p>
</footer>
- </div>
+ </div >
);
};
diff --git a/src/styles.css b/src/styles.css
index 377c0ca..d667025 100644
--- a/src/styles.css
+++ b/src/styles.css
@@ -8,6 +8,12 @@ h1 {
text-shadow:
0 0 15px rgba(243, 156, 18, 0.4),
3px 3px 0px rgba(231, 76, 60, 0.6);
+ cursor: pointer;
+ transition: transform 0.2s ease;
+}
+
+h1:hover {
+ transform: scale(1.03);
}
h1::after {
@@ -522,22 +528,30 @@ h1::after {
0% {
box-shadow: 0 8px 0 var(--success-dark), 0 0 20px rgba(46, 204, 113, 0.5);
}
+
50% {
box-shadow: 0 8px 0 var(--success-dark), 0 0 40px rgba(46, 204, 113, 0.8);
}
+
100% {
box-shadow: 0 8px 0 var(--success-dark), 0 0 20px rgba(46, 204, 113, 0.5);
}
}
@keyframes shake {
- 0%, 100% {
+
+ 0%,
+ 100% {
transform: translateX(0);
}
- 20%, 60% {
+
+ 20%,
+ 60% {
transform: translateX(-10px);
}
- 40%, 80% {
+
+ 40%,
+ 80% {
transform: translateX(10px);
}
}
@@ -560,36 +574,36 @@ body.game-active #startScreen {
.game-container {
padding: 30px 20px;
}
-
+
.options {
grid-template-columns: 1fr;
gap: 20px;
}
-
+
.option-button {
font-size: 30px;
padding: 20px 15px;
min-height: 110px;
}
-
+
h1 {
font-size: 3.5em;
}
-
+
.start-button {
font-size: 28px;
padding: 15px 40px;
}
-
+
.score-container {
flex-direction: column;
align-items: center;
}
-
+
.score-widget {
margin-bottom: 15px;
}
-
+
.settings-toggle {
margin-left: 0;
margin-top: 10px;
@@ -600,22 +614,22 @@ body.game-active #startScreen {
.game-container {
padding: 25px 15px;
}
-
+
.option-button {
font-size: 24px;
padding: 15px 10px;
min-height: 90px;
}
-
+
h1 {
font-size: 2.8em;
}
-
+
.start-button {
font-size: 24px;
padding: 12px 30px;
}
-
+
.hint-setting {
margin-left: 0;
margin-top: 10px;