diff --git a/src/domains/freetalk/components/ChatRoomCard.jsx b/src/domains/freetalk/components/ChatRoomCard.jsx index a513a93..f7e1fc9 100644 --- a/src/domains/freetalk/components/ChatRoomCard.jsx +++ b/src/domains/freetalk/components/ChatRoomCard.jsx @@ -1,5 +1,5 @@ -import { Card, CardContent, Box, Typography, Chip, Avatar, AvatarGroup } from '@mui/material' -import { AccessTime as TimeIcon, People as PeopleIcon } from '@mui/icons-material' +import { Card, CardContent, Box, Typography, Chip, Button } from '@mui/material' +import { AccessTime as TimeIcon, People as PeopleIcon, Lock as LockIcon } from '@mui/icons-material' const levelColors = { beginner: { bg: '#e8f5e9', color: '#2e7d32', label: '초급' }, @@ -19,25 +19,27 @@ const formatTimeAgo = (date) => { 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 year = d.getFullYear().toString().slice(2) + const month = (d.getMonth() + 1).toString().padStart(2, '0') + const day = d.getDate().toString().padStart(2, '0') + return `${year}/${month}/${day}` } const ChatRoomCard = ({ room, onClick }) => { const level = levelColors[room.level] || levelColors.beginner + const handleEnterClick = (e) => { + e.stopPropagation() + onClick?.(room) + } + return ( onClick?.(room)} sx={{ - width: '100%', - height: '100%', + width: 300, + height: 140, display: 'flex', flexDirection: 'column', - cursor: 'pointer', transition: 'all 0.2s ease-in-out', '&:hover': { transform: 'translateY(-4px)', @@ -45,9 +47,9 @@ const ChatRoomCard = ({ room, onClick }) => { }, }} > - - - {/* 레벨 뱃지 */} + + {/* 상단: 레벨 뱃지 + 방 이름 + 입장 버튼 */} + { backgroundColor: level.bg, color: level.color, fontWeight: 600, - minWidth: 48, + fontSize: 11, + height: 24, }} /> - {/* 채팅방 정보 */} - - + + {room.isPrivate && ( + + )} + {room.name} + - - {/* 인원 */} - - - - - {room.currentMembers} - - /{room.maxMembers} - - + + - {/* 마지막 대화 */} - - - - {formatTimeAgo(room.lastMessageAt)} - - - + {/* 중단: 소개 */} + {room.description && ( + + {room.description} + + )} - {/* 참여자 아바타 & 생성일 */} - - - {room.participants?.map((participant, index) => ( - - {participant.name?.[0]} - - ))} - + {/* 하단: 인원, 마지막 대화, 생성일 */} + + + + + + {room.currentMembers} + + /{room.maxMembers} + + - - 생성: {formatDate(room.createdAt)} - - + + + + {formatTimeAgo(room.lastMessageAt)} + + + + · 생성: {formatDate(room.createdAt)} + diff --git a/src/domains/freetalk/pages/FreetalkPeoplePage.jsx b/src/domains/freetalk/pages/FreetalkPeoplePage.jsx index fd90813..53762db 100644 --- a/src/domains/freetalk/pages/FreetalkPeoplePage.jsx +++ b/src/domains/freetalk/pages/FreetalkPeoplePage.jsx @@ -11,87 +11,87 @@ import { ToggleButton, Button, Fab, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + Chip, } from '@mui/material' import { Search as SearchIcon, Add as AddIcon, - FilterList as FilterIcon, + Lock as LockIcon, + People as PeopleIcon, } from '@mui/icons-material' import ChatRoomCard from '../components/ChatRoomCard' +const levelColors = { + beginner: { bg: '#e8f5e9', color: '#2e7d32', label: '초급' }, + intermediate: { bg: '#fff3e0', color: '#ef6c00', label: '중급' }, + advanced: { bg: '#fce4ec', color: '#c2185b', label: '고급' }, +} + // 더미 데이터 const mockRooms = [ { id: 1, name: '영어 일상 대화방', + description: '편하게 일상 영어로 대화해요', 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: '' }, - ], + lastMessageAt: new Date(Date.now() - 5 * 60 * 1000), + createdAt: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000), + isPrivate: false, + isJoined: true, }, { id: 2, name: '비즈니스 영어 연습', + description: '회의, 이메일, 프레젠테이션 영어', 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: '' }, - ], + lastMessageAt: new Date(Date.now() - 30 * 60 * 1000), + createdAt: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000), + isPrivate: true, + isJoined: false, }, { id: 3, name: '고급 토론방', + description: '시사 이슈로 깊이 있는 토론', 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: '' }, - ], + lastMessageAt: new Date(Date.now() - 2 * 60 * 60 * 1000), + createdAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000), + isPrivate: true, + isJoined: true, }, { id: 4, name: '영어 초보 환영', + description: '틀려도 괜찮아요! 함께 성장해요', 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: '' }, - ], + lastMessageAt: new Date(Date.now() - 10 * 60 * 1000), + createdAt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000), + isPrivate: false, + isJoined: false, }, { id: 5, name: '프리토킹 중급반', + description: '자유 주제로 스피킹 연습', 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: '' }, - ], + lastMessageAt: new Date(Date.now() - 45 * 60 * 1000), + createdAt: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000), + isPrivate: false, + isJoined: true, }, ] @@ -99,6 +99,10 @@ const FreetalkPeoplePage = () => { const navigate = useNavigate() const [searchQuery, setSearchQuery] = useState('') const [levelFilter, setLevelFilter] = useState('all') + const [selectedRoom, setSelectedRoom] = useState(null) + const [modalOpen, setModalOpen] = useState(false) + const [password, setPassword] = useState('') + const [passwordError, setPasswordError] = useState('') const handleLevelChange = (event, newLevel) => { if (newLevel !== null) { @@ -107,14 +111,44 @@ const FreetalkPeoplePage = () => { } const handleRoomClick = (room) => { - // TODO: 채팅방 입장 로직 - console.log('Entering room:', room.id) - navigate(`/freetalk/people/room/${room.id}`) + setSelectedRoom(room) + setPassword('') + setPasswordError('') + setModalOpen(true) + } + + const handleCloseModal = () => { + setModalOpen(false) + setSelectedRoom(null) + setPassword('') + setPasswordError('') + } + + const handleEnterRoom = () => { + if (selectedRoom?.isPrivate) { + // 비밀번호 검증 (더미: 1234) + if (password === '1234') { + navigate(`/freetalk/people/room/${selectedRoom.id}`) + handleCloseModal() + } else { + setPasswordError('비밀번호가 일치하지 않습니다') + } + } else { + navigate(`/freetalk/people/room/${selectedRoom.id}`) + handleCloseModal() + } } const filteredRooms = mockRooms.filter((room) => { const matchesSearch = room.name.toLowerCase().includes(searchQuery.toLowerCase()) - const matchesLevel = levelFilter === 'all' || room.level === levelFilter + let matchesLevel = false + if (levelFilter === 'all') { + matchesLevel = true + } else if (levelFilter === 'joined') { + matchesLevel = room.isJoined + } else { + matchesLevel = room.level === levelFilter + } return matchesSearch && matchesLevel }) @@ -159,6 +193,7 @@ const FreetalkPeoplePage = () => { 초급 중급 고급 + 참여중 @@ -199,6 +234,82 @@ const FreetalkPeoplePage = () => { > + + {/* 입장 모달 */} + + {selectedRoom && ( + <> + + + {selectedRoom.isPrivate && ( + + )} + + {selectedRoom.name} + + + + + {/* 방 정보 */} + + + + + + + {selectedRoom.currentMembers}/{selectedRoom.maxMembers}명 + + + + {selectedRoom.description && ( + + {selectedRoom.description} + + )} + + + {/* 비밀번호 입력 (비밀방인 경우) */} + {selectedRoom.isPrivate && ( + { + setPassword(e.target.value) + setPasswordError('') + }} + error={!!passwordError} + helperText={passwordError} + size="small" + autoFocus + /> + )} + + + + + + + )} + ) }