Skip to content

Commit 58bfeb0

Browse files
committed
[FE-81] 分からなかったときのギブアップボタン
1 parent 6f1a3ee commit 58bfeb0

File tree

4 files changed

+122
-9
lines changed

4 files changed

+122
-9
lines changed

frontend/src/Result/Components/ResultOverlay.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ interface Props {
1313
readonly isAnimating: boolean;
1414
readonly onBookmark: () => void;
1515
readonly onClose?: () => void;
16+
readonly isGivenUp?: boolean;
1617
}
1718

1819
export default function ResultOverlay({
@@ -21,6 +22,7 @@ export default function ResultOverlay({
2122
isAnimating,
2223
onBookmark,
2324
onClose,
25+
isGivenUp = false,
2426
}: Props) {
2527
const navigate = useNavigate();
2628
const [isShareOpen, setIsShareOpen] = useState(false);
@@ -41,7 +43,7 @@ export default function ResultOverlay({
4143
type="button"
4244
tabIndex={0}
4345
>
44-
<ThanksConfetti />
46+
{!isGivenUp && <ThanksConfetti />}
4547

4648
<div
4749
className="result-card"
@@ -61,7 +63,7 @@ export default function ResultOverlay({
6163
<CloseIcon />
6264
</IconButton>
6365

64-
<h1 className="seikai-text">正解</h1>
66+
{!isGivenUp && <h1 className="seikai-text">正解</h1>}
6567

6668
<ResultButtons
6769
gameId={gameId}

frontend/src/Result/Styles/Result.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@
2222
padding: 36px 20px 24px;
2323
width: calc(100vw - 32px);
2424
max-width: 400px;
25+
min-height: 200px;
2526
box-sizing: border-box;
2627
display: flex;
2728
flex-direction: column;
2829
align-items: center;
30+
justify-content: center;
2931
gap: 24px;
3032
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
3133
z-index: 1001;

frontend/src/Solo/Solo.css

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,3 +288,50 @@
288288
white-space: nowrap;
289289
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
290290
}
291+
292+
/* --- ギブアップボタン --- */
293+
.input-with-giveup {
294+
display: flex;
295+
align-items: center;
296+
width: 100%;
297+
gap: 8px;
298+
}
299+
300+
.giveup-button {
301+
all: unset;
302+
box-sizing: border-box;
303+
cursor: pointer;
304+
display: flex;
305+
flex-direction: column;
306+
align-items: center;
307+
justify-content: center;
308+
gap: 2px;
309+
padding: 8px 12px;
310+
border-radius: 12px;
311+
border: 2px solid #e57373;
312+
background-color: #fff5f5;
313+
color: #d32f2f;
314+
font-size: 11px;
315+
font-weight: 700;
316+
white-space: nowrap;
317+
flex-shrink: 0;
318+
transition: all 0.2s ease;
319+
}
320+
321+
.giveup-button:hover {
322+
background-color: #ffebee;
323+
border-color: #d32f2f;
324+
transform: translateY(-1px);
325+
box-shadow: 0 2px 8px rgba(211, 47, 47, 0.2);
326+
}
327+
328+
.giveup-button:active {
329+
transform: translateY(0);
330+
}
331+
332+
@media (max-width: 768px) {
333+
.giveup-button {
334+
padding: 6px 10px;
335+
font-size: 10px;
336+
}
337+
}

frontend/src/Solo/index.tsx

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import ShareModal from "../Result/Components/ShareModal";
66
import InputArea from "./Components/InputArea";
77
import MessageBubble from "./Components/MessageBubble";
88
import Timer from "./Components/Timer";
9+
import FlagIcon from "@mui/icons-material/Flag";
910
import "./Solo.css";
1011

1112
const HINT_ICONS = ["/Image/Kyoto.jpg", "/Image/Osaka.jpg"];
@@ -31,6 +32,7 @@ function Solo() {
3132
const [isShareOpen, setIsShareOpen] = useState(false);
3233
const [isBookmarked, setIsBookmarked] = useState(false);
3334
const [isAnimating, setIsAnimating] = useState(false);
35+
const [isGivenUp, setIsGivenUp] = useState(false);
3436
const [pendingHints, setPendingHints] = useState<any[]>([]);
3537
const [loadingMsgIndex, setLoadingMsgIndex] = useState(0);
3638
const loadingMessages = [
@@ -192,6 +194,57 @@ function Solo() {
192194
}
193195
};
194196

197+
// 全ヒントが表示されたかどうかを判定する
198+
const shownHintCount = messages.filter(
199+
(m) =>
200+
!m.isUser &&
201+
!m.isDivider &&
202+
m.hint !== "正解やで!" &&
203+
m.hint !== "不正解どす..." &&
204+
!m.hint.startsWith("正解は「"),
205+
).length;
206+
const allHintsShown = hints.length > 0 && shownHintCount >= hints.length;
207+
208+
// ギブアップ処理:正解を取得してチャットに表示する
209+
const handleGiveUp = async () => {
210+
if (gameId === null) return;
211+
212+
try {
213+
const res = await fetch(`/api/solo/${gameId}/answer`);
214+
const data = await res.json();
215+
const correctAnswer = data.answer;
216+
217+
// 「ギブアップ!」のユーザーメッセージを追加
218+
setMessages((prev) => [
219+
...prev,
220+
{
221+
messageId: Date.now(),
222+
hint: "ギブアップ!",
223+
isUser: true,
224+
icon: "😎",
225+
},
226+
]);
227+
228+
// 少し間を空けてから正解を表示する
229+
setTimeout(() => {
230+
setMessages((prev) => [
231+
...prev,
232+
{
233+
messageId: Date.now() + 1,
234+
hint: `正解は「${correctAnswer}」やで!`,
235+
isUser: false,
236+
icon: "/Image/Osaka.jpg",
237+
},
238+
]);
239+
setIsGivenUp(true);
240+
setHasAnswered(true);
241+
setShowResultOverlay(true);
242+
}, 500);
243+
} catch (error) {
244+
console.error("正解の取得に失敗しました:", error);
245+
}
246+
};
247+
195248
const handleTitle = () => navigate("/");
196249
const handleRetry = () => window.location.reload();
197250
const handleShare = () => setIsShareOpen(true);
@@ -302,6 +355,7 @@ function Solo() {
302355
isAnimating={isAnimating}
303356
onBookmark={handleBookmark}
304357
onClose={handleCloseResult}
358+
isGivenUp={isGivenUp}
305359
/>
306360
)}
307361
{isShareOpen && gameId !== null && (
@@ -342,13 +396,21 @@ function Solo() {
342396
</div>
343397
<div className="solo-footer">
344398
{!hasAnswered || showResultOverlay ? (
345-
<InputArea
346-
value={inputValue}
347-
onChange={setInputValue}
348-
onSubmit={handleSubmit}
349-
placeholder="回答を記入してください"
350-
hidden={hasAnswered}
351-
/>
399+
<div className="input-with-giveup">
400+
<InputArea
401+
value={inputValue}
402+
onChange={setInputValue}
403+
onSubmit={handleSubmit}
404+
placeholder="回答を記入してください"
405+
hidden={hasAnswered}
406+
/>
407+
{allHintsShown && !hasAnswered && (
408+
<button type="button" className="giveup-button" onClick={handleGiveUp}>
409+
<FlagIcon fontSize="small" />
410+
<span>ギブアップ</span>
411+
</button>
412+
)}
413+
</div>
352414
) : (
353415
<div className="result-buttons-container">
354416
<ResultButtons

0 commit comments

Comments
 (0)