mirror of
https://github.com/UiO-Gaming/name-100-uio-gamers.git
synced 2026-11-05 13:56:53 +01:00
Show an error when a guess fails and keep the input for retrying
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
bcb8259489
commit
148449bcae
3 files changed
+28
-26
No files matched your search
@@ -14,15 +14,12 @@ const GuessForm: React.FC<GuessFormProps> = ({ input, onInputChange, onSubmit, d
|
||||
const { language } = useLanguage();
|
||||
const t = translations[language];
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const prevInputRef = useRef(input);
|
||||
|
||||
// Focus input when it gets cleared after submission
|
||||
useEffect(() => {
|
||||
if (prevInputRef.current && !input && !loading) {
|
||||
if (!loading && !disabled) {
|
||||
inputRef.current?.focus();
|
||||
}
|
||||
prevInputRef.current = input;
|
||||
}, [input, loading]);
|
||||
}, [loading, disabled]);
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
onSubmit(e);
|
||||
|
||||
@@ -27,7 +27,7 @@ export default function HomeClient({ session }: { session: Session }) {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const timerRef = useRef<NodeJS.Timeout | null>(null);
|
||||
const [howToPlayOpen, setHowToPlayOpen] = useState(false);
|
||||
const [repeatMessage, setRepeatMessage] = useState("");
|
||||
const [errorMessage, setErrorMessage] = useState("");
|
||||
const { language } = useLanguage();
|
||||
const t = translations[language];
|
||||
const [goalAmount, setGoalAmount] = useState(100);
|
||||
@@ -83,49 +83,50 @@ export default function HomeClient({ session }: { session: Session }) {
|
||||
setTimerStarted(false);
|
||||
setMatches([]);
|
||||
setInput("");
|
||||
setRepeatMessage("");
|
||||
setErrorMessage("");
|
||||
};
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
const trimmedInput = input.trim();
|
||||
if (!trimmedInput) return;
|
||||
if (matches.some((m) => m.input.toLowerCase() === trimmedInput.toLowerCase() && !m.name)) {
|
||||
setRepeatMessage(t.alreadySubmitted);
|
||||
if (matches.some((m) => !m.name && m.input.toLowerCase() === trimmedInput.toLowerCase())) {
|
||||
setErrorMessage(t.alreadySubmitted);
|
||||
return;
|
||||
}
|
||||
setRepeatMessage("");
|
||||
setErrorMessage("");
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
const guessedIds = matches.filter((m) => m.correct && m.id).map((m) => m.id!);
|
||||
const guessedIds = matches.flatMap((m) => (m.correct && m.id ? [m.id] : []));
|
||||
|
||||
const res = await fetch("/api/guess", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ input: trimmedInput, guessedIds }),
|
||||
});
|
||||
const data: Match | null = res.ok ? await res.json() : null;
|
||||
|
||||
if (res.ok) {
|
||||
const data = (await res.json()) as Match;
|
||||
if (!data) {
|
||||
setErrorMessage(res.status === 401 ? t.sessionExpired : t.guessFailed);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.id && matches.some((m) => m.id && m.id === data.id)) {
|
||||
setRepeatMessage(t.alreadySubmitted);
|
||||
setInput("");
|
||||
return;
|
||||
}
|
||||
setMatches((prev) => [...prev, data]);
|
||||
setInput("");
|
||||
if (data.id && matches.some((m) => m.id === data.id)) {
|
||||
setErrorMessage(t.alreadySubmitted);
|
||||
return;
|
||||
}
|
||||
setMatches((prev) => [...prev, data]);
|
||||
|
||||
if (data.correct && !timerStarted) {
|
||||
startTimer();
|
||||
}
|
||||
if (data.correct && !timerStarted) {
|
||||
startTimer();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error submitting guess:", error);
|
||||
setRepeatMessage("An error occurred. Please try again.");
|
||||
setErrorMessage(t.guessFailed);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
setInput("");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -175,14 +176,14 @@ export default function HomeClient({ session }: { session: Session }) {
|
||||
input={input}
|
||||
onInputChange={(e) => {
|
||||
setInput(e.target.value);
|
||||
setRepeatMessage("");
|
||||
setErrorMessage("");
|
||||
}}
|
||||
onSubmit={handleSubmit}
|
||||
disabled={correctMatchesCount === goalAmount}
|
||||
loading={loading}
|
||||
/>
|
||||
<Score matchesCount={correctMatchesCount} goalAmount={goalAmount} />
|
||||
{repeatMessage && <div className="mb-2 font-semibold text-red-500">{repeatMessage}</div>}
|
||||
{errorMessage && <div className="mb-2 font-semibold text-red-500">{errorMessage}</div>}
|
||||
{matches.length > 0 && (
|
||||
<>
|
||||
<h2 className="mt-4 text-2xl">{t.submittedAnswers}</h2>
|
||||
|
||||
@@ -22,6 +22,8 @@ export const translations = {
|
||||
tryAgain: "Try logging in again",
|
||||
notPayingMember: "not a paying member",
|
||||
goalSelectorLabel: "Number of gamers to name:",
|
||||
guessFailed: "Something went wrong. Please try again.",
|
||||
sessionExpired: "Your session has expired. Reload the page to log in again.",
|
||||
},
|
||||
no: {
|
||||
submittedAnswers: "Dine svar",
|
||||
@@ -45,5 +47,7 @@ export const translations = {
|
||||
tryAgain: "Logg på igjen",
|
||||
notPayingMember: "ikke betalende medlem",
|
||||
goalSelectorLabel: "Velg antall som må navngis:",
|
||||
guessFailed: "Noe gikk galt. Prøv igjen.",
|
||||
sessionExpired: "Økten din har utløpt. Last inn siden på nytt for å logge inn igjen.",
|
||||
},
|
||||
};
|
||||
Reference in new issue
Block a user