import React from 'react'; import { useNavigate } from 'react-router-dom'; import DesktopHero from '../_shell/DesktopHero'; import DesktopFooter from '../_shell/DesktopFooter'; import PanelHeader from '../_shell/PanelHeader'; import OrnamentBloom from '../_shell/OrnamentBloom'; import { IconChevron, IconPaw } from '../_shell/Icons'; import deriveTraits from '../_shell/helpers/deriveTraits'; import daeunLabel from '../_shell/helpers/daeunLabel'; import hexA from '../_shell/helpers/hexA'; const HANJA_TO_ID = { '木': 'wood', '火': 'fire', '土': 'earth', '金': 'metal', '水': 'water' }; const ID_TO_KO = { wood: '목', fire: '화', earth: '토', metal: '금', water: '수' }; const ID_TO_CH = { wood: '木', fire: '火', earth: '土', metal: '金', water: '水' }; const ID_TO_COLOR = { wood: '#4E6B5C', fire: '#C04A4A', earth: '#A67B3F', metal: '#D4AF37', water: '#3A5A8C', }; const STEM_EL = { '甲': 'wood', '乙': 'wood', '丙': 'fire', '丁': 'fire', '戊': 'earth', '己': 'earth', '庚': 'metal', '辛': 'metal', '壬': 'water', '癸': 'water' }; const BRANCH_EL = { '子': 'water', '丑': 'earth', '寅': 'wood', '卯': 'wood', '辰': 'earth', '巳': 'fire', '午': 'fire', '未': 'earth', '申': 'metal', '酉': 'metal', '戌': 'earth', '亥': 'water' }; const PILLAR_LABELS = { year: '년주', month: '월주', day: '일주', hour: '시주' }; function elementsByEngId(scores = {}) { const out = {}; for (const [key, value] of Object.entries(scores || {})) { const id = HANJA_TO_ID[key] || key; if (ID_TO_KO[id]) out[id] = Number(value) || 0; } return out; } function maxElement(elementsObj) { return ['wood', 'fire', 'earth', 'metal', 'water'] .map((id) => ({ id, value: Math.round(elementsObj[id] || 0), color: ID_TO_COLOR[id] })) .reduce((best, item) => (item.value > best.value ? item : best), { id: 'metal', value: 0, color: '#D4AF37' }); } function normalizePillar(pillar = {}, key) { const stem = pillar.stem || '-'; const branch = pillar.branch || '-'; return { id: key, label: PILLAR_LABELS[key], cheongan: { ch: stem, ko: pillar.stem_kr || '', mark: stem && STEM_EL[stem] ? `(${ID_TO_KO[STEM_EL[stem]]})` : '', color: ID_TO_COLOR[STEM_EL[stem]] || '#1F2A44', }, jiji: { ch: branch, ko: pillar.branch_kr || '', mark: branch && BRANCH_EL[branch] ? `(${ID_TO_KO[BRANCH_EL[branch]]})` : '', color: ID_TO_COLOR[BRANCH_EL[branch]] || '#1F2A44', }, sipsin: pillar.ten_god || '-', jijang: pillar.hidden_stems || pillar.fortune || '-', }; } function readingToDesktopData(reading) { const saju = reading?.saju_data || {}; const elementsObj = elementsByEngId(reading?.analysis_data?.element_scores); const strongest = maxElement(elementsObj); const pillars = ['year', 'month', 'day', 'hour'].map((key) => normalizePillar(saju[key], key)); const daeun = (reading?.daeun_data || []).map((item) => ({ age: `${item.age}~${item.age + 9}세`, rawAge: item.age, gan: item.stem || item.gan || '-', label: daeunLabel(item.age), current: item.start_year <= new Date().getFullYear() && new Date().getFullYear() <= item.end_year, startYear: item.start_year, endYear: item.end_year, })); const fallbackDaeun = [0, 10, 20, 30, 40, 50, 60, 70].map((age, index) => ({ age: `${age}~${age + 9}세`, rawAge: age, gan: ['戊', '丁', '丙', '乙', '甲', '癸', '壬', '辛'][index], label: daeunLabel(age), current: age === 30, })); return { name: reading?.name || '백호', gender: reading?.gender === 'female' ? '여' : '남', birth: `${reading?.birth_year || '1990'}년 ${reading?.birth_month || '01'}월 ${reading?.birth_day || '01'}일 ${reading?.birth_hour ?? '10'}:00`, lunar: reading?.calendar_type === 'lunar' ? '음력 입력' : '양력 입력', birthPlace: reading?.birth_place || '서울특별시', ilgan: pillars[2]?.cheongan || { ch: '庚', color: '#3A5A8C' }, pillars, elementsObj, ohaeng: ['wood', 'fire', 'earth', 'metal', 'water'].map((id) => ({ id, ko: ID_TO_KO[id], ch: ID_TO_CH[id], value: Math.round(elementsObj[id] || ({ wood: 20, fire: 35, earth: 25, metal: 55, water: 30 }[id])), color: ID_TO_COLOR[id], })), strongest, summary: reading?.interpretation_json?.summary || '의리가 강하고 책임감이 뛰어난 흐름입니다. 목표를 정하면 끝까지 해내는 추진력과 원칙을 중시하는 태도가 장점으로 드러납니다.', traits: deriveTraits(elementsObj, []), daeun: daeun.length ? daeun : fallbackDaeun, dayMasterStrength: reading?.analysis_data?.day_master_strength, }; } export default function SajuDesktop({ reading }) { const navigate = useNavigate(); const data = readingToDesktopData(reading); return (
사주의 흐름을 읽고,
당신의 길을 밝혀드립니다.} />
navigate('/saju')} />
t.ko || t.label)} />
navigate('/saju/me')} />
); } function BasicInfoBar({ data, onEdit }) { return (
기본 정보
양 · 일간 {data.ilgan.ch}} />
); } function InfoCol({ label, value }) { return (
{label}
{value}
); } function SajuStructureCard({ data }) { return (
))} pillar.cheongan)} day /> pillar.jiji)} day /> pillar.sipsin)} /> pillar.jijang)} mono />
{data.pillars.map((pillar) => ( {pillar.id === 'day' && (
일간
)}
{pillar.label}
※ 일간(나)을 중심으로 사주의 흐름과 균형을 해석합니다.
); } const thStyle = ({ active = false } = {}) => ({ padding: '8px 4px 12px', textAlign: 'center', borderBottom: '1px solid rgba(31,42,68,0.08)', background: active ? 'rgba(106,76,124,0.06)' : 'transparent', position: 'relative', }); function Row({ label, cells, day }) { return ( {label} {cells.map((cell, index) => { const isDay = index === 2 && day; return (
{cell.ch}
{cell.ko} {cell.mark}
); })} ); } function RowText({ label, cells, mono }) { return ( {label} {cells.map((cell, index) => ( {String(cell || '-')} ))} ); } function OhaengCard({ data }) { const strongest = maxElement(data.elementsObj); return (
{data.ohaeng.map((element) => { const height = Math.min(100, Math.max(8, (element.value / 60) * 100)); return (
{element.value}%
{element.ko}({element.ch})
); })}
{ID_TO_KO[strongest.id]}({ID_TO_CH[strongest.id]})의 기운이 강한 사주입니다.
강한 기운을 바탕으로 장점을 살리고 부족한 기운은 생활 습관과 관계에서 보완해 보세요.
); } function HoryungInsightCard({ data }) { const strongest = maxElement(data.elementsObj); const items = [ { title: `일간이 ${data.ilgan.ch}이시네요.`, desc: '단단한 중심과 자기 기준을 갖고 흐름을 읽는 힘이 있습니다.' }, { title: `${ID_TO_KO[strongest.id]}(${ID_TO_CH[strongest.id]})의 기운이 두드러져요.`, desc: '해당 기운의 장점을 생활과 일의 방향으로 살려보세요.' }, { title: '균형을 보완하면 더욱 좋아요.', desc: '강한 기운만 밀어붙이기보다 부족한 기운을 의식하면 흐름이 부드러워집니다.' }, { title: '지금의 선택이 미래의 나를 만듭니다.', desc: '작은 실천을 꾸준히 쌓는 시기로 삼아보세요.' }, ]; return (

호령이의 해설

{items.map((item, index) => (
{index + 1}
{item.title}
{item.desc}
))}
지금의 선택이
미래의 나를 만듭니다.
); } function TraitDeskCard({ color, iconName, title, body, bullets }) { return (
{title}
{body &&
{body}
} {bullets && (
    {bullets.map((item) => (
  • · {item}
  • ))}
)}
); } function TraitIcon({ name, color, size }) { const common = { width: size, height: size, viewBox: '0 0 24 24', fill: 'none', stroke: color, strokeWidth: '1.7', strokeLinecap: 'round', strokeLinejoin: 'round' }; if (name === 'heart') return ; if (name === 'challenge') return ; if (name === 'lead') return ; if (name === 'adapt') return ; return ; } function DaeunDeskCard({ data }) { const current = data.daeun.find((item) => item.current) || data.daeun[0]; return (

대운 흐름

10년 단위 운의 흐름을 살펴보세요.
{data.daeun.map((item, index) => ( {index < data.daeun.length - 1 && (
)}
))}
현재 대운 해설 ({current?.age})
자기 확장과 기반을 다지는 시기입니다.
꾸준한 노력과 인내가 결실을 맺고, 커리어와 재정적 성장이 기대됩니다.
); } function DaeunNodeDesk({ age, gan, label, current }) { return (
{current && (
현재
)}
{age}
{gan}
{label}
); } function ConsultCTA({ onClick }) { return (
1:1 PERSONAL CONSULT
더 깊은 해석이 필요하신가요?
개인 맞춤 상담을 통해 당신의 사주를 더 깊이 이해하고 명확한 방향을 찾아보세요.
); }