Conversation
* feat: bottom-sheet 컴포넌트 제작 * design: sheet boutton에 포인터 추가, text 위치 수정 * feat: text들을 prop 전달 가능 * feat: item 클릭 이벤트 * refactor: 애니메이션 라이브러리 교체 (tw-animate-css → tailwindcss-animate) - tw-animate-css 제거 - tailwindcss-animate 플러그인 추가 - 애니메이션 유틸리티 설정 업데이트 * refactor: test 페이지 버튼 아이콘 수정 * feat: 선택된 값을 trigger 텍스트에 표시 * feat: 선택된 값 bottomSheet에 표시 * feat: bottomSheet 너비 설정 * remove: 불필요한 dev 태그 삭제 * refactor: onSelect() 인라인으로 코드 수정 * design: 부모 기준으로 위치시킴 * feat: 토글 기능 추가 --------- Co-authored-by: hgTime <hgtime@gmail.com>
…rontend into feat/chat-filter
…t/zoop-frontend into feat/chat-filter
* feat: 부동산 페이지 퍼블리싱 1차 * design: 부동산 정보영역 퍼블리싱 * design: 탭, 리스트 영역 추가 * feat: 더보기 버튼 수정 * design: 버튼 추가 * design: 버튼 뒤 흰 배경 * design: 버튼 위치 수정 * design: 버튼 속성 수정 * design: 버튼 수정 * design: 불필요한 클래스 제거 * style: 변수명 수정(대소문자)
* design: 내정보 페이지 퍼블리싱 * design: 닉네임 수정 페이지 퍼블리싱 * style: 함수명수정 * design: 정보수정 페이지 퍼블리싱 * design: 내정보 스타일가이드 적용 * design: 스타일 가이드 적용 * design: 아이콘 변경 * style: 함수 선언방식 통일 * feat: input maxlength설정 * style: Image컴포넌트 적용 * design: 폰트 수정 * style: 불필요한 코드 수정 * rename: 폴더 구조 수정
* design: 내가쓴글 페이지 퍼블리싱 * design: 컴포넌트 통합(리뷰/댓글) * style: 명칭 수정 * fix: 타입에러 수정 * design: 디자인 수정 * design: 문구 추가 * feat: 리뷰 클릭 시 리뷰 페이지로 이동 * style: 함수선언방식 통일 * rename: 폴더구조 수정
* feat: 공통컴포넌트 매물카드 * fix: 매물카드 데이터 수정 * feat: 매물 정보 데이터 분리, 상세페이지로 이동 * rename: 예시코드 test 페이지로 이동 * feat: 좋아요 버튼 on/off * reaname: 이미지 파일명 수정 * style: 태그 높이 고정 * feat: 태그 최대 한줄로 고정 * style: 코드 포맷팅 * style: tailwind 스타일가이드 적용 * fix: metadata 에러 수정 * feat: 말줄임표 처리 개선 * feat: 찜 기능 분리(컴포넌트/훅) * remove: 불필요한 코드 제거 * rename: 파일 위치 변경 * design: 거래완료 디자인 * style: 변수명,타입 수정(small->size) * style: 테스트 페이지 수정 * Merge branch 'dev'
…t/zoop-frontend into feat/chat-filter
| import { UserNickname } from "@/types/user"; | ||
| import axiosInstance from "../utils/axiosInstance"; | ||
|
|
||
| export const createUserNickname = async (nickname: string): Promise<UserNickname> => { |
There was a problem hiding this comment.
API 전체적으로 타입 추론이 return 단위가 아닌, axiosInstance단에서 제네릭으로 되면 좋을 것 같습니다!
추가로 특정 API의 return 타입도 여기 파일 내에 함께 존재하는 게 응집도가 좋을 것 같아요
| const response = await axiosInstance.get("/users/auth/me"); | ||
| const data = response.data; | ||
|
|
||
| console.log("로그인 된 유저 data확인::", data); |
| // ✅ Zustand 저장 | ||
| const setUser = useUserInfoStore.getState().setUser; | ||
| setUser({ | ||
| userId: data.userId, | ||
| email: data.email, | ||
| nickname: data.nickname, | ||
| profileImage: data.profileImage, | ||
| }); |
There was a problem hiding this comment.
하나의 함수가 여러 역할을 하고 있어요.
그래서 일반 함수 내에 훅 이름을 가지니 더 어색해보입니다.
유저 정보를 가져오는 API와 해당 값을 받아 초기에 처리해주는 store custom hook이 존재하고 그걸 가장 첫 포인트 (root layout) 같은 데서 지정하는 것도 좋을 것 같아요
|
|
||
| const fetchPostComment = async () => { | ||
| const res = await axiosInstance.get("/mypage/comments"); | ||
| return res.data.data || []; |
There was a problem hiding this comment.
해당 API는 타입정의가 없어 추론이 안될 것 같아요! (비슷한 파일이 많아 확인 부탁드립니다)
추가로 falsy값에 대한 기본값을 선호하지 않습니다! (의도적으로 빈건지 유무를 알 수 없음)
|
|
||
| export const fetchReviewList = async ( | ||
| propertyId: number, | ||
| params?: { sort?: "like" | "latest" }, |
| strategy="beforeInteractive" | ||
| /> | ||
| <Providers> | ||
| <AuthGuardWrapper> |
There was a problem hiding this comment.
Auth 가드 처리는 middleware를 활용하시면 좋을 것 같아요!
|
|
||
| const handleSubmit = async () => { | ||
| try { | ||
| const userData = await getUserInfo(); |
| const userData = await getUserInfo(); | ||
|
|
||
| setUser(userData); // Zustand에 유저 정보 저장 |
There was a problem hiding this comment.
만약 유저 닉네임 처리를 하면 user 정보가 업데이트하는거라면 키 만료하는 것도 좋을 것 같습니다!
root/layout.tsx에서 바로 유저 정보 저장하는것도 좋을 것 같아요
|
리뷰 진행중 입니다! 파일 개수가 너무 많아서 너무 느려서,,, |
| const { | ||
| data: reviews, | ||
| isLoading: reviewsLoading, | ||
| refetch: reviewsRefetch, |
There was a problem hiding this comment.
안쓰는 메서드들 삭제하셔도 좋을 것 같아요!
추가로, refetch가 필요한지 고민해보셔도 좋습니다! (보통 특정 이벤트에 대해 키 만료로 많이 처리해서요!)
| const [sortType] = useState<"like" | "latest">("like"); | ||
| const currentSort = sortType === "like" ? "like" : "latest"; |
| data: realEstateInfoResponse, | ||
| isLoading: isInfoLoading, | ||
| error: infoError, | ||
| } = useRealEstateInfoQuery(propertyId, !!propertyId); |
| useEffect(() => { | ||
| if (lastMessageRef.current) { | ||
| lastMessageRef.current.scrollIntoView({ | ||
| behavior: isFirstRender.current ? "auto" : "smooth", | ||
| }); | ||
| isFirstRender.current = false; | ||
| } | ||
| }, [allMessages]); |
There was a problem hiding this comment.
스크롤은 훅으로 분리하면 로직이 더 명확할 것 같습니다! (주석 불필요)
| return ( | ||
| <React.Fragment key={message.messageId}> | ||
| {messageContent} | ||
| {isLast && <div ref={lastMessageRef} />} |
There was a problem hiding this comment.
map 안에 넣기보다 allMessage.map 렌더링 이후에 넣으셔도 무방할 것 같습니다!
| reviewId, | ||
| propertyId, | ||
| currentSort, | ||
| comments, |
There was a problem hiding this comment.
개인적으론 CommentList 내부에서 관련 데이터를 가져오는 것도 좋을 것 같습니다!
| import { getUserInfo } from "@/apis/login/getUserInfo"; | ||
| import { useUserInfoStore } from "@/stores/useUserInfoStore"; | ||
|
|
||
| export default function useAuthGuard() { |
There was a problem hiding this comment.
넥스트 미들웨어로 처리하는 게 국룰이에요! 한 번 살펴보시면 좋을 것 같습니다
| export const useMarkerPositions = (propertyList: MapPropertyItem[]) => { | ||
| const markerPositions = useMemo( | ||
| () => | ||
| propertyList.map(({ order, propertyId, latitude, longitude }) => ({ | ||
| order, | ||
| propertyId, | ||
| latitude, | ||
| longitude, | ||
| })), | ||
| [propertyList], | ||
| ); | ||
|
|
||
| return markerPositions; | ||
| }; |
There was a problem hiding this comment.
훅이 아니라 일반 함수로 가능할 것 같아요! (그럼 useMemo빼도 무방)
| // "use client"; | ||
|
|
||
| // import { useEffect } from "react"; | ||
| // import { useRouter } from "next/navigation"; | ||
|
|
||
| // export default function useRedirect() { | ||
| // const router = useRouter(); | ||
|
|
||
| // useEffect(() => { | ||
| // const hasToken = document.cookie.includes("ACCESS_TOKEN"); | ||
|
|
||
| // if (hasToken) { | ||
| // router.replace("/"); | ||
| // } | ||
| // }, []); | ||
| // } |
| colors: { | ||
| white: "#FFFFFF", | ||
| black: "#000000", | ||
| gray: { | ||
| "050": "#FCFCFC", | ||
| "100": "#F8F8F8", | ||
| "200": "#F3F3F3", | ||
| "300": "#EDEDED", | ||
| "400": "#DDE0E4", | ||
| "500-alternative": "#D4D7DD", | ||
| "600-hint": "#BCC2CA", | ||
| "700-info": "#949CA8", | ||
| "800": "#778292", | ||
| "900": "#444A54", | ||
| "950-dark": "#252730", | ||
| }, | ||
| blue: { | ||
| "050-bg": "#EDF0FD", | ||
| "100": "#D9E0FB", | ||
| "200": "#B7C9F7", | ||
| "300": "#8FAEF4", | ||
| "400": "#6F99F1", | ||
| "500-secondary": "#4F7FEC", | ||
| "600": "#3B68E9", | ||
| "700": "#2E57E7", | ||
| "800-primary": "#204AE5", | ||
| "900": "#1939B5", | ||
| }, | ||
| }, |
There was a problem hiding this comment.
따로 객체로 정의해서 관리하기도 합니다! (fontSize도)
import { colors, fontSize } from ".."
extends: {
colors,
fontSize,
}* refactor: 매매/주거 형태 필터 선택 값 저장하는 state명 수정 * fix: 장소 저장 타입 옵셔널로 변경 * fix: 파라미터 타입 변경 및 헤더 렌더 구조 수정 * refactor: 사이드바 footer 분리 (불필요 리렌더링 방지) * feat - 채팅 내 up 버튼 추가 - 채팅 input 분리 - ChatMain -> ChatContent로 변경 * refactor: scroll ref 구조 변경
* refactor: api 호출과 queries 합치기 * fix: label과 value 띄어쓰기 * remove: api 호출 제거 * fix: title의 children을 String만이 아닌 reactNode로 변경 * refactor: isLoading 일관적 스켈레톤 반영 * remove: 안 쓰는 fetch 함수 import 제거 * refactor: 매물 상세 skeleton 반영 * refactor: 리뷰, 댓글 skeleton 컴포넌트 제작 후 반영 * refactor: 리뷰 리스트에도 제작한 skeleton card로 대체
* refactor: api 호출 query파일에 병합 * feat: 매물카드 찜 토스트 적용 * refactor: postItem key값 수정 * refactor: 무한스크롤 확인용 2초 대기 제거 * refactror: 부동산페이지 api호출 query파일에 병합 * feat: 마이페이지인 경우에 찜한매물보러가기 버튼 제거
✨ Related Issues
📝 Task Details
초기 세팅을 제외한 작업 내용 전부 반영
📂 References
💖 Review Requirements
배포 -> https://zoop-frontend-sable.vercel.app
카카오 소셜 로그인으로 회원가입 / 로그인 후 서비스 이용이 가능합니다!
현재 ai 학습이 부족하여 초기 추천 받은 후 재추천 받을 때 원활한 답변을 받기 어려울 수 있습니다
감사합니다!