diff --git a/public/images/tarot/card_bunch.png b/public/images/tarot/card_bunch.png new file mode 100644 index 0000000..eae81b3 Binary files /dev/null and b/public/images/tarot/card_bunch.png differ diff --git a/src/pages/tarot/Reading.jsx b/src/pages/tarot/Reading.jsx index d99083d..f95a575 100644 --- a/src/pages/tarot/Reading.jsx +++ b/src/pages/tarot/Reading.jsx @@ -4,14 +4,27 @@ import { TAROT_DECK, CATEGORIES, SPREADS } from './data/cards'; import { useTarotShuffle } from './hooks/useTarotShuffle'; import { useTarotReading } from './hooks/useTarotReading'; import TarotCard from './components/TarotCard'; -import CardGrid from './components/CardGrid'; -import SpreadSlots from './components/SpreadSlots'; import InterpretationPanel from './components/InterpretationPanel'; const STEPS = [ { id: 1, label: '질문 & 설정' }, { id: 2, label: '카드 선택' }, - { id: 3, label: '해석' }, + { id: 3, label: '해석 보기' }, +]; + +const CATEGORY_LABELS = { + '연애': '♡ 연애', + '일·커리어': '직업', + '관계': '인간관계', + '재물': '재물', + '건강': '건강', + '일반': '기타', +}; + +const RECENT_READINGS = [ + { title: '연애운에 대해', meta: '3장 스프레드 · 방금 전' }, + { title: '새로운 직장에 대한 고민', meta: '3장 스프레드 · 어제' }, + { title: '오늘의 운세', meta: '3장 스프레드 · 2일 전' }, ]; function StepIndicator({ current }) { @@ -39,23 +52,32 @@ export default function Reading() { const [focusIdx, setFocusIdx] = useState(null); const spread = SPREADS[spreadId]; - const { slice, reshuffle } = useTarotShuffle(TAROT_DECK, 16); + const { slice, reshuffle } = useTarotShuffle(TAROT_DECK, 20); const { status, interpretation, runInterpretAndSave, error } = useTarotReading(); const startShuffle = () => { reshuffle(); + setPicks([]); + setFocusIdx(null); + setStep(1); + }; + + const openCardSpread = () => { setPicks([]); setFocusIdx(null); setStep(2); }; - const handlePick = (card) => { + const handlePick = (card = null) => { if (picks.length >= spread.positions.length) return; const idx = picks.length; + const nextCard = card || slice.find((c) => !disabledIds.includes(c.slug)); + if (!nextCard) return; const pos = spread.positions[idx]; - const next = [...picks, { card, position: pos.label, reversed: card.reversed }]; + const next = [...picks, { card: nextCard, position: pos.label, reversed: nextCard.reversed }]; setPicks(next); - if (next.length === spread.positions.length) setFocusIdx(0); + setFocusIdx(idx); + setStep(next.length === spread.positions.length ? 3 : 2); }; const handleInterpret = async () => { @@ -72,128 +94,285 @@ export default function Reading() { setStep(1); setPicks([]); setFocusIdx(null); }; + const resetCards = () => { + reshuffle(); + setPicks([]); + setFocusIdx(null); + setStep(1); + }; + + const changeSpread = (nextSpreadId) => { + setSpreadId(nextSpreadId); + setPicks([]); + setFocusIdx(null); + setStep(1); + reshuffle(); + }; + const disabledIds = picks.map((p) => p.card.slug); - const focusCard = focusIdx !== null && picks[focusIdx] ? picks[focusIdx].card : null; + const focusPick = focusIdx !== null && picks[focusIdx] ? picks[focusIdx] : picks[picks.length - 1] || null; + const focusCard = focusPick?.card || null; const focusCardId = focusCard?.slug; const allPicked = picks.length === spread.positions.length; const busy = status === 'interpreting' || status === 'saving'; - const remaining = slice.filter((c) => !disabledIds.includes(c.slug)); + const currentPosition = step > 1 ? spread.positions[picks.length] : null; + const canDraw = picks.length < spread.positions.length; + const selectionOpen = step === 2 && !allPicked; + const remainingCount = spread.positions.length - picks.length; return (
- -
-