Files
hoerdle/components/GuessInput.tsx

95 lines
2.8 KiB
TypeScript

'use client';
import { useState, useEffect } from 'react';
import { useTranslations } from 'next-intl';
interface Song {
id: number;
title: string;
artist: string;
}
interface GuessInputProps {
onGuess: (song: Song) => void;
disabled: boolean;
}
export default function GuessInput({ onGuess, disabled }: GuessInputProps) {
const t = useTranslations('Game');
const [query, setQuery] = useState('');
const [songs, setSongs] = useState<Song[]>([]);
const [filteredSongs, setFilteredSongs] = useState<Song[]>([]);
const [isOpen, setIsOpen] = useState(false);
useEffect(() => {
fetch('/api/public-songs')
.then(res => {
if (!res.ok) {
throw new Error(`Failed to load songs: ${res.status}`);
}
return res.json();
})
.then(data => {
if (Array.isArray(data)) {
setSongs(data);
} else {
console.error('Unexpected songs payload in GuessInput:', data);
setSongs([]);
}
})
.catch(err => {
console.error('Error loading songs for GuessInput:', err);
setSongs([]);
});
}, []);
useEffect(() => {
if (query.length > 1) {
const lower = query.toLowerCase();
const filtered = songs.filter(s =>
s.title.toLowerCase().includes(lower) ||
s.artist.toLowerCase().includes(lower)
);
setFilteredSongs(filtered);
setIsOpen(true);
} else {
setFilteredSongs([]);
setIsOpen(false);
}
}, [query, songs]);
const handleSelect = (song: Song) => {
onGuess(song);
setQuery('');
setIsOpen(false);
};
return (
<div className="input-container">
<input
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
disabled={disabled}
placeholder={disabled ? t('gameOverPlaceholder') : t('knowItSearch')}
className="guess-input"
/>
{isOpen && filteredSongs.length > 0 && (
<ul className="suggestions-list">
{filteredSongs.map(song => (
<li
key={song.id}
onClick={() => handleSelect(song)}
className="suggestion-item"
>
<div className="suggestion-title">{song.title}</div>
<div className="suggestion-artist">{song.artist}</div>
</li>
))}
</ul>
)}
</div>
);
}