feat(saju-ui-v2): CompatibilityResult.jsx v2 — 점수 + 요약 + strengths/challenges

This commit is contained in:
2026-05-27 07:47:39 +09:00
parent 1664fbda09
commit be762e1ee8

View File

@@ -1,10 +1,108 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import { useSearchParams, Link } from 'react-router-dom';
import './_shell/tokens.css';
import './_shell/shell.css';
import useViewportMode from './_shell/useViewportMode';
import BottomNav from './_shell/BottomNav';
import DesktopHeader from './_shell/DesktopHeader';
import TopRibbon from './_shell/TopRibbon';
import TitleBlock from './_shell/TitleBlock';
import Mascot from './_shell/Mascot';
import MascotBubble from './_shell/MascotBubble';
import OrnateFrame from './_shell/OrnateFrame';
import PrimaryButton from './_shell/PrimaryButton';
import GhostButton from './_shell/GhostButton';
import { compatGetReading } from '../../api';
export default function CompatibilityResult() {
const mode = useViewportMode();
const [params] = useSearchParams();
const cid = params.get('cid');
const [result, setResult] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
if (!cid) return;
compatGetReading(parseInt(cid, 10))
.then(setResult)
.catch((e) => setError(e?.message || '결과를 가져오지 못했어요.'));
}, [cid]);
const interp = result?.interpretation_json || {};
const strengths = interp.strengths || [];
const challenges = interp.challenges || [];
return (
<div style={{ padding: '2rem', color: '#fff' }}>
<h1>궁합 분석 결과</h1>
<p>UI 시안 적용 대기 ...</p>
<div className="saju-v2">
{mode === 'desktop' && <DesktopHeader />}
<main className="page paper-bg screen-in">
<TopRibbon color="#4E6B5C" opacity={0.6} />
<div style={{ maxWidth: mode === 'desktop' ? 720 : 'none', margin: '0 auto', padding: '24px 20px 40px' }}>
{!cid && (
<>
<TitleBlock title="궁합 결과" gold="#4E6B5C" />
<div style={{ textAlign: 'center', marginTop: 24 }}>
<MascotBubble tone="green" tail={false} text="궁합을 먼저 보세요." style={{ margin: '0 auto 20px' }} />
<Link to="/saju/compatibility">
<PrimaryButton color="#4E6B5C" full={false}>궁합 입력하러 가기</PrimaryButton>
</Link>
</div>
</>
)}
{cid && !result && !error && (
<div style={{ textAlign: 'center', padding: 40 }}>
<Mascot variant="thinking" size={140} style={{ margin: '0 auto 16px' }} />
<MascotBubble tone="green" tail={false}
text="호령이 두 사주를 비교 중이에요..."
style={{ margin: '0 auto' }} />
</div>
)}
{cid && error && (
<div style={{ textAlign: 'center', padding: 40 }}>
<MascotBubble tone="green" tail={false}
text="궁합 결과를 가져오지 못했어요."
style={{ margin: '0 auto 20px' }} />
<GhostButton color="#4E6B5C" full={false} onClick={() => window.location.reload()}>다시 시도</GhostButton>
</div>
)}
{result && (
<>
<TitleBlock title="궁합 결과" gold="#4E6B5C"
subtitle={`${result.person_a?.name || '사람 A'} × ${result.person_b?.name || '사람 B'}`} />
<div style={{ marginTop: 20, textAlign: 'center' }}>
<div className="font-title" style={{ fontSize: 48, color: '#4E6B5C' }}>
{result.score}<span style={{ fontSize: 18, color: '#9A968D', fontWeight: 500 }}></span>
</div>
</div>
{interp.summary && (
<OrnateFrame color="#4E6B5C" bg="#FBF7EF" radius={14} padding="16px 18px" style={{ marginTop: 20 }}>
<div className="font-title" style={{ fontSize: 13, color: '#4E6B5C', textAlign: 'center', marginBottom: 6 }}>요약</div>
<div style={{ fontSize: 13, color: '#1F2A44', lineHeight: 1.7, whiteSpace: 'pre-line' }}>
{interp.summary}
</div>
</OrnateFrame>
)}
{strengths.length > 0 && (
<OrnateFrame color="#4E6B5C" bg="#FBF7EF" radius={14} padding="16px 18px" style={{ marginTop: 14 }}>
<div className="font-title" style={{ fontSize: 13, color: '#4E6B5C', marginBottom: 8 }}>강점</div>
<ul style={{ margin: 0, paddingLeft: 18, color: '#1F2A44', fontSize: 13, lineHeight: 1.7 }}>
{strengths.map((s, i) => (<li key={i}>{s}</li>))}
</ul>
</OrnateFrame>
)}
{challenges.length > 0 && (
<OrnateFrame color="#C04A4A" bg="#FBF7EF" radius={14} padding="16px 18px" style={{ marginTop: 14 }}>
<div className="font-title" style={{ fontSize: 13, color: '#C04A4A', marginBottom: 8 }}>주의할 </div>
<ul style={{ margin: 0, paddingLeft: 18, color: '#1F2A44', fontSize: 13, lineHeight: 1.7 }}>
{challenges.map((s, i) => (<li key={i}>{s}</li>))}
</ul>
</OrnateFrame>
)}
</>
)}
</div>
</main>
{mode === 'mobile' && <BottomNav theme="ivory" />}
</div>
);
}