diff --git a/src/pages/tarot/History.jsx b/src/pages/tarot/History.jsx new file mode 100644 index 0000000..da7beca --- /dev/null +++ b/src/pages/tarot/History.jsx @@ -0,0 +1,131 @@ +import React, { useCallback, useEffect, useState } from 'react'; +import './Tarot.css'; +import { tarotListReadings, tarotPatchReading, tarotDeleteReading } from '../../api'; +import { findCard, SPREADS } from './data/cards'; + +function pickLine(r) { + const labels = (r.cards || []).map((c) => { + const card = findCard(c.card_id); + const name = card ? card.name : c.card_id; + return `${c.position} · ${name}${c.reversed ? '(역)' : ''}`; + }); + return labels.join(' / '); +} + +export default function History() { + const [items, setItems] = useState([]); + const [total, setTotal] = useState(0); + const [page, setPage] = useState(1); + const [favoriteOnly, setFavoriteOnly] = useState(false); + const [spreadFilter, setSpreadFilter] = useState(''); + const [categoryFilter, setCategoryFilter] = useState(''); + const [loading, setLoading] = useState(false); + const [openId, setOpenId] = useState(null); + + const load = useCallback(async () => { + setLoading(true); + try { + const res = await tarotListReadings({ + page, size: 20, + favorite: favoriteOnly || undefined, + spread_type: spreadFilter || undefined, + category: categoryFilter || undefined, + }); + setItems(res.items); + setTotal(res.total); + } finally { + setLoading(false); + } + }, [page, favoriteOnly, spreadFilter, categoryFilter]); + + useEffect(() => { load(); }, [load]); + + const toggleFav = async (id, cur) => { + await tarotPatchReading(id, { favorite: !cur }); + load(); + }; + + const remove = async (id) => { + if (!window.confirm('삭제할까요?')) return; + await tarotDeleteReading(id); + load(); + }; + + return ( +
+

+ 리딩 히스토리 +

+ +
+ + + +
+ + {loading &&

불러오는 중…

} + {!loading && items.length === 0 &&

리딩 기록이 없습니다.

} + + {items.map((r) => ( +
+
+
+ {r.created_at} · {SPREADS[r.spread_type]?.name || r.spread_type} + {r.category ? ` · ${r.category}` : ''} +
+
{r.question || '(질문 없음)'}
+
+ {pickLine(r)} +
+

+ {r.summary} +

+ {openId === r.id && r.interpretation_json && ( +
+

{r.interpretation_json.advice}

+ {r.interpretation_json.warning && ( +

⚠️ {r.interpretation_json.warning}

+ )} +
+ )} + +
+
+ + +
+
+ ))} + + {total > 20 && ( +
+ + {page} / {Math.ceil(total / 20)} + +
+ )} +
+ ); +}