From d905d7d7ba1f2e2b28bef56a28bdc6ca3b6645d1 Mon Sep 17 00:00:00 2001 From: cjeongmin Date: Tue, 21 May 2024 17:25:32 +0900 Subject: [PATCH 1/4] feat: Add isCreateable state --- src/app/pages/writing-post-page.tsx | 11 +++++++++++ src/features/shared/shared.hook.ts | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/app/pages/writing-post-page.tsx b/src/app/pages/writing-post-page.tsx index 81645fb392..0726841163 100644 --- a/src/app/pages/writing-post-page.tsx +++ b/src/app/pages/writing-post-page.tsx @@ -441,6 +441,7 @@ export function WritingPostPage({ selectedExtraOptions, expectedMonthlyFee, derivedMateCardFeatures, + isCreatable, setSharedPostProps, handleOptionClick, handleExtraOptionClick, @@ -525,6 +526,16 @@ export function WritingPostPage({ }; const handleCreatePost = (event: React.MouseEvent) => { + if (!isCreatable) { + createToast({ + message: '필수 항목들이 입력되어야 합니다.', + option: { + duration: 3000, + }, + }); + return; + } + const extractFileName = (url: string): string => { const regex = /\/([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}\.\w+)/; diff --git a/src/features/shared/shared.hook.ts b/src/features/shared/shared.hook.ts index b95ee5410b..3f8546e7b1 100644 --- a/src/features/shared/shared.hook.ts +++ b/src/features/shared/shared.hook.ts @@ -324,9 +324,31 @@ export const useSharedPostProps = ({ } }, [user, setState]); + const isCreatable = useMemo( + () => + state.title.trim().length > 0 && + state.content.trim().length > 0 && + state.images.length >= 2 && + state.address != null && + state.mateLimit > 0 && + state.expectedMonthlyFee > 0 && + state.houseSize > 0 && + state.selectedOptions.budget != null && + state.selectedOptions.roomType != null && + state.selectedOptions.livingRoom != null && + state.selectedOptions.roomCount != null && + state.selectedOptions.restRoomCount != null && + state.selectedOptions.floorType != null && + state.mateCard.features.smoking != null && + state.mateCard.features.roomSharingOption != null && + state.mateCard.features.mateAge != null, + [state], + ); + return { ...state, derivedMateCardFeatures, + isCreatable, setSharedPostProps: setState, reset, handleOptionClick, From 47b4a1447b84674d4525a5ff963dbcf12dc3baa9 Mon Sep 17 00:00:00 2001 From: cjeongmin Date: Tue, 21 May 2024 22:46:11 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20RangeSlider=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EA=B0=92=20=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/FloatingChatting.tsx | 6 +-- src/components/RangeSlider.tsx | 3 +- src/components/chat/ChattingRoom.tsx | 2 +- src/components/chat/MobileChattingBox.tsx | 2 +- src/components/chat/MobileChattingRoom.tsx | 4 +- .../shared-posts/filter/DealTypeFilter.tsx | 32 +++++++++++++--- .../shared-posts/filter/RoomTypeFilter.tsx | 37 ++++++++++++++++++- 7 files changed, 72 insertions(+), 14 deletions(-) diff --git a/src/components/FloatingChatting.tsx b/src/components/FloatingChatting.tsx index 6a0364de2e..c524d2a1bf 100644 --- a/src/components/FloatingChatting.tsx +++ b/src/components/FloatingChatting.tsx @@ -158,7 +158,7 @@ function FloatingChattingBox() { const initializeChat = async () => { try { const stomp = new Client({ - brokerURL: `ws://ec2-54-180-133-123.ap-northeast-2.compute.amazonaws.com:8080/ws`, + brokerURL: `${process.env.NEXT_PUBLIC_CHAT_API_URL}`, connectHeaders: { Authorization: `Bearer ${auth?.accessToken}`, }, @@ -189,12 +189,12 @@ function FloatingChattingBox() { }; if (auth?.accessToken != null) { - void initializeChat(); + initializeChat(); } return () => { if (stompClient != null && stompClient.connected) { - void stompClient.deactivate(); + stompClient.deactivate(); } }; }, [auth?.accessToken, userId]); diff --git a/src/components/RangeSlider.tsx b/src/components/RangeSlider.tsx index ae5c7982c1..5cf319794d 100644 --- a/src/components/RangeSlider.tsx +++ b/src/components/RangeSlider.tsx @@ -12,6 +12,7 @@ const styles = { container: styled.div` position: relative; width: 100%; + margin-block: 1rem; div { position: absolute; @@ -41,7 +42,7 @@ const styles = { } input[type='range']::-moz-range-thumb { - -webkit-appearance: none; + appearance: none; pointer-events: all; width: 24px; height: 24px; diff --git a/src/components/chat/ChattingRoom.tsx b/src/components/chat/ChattingRoom.tsx index 70c983ef3b..0f47d8ac00 100644 --- a/src/components/chat/ChattingRoom.tsx +++ b/src/components/chat/ChattingRoom.tsx @@ -217,7 +217,7 @@ export function ChattingRoom({ const initializeChat = async () => { try { const stomp = new Client({ - brokerURL: `ws://ec2-54-180-133-123.ap-northeast-2.compute.amazonaws.com:8080/ws`, + brokerURL: `${process.env.NEXT_PUBLIC_CHAT_API_URL}`, connectHeaders: { Authorization: `Bearer ${auth?.accessToken}`, }, diff --git a/src/components/chat/MobileChattingBox.tsx b/src/components/chat/MobileChattingBox.tsx index 007bb50de1..1710813e7f 100644 --- a/src/components/chat/MobileChattingBox.tsx +++ b/src/components/chat/MobileChattingBox.tsx @@ -121,7 +121,7 @@ export function MobileChattingBox() { const initializeChat = async () => { try { const stomp = new Client({ - brokerURL: `ws://ec2-54-180-133-123.ap-northeast-2.compute.amazonaws.com:8080/ws`, + brokerURL: `${process.env.NEXT_PUBLIC_CHAT_API_URL}`, connectHeaders: { Authorization: `Bearer ${auth?.accessToken}`, }, diff --git a/src/components/chat/MobileChattingRoom.tsx b/src/components/chat/MobileChattingRoom.tsx index be2d7a7d49..28f5a73de4 100644 --- a/src/components/chat/MobileChattingRoom.tsx +++ b/src/components/chat/MobileChattingRoom.tsx @@ -213,7 +213,7 @@ export function MobileChattingRoom({ const initializeChat = async () => { try { const stomp = new Client({ - brokerURL: `ws://ec2-54-180-133-123.ap-northeast-2.compute.amazonaws.com:8080/ws`, + brokerURL: `${process.env.NEXT_PUBLIC_CHAT_API_URL}`, connectHeaders: { Authorization: `Bearer ${auth?.accessToken}`, }, @@ -263,7 +263,7 @@ export function MobileChattingRoom({ stompClient.publish({ destination, body: JSON.stringify({ - roomId: roomId, + roomId, sender: user, message: inputMessage, nickname: userName, diff --git a/src/components/shared-posts/filter/DealTypeFilter.tsx b/src/components/shared-posts/filter/DealTypeFilter.tsx index e7b6ec7625..307daffecb 100644 --- a/src/components/shared-posts/filter/DealTypeFilter.tsx +++ b/src/components/shared-posts/filter/DealTypeFilter.tsx @@ -22,7 +22,7 @@ const styles = { width: 20rem; @media (max-width: 768px) { - width: 10rem; + width: 13rem; gap: 1rem; } `, @@ -33,6 +33,18 @@ const styles = { align-items: flex-start; gap: 1rem; + .slider-value { + font-size: 0.95rem; + color: #808080; + } + + @media (max-width: 768px) { + .slider-value { + font-size: 0.75rem; + color: #808080; + } + } + h1 { color: #000; font-family: 'Noto Sans KR'; @@ -48,7 +60,7 @@ const styles = { div { display: flex; - align-items: flex-start; + align-items: flex-end; gap: 0.5rem; button { @@ -148,11 +160,21 @@ export function DealTypeFilter() { -

희망 월 분담금

+
+

희망 월 분담금

+ {filter.dealInfo.expectedFee != null ? ( +

+ {filter.dealInfo.expectedFee?.low}만원 ~{' '} + {filter.dealInfo.expectedFee?.high}만원 +

+ ) : ( +

0만원 ~ 무제한

+ )} +
{ setFilter(prev => ({ ...prev, diff --git a/src/components/shared-posts/filter/RoomTypeFilter.tsx b/src/components/shared-posts/filter/RoomTypeFilter.tsx index 3c8aef6f55..63a316cb0e 100644 --- a/src/components/shared-posts/filter/RoomTypeFilter.tsx +++ b/src/components/shared-posts/filter/RoomTypeFilter.tsx @@ -121,6 +121,32 @@ const styles = { flex-direction: column; align-items: flex-start; gap: 1rem; + + div { + display: flex; + flex-direction: row; + align-items: flex-end; + gap: 0.5rem; + + p { + font-size: 0.9rem; + color: #808080; + } + } + + @media (max-width: 768px) { + div { + display: flex; + flex-direction: row; + align-items: flex-end; + gap: 0.5rem; + + p { + font-size: 0.75rem; + color: #808080; + } + } + } `, floor: styled.div` display: flex; @@ -345,7 +371,16 @@ export function RoomTypeFilter() { -

면적

+
+

면적

+ {filter.roomInfo.size != null ? ( +

+ {filter.roomInfo.size.low}평 ~ {filter.roomInfo.size.high}평 +

+ ) : ( +

0평 ~ 무제한

+ )} +
Date: Tue, 21 May 2024 22:57:28 +0900 Subject: [PATCH 3/4] feat: Refetch post data when follow, unfollow, scrap --- src/app/pages/shared-post-page.tsx | 48 ++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/src/app/pages/shared-post-page.tsx b/src/app/pages/shared-post-page.tsx index 47dde2c2ea..9d7d431928 100644 --- a/src/app/pages/shared-post-page.tsx +++ b/src/app/pages/shared-post-page.tsx @@ -1,5 +1,6 @@ 'use client'; +import { useQueryClient } from '@tanstack/react-query'; import { useRouter } from 'next/navigation'; import { useEffect, useMemo, useRef, useState } from 'react'; import { useRecoilState } from 'recoil'; @@ -583,6 +584,8 @@ export function SharedPostPage({ setFollowList(newFollowList); }, [post]); + const queryClient = useQueryClient(); + if (isLoading || post == null) return <>; return ( @@ -599,7 +602,18 @@ export function SharedPostPage({ hasBorder={false} marked={post.data.isScrapped} onToggle={() => { - scrapPost(postId); + scrapPost(postId, { + onSuccess: () => { + if (type === 'hasRoom') + queryClient.invalidateQueries({ + queryKey: [`/api/shared/posts/studio/${postId}`], + }); + else + queryClient.invalidateQueries({ + queryKey: [`/api/shared/posts/dormitory/${postId}`], + }); + }, + }); }} color="black" /> @@ -767,8 +781,36 @@ export function SharedPostPage({ followList[selected.memberId] == null ) return; - if (followList[selected.memberId]) unfollow(); - else follow(); + if (followList[selected.memberId]) + unfollow(undefined, { + onSuccess: () => { + if (type === 'hasRoom') + queryClient.invalidateQueries({ + queryKey: [`/api/shared/posts/studio/${postId}`], + }); + else + queryClient.invalidateQueries({ + queryKey: [ + `/api/shared/posts/dormitory/${postId}`, + ], + }); + }, + }); + else + follow(undefined, { + onSuccess: () => { + if (type === 'hasRoom') + queryClient.invalidateQueries({ + queryKey: [`/api/shared/posts/studio/${postId}`], + }); + else + queryClient.invalidateQueries({ + queryKey: [ + `/api/shared/posts/dormitory/${postId}`, + ], + }); + }, + }); }} hasBorder color="#888" From 39c8a210d896f49dd826c1c4db50c49da90ed24f Mon Sep 17 00:00:00 2001 From: cjeongmin Date: Tue, 21 May 2024 23:05:40 +0900 Subject: [PATCH 4/4] feat: Apply data refetching for follow, unfollow, and scrap actions in mobile --- .../pages/mobile/mobile-shared-post-page.tsx | 52 +++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/src/app/pages/mobile/mobile-shared-post-page.tsx b/src/app/pages/mobile/mobile-shared-post-page.tsx index 49ef50159a..9027d31b15 100644 --- a/src/app/pages/mobile/mobile-shared-post-page.tsx +++ b/src/app/pages/mobile/mobile-shared-post-page.tsx @@ -1,5 +1,6 @@ 'use client'; +import { useQueryClient } from '@tanstack/react-query'; import { useRouter } from 'next/navigation'; import { useEffect, useMemo, useRef, useState } from 'react'; import styled from 'styled-components'; @@ -531,6 +532,8 @@ export function MobileSharedPostPage({ setFollowList(newFollowList); }, [post]); + const queryClient = useQueryClient(); + if (isLoading || post == null) return <>; return ( @@ -565,8 +568,40 @@ export function MobileSharedPostPage({ followList[selected.memberId] == null ) return; - if (followList[selected.memberId]) unfollow(); - else follow(); + if (followList[selected.memberId]) + unfollow(undefined, { + onSuccess: () => { + if (type === 'hasRoom') + queryClient.invalidateQueries({ + queryKey: [ + `/api/shared/posts/studio/${postId}`, + ], + }); + else + queryClient.invalidateQueries({ + queryKey: [ + `/api/shared/posts/dormitory/${postId}`, + ], + }); + }, + }); + else + follow(undefined, { + onSuccess: () => { + if (type === 'hasRoom') + queryClient.invalidateQueries({ + queryKey: [ + `/api/shared/posts/studio/${postId}`, + ], + }); + else + queryClient.invalidateQueries({ + queryKey: [ + `/api/shared/posts/dormitory/${postId}`, + ], + }); + }, + }); }} hasBorder color="#888" @@ -606,7 +641,18 @@ export function MobileSharedPostPage({ hasBorder={false} marked={post.data.isScrapped} onToggle={() => { - scrapPost(postId); + scrapPost(postId, { + onSuccess: () => { + if (type === 'hasRoom') + queryClient.invalidateQueries({ + queryKey: [`/api/shared/posts/studio/${postId}`], + }); + else + queryClient.invalidateQueries({ + queryKey: [`/api/shared/posts/dormitory/${postId}`], + }); + }, + }); }} color="black" />