diff --git a/src/components/RandomQuestion.tsx b/src/components/RandomQuestion.tsx index 7e64cf9..7a9e479 100644 --- a/src/components/RandomQuestion.tsx +++ b/src/components/RandomQuestion.tsx @@ -8,9 +8,11 @@ import { type IRandomNotificationPayload, } from '@/services/randomQuestionApi'; import clockFrog from '@/assets/clockFrog.svg'; +import frog from '@/assets/frog.svg'; type TNotification = IRandomNotificationPayload; -const MAX_TIME = 180; +const INITIAL_TIME = 30; // 녹음 시작 전 제한 시간 +const RECORDING_TIME = 80; // 녹음 후 전체 시간 const isDev = import.meta.env.DEV; // 🔎 알림 페이로드에서 id를 안전하게 뽑아오기 (peerAnswerId 우선, 없으면 peerFeedbackId) @@ -28,7 +30,8 @@ export default function RandomQuestion() { const [errorMessage, setErrorMessage] = useState(null); // ===== 타이머 상태 ===== - const [remainingTime, setRemainingTime] = useState(MAX_TIME); + const [remainingTime, setRemainingTime] = useState(INITIAL_TIME); + const [hasStartedRecording, setHasStartedRecording] = useState(false); // 녹음을 시작했는지 여부 const countdownTimerRef = useRef(null); // ===== 녹음 상태 ===== @@ -59,6 +62,18 @@ export default function RandomQuestion() { const shouldTickPopup = showPopup && remainingTime > 0 && (isRecording || (!recordedAudio && !isPlaying)); + // 이미지 선택: 30초 이하면 clockFrog, 아니면 frog + const currentImage = remainingTime <= 30 ? clockFrog : frog; + + // 빨간 오버레이 opacity 계산 (30초 이하일 때만) + const redOverlayOpacity = remainingTime <= 30 ? Math.min(0.3, (30 - remainingTime) / 30 * 0.3) : 0; + + // 진행바 색상 (녹음 시작 전: 파란색, 녹음 후: coral) + const progressBarColor = hasStartedRecording ? 'bg-coral-500' : 'bg-blue-500'; + + // 최대 시간 (진행바 계산용) + const maxTime = hasStartedRecording ? RECORDING_TIME : INITIAL_TIME; + const clearReconnectTimer = () => { if (reconnectTimerRef.current) { clearTimeout(reconnectTimerRef.current); @@ -130,7 +145,8 @@ export default function RandomQuestion() { }); latestAudioBlobRef.current = null; setRecordingTime(0); - setRemainingTime(MAX_TIME); + setRemainingTime(INITIAL_TIME); + setHasStartedRecording(false); await fetchRandomQuestion(id); } catch { @@ -182,7 +198,8 @@ export default function RandomQuestion() { if (recordedAudio) URL.revokeObjectURL(recordedAudio); latestAudioBlobRef.current = null; setRecordingTime(0); - setRemainingTime(MAX_TIME); + setRemainingTime(INITIAL_TIME); + setHasStartedRecording(false); if (peerAnswerId === -1) { setLoadingQuestion(true); @@ -292,6 +309,13 @@ export default function RandomQuestion() { alert('시간이 종료되어 더 이상 녹음할 수 없습니다.'); return; } + + // 녹음 시작 시 전체 시간을 80초로 변경 + if (!hasStartedRecording) { + setRemainingTime(RECORDING_TIME); + setHasStartedRecording(true); + } + try { if (recordedAudio) { URL.revokeObjectURL(recordedAudio); @@ -371,7 +395,8 @@ export default function RandomQuestion() { setRecordingTime(0); latestAudioBlobRef.current = null; audioChunksRef.current = []; - setRemainingTime(MAX_TIME); + // ✅ 다시 녹음하기: 시간 초기화 + setRemainingTime(RECORDING_TIME); void startRecording(); }; @@ -421,6 +446,7 @@ export default function RandomQuestion() { if (isRecording) stopRecording(); if (audioRef.current) audioRef.current.pause(); setShowPopup(false); + setHasStartedRecording(false); if (countdownTimerRef.current) { clearInterval(countdownTimerRef.current); countdownTimerRef.current = null; @@ -446,6 +472,7 @@ export default function RandomQuestion() { const feedback = await uploadFeedbackRecordingAndGetResult(questionDetail.question.questionId, latestAudioBlobRef.current); alert(`AI 피드백이 도착했어요.\n\n${feedback.aiFeedback}`); setShowPopup(false); + setHasStartedRecording(false); } catch (err) { console.error('랜덤 팝업 답변 제출 실패:', err); alert('답변 제출에 실패했습니다. 잠시 후 다시 시도해주세요.'); @@ -455,7 +482,8 @@ export default function RandomQuestion() { }; const playbackPercent = playbackDuration > 0 ? Math.min(100, Math.max(0, (playbackTime / playbackDuration) * 100)) : 0; - const progressPercent = Math.max(0, Math.min(100, (remainingTime / MAX_TIME) * 100)); + // ✅ 진행바: 남은 시간 비율로 표시 + const progressPercent = Math.max(0, Math.min(100, (remainingTime / maxTime) * 100)); return ( <> @@ -470,7 +498,14 @@ export default function RandomQuestion() { {!showPopup ? null : (
-
+ {/* 빨간 오버레이 */} + {redOverlayOpacity > 0 && ( +
+ )} +