@@ -14,6 +14,7 @@ import Button from "@/components/Button";
1414import DottedLine from "@/components/DottedLine" ;
1515import LinkLogin from "@/components/Link/LinkLogin" ;
1616import MiniCircle from "@/components/MiniCircle" ;
17+ import CarrierOptionRow from "@/components/ModalRoomOptions/CarrierOptionRow" ;
1718import Users from "@/components/User/Users" ;
1819import { MAX_PARTICIPATION } from "@/pages/Myroom" ;
1920
@@ -37,8 +38,10 @@ type InfoSectionProps = {
3738 alignDirection : "left" | "right" ;
3839 children : React . ReactNode ;
3940} ;
41+
4042export type BodyRoomSelectionProps = {
4143 roomInfo : Room ;
44+ onToggleCarrier ?: ( ) => void ;
4245 triggerTags ?: string ;
4346} ;
4447
@@ -116,44 +119,75 @@ const BodyRoomSelection = ({
116119 const fetchMyRooms = useFetchRecoilState ( "myRooms" ) ;
117120 const setAlert = useSetRecoilState ( alertAtom ) ;
118121
119- const isLogin = useIsLogin ( ) && ! ! loginInfo ?. id ; // 로그인 여부
120- const isRoomFull = roomInfo && roomInfo . part . length >= roomInfo . maxPartLength ; // 방이 꽉 찼는지 여부
122+ // 참여 시 캐리어 지참 여부 상태 (기본값 false)
123+ const [ joinWithCarrier , setJoinWithCarrier ] = useState ( false ) ;
124+
125+ const isLogin = useIsLogin ( ) && ! ! loginInfo ?. id ;
126+ const isRoomFull = roomInfo && roomInfo . part . length >= roomInfo . maxPartLength ;
127+
121128 const isAlreadyPart =
122129 isLogin &&
123130 roomInfo &&
124131 ( roomInfo . part . some (
125132 ( user : Room [ "part" ] [ number ] ) => user . _id === loginInfo . oid
126133 ) ??
127- true ) ; // 이미 참여 중인지 여부
134+ true ) ;
135+
128136 const isMaxPart =
129- isLogin && myRooms && myRooms . ongoing . length >= MAX_PARTICIPATION ; // 최대 참여 가능한 방 개수를 초과했는지 여부
130- const isDepart = useIsTimeOver ( dayServerToClient ( roomInfo . time ) ) ; // 방 출발 여부
137+ isLogin && myRooms && myRooms . ongoing . length >= MAX_PARTICIPATION ;
138+ const isDepart = useIsTimeOver ( dayServerToClient ( roomInfo . time ) ) ;
131139
132140 const notPaid = useMemo ( ( ) => {
133141 const myOngoingRoom = myRooms ?. ongoing . slice ( ) ?? [ ] ;
134142 const notPaid = myOngoingRoom . find (
135143 ( room ) =>
136144 room . part . find ( ( item : any ) => item . _id === loginInfo ?. oid )
137- . isSettlement === "send-required" && room . isDeparted
138- ) ; // 다른 사람이 정산을 올렸으나 내가 아직 송금하지 않은 방이 있는지 여부 (추가 입장 제한에 사용)
145+ ? .isSettlement === "send-required" && room . isDeparted
146+ ) ;
139147 return notPaid ;
140- } , [ myRooms ] ) ; // myOngoingRoom은 infoSection의 sortedMyRoom에서 정렬만 뺀 코드입니다. useMemo로 감싼 형태입니다.
141- // item : any 가 좋은 방법인지 모르겠습니다
148+ } , [ myRooms , loginInfo ] ) ;
149+
150+ const participantsWithCarrier = useMemo ( ( ) => {
151+ if ( ! roomInfo ?. part ) return [ ] ;
152+ return roomInfo . part . map ( ( user : any ) => ( {
153+ ...user ,
154+ withCarrier : user . hasCarrier || false ,
155+ } ) ) ;
156+ } , [ roomInfo . part ] ) ;
142157
143158 const requestJoin = useCallback ( async ( ) => {
159+ // 이미 참여 중이면 이동만
144160 if ( isAlreadyPart ) {
145- // 이미 참여 중인 방에서 버튼을 누르면 API 호출 관련 로직을 건너뛰고 해당 방으로 이동합니다.
146161 history . push ( `/myroom/${ roomInfo . _id } ` ) ;
147162 return ;
148163 }
149- // 여기부터는 이미 참여 중인 방이 아닌 경우의 로직입니다.
164+
150165 if ( onCall . current ) return ;
151166 onCall . current = true ;
167+
152168 await axios ( {
153169 url : "/rooms/join" ,
154170 method : "post" ,
155171 data : { roomId : roomInfo . _id } ,
156- onSuccess : ( ) => {
172+ onSuccess : async ( ) => {
173+ // 만약 캐리어를 들고 탄다고 체크했다면 토글 API 추가 호출
174+ if ( joinWithCarrier ) {
175+ try {
176+ await axios ( {
177+ url : "/rooms/carrier/toggle" ,
178+ method : "post" ,
179+ data : {
180+ roomId : roomInfo . _id ,
181+ hasCarrier : true ,
182+ } ,
183+ // ...
184+ } ) ;
185+ } catch ( e ) {
186+ console . error ( "캐리어 상태 반영 실패" , e ) ;
187+ }
188+ }
189+
190+ // 내 방 목록 갱신 및 페이지 이동
157191 fetchMyRooms ( ) ;
158192 history . push ( `/myroom/${ roomInfo . _id } ` ) ;
159193
@@ -163,10 +197,12 @@ const BodyRoomSelection = ({
163197 }
164198 }
165199 } ,
200+
166201 onError : ( ) => setAlert ( "방 참여에 실패하였습니다." ) ,
167202 } ) ;
203+
168204 onCall . current = false ;
169- } , [ roomInfo ?. _id , history , triggerTags ] ) ;
205+ } , [ roomInfo ?. _id , history , joinWithCarrier , triggerTags ] ) ; // 의존성 유지
170206
171207 const [ taxiFare , setTaxiFare ] = useState < number > ( 0 ) ;
172208 const getTaxiFare = async ( ) => {
@@ -231,7 +267,7 @@ const BodyRoomSelection = ({
231267 < div css = { styleMultipleInfo } >
232268 < div css = { { minWidth : 0 } } >
233269 < InfoSection title = "탑승자" alignDirection = "left" >
234- < Users values = { roomInfo . part } />
270+ < Users values = { participantsWithCarrier } />
235271 </ InfoSection >
236272 </ div >
237273 < div css = { { minWidth : "fit-content" } } >
@@ -266,6 +302,18 @@ const BodyRoomSelection = ({
266302 </ InfoSection >
267303 ) : null }
268304 </ div >
305+
306+ { ! isAlreadyPart && ! isRoomFull && ! isDepart && isLogin && (
307+ < div
308+ css = { { marginTop : "-5px" , marginBottom : "12px" , padding : "0 10px" } }
309+ >
310+ < CarrierOptionRow
311+ value = { joinWithCarrier }
312+ handler = { setJoinWithCarrier }
313+ /> { " " }
314+ </ div >
315+ ) }
316+
269317 { isLogin || isRoomFull || isDepart ? (
270318 < Button
271319 type = "purple"
0 commit comments