fix(tarot): 해석 완료 시 자동 AI 탭 전환 + 새 리딩 시 해석 state 잔존 버그
Issue 1 — 우측 패널 탭이 hardcoded is-active로 클릭/state 없음: - InterpretationPanel에 activeTab state 추가 - useEffect로 interpretation 도착 시 자동 'ai' 탭 전환, 없으면 'card' - 두 탭 콘텐츠 분리: card=카드 의미·상징·조언, ai=위치 해석·종합·상호작용·근거 Issue 2 — useTarotReading hook의 interpretation이 새 리딩 시작에 잔존: - hook에 reset() 함수 추가 (status/interpretation/readingId/error 초기화) - Reading.jsx의 startShuffle/openCardSpread/restart/resetCards/changeSpread 5개 액션에서 모두 reset() 호출 — 새 리딩 시작 시 이전 해석 완전 제거 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -53,19 +53,21 @@ export default function Reading() {
|
||||
|
||||
const spread = SPREADS[spreadId];
|
||||
const { slice, reshuffle } = useTarotShuffle(TAROT_DECK, 20);
|
||||
const { status, interpretation, runInterpretAndSave, error } = useTarotReading();
|
||||
const { status, interpretation, runInterpretAndSave, error, reset } = useTarotReading();
|
||||
|
||||
const startShuffle = () => {
|
||||
reshuffle();
|
||||
setPicks([]);
|
||||
setFocusIdx(null);
|
||||
setStep(1);
|
||||
reset();
|
||||
};
|
||||
|
||||
const openCardSpread = () => {
|
||||
setPicks([]);
|
||||
setFocusIdx(null);
|
||||
setStep(2);
|
||||
reset();
|
||||
};
|
||||
|
||||
const handlePick = (card = null) => {
|
||||
@@ -92,6 +94,7 @@ export default function Reading() {
|
||||
|
||||
const restart = () => {
|
||||
setStep(1); setPicks([]); setFocusIdx(null);
|
||||
reset();
|
||||
};
|
||||
|
||||
const resetCards = () => {
|
||||
@@ -99,6 +102,7 @@ export default function Reading() {
|
||||
setPicks([]);
|
||||
setFocusIdx(null);
|
||||
setStep(1);
|
||||
reset();
|
||||
};
|
||||
|
||||
const changeSpread = (nextSpreadId) => {
|
||||
@@ -107,6 +111,7 @@ export default function Reading() {
|
||||
setFocusIdx(null);
|
||||
setStep(1);
|
||||
reshuffle();
|
||||
reset();
|
||||
};
|
||||
|
||||
const disabledIds = picks.map((p) => p.card.slug);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
function ConfidenceBadge({ level }) {
|
||||
if (!level) return null;
|
||||
@@ -14,15 +14,36 @@ export default function InterpretationPanel({
|
||||
selectedPosition,
|
||||
selectedReversed = false,
|
||||
}) {
|
||||
const [activeTab, setActiveTab] = useState('card');
|
||||
const [showEvidence, setShowEvidence] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
setActiveTab(interpretation ? 'ai' : 'card');
|
||||
}, [interpretation]);
|
||||
|
||||
const hasAI = !!interpretation;
|
||||
|
||||
const renderTabs = () => (
|
||||
<div className="tarot-panel__tabs">
|
||||
<button
|
||||
type="button"
|
||||
className={activeTab === 'card' ? 'is-active' : ''}
|
||||
onClick={() => setActiveTab('card')}
|
||||
>카드 해석</button>
|
||||
<button
|
||||
type="button"
|
||||
className={activeTab === 'ai' ? 'is-active' : ''}
|
||||
onClick={() => setActiveTab('ai')}
|
||||
disabled={!hasAI}
|
||||
aria-disabled={!hasAI}
|
||||
>AI 인사이트</button>
|
||||
</div>
|
||||
);
|
||||
|
||||
if (!interpretation && !selectedCard) {
|
||||
return (
|
||||
<aside className="tarot-panel tarot-panel--reading">
|
||||
<div className="tarot-panel__tabs">
|
||||
<button type="button" className="is-active">카드 해석</button>
|
||||
<button type="button">AI 인사이트</button>
|
||||
</div>
|
||||
{renderTabs()}
|
||||
<div className="tarot-panel__empty-state">
|
||||
<span>✦</span>
|
||||
<p>카드를 뽑으면 이곳에 카드 의미와 AI 인사이트가 표시됩니다.</p>
|
||||
@@ -44,10 +65,7 @@ export default function InterpretationPanel({
|
||||
|
||||
return (
|
||||
<aside className="tarot-panel tarot-panel--reading">
|
||||
<div className="tarot-panel__tabs">
|
||||
<button type="button" className="is-active">카드 해석</button>
|
||||
<button type="button">AI 인사이트</button>
|
||||
</div>
|
||||
{renderTabs()}
|
||||
|
||||
{selectedCard && (
|
||||
<header className="tarot-panel__head">
|
||||
@@ -65,7 +83,7 @@ export default function InterpretationPanel({
|
||||
</header>
|
||||
)}
|
||||
|
||||
{selectedCard && !interpretation && (
|
||||
{activeTab === 'card' && selectedCard && (
|
||||
<>
|
||||
<section className="tarot-panel__section">
|
||||
<h4>카드 의미 요약</h4>
|
||||
@@ -86,10 +104,12 @@ export default function InterpretationPanel({
|
||||
))}
|
||||
</ul>
|
||||
</section>
|
||||
{!hasAI && (
|
||||
<section className="tarot-panel__section tarot-panel__ai-note">
|
||||
<h4>AI 타로 해석 ✦</h4>
|
||||
<p>모든 카드를 뽑은 뒤 해석 버튼을 누르면 질문과 스프레드 위치를 함께 반영한 리딩이 생성됩니다.</p>
|
||||
</section>
|
||||
)}
|
||||
<div className="tarot-panel__advice-card">
|
||||
<span aria-hidden>☾</span>
|
||||
<p>
|
||||
@@ -100,6 +120,8 @@ export default function InterpretationPanel({
|
||||
</>
|
||||
)}
|
||||
|
||||
{activeTab === 'ai' && hasAI && (
|
||||
<>
|
||||
{cardDetail && (
|
||||
<section className="tarot-panel__section">
|
||||
<h4>이 위치의 해석</h4>
|
||||
@@ -125,7 +147,6 @@ export default function InterpretationPanel({
|
||||
</section>
|
||||
)}
|
||||
|
||||
{interpretation && (
|
||||
<section className="tarot-panel__section">
|
||||
<h4>종합 해석 <ConfidenceBadge level={interpretation.confidence} /></h4>
|
||||
<p>{interpretation.summary}</p>
|
||||
@@ -134,9 +155,8 @@ export default function InterpretationPanel({
|
||||
<p className="tarot-panel__warning">⚠️ {interpretation.warning}</p>
|
||||
)}
|
||||
</section>
|
||||
)}
|
||||
|
||||
{(interpretation?.interactions || []).length > 0 && (
|
||||
{(interpretation.interactions || []).length > 0 && (
|
||||
<section className="tarot-panel__section">
|
||||
<h4>카드 상호작용</h4>
|
||||
<ul className="tarot-interactions">
|
||||
@@ -153,6 +173,8 @@ export default function InterpretationPanel({
|
||||
</ul>
|
||||
</section>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -96,5 +96,12 @@ export function useTarotReading() {
|
||||
return interp.interpretation_json;
|
||||
}, []);
|
||||
|
||||
return { status, interpretation, readingId, error, runInterpretAndSave };
|
||||
const reset = useCallback(() => {
|
||||
setStatus('idle');
|
||||
setInterpretation(null);
|
||||
setReadingId(null);
|
||||
setError(null);
|
||||
}, []);
|
||||
|
||||
return { status, interpretation, readingId, error, runInterpretAndSave, reset };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user