From 435e6fb1bc1c45fab38956a5e82b4fa978eb7866 Mon Sep 17 00:00:00 2001 From: gahusb Date: Tue, 26 May 2026 08:33:52 +0900 Subject: [PATCH] =?UTF-8?q?feat(saju):=20=EC=98=A4=EB=8A=98=EC=9A=B4?= =?UTF-8?q?=EC=84=B8=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=203=EA=B0=9C?= =?UTF-8?q?=20(FortuneRing=20+=20ScoreCard=20+=20LuckyBox)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/saju/components/FortuneRing.jsx | 32 +++++++++++++++++++ src/pages/saju/components/LuckyBox.jsx | 21 +++++++++++++ src/pages/saju/components/ScoreCard.jsx | 38 +++++++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 src/pages/saju/components/FortuneRing.jsx create mode 100644 src/pages/saju/components/LuckyBox.jsx create mode 100644 src/pages/saju/components/ScoreCard.jsx diff --git a/src/pages/saju/components/FortuneRing.jsx b/src/pages/saju/components/FortuneRing.jsx new file mode 100644 index 0000000..17b1a6c --- /dev/null +++ b/src/pages/saju/components/FortuneRing.jsx @@ -0,0 +1,32 @@ +import React from 'react'; + +export default function FortuneRing({ score, max = 100 }) { + const radius = 80; + const circumference = 2 * Math.PI * radius; + const safe = Math.max(0, Math.min(score || 0, max)); + const dashOffset = circumference - (safe / max) * circumference; + + return ( +
+ + + + +
+
{safe}
+
/ {max}
+
+
+ ); +} diff --git a/src/pages/saju/components/LuckyBox.jsx b/src/pages/saju/components/LuckyBox.jsx new file mode 100644 index 0000000..847fd99 --- /dev/null +++ b/src/pages/saju/components/LuckyBox.jsx @@ -0,0 +1,21 @@ +import React from 'react'; + +export default function LuckyBox({ lucky }) { + if (!lucky) return null; + return ( +
+
+
럭키 컬러
+
{(lucky.color || []).join(' · ')}
+
+
+
럭키 숫자
+
{lucky.number}
+
+
+
럭키 방향
+
{lucky.direction}
+
+
+ ); +} diff --git a/src/pages/saju/components/ScoreCard.jsx b/src/pages/saju/components/ScoreCard.jsx new file mode 100644 index 0000000..22546f8 --- /dev/null +++ b/src/pages/saju/components/ScoreCard.jsx @@ -0,0 +1,38 @@ +import React from 'react'; + +const ICON_BY_CATEGORY = { + wealth: '💰', + romance: '💖', + social: '🤝', + career: '💼', +}; + +const COLOR_VAR_BY_CATEGORY = { + wealth: 'var(--saju-wealth)', + romance: 'var(--saju-romance)', + social: 'var(--saju-social)', + career: 'var(--saju-career)', +}; + +const TITLE_BY_CATEGORY = { + wealth: '재물운', + romance: '연애운', + social: '인간관계', + career: '직장운', +}; + +export default function ScoreCard({ category, score }) { + const safe = Math.max(0, Math.min(score || 0, 100)); + return ( +
+
+ {ICON_BY_CATEGORY[category]} + {TITLE_BY_CATEGORY[category]} +
+
{safe}/100
+
+
+
+
+ ); +}