From c0f1a72c2c303b5ae8cc9c475a40a2ffe8f5526f Mon Sep 17 00:00:00 2001 From: ddingjoo Date: Tue, 6 Jan 2026 13:52:02 +0900 Subject: [PATCH 1/3] =?UTF-8?q?[FEAT]=20Sidebar=20=EB=A9=94=EB=89=B4=20?= =?UTF-8?q?=EA=B3=84=EC=B8=B5=20=EA=B5=AC=EC=A1=B0=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 영어공부: OPIC 연습, 작문 연습 하위 메뉴 추가 - 프리토킹: 사람들과, AI와 하위 메뉴 추가 - 하위 메뉴 접기/펼치기 기능 (Collapse) - 펼침 상태 localStorage 저장 - Dashboard 학습 모드 카드 업데이트 (3개로 변경) - Dashboard 이모지 제거 --- src/App.jsx | 49 +++--- src/layouts/MainLayout/Sidebar/index.jsx | 205 +++++++++++++++-------- 2 files changed, 164 insertions(+), 90 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 24d742d..40fcdca 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -2,15 +2,22 @@ import { Routes, Route } from 'react-router-dom' import { Box, Typography, Container, Card, CardContent, Grid, Button } from '@mui/material' import { RecordVoiceOver as InterviewIcon, - Headphones as OpicIcon, + School as EnglishIcon, Chat as FreetalkIcon, - Edit as WritingIcon, } from '@mui/icons-material' import MainLayout from './layouts/MainLayout' // 임시 대시보드 페이지 function Dashboard() { const learningModes = [ + { + id: 'english', + title: '영어공부', + description: 'OPIC 연습, 작문 연습으로 영어 실력 향상', + icon: EnglishIcon, + color: '#2196f3', + path: '/opic', + }, { id: 'interview', title: '면접 시뮬레이션', @@ -19,29 +26,13 @@ function Dashboard() { color: '#0124ac', path: '/interview', }, - { - id: 'opic', - title: 'OPIC 연습', - description: '레벨별 맞춤 문제로 실력 향상', - icon: OpicIcon, - color: '#2196f3', - path: '/opic', - }, { id: 'freetalk', title: '프리토킹', - description: 'AI와 자유롭게 영어로 대화', + description: '사람들과 또는 AI와 자유롭게 대화', icon: FreetalkIcon, color: '#4caf50', - path: '/freetalk', - }, - { - id: 'writing', - title: '작문 연습', - description: '문법 교정과 표현 피드백', - icon: WritingIcon, - color: '#ff9800', - path: '/writing', + path: '/freetalk/ai', }, ] @@ -49,7 +40,7 @@ function Dashboard() { - 안녕하세요! 👋 + 안녕하세요! 오늘은 어떤 학습을 해볼까요? @@ -136,10 +127,19 @@ function OpicPage() { ) } -function FreetalkPage() { +function FreetalkPeoplePage() { + return ( + + 프리토킹 - 사람들과 + 다른 학습자와 영어로 대화 + + ) +} + +function FreetalkAiPage() { return ( - 프리토킹 + 프리토킹 - AI와 AI와 자유로운 대화 ) @@ -199,7 +199,8 @@ function App() { } /> } /> } /> - } /> + } /> + } /> } /> } /> } /> diff --git a/src/layouts/MainLayout/Sidebar/index.jsx b/src/layouts/MainLayout/Sidebar/index.jsx index 4900e66..2b70964 100644 --- a/src/layouts/MainLayout/Sidebar/index.jsx +++ b/src/layouts/MainLayout/Sidebar/index.jsx @@ -1,3 +1,4 @@ +import { useState, useEffect } from 'react' import { useLocation, useNavigate } from 'react-router-dom' import { Drawer, @@ -10,6 +11,7 @@ import { IconButton, Divider, Typography, + Collapse, useTheme, useMediaQuery, } from '@mui/material' @@ -23,6 +25,11 @@ import { Edit as WritingIcon, Assessment as ReportIcon, Settings as SettingsIcon, + School as EnglishIcon, + People as PeopleIcon, + SmartToy as AiIcon, + ExpandMore as ExpandMoreIcon, + ExpandLess as ExpandLessIcon, } from '@mui/icons-material' const DRAWER_WIDTH = 260 @@ -32,6 +39,27 @@ const menuItems = [ { category: '학습 모드', items: [ + { + id: 'english', + label: '영어공부', + icon: EnglishIcon, + children: [ + { + id: 'opic', + label: 'OPIC 연습', + icon: OpicIcon, + path: '/opic', + description: '레벨별 맞춤 연습' + }, + { + id: 'writing', + label: '작문 연습', + icon: WritingIcon, + path: '/writing', + description: '문법 교정 & 피드백' + }, + ], + }, { id: 'interview', label: '면접 시뮬레이션', @@ -39,26 +67,26 @@ const menuItems = [ path: '/interview', description: 'AI 면접관과 실전 연습' }, - { - id: 'opic', - label: 'OPIC 연습', - icon: OpicIcon, - path: '/opic', - description: '레벨별 맞춤 연습' - }, { id: 'freetalk', label: '프리토킹', icon: FreetalkIcon, - path: '/freetalk', - description: 'AI와 자유로운 대화' - }, - { - id: 'writing', - label: '작문 연습', - icon: WritingIcon, - path: '/writing', - description: '문법 교정 & 피드백' + children: [ + { + id: 'freetalk-people', + label: '사람들과', + icon: PeopleIcon, + path: '/freetalk/people', + description: '다른 학습자와 대화' + }, + { + id: 'freetalk-ai', + label: 'AI와', + icon: AiIcon, + path: '/freetalk/ai', + description: 'AI와 자유로운 대화' + }, + ], }, ], }, @@ -96,6 +124,16 @@ const Sidebar = ({ open, collapsed, onToggleCollapse, onClose }) => { const navigate = useNavigate() const isMobile = useMediaQuery(theme.breakpoints.down('md')) + // 펼침 상태 (localStorage 저장) + const [expandedMenus, setExpandedMenus] = useState(() => { + const saved = localStorage.getItem('expandedMenus') + return saved ? JSON.parse(saved) : { english: true, freetalk: true } + }) + + useEffect(() => { + localStorage.setItem('expandedMenus', JSON.stringify(expandedMenus)) + }, [expandedMenus]) + const drawerWidth = collapsed ? DRAWER_WIDTH_COLLAPSED : DRAWER_WIDTH const handleNavigation = (path) => { @@ -105,7 +143,91 @@ const Sidebar = ({ open, collapsed, onToggleCollapse, onClose }) => { } } + const handleToggleExpand = (menuId) => { + setExpandedMenus((prev) => ({ + ...prev, + [menuId]: !prev[menuId], + })) + } + const isActive = (path) => location.pathname === path + const isParentActive = (children) => children?.some((child) => location.pathname === child.path) + + const renderMenuItem = (item, isChild = false) => { + const Icon = item.icon + const hasChildren = item.children && item.children.length > 0 + const active = item.path ? isActive(item.path) : isParentActive(item.children) + const expanded = expandedMenus[item.id] + + return ( + + + { + if (hasChildren) { + handleToggleExpand(item.id) + } else if (item.path) { + handleNavigation(item.path) + } + }} + sx={{ + borderRadius: 2, + minHeight: 48, + justifyContent: collapsed ? 'center' : 'flex-start', + px: collapsed ? 1 : 2, + pl: isChild && !collapsed ? 4 : (collapsed ? 1 : 2), + backgroundColor: active && !hasChildren ? 'primary.main' : 'transparent', + color: active && !hasChildren ? 'white' : 'text.primary', + '&:hover': { + backgroundColor: active && !hasChildren + ? 'primary.dark' + : 'action.hover', + }, + }} + > + + + + + {!collapsed && ( + <> + + {hasChildren && ( + expanded ? : + )} + + )} + + + + {/* 하위 메뉴 */} + {hasChildren && !collapsed && ( + + + {item.children.map((child) => renderMenuItem(child, true))} + + + )} + + ) + } const drawerContent = ( @@ -143,56 +265,7 @@ const Sidebar = ({ open, collapsed, onToggleCollapse, onClose }) => { )} - {category.items.map((item) => { - const Icon = item.icon - const active = isActive(item.path) - - return ( - - handleNavigation(item.path)} - sx={{ - borderRadius: 2, - minHeight: 48, - justifyContent: collapsed ? 'center' : 'flex-start', - px: collapsed ? 1 : 2, - backgroundColor: active ? 'primary.main' : 'transparent', - color: active ? 'white' : 'text.primary', - '&:hover': { - backgroundColor: active - ? 'primary.dark' - : 'action.hover', - }, - }} - > - - - - - {!collapsed && ( - - )} - - - ) - })} + {category.items.map((item) => renderMenuItem(item))} {categoryIndex < menuItems.length - 1 && !collapsed && ( From 3de5b6bba041b595b1675e035424be913ccdc775 Mon Sep 17 00:00:00 2001 From: ddingjoo Date: Tue, 6 Jan 2026 13:56:52 +0900 Subject: [PATCH 2/3] =?UTF-8?q?[FEAT]=20=EB=A9=B4=EC=A0=91=20=EC=8B=9C?= =?UTF-8?q?=EB=AE=AC=EB=A0=88=EC=9D=B4=EC=85=98=20=EB=A9=94=EB=89=B4=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.jsx | 184 ++++++++++++++++++----- src/layouts/MainLayout/Sidebar/index.jsx | 8 - 2 files changed, 144 insertions(+), 48 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 40fcdca..7171b49 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,14 +1,22 @@ -import { Routes, Route } from 'react-router-dom' -import { Box, Typography, Container, Card, CardContent, Grid, Button } from '@mui/material' +import { useState } from 'react' +import { Routes, Route, useNavigate } from 'react-router-dom' +import { Box, Typography, Container, Card, CardContent, Grid, Button, Collapse, IconButton } from '@mui/material' import { - RecordVoiceOver as InterviewIcon, School as EnglishIcon, Chat as FreetalkIcon, + Headphones as OpicIcon, + Edit as WritingIcon, + People as PeopleIcon, + SmartToy as AiIcon, + ChevronRight as ChevronRightIcon, } from '@mui/icons-material' import MainLayout from './layouts/MainLayout' // 임시 대시보드 페이지 function Dashboard() { + const navigate = useNavigate() + const [expandedCard, setExpandedCard] = useState(null) + const learningModes = [ { id: 'english', @@ -16,15 +24,10 @@ function Dashboard() { description: 'OPIC 연습, 작문 연습으로 영어 실력 향상', icon: EnglishIcon, color: '#2196f3', - path: '/opic', - }, - { - id: 'interview', - title: '면접 시뮬레이션', - description: 'AI 면접관과 실전처럼 연습하세요', - icon: InterviewIcon, - color: '#0124ac', - path: '/interview', + children: [ + { id: 'opic', title: 'OPIC 연습', icon: OpicIcon, path: '/opic', description: '레벨별 맞춤 연습' }, + { id: 'writing', title: '작문 연습', icon: WritingIcon, path: '/writing', description: '문법 교정 & 피드백' }, + ], }, { id: 'freetalk', @@ -32,10 +35,26 @@ function Dashboard() { description: '사람들과 또는 AI와 자유롭게 대화', icon: FreetalkIcon, color: '#4caf50', - path: '/freetalk/ai', + children: [ + { id: 'freetalk-people', title: '사람들과', icon: PeopleIcon, path: '/freetalk/people', description: '다른 학습자와 대화' }, + { id: 'freetalk-ai', title: 'AI와', icon: AiIcon, path: '/freetalk/ai', description: 'AI와 자유 대화' }, + ], }, ] + const handleCardClick = (mode) => { + if (mode.children) { + setExpandedCard(expandedCard === mode.id ? null : mode.id) + } else if (mode.path) { + navigate(mode.path) + } + } + + const handleSubItemClick = (path, e) => { + e.stopPropagation() + navigate(path) + } + return ( @@ -47,49 +66,134 @@ function Dashboard() { - + {learningModes.map((mode) => { const Icon = mode.icon + const isExpanded = expandedCard === mode.id + const hasChildren = mode.children && mode.children.length > 0 + return ( - + handleCardClick(mode)} sx={{ height: '100%', cursor: 'pointer', - transition: 'transform 0.2s, box-shadow 0.2s', + transition: 'all 0.4s cubic-bezier(0.4, 0, 0.2, 1)', + transform: isExpanded ? 'scale(1.02)' : 'scale(1)', + boxShadow: isExpanded ? 8 : 1, + border: isExpanded ? `2px solid ${mode.color}` : '2px solid transparent', '&:hover': { - transform: 'translateY(-4px)', - boxShadow: 4, + transform: isExpanded ? 'scale(1.02)' : 'translateY(-4px)', + boxShadow: isExpanded ? 8 : 4, }, }} > - - - + + + {/* 메인 아이콘 */} + + + + + {/* 텍스트 */} + + + + {mode.title} + + {hasChildren && ( + + )} + + + {mode.description} + + - - {mode.title} - - - {mode.description} - + + {/* 하위 카테고리 - 애니메이션으로 펼쳐짐 */} + {hasChildren && ( + + + {mode.children.map((child, index) => { + const ChildIcon = child.icon + return ( + handleSubItemClick(child.path, e)} + sx={{ + flex: 1, + p: 2, + borderRadius: 2, + backgroundColor: 'action.hover', + cursor: 'pointer', + transition: 'all 0.3s', + transform: isExpanded ? 'translateX(0)' : 'translateX(-20px)', + opacity: isExpanded ? 1 : 0, + transitionDelay: `${index * 100}ms`, + '&:hover': { + backgroundColor: `${mode.color}20`, + transform: 'scale(1.02)', + }, + }} + > + + + + + {child.title} + + + {child.description} + + + + + ) + })} + + + )} - + ) })} - + {/* 최근 학습 */} diff --git a/src/layouts/MainLayout/Sidebar/index.jsx b/src/layouts/MainLayout/Sidebar/index.jsx index 2b70964..99812a3 100644 --- a/src/layouts/MainLayout/Sidebar/index.jsx +++ b/src/layouts/MainLayout/Sidebar/index.jsx @@ -19,7 +19,6 @@ import { ChevronLeft as ChevronLeftIcon, ChevronRight as ChevronRightIcon, Dashboard as DashboardIcon, - RecordVoiceOver as InterviewIcon, Headphones as OpicIcon, Chat as FreetalkIcon, Edit as WritingIcon, @@ -60,13 +59,6 @@ const menuItems = [ }, ], }, - { - id: 'interview', - label: '면접 시뮬레이션', - icon: InterviewIcon, - path: '/interview', - description: 'AI 면접관과 실전 연습' - }, { id: 'freetalk', label: '프리토킹', From 6bdb2b51b0ac8c484c7e073e8ad354c21569924f Mon Sep 17 00:00:00 2001 From: ddingjoo Date: Tue, 6 Jan 2026 14:00:29 +0900 Subject: [PATCH 3/3] =?UTF-8?q?[FEAT]=20=ED=94=84=EB=A6=AC=ED=86=A0?= =?UTF-8?q?=ED=82=B9(=EC=82=AC=EB=9E=8C=EB=93=A4=EA=B3=BC)=20=EC=B1=84?= =?UTF-8?q?=ED=8C=85=EB=B0=A9=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ChatRoomCard 컴포넌트 추가 - FreetalkPeoplePage 페이지 구현 - 레벨 필터링, 검색 기능 추가 - 더미 데이터로 UI 테스트 --- src/App.jsx | 20 +- .../freetalk/components/ChatRoomCard.jsx | 106 +++++++++ .../freetalk/pages/FreetalkPeoplePage.jsx | 206 ++++++++++++++++++ 3 files changed, 313 insertions(+), 19 deletions(-) create mode 100644 src/domains/freetalk/components/ChatRoomCard.jsx create mode 100644 src/domains/freetalk/pages/FreetalkPeoplePage.jsx diff --git a/src/App.jsx b/src/App.jsx index 7171b49..f52de8c 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -11,6 +11,7 @@ import { ChevronRight as ChevronRightIcon, } from '@mui/icons-material' import MainLayout from './layouts/MainLayout' +import FreetalkPeoplePage from './domains/freetalk/pages/FreetalkPeoplePage' // 임시 대시보드 페이지 function Dashboard() { @@ -213,15 +214,6 @@ function Dashboard() { } // 임시 페이지들 -function InterviewPage() { - return ( - - 면접 시뮬레이션 - AI 면접관과 실전 연습 - - ) -} - function OpicPage() { return ( @@ -231,15 +223,6 @@ function OpicPage() { ) } -function FreetalkPeoplePage() { - return ( - - 프리토킹 - 사람들과 - 다른 학습자와 영어로 대화 - - ) -} - function FreetalkAiPage() { return ( @@ -301,7 +284,6 @@ function App() { }> } /> } /> - } /> } /> } /> } /> diff --git a/src/domains/freetalk/components/ChatRoomCard.jsx b/src/domains/freetalk/components/ChatRoomCard.jsx new file mode 100644 index 0000000..321c091 --- /dev/null +++ b/src/domains/freetalk/components/ChatRoomCard.jsx @@ -0,0 +1,106 @@ +import { Card, CardContent, Box, Typography, Chip, Avatar, AvatarGroup } from '@mui/material' +import { AccessTime as TimeIcon, People as PeopleIcon } from '@mui/icons-material' + +const levelColors = { + beginner: { bg: '#e8f5e9', color: '#2e7d32', label: '초급' }, + intermediate: { bg: '#fff3e0', color: '#ef6c00', label: '중급' }, + advanced: { bg: '#fce4ec', color: '#c2185b', label: '고급' }, +} + +const formatTimeAgo = (date) => { + const now = new Date() + const diff = Math.floor((now - new Date(date)) / 1000) + + if (diff < 60) return '방금 전' + if (diff < 3600) return `${Math.floor(diff / 60)}분 전` + if (diff < 86400) return `${Math.floor(diff / 3600)}시간 전` + return `${Math.floor(diff / 86400)}일 전` +} + +const formatDate = (date) => { + const d = new Date(date) + const month = d.getMonth() + 1 + const day = d.getDate() + const hours = d.getHours() + const minutes = d.getMinutes().toString().padStart(2, '0') + return `${month}/${day} ${hours}:${minutes}` +} + +const ChatRoomCard = ({ room, onClick }) => { + const level = levelColors[room.level] || levelColors.beginner + + return ( + onClick?.(room)} + sx={{ + cursor: 'pointer', + transition: 'all 0.2s ease-in-out', + '&:hover': { + transform: 'translateY(-4px)', + boxShadow: 4, + }, + }} + > + + + {/* 레벨 뱃지 */} + + + {/* 채팅방 정보 */} + + + {room.name} + + + + {/* 인원 */} + + + + + {room.currentMembers} + + /{room.maxMembers} + + + + {/* 마지막 대화 */} + + + + {formatTimeAgo(room.lastMessageAt)} + + + + + {/* 참여자 아바타 & 생성일 */} + + + {room.participants?.map((participant, index) => ( + + {participant.name?.[0]} + + ))} + + + + 생성: {formatDate(room.createdAt)} + + + + + + + ) +} + +export default ChatRoomCard diff --git a/src/domains/freetalk/pages/FreetalkPeoplePage.jsx b/src/domains/freetalk/pages/FreetalkPeoplePage.jsx new file mode 100644 index 0000000..b6f7992 --- /dev/null +++ b/src/domains/freetalk/pages/FreetalkPeoplePage.jsx @@ -0,0 +1,206 @@ +import { useState } from 'react' +import { useNavigate } from 'react-router-dom' +import { + Container, + Box, + Typography, + Grid, + TextField, + InputAdornment, + ToggleButtonGroup, + ToggleButton, + Button, + Fab, +} from '@mui/material' +import { + Search as SearchIcon, + Add as AddIcon, + FilterList as FilterIcon, +} from '@mui/icons-material' +import ChatRoomCard from '../components/ChatRoomCard' + +// 더미 데이터 +const mockRooms = [ + { + id: 1, + name: '영어 일상 대화방', + level: 'beginner', + currentMembers: 3, + maxMembers: 6, + lastMessageAt: new Date(Date.now() - 5 * 60 * 1000), // 5분 전 + createdAt: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000), // 2일 전 + participants: [ + { name: '김철수', avatar: '' }, + { name: '이영희', avatar: '' }, + { name: 'John', avatar: '' }, + ], + }, + { + id: 2, + name: '비즈니스 영어 연습', + level: 'intermediate', + currentMembers: 4, + maxMembers: 5, + lastMessageAt: new Date(Date.now() - 30 * 60 * 1000), // 30분 전 + createdAt: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000), // 5일 전 + participants: [ + { name: 'Mike', avatar: '' }, + { name: '박지성', avatar: '' }, + { name: 'Emma', avatar: '' }, + { name: '최민수', avatar: '' }, + ], + }, + { + id: 3, + name: '고급 토론방', + level: 'advanced', + currentMembers: 2, + maxMembers: 4, + lastMessageAt: new Date(Date.now() - 2 * 60 * 60 * 1000), // 2시간 전 + createdAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000), // 1일 전 + participants: [ + { name: 'Sarah', avatar: '' }, + { name: '정유진', avatar: '' }, + ], + }, + { + id: 4, + name: '영어 초보 환영', + level: 'beginner', + currentMembers: 5, + maxMembers: 8, + lastMessageAt: new Date(Date.now() - 10 * 60 * 1000), // 10분 전 + createdAt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000), // 7일 전 + participants: [ + { name: '홍길동', avatar: '' }, + { name: 'Tom', avatar: '' }, + { name: '김미나', avatar: '' }, + { name: 'Lisa', avatar: '' }, + { name: '박준호', avatar: '' }, + ], + }, + { + id: 5, + name: '프리토킹 중급반', + level: 'intermediate', + currentMembers: 3, + maxMembers: 6, + lastMessageAt: new Date(Date.now() - 45 * 60 * 1000), // 45분 전 + createdAt: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000), // 3일 전 + participants: [ + { name: '이수진', avatar: '' }, + { name: 'David', avatar: '' }, + { name: '김태희', avatar: '' }, + ], + }, +] + +const FreetalkPeoplePage = () => { + const navigate = useNavigate() + const [searchQuery, setSearchQuery] = useState('') + const [levelFilter, setLevelFilter] = useState('all') + + const handleLevelChange = (event, newLevel) => { + if (newLevel !== null) { + setLevelFilter(newLevel) + } + } + + const handleRoomClick = (room) => { + // TODO: 채팅방 입장 로직 + console.log('Entering room:', room.id) + navigate(`/freetalk/people/room/${room.id}`) + } + + const filteredRooms = mockRooms.filter((room) => { + const matchesSearch = room.name.toLowerCase().includes(searchQuery.toLowerCase()) + const matchesLevel = levelFilter === 'all' || room.level === levelFilter + return matchesSearch && matchesLevel + }) + + return ( + + {/* 헤더 */} + + + 사람들과 프리토킹 + + + 다른 학습자들과 함께 영어로 자유롭게 대화해보세요 + + + + {/* 필터 영역 */} + + {/* 검색 */} + setSearchQuery(e.target.value)} + sx={{ flex: 1, maxWidth: { sm: 300 } }} + InputProps={{ + startAdornment: ( + + + + ), + }} + /> + + {/* 레벨 필터 */} + + 전체 + 초급 + 중급 + 고급 + + + + {/* 채팅방 목록 */} + + {filteredRooms.map((room) => ( + + + + ))} + + + {/* 빈 상태 */} + {filteredRooms.length === 0 && ( + + + 검색 결과가 없습니다 + + + 다른 키워드로 검색하거나 새 채팅방을 만들어보세요 + + + )} + + {/* 채팅방 만들기 FAB */} + { + // TODO: 채팅방 생성 모달 + console.log('Create new room') + }} + > + + + + ) +} + +export default FreetalkPeoplePage