사주 풀이 고도화, NAS 배포 자동화
This commit is contained in:
71
components/AccordionItem.tsx
Normal file
71
components/AccordionItem.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
|
||||
export function AccordionItem({ title, content, icon, defaultOpen = false }: {
|
||||
title: string;
|
||||
content: string;
|
||||
icon: string;
|
||||
defaultOpen?: boolean;
|
||||
}) {
|
||||
const [isOpen, setIsOpen] = useState(defaultOpen);
|
||||
|
||||
return (
|
||||
<div className={`rounded-2xl border transition-all duration-300 ${isOpen ? 'border-indigo-200 shadow-lg bg-white' : 'border-gray-100 bg-gray-50/50 hover:bg-white hover:border-gray-200'}`}>
|
||||
<button
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
className="w-full flex items-center gap-3 p-4 md:p-5 text-left cursor-pointer"
|
||||
>
|
||||
<span className="text-2xl flex-shrink-0">{icon}</span>
|
||||
<span className={`flex-1 font-bold text-base md:text-lg transition-colors ${isOpen ? 'text-indigo-900' : 'text-gray-700'}`}>
|
||||
{title}
|
||||
</span>
|
||||
<svg
|
||||
className={`w-5 h-5 text-gray-400 transition-transform duration-300 flex-shrink-0 ${isOpen ? 'rotate-180' : ''}`}
|
||||
fill="none" viewBox="0 0 24 24" stroke="currentColor"
|
||||
>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
</button>
|
||||
<div className={`overflow-hidden transition-all duration-300 ${isOpen ? 'max-h-[2000px] opacity-100' : 'max-h-0 opacity-0'}`}>
|
||||
<div className="px-4 md:px-5 pb-5 pt-0">
|
||||
<div className="border-t border-gray-100 pt-4">
|
||||
<article className="prose prose-base max-w-none prose-indigo prose-p:text-gray-700 prose-li:text-gray-700 prose-p:leading-relaxed">
|
||||
<ReactMarkdown remarkPlugins={[remarkGfm]}>
|
||||
{content}
|
||||
</ReactMarkdown>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function parseSections(markdown: string): { title: string; content: string }[] {
|
||||
const sections: { title: string; content: string }[] = [];
|
||||
const lines = markdown.split('\n');
|
||||
let currentTitle = '';
|
||||
let currentContent: string[] = [];
|
||||
|
||||
for (const line of lines) {
|
||||
const headerMatch = line.match(/^## \d+\.\s*(.+)$/);
|
||||
if (headerMatch) {
|
||||
if (currentTitle) {
|
||||
sections.push({ title: currentTitle, content: currentContent.join('\n').trim() });
|
||||
}
|
||||
currentTitle = headerMatch[1];
|
||||
currentContent = [];
|
||||
} else if (currentTitle) {
|
||||
currentContent.push(line);
|
||||
}
|
||||
}
|
||||
if (currentTitle) {
|
||||
sections.push({ title: currentTitle, content: currentContent.join('\n').trim() });
|
||||
}
|
||||
return sections;
|
||||
}
|
||||
|
||||
export const SECTION_ICONS = ['🌟', '⚖️', '🔗', '✨', '💰', '💼', '💕', '🏥', '🌊', '📅', '👑', '💌'];
|
||||
Reference in New Issue
Block a user