From b32478850897f8378352af942a15df382277bde4 Mon Sep 17 00:00:00 2001 From: CocoRoF Date: Wed, 16 Jul 2025 01:08:55 +0000 Subject: [PATCH 1/5] feat: Implement ChatPage with Sidebar and ChatContent components, including localStorage integration for active section --- .../chat/components/ChatContent.module.scss | 116 ++++++++++++++++++ src/app/chat/components/ChatContent.tsx | 31 +++++ src/app/chat/page.tsx | 75 +++++++++++ src/app/main/components/MainPageContent.tsx | 9 ++ src/app/main/components/Sidebar.tsx | 17 ++- src/app/main/components/types.ts | 2 + 6 files changed, 244 insertions(+), 6 deletions(-) create mode 100644 src/app/chat/components/ChatContent.module.scss create mode 100644 src/app/chat/components/ChatContent.tsx create mode 100644 src/app/chat/page.tsx diff --git a/src/app/chat/components/ChatContent.module.scss b/src/app/chat/components/ChatContent.module.scss new file mode 100644 index 00000000..9709099d --- /dev/null +++ b/src/app/chat/components/ChatContent.module.scss @@ -0,0 +1,116 @@ +// Chat Content Styles +$primary-blue: #2563eb; +$primary-purple: #7c3aed; +$primary-green: #059669; +$gray-50: #f9fafb; +$gray-100: #f3f4f6; +$gray-200: #e5e7eb; +$gray-300: #d1d5db; +$gray-400: #9ca3af; +$gray-500: #6b7280; +$gray-600: #4b5563; +$gray-700: #374151; +$gray-800: #1f2937; +$gray-900: #111827; +$white: #ffffff; + +.chatContainer { + height: 100%; + display: flex; + flex-direction: column; + background: $white; + border-radius: 0.75rem; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); +} + +.welcomeSection { + flex: 1; + display: flex; + align-items: center; + justify-content: center; + padding: 3rem; +} + +.welcomeContent { + text-align: center; + max-width: 600px; + + h1 { + font-size: 2.5rem; + font-weight: 700; + color: $gray-900; + margin: 0 0 1rem 0; + background: linear-gradient(135deg, $primary-blue 0%, $primary-purple 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + } + + p { + font-size: 1.125rem; + color: $gray-600; + margin: 0 0 3rem 0; + line-height: 1.6; + } +} + +.suggestionCards { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); + gap: 1.5rem; + margin-top: 2rem; +} + +.card { + background: $white; + border: 1px solid $gray-200; + border-radius: 0.75rem; + padding: 1.5rem; + text-align: center; + transition: all 0.3s ease; + cursor: pointer; + + &:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1); + border-color: $primary-blue; + } + + h3 { + font-size: 1.125rem; + font-weight: 600; + color: $gray-900; + margin: 0 0 0.5rem 0; + } + + p { + font-size: 0.875rem; + color: $gray-500; + margin: 0; + line-height: 1.4; + } +} + +// Responsive Design +@media (max-width: 768px) { + .welcomeContent { + padding: 1.5rem; + + h1 { + font-size: 2rem; + } + + p { + font-size: 1rem; + } + } + + .suggestionCards { + grid-template-columns: 1fr; + gap: 1rem; + } + + .card { + padding: 1rem; + } +} diff --git a/src/app/chat/components/ChatContent.tsx b/src/app/chat/components/ChatContent.tsx new file mode 100644 index 00000000..89726151 --- /dev/null +++ b/src/app/chat/components/ChatContent.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import styles from './ChatContent.module.scss'; + +const ChatContent: React.FC = () => { + return ( +
+
+
+

채팅을 시작해보세요! 🚀

+

AI와 대화하며 궁금한 것들을 물어보세요.

+
+
+

✨ 질문하기

+

무엇이든 물어보세요

+
+
+

💡 아이디어 얻기

+

창의적인 아이디어를 얻어보세요

+
+
+

📚 학습하기

+

새로운 것을 배워보세요

+
+
+
+
+
+ ); +}; + +export default ChatContent; diff --git a/src/app/chat/page.tsx b/src/app/chat/page.tsx new file mode 100644 index 00000000..a4b480cf --- /dev/null +++ b/src/app/chat/page.tsx @@ -0,0 +1,75 @@ +'use client'; +import React from 'react'; +import { useRouter } from 'next/navigation'; +import { + FiGrid, + FiFolder, + FiCpu, + FiSettings, + FiEye, +} from 'react-icons/fi'; +import Sidebar from '@/app/main/components/Sidebar'; +import ChatContent from '@/app/chat/components/ChatContent'; +import { SidebarItem } from '@/app/main/components/types'; +import styles from '@/app/main/assets/MainPage.module.scss'; + +const ChatPage: React.FC = () => { + const router = useRouter(); + + // Main 페이지와 동일한 사이드바 아이템들 + const sidebarItems: SidebarItem[] = [ + { + id: 'canvas', + title: '워크플로우 캔버스', + description: '새로운 워크플로우 만들기', + icon: , + }, + { + id: 'workflows', + title: '완성된 워크플로우', + description: '저장된 워크플로우 관리', + icon: , + }, + { + id: 'exec-monitor', + title: '실행 및 모니터링', + description: '워크플로우 실행과 성능 모니터링', + icon: , + }, + { + id: 'settings', + title: '고급 환경 설정', + description: 'LLM 및 Tool 환경변수 직접 관리', + icon: , + }, + { + id: 'config-viewer', + title: '설정값 확인', + description: '백엔드 환경변수 및 설정 확인', + icon: , + }, + ]; + + const handleItemClick = (itemId: string) => { + // 클릭한 섹션을 localStorage에 저장하고 /main으로 이동 + localStorage.setItem('activeSection', itemId); + router.push('/main'); + }; + + return ( +
+ +
+ +
+
+ ); +}; + +export default ChatPage; diff --git a/src/app/main/components/MainPageContent.tsx b/src/app/main/components/MainPageContent.tsx index 54bf496d..4552100c 100644 --- a/src/app/main/components/MainPageContent.tsx +++ b/src/app/main/components/MainPageContent.tsx @@ -51,6 +51,13 @@ const MainPageContent: React.FC = () => { } setInitialLoad(false); } else { + // Check if there's a saved activeSection from chat page navigation + const savedActiveSection = localStorage.getItem('activeSection'); + if (savedActiveSection && ['canvas', 'workflows', 'exec-monitor', 'settings', 'config-viewer'].includes(savedActiveSection)) { + setActiveSection(savedActiveSection); + localStorage.removeItem('activeSection'); // Clear after use + } + // If no view parameter, load from localStorage const savedTab = localStorage.getItem('execMonitorTab'); if (savedTab === 'executor' || savedTab === 'monitoring') { @@ -215,6 +222,8 @@ const MainPageContent: React.FC = () => { items={sidebarItems} activeItem={activeSection} onItemClick={handleSidebarItemClick} + initialChatExpanded={false} + initialSettingExpanded={true} />
{renderContent()}
diff --git a/src/app/main/components/Sidebar.tsx b/src/app/main/components/Sidebar.tsx index a7d335e7..43fb0cbd 100644 --- a/src/app/main/components/Sidebar.tsx +++ b/src/app/main/components/Sidebar.tsx @@ -1,6 +1,7 @@ 'use client'; import React, { useState } from 'react'; import { useRouter } from 'next/navigation'; +import { RiChatSmileAiLine } from "react-icons/ri"; import { SidebarProps } from '@/app/main/components/types'; import styles from '@/app/main/assets/MainPage.module.scss'; @@ -9,10 +10,12 @@ const Sidebar: React.FC = ({ activeItem, onItemClick, className = '', + initialChatExpanded = false, + initialSettingExpanded = false, }) => { const router = useRouter(); - const [isSettingExpanded, setIsSettingExpanded] = useState(false); - const [isChatExpanded, setIsChatExpanded] = useState(false); + const [isSettingExpanded, setIsSettingExpanded] = useState(initialSettingExpanded); + const [isChatExpanded, setIsChatExpanded] = useState(initialChatExpanded); const toggleExpanded = () => { setIsSettingExpanded(!isSettingExpanded); @@ -32,6 +35,10 @@ const Sidebar: React.FC = ({ router.push('/'); }; + const handleNewChatClick = () => { + router.push('/chat'); + }; + return (