From 080ec24a09fc9a271800eaa44b5f7e6463976aab Mon Sep 17 00:00:00 2001 From: KIMJINYOUNG Date: Wed, 4 Dec 2024 21:48:06 +0900 Subject: [PATCH 01/10] =?UTF-8?q?refactor:=20=EB=B9=84=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EC=9D=98=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=9C=A0=EB=8F=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 비회원이 공유, 좋아요 버튼 누를 시 로그인 바텀시트 올라오도록 #154 --- ...webcam-npm-7.2.0-4404f3658d-d639a9e4cd.zip | Bin 0 -> 171016 bytes .../src/components/Chat/ChatProductItem.tsx | 23 +++++++++++++++--- .../components/Chat/ChatShareDislikeBox.tsx | 23 ++++++++++++++++-- frontend/src/components/login/Login.tsx | 14 ++++++++++- .../src/components/signup/SignUpRequired.tsx | 17 +++++++++++++ 5 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 frontend/.yarn/cache/react-webcam-npm-7.2.0-4404f3658d-d639a9e4cd.zip diff --git a/frontend/.yarn/cache/react-webcam-npm-7.2.0-4404f3658d-d639a9e4cd.zip b/frontend/.yarn/cache/react-webcam-npm-7.2.0-4404f3658d-d639a9e4cd.zip new file mode 100644 index 0000000000000000000000000000000000000000..a8a2b73b3e0f1c9a2b710743c4dd8afd0d389aa9 GIT binary patch literal 171016 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

~wR@iK#b}=H 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 literal 0 HcmV?d00001 diff --git a/frontend/src/components/Chat/ChatProductItem.tsx b/frontend/src/components/Chat/ChatProductItem.tsx index a5db168..5eaa944 100644 --- a/frontend/src/components/Chat/ChatProductItem.tsx +++ b/frontend/src/components/Chat/ChatProductItem.tsx @@ -2,7 +2,9 @@ import { addOrRemoveShoeFromLikes } from "@apis/firebase/likeFirestore"; import userStore from "@store/auth.store"; import LikeButton from "@common/LikeButton"; import Img from "@common/html/Img"; -import { useParams } from "react-router-dom"; +import { useNavigate, useParams } from "react-router-dom"; +import useChatStore from "@/store/chat.store"; +import { useBottomSheet } from "@/store/bottomSheet.store"; interface ProductItemProps { brand: string; @@ -28,6 +30,14 @@ const ChatProductItem = (props: ProductItemProps) => { const { messageId } = useParams(); const isSharePage = Boolean(messageId); + const { addGuestMessage } = useChatStore(); + const { open } = useBottomSheet(); + const navigate = useNavigate(); + const goToLogin = () => { + navigate("#login"); + open("login"); + }; + const handleLikeClick = async (e: React.MouseEvent) => { e.stopPropagation(); if (isLoggedIn) { @@ -41,8 +51,15 @@ const ChatProductItem = (props: ProductItemProps) => { }); updateUserInfo(); } else { - console.log("로그인이 필요합니다."); - // 여기서 로그인하라는 채팅을 띄워주면 좋을 듯 하다. 일단 나중에 .. + addGuestMessage({ + type: "bot", + content: { + message: "로그인이 필요한 기능입니다.", + }, + }); + setTimeout(() => { + goToLogin(); + }, 1500); } }; return ( diff --git a/frontend/src/components/Chat/ChatShareDislikeBox.tsx b/frontend/src/components/Chat/ChatShareDislikeBox.tsx index 1d2405e..16a0ab2 100644 --- a/frontend/src/components/Chat/ChatShareDislikeBox.tsx +++ b/frontend/src/components/Chat/ChatShareDislikeBox.tsx @@ -10,6 +10,8 @@ import { TChatResponse } from "@/types/chat"; import { Timestamp } from "firebase/firestore"; import ShareModal from "@common/ShareModal"; import useToggle from "@hooks/useToggle"; +import { useNavigate } from "react-router-dom"; +import { useBottomSheet } from "@/store/bottomSheet.store"; interface ChatShareDislikeBoxProps { docId?: string | null; @@ -29,9 +31,18 @@ const ChatShareDislikeBox = (props: ChatShareDislikeBoxProps) => { timestamp: Timestamp; }>(); const { user } = userStore(); - const { roomId } = useChatStore(); + const { roomId, addGuestMessage } = useChatStore(); const userId = user?.uid!; + const { open } = useBottomSheet(); + + const navigate = useNavigate(); + + const goToLogin = () => { + navigate("#login"); + open("login"); + }; + const handleOpenModal = async () => { if (user) { try { @@ -44,7 +55,15 @@ const ChatShareDislikeBox = (props: ChatShareDislikeBoxProps) => { console.error(error); } } else { - console.log("로그인 해야 모달창이 열린단다"); + addGuestMessage({ + type: "bot", + content: { + message: "로그인이 필요한 기능입니다.", + }, + }); + setTimeout(() => { + goToLogin(); + }, 1500); } }; diff --git a/frontend/src/components/login/Login.tsx b/frontend/src/components/login/Login.tsx index c4d0fd5..2116de0 100644 --- a/frontend/src/components/login/Login.tsx +++ b/frontend/src/components/login/Login.tsx @@ -23,7 +23,13 @@ const Login = () => { const [emailError, setEmailError] = useState(""); const [passwordError, setPasswordError] = useState(""); - const { closeAll } = useBottomSheet(); + const { closeAll, open } = useBottomSheet(); + + const goToSignUp = () => { + closeAll(); + navigate("#signup"); + open("login"); + }; // 자동 포커스 const [emailRef, focusEmail, handleEmailKeyPress] = @@ -152,6 +158,12 @@ const Login = () => { onKeyDown={(e) => handlePasswordPress(e, focusFormButton)} /> + + 아이디가 없으신가요? +

{/*로그인 폼 제출 버튼*/} diff --git a/frontend/src/components/signup/SignUpRequired.tsx b/frontend/src/components/signup/SignUpRequired.tsx index f4abe5a..5a40306 100644 --- a/frontend/src/components/signup/SignUpRequired.tsx +++ b/frontend/src/components/signup/SignUpRequired.tsx @@ -8,12 +8,15 @@ import { useInput } from "@hooks/useInput"; import userStore from "@store/auth.store"; import { auth } from "@/firebase"; import useFocus from "@hooks/useFocus"; +import { useBottomSheet } from "@/store/bottomSheet.store"; +import { useNavigate } from "react-router-dom"; const SignUpRequired = () => { const user = auth.currentUser; const { updateUserInfo } = userStore((store) => ({ updateUserInfo: store.updateUserInfo, })); + const { closeAll, open } = useBottomSheet(); const { value: signUpRequired, setValue: setSignUpRequired } = useInput({ email: user?.email || "", password: user ? "blocked" : "", @@ -178,6 +181,14 @@ const SignUpRequired = () => { } }; + const navigate = useNavigate(); + + const goToLogin = () => { + closeAll(); + navigate("#login"); + open("login"); + }; + return ( <>
@@ -276,6 +287,12 @@ const SignUpRequired = () => { />
+ + 이미 아이디가 있으신가요? +
{/*회원가입 다음 페이지로 이동 버튼*/} From d20dc4ce419d2b2f4ee1aced9e43409e82eb0bd2 Mon Sep 17 00:00:00 2001 From: KIMJINYOUNG Date: Thu, 5 Dec 2024 21:01:31 +0900 Subject: [PATCH 02/10] =?UTF-8?q?refactor:=20=EB=A1=9C=EC=BB=AC=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=8B=9C=20=EB=8B=89=EB=84=A4?= =?UTF-8?q?=EC=9E=84=20=ED=91=9C=EC=8B=9C=20=EC=95=88=EB=90=98=EB=8A=94=20?= =?UTF-8?q?=EA=B2=83=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/apis/firebase/auth.ts | 4 ++- frontend/src/components/login/Login.tsx | 27 ++++++++++--------- frontend/src/components/sidemenu/SideMenu.tsx | 5 +++- frontend/src/store/auth.store.ts | 12 ++++++--- 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/frontend/src/apis/firebase/auth.ts b/frontend/src/apis/firebase/auth.ts index 0e24c4c..e583fb1 100644 --- a/frontend/src/apis/firebase/auth.ts +++ b/frontend/src/apis/firebase/auth.ts @@ -32,6 +32,8 @@ const getUserData = async () => { return null; } + const userData = docSnap.data() as TUser; + const likeShoesRef = collection(db, "users", uid, "likeShoes"); const likeShoesSnap = await getDocs(likeShoesRef); const likeShoes = likeShoesSnap.docs.map((doc) => ({ @@ -48,7 +50,7 @@ const getUserData = async () => { return { uid, - ...docSnap.data(), + ...userData, likeShoes, shoeCloset, }; diff --git a/frontend/src/components/login/Login.tsx b/frontend/src/components/login/Login.tsx index 2116de0..72cc280 100644 --- a/frontend/src/components/login/Login.tsx +++ b/frontend/src/components/login/Login.tsx @@ -14,7 +14,7 @@ import useFocus from "@hooks/useFocus"; const Login = () => { const navigate = useNavigate(); - const { updateUserInfo, user, isLoggedIn } = userStore(); + const { updateUserInfo, isLoggedIn } = userStore(); const { roomId, addUserMessage } = useChatStore(); const [loginData, setLoginData] = useState({ email: "", @@ -87,24 +87,25 @@ const Login = () => { //값 확인용 if (isLoginValid) { - await signInWithCredential(loginData).then(() => { - updateUserInfo(); - closeAll(); - navigate("/"); - }); - - // 여기서 왜 isLoggedIn이 false 일까.. - // 루트 경로로 보냈으니 Layout 컴포넌트에서 로그인 상태 변경 해줘야 하는거 아닌가?? - // 일단 급한대로 아래 try문에서 로그인 상태 확인 없이 진행 - console.log(isLoggedIn); + await signInWithCredential(loginData); + // zustand로 관리하는 user가 업데이트가 바로 안이루어져서, + // 임시 방편으로 updateUserInfo 가 userData를 반환하게끔 하고 + // 반환값을 사용하도록 하자 + // 필요한 데이터만 구조분해할당 + const { uid, username } = (await updateUserInfo()) as { + uid: string; + username: string; + }; + closeAll(); + navigate("/"); // 여기서 맞춤상품 api 호출 처리 try { - const loginMent = `반갑습니다 ${user?.username}님! ${user?.username}님을 위한 맞춤 상품을 추천해 드릴께요`; + const loginMent = `반갑습니다 ${username!}님! ${username!}님을 위한 맞춤 상품을 추천해 드릴께요`; const res = await chatApi.getCustomizedProduct(); if (res.status === 200) { - await addMessageToFirestore(user?.uid!, roomId!, "", { + await addMessageToFirestore(uid!, roomId!, "", { message: loginMent, reqProducts: res.data, } as TChatResponse); diff --git a/frontend/src/components/sidemenu/SideMenu.tsx b/frontend/src/components/sidemenu/SideMenu.tsx index 385fbad..f536ef5 100644 --- a/frontend/src/components/sidemenu/SideMenu.tsx +++ b/frontend/src/components/sidemenu/SideMenu.tsx @@ -119,7 +119,10 @@ const SideMenu = ({ await deleteChatRoom(userId, deleteId); const updatedChats = await getUserChatRooms(user?.uid!); setChats(updatedChats); - // 지우려는 방이 현재 속한 방이라면 채팅방의 내용을 가장 최신 채팅으로 업데이트 + + // 지우려는 방이 현재 속한 방이라면 채팅방의 내용을 + // 가장 최신 채팅이 이루어진 채팅방으로 업데이트 + // (채팅방을 삭제했을 때 채팅창에 메세지가 전부 다 사라지면 사용자 경험 측면에서 안좋으니.) if (deleteId === roomId) { loadUserMessages(userId); } diff --git a/frontend/src/store/auth.store.ts b/frontend/src/store/auth.store.ts index 506a75a..0dba059 100644 --- a/frontend/src/store/auth.store.ts +++ b/frontend/src/store/auth.store.ts @@ -39,7 +39,7 @@ interface UserState { likeShoes: likeShoes; // 신발장의 신발들 관리하는 상태 shoeCloset: shoeCloset; - updateUserInfo: () => void; + updateUserInfo: () => Promise; // async 함수는 암묵적으로 Promise를 반환한다. setUserInfo: (key: string, value: string | number) => void; setIsLoggedIn: (state: boolean) => void; } @@ -49,8 +49,9 @@ const userStore = create((set) => ({ user: null, likeShoes: null, shoeCloset: null, - updateUserInfo: () => { - getUserData().then((data) => { + updateUserInfo: async () => { + try { + const data = await getUserData(); if (data) { const { likeShoes, shoeCloset, ...userData } = data; set({ @@ -58,10 +59,13 @@ const userStore = create((set) => ({ likeShoes: likeShoes as likeShoes, shoeCloset: shoeCloset as shoeCloset, }); + return userData; } else { set({ user: null }); } - }); + } catch (error) { + console.error(error); + } }, setUserInfo: (key: string, value: string | number) => { set((user) => ({ ...user, [key]: value })); From 175844f0a0f652b66b3e3cf7542c3dc7ffe36f25 Mon Sep 17 00:00:00 2001 From: KIMJINYOUNG Date: Thu, 5 Dec 2024 21:02:14 +0900 Subject: [PATCH 03/10] =?UTF-8?q?refactor:=20=EC=B1=84=ED=8C=85=EB=B0=A9?= =?UTF-8?q?=20=EC=98=AE=EA=B8=B8=20=EB=95=8C=20=EC=8A=A4=ED=81=AC=EB=A1=A4?= =?UTF-8?q?=20=EC=A0=81=EC=9A=A9=20=EC=95=88=EB=90=98=EB=8A=94=20=EA=B2=83?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/Chat/Chat.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/frontend/src/pages/Chat/Chat.tsx b/frontend/src/pages/Chat/Chat.tsx index 330e800..f99aa7b 100644 --- a/frontend/src/pages/Chat/Chat.tsx +++ b/frontend/src/pages/Chat/Chat.tsx @@ -87,10 +87,7 @@ const Chat = () => { }); }, 0); } - }, [ - isLoggedIn ? userMessages.length : guestMessages.length, - isAllSheetsOpen, - ]); + }, [isLoggedIn ? userMessages : guestMessages.length, isAllSheetsOpen]); return (
From 09bea6c0f5e536f123d4d2bf191f1c109addfeba Mon Sep 17 00:00:00 2001 From: KIMJINYOUNG Date: Thu, 5 Dec 2024 21:02:35 +0900 Subject: [PATCH 04/10] =?UTF-8?q?refactor:=20=EB=AC=B4=ED=95=9C=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=A1=A4=EC=97=90=20=ED=95=84=EC=9A=94=ED=95=9C=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/apis/firebase/chatFirestore.ts | 90 ++++++++++++++++++--- frontend/src/store/chat.store.ts | 59 +++++++++++--- 2 files changed, 129 insertions(+), 20 deletions(-) diff --git a/frontend/src/apis/firebase/chatFirestore.ts b/frontend/src/apis/firebase/chatFirestore.ts index 1065b9b..80003da 100644 --- a/frontend/src/apis/firebase/chatFirestore.ts +++ b/frontend/src/apis/firebase/chatFirestore.ts @@ -14,6 +14,9 @@ import { setDoc, FieldValue, writeBatch, + startAfter, + QueryDocumentSnapshot, + DocumentData, } from "firebase/firestore"; import { TChatResponse } from "@/types/chat"; @@ -26,6 +29,7 @@ export const getMessagesFromLatestRoom = async ( content: string | TChatResponse; id?: string; }[]; + lastVisibleDoc: QueryDocumentSnapshot | null; }> => { const roomsCollection = collection(db, "chatSessions", userId, "rooms"); // 이 코드는 userId라는 도큐먼트의 하위 컬렉션 rooms에 접근하여, @@ -48,7 +52,7 @@ export const getMessagesFromLatestRoom = async ( }); latestRoomId = newRoomRef.id; - return { roomId: latestRoomId, messages: [] }; + return { roomId: latestRoomId, messages: [], lastVisibleDoc: null }; } else { const latestRoom = roomsSnapshot.docs[0]; latestRoomId = latestRoom.id; @@ -62,12 +66,19 @@ export const getMessagesFromLatestRoom = async ( latestRoomId, "messages" ); - const messagesQuery = query(messagesCollection, orderBy("timestamp", "asc")); + const messagesQuery = query( + messagesCollection, + orderBy("timestamp", "desc"), + limit(5) + ); const messagesSnapshot = await getDocs(messagesQuery); - const messages = messagesSnapshot.docs.flatMap((doc) => { + const messages = messagesSnapshot.docs.reverse().flatMap((doc) => { const data = doc.data(); const result = []; + // 질문과 답변을 한쌍으로 저장했기에, 하나의 doc에 대해서 + // bot과 user 메세지 객체를 분리하여 저장한다. + // 이후에 type이 bot인지 user인지에 따라 화면에 그려지는 위치가 정해진다. // user 메시지가 빈 문자열이 아닌 경우에만 추가 if (data.user && data.user.trim() !== "") { @@ -89,7 +100,10 @@ export const getMessagesFromLatestRoom = async ( return result; }); - return { roomId: latestRoomId, messages }; + const lastVisibleDoc = + messagesSnapshot.docs[messagesSnapshot.docs.length - 1] || null; + + return { roomId: latestRoomId, messages, lastVisibleDoc }; }; export const addMessageToFirestore = async ( @@ -133,8 +147,7 @@ export const addMessageToFirestore = async ( // 성공적으로 메시지가 저장되었으므로 doc.id 반환 return docRef.id; } catch (error) { - console.error("메시지 추가 중 에러 발생: ", error); - return null; // 에러 발생 시 null 반환 + throw new Error(); } }; @@ -257,6 +270,7 @@ export const getMessagesByUserIdAndRoomId = async ( content: string | TChatResponse; id?: string; }[]; + lastVisibleDoc: QueryDocumentSnapshot | null; }> => { try { const messagesCollection = collection( @@ -269,11 +283,12 @@ export const getMessagesByUserIdAndRoomId = async ( ); const messagesQuery = query( messagesCollection, - orderBy("timestamp", "asc") + orderBy("timestamp", "desc"), + limit(5) ); const messagesSnapshot = await getDocs(messagesQuery); - const messages = messagesSnapshot.docs.flatMap((doc) => { + const messages = messagesSnapshot.docs.reverse().flatMap((doc) => { const data = doc.data(); const result = []; @@ -295,10 +310,13 @@ export const getMessagesByUserIdAndRoomId = async ( return result; }); - return { roomId, messages }; + const lastVisibleDoc = + messagesSnapshot.docs[messagesSnapshot.docs.length - 1] || null; + + return { roomId, messages, lastVisibleDoc }; } catch (error) { console.error(error); - return { roomId, messages: [] }; + return { roomId, messages: [], lastVisibleDoc: null }; } }; @@ -330,3 +348,55 @@ export const deleteChatRoom = async (userId: string, roomId: string) => { console.error(error); } }; + +// 스크롤 위로 올렸을 때 호출할 함수 +export const getOlderMessages = async ( + userId: string, + roomId: string, + lastVisibleDoc: QueryDocumentSnapshot | null +) => { + const messagesCollection = collection( + db, + "chatSessions", + userId, + "rooms", + roomId, + "messages" + ); + + const messagesQuery = query( + messagesCollection, + orderBy("timestamp", "desc"), + startAfter(lastVisibleDoc), // 마지막 스냅샷 이후부터 가져옴 + limit(5) + ); + + const messagesSnapshot = await getDocs(messagesQuery); + + const messages = messagesSnapshot.docs.reverse().flatMap((doc) => { + const data = doc.data(); + const result = []; + + if (data.user && data.user.trim() !== "") { + result.push({ + type: "user" as const, + content: data.user as string, + }); + } + + if (data.bot) { + result.push({ + type: "bot" as const, + content: data.bot as TChatResponse, + id: doc.id, + }); + } + + return result; + }); + + const newLastVisibleDoc = + messagesSnapshot.docs[messagesSnapshot.docs.length - 1]; + + return { messages, newLastVisibleDoc }; +}; diff --git a/frontend/src/store/chat.store.ts b/frontend/src/store/chat.store.ts index 815b1a8..8c12914 100644 --- a/frontend/src/store/chat.store.ts +++ b/frontend/src/store/chat.store.ts @@ -3,7 +3,9 @@ import { TChatResponse } from "@/types/chat"; import { getMessagesByUserIdAndRoomId, getMessagesFromLatestRoom, + getOlderMessages, } from "@/apis/firebase/chatFirestore"; +import { DocumentData, QueryDocumentSnapshot } from "firebase/firestore"; interface UserMessage { type: "user"; @@ -20,19 +22,22 @@ interface ChatState { guestMessages: (UserMessage | BotMessage)[]; userMessages: (UserMessage | BotMessage)[]; roomId: string | null; + lastVisibleDoc: QueryDocumentSnapshot | null; setRoomId: (roomId: string) => void; addGuestMessage: (message: UserMessage | BotMessage) => void; addUserMessage: (message: UserMessage | BotMessage) => void; loadGuestMessages: () => void; - loadUserMessages: (userId: string) => void; + loadUserMessages: (userId: string) => Promise; getMessagesByRoomId: (userId: string, roomId: string) => void; + loadOlderMessages: (userId: string, roomId: string) => Promise; clearGuestMessages: () => void; } -const useChatStore = create((set) => ({ +const useChatStore = create((set, get) => ({ guestMessages: [], userMessages: [], roomId: null, + lastVisibleDoc: null, // roomId 설정 함수 setRoomId: (roomId: string) => set({ roomId }), @@ -62,7 +67,8 @@ const useChatStore = create((set) => ({ // 회원 메시지 로드 (Firestore에서) loadUserMessages: async (userId: string) => { - const { roomId, messages } = await getMessagesFromLatestRoom(userId); + const { roomId, messages, lastVisibleDoc } = + await getMessagesFromLatestRoom(userId); // 어디서부터 꼬인건지.. 일단 여기서 이렇게 해줘야 에러가 안나긴 한다. 나중에 찾아보자.. const formattedMessages = messages.map((msg) => { @@ -79,14 +85,16 @@ const useChatStore = create((set) => ({ } as UserMessage; } }); - - set({ roomId, userMessages: formattedMessages }); + set({ roomId, userMessages: formattedMessages, lastVisibleDoc }); }, // userId와 roomId를 인자로 받아 그에 해당하는 메세지를 가져오는 함수 getMessagesByRoomId: async (userId: string, roomId: string) => { - const { roomId: fetchedRoomId, messages } = - await getMessagesByUserIdAndRoomId(userId, roomId); + const { + roomId: fetchedRoomId, + messages, + lastVisibleDoc, + } = await getMessagesByUserIdAndRoomId(userId, roomId); // 어디서부터 꼬인건지.. 일단 여기서 이렇게 해줘야 에러가 안나긴 한다. 나중에 찾아보자.. const formattedMessages = messages.map((msg) => { @@ -103,10 +111,41 @@ const useChatStore = create((set) => ({ } as UserMessage; } }); - console.log(formattedMessages); - console.log(fetchedRoomId); - set({ roomId: fetchedRoomId, userMessages: formattedMessages }); + set({ + roomId: fetchedRoomId, + userMessages: formattedMessages, + lastVisibleDoc, + }); + }, + + loadOlderMessages: async (userId: string, roomId: string) => { + const { lastVisibleDoc } = get(); + if (!lastVisibleDoc) return; // 마지막 메시지가 없으면 더 이상 로드하지 않음 + const { messages, newLastVisibleDoc } = await getOlderMessages( + userId, + roomId, + lastVisibleDoc + ); + + const formattedMessages = messages.map((msg) => { + if (msg.type === "bot") { + return { + type: "bot", + content: msg.content, + id: msg.id, + } as BotMessage; + } else { + return { + type: "user", + content: msg.content, + } as UserMessage; + } + }); + set((state) => ({ + userMessages: [...formattedMessages, ...state.userMessages], + lastVisibleDoc: newLastVisibleDoc, + })); }, // 비회원 메시지 비우기 (로그인 시) From f44332e22d4dab322427af0674f59077d8861072 Mon Sep 17 00:00:00 2001 From: KIMJINYOUNG Date: Fri, 6 Dec 2024 00:47:10 +0900 Subject: [PATCH 05/10] =?UTF-8?q?refactor:=20=EB=AC=B4=ED=95=9C=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=A1=A4(=ED=9D=89=EB=82=B4=20=EB=82=B4=EB=B4=84)=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/Chat/Chat.tsx | 50 +++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/frontend/src/pages/Chat/Chat.tsx b/frontend/src/pages/Chat/Chat.tsx index f99aa7b..f7c04ea 100644 --- a/frontend/src/pages/Chat/Chat.tsx +++ b/frontend/src/pages/Chat/Chat.tsx @@ -1,4 +1,4 @@ -import { useEffect, useLayoutEffect, useRef } from "react"; +import { useEffect, useLayoutEffect, useRef, useState } from "react"; import { motion } from "framer-motion"; import ChatInput from "@components/Chat/ChatInput"; import ChatMessage from "@components/Chat/ChatMessage"; @@ -17,8 +17,14 @@ import { useBottomSheet } from "@store/bottomSheet.store"; import ChatSampleQuestions from "@components/Chat/ChatSampleQuestions"; const Chat = () => { - const { guestMessages, userMessages, loadGuestMessages, loadUserMessages } = - useChatStore(); + const { + guestMessages, + userMessages, + roomId, + loadGuestMessages, + loadUserMessages, + loadOlderMessages, + } = useChatStore(); const { clickedProducts, clickedBrand, setClickedProducts, setClickedBrand } = productAndBrandStore(); @@ -75,11 +81,37 @@ const Chat = () => { }, [isLoggedIn, userId]); const mainRef = useRef(null); + const [isLoadingOlderMessages, setIsLoadingOlderMessages] = useState(false); + const handleScroll = () => { + if (mainRef.current) { + const { scrollTop } = mainRef.current; + if (scrollTop === 0) { + setIsLoadingOlderMessages(true); + setTimeout(() => { + loadOlderMessages(userId!, roomId!).finally(() => { + setIsLoadingOlderMessages(false); + }); + }, 1000); + } + } + }; + + // roomId가 비동기적으로(?) update 돼서 roomId가 제대로 들어왔을 때만 동작하게끔 + useEffect(() => { + const mainElement = mainRef.current; + if (mainElement && roomId) { + mainElement.addEventListener("scroll", handleScroll); + + return () => { + mainElement.removeEventListener("scroll", handleScroll); + }; + } + }, [roomId]); // 스크롤을 항상 하단에 위치시키기 useLayoutEffect(() => { // 바텀 오픈 X 일 경우 - if (!isAllSheetsOpen) { + if (!isAllSheetsOpen && !isLoadingOlderMessages) { setTimeout(() => { mainRef.current?.scrollTo({ top: mainRef.current.scrollHeight, @@ -97,6 +129,16 @@ const Chat = () => { {/* 현재 질문 가능한 목록 */} + {isLoadingOlderMessages && ( +
+
+
+
+
+
+
+ )} +
{!isLoggedIn && } From 1f8201e00e46a3420c40494959827379e3a721bc Mon Sep 17 00:00:00 2001 From: KIMJINYOUNG Date: Fri, 6 Dec 2024 17:46:55 +0900 Subject: [PATCH 06/10] =?UTF-8?q?refactor:=20=EC=B1=84=ED=8C=85=EC=B0=BD?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=82=AC=EC=9A=A9=EB=90=98=EB=8A=94=20Cha?= =?UTF-8?q?tLoading=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Chat/ChatLoading.tsx | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 frontend/src/components/Chat/ChatLoading.tsx diff --git a/frontend/src/components/Chat/ChatLoading.tsx b/frontend/src/components/Chat/ChatLoading.tsx new file mode 100644 index 0000000..087b3f5 --- /dev/null +++ b/frontend/src/components/Chat/ChatLoading.tsx @@ -0,0 +1,12 @@ +const ChatLoading = () => { + return ( +
+
+
+
+
+
+
+ ); +}; +export default ChatLoading; From 2929bbacecf7fe3e02dc1556be0b59b34b4dd859 Mon Sep 17 00:00:00 2001 From: KIMJINYOUNG Date: Fri, 6 Dec 2024 17:48:30 +0900 Subject: [PATCH 07/10] =?UTF-8?q?refactor:=20=EB=A1=9C=EB=94=A9=EC=97=90?= =?UTF-8?q?=20=ED=95=84=EC=9A=94=ED=95=9C=20state=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/layout/Layout.tsx | 15 ++++-- frontend/src/pages/Chat/Chat.tsx | 57 ++++++++++++----------- frontend/src/types/chat.d.ts | 4 ++ 3 files changed, 47 insertions(+), 29 deletions(-) diff --git a/frontend/src/components/layout/Layout.tsx b/frontend/src/components/layout/Layout.tsx index f0244e2..9bd62aa 100644 --- a/frontend/src/components/layout/Layout.tsx +++ b/frontend/src/components/layout/Layout.tsx @@ -1,7 +1,7 @@ import { auth } from "@/firebase"; import userStore from "@/store/auth.store"; import { onAuthStateChanged } from "firebase/auth"; -import { useEffect } from "react"; +import { useEffect, useState } from "react"; import { Outlet } from "react-router-dom"; const Layout = () => { @@ -10,23 +10,32 @@ const Layout = () => { setIsLoggedIn: store.setIsLoggedIn, })); + const [isAuthLoading, setIsAuthLoading] = useState(true); + + // onAuthStateChanged는 Firebase Auth가 제공하는 상태 변화 감지 메서드 + // 사용자가 로그인하거나 로그아웃할 때 이벤트를 트리거 + // user 객체는 로그인된 사용자의 정보이며, 로그아웃 상태일 때는 null + // unmount시 Firebase Auth의 상태 변화 구독을 중지 + // 이를 통해 메모리 누수와 불필요한 상태 업데이트를 방지 useEffect(() => { const unsubscribe = onAuthStateChanged(auth, (user) => { if (user) { setIsLoggedIn(true); updateUserInfo(); } else { + // 로그인 된 상태면 여기 안탄다.(깜빡임도 존재하지 않음) setIsLoggedIn(false); } + setIsAuthLoading(false); }); return () => unsubscribe(); - }, [setIsLoggedIn, updateUserInfo]); + }, []); return (
- +
); diff --git a/frontend/src/pages/Chat/Chat.tsx b/frontend/src/pages/Chat/Chat.tsx index f7c04ea..f93cebd 100644 --- a/frontend/src/pages/Chat/Chat.tsx +++ b/frontend/src/pages/Chat/Chat.tsx @@ -4,7 +4,7 @@ import ChatInput from "@components/Chat/ChatInput"; import ChatMessage from "@components/Chat/ChatMessage"; import ChatUserMessage from "@components/Chat/ChatUserMessage"; import Header from "@common/Header"; -import { TChatResponse } from "@type/chat"; +import { OutletContextType, TChatResponse } from "@type/chat"; import ChatLogin from "@components/Chat/ChatLogin"; import ChatRecommendedQuestion from "@components/Chat/ChatRecommendedQuestion"; import LoginBottomSheet from "@components/login/LoginBottomSheet"; @@ -15,6 +15,8 @@ import productAndBrandStore from "@store/productAndBrand.store"; import InterestKeywordsBottomSheet from "@components/Chat/InterestKeywordsBottomSheet"; import { useBottomSheet } from "@store/bottomSheet.store"; import ChatSampleQuestions from "@components/Chat/ChatSampleQuestions"; +import { useOutletContext } from "react-router-dom"; +import ChatLoading from "@/components/Chat/ChatLoading"; const Chat = () => { const { @@ -82,6 +84,7 @@ const Chat = () => { const mainRef = useRef(null); const [isLoadingOlderMessages, setIsLoadingOlderMessages] = useState(false); + const handleScroll = () => { if (mainRef.current) { const { scrollTop } = mainRef.current; @@ -119,7 +122,11 @@ const Chat = () => { }); }, 0); } - }, [isLoggedIn ? userMessages : guestMessages.length, isAllSheetsOpen]); + // isAllSheetsOpen 를 의존성 배열에 넣으면, 바텀시트 닫을 때 스크롤이 최하단으로 움직여서 일단 뺌 + }, [userMessages, guestMessages]); + + // 로그인 된 유저가 새로고침할 때 생기는 깜빡임을 제어할 state + const { isAuthLoading } = useOutletContext(); return (
@@ -129,32 +136,30 @@ const Chat = () => { {/* 현재 질문 가능한 목록 */} - {isLoadingOlderMessages && ( -
-
-
-
-
-
-
- )} + {/* 이전 메세지를 보이는 UI */} + {isLoadingOlderMessages && }
- {!isLoggedIn && } - - {(isLoggedIn ? userMessages : guestMessages).map((msg, index) => ( -
- {msg.type === "user" ? ( - - ) : ( - - )} -
- ))} - {/*
*/} + {isAuthLoading ? ( + + ) : ( + <> + {!isLoggedIn && } + + {(isLoggedIn ? userMessages : guestMessages).map((msg, index) => ( +
+ {msg.type === "user" ? ( + + ) : ( + + )} +
+ ))} + + )}
diff --git a/frontend/src/types/chat.d.ts b/frontend/src/types/chat.d.ts index 2823cf1..2f9d3f4 100644 --- a/frontend/src/types/chat.d.ts +++ b/frontend/src/types/chat.d.ts @@ -28,3 +28,7 @@ export type TChatResponse = { productId: string; }[]; }; + +export type OutletContextType = { + isAuthLoading: boolean; +}; From 252fd7b80df33a4e6c9ad6eb6c23cff551c24520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=99=8D=EC=84=B1=EC=88=99?= <134491629+SSUK-H@users.noreply.github.com> Date: Sat, 8 Feb 2025 21:53:39 +0900 Subject: [PATCH 08/10] =?UTF-8?q?chore:=20vite.congif.ts=20=EB=B0=B0?= =?UTF-8?q?=ED=8F=AC=20=EC=8B=9C=20console.log=20=EB=B0=8F=20debugger=20?= =?UTF-8?q?=EC=9E=90=EB=8F=99=20=EC=A0=9C=EA=B1=B0=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20#165=20(#166)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/vite.config.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 53cab5c..4af401e 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -4,7 +4,11 @@ import tsconfigPaths from "vite-tsconfig-paths"; import svgr from "vite-plugin-svgr"; // https://vitejs.dev/config/ -export default defineConfig({ +export default defineConfig(({ mode }) => ({ plugins: [react(), tsconfigPaths(), svgr()], base: "/stepup_front", -}); + esbuild: { + drop: ["debugger"], + pure: mode === "production" ? ["console.log"] : [], + }, +})); From 8affc9ade1a5a3b693464466e1fa36ded8e1616c Mon Sep 17 00:00:00 2001 From: Wonju <128772605+oneju@users.noreply.github.com> Date: Sat, 8 Feb 2025 21:54:06 +0900 Subject: [PATCH 09/10] =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=ED=9A=8C?= =?UTF-8?q?=EC=9B=90=EA=B0=80=EC=9E=85=20=EC=88=98=EC=A0=95=20(#164)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update: Add check email valid * update: Fix login Error * fix: Remove test log --- frontend/src/apis/firebase/auth.ts | 25 +++-- frontend/src/components/Chat/ChatLoading.tsx | 6 +- .../src/components/common/html/DropDown.tsx | 1 - frontend/src/components/common/html/Input.tsx | 6 +- frontend/src/components/login/Login.tsx | 20 ++-- .../src/components/signup/SignUpRequired.tsx | 99 ++++++++++--------- frontend/src/styles/tailwind.css | 3 + 7 files changed, 98 insertions(+), 62 deletions(-) diff --git a/frontend/src/apis/firebase/auth.ts b/frontend/src/apis/firebase/auth.ts index e583fb1..78ca45d 100644 --- a/frontend/src/apis/firebase/auth.ts +++ b/frontend/src/apis/firebase/auth.ts @@ -12,8 +12,10 @@ import { doc, getDoc, getDocs, + query, setDoc, updateDoc, + where, } from "firebase/firestore"; interface UserTypeforSignup { @@ -69,25 +71,24 @@ const updateUserData = async (key: string, value: string | number) => { const signUpWithCredential = async (user: UserTypeforSignup & TUser) => { const { email, password, ...rest } = user; - await createUserWithEmailAndPassword(auth, email, password) - .then((credential) => { + await createUserWithEmailAndPassword(auth, email, password).then( + (credential) => { setDoc(doc(db, "users", credential.user.uid), { ...rest, + email: email, imgUrl: "", sizeType: null, sneakerSize: 0, }); - }) - .catch((e) => alert(e)); + } + ); }; const signInWithCredential = async (user: { email: string; password: string; }) => { - await signInWithEmailAndPassword(auth, user.email, user.password) - .then() - .catch((e) => alert(e.message)); + await signInWithEmailAndPassword(auth, user.email, user.password); }; const signInWithGoogle = async () => { @@ -96,6 +97,7 @@ const signInWithGoogle = async () => { const isNew = await signInWithPopup(auth, provider) .then((credential) => { setDoc(doc(db, "users", credential.user.uid), { + email: credential.user.email, username: credential.user.displayName, gender: null, birthDate: "", @@ -120,6 +122,14 @@ const logOut = async () => { .catch((e) => alert(e.message)); }; +const availableAccount = async (email: string) => { + const docRef = collection(db, "users"); + const q = query(docRef, where("email", "==", email)); + const querySnapshot = await getDocs(q); + + return querySnapshot.empty; +}; + export { getUserData, updateUserData, @@ -127,4 +137,5 @@ export { signInWithCredential, signInWithGoogle, logOut, + availableAccount, }; diff --git a/frontend/src/components/Chat/ChatLoading.tsx b/frontend/src/components/Chat/ChatLoading.tsx index 087b3f5..7dd0827 100644 --- a/frontend/src/components/Chat/ChatLoading.tsx +++ b/frontend/src/components/Chat/ChatLoading.tsx @@ -2,9 +2,9 @@ const ChatLoading = () => { return (
-
-
-
+
+
+
); diff --git a/frontend/src/components/common/html/DropDown.tsx b/frontend/src/components/common/html/DropDown.tsx index e8e92d9..d27336e 100644 --- a/frontend/src/components/common/html/DropDown.tsx +++ b/frontend/src/components/common/html/DropDown.tsx @@ -41,7 +41,6 @@ const DropDown = forwardRef((props, ref) => { setIsOpen(false); if (onChange) { onChange(value); - console.log(value); } }; diff --git a/frontend/src/components/common/html/Input.tsx b/frontend/src/components/common/html/Input.tsx index d98f055..415e536 100644 --- a/frontend/src/components/common/html/Input.tsx +++ b/frontend/src/components/common/html/Input.tsx @@ -8,7 +8,11 @@ const Input = forwardRef((props, ref) => { return ( <> diff --git a/frontend/src/components/login/Login.tsx b/frontend/src/components/login/Login.tsx index 72cc280..a17d7b1 100644 --- a/frontend/src/components/login/Login.tsx +++ b/frontend/src/components/login/Login.tsx @@ -45,8 +45,8 @@ const Login = () => { [name]: value, }); - if (name === "email") setEmailError(""); - if (name === "password") setPasswordError(""); + setEmailError(""); + setPasswordError(""); }; const submitHandle = async (e: React.FormEvent) => { @@ -87,7 +87,16 @@ const Login = () => { //값 확인용 if (isLoginValid) { - await signInWithCredential(loginData); + await signInWithCredential(loginData) + .then(() => { + closeAll(); + navigate("/"); + }) + .catch(() => { + setEmailError("이메일을 확인해주세요."); + setPasswordError("비밀번호를 확인해주세요."); + }); + // zustand로 관리하는 user가 업데이트가 바로 안이루어져서, // 임시 방편으로 updateUserInfo 가 userData를 반환하게끔 하고 // 반환값을 사용하도록 하자 @@ -96,8 +105,6 @@ const Login = () => { uid: string; username: string; }; - closeAll(); - navigate("/"); // 여기서 맞춤상품 api 호출 처리 try { @@ -118,7 +125,6 @@ const Login = () => { }); } } catch (error) { - console.log(error); const errorMessage = "예기치 못한 에러가 발생하였습니다. 다시 시도해주세요."; if (isLoggedIn) { @@ -137,6 +143,7 @@ const Login = () => { { { const [userNameRef, focusUserName, handleUserNamePress] = useFocus(); const [genderRef, focusGender] = useFocus(); - const [birthYearRef, focusBirthYear] = useFocus(); - const [birthMonthRef, focusBirthMonth] = useFocus(); - const [birthDayRef, focusBirthDay] = useFocus(); const genderOptions: { value: string; label: string }[] = [ { value: "남성", label: "남성" }, @@ -96,74 +97,69 @@ const SignUpRequired = () => { if (name === "username") setnameError(""); }; - const submitHandle = (e: React.FormEvent) => { - e.preventDefault(); - + const checkValidate = () => { + let isvalid = true; const validateEmail = (email: string) => { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(email)) { focusEmail(); // 이메일 필드 자동 포커스 setEmailError("이메일 형식을 확인해주세요"); - isSignUpRequiredValid = false; - return false; - } else { - setEmailError(""); - return true; } }; - let isSignUpRequiredValid = true; - if (!signUpRequired.email) { //아이디 비어있을 때 - if (isSignUpRequiredValid) focusEmail(); // 이메일 필드 자동 포커스 - + focusEmail(); // 이메일 필드 자동 포커스 setEmailError("아이디를 입력하세요"); - isSignUpRequiredValid = false; - } else if (validateEmail(signUpRequired.email)) { - isSignUpRequiredValid = true; - } + isvalid = false; + } else if (emailError.length > 0) { + focusEmail(); + isvalid = false; + } else validateEmail(signUpRequired.email); if (!signUpRequired.password) { //비밀번호 비어있을 때 - if (isSignUpRequiredValid) focusPassword(); // 비밀번호 필드 자동 포커스 - + if (isvalid) focusPassword(); // 비밀번호 필드 자동 포커스 + isvalid = false; setPasswordError("비밀번호를 입력하세요"); - isSignUpRequiredValid = false; } if (!signUpRequired.username) { - if (isSignUpRequiredValid) focusUserName(); // 이름 필드 자동 포커스 - + if (isvalid) focusUserName(); // 이름 필드 자동 포커스 + isvalid = false; setnameError("이름을 입력하세요"); - isSignUpRequiredValid = false; } if (!signUpRequired.gender) { - if (isSignUpRequiredValid) focusGender(); // 성별 필드 자동 포커스 - + if (isvalid) focusGender(); // 성별 필드 자동 포커스 + isvalid = false; setGenderError("성별을 입력하세요"); - isSignUpRequiredValid = false; } if (!signUpRequired.birthDate) { if (!birthYear) { - focusBirthYear(); // 년도 필드에 포커스 + // focusBirthYear(); // 년도 필드에 포커스 setBirthDateError("년도를 선택하세요"); - isSignUpRequiredValid = false; } else if (!birthMonth) { - focusBirthMonth(); // 월 필드에 포커스 + // focusBirthMonth(); // 월 필드에 포커스 setBirthDateError("월을 선택하세요"); - isSignUpRequiredValid = false; } else if (!birthDay) { - focusBirthDay(); // 일 필드에 포커스 + // focusBirthDay(); // 일 필드에 포커스 setBirthDateError("일을 선택하세요"); - isSignUpRequiredValid = false; } } + }; - //값 확인용 - if (isSignUpRequiredValid) { + const submitHandle = (e: React.FormEvent) => { + e.preventDefault(); + + if ( + emailError.length === 0 && + passwordError.length === 0 && + genderError.length === 0 && + birthDateError.length === 0 && + nameError.length === 0 + ) { if (user) { updateUserData("gender", signUpRequired.gender); updateUserData("birthDate", signUpRequired.birthDate); @@ -177,7 +173,15 @@ const SignUpRequired = () => { gender: signUpRequired.gender === "남성" ? "male" : "female", username: signUpRequired.username, birthDate: signUpRequired.birthDate, - }).then(updateUserInfo); + }) + .then(updateUserInfo) + .catch((data) => { + if (data.code === "auth/email-already-in-use") + setEmailError("이미 사용중인 이메일입니다"); + else if (data.code === "auth/weak-password") { + setPasswordError("비밀번호는 6자 이상이어야합니다"); + } + }); } }; @@ -200,11 +204,19 @@ const SignUpRequired = () => { type="email" name="email" placeholder={user?.email || "이메일을 입력해주세요"} - className="h-[48px] w-full rounded-[4px] px-4 py-[14px]" + className={`py-[14px h-[48px] w-full rounded-[4px] px-4`} + isErrored={emailError} value={user?.email ? "" : signUpRequired.email} onChange={handleInputChange} disabled={user?.email ? true : false} onKeyDown={(e) => handleEmailPress(e, focusPassword)} // 다음 패스워드 포커스 + onBlur={async (e) => { + const isAvailable = await availableAccount(e.target.value); + + if (!isAvailable) { + setEmailError("이미 사용중인 이메일입니다"); + } + }} /> {/*패스워드 입력 필드*/} @@ -213,6 +225,7 @@ const SignUpRequired = () => { ref={passwordRef} type="password" name="password" + isErrored={passwordError} placeholder={ user?.email ? "소셜 로그인 회원입니다." @@ -231,6 +244,7 @@ const SignUpRequired = () => { ref={userNameRef} type="text" name="username" + isErrored={nameError} placeholder={user?.displayName || "이름을 입력해주세요"} className="h-[48px] w-full rounded-[4px] px-4 py-[14px]" value={user?.displayName ? "" : signUpRequired.username} @@ -253,18 +267,16 @@ const SignUpRequired = () => {
b.value - a.value)} onChange={(value) => { setBirthYear(value); updateBirthDate(value, birthMonth, birthDay); }} /> { }} /> {
{/*회원가입 다음 페이지로 이동 버튼*/} - +
diff --git a/frontend/src/styles/tailwind.css b/frontend/src/styles/tailwind.css index 2881ba1..7994839 100644 --- a/frontend/src/styles/tailwind.css +++ b/frontend/src/styles/tailwind.css @@ -8,6 +8,9 @@ html { font-family: "Pretendard Variable", system-ui, sans-serif; } + input{ + outline: none; + } } /* Custom CSS */ From 077725bb590c0a19f019c0a64923db1e720befa0 Mon Sep 17 00:00:00 2001 From: Wonju Date: Thu, 20 Feb 2025 22:22:12 +0900 Subject: [PATCH 10/10] =?UTF-8?q?fix:=20build=20error=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit + input 타입 수정 + 기타 build, lint 교정 --- frontend/src/components/Chat/ChatLoading.tsx | 6 +++--- frontend/src/components/common/html/Input.tsx | 4 ++-- frontend/src/components/login/Login.tsx | 6 +++--- .../src/components/login/LoginBottomSheet.tsx | 2 +- frontend/src/components/signup/SignUp.tsx | 4 ++-- .../src/components/signup/SignUpRequired.tsx | 19 +++++++++++-------- 6 files changed, 22 insertions(+), 19 deletions(-) diff --git a/frontend/src/components/Chat/ChatLoading.tsx b/frontend/src/components/Chat/ChatLoading.tsx index 7dd0827..09482b0 100644 --- a/frontend/src/components/Chat/ChatLoading.tsx +++ b/frontend/src/components/Chat/ChatLoading.tsx @@ -1,10 +1,10 @@ const ChatLoading = () => { return ( -
+
-
-
+
+
); diff --git a/frontend/src/components/common/html/Input.tsx b/frontend/src/components/common/html/Input.tsx index 415e536..86b6ae9 100644 --- a/frontend/src/components/common/html/Input.tsx +++ b/frontend/src/components/common/html/Input.tsx @@ -1,7 +1,7 @@ import { ComponentPropsWithoutRef, forwardRef } from "react"; import { twMerge } from "tailwind-merge"; -type InputProps = ComponentPropsWithoutRef<"input">; +type InputProps = ComponentPropsWithoutRef<"input"> & { isErrored?: boolean }; const Input = forwardRef((props, ref) => { const { className, ...rest } = props; @@ -15,7 +15,7 @@ const Input = forwardRef((props, ref) => { )} ref={ref} {...rest} - > + /> ); }); diff --git a/frontend/src/components/login/Login.tsx b/frontend/src/components/login/Login.tsx index ea75d44..ef03017 100644 --- a/frontend/src/components/login/Login.tsx +++ b/frontend/src/components/login/Login.tsx @@ -96,7 +96,6 @@ const Login = () => { setEmailError("이메일을 확인해주세요."); setPasswordError("비밀번호를 확인해주세요."); }); - // zustand로 관리하는 user가 업데이트가 바로 안이루어져서, // 임시 방편으로 updateUserInfo 가 userData를 반환하게끔 하고 // 반환값을 사용하도록 하자 @@ -125,6 +124,7 @@ const Login = () => { }); } } catch (error) { + console.log(error); const errorMessage = "예기치 못한 에러가 발생하였습니다. 다시 시도해주세요."; if (isLoggedIn) { @@ -143,7 +143,7 @@ const Login = () => { { { const location = useLocation(); diff --git a/frontend/src/components/signup/SignUp.tsx b/frontend/src/components/signup/SignUp.tsx index 78e7add..7b53068 100644 --- a/frontend/src/components/signup/SignUp.tsx +++ b/frontend/src/components/signup/SignUp.tsx @@ -1,5 +1,5 @@ -import SignUpRequired from "./SignUpRequired"; -import SignUpAdditional from "./SignUpAdditional"; +import SignUpRequired from "@components/signUp/SignUpRequired"; +import SignUpAdditional from "@components/signUp/SignUpAdditional"; import userStore from "@store/auth.store.ts"; import { redirect } from "react-router-dom"; diff --git a/frontend/src/components/signup/SignUpRequired.tsx b/frontend/src/components/signup/SignUpRequired.tsx index 72a5c12..873831d 100644 --- a/frontend/src/components/signup/SignUpRequired.tsx +++ b/frontend/src/components/signup/SignUpRequired.tsx @@ -56,7 +56,7 @@ const SignUpRequired = () => { const generateYearOptions = (startYear: number, endYear: number) => { const options: { value: string; label: string }[] = []; - for (let year = startYear; year <= endYear; year++) { + for (let year = endYear; year >= startYear; year--) { options.push({ value: year.toString(), label: year.toString() }); } return options; @@ -163,7 +163,7 @@ const SignUpRequired = () => { if (user) { updateUserData("gender", signUpRequired.gender); updateUserData("birthDate", signUpRequired.birthDate); - + console.log(166); updateUserInfo(); } else signUpWithCredential({ @@ -174,7 +174,10 @@ const SignUpRequired = () => { username: signUpRequired.username, birthDate: signUpRequired.birthDate, }) - .then(updateUserInfo) + .then(() => { + updateUserInfo(); + console.log(179); + }) .catch((data) => { if (data.code === "auth/email-already-in-use") setEmailError("이미 사용중인 이메일입니다"); @@ -204,8 +207,8 @@ const SignUpRequired = () => { type="email" name="email" placeholder={user?.email || "이메일을 입력해주세요"} - className={`py-[14px h-[48px] w-full rounded-[4px] px-4`} - isErrored={emailError} + className={`h-[48px] w-full rounded-[4px] px-4 py-[14px]`} + isErrored={!!emailError} value={user?.email ? "" : signUpRequired.email} onChange={handleInputChange} disabled={user?.email ? true : false} @@ -225,7 +228,7 @@ const SignUpRequired = () => { ref={passwordRef} type="password" name="password" - isErrored={passwordError} + isErrored={!!passwordError} placeholder={ user?.email ? "소셜 로그인 회원입니다." @@ -244,7 +247,7 @@ const SignUpRequired = () => { ref={userNameRef} type="text" name="username" - isErrored={nameError} + isErrored={!!nameError} placeholder={user?.displayName || "이름을 입력해주세요"} className="h-[48px] w-full rounded-[4px] px-4 py-[14px]" value={user?.displayName ? "" : signUpRequired.username} @@ -270,7 +273,7 @@ const SignUpRequired = () => { className="h-[45px] gap-2 rounded-[6px] border-[#E4E4E7] px-[10px] py-[14px]" menuPlacement="top" placeholder="년" - options={birthYearOptions.sort((a, b) => b.value - a.value)} + options={birthYearOptions} onChange={(value) => { setBirthYear(value); updateBirthDate(value, birthMonth, birthDay);