in Output/GPT4_Turbo/JS/extracted_code/translation/VanillaToReact_high_low/App.tsx [34:119]
function App() {
const [activeNotes, setActiveNotes] = useState<string[]>([]);
const [showLetters, setShowLetters] = useState(false);
useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
const note = keys.find(key => key.letter === event.key.toUpperCase())?.note;
if (note && !activeNotes.includes(note)) {
setActiveNotes(prev => [...prev, note]);
}
};
const handleKeyUp = (event: KeyboardEvent) => {
const note = keys.find(key => key.letter === event.key.toUpperCase())?.note;
if (note) {
setActiveNotes(prev => prev.filter(n => n !== note));
}
};
document.addEventListener('keydown', handleKeyDown);
document.addEventListener('keyup', handleKeyUp);
return () => {
document.removeEventListener('keydown', handleKeyDown);
document.removeEventListener('keyup', handleKeyUp);
};
}, [activeNotes]);
const playSound = (note: string) => {
const audio = new Audio(soundMapper[note]);
audio.currentTime = 0;
audio.play();
};
const handleNoteClick = (note: string) => {
if (!activeNotes.includes(note)) {
setActiveNotes([...activeNotes, note]);
playSound(note);
}
};
const toggleLetters = () => setShowLetters(!showLetters);
const toggleFullscreen = () => {
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen();
} else {
document.exitFullscreen();
}
};
return (
<div className="App">
<header className="header">
<h1 className="header-title">Virtual Piano</h1>
</header>
<main className="main">
<div className="btn-container">
<button className={`btn btn-notes ${!showLetters ? 'btn-active' : ''}`} onClick={toggleLetters}>Notes</button>
<button className={`btn btn-letters ${showLetters ? 'btn-active' : ''}`} onClick={toggleLetters}>Letters</button>
</div>
<div className={`piano ${showLetters ? 'letters' : ''}`}>
{keys.map(({ letter, note, sharp }) => (
<div
key={note}
className={`piano-key ${sharp ? 'sharp' : ''} ${activeNotes.includes(note) ? 'piano-key-active' : ''}`}
data-letter={letter}
data-note={note}
onMouseDown={() => handleNoteClick(note)}
onMouseUp={() => setActiveNotes(prev => prev.filter(n => n !== note))}
onMouseOut={() => setActiveNotes(prev => prev.filter(n => n !== note))}
>
{showLetters ? letter : ''}
</div>
))}
</div>
<button className="fullscreen openfullscreen" onClick={toggleFullscreen}></button>
</main>
<footer className="footer">
<div className="footer-container">
2020
</div>
</footer>
</div>
);
}