feat(phase2.5): SajuAISection 라이트 재스킨 — 이모지→SVG, gradient/보라→--jsm
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import { useState, useEffect, useRef } from 'react';
|
|||||||
import { usePathname, useSearchParams } from 'next/navigation';
|
import { usePathname, useSearchParams } from 'next/navigation';
|
||||||
import ReactMarkdown from 'react-markdown';
|
import ReactMarkdown from 'react-markdown';
|
||||||
import remarkGfm from 'remark-gfm';
|
import remarkGfm from 'remark-gfm';
|
||||||
|
import { SajuIcon, SECTION_ICON_ORDER } from './SajuIcons';
|
||||||
|
|
||||||
interface BirthKey {
|
interface BirthKey {
|
||||||
birth_year: number;
|
birth_year: number;
|
||||||
@@ -30,26 +31,20 @@ interface SajuAISectionProps {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── 섹션별 메타 (아이콘·색상) ──────────────────────────────────────────
|
// ── 섹션별 메타 (뱃지 라벨) — 아이콘은 SECTION_ICON_ORDER에서 동일 인덱스로 조회 ──
|
||||||
const SECTION_META: {
|
const SECTION_META: { badgeText: string }[] = [
|
||||||
icon: string;
|
{ badgeText: '기질' },
|
||||||
gradient: string;
|
{ badgeText: '오행' },
|
||||||
border: string;
|
{ badgeText: '지지' },
|
||||||
badge: string;
|
{ badgeText: '신살' },
|
||||||
badgeText: string;
|
{ badgeText: '재물' },
|
||||||
}[] = [
|
{ badgeText: '직업' },
|
||||||
{ icon: '🌟', gradient: 'from-violet-500 to-purple-600', border: 'border-violet-100', badge: 'bg-violet-50 border-violet-200 text-violet-700', badgeText: '기질' },
|
{ badgeText: '애정' },
|
||||||
{ icon: '⚖️', gradient: 'from-emerald-500 to-teal-600', border: 'border-emerald-100', badge: 'bg-emerald-50 border-emerald-200 text-emerald-700', badgeText: '오행' },
|
{ badgeText: '건강' },
|
||||||
{ icon: '🔗', gradient: 'from-blue-500 to-indigo-600', border: 'border-blue-100', badge: 'bg-blue-50 border-blue-200 text-blue-700', badgeText: '지지' },
|
{ badgeText: '대운' },
|
||||||
{ icon: '✨', gradient: 'from-amber-500 to-orange-500', border: 'border-amber-100', badge: 'bg-amber-50 border-amber-200 text-amber-700', badgeText: '신살' },
|
{ badgeText: '세운' },
|
||||||
{ icon: '💰', gradient: 'from-yellow-500 to-amber-600', border: 'border-yellow-100', badge: 'bg-yellow-50 border-yellow-200 text-yellow-700', badgeText: '재물' },
|
{ badgeText: '황금기' },
|
||||||
{ icon: '🎯', gradient: 'from-rose-500 to-pink-600', border: 'border-rose-100', badge: 'bg-rose-50 border-rose-200 text-rose-700', badgeText: '직업' },
|
{ badgeText: '종합' },
|
||||||
{ icon: '💕', gradient: 'from-pink-500 to-rose-500', border: 'border-pink-100', badge: 'bg-pink-50 border-pink-200 text-pink-700', badgeText: '애정' },
|
|
||||||
{ icon: '🌿', gradient: 'from-green-500 to-emerald-600', border: 'border-green-100', badge: 'bg-green-50 border-green-200 text-green-700', badgeText: '건강' },
|
|
||||||
{ icon: '🗺️', gradient: 'from-cyan-500 to-blue-600', border: 'border-cyan-100', badge: 'bg-cyan-50 border-cyan-200 text-cyan-700', badgeText: '대운' },
|
|
||||||
{ icon: '📅', gradient: 'from-indigo-500 to-violet-600', border: 'border-indigo-100', badge: 'bg-indigo-50 border-indigo-200 text-indigo-700', badgeText: '세운' },
|
|
||||||
{ icon: '🏆', gradient: 'from-amber-400 to-yellow-500', border: 'border-amber-100', badge: 'bg-amber-50 border-amber-200 text-amber-700', badgeText: '황금기' },
|
|
||||||
{ icon: '💌', gradient: 'from-slate-600 to-slate-800', border: 'border-slate-100', badge: 'bg-slate-50 border-slate-200 text-slate-700', badgeText: '종합' },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// ── 마크다운 → 섹션 파싱 ──────────────────────────────────────────────
|
// ── 마크다운 → 섹션 파싱 ──────────────────────────────────────────────
|
||||||
@@ -86,30 +81,31 @@ function parseInterpretation(text: string): ParsedSection[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── 섹션 카드 컴포넌트 ────────────────────────────────────────────────
|
// ── 섹션 카드 컴포넌트 ────────────────────────────────────────────────
|
||||||
function SectionCard({ section, meta, isOpen, onToggle }: {
|
function SectionCard({ section, meta, iconName, isOpen, onToggle }: {
|
||||||
section: ParsedSection;
|
section: ParsedSection;
|
||||||
meta: typeof SECTION_META[0];
|
meta: typeof SECTION_META[0];
|
||||||
|
iconName: (typeof SECTION_ICON_ORDER)[number];
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
onToggle: () => void;
|
onToggle: () => void;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className={`rounded-2xl border-2 ${meta.border} bg-white overflow-hidden shadow-sm transition-all`}>
|
<div className="rounded-2xl border-2 border-[var(--jsm-line)] bg-[var(--jsm-surface)] overflow-hidden shadow-sm transition-all">
|
||||||
{/* 헤더 */}
|
{/* 헤더 */}
|
||||||
<button
|
<button
|
||||||
onClick={onToggle}
|
onClick={onToggle}
|
||||||
className="w-full flex items-center gap-3 p-4 text-left hover:bg-slate-50 transition-colors"
|
className="w-full flex items-center gap-3 p-4 text-left hover:bg-[var(--jsm-surface-alt)] transition-colors"
|
||||||
>
|
>
|
||||||
{/* 번호 아이콘 */}
|
{/* 번호 아이콘 */}
|
||||||
<div className={`w-10 h-10 rounded-xl bg-gradient-to-br ${meta.gradient} flex items-center justify-center text-white font-extrabold text-sm flex-shrink-0 shadow-sm`}>
|
<div className="w-10 h-10 rounded-xl bg-[var(--jsm-accent)] flex items-center justify-center text-white font-extrabold text-sm flex-shrink-0 shadow-sm">
|
||||||
{section.number > 0 ? section.number : meta.icon}
|
{section.number > 0 ? section.number : <SajuIcon name={iconName} className="w-5 h-5" />}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
<div className="flex items-center gap-2 flex-wrap">
|
<div className="flex items-center gap-2 flex-wrap">
|
||||||
<span className={`text-[11px] font-bold px-2 py-0.5 rounded-full border ${meta.badge}`}>
|
<span className="text-[11px] font-bold px-2 py-0.5 rounded-full border border-[var(--jsm-line)] bg-[var(--jsm-accent-soft)] text-[var(--jsm-accent)]">
|
||||||
{meta.badgeText}
|
{meta.badgeText}
|
||||||
</span>
|
</span>
|
||||||
<h3 className="font-extrabold text-[#04102b] text-sm leading-snug">
|
<h3 className="font-extrabold text-[var(--jsm-ink)] text-sm leading-snug">
|
||||||
{section.title}
|
{section.title}
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
@@ -117,7 +113,7 @@ function SectionCard({ section, meta, isOpen, onToggle }: {
|
|||||||
|
|
||||||
{/* 토글 화살표 */}
|
{/* 토글 화살표 */}
|
||||||
<svg
|
<svg
|
||||||
className={`w-4 h-4 text-slate-400 flex-shrink-0 transition-transform duration-200 ${isOpen ? 'rotate-180' : ''}`}
|
className={`w-4 h-4 text-[var(--jsm-ink-faint)] flex-shrink-0 transition-transform duration-200 ${isOpen ? 'rotate-180' : ''}`}
|
||||||
fill="none" stroke="currentColor" viewBox="0 0 24 24"
|
fill="none" stroke="currentColor" viewBox="0 0 24 24"
|
||||||
>
|
>
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
||||||
@@ -126,31 +122,31 @@ function SectionCard({ section, meta, isOpen, onToggle }: {
|
|||||||
|
|
||||||
{/* 내용 (아코디언) */}
|
{/* 내용 (아코디언) */}
|
||||||
{isOpen && (
|
{isOpen && (
|
||||||
<div className="px-5 pb-5 pt-1 border-t border-slate-100">
|
<div className="px-5 pb-5 pt-1 border-t border-[var(--jsm-line)]">
|
||||||
<div className={`text-[11px] font-semibold mb-3 flex items-center gap-1.5 ${meta.badge.includes('violet') ? 'text-violet-400' : 'text-slate-400'}`}>
|
<div className="text-[11px] font-semibold mb-3 flex items-center gap-1.5 text-[var(--jsm-ink-faint)]">
|
||||||
<span className="text-base">{meta.icon}</span>
|
<SajuIcon name={iconName} className="w-4 h-4" />
|
||||||
</div>
|
</div>
|
||||||
<div className="prose prose-sm max-w-none text-slate-700 leading-relaxed">
|
<div className="prose prose-sm max-w-none text-slate-700 leading-relaxed">
|
||||||
<ReactMarkdown
|
<ReactMarkdown
|
||||||
remarkPlugins={[remarkGfm]}
|
remarkPlugins={[remarkGfm]}
|
||||||
components={{
|
components={{
|
||||||
h1: ({ children }) => <h1 className="text-base font-extrabold text-[#04102b] mt-4 mb-2">{children}</h1>,
|
h1: ({ children }) => <h1 className="text-base font-extrabold text-[var(--jsm-ink)] mt-4 mb-2">{children}</h1>,
|
||||||
h2: ({ children }) => <h2 className="text-sm font-extrabold text-[#04102b] mt-3 mb-1.5">{children}</h2>,
|
h2: ({ children }) => <h2 className="text-sm font-extrabold text-[var(--jsm-ink)] mt-3 mb-1.5">{children}</h2>,
|
||||||
h3: ({ children }) => <h3 className="text-sm font-bold text-[#04102b] mt-2 mb-1">{children}</h3>,
|
h3: ({ children }) => <h3 className="text-sm font-bold text-[var(--jsm-ink)] mt-2 mb-1">{children}</h3>,
|
||||||
p: ({ children }) => <p className="mb-3 text-sm leading-relaxed text-slate-700">{children}</p>,
|
p: ({ children }) => <p className="mb-3 text-sm leading-relaxed text-slate-700">{children}</p>,
|
||||||
strong: ({ children }) => <strong className="font-bold text-[#04102b]">{children}</strong>,
|
strong: ({ children }) => <strong className="font-bold text-[var(--jsm-ink)]">{children}</strong>,
|
||||||
em: ({ children }) => <em className="italic text-slate-600">{children}</em>,
|
em: ({ children }) => <em className="italic text-slate-600">{children}</em>,
|
||||||
ul: ({ children }) => <ul className="list-disc list-inside space-y-1.5 mb-3 text-sm text-slate-700 pl-1">{children}</ul>,
|
ul: ({ children }) => <ul className="list-disc list-inside space-y-1.5 mb-3 text-sm text-slate-700 pl-1">{children}</ul>,
|
||||||
ol: ({ children }) => <ol className="list-decimal list-inside space-y-1.5 mb-3 text-sm text-slate-700 pl-1">{children}</ol>,
|
ol: ({ children }) => <ol className="list-decimal list-inside space-y-1.5 mb-3 text-sm text-slate-700 pl-1">{children}</ol>,
|
||||||
li: ({ children }) => <li className="leading-relaxed">{children}</li>,
|
li: ({ children }) => <li className="leading-relaxed">{children}</li>,
|
||||||
blockquote: ({ children }) => (
|
blockquote: ({ children }) => (
|
||||||
<blockquote className="border-l-4 border-violet-300 pl-4 py-1 my-3 text-slate-600 bg-violet-50 rounded-r-lg text-sm italic">
|
<blockquote className="border-l-4 border-[var(--jsm-accent)] pl-4 py-1 my-3 text-slate-600 bg-[var(--jsm-accent-soft)] rounded-r-lg text-sm italic">
|
||||||
{children}
|
{children}
|
||||||
</blockquote>
|
</blockquote>
|
||||||
),
|
),
|
||||||
hr: () => <hr className="border-slate-200 my-4" />,
|
hr: () => <hr className="border-slate-200 my-4" />,
|
||||||
code: ({ children }) => (
|
code: ({ children }) => (
|
||||||
<code className="bg-slate-100 text-violet-700 px-1.5 py-0.5 rounded text-xs font-mono">
|
<code className="bg-slate-100 text-[var(--jsm-accent)] px-1.5 py-0.5 rounded text-xs font-mono">
|
||||||
{children}
|
{children}
|
||||||
</code>
|
</code>
|
||||||
),
|
),
|
||||||
@@ -314,37 +310,33 @@ export default function SajuAISection({
|
|||||||
// ── 미로그인 ────────────────────────────────────────────────────────
|
// ── 미로그인 ────────────────────────────────────────────────────────
|
||||||
if (!hasPaid) {
|
if (!hasPaid) {
|
||||||
return (
|
return (
|
||||||
<div className="bg-gradient-to-br from-[#04102b] via-[#0a1f5c] to-[#04102b] rounded-2xl border border-[#1a3a7a] p-7 text-center relative overflow-hidden">
|
<div className="bg-[var(--jsm-navy)] rounded-2xl p-7 text-center">
|
||||||
<div className="absolute inset-0 opacity-[0.05]"
|
<div className="inline-flex items-center gap-2 bg-[var(--jsm-accent)] text-white text-xs font-semibold px-3 py-1 rounded-full mb-3">
|
||||||
style={{ backgroundImage: 'radial-gradient(circle, #a78bfa 1px, transparent 1px)', backgroundSize: '22px 22px' }} />
|
AI PREMIUM
|
||||||
<div className="relative">
|
|
||||||
<div className="inline-flex items-center gap-2 bg-amber-400/10 border border-amber-400/25 text-amber-300 text-xs font-semibold px-3 py-1 rounded-full mb-3">
|
|
||||||
AI PREMIUM
|
|
||||||
</div>
|
|
||||||
<h3 className="text-xl font-extrabold text-white mb-2">AI 상세 해석 (12개 항목)</h3>
|
|
||||||
<p className="text-blue-200/60 text-sm mb-6">
|
|
||||||
성격, 재물운, 직업 적성, 애정운, 건강운, 대운 분석 등<br />
|
|
||||||
Gemini 2.5 Pro가 생성하는 맞춤형 사주 해석을 받아보세요.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
{/* 미리보기 섹션 목록 */}
|
|
||||||
<div className="grid grid-cols-3 gap-2 mb-6 text-left">
|
|
||||||
{SECTION_META.map((meta, i) => (
|
|
||||||
<div key={i} className="flex items-center gap-1.5 bg-white/5 rounded-lg px-2 py-1.5">
|
|
||||||
<span className="text-sm">{meta.icon}</span>
|
|
||||||
<span className="text-xs text-blue-200/70 font-medium">{meta.badgeText}</span>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<a
|
|
||||||
href={loginHref}
|
|
||||||
className="inline-flex items-center gap-2 bg-white/10 hover:bg-white/20 text-blue-100/80 font-semibold px-7 py-3 rounded-xl transition-colors"
|
|
||||||
>
|
|
||||||
로그인하고 AI 상세 해석 무료로 받기
|
|
||||||
</a>
|
|
||||||
<p className="text-blue-200/40 text-xs mt-3">로그인 회원은 하루 1회 무료 · 저장된 해석은 언제든 다시 보기</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
<h3 className="text-xl font-extrabold text-white mb-2">AI 상세 해석 (12개 항목)</h3>
|
||||||
|
<p className="text-white/70 text-sm mb-6">
|
||||||
|
성격, 재물운, 직업 적성, 애정운, 건강운, 대운 분석 등<br />
|
||||||
|
Gemini 2.5 Pro가 생성하는 맞춤형 사주 해석을 받아보세요.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* 미리보기 섹션 목록 */}
|
||||||
|
<div className="grid grid-cols-3 gap-2 mb-6 text-left">
|
||||||
|
{SECTION_META.map((meta, i) => (
|
||||||
|
<div key={i} className="flex items-center gap-1.5 bg-white/10 rounded-lg px-2 py-1.5">
|
||||||
|
<SajuIcon name={SECTION_ICON_ORDER[i]} className="w-4 h-4 text-white/80" />
|
||||||
|
<span className="text-xs text-white/70 font-medium">{meta.badgeText}</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href={loginHref}
|
||||||
|
className="inline-flex items-center gap-2 bg-white hover:bg-white/90 text-[var(--jsm-navy)] font-semibold px-7 py-3 rounded-xl transition-colors"
|
||||||
|
>
|
||||||
|
로그인하고 AI 상세 해석 무료로 받기
|
||||||
|
</a>
|
||||||
|
<p className="text-white/50 text-xs mt-3">로그인 회원은 하루 1회 무료 · 저장된 해석은 언제든 다시 보기</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -352,14 +344,14 @@ export default function SajuAISection({
|
|||||||
// ── 로딩 ──────────────────────────────────────────────────────────
|
// ── 로딩 ──────────────────────────────────────────────────────────
|
||||||
if (status === 'loading') {
|
if (status === 'loading') {
|
||||||
return (
|
return (
|
||||||
<div className="bg-white rounded-2xl border border-[#dbe8ff] p-8 text-center">
|
<div className="bg-[var(--jsm-surface)] rounded-2xl border border-[var(--jsm-line)] p-8 text-center">
|
||||||
<div className="w-10 h-10 border-2 border-violet-600 border-t-transparent rounded-full animate-spin mx-auto mb-4" />
|
<div className="w-10 h-10 border-2 border-[var(--jsm-accent)] border-t-transparent rounded-full animate-spin mx-auto mb-4" />
|
||||||
<p className="text-slate-500 text-sm font-medium">AI가 사주를 분석하는 중입니다...</p>
|
<p className="text-slate-500 text-sm font-medium">AI가 사주를 분석하는 중입니다...</p>
|
||||||
<p className="text-slate-400 text-xs mt-1">약 20~30초 소요될 수 있습니다</p>
|
<p className="text-slate-400 text-xs mt-1">약 20~30초 소요될 수 있습니다</p>
|
||||||
<div className="mt-5 flex flex-wrap justify-center gap-2">
|
<div className="mt-5 flex flex-wrap justify-center gap-2">
|
||||||
{SECTION_META.map((meta, i) => (
|
{SECTION_META.map((meta, i) => (
|
||||||
<span key={i} className="flex items-center gap-1 text-xs text-slate-400 animate-pulse">
|
<span key={i} className="flex items-center gap-1 text-xs text-slate-400 animate-pulse">
|
||||||
<span>{meta.icon}</span>{meta.badgeText}
|
<SajuIcon name={SECTION_ICON_ORDER[i]} className="w-3.5 h-3.5" />{meta.badgeText}
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -388,23 +380,23 @@ export default function SajuAISection({
|
|||||||
|
|
||||||
// ── 해석 완료 ─────────────────────────────────────────────────────
|
// ── 해석 완료 ─────────────────────────────────────────────────────
|
||||||
return (
|
return (
|
||||||
<div className="bg-white rounded-2xl border border-[#dbe8ff] overflow-hidden">
|
<div className="bg-[var(--jsm-surface)] rounded-2xl border border-[var(--jsm-line)] overflow-hidden">
|
||||||
{/* 헤더 */}
|
{/* 헤더 */}
|
||||||
<div className="flex items-center gap-2 px-6 py-4 border-b border-slate-100 bg-gradient-to-r from-[#04102b] to-[#0a1f5c]">
|
<div className="flex items-center gap-2 px-6 py-4 bg-[var(--jsm-navy)]">
|
||||||
<div className="w-7 h-7 rounded-lg bg-gradient-to-br from-violet-400 to-amber-400 flex items-center justify-center flex-shrink-0">
|
<div className="w-7 h-7 rounded-lg bg-[var(--jsm-accent)] flex items-center justify-center flex-shrink-0">
|
||||||
<svg className="w-4 h-4 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg className="w-4 h-4 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" />
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<h2 className="text-sm font-extrabold text-white">AI 상세 해석</h2>
|
<h2 className="text-sm font-extrabold text-white">AI 상세 해석</h2>
|
||||||
<p className="text-blue-300/60 text-[11px]">12개 항목 · 클릭해서 펼쳐보세요</p>
|
<p className="text-white/60 text-[11px]">12개 항목 · 클릭해서 펼쳐보세요</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<button
|
<button
|
||||||
onClick={handleRegenerate}
|
onClick={handleRegenerate}
|
||||||
title="AI 해석 재생성"
|
title="AI 해석 재생성"
|
||||||
className="text-[11px] text-blue-300/60 hover:text-blue-200 px-2 py-1 rounded-lg hover:bg-white/10 transition-all flex items-center gap-1"
|
className="text-[11px] text-white/60 hover:text-white px-2 py-1 rounded-lg hover:bg-white/10 transition-all flex items-center gap-1"
|
||||||
>
|
>
|
||||||
<svg className="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg className="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||||||
@@ -428,7 +420,7 @@ export default function SajuAISection({
|
|||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<button
|
<button
|
||||||
onClick={expandAll}
|
onClick={expandAll}
|
||||||
className="text-xs text-violet-600 hover:text-violet-800 font-semibold px-3 py-1 rounded-lg border border-violet-200 hover:bg-violet-50 transition-colors"
|
className="text-xs text-[var(--jsm-accent)] hover:text-[var(--jsm-accent-hover)] font-semibold px-3 py-1 rounded-lg border border-[var(--jsm-accent)] hover:bg-[var(--jsm-accent-soft)] transition-colors"
|
||||||
>
|
>
|
||||||
전체 펼치기
|
전체 펼치기
|
||||||
</button>
|
</button>
|
||||||
@@ -452,6 +444,7 @@ export default function SajuAISection({
|
|||||||
key={idx}
|
key={idx}
|
||||||
section={section}
|
section={section}
|
||||||
meta={meta}
|
meta={meta}
|
||||||
|
iconName={SECTION_ICON_ORDER[metaIdx]}
|
||||||
isOpen={openSections.has(idx)}
|
isOpen={openSections.has(idx)}
|
||||||
onToggle={() => toggleSection(idx)}
|
onToggle={() => toggleSection(idx)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user