당신의 길을 밝혀드립니다.} />
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 (
당신의 길을 밝혀드립니다.}
/>
| {data.pillars.map((pillar) => ( |
{pillar.id === 'day' && (
일간
)}
{pillar.label}
|
))}
|---|