From ecc4bdf149c44bee71e3f086d9e0dd4df34b0006 Mon Sep 17 00:00:00 2001 From: kim gisu Date: Mon, 9 Sep 2024 16:38:49 +0900 Subject: [PATCH 01/57] second commit --- package-lock.json | 10 + package.json | 1 + src/App.jsx | 27 +- src/page/Main/ChatPage/ChatPage.css | 425 ++++++++++++++++++ src/page/Main/ChatPage/ChatRoom/ChatRoom.css | 237 ++++++++++ src/page/Main/ChatPage/ChatRoom/ChatRoom.jsx | 91 ++++ .../ChatRoomInformation.jsx | 32 ++ src/page/Main/ChatPage/ChatStartPage.jsx | 175 ++++++++ .../Main/ChatPage/Dialog/MaxChanceDialog.jsx | 32 ++ .../Main/ChatPage/Dialog/MaxMemberDialog.jsx | 31 ++ src/page/Main/ChatPage/Dialog/OkayDialog.jsx | 70 +++ src/page/Main/ChatPage/Dialog/dialog.css | 296 ++++++++++++ src/page/Main/ChatPage/EnterCheckPage.jsx | 156 +++++++ src/page/Main/ChatPage/NoEnterCheckPage.jsx | 197 ++++++++ src/page/Main/Main.jsx | 8 +- 15 files changed, 1775 insertions(+), 13 deletions(-) create mode 100644 src/page/Main/ChatPage/ChatPage.css create mode 100644 src/page/Main/ChatPage/ChatRoom/ChatRoom.css create mode 100644 src/page/Main/ChatPage/ChatRoom/ChatRoom.jsx create mode 100644 src/page/Main/ChatPage/ChatRoom/ChatRoomInformation/ChatRoomInformation.jsx create mode 100644 src/page/Main/ChatPage/ChatStartPage.jsx create mode 100644 src/page/Main/ChatPage/Dialog/MaxChanceDialog.jsx create mode 100644 src/page/Main/ChatPage/Dialog/MaxMemberDialog.jsx create mode 100644 src/page/Main/ChatPage/Dialog/OkayDialog.jsx create mode 100644 src/page/Main/ChatPage/Dialog/dialog.css create mode 100644 src/page/Main/ChatPage/EnterCheckPage.jsx create mode 100644 src/page/Main/ChatPage/NoEnterCheckPage.jsx diff --git a/package-lock.json b/package-lock.json index ee66c43..17a48c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "jwt-decode": "^4.0.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.26.0", @@ -12253,6 +12254,15 @@ "node": ">=4.0" } }, + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", diff --git a/package.json b/package.json index 80da5dd..7e3b85b 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "jwt-decode": "^4.0.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.26.0", diff --git a/src/App.jsx b/src/App.jsx index a0a8dcd..691e448 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,18 +1,25 @@ -import { BrowserRouter as Router, Routes, Route, Navigate } from "react-router-dom"; +import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; import "./App.css"; import Main from "./page/Main/Main"; +import ChatStartPage from "./page/Main/ChatPage/ChatStartPage" +import ChatRoom from "./page/Main/ChatPage/ChatRoom/ChatRoom" +import ChatRoomInformation from "./page/Main/ChatPage/ChatRoom/ChatRoomInformation/ChatRoomInformation" + function App() { - + return ( - - - - - } /> - - - + + + + } /> + } /> + {/* } /> */} + } /> + {/* } /> */} + } /> + + ); } diff --git a/src/page/Main/ChatPage/ChatPage.css b/src/page/Main/ChatPage/ChatPage.css new file mode 100644 index 0000000..4e00fac --- /dev/null +++ b/src/page/Main/ChatPage/ChatPage.css @@ -0,0 +1,425 @@ +@import url("https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.8/dist/web/static/pretendard.css"); + +@keyframes spin { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} + + + +.chatStartPage { + + height: 812px; + width: 375px; + margin: 0 auto; + + .logo { + width: 100px; + height: 36px; + margin-top: 50px; + background: #D9D9D9; + } + + .title-name { + display: flex; + flex-direction: row; + } + + .one-click { + border-bottom: 2px solid #FF7898; + } + + .two-click { + border-bottom: none; + } + + + .enter { + /* 참여중인 채팅방 */ + margin-top: 10px; + width: 50%; + height: 20px; + text-align: center; + font-family: 'Pretendard'; + font-style: normal; + font-weight: 600; + font-size: 16px; + line-height: 18px; + /* identical to box height, or 112% */ + color: #000000; + } + + .no-enter { + /* 참여중인 채팅방 */ + text-align: center; + margin-top: 10px; + + width: 50%; + font-family: 'Pretendard'; + font-style: normal; + font-weight: 600; + font-size: 16px; + line-height: 18px; + /* identical to box height, or 112% */ + color: #000000; + } + + .title { + height: 50px; + display: flex; + flex-direction: column; + justify-content: space-between; + + } + + .title-span { + /* 최대 0개방까지 참여 가능합니다 */ + + + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 500; + font-size: 10px; + line-height: 12px; + + + color: #696969; + } + + .chatRoomLists { + overflow: auto; + margin: 20px 0 0 0; + display: flex; + height: 575px; + justify-content: center; + } + + .chatRoomList { + /* Rectangle 3470027 */ + margin-bottom: 20px; + box-sizing: border-box; + width: 343px; + background: #FFFFFF; + } + + .chatRoomList-up { + border-width: 1px 1px 0px 1px; + border-style: solid; + border-color: #EAEAEA; + border-radius: 12px 12px 0px 0px; + height: 70px; + padding-bottom: 10px; + cursor: pointer; + } + + .room-title { + /* 채팅방 메인 타이틀 */ + + position: relative; + width: 104px; + height: 16px; + top: -40px; + left: 60px; + font-family: 'Pretendard'; + font-style: normal; + font-weight: 600; + font-size: 14px; + line-height: 16px; + /* identical to box height, or 114% */ + display: flex; + align-items: center; + + color: #000000; + } + + .bigCircle { + /* Ellipse 1447 */ + + position: relative; + width: 40px; + height: 40px; + left: 10px; + top: 5px; + border-radius: 50%; + background: #BDBDBD; + + } + + .bigCircle-pink { + background-color: #FF7898; + } + + .pink-text { + color: #FF7898; + } + + .bigCircle-name { + /* 참여 가능 */ + color: #FFFFFF; + position: relative; + width: 25px; + height: 28px; + left: 8px; + top: 7px; + text-align: center; + font-family: 'Pretendard'; + font-style: normal; + font-weight: 500; + font-size: 14px; + line-height: 14px; + /* or 100% */ + display: flex; + align-items: center; + } + + .gender-number { + + position: relative; + width: 50px; + height: 12px; + left: 180px; + top: -70px; + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 400; + font-size: 10px; + line-height: 12px; + /* identical to box height, or 120% */ + display: flex; + align-items: center; + + color: #777777; + } + + + + .room-subTitle { + /* 채팅방 한 줄 소개, 서브 타이틀 */ + margin-top: 0; + position: relative; + width: 250px; + height: 14px; + left: 60px; + top: -60px; + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 500; + font-size: 12px; + line-height: 14px; + /* identical to box height, or 117% */ + display: flex; + align-items: center; + + color: #5E5E5E; + } + + .members { + cursor: pointer; + /* Rectangle 3470028 */ + display: flex; + justify-content: center; + box-sizing: border-box; + flex-direction: column; + + + min-height: 34px; + + background: #F5F5F5; + + + border-width: 1px 1px 0px 1px; + border-style: solid; + border-color: #EAEAEA; + border-radius: 0px 0px 12px 12px; + } + + .members-see { + justify-content: center; + font-family: 'Pretendard'; + font-style: normal; + font-weight: 500; + font-size: 12px; + line-height: 14px; + /* identical to box height, or 117% */ + display: flex; + align-items: center; + + color: #000000; + } + + .expanded { + padding-top: 10px; + } + + .members-list { + max-height: 0; + /* 기본적으로 숨김 상태 */ + overflow: hidden; + } + + .members-list.expanded { + max-height: 500px; + /* 충분히 큰 값으로 설정, 필요에 따라 조정 가능 */ + padding: 10px 0; + /* 확장되면서 패딩 추가 */ + } + + .members-list.collapsed { + max-height: 0; + padding: 0; + } + + .members-container { + display: flex; + align-items: flex-start; + max-height: 120px; + overflow: auto; + } + + .members-section { + flex: 1; + padding: 0 10px; + word-wrap: break-word; + word-break: break-all; + overflow-wrap: break-word + } + + + .major { + + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 400; + font-size: 12px; + line-height: 14px; + /* identical to box height, or 117% */ + display: flex; + align-items: center; + + color: #777777; + } + + .nickName { + + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 500; + font-size: 12px; + line-height: 14px; + /* identical to box height, or 117% */ + display: flex; + align-items: center; + + color: #3D3D3D; + } + + + .members-section ul { + list-style: none; + padding: 0; + margin: 0; + } + + .members-section li { + margin-bottom: 5px; + } + + .gender-text { + margin-bottom: 5px; + font-family: 'Pretendard'; + font-style: normal; + font-weight: 500; + font-size: 10px; + line-height: 12px; + /* identical to box height, or 120% */ + display: flex; + align-items: center; + + color: #777777; + } + + .smallCircle { + width: 5px; + height: 5px; + position: relative; + top: 5px; + left: 320px; + } + + .gender-contatiner { + /* 남녀현황 */ + position: relative; + width: 40px; + height: 27px; + left: 290px; + top: -75px; + } + + .gender-number-information { + /* 남 */ + font-family: 'Pretendard'; + font-style: normal; + font-weight: 400; + font-size: 12px; + line-height: 14px; + /* identical to box height, or 117% */ + display: flex; + align-items: center; + + color: #3D3D3D; + } + + .make-chatRoom-button { + + position: relative; + width: 343px; + height: 50px; + top: -10px; + left: calc(50% - 343px / 2); + background: #FF7898; + border-radius: 5px; + border: none; + + } + + .make-chatRoom-button span { + justify-content: center; + /* 채팅방 만들기 */ + font-family: 'Pretendard'; + font-style: normal; + font-weight: 700; + font-size: 18px; + line-height: 20px; + /* identical to box height, or 111% */ + display: flex; + align-items: center; + text-align: center; + + color: #FFFFFF; + } + + .refresh-indicator { + position: relative; + justify-content: center; + width: 100%; + text-align: center; + margin-bottom: 20px; + } + + + + + .refresh-icon { + animation: spin 1s linear infinite; + } +} \ No newline at end of file diff --git a/src/page/Main/ChatPage/ChatRoom/ChatRoom.css b/src/page/Main/ChatPage/ChatRoom/ChatRoom.css new file mode 100644 index 0000000..a5f91e0 --- /dev/null +++ b/src/page/Main/ChatPage/ChatRoom/ChatRoom.css @@ -0,0 +1,237 @@ +.chatRoom { + + height: 812px; + width: 375px; + margin: 0 auto; + + .margin-container { + display: flex; + flex-direction: column; + height: 100%; + margin: 0 16px; + } + + .title { + width: 100%; + height: 46px; + margin-top: 50px; + background: #ffffff; + display: flex; + text-align: center; + justify-content: space-between; + } + + .title-name { + /* 채팅방 이름 */ + + padding-top: 15px; + width: 90px; + height: 18px; + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 600; + font-size: 16px; + line-height: 18px; + /* identical to box height, or 112% */ + display: flex; + align-items: center; + + color: #3D3D3D; + } + + + .bar { + width: 343px; + height: 6px; + + + + background-color: #F5F6F7; + + } + + + .dialog-icon-container { + margin-top: 15px; + display: flex; + justify-content: center; + text-align: center; + } + + /*원이 3개이상*/ + .profile-icon-0 { + width: 20px; + height: 20px; + background-size: cover; + background-position: center; + border-radius: 50%; + position: relative; + background-color: #A0A0A0; + left: 37px; + top: 0; + z-index: 0; + } + + .profile-icon-1 { + width: 20px; + height: 20px; + background-size: cover; + background-position: center; + border-radius: 50%; + position: relative; + background-color: #BBBBBB; + left: 27px; + top: 0; + z-index: 1; + } + + .profile-icon-2 { + width: 20px; + height: 20px; + background-size: cover; + background-position: center; + border-radius: 50%; + position: relative; + background-color: #F5F5F5; + left: 17px; + top: 0; + z-index: 2; + } + + /*원이 2개*/ + .profile-icon-0.member-length-2 { + width: 20px; + height: 20px; + background-size: cover; + background-position: center; + border-radius: 50%; + position: relative; + background-color: #A0A0A0; + left: 10px; + top: 0; + z-index: 0; + } + + .profile-icon-1.member-length-2 { + width: 20px; + height: 20px; + background-size: cover; + background-position: center; + border-radius: 50%; + position: relative; + background-color: #BBBBBB; + left: 0px; + top: 0; + z-index: 1; + } + + /*원이 1개*/ + .profile-icon-0.member-length-1 { + width: 20px; + height: 20px; + background-size: cover; + background-position: center; + border-radius: 50%; + position: relative; + background-color: #A0A0A0; + left: 0px; + top: 0; + z-index: 0; + } + + + .extra-profile-count { + + /* +2 */ + + position: relative; + width: 17px; + height: 16px; + left: 2px; + top: 2px; + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 500; + font-size: 10px; + line-height: 16px; + /* identical to box height, or 114% */ + display: flex; + align-items: center; + text-align: center; + + color: #606060; + z-index: 3; + + } + + + + .text-bar { + position: relative; + width: 343px; + height: 40px; + top: 500px; + + display: flex; + flex-direction: row; + justify-content: space-between; + } + + .text-container { + /* Rectangle 3470037 */ + width: 299px; + height: 40px; + background: #F5F5F5; + border-radius: 42px; + display: flex; + text-align: center; + align-items: center; + } + + .send-container { + width: 40px; + height: 40px; + justify-content: center; + display: flex; + align-items: center; + border-radius: 50%; + background: #F5F5F5; + } + + .text { + /* Text... */ + border: none; + + /* 기본 배경 제거 */ + background: none; + + /* 기본 그림자 제거 */ + box-shadow: none; + + /* 기본 외곽선(focus 시 생기는 테두리) 제거 */ + outline: none; + + /* 기본 여백 제거 */ + padding: 0; + margin: 0; + /* 텍스트 선택 시 색상 초기화 (선택 사항) */ + user-select: text; + + /* 모양을 네이티브 스타일로 초기화 (iOS, Android 등) */ + appearance: none; + + margin-left: 20px; + height: 20px; + font-family: 'Pretendard'; + font-style: normal; + font-weight: 400; + font-size: 14px; + line-height: 20px; + border-radius: 42px; + color: #000000; + z-index: 1000; + } + +} \ No newline at end of file diff --git a/src/page/Main/ChatPage/ChatRoom/ChatRoom.jsx b/src/page/Main/ChatPage/ChatRoom/ChatRoom.jsx new file mode 100644 index 0000000..6106529 --- /dev/null +++ b/src/page/Main/ChatPage/ChatRoom/ChatRoom.jsx @@ -0,0 +1,91 @@ +import React, { useState } from "react"; +import '../ChatRoom/ChatRoom.css' +import { useNavigate } from 'react-router-dom'; + +function ChatRoom() { + const navigate = useNavigate(); + + + const [selectChatRoom, setSelectChatRoom] = useState({ + id: 1, + //제목 길이 20자 제한 + title: "채팅방 메인 타이틀아아아아f", + //서브제목 길이 30자 제한 + subTitle: "sdafasdfadsfjlsadflㅁㄴ어ㅣㄹㄴㅁ이ㅓ리너아리ㅁㄴㅇㄻㄴㅇㄹ", + + //방아이디로 조회한다. + members: [ + { gender: "Male", major: "Computer Science", studentId: "20210001", nickname: "John", profileImage: "sd" }, + { gender: "Female", major: "Design", studentId: "20210002", nickname: "Jane", profileImage: "sd" } + , { gender: "Female", major: "Design", studentId: "20210002", nickname: "Jane", profileImage: "sd" } + , { gender: "Female", major: "Design", studentId: "20210002", nickname: "Jane", profileImage: "sd" } + + ], + maxMembers: 6, + //입장체크 + enterCheck: false, + }) + + + const maxVisibleProfiles = 3; + const memberLength = selectChatRoom.members.length; + const members = selectChatRoom.members.slice(0, maxVisibleProfiles); + const extraProfilesCount = memberLength - maxVisibleProfiles; + + const memberLengthClassName = `member-length-${memberLength}`; + + + + const goChatRoomInformation = () => { + navigate('/ChatRoomInformation/0') + } + + + return ( +
+
+
+
goChatRoomInformation()}> + 채팅방이름 + + + +
+
+ {members.map((member, index) => ( +
//멤버의 프로필 사진 스타일 설정 + ))} + {extraProfilesCount > 0 && ( +
+ +{extraProfilesCount} +
+ )} + +
+
+
+
+ +
+ + + + + +
+
+ +
+
+ + + +
+ +
+
+
+ ); +} + +export default ChatRoom; \ No newline at end of file diff --git a/src/page/Main/ChatPage/ChatRoom/ChatRoomInformation/ChatRoomInformation.jsx b/src/page/Main/ChatPage/ChatRoom/ChatRoomInformation/ChatRoomInformation.jsx new file mode 100644 index 0000000..3115a92 --- /dev/null +++ b/src/page/Main/ChatPage/ChatRoom/ChatRoomInformation/ChatRoomInformation.jsx @@ -0,0 +1,32 @@ +import React, { useState } from "react"; +import { useNavigate } from 'react-router-dom'; + + +const ChatRoomInformation = () => { + return ( +
+
+ + + + + + +
+ 네비바 +
+ +
+
+ +
+
+ +
+
+
+
+ ); +} + +export default ChatRoomInformation; \ No newline at end of file diff --git a/src/page/Main/ChatPage/ChatStartPage.jsx b/src/page/Main/ChatPage/ChatStartPage.jsx new file mode 100644 index 0000000..90ac44f --- /dev/null +++ b/src/page/Main/ChatPage/ChatStartPage.jsx @@ -0,0 +1,175 @@ +import React, { useState, useEffect } from "react"; +import './ChatPage.css' +import EnterCheckPage from './EnterCheckPage' +import NoEnterCheckPage from './NoEnterCheckPage' +import { jwtDecode } from 'jwt-decode'; + +function ChatStartPage() { + + const [loading, setLoading] = useState(true); + + const [isEnterCheck, setIsEnterClick] = useState(false); + //유저의 정보를 가져와 성별,입장참여 횟수를 가져온다 + const [possibleEnterNumber, setPossibleEnterNumber] = useState(3); + const [gender, setGender] = useState("male"); + + + useEffect(() => { + const fetchUserData = async () => { + try { + const token = localStorage.getItem('token'); + + if (!token) { + throw new Error('No token found'); + } + + // JWT 디코딩 + const decodedToken = jwtDecode(token); + const email = decodedToken.email; // 토큰에서 이메일 추출 + + const response = await fetch(`/api/user/${email}`, { + method: 'GET', + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json' + } + }); + + if (!response.ok) { + throw new Error('Network response was not ok'); + } + + const data = await response.json(); + setGender(data.gender); + setPossibleEnterNumber(data.ticket) + } catch (error) { + console.log(error); + } finally { + setLoading(false); + } + }; + + fetchUserData(); + + // 소켓 관련 코드 (예시) + // const socket = io('http://localhost:3000'); + // socket.on('userUpdate', (updatedUser) => { + // setUser(updatedUser); + // }); + + // return () => { + // socket.disconnect(); + // }; + }, []); + + + + // 채팅방 정보를 저장하는 state(예시 백에서 받아와야함) + //나중에 역순으로 할거? + const [chatRooms, setChatRooms] = useState([ + { + id: 1, + //제목 길이 20자 제한 + title: "채팅방 메인 타이틀아아아아f", + //서브제목 길이 30자 제한 + subTitle: "sdafasdfadsfjlsadflㅁㄴ어ㅣㄹㄴㅁ이ㅓ리너아리ㅁㄴㅇㄻㄴㅇㄹ", + + //방아이디로 조회한다. + members: [ + { gender: "Male", major: "Computer Science", studentId: "20210001", nickname: "John", profileImage: "sd" }, + { gender: "Female", major: "Design", studentId: "20210002", nickname: "Jane", profileImage: "sd" } + ], + maxMembers: 2, + //입장체크 + enterCheck: false, + }, + { + id: 2, + title: "프로그래밍 기초", + subTitle: "프로그래밍의 기초를 배워봅시다", + members: [ + { gender: "Female", major: "Physics", studentId: "20210003", nickname: "Alice", profileImage: "sd" }, + { gender: "Female", major: "Mathematicasdfasdfdassdfsssadfsdf", studentId: "20210004", nickname: "Bob", profileImage: "sd" } + ], + maxMembers: 4, + enterCheck: true, + }, + { + id: 3, + title: "프로그래밍 기초", + subTitle: "프로그래밍의 기초를 배워봅시다", + members: [ + { gender: "Female", major: "Physics", studentId: "20210003", nickname: "Alice", profileImage: "sd" }, + { gender: "Male", major: "Mathematics", studentId: "20210004", nickname: "Bob", profileImage: "sd" }, + { gender: "Male", major: "asd", studentId: "20210004", nickname: "Bob", profileImage: "sd" }, + + ], + maxMembers: 6, + enterCheck: false, + }, + { + id: 4, + title: "프로그래밍 기초", + subTitle: "프로그래밍의 기초를 배워봅시다", + members: [ + { gender: "Female", major: "Physics", studentId: "20210003", nickname: "Alice", profileImage: "sd" }, + { gender: "Male", major: "Mathematics", studentId: "20210004", nickname: "Bob", profileImage: "sd" }, + { gender: "Female", major: "Mathematics", studentId: "20210004", nickname: "Bob", profileImage: "sd" }, + { gender: "Male", major: "Mathematics", studentId: "20210004", nickname: "Bob", profileImage: "sd" }, + { gender: "Female", major: "asd", studentId: "20210004", nickname: "한준서", profileImage: "sd" } + ], + maxMembers: 6, + enterCheck: false, + } + ]); + + + + + const makeChatRoom = () => { + //챗룸 만들기로 이동 + } + + + + if (loading) return ( +
+ ); + + return ( +
+ logo + +
+
+ setIsEnterClick(true)} >참여중 + setIsEnterClick(false)}>모집중 +
+ {isEnterCheck ? 최대 {possibleEnterNumber}개 방까지 참여 가능합니다 : } + +
+ +
+ {isEnterCheck ? : } +
+ + +
+ 네비바 +
+ +
+
+ +
+
+ +
+
+
+ ); +} + +export default ChatStartPage; \ No newline at end of file diff --git a/src/page/Main/ChatPage/Dialog/MaxChanceDialog.jsx b/src/page/Main/ChatPage/Dialog/MaxChanceDialog.jsx new file mode 100644 index 0000000..672d790 --- /dev/null +++ b/src/page/Main/ChatPage/Dialog/MaxChanceDialog.jsx @@ -0,0 +1,32 @@ +import React, { useState } from "react"; +import './dialog.css' + +function MaxChanceDialog({ isOpen, onClose }) { + if (!isOpen) return null; + + return ( +
+
+
+
+ + + + + + +
+

최대 참여 가능한 채팅방 수가 초과되었습니다

+

+ 현재 나의 채팅방 입장 참여 횟수 0개 +

+ +
+
+
+ ); +} + +export default MaxChanceDialog; \ No newline at end of file diff --git a/src/page/Main/ChatPage/Dialog/MaxMemberDialog.jsx b/src/page/Main/ChatPage/Dialog/MaxMemberDialog.jsx new file mode 100644 index 0000000..92c0323 --- /dev/null +++ b/src/page/Main/ChatPage/Dialog/MaxMemberDialog.jsx @@ -0,0 +1,31 @@ +import React, { useState } from "react"; + +function MaxMemberDialog({ isOpen, onClose }) { + if (!isOpen) return null; + + return ( +
+
+
+
+ + + + + + +
+

채팅방 인원이 마감되었습니다

+

+ +

+ +
+
+
+ ); +} + +export default MaxMemberDialog; \ No newline at end of file diff --git a/src/page/Main/ChatPage/Dialog/OkayDialog.jsx b/src/page/Main/ChatPage/Dialog/OkayDialog.jsx new file mode 100644 index 0000000..8778243 --- /dev/null +++ b/src/page/Main/ChatPage/Dialog/OkayDialog.jsx @@ -0,0 +1,70 @@ +import React, { useState } from "react"; +import { useNavigate } from 'react-router-dom'; +import './dialog.css' + +function OkayDialog({ isOpen, onClose, selectChatRoom, possibleEnterNumber }) { + const navigate = useNavigate(); + + if (!isOpen) return null; + + + const maxVisibleProfiles = 3; + const memberLength = selectChatRoom.members.length; + const members = selectChatRoom.members.slice(0, maxVisibleProfiles); + const extraProfilesCount = memberLength - maxVisibleProfiles; + + const memberLengthClassName = `member-length-${memberLength}`; + + + + const goChatRoom = () => { + navigate(`/chat/0`); // 원하는 경로로 이동 + //소켓으로 업그레이드 하고 방으로 이동 + onClose(); + } + + return ( +
+
+
+

채팅방 메인 타이틀에 입장하시겠습니까?

+
+ {members.map((member, index) => ( +
//멤버의 프로필 사진 스타일 설정 + ))} + {extraProfilesCount > 0 && ( +
+ +{extraProfilesCount} +
+ )} + +
+
+

+ 원활한 서비스 이용을 위해 + 동시에 최대 3개의 채팅방을 이용할 수 있습니다 +

+

+ 현재 나의 채팅방 입장 참여 횟수 {possibleEnterNumber}개 +

+
+ + + +
+ + + +
+ +
+
+
+ ); +} + +export default OkayDialog; \ No newline at end of file diff --git a/src/page/Main/ChatPage/Dialog/dialog.css b/src/page/Main/ChatPage/Dialog/dialog.css new file mode 100644 index 0000000..7f37b31 --- /dev/null +++ b/src/page/Main/ChatPage/Dialog/dialog.css @@ -0,0 +1,296 @@ +.dialog { + + position: absolute; + height: 812px; + width: 375px; + top: 0px; + background: rgba(0, 0, 0, 0.1); + z-index: 1000; + + .dialog-backdrop { + + + display: flex; + justify-content: center; + align-items: center; + + + z-index: 1000; + /* 앞으로 오게 하기 위해 z-index 값 추가 */ + + /* Group 816134 */ + + position: absolute; + width: 343px; + height: 330px; + left: calc(50% - 343px/2); + top: 199px; + } + + .dialog-container { + background-color: white; + border-radius: 20px; + width: 343px; + height: 330px; + text-align: center; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + display: flex; + flex-direction: column; + + + } + + .dialog-icon { + margin-top: 32px; + margin-bottom: 32px; + } + + .dialog-title { + /* 최대 참여 가능 채팅방 수가 초과되었습니다 */ + font-family: 'Pretendard'; + font-style: normal; + font-weight: 600; + font-size: 16px; + line-height: 18px; + margin-bottom: 0; + /* identical to box height, or 112% */ + + + color: #3D3D3D; + } + + .dialog-message { + margin-top: 3px; + font-family: 'Pretendard'; + font-style: normal; + font-weight: 500; + font-size: 12px; + line-height: 14px; + /* identical to box height, or 117% */ + + + color: #3D3D3D; + } + + .highlight-text { + color: #FF7898; + font-weight: bold; + } + + + + .dialog-button { + background-color: #F5F5F5; + font-family: 'Pretendard'; + font-style: normal; + font-weight: 600; + font-size: 18px; + line-height: 20px; + color: #3D3D3D; + border: none; + border-radius: 14px; + padding: 10px 20px; + font-size: 16px; + cursor: pointer; + margin: 10px 31px 0 31px; + } + + .dialog-button:hover { + background-color: #FF7898; + } + + + .dialog-okay-title { + /* 에 입장하시겠습니까? */ + font-family: 'Pretendard'; + font-style: normal; + font-weight: 500; + font-size: 16px; + line-height: 18px; + /* identical to box height, or 112% */ + margin-top: 30px; + align-items: center; + color: #3D3D3D; + } + + .button-container { + display: flex; + flex-direction: row; + justify-content: space-evenly; + } + + .dialog-button-cancle { + /* Rectangle 3470049 */ + width: 136px; + height: 44px; + border: none; + background: #F5F5F5; + border-radius: 14px; + font-family: 'Pretendard'; + font-style: normal; + font-weight: 600; + font-size: 18px; + line-height: 20px; + color: #3D3D3D; + } + + .dialog-button-pink { + /* Rectangle 3470049 */ + font-family: 'Pretendard'; + font-style: normal; + font-weight: 600; + font-size: 18px; + line-height: 20px; + color: #FFFFFF; + width: 136px; + height: 44px; + border: none; + background: #FF7898; + border-radius: 14px; + } + + + .dialog-icon-container { + margin-top: 15px; + display: flex; + justify-content: center; + text-align: center; + } + + /*원이 3개이상*/ + .profile-icon-0 { + width: 96px; + height: 96px; + background-size: cover; + background-position: center; + border-radius: 50%; + position: relative; + background-color: #A0A0A0; + left: 60px; + top: 0; + z-index: 0; + } + + .profile-icon-1 { + width: 96px; + height: 96px; + background-size: cover; + background-position: center; + border-radius: 50%; + position: relative; + background-color: #BBBBBB; + left: 0; + top: 0; + z-index: 1; + } + + .profile-icon-2 { + width: 96px; + height: 96px; + background-size: cover; + background-position: center; + border-radius: 50%; + position: relative; + background-color: #F5F5F5; + left: -60px; + top: 0; + z-index: 2; + } + + /*원이 2개*/ + .profile-icon-0.member-length-2 { + width: 96px; + height: 96px; + background-size: cover; + background-position: center; + border-radius: 50%; + position: relative; + background-color: #A0A0A0; + left: 30px; + top: 0; + z-index: 0; + } + + .profile-icon-1.member-length-2 { + width: 96px; + height: 96px; + background-size: cover; + background-position: center; + border-radius: 50%; + position: relative; + background-color: #BBBBBB; + left: -30px; + top: 0; + z-index: 1; + } + + /*원이 1개*/ + .profile-icon-0.member-length-1 { + width: 96px; + height: 96px; + background-size: cover; + background-position: center; + border-radius: 50%; + position: relative; + background-color: #A0A0A0; + left: 0px; + top: 0; + z-index: 0; + } + + + .extra-profile-count { + + /* +2 */ + + position: absolute; + width: 17px; + height: 16px; + left: 200px; + top: 118px; + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 500; + font-size: 14px; + line-height: 16px; + /* identical to box height, or 114% */ + display: flex; + align-items: center; + text-align: center; + + color: #606060; + z-index: 3; + + } + + .okayDialog-container { + display: flex; + flex-direction: column; + margin-left: 47px; + } + + .dialog-message-2 { + /* 원활한 서비스 이용을 위해 동시에 최대 3개의 채팅방을 이용할 수 있습니다 */ + margin-top: 15px; + font-family: 'Pretendard'; + font-style: normal; + font-weight: 500; + font-size: 12px; + line-height: 18px; + /* or 150% */ + margin-bottom: 0px; + color: #777777; + + display: flex; + justify-content: start; + flex-direction: column; + text-align: left; + } + + .dialog-message.okay { + margin-top: 0px; + margin-bottom: 16px; + text-align: left; + } +} \ No newline at end of file diff --git a/src/page/Main/ChatPage/EnterCheckPage.jsx b/src/page/Main/ChatPage/EnterCheckPage.jsx new file mode 100644 index 0000000..10e7430 --- /dev/null +++ b/src/page/Main/ChatPage/EnterCheckPage.jsx @@ -0,0 +1,156 @@ +import React, { useState } from "react"; +import { useNavigate } from 'react-router-dom'; +import './ChatPage.css' + + +function EnterCheckPage(props) { + const { chatRooms } = props; + const [expandedRoomIds, setExpandedRoomIds] = useState([]); + const navigate = useNavigate(); + + + + //알림용뱃지(브로드캐스트를 받아와야함) + const [missedMessage, setMissedMessage] = useState(false); + + + + //새로고침 + const [startY, setStartY] = useState(0); + const [translateY, setTranslateY] = useState(0); + const [isRefreshing, setIsRefreshing] = useState(false); + + const threshold = 80; // 새로고침을 트리거하는 기준 거리 + + // 새로고침 함수 + const handleRefresh = () => { + setIsRefreshing(true); + setTimeout(() => { + setIsRefreshing(false); + window.location.reload(); // 페이지 새로고침 (필요에 따라 이 부분을 변경) + }, 1500); + }; + + // 터치 시작 + const handleTouchStart = (event) => { + setStartY(event.touches[0].clientY); + }; + + // 터치 중일 때 + const handleTouchMove = (event) => { + const currentY = event.touches[0].clientY; + const distance = currentY - startY; + + + // 스크롤이 최상단일 때만 동작 + if (window.scrollY === 0 && distance > 0) { + setTranslateY(distance * 0.3); // 끌린 만큼 translateY 값을 설정 + } + + // 기준 거리를 넘었을 때 새로고침 + if (distance > threshold) { + handleRefresh(); + } + }; + + // 터치 끝 + const handleTouchEnd = () => { + setTranslateY(0); // 터치가 끝나면 원래 위치로 돌아가기 + }; + + + + //토글확장 관리 + const toggleExpand = (roomId) => { + setExpandedRoomIds(prevState => + prevState.includes(roomId) + ? prevState.filter(id => id !== roomId) + : [...prevState, roomId] + ); + }; + + + const goChatRoom = () => { + navigate(`/chat/0`); // 원하는 경로로 이동 + } + + + + return ( +
+ {isRefreshing &&
} + {chatRooms + .filter(room => room.enterCheck === true) // isEnterCheck 상태에 따라 필터링 + .map(room => { + const maleCount = room.members.filter(member => member.gender === "Male").length; + const femaleCount = room.members.filter(member => member.gender === "Female").length; + + const isExpanded = expandedRoomIds.includes(room.id); // 현재 방이 확장되었는지 확인 + return ( +
+
goChatRoom()}> + {room.enterCheck ?
+ + +
: null} + + +
참여 중
+

{room.title}

+ 남: {maleCount} 여: {femaleCount} +

{room.subTitle}

+
+
toggleExpand(room.id)}> + + 참여인원 보기 + {!isExpanded ? + + : + + + } + + + {/* 확장된 상태일 때만 멤버 리스트를 렌더링 */} +
+
+
+

남자

+
    + {room.members.filter(member => member.gender === "Male").map((member, index) => ( +
  • + {member.major}{member.studentId[0] + member.studentId[1]} {member.nickname} +
  • + ))} +
+
+
+

여자

+
    + {room.members.filter(member => member.gender === "Female").map((member, index) => ( +
  • + {member.major}{member.studentId[0] + member.studentId[1]} {member.nickname} +
  • + ))} +
+
+
+
+
+
+ ); + })} +
+ ) +} + + +export default EnterCheckPage; \ No newline at end of file diff --git a/src/page/Main/ChatPage/NoEnterCheckPage.jsx b/src/page/Main/ChatPage/NoEnterCheckPage.jsx new file mode 100644 index 0000000..7bce082 --- /dev/null +++ b/src/page/Main/ChatPage/NoEnterCheckPage.jsx @@ -0,0 +1,197 @@ +import React, { useState } from "react"; +import './ChatPage.css' +import OkayDialog from './Dialog/OkayDialog' +import MaxMemberDialog from './Dialog/MaxMemberDialog' +import MaxChanceDialog from './Dialog/MaxChanceDialog' + + +function NoEnterCheckPage(props) { + const { chatRooms, possibleEnterNumber, gender } = props; + const [expandedRoomIds, setExpandedRoomIds] = useState([]); + const [okayDialog, setOkayDialog] = useState(false); + const [maxMemberDialog, setMaxMemberDialog] = useState(false); + const [maxChanceDialog, setMaxChanceDialog] = useState(false); + const [selectChatRoom, setSelectChatRoom] = useState(false); + + + + //새로고침 + const [startY, setStartY] = useState(0); + const [translateY, setTranslateY] = useState(0); + const [isRefreshing, setIsRefreshing] = useState(false); + + const threshold = 80; // 새로고침을 트리거하는 기준 거리 + + // 새로고침 함수 + const handleRefresh = () => { + setIsRefreshing(true); + setTimeout(() => { + setIsRefreshing(false); + window.location.reload(); // 페이지 새로고침 (필요에 따라 이 부분을 변경) + }, 1500); + }; + + // 터치 시작 + const handleTouchStart = (event) => { + setStartY(event.touches[0].clientY); + }; + + // 터치 중일 때 + const handleTouchMove = (event) => { + const currentY = event.touches[0].clientY; + const distance = currentY - startY; + + + // 스크롤이 최상단일 때만 동작 + if (window.scrollY === 0 && distance > 0) { + setTranslateY(distance * 0.3); // 끌린 만큼 translateY 값을 설정 + } + + // 기준 거리를 넘었을 때 새로고침 + if (distance > threshold) { + handleRefresh(); + } + }; + + // 터치 끝 + const handleTouchEnd = () => { + setTranslateY(0); // 터치가 끝나면 원래 위치로 돌아가기 + }; + + + + const toggleExpand = (roomId) => { + setExpandedRoomIds(prevState => + prevState.includes(roomId) + ? prevState.filter(id => id !== roomId) // 이미 확장된 상태면 닫기 + : [...prevState, roomId] // 확장되지 않았다면 추가 + ); + }; + + const enterCheckMessage = (chatRoom) => { + const halfMaxMembers = Math.floor(chatRoom.maxMembers / 2); // 최대 인원의 절반 계산 + let maleCount = 0; + let femaleCount = 0; + + // 방에 있는 멤버 중 남성과 여성 인원 카운트 + chatRoom.members.forEach(member => { + if (member.gender === "Male") { + maleCount++; + } else if (member.gender === "Female") { + femaleCount++; + } + }); + + // 유저가 남성일 때: 남성 인원이 절반보다 적으면 true + if (gender === "male" && maleCount < halfMaxMembers) { + return true; + } + + // 유저가 여성일 때: 여성 인원이 절반보다 적으면 true + if (gender === "female" && femaleCount < halfMaxMembers) { + return true; + } + + // 그 외에는 참가 불가 + return false; + }; + + const dialogOpen = (room) => { + if (!enterCheckMessage(room)) { + setMaxMemberDialog(true); + } else if (possibleEnterNumber === 0) { + setMaxChanceDialog(true) + } else { + setSelectChatRoom(room) + setOkayDialog(true); + } + } + + + + return ( + <> + {/* 다이얼로그 컴포넌트들 */} + setOkayDialog(false)} /> + setMaxMemberDialog(false)} /> + setMaxChanceDialog(false)} /> + +
+ {isRefreshing &&
} + + {chatRooms + .filter(room => room.enterCheck === false) // isEnterCheck 상태에 따라 필터링 + .map(room => { + const maleCount = room.members.filter(member => member.gender === "Male").length; + const femaleCount = room.members.filter(member => member.gender === "Female").length; + + const isExpanded = expandedRoomIds.includes(room.id); // 현재 방이 확장되었는지 확인 + return ( +
+
dialogOpen(room)}> + {enterCheckMessage(room) ?
참여가능
:
참여불가
} +

{room.title}

+
+ 남  {enterCheckMessage(room) ? {maleCount} : {maleCount}}/{room.maxMembers / 2} + 여  {enterCheckMessage(room) ? {femaleCount} : {femaleCount}}/{room.maxMembers / 2} +
+ +

{room.subTitle}

+
+
toggleExpand(room.id)}> + + 참여인원 보기 + {!isExpanded ? + + : + + + } + + + {/* 확장된 상태일 때만 멤버 리스트를 렌더링 */} +
+
+
+

남자

+
    + {room.members.filter(member => member.gender === "Male").map((member, index) => ( +
  • + {member.major}{member.studentId[0] + member.studentId[1]} {member.nickname} +
  • + ))} +
+
+
+

여자

+
    + {room.members.filter(member => member.gender === "Female").map((member, index) => ( +
  • + {member.major}{member.studentId[0] + member.studentId[1]} {member.nickname} +
  • + ))} +
+
+
+
+
+
+ ); + })} +
+ + ) + +} + + + +export default NoEnterCheckPage; \ No newline at end of file diff --git a/src/page/Main/Main.jsx b/src/page/Main/Main.jsx index c647dac..523153e 100644 --- a/src/page/Main/Main.jsx +++ b/src/page/Main/Main.jsx @@ -1,9 +1,11 @@ import React from "react"; +import { useNavigate } from "react-router-dom"; -function Main(){ - return( +function Main() { + const navigate = useNavigate(); + return (
- 메인 +
navigate('/chatStartPage')}>메인
) } From 7ee62cc94099b1c8fe1dadf4eadb0bfdee845b39 Mon Sep 17 00:00:00 2001 From: kim gisu Date: Fri, 13 Sep 2024 14:45:37 +0900 Subject: [PATCH 02/57] third commit --- package-lock.json | 32 ++ package.json | 1 + src/App.jsx | 3 + src/page/Main/ChatPage/ChatPage.css | 40 ++- src/page/Main/ChatPage/ChatRoom/ChatRoom.css | 150 +++++++++- src/page/Main/ChatPage/ChatRoom/ChatRoom.jsx | 117 +++++++- .../ChatRoomInformation.css | 276 ++++++++++++++++++ .../ChatRoomInformation.jsx | 195 ++++++++++++- src/page/Main/ChatPage/ChatStartPage.jsx | 52 ++-- src/page/Main/ChatPage/Dialog/ExitDialog.jsx | 45 +++ .../Main/ChatPage/Dialog/MaxChanceDialog.jsx | 1 + .../ChatPage/Dialog/UserIntroduceDialog.jsx | 44 +++ src/page/Main/ChatPage/Dialog/dialog.css | 191 +++++++++++- src/page/Main/ChatPage/EnterCheckPage.jsx | 14 +- .../ChatPage/MakeChatRoom/MakeChatRoom.css | 255 ++++++++++++++++ .../ChatPage/MakeChatRoom/MakeChatRoom.jsx | 176 +++++++++++ src/page/Main/ChatPage/NoEnterCheckPage.jsx | 14 +- src/page/Mypage/Mypage.css | 123 ++++---- src/page/Mypage/Mypage.jsx | 14 +- 19 files changed, 1622 insertions(+), 121 deletions(-) create mode 100644 src/page/Main/ChatPage/ChatRoom/ChatRoomInformation/ChatRoomInformation.css create mode 100644 src/page/Main/ChatPage/Dialog/ExitDialog.jsx create mode 100644 src/page/Main/ChatPage/Dialog/UserIntroduceDialog.jsx create mode 100644 src/page/Main/ChatPage/MakeChatRoom/MakeChatRoom.css create mode 100644 src/page/Main/ChatPage/MakeChatRoom/MakeChatRoom.jsx diff --git a/package-lock.json b/package-lock.json index 17a48c9..0d2540d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "axios": "^1.7.7", "jwt-decode": "^4.0.0", "react": "^18.3.1", "react-dom": "^18.3.1", @@ -5394,6 +5395,31 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/axobject-query": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", @@ -14627,6 +14653,12 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", diff --git a/package.json b/package.json index 7e3b85b..40cd4b9 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "axios": "^1.7.7", "jwt-decode": "^4.0.0", "react": "^18.3.1", "react-dom": "^18.3.1", diff --git a/src/App.jsx b/src/App.jsx index da1ad2d..499bf17 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -4,6 +4,8 @@ import Main from "./page/Main/Main"; import ChatStartPage from "./page/Main/ChatPage/ChatStartPage" import ChatRoom from "./page/Main/ChatPage/ChatRoom/ChatRoom" import ChatRoomInformation from "./page/Main/ChatPage/ChatRoom/ChatRoomInformation/ChatRoomInformation" +import MakeChatRoom from "./page/Main/ChatPage/MakeChatRoom/MakeChatRoom"; + import Mypage from "./page/Mypage/Mypage" @@ -20,6 +22,7 @@ function App() { } /> {/* } /> */} } /> + } /> diff --git a/src/page/Main/ChatPage/ChatPage.css b/src/page/Main/ChatPage/ChatPage.css index 4e00fac..4668c65 100644 --- a/src/page/Main/ChatPage/ChatPage.css +++ b/src/page/Main/ChatPage/ChatPage.css @@ -18,6 +18,12 @@ width: 375px; margin: 0 auto; + + .margin-container { + margin: 0 16px; + height: 100%; + } + .logo { width: 100px; height: 36px; @@ -93,7 +99,11 @@ } .chatRoomLists { - overflow: auto; + overflow-y: scroll; + scrollbar-width: none; + /* Firefox */ + -ms-overflow-style: none; + /* Internet Explorer 10+ */ margin: 20px 0 0 0; display: flex; height: 575px; @@ -113,7 +123,7 @@ border-style: solid; border-color: #EAEAEA; border-radius: 12px 12px 0px 0px; - height: 70px; + height: 80px; padding-bottom: 10px; cursor: pointer; } @@ -214,10 +224,7 @@ font-weight: 500; font-size: 12px; line-height: 14px; - /* identical to box height, or 117% */ - display: flex; - align-items: center; - + word-wrap: break-word; color: #5E5E5E; } @@ -384,7 +391,7 @@ position: relative; width: 343px; height: 50px; - top: -10px; + top: -25px; left: calc(50% - 343px / 2); background: #FF7898; border-radius: 5px; @@ -422,4 +429,23 @@ .refresh-icon { animation: spin 1s linear infinite; } + + + .user-list { + display: flex; + flex-direction: row; + } + + .user-list img { + width: 18px; + height: 18px; + border-radius: 50%; + margin-left: 3px; + margin-right: 5px; + } + + .user-container { + display: flex; + flex-direction: column; + } } \ No newline at end of file diff --git a/src/page/Main/ChatPage/ChatRoom/ChatRoom.css b/src/page/Main/ChatPage/ChatRoom/ChatRoom.css index a5f91e0..5269245 100644 --- a/src/page/Main/ChatPage/ChatRoom/ChatRoom.css +++ b/src/page/Main/ChatPage/ChatRoom/ChatRoom.css @@ -28,6 +28,7 @@ width: 90px; height: 18px; + cursor: pointer; font-family: 'Pretendard'; font-style: normal; font-weight: 600; @@ -47,7 +48,7 @@ - background-color: #F5F6F7; + background-color: #FAFAFA; } @@ -57,6 +58,7 @@ display: flex; justify-content: center; text-align: center; + cursor: pointer; } /*원이 3개이상*/ @@ -169,10 +171,10 @@ .text-bar { - position: relative; + position: fixed; width: 343px; height: 40px; - top: 500px; + bottom: 20px; display: flex; flex-direction: row; @@ -234,4 +236,146 @@ z-index: 1000; } + .chat-container { + gap: 10px; + display: flex; + flex-direction: column; + margin-top: 10px; + max-height: 639px; + overflow-y: scroll; + scrollbar-width: none; + /* Firefox */ + -ms-overflow-style: none; + /* Internet Explorer 10+ */ + + } + + .message-group { + display: flex; + flex-direction: row; + align-items: flex-start; + margin-bottom: 5px; + } + + .profile-icon { + /* Ellipse 1457 */ + + width: 30px; + height: 30px; + border-radius: 50%; + /* 임시 */ + background: #eee; + } + + .message-box { + width: 100%; + display: flex; + flex-direction: column; + } + + .message-box.noSent { + padding-left: 5px; + } + + .message { + background-color: #f1f1f1; + padding: 8px 15px; + border-radius: 42px; + max-width: 60%; + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 400; + font-size: 14px; + line-height: 20px; + /* identical to box height, or 143% */ + display: flex; + align-items: center; + + color: #3D3D3D; + + + /* Inside auto layout */ + flex: none; + order: 0; + flex-grow: 0; + + } + + .message-group.sent { + margin-top: 13px; + transform: scaleX(-1); + } + + + .message.sent { + background-color: #FF7898; + transform: scaleX(-1); + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 400; + font-size: 14px; + line-height: 20px; + /* identical to box height, or 143% */ + display: flex; + align-items: center; + + color: #FFFFFF; + + + /* Inside auto layout */ + flex: none; + order: 0; + flex-grow: 0; + } + + .message-time.sent { + transform: scaleX(-1); + } + + .message-time { + font-size: 10px; + color: gray; + margin-top: auto; + position: relative; + left: 5px; + + } + + .message-time-box { + display: flex; + flex-direction: row; + } + + .chat-nickName { + /* 참여자닉네임1 */ + + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 400; + font-size: 10px; + line-height: 12px; + /* identical to box height, or 120% */ + display: flex; + align-items: center; + padding-left: 7px; + color: #777777; + margin-bottom: 5px; + } + + .message-group.noSent { + .no-see { + width: 30px; + height: 30px; + } + } + + .message-box.no-see-box.noSent { + position: relative; + top: -5px + } + + } \ No newline at end of file diff --git a/src/page/Main/ChatPage/ChatRoom/ChatRoom.jsx b/src/page/Main/ChatPage/ChatRoom/ChatRoom.jsx index 6106529..997d971 100644 --- a/src/page/Main/ChatPage/ChatRoom/ChatRoom.jsx +++ b/src/page/Main/ChatPage/ChatRoom/ChatRoom.jsx @@ -1,10 +1,14 @@ -import React, { useState } from "react"; +import React, { useState, useRef, useEffect } from "react"; import '../ChatRoom/ChatRoom.css' import { useNavigate } from 'react-router-dom'; function ChatRoom() { const navigate = useNavigate(); + const chatContainerRef = useRef(null); + const [inputValue, setInputValue] = useState(''); // 입력된 메시지 저장 + const [messages, setMessages] = useState([]); // 메시지 리스트 저장 + const [selectChatRoom, setSelectChatRoom] = useState({ id: 1, @@ -24,6 +28,25 @@ function ChatRoom() { maxMembers: 6, //입장체크 enterCheck: false, + + // 메시지 데이터 + messages: [ + { sender: "John", text: "안녕하세요, 모두들!", time: "13:57", profileImage: "https://example.com/profile1.png" }, + { sender: "Jane", text: "안녕하세요, John!", time: "13:58", profileImage: "https://example.com/profile2.png" }, + { sender: "Emma", text: "모두들 잘 지내시나요?", time: "13:59", profileImage: "https://example.com/profile3.png" }, + { sender: "John", text: "네, 저희 프로젝트가 잘 진행되고 있어요.", time: "14:00", profileImage: "https://example.com/profile1.png" }, + { sender: "Mike", text: "다들 프로젝트 진행 상황 공유할까요?", time: "14:01", profileImage: "https://example.com/profile4.png" }, + { sender: "Jane", text: "좋아요! 저는 디자인을 거의 완료했어요.", time: "14:02", profileImage: "https://example.com/profile2.png" }, + { sender: "Jane", text: "좋아요! 저는 디ㄹㅇ.", time: "14:02", profileImage: "https://example.com/profile2.png" }, + { sender: "John", text: "완성된 디자인을 빨리 보고 싶네요.", time: "14:03", profileImage: "https://example.com/profile1.png" }, + { sender: "Mike", text: "다들 프로젝트 진행 상황 공유할까요?", time: "14:05", profileImage: "https://example.com/profile4.png" }, + { sender: "Mike", text: "다들 프로젝트 진행 상황 공유할까요?", time: "14:05", profileImage: "https://example.com/profile4.png" }, + { sender: "Mike", text: "다들 프로젝트 진행 상황 공유할까요?", time: "14:05", profileImage: "https://example.com/profile4.png" }, + { sender: "Mike", text: "다들 프로젝트 진행 상황 공유할까요?", time: "14:06", profileImage: "https://example.com/profile4.png" }, + { sender: "Mike", text: "다들 프로젝트 진행 상황 공유할까요?", time: "14:06", profileImage: "https://example.com/profile4.png" }, + + + ] }) @@ -34,13 +57,85 @@ function ChatRoom() { const memberLengthClassName = `member-length-${memberLength}`; + // 컴포넌트가 처음 렌더링되거나 messages가 업데이트될 때 스크롤을 아래로 이동 + useEffect(() => { + if (chatContainerRef.current) { + chatContainerRef.current.scrollTop = chatContainerRef.current.scrollHeight; + } + }, [selectChatRoom]); // messages가 변경될 때마다 스크롤을 업데이트 + + const goChatRoomInformation = () => { - navigate('/ChatRoomInformation/0') + navigate('/goChatRoomInformation/0') } + // 메시지 전송 함수 + const sendMessage = () => { + if (inputValue.trim()) { + const newMessage = { + sender: "John", // 현재 사용자 + text: inputValue, + time: new Date().toLocaleTimeString(), // 현재 시간 + }; + + setMessages([...messages, newMessage]); // 메시지 리스트에 새 메시지 추가 + setInputValue(''); // 입력 필드 비우기 + } + }; + + // Enter 키를 누르면 메시지 전송 + const handleKeyPress = (event) => { + if (event.key === 'Enter') { + sendMessage(); + } + }; + + + const formatMessages = (messages) => { + return messages.map((message, index) => { + // 현재 유저를 받는 로직 추가 해야됨 + const isCurrentUser = message.sender === "John"; + + // 프로필 이미지와 닉네임을 표시할지 여부 결정 + const showProfile = !isCurrentUser && + (index === 0 || messages[index - 1].sender !== message.sender || messages[index - 1].time !== message.time); + + // 시간 표시할지 여부 결정 + const isLastMessage = index === messages.length - 1; + const isNextSenderDifferent = !isLastMessage && messages[index + 1].sender !== message.sender; + const isNextTimeDifferent = !isLastMessage && messages[index + 1].time !== message.time; + const showTime = isLastMessage || isNextSenderDifferent || isNextTimeDifferent; + + return ( +
+ {showProfile ? + {`${message.sender}'s :
+ } +
+ {showProfile && ({message.sender})} +
+
+ {message.text} +
+ {showTime && ( +
{message.time}
+ )} +
+
+
+ ); + }); + }; + + + return (
@@ -51,7 +146,7 @@ function ChatRoom() {
-
+
goChatRoomInformation()}> {members.map((member, index) => (
//멤버의 프로필 사진 스타일 설정 ))} @@ -64,19 +159,23 @@ function ChatRoom() {
-
- -
- +
+ {formatMessages(selectChatRoom.messages)} +
- + setInputValue(e.target.value)} // 입력된 값 업데이트 + onKeyDown={handleKeyPress} // Enter 키 처리 + />
-
+
diff --git a/src/page/Main/ChatPage/ChatRoom/ChatRoomInformation/ChatRoomInformation.css b/src/page/Main/ChatPage/ChatRoom/ChatRoomInformation/ChatRoomInformation.css new file mode 100644 index 0000000..2da054d --- /dev/null +++ b/src/page/Main/ChatPage/ChatRoom/ChatRoomInformation/ChatRoomInformation.css @@ -0,0 +1,276 @@ +.chatRoomInformation { + height: 812px; + width: 375px; + + margin: 0 auto; + + .margin-container { + display: flex; + flex-direction: column; + height: 100%; + margin: 0 16px; + } + + .title { + width: 100%; + height: 46px; + margin-top: 50px; + background: #ffffff; + display: flex; + text-align: center; + + } + + .title-name { + /* 채팅방 이름 */ + + padding-top: 15px; + width: 90px; + height: 18px; + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 600; + font-size: 16px; + line-height: 18px; + /* identical to box height, or 112% */ + display: flex; + align-items: center; + + color: #3D3D3D; + } + + + .chat-room-header { + display: flex; + flex-direction: column; + align-items: center; + margin-bottom: 50px; + margin-top: 10px + } + + .chat-room-image { + border-radius: 50%; + margin-bottom: 10px; + + /* 채팅방 대표사진 */ + width: 60px; + height: 60px; + background-color: #3D3D3D; + + } + + .chat-room-name { + + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 600; + font-size: 16px; + line-height: 18px; + + color: #3D3D3D; + } + + + + .chat-room-actions { + width: 300px; + margin: 0 auto; + display: flex; + justify-content: space-evenly; + margin-bottom: 20px; + } + + .action-item { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 5px; + width: 84px; + height: 84px; + background-color: #FAFAFA; + border-radius: 20%; + transition: all 0.3s ease; + } + + .action-item img { + width: 30px; + height: 30px; + } + + .action-item span { + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 500; + font-size: 12px; + line-height: 14px; + + color: #000000; + } + + .chat-room-timer { + + margin: 0 auto; + width: 272px; + height: 40px; + + + background: #FAFAFA; + border-radius: 10px; + margin-bottom: 20px; + display: flex; + justify-content: center; + align-items: center; + } + + .chat-room-timer span { + + + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 500; + font-size: 12px; + line-height: 14px; + /* identical to box height, or 117% */ + + + color: #000000; + } + + .participant-list { + margin-top: 20px; + display: flex; + flex-direction: column; + gap: 5px; + } + + .participant-list-text { + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 600; + font-size: 14px; + line-height: 18px; + + color: #3D3D3D; + margin-bottom: 10px; + } + + .gender { + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 500; + font-size: 12px; + line-height: 12px; + color: #777777; + margin-bottom: 10px; + } + + + .participant-group { + max-height: 150px; + overflow-y: scroll; + scrollbar-width: none; + /* Firefox */ + -ms-overflow-style: none; + } + + .participant-group ul { + padding-left: 0px; + } + + + + .bar { + width: 343px; + height: 6px; + background-color: #FAFAFA; + + } + + + .major { + + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 400; + font-size: 12px; + line-height: 14px; + /* identical to box height, or 117% */ + display: flex; + align-items: center; + + color: #777777; + } + + .nickName { + + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 500; + font-size: 12px; + line-height: 14px; + /* identical to box height, or 117% */ + display: flex; + align-items: center; + + color: #3D3D3D; + } + + .user-list { + display: flex; + flex-direction: row; + margin-bottom: 5px; + } + + .user-list img { + width: 18px; + height: 18px; + border-radius: 50%; + margin-left: 3px; + margin-right: 5px; + } + + .user-container { + display: flex; + flex-direction: column; + } + + + + + + + .action-item svg { + fill: none; + transition: all 0.3s ease; + } + + .action-item span { + color: #3D3D3D; + transition: all 0.3s ease; + } + + .action-item.active { + background-color: #FF7898; + /* 핑크 배경 */ + } + + .action-item.active svg { + fill: #fff; + /* 아이콘 하얀색 */ + } + + .action-item.active span { + color: #fff; + /* 글자 하얀색 */ + } + +} \ No newline at end of file diff --git a/src/page/Main/ChatPage/ChatRoom/ChatRoomInformation/ChatRoomInformation.jsx b/src/page/Main/ChatPage/ChatRoom/ChatRoomInformation/ChatRoomInformation.jsx index 3115a92..50f146b 100644 --- a/src/page/Main/ChatPage/ChatRoom/ChatRoomInformation/ChatRoomInformation.jsx +++ b/src/page/Main/ChatPage/ChatRoom/ChatRoomInformation/ChatRoomInformation.jsx @@ -1,31 +1,202 @@ import React, { useState } from "react"; -import { useNavigate } from 'react-router-dom'; +import { UNSAFE_DataRouterStateContext, useNavigate } from 'react-router-dom'; +import '../ChatRoomInformation/ChatRoomInformation.css' +import ExitDialog from '../../Dialog/ExitDialog' +import UserIntroduceDialog from '../../Dialog/UserIntroduceDialog' -const ChatRoomInformation = () => { - return ( -
-
+function ChatRoomInformation() { + const navigate = useNavigate(); + const [exitDialog, setExitDialog] = useState(false); + + + const goChatRoom = () => { + navigate('/chat/0'); + }; + + const [activeItemPromise, setActiveItemPromise] = useState(null); + const [activeItemAlarm, setActiveItemAlarm] = useState(null); + const [activeItemExit, setActiveItemExit] = useState(null); + const [userIntroduceDialog, setUserIntroduceDialog] = useState(false); + const [clickUser, setClickUser] = useState(); + + const handleClick = (item) => { + if (item === "promise") { + if (activeItemPromise) { + setActiveItemPromise(false); + } else { + setActiveItemPromise(true); + } + } else if (item === "alarm") { + if (activeItemAlarm) { + setActiveItemAlarm(false); + } else { + setActiveItemAlarm(true); + } + } else if (item === "exit") { + if (activeItemExit) { + setActiveItemExit(false); + } else { + setActiveItemExit(true); + } + } + + }; + + const [room, setRoom] = useState({ + id: 1, + //제목 길이 20자 제한 + title: "채팅방 메인 타이틀아아아아f", + //서브제목 길이 30자 제한 + subTitle: "sdafasdfadsfjlsadflㅁㄴ어ㅣㄹㄴㅁ이ㅓ리너아리ㅁㄴㅇㄻㄴㅇㄹ", + //방아이디로 조회한다. + members: [ + { gender: "Male", major: "Computer Science", studentId: "20210001", nickname: "John", profileImage: "sd" }, + { gender: "Female", major: "Design", studentId: "20210002", nickname: "Jane", profileImage: "sd" } + , { gender: "Female", major: "Design", studentId: "20210002", nickname: "Jane", profileImage: "sd" } + , { gender: "Female", major: "Design", studentId: "20210002", nickname: "Jane", profileImage: "sd" } + ], + maxMembers: 6, + //입장체크 + enterCheck: false, + // 메시지 데이터 + messages: [ + { sender: "John", text: "안녕하세요, 모두들!", time: "13:57", profileImage: "https://example.com/profile1.png" }, + { sender: "Jane", text: "안녕하세요, John!", time: "13:58", profileImage: "https://example.com/profile2.png" }, + { sender: "Emma", text: "모두들 잘 지내시나요?", time: "13:59", profileImage: "https://example.com/profile3.png" }, + { sender: "John", text: "네, 저희 프로젝트가 잘 진행되고 있어요.", time: "14:00", profileImage: "https://example.com/profile1.png" }, + { sender: "Mike", text: "다들 프로젝트 진행 상황 공유할까요?", time: "14:01", profileImage: "https://example.com/profile4.png" }, + { sender: "Jane", text: "좋아요! 저는 디자인을 거의 완료했어요.", time: "14:02", profileImage: "https://example.com/profile2.png" }, + { sender: "Jane", text: "좋아요! 저는 디ㄹㅇ.", time: "14:02", profileImage: "https://example.com/profile2.png" }, + { sender: "John", text: "완성된 디자인을 빨리 보고 싶네요.", time: "14:03", profileImage: "https://example.com/profile1.png" }, + { sender: "Mike", text: "다들 프로젝트 진행 상황 공유할까요?", time: "14:05", profileImage: "https://example.com/profile4.png" }, + { sender: "Mike", text: "다들 프로젝트 진행 상황 공유할까요?", time: "14:05", profileImage: "https://example.com/profile4.png" }, + { sender: "Mike", text: "다들 프로젝트 진행 상황 공유할까요?", time: "14:05", profileImage: "https://example.com/profile4.png" }, + { sender: "Mike", text: "다들 프로젝트 진행 상황 공유할까요?", time: "14:06", profileImage: "https://example.com/profile4.png" }, + { sender: "Mike", text: "다들 프로젝트 진행 상황 공유할까요?", time: "14:06", profileImage: "https://example.com/profile4.png" }, -
- 네비바 -
+ ] + }) + const dialogOpen = (user) => { + setUserIntroduceDialog(true); + setClickUser(user); + } + + + + + return ( +
+ setUserIntroduceDialog(false)} /> + setExitDialog(false)} /> +
+
+
goChatRoom()}> + + +
-
+
+ {/* 이미지와 채팅방 이름 */} +
+ Chat Room + 채팅방 이름 +
+ + {/* 버튼들 */} +
+ {/* 약속 잡기 */} +
handleClick('promise')} + > + + + + + + + + 약속 잡기 +
+ + {/* 알림 끄기 */} +
handleClick('alarm')} + > + + + + + + {activeItemAlarm ? <> + + 알림 키기 : 알림 끄기 + } + +
+ + {/* 나가기 */} +
{ handleClick('exit'); setExitDialog(true) }} + > + + + + 나가기
-
+
+ + + {/* 채팅방 종료 시간 */} +
+ 0일 00시간 00분 후에 채팅방이 종료됩니다 +
+
+ + {/* 참여자 목록 */} +
+ 참여자 목록 +
+
남자
+
    + {room.members.filter(member => member.gender === "Male").map((member, index) => ( +
  • dialogOpen()}> + zz +
    + {member.major}{member.studentId[0] + member.studentId[1]} {member.nickname} +
    +
  • + ))} +
+
+
+
여자
+
    + {room.members.filter(member => member.gender === "Female").map((member, index) => ( +
  • dialogOpen()}> + zz +
    + {member.major}{member.studentId[0] + member.studentId[1]} {member.nickname} +
    +
  • + ))} +
-
-
+ +
+
); } diff --git a/src/page/Main/ChatPage/ChatStartPage.jsx b/src/page/Main/ChatPage/ChatStartPage.jsx index 90ac44f..551a3ef 100644 --- a/src/page/Main/ChatPage/ChatStartPage.jsx +++ b/src/page/Main/ChatPage/ChatStartPage.jsx @@ -3,9 +3,11 @@ import './ChatPage.css' import EnterCheckPage from './EnterCheckPage' import NoEnterCheckPage from './NoEnterCheckPage' import { jwtDecode } from 'jwt-decode'; +import { useNavigate } from 'react-router-dom'; function ChatStartPage() { + const navigate = useNavigate(); const [loading, setLoading] = useState(true); const [isEnterCheck, setIsEnterClick] = useState(false); @@ -14,6 +16,7 @@ function ChatStartPage() { const [gender, setGender] = useState("male"); + useEffect(() => { const fetchUserData = async () => { try { @@ -41,7 +44,7 @@ function ChatStartPage() { const data = await response.json(); setGender(data.gender); - setPossibleEnterNumber(data.ticket) + setPossibleEnterNumber(data.ticket); } catch (error) { console.log(error); } finally { @@ -72,7 +75,7 @@ function ChatStartPage() { //제목 길이 20자 제한 title: "채팅방 메인 타이틀아아아아f", //서브제목 길이 30자 제한 - subTitle: "sdafasdfadsfjlsadflㅁㄴ어ㅣㄹㄴㅁ이ㅓ리너아리ㅁㄴㅇㄻㄴㅇㄹ", + subTitle: "dddddddddddddddddddddddddddddddddddddddddddddddddd", //방아이디로 조회한다. members: [ @@ -128,6 +131,7 @@ function ChatStartPage() { const makeChatRoom = () => { //챗룸 만들기로 이동 + navigate('/makeChatRoom') } @@ -138,37 +142,35 @@ function ChatStartPage() { return (
- logo - -
-
- setIsEnterClick(true)} >참여중 - setIsEnterClick(false)}>모집중 -
- {isEnterCheck ? 최대 {possibleEnterNumber}개 방까지 참여 가능합니다 : } - -
- -
- {isEnterCheck ? : } -
+
+ logo - -
- 네비바 -
+
+
+ setIsEnterClick(true)} >참여중 + setIsEnterClick(false)}>모집중 +
+ {isEnterCheck ? 최대 {possibleEnterNumber}개 방까지 참여 가능합니다 : }
-
+
+ {isEnterCheck ? : }
-
+ + +
+ -
+
); } diff --git a/src/page/Main/ChatPage/Dialog/ExitDialog.jsx b/src/page/Main/ChatPage/Dialog/ExitDialog.jsx new file mode 100644 index 0000000..38a5fa5 --- /dev/null +++ b/src/page/Main/ChatPage/Dialog/ExitDialog.jsx @@ -0,0 +1,45 @@ +import React, { useState } from "react"; +import './dialog.css' + +function ExitDialog({ isOpen, onClose }) { + if (!isOpen) return null; + + const exitRoom = () => { + //로직구현 + onClose(); + } + + return ( +
+
+
+
+ + + + + + +
+

정말로 채팅방을 나가시겠어요?

+

+ {/* 로직구현 */} + 현재 나의 채팅방 입장 참여 횟수 0개 +

+
+ + + +
+ +
+
+
+ ); +} + +export default ExitDialog; \ No newline at end of file diff --git a/src/page/Main/ChatPage/Dialog/MaxChanceDialog.jsx b/src/page/Main/ChatPage/Dialog/MaxChanceDialog.jsx index 672d790..74eb073 100644 --- a/src/page/Main/ChatPage/Dialog/MaxChanceDialog.jsx +++ b/src/page/Main/ChatPage/Dialog/MaxChanceDialog.jsx @@ -18,6 +18,7 @@ function MaxChanceDialog({ isOpen, onClose }) {

최대 참여 가능한 채팅방 수가 초과되었습니다

+ {/* 로직구현 */} 현재 나의 채팅방 입장 참여 횟수 0개

+
+
+
+
+ ); +} + +export default UserIntroduceDialog; \ No newline at end of file diff --git a/src/page/Main/ChatPage/Dialog/dialog.css b/src/page/Main/ChatPage/Dialog/dialog.css index 7f37b31..3e3e3fd 100644 --- a/src/page/Main/ChatPage/Dialog/dialog.css +++ b/src/page/Main/ChatPage/Dialog/dialog.css @@ -1,11 +1,12 @@ .dialog { position: absolute; - height: 812px; - width: 375px; + height: 100%; + width: 100%; top: 0px; background: rgba(0, 0, 0, 0.1); z-index: 1000; + left: 0px; .dialog-backdrop { @@ -293,4 +294,190 @@ margin-bottom: 16px; text-align: left; } +} + + +.userIntroduceDialog { + position: absolute; + height: 100%; + width: 100%; + top: 0px; + background: rgba(0, 0, 0, 0.1); + z-index: 1000; + left: 0px; + display: flex; + justify-content: center; + + .dialog-backdrop { + display: flex; + justify-content: center; + align-items: center; + z-index: 1000; + position: absolute; + width: 375px; + height: 558px; + top: 254px; + } + + .dialog-container { + background-color: white; + border-radius: 20px; + width: 100%; + height: 100%; + text-align: center; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + display: flex; + flex-direction: column; + + + } + + + .dialog-title { + /* 최대 참여 가능 채팅방 수가 초과되었습니다 */ + font-family: 'Pretendard'; + font-style: normal; + font-weight: 600; + font-size: 16px; + line-height: 18px; + margin-bottom: 0; + /* identical to box height, or 112% */ + margin-top: 10px; + + color: #3D3D3D; + } + + .dialog-message { + margin-top: 3px; + font-family: 'Pretendard'; + font-style: normal; + font-weight: 500; + font-size: 14px; + color: #777777; + } + + + .button-container { + margin-top: 30px; + display: flex; + flex-direction: row; + justify-content: space-evenly; + } + + + + + .dialog-button-cancle { + /* Rectangle 3470049 */ + width: 136px; + height: 44px; + border: none; + background-color: #F5F5F5; + border-radius: 14px; + font-family: 'Pretendard'; + font-style: normal; + font-weight: 600; + font-size: 18px; + line-height: 20px; + cursor: pointer; + color: #3D3D3D; + } + + + .dialog-button-cancle:hover { + background-color: #FF7898; + color: #F5F5F5; + } + + .profile-image-container { + margin-top: 50px; + } + + .profile-image-container img { + width: 128px; + height: 128px; + border-radius: 50%; + } + + .introduction-container { + margin: 10px auto; + margin-bottom: 30px; + width: 343px; + height: 46px; + background: #F5F5F5; + border-radius: 10px; + align-items: center; + display: flex; + } + + .introduction { + /* 한 줄 소개 안녕하세요~~~~ */ + width: 100%; + height: 16px; + padding: 0 20px; + text-align: left; + font-family: 'Pretendard'; + font-style: normal; + font-weight: 400; + font-size: 14px; + line-height: 16px; + + + color: #3D3D3D; + } + + .additional-info-container { + margin: 0 20px; + padding: 0 10px; + background: #F5F5F5; + border-radius: 10px; + + } + + .additional-info { + width: 100%; + height: 100%; + text-align: left; + display: flex; + flex-direction: column; + padding: 10px; + gap: 7px; + } + + .additional-info div { + display: flex; + flex-direction: row; + } + + .additional-info .first { + + width: 45px; + height: 16px; + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 400; + font-size: 14px; + line-height: 16px; + + + color: #3D3D3D; + } + + .additional-info .second { + + width: 269px; + height: 16px; + margin-left: 10px; + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 500; + font-size: 14px; + line-height: 16px; + + + color: #3D3D3D; + } + } \ No newline at end of file diff --git a/src/page/Main/ChatPage/EnterCheckPage.jsx b/src/page/Main/ChatPage/EnterCheckPage.jsx index 10e7430..3186f46 100644 --- a/src/page/Main/ChatPage/EnterCheckPage.jsx +++ b/src/page/Main/ChatPage/EnterCheckPage.jsx @@ -126,8 +126,11 @@ function EnterCheckPage(props) {

남자

    {room.members.filter(member => member.gender === "Male").map((member, index) => ( -
  • - {member.major}{member.studentId[0] + member.studentId[1]} {member.nickname} +
  • + zz +
    + {member.major}{member.studentId[0] + member.studentId[1]} {member.nickname} +
  • ))}
@@ -136,8 +139,11 @@ function EnterCheckPage(props) {

여자

    {room.members.filter(member => member.gender === "Female").map((member, index) => ( -
  • - {member.major}{member.studentId[0] + member.studentId[1]} {member.nickname} +
  • + zz +
    + {member.major}{member.studentId[0] + member.studentId[1]} {member.nickname} +
  • ))}
diff --git a/src/page/Main/ChatPage/MakeChatRoom/MakeChatRoom.css b/src/page/Main/ChatPage/MakeChatRoom/MakeChatRoom.css new file mode 100644 index 0000000..9b9a57c --- /dev/null +++ b/src/page/Main/ChatPage/MakeChatRoom/MakeChatRoom.css @@ -0,0 +1,255 @@ +.makeChatRoom { + + height: 812px; + width: 375px; + margin: 0 auto; + + .margin-container { + display: flex; + flex-direction: column; + height: 100%; + margin: 0 10px; + } + + .title { + width: 100%; + height: 46px; + margin-top: 50px; + background: #ffffff; + display: flex; + text-align: center; + margin-left: 6px; + justify-content: space-between; + } + + .title-name { + /* 채팅방 이름 */ + + padding-top: 15px; + width: 120px; + height: 18px; + + cursor: pointer; + font-family: 'Pretendard'; + font-style: normal; + font-weight: 600; + font-size: 16px; + line-height: 18px; + /* identical to box height, or 112% */ + display: flex; + align-items: center; + + color: #3D3D3D; + + + } + + .small-title { + /* 채팅방 정보 */ + margin-top: 20px; + width: 73px; + height: 18px; + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 600; + font-size: 16px; + line-height: 18px; + + color: #3D3D3D; + + } + + .top { + width: 100%; + display: flex; + flex-direction: row; + gap: 20px; + height: 80px; + margin-bottom: 20px; + justify-content: space-between; + + } + + + .chat-room-info { + display: flex; + flex-direction: column; + align-items: center; + margin-top: 5px; + } + + + + .top img { + border: 1px solid #ccc; + border-radius: 50%; + width: 80px; + height: 100%; + background-color: none; + } + + + .edit-avatar { + border: 1px solid #ccc; + border-radius: 50%; + position: relative; + width: 20px; + height: 20px; + left: -110px; + top: 80px; + display: flex; + justify-content: center; + align-items: center; + background: #F5F5F5; + } + + .chat-room-name { + + + width: 230px; + background: #F5F5F5; + border-radius: 10px; + margin: auto 0px; + height: 50px; + border: 1px solid #ccc; + padding: 0 10px; + font-family: 'Pretendard'; + font-style: normal; + font-weight: 400; + font-size: 14px; + line-height: 16px; + color: #777777; + } + + .chat-room-description { + + width: 335px; + height: 100px; + + background: #F5F5F5; + border-radius: 10px; + + border: 1px solid #ccc; + border-radius: 10px; + font-size: 14px; + + + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 400; + font-size: 14px; + line-height: 16px; + padding: 10px; + color: #777777; + } + + .members-settings { + margin-top: 50px; + margin-bottom: 20px; + } + + .small-title2 { + width: 73px; + height: 18px; + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 600; + font-size: 16px; + line-height: 18px; + margin-bottom: 30px; + color: #3D3D3D; + } + + .gender-settings { + margin-left: 10px; + display: flex; + flex-direction: column; + gap: 15px; + } + + + .gender-settings div { + display: flex; + flex-direction: row; + align-items: center; + gap: 10px; + } + + .gender-settings span { + + width: 25px; + height: 16px; + + font-family: 'Pretendard'; + font-style: normal; + font-weight: 500; + font-size: 14px; + line-height: 16px; + + + color: #3D3D3D; + } + + + + .count-button { + + padding: 5px 15px; + border-radius: 20px; + border: 1px solid #ccc; + background-color: #fff; + cursor: pointer; + } + + .count-button.active { + background-color: #FF7898; + border-color: #ccc; + color: #F5F5F5; + } + + + + .note { + margin-top: 50px; + font-size: 12px; + color: #888; + margin-bottom: 20px; + } + + .create-room-button { + /* Rectangle 13 */ + margin: 5px auto; + font-family: 'Pretendard'; + font-style: normal; + font-weight: 700; + font-size: 18px; + line-height: 20px; + color: #FFFFFF; + background: #FF7898; + width: 343px; + height: 50px; + background: #FF7898; + border-radius: 5px; + border: none; + } + + .create-room-button:hover { + background-color: #FF7898; + } + + .error { + margin-left: 7px; + font-family: 'Pretendard'; + font-style: normal; + font-weight: 400; + font-size: 12px; + line-height: 14px; + display: flex; + align-items: center; + color: #FF3131; + } + +} \ No newline at end of file diff --git a/src/page/Main/ChatPage/MakeChatRoom/MakeChatRoom.jsx b/src/page/Main/ChatPage/MakeChatRoom/MakeChatRoom.jsx new file mode 100644 index 0000000..1b07cb6 --- /dev/null +++ b/src/page/Main/ChatPage/MakeChatRoom/MakeChatRoom.jsx @@ -0,0 +1,176 @@ +import React, { useState, useRef } from "react"; +import '../MakeChatRoom/MakeChatRoom.css' +import { useNavigate } from 'react-router-dom'; + +function MakeChatRoom() { + const navigate = useNavigate(); + + const [count, setCount] = useState(3); + const [roomTitle, setRoomTitle] = useState(''); + const [subTitle, setSubTitle] = useState('');//30자 이내로 제한 + const [profileImage, setProfileImage] = useState('https://mblogthumb-phinf.pstatic.net/MjAyMzA2MjdfMjgx/MDAxNjg3ODM1MzE3NjQ5.oBDtVqa7bFScuJ308FzHAdmRtABmaL1_SXK17n0-ndQg.KzZ6AcPYVQvHqB_vw4dZp8FG97HJp6bUS4QOU5RatRsg.JPEG.dream_we/IMG_7305.JPG?type=w800'); + const [error, setError] = useState(''); + + const fileInputRef = useRef(null); + + const handleImageClick = () => { + fileInputRef.current.click(); + }; + + const handleImageChange = (event) => { + const file = event.target.files[0]; + if (file) { + const reader = new FileReader(); + reader.onloadend = () => { + setProfileImage(reader.result); + }; + reader.readAsDataURL(file); + } + }; + + + const handleTitleChange = (e) => { + if (e.target.value.length <= 20) { + setRoomTitle(e.target.value); + } + }; + + const handleSubTitleChange = (e) => { + if (e.target.value.length <= 50) { + setSubTitle(e.target.value); + } + }; + + const makeRoom = () => { + if (roomTitle === '' || subTitle === '') { + setError('모든 필드를 입력해 주세요.'); + return; + } + // Logic for making the chat room + console.log("Room Created"); + // Clear error if successful + setError(''); + }; + + + + + return ( + <> +
+
+
+
navigate('/ChatStartPage')} > + + + + + 채팅방 만들기 +
+ +
+ +
채팅방 정보
+ +
+
+ + + +
+
+ + +
+