diff --git a/src/api/endpoint/coffeechat/getCoffeechatDetail.ts b/src/api/endpoint/coffeechat/getCoffeechatDetail.ts index ac54ca1a8..e67cbc11d 100644 --- a/src/api/endpoint/coffeechat/getCoffeechatDetail.ts +++ b/src/api/endpoint/coffeechat/getCoffeechatDetail.ts @@ -1,7 +1,7 @@ +import { useQuery } from '@tanstack/react-query'; import { z } from 'zod'; import { createEndpoint } from '@/api/typedAxios'; -import { useQuery } from '@tanstack/react-query'; const CoffeechatDetailSchema = z.object({ bio: z.string(), @@ -21,6 +21,7 @@ const CoffeechatDetailSchema = z.object({ isBlind: z.boolean().nullable(), profileImage: z.string().nullable(), isCoffeeChatActivate: z.boolean().nullable(), + sections: z.array(z.string()), }); export const getCoffeechatDetail = createEndpoint({ diff --git a/src/components/coffeechat/CoffeeChatCategory/index.tsx b/src/components/coffeechat/CoffeeChatCategory/index.tsx index 9920eae6c..fd5aea442 100644 --- a/src/components/coffeechat/CoffeeChatCategory/index.tsx +++ b/src/components/coffeechat/CoffeeChatCategory/index.tsx @@ -2,9 +2,7 @@ import styled from '@emotion/styled'; import { colors } from '@sopt-makers/colors'; import { fonts } from '@sopt-makers/fonts'; import { IconChevronDown } from '@sopt-makers/icons'; -import { SelectV2 } from '@sopt-makers/ui'; -import { SearchField } from '@sopt-makers/ui'; -import { width100 } from '@toss/emotion-utils'; +import { SearchField, SelectV2 } from '@sopt-makers/ui'; import { useEffect, useState } from 'react'; import { useGetMembersCoffeeChat } from '@/api/endpoint/members/getMembersCoffeeChat'; @@ -21,16 +19,12 @@ import Loading from '@/components/common/Loading'; import Responsive from '@/components/common/Responsive'; import { MB_BIG_MEDIA_QUERY, - MB_BIG_WIDTH, MB_MID_MEDIA_QUERY, - MB_SM_MEDIA_QUERY, MOBILE_MEDIA_QUERY, PCTA_BIG_MEDIA_QUERY, PCTA_MID_MEDIA_QUERY, PCTA_S_MEDIA_QUERY, - PCTA_S_WIDTH, PCTA_SM_MEDIA_QUERY, - PCTA_SM_WIDTH, } from '@/styles/mediaQuery'; export default function CoffeeChatCategory() { @@ -86,7 +80,7 @@ export default function CoffeeChatCategory() { setCareer(CAREER_FILTER_OPTIONS[e - 1].label)} defaultValue={CAREER_FILTER_OPTIONS.find((option) => option.label === career)} type='text' @@ -103,7 +97,7 @@ export default function CoffeeChatCategory() { setPart(PART_FILTER_OPTIONS[e - 1].label)} defaultValue={PART_FILTER_OPTIONS.find((option) => option.label === part)} type='text' @@ -177,8 +171,8 @@ export default function CoffeeChatCategory() { }))} placeholder='분야' trigger={(placeholder) => ( - 0} value={section}> - {section?section:placeholder} + 0} value={section}> + {section ? section : placeholder} )} @@ -192,8 +186,8 @@ export default function CoffeeChatCategory() { }))} placeholder='주제' trigger={(placeholder) => ( - 0}> - {topicType?topicType:placeholder} + 0}> + {topicType ? topicType : placeholder} )} @@ -207,8 +201,8 @@ export default function CoffeeChatCategory() { }))} placeholder='경력' trigger={(placeholder) => ( - 0}> - {career?career:placeholder} + 0}> + {career ? career : placeholder} )} @@ -222,8 +216,8 @@ export default function CoffeeChatCategory() { }))} placeholder='파트' trigger={(placeholder) => ( - 0}> - {part?part:placeholder} + 0}> + {part ? part : placeholder} )} @@ -272,11 +266,11 @@ const Container = styled.div` align-items: center; justify-content: center; margin-top: 48px; - - .responsive-mobile-only{ - @media ${MB_BIG_MEDIA_QUERY}{ - width:100%; - } + + .responsive-mobile-only { + @media ${MB_BIG_MEDIA_QUERY} { + width: 100%; + } } @media ${PCTA_S_MEDIA_QUERY} { margin-top: 28px; @@ -294,11 +288,11 @@ const Header = styled.div` margin-bottom: 24px; width: 100%; width: 1300px; - @media ${PCTA_BIG_MEDIA_QUERY}{ - width:866px; + @media ${PCTA_BIG_MEDIA_QUERY} { + width: 866px; } - @media ${PCTA_SM_MEDIA_QUERY}{ - padding-left:30px; + @media ${PCTA_SM_MEDIA_QUERY} { + padding-left: 30px; width: 100%; } @media ${PCTA_S_MEDIA_QUERY} { @@ -427,47 +421,45 @@ const SelectFilterArea = styled.div` white-space: nowrap; } - .topic-select{ + .topic-select { width: 130px; - button{ - width:130px; + button { + width: 130px; - div{ - width:130px; + div { + width: 130px; } } } - .career-select{ - width:162px; + .career-select { + width: 162px; - button{ - width:162px; + button { + width: 162px; - div{ - width:162px; + div { + width: 162px; } } } - .part-select{ - width:109px; + .part-select { + width: 109px; - button{ - width:109px; + button { + width: 109px; - div{ - width:109px; + div { + width: 109px; } } } - ul { - z-index: 203; + z-index: 99; } - `; const StyledSearchField = styled(SearchField)` @@ -480,16 +472,16 @@ const StyledSearchField = styled(SearchField)` width: 424px; } @media ${MB_BIG_MEDIA_QUERY} { - padding-right:20px; - padding-left:20px; + padding-right: 20px; + padding-left: 20px; width: 100%; - button{ - right:15px; + button { + right: 15px; } } @media ${MB_MID_MEDIA_QUERY} { - width: 100% + width: 100%; } `; const LoadingContainer = styled.div` @@ -587,7 +579,6 @@ const StyledChevronDown = styled(IconChevronDown)` const StyledMobileFilter = styled(CoffeeChatFilterSheet)` flex: none; - `; const StyledMobileFilterWrapper = styled.div` @@ -603,26 +594,26 @@ const StyledMobileFilterWrapper = styled.div` /* to disable scroll bar */ -ms-overflow-style: none; /* IE and Edge */ scrollbar-width: none; /* Firefox */ - button{ - width:auto; + button { + width: auto; } ::-webkit-scrollbar { display: none; /* Chrome, Safari, Opera */ } - @media ${PCTA_S_MEDIA_QUERY}{ - padding:0; - width:424px; + @media ${PCTA_S_MEDIA_QUERY} { + padding: 0; + width: 424px; - button{ - width:100px; + button { + width: 100px; white-space: nowrap; } } - @media ${MB_BIG_MEDIA_QUERY}{ - padding-right:20px; - padding-left:20px; - width:auto; + @media ${MB_BIG_MEDIA_QUERY} { + padding-right: 20px; + padding-left: 20px; + width: auto; max-width: 100%; } `; diff --git a/src/components/coffeechat/CoffeeRecentChatList/index.tsx b/src/components/coffeechat/CoffeeRecentChatList/index.tsx index 04a477d1b..8c905a186 100644 --- a/src/components/coffeechat/CoffeeRecentChatList/index.tsx +++ b/src/components/coffeechat/CoffeeRecentChatList/index.tsx @@ -4,7 +4,7 @@ import { fonts } from '@sopt-makers/fonts'; import { Button } from '@sopt-makers/ui'; import { useRouter } from 'next/router'; import { playgroundLink } from 'playground-common/export'; -import { ReactNode, startTransition, useEffect, useRef,useState } from 'react'; +import { ReactNode, startTransition, useEffect, useState } from 'react'; import { useGetRecentCoffeeChat } from '@/api/endpoint/members/getRecentCoffeeChats'; import CoffeeChatCard from '@/components/coffeechat/CoffeeChatCard'; @@ -14,10 +14,17 @@ import Carousel from '@/components/common/Carousel'; import Loading from '@/components/common/Loading'; import Responsive from '@/components/common/Responsive'; import useEventLogger from '@/components/eventLogger/hooks/useEventLogger'; -import { MB_BIG_MEDIA_QUERY, MB_MID_MEDIA_QUERY, MB_SM_MEDIA_QUERY, MOBILE_MEDIA_QUERY, PCTA_BIG_MEDIA_QUERY, PCTA_S_MEDIA_QUERY, PCTA_SM_MEDIA_QUERY } from '@/styles/mediaQuery'; +import { + MB_BIG_MEDIA_QUERY, + MB_MID_MEDIA_QUERY, + MB_SM_MEDIA_QUERY, + MOBILE_MEDIA_QUERY, + PCTA_S_MEDIA_QUERY, + PCTA_SM_MEDIA_QUERY, +} from '@/styles/mediaQuery'; import { getScreenMaxWidthMediaQuery } from '@/utils'; -type ListType = 'carousel-large' | 'carousel-small' | 'scroll' | 'tablet'| undefined; +type ListType = 'carousel-large' | 'carousel-small' | 'scroll' | 'tablet' | undefined; const SCREEN_SIZE = { desktopLarge: { size: 1488, className: 'large-desktop-only' }, @@ -73,15 +80,15 @@ export default function CoffeeChatList() { }; desktopLargeMedia.addEventListener('change', handleChangeDesktopLargeMedia); desktopSmallMedia.addEventListener('change', handleChangeDesktopSmallMedia); - tabletMedia.addEventListener('change',handleChangeTabletMedia) + tabletMedia.addEventListener('change', handleChangeTabletMedia); startTransition(() => { - if (tabletMedia.matches){ - setListType('tablet')} - else if (desktopSmallMedia.matches) { + if (tabletMedia.matches) { + setListType('tablet'); + } else if (desktopSmallMedia.matches) { setListType('scroll'); } else if (desktopLargeMedia.matches) { setListType('carousel-small'); - }else{ + } else { setListType('carousel-large'); } }); @@ -89,49 +96,41 @@ export default function CoffeeChatList() { return () => { desktopLargeMedia.removeEventListener('change', handleChangeDesktopLargeMedia); desktopSmallMedia.removeEventListener('change', handleChangeDesktopSmallMedia); - tabletMedia.removeEventListener('change',handleChangeTabletMedia) + tabletMedia.removeEventListener('change', handleChangeTabletMedia); }; }, []); return ( -
- - {isLoading - ? '' - : isEmptyData - ? '최근 진행된 커피챗이에요✨' - : '최근 진행된 커피챗이에요✨'} - - - - - - - - - -
+ + + {isLoading ? ( @@ -156,18 +155,18 @@ export default function CoffeeChatList() { )} {(listType === undefined || listType === 'scroll') && ( {children}} - className={SCREEN_SIZE.tablet.className} + itemList={coffeeChatRecentCardList} + limit={2} + renderItemContainer={(children: ReactNode) => {children}} + className={SCREEN_SIZE.tablet.className} > )} {(listType === undefined || listType === 'tablet') && ( {children}} - className={SCREEN_SIZE.tablet.className} + itemList={coffeeChatRecentCardList} + limit={1} + renderItemContainer={(children: ReactNode) => {children}} + className={SCREEN_SIZE.tablet.className} > )} @@ -185,7 +184,6 @@ const Container = styled.div` margin-top: 80px; @media ${DESKTOP_LARGE_MEDIA_QUERY} { - .${SCREEN_SIZE.desktopSmall.className} { display: grid; } @@ -214,7 +212,6 @@ const Container = styled.div` @media ${TABLET_MEDIA_QUERY} { gap: 16px; - } @media ${MOBILE_MEDIA_QUERY} { @@ -237,30 +234,29 @@ const Header = styled.div` flex-direction: column; gap: 20px; align-items: flex-start; - } @media ${TABLET_MEDIA_QUERY} { gap: 12px; - margin-bottom:10px; + margin-bottom: 10px; width: 420px; } - @media ${PCTA_S_MEDIA_QUERY}{ - margin-top:12px; + @media ${PCTA_S_MEDIA_QUERY} { + margin-top: 12px; + } + @media ${MB_BIG_MEDIA_QUERY} { + padding-right: 20px; + padding-left: 20px; + width: 100%; } - @media ${MB_BIG_MEDIA_QUERY}{ - padding-right:20px; - padding-left:20px; - width:100%; - } `; const Title = styled.div` - max-height:56px; + max-height: 56px; text-align: start; /* Heading/24_B */ - ${fonts.HEADING_24_B} + ${fonts.HEADING_24_B} color: ${colors.white}; @@ -297,42 +293,36 @@ const StyledCarousel = styled(Carousel)` const StyledScrollCarousel = styled(ScrollCarousel)` padding-top: 8px; width: 860px; - @media ${PCTA_SM_MEDIA_QUERY}{ - width:420px; - height:100%; + @media ${PCTA_SM_MEDIA_QUERY} { + width: 420px; + height: 100%; } - @media ${MB_BIG_MEDIA_QUERY}{ - width:390px; - height:298px; + @media ${MB_BIG_MEDIA_QUERY} { + width: 390px; + height: 298px; } - @media ${MB_MID_MEDIA_QUERY}{ - width:320px; + @media ${MB_MID_MEDIA_QUERY} { + width: 320px; } - @media ${MB_SM_MEDIA_QUERY}{ - width:280px; - + @media ${MB_SM_MEDIA_QUERY} { + width: 280px; } -` +`; export const CardContainer = styled.div` display: flex; gap: 20px; `; +const FixedButtonArea = styled.div` + position: fixed; + right: 90px; + bottom: 42px; + z-index: 202; -const FixedButtonArea=styled.div` -position:fixed; -right: 90px; -bottom:42px; -z-index: 202; - -@media ${PCTA_S_MEDIA_QUERY}{ - right:20px; - bottom:42px; -} -` - - - - + @media ${PCTA_S_MEDIA_QUERY} { + right: 20px; + bottom: 42px; + } +`; diff --git a/src/components/coffeechat/Loading/index.tsx b/src/components/coffeechat/Loading/index.tsx new file mode 100644 index 000000000..833851afb --- /dev/null +++ b/src/components/coffeechat/Loading/index.tsx @@ -0,0 +1,18 @@ +import styled from '@emotion/styled'; + +import Loading from '@/components/common/Loading'; + +export default function CoffeechatLoading() { + return ( + + + + ); +} + +const LoadingWrapper = styled.div` + display: flex; + flex-direction: column; + align-items: center; + margin-top: 100px; +`; diff --git a/src/components/coffeechat/detail/OpenerProfile/index.tsx b/src/components/coffeechat/detail/OpenerProfile/index.tsx index 6252789b7..6f5053a82 100644 --- a/src/components/coffeechat/detail/OpenerProfile/index.tsx +++ b/src/components/coffeechat/detail/OpenerProfile/index.tsx @@ -40,9 +40,11 @@ export default function OpenerProfile({ memberId }: OpenerProfileProps) { {openerProfile.memberCareerTitle && ' | ' + openerProfile.memberCareerTitle} - - {openerProfile.phone} - + {openerProfile.phone && ( + + {openerProfile.phone} + + )} {openerProfile.email} diff --git a/src/components/coffeechat/detail/index.tsx b/src/components/coffeechat/detail/index.tsx index 0fc8a3068..0de0eb833 100644 --- a/src/components/coffeechat/detail/index.tsx +++ b/src/components/coffeechat/detail/index.tsx @@ -9,7 +9,7 @@ import { useGetMemberOfMe } from '@/api/endpoint/members/getMemberOfMe'; import { useGetMemberProfileById } from '@/api/endpoint_LEGACY/hooks'; import CoffeechatContents from '@/components/coffeechat/detail/CoffeechatContents'; import OpenerProfile from '@/components/coffeechat/detail/OpenerProfile'; -import Loading from '@/components/common/Loading'; +import CoffeechatLoading from '@/components/coffeechat/Loading'; import CareerSection from '@/components/members/detail/CareerSection'; import DetailInfoSection from '@/components/members/detail/DetailinfoSection'; import ProjectSection from '@/components/members/detail/ProjectSection'; @@ -70,9 +70,7 @@ export default function CoffeechatDetail({ memberId }: CoffeechatDetailProp) { ) : ( - - - + )} @@ -89,12 +87,6 @@ const ProfileContents = styled.div` } `; -const CoffeechatLoading = styled.div` - display: flex; - flex-direction: column; - align-items: center; -`; - const ProfilPojectSection = styled.div` margin-top: 30px; diff --git a/src/components/coffeechat/upload/CoffeechatForm/ChipField/index.tsx b/src/components/coffeechat/upload/CoffeechatForm/ChipField/index.tsx index 07040ab4a..acd250e81 100644 --- a/src/components/coffeechat/upload/CoffeechatForm/ChipField/index.tsx +++ b/src/components/coffeechat/upload/CoffeechatForm/ChipField/index.tsx @@ -1,6 +1,6 @@ import styled from '@emotion/styled'; import { Chip } from '@sopt-makers/ui'; -import { Controller, useFormContext } from 'react-hook-form'; +import { Controller, ControllerRenderProps, useFormContext } from 'react-hook-form'; import { CoffeechatFormContent, CoffeechatFormPaths } from '@/components/coffeechat/upload/CoffeechatForm/types'; import FormItem from '@/components/common/form/FormItem'; @@ -16,6 +16,14 @@ interface ChipFieldProps { export default function ChipField({ field, errorMessage, chipList, isSingleSelect = false }: ChipFieldProps) { const { control } = useFormContext(); + const isActive = (field: ControllerRenderProps, chip: string) => { + return Array.isArray(field.value) + ? isSingleSelect + ? field.value[0] === chip + : field.value.includes(chip) + : field.value === chip; + }; + return ( - + {chip} - + {chip} diff --git a/src/components/coffeechat/upload/CoffeechatForm/CoffeechatInfoForm/index.tsx b/src/components/coffeechat/upload/CoffeechatForm/CoffeechatInfoForm/index.tsx index fadc17f27..267db727c 100644 --- a/src/components/coffeechat/upload/CoffeechatForm/CoffeechatInfoForm/index.tsx +++ b/src/components/coffeechat/upload/CoffeechatForm/CoffeechatInfoForm/index.tsx @@ -10,6 +10,7 @@ import { MEETING_TYPE_OPTIONS, } from '@/components/coffeechat/upload/CoffeechatForm/constants'; import { CoffeechatFormContent } from '@/components/coffeechat/upload/CoffeechatForm/types'; +import FormItem from '@/components/common/form/FormItem'; import FormTitle from '@/components/common/form/FormTitle'; import TextFieldLineBreak from '@/components/common/form/TextFieldLineBreak'; import Responsive from '@/components/common/Responsive'; @@ -19,6 +20,7 @@ export default function CoffeechatInfoForm() { control, formState: { errors }, } = useFormContext(); + return ( <> @@ -31,7 +33,7 @@ export default function CoffeechatInfoForm() { @@ -49,8 +51,9 @@ export default function CoffeechatInfoForm() { placeholder='ex. 디자인 관련 고민이 있다면, 함께 나눠봐요!' maxLength={40} isError={!!errors.coffeeChatInfo?.bio} - errorMessage='커피챗 제목을 입력해주세요' + errorMessage={errors.coffeeChatInfo?.bio?.message} onChange={(e) => field.onChange(e.target.value)} + disableEnterSubmit /> )} /> @@ -65,7 +68,7 @@ export default function CoffeechatInfoForm() { @@ -87,7 +90,7 @@ export default function CoffeechatInfoForm() { '• 당근, 토스, 넥슨, 하나은행, LG전자 면접 후기', ]} isError={!!errors.coffeeChatInfo?.topic} - errorMessage='커피챗 주제 소개를 입력해주세요' + errorMessage={errors.coffeeChatInfo?.topic?.message} onChange={(e) => field.onChange(e.target.value)} /> @@ -104,7 +107,7 @@ export default function CoffeechatInfoForm() { '• 당근, 토스, 넥슨, 하나은행, LG전자 면접 후기', ]} isError={!!errors.coffeeChatInfo?.topic} - errorMessage='커피챗 주제 소개를 입력해주세요' + errorMessage={errors.coffeeChatInfo?.topic?.message} onChange={(e) => field.onChange(e.target.value)} /> @@ -112,32 +115,39 @@ export default function CoffeechatInfoForm() { )} /> -
- 커피챗 진행 방식 - ( -
- option.value === field.value)} - onChange={(value) => field.onChange(value)} - > - - - - - {MEETING_TYPE_OPTIONS.map((option) => ( - - ))} - - -
- )} - /> -
+ + + 커피챗 진행 방식 + + + ( +
+ option.value === field.value) ?? + MEETING_TYPE_OPTIONS[MEETING_TYPE_OPTIONS.length - 1] + } + onChange={(value) => field.onChange(value)} + > + + + + + {MEETING_TYPE_OPTIONS.map((option) => ( + + ))} + + +
+ )} + /> +
+
유의사항 @@ -49,7 +49,7 @@ export default function MyInfoForm() { fixedHeight={126} lineBreakPlaceholder={['• 직무 경험이나 관심 분야를 적어주면 더 좋아요!']} isError={!!errors.memberInfo?.introduction} - errorMessage='자기소개를 입력해주세요' + errorMessage={errors.memberInfo?.introduction?.message} onChange={(e) => field.onChange(e.target.value)} /> @@ -61,7 +61,7 @@ export default function MyInfoForm() { fixedHeight={150} lineBreakPlaceholder={['• 직무 경험이나 관심 분야를 적어주면 더 좋아요!']} isError={!!errors.memberInfo?.introduction} - errorMessage='자기소개를 입력해주세요' + errorMessage={errors.memberInfo?.introduction?.message} onChange={(e) => field.onChange(e.target.value)} /> diff --git a/src/components/coffeechat/upload/CoffeechatForm/schema.ts b/src/components/coffeechat/upload/CoffeechatForm/schema.ts index 72770ed12..2740b06e1 100644 --- a/src/components/coffeechat/upload/CoffeechatForm/schema.ts +++ b/src/components/coffeechat/upload/CoffeechatForm/schema.ts @@ -21,7 +21,7 @@ const coffeeChatInfoSchema = yup.object().shape({ .min(1, '커피챗 주제 키워드를 선택해주세요') .required('커피챗 주제 키워드를 선택해주세요'), topic: yup.string().required('커피챗 주제 소개를 입력해주세요'), - meetingType: yup.string().nullable(), + meetingType: yup.string().nullable().required('커피챗 진행 방식을 선택해주세요'), guideline: yup.string().nullable(), }); diff --git a/src/components/coffeechat/upload/CoffeechatForm/types.ts b/src/components/coffeechat/upload/CoffeechatForm/types.ts index ec70fbd26..a2f76ac5e 100644 --- a/src/components/coffeechat/upload/CoffeechatForm/types.ts +++ b/src/components/coffeechat/upload/CoffeechatForm/types.ts @@ -1,15 +1,15 @@ export interface CoffeechatFormContent { memberInfo: { - career: string[] | string | null; - introduction: string | null; + career: string[] | string | null | undefined; + introduction: string | null | undefined; }; coffeeChatInfo: { - sections: string[]; - bio: string | null; - topicTypes: string[]; - topic: string | null; - meetingType: string | null; - guideline: string | null; + sections: string[] | undefined; + bio: string | null | undefined; + topicTypes: string[] | undefined; + topic: string | null | undefined; + meetingType: string | null | undefined; + guideline: string | null | undefined; }; } diff --git a/src/components/common/form/TextFieldLineBreak/index.tsx b/src/components/common/form/TextFieldLineBreak/index.tsx index 720d64d31..7a762392f 100644 --- a/src/components/common/form/TextFieldLineBreak/index.tsx +++ b/src/components/common/form/TextFieldLineBreak/index.tsx @@ -38,6 +38,7 @@ export default function TextFieldLineBreak({ errorMessage={errorMessage} onChange={onChange} autoFocus={isError} + disableEnterSubmit /> {!value && ( diff --git a/src/pages/coffeechat/edit/[id].tsx b/src/pages/coffeechat/edit/[id].tsx index 807f907ec..46152d49b 100644 --- a/src/pages/coffeechat/edit/[id].tsx +++ b/src/pages/coffeechat/edit/[id].tsx @@ -1,17 +1,30 @@ +import { DialogOptionType, useDialog, useToast } from '@sopt-makers/ui'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; +import { useRouter } from 'next/router'; +import { playgroundLink } from 'playground-common/export'; +import { FieldValues } from 'react-hook-form'; + import { editCoffeechat } from '@/api/endpoint/coffeechat/editCoffeechat'; +import { useGetCoffeechatDetail } from '@/api/endpoint/coffeechat/getCoffeechatDetail'; +import { useGetMemberOfMe } from '@/api/endpoint/members/getMemberOfMe'; import AuthRequired from '@/components/auth/AuthRequired'; +import CoffeechatLoading from '@/components/coffeechat/Loading'; import CoffeechatUploadPage from '@/components/coffeechat/page/CoffeechatUploadPage'; import { CoffeechatFormContent } from '@/components/coffeechat/upload/CoffeechatForm/types'; -import Loading from '@/components/common/Loading'; +import useStringRouterQuery from '@/hooks/useStringRouterQuery'; import { setLayout } from '@/utils/layout'; -import { useMutation } from '@tanstack/react-query'; -import { FieldValues } from 'react-hook-form'; const CoffeechatEdit = () => { - // const router = useRouter(); - // const queryClient = useQueryClient(); + const { query, status } = useStringRouterQuery(['id'] as const); + const memberId = status === 'success' ? query.id : ''; + const router = useRouter(); + const queryClient = useQueryClient(); + const { data: me } = useGetMemberOfMe(); + const { data: openerProfile, isError, error, isPending: isDetailPending } = useGetCoffeechatDetail(memberId); + const { open } = useDialog(); + const { open: toastOpen } = useToast(); - const { mutate, isPending } = useMutation({ + const { mutate, isPending: isEditPending } = useMutation({ mutationFn: (reqeustBody: CoffeechatFormContent) => editCoffeechat.request({ ...reqeustBody }), }); @@ -21,46 +34,98 @@ const CoffeechatEdit = () => { mutate( { - memberInfo: { ...memberInfo, career: memberInfo.career ? memberInfo.career[0] : null }, - coffeeChatInfo: { ...coffeeChatInfo }, + memberInfo: { + ...memberInfo, + career: memberInfo.career + ? Array.isArray(memberInfo.career) + ? memberInfo.career[0] + : memberInfo.career + : null, + }, + coffeeChatInfo: { ...coffeeChatInfo, meetingType: coffeeChatInfo.meetingType ?? '온/오프라인' }, }, { onSuccess: async () => { - // TODO: 쿼리 무효화 및 페이지 이동 처리 - // queryClient.invalidateQueries({ queryKey: 'coffeechat' }); - // await router.push(playgroundLink.coffeechatdetail()); + queryClient.invalidateQueries({ + predicate: (query) => ['getRecentCoffeeChat', 'getMembersCoffeeChat'].includes(query.queryKey[0] as string), + }); + toastOpen({ icon: 'success', content: '커피챗이 오픈됐어요! 경험을 나눠주셔서 감사해요.' }); + + await router.push(playgroundLink.coffeechatDetail(me?.id ?? '')); }, onError: (error) => { - console.error('업로드 실패:', error); + const option: DialogOptionType = { + title: `${error.message}`, + description: ``, + type: 'single', + typeOptions: { + approveButtonText: '확인', + buttonFunction: async () => await router.push(playgroundLink.coffeechat()), + }, + }; + open(option); }, }, ); }; - // TODO: 데이터 get api 패칭 필요 + // FIXME: url에서 직접 id 변경하여 접속하는 경우, 다른 사람의 커피챗 수정 불가능하도록 막기 + // useEffect(() => { + // if (memberId !== String(me?.id)) { + // open({ + // title: '다른 사람의 커피챗은 수정할 수 없어요', + // description: ``, + // type: 'single', + // typeOptions: { + // approveButtonText: '확인', + // buttonFunction: async () => await router.push(playgroundLink.coffeechat()), + // }, + // }); + // } + // }, [me?.id, memberId, open, router]); + + // FIXME: 존재하지 않는 커피챗 id 접속 + // useEffect(() => { + // if (isError) { + // const axiosError = error as AxiosError; + + // open({ + // title: `${axiosError?.response?.data}`, + // description: ``, + // type: 'single', + // typeOptions: { + // approveButtonText: '확인', + // buttonFunction: async () => await router.push(playgroundLink.coffeechat()), + // }, + // }); + // } + // }, [error, isError, open, router]); + const defaultForm = { memberInfo: { - career: '주니어 (0-3년)', //TODO: 데이터 가져와서 배열에 담기 - introduction: '안녕하세요! 저는 프론트엔드 개발자로 다양한 프로젝트 경험을 쌓고 있습니다.', + career: openerProfile?.career, + introduction: openerProfile?.introduction, }, coffeeChatInfo: { - sections: ['프론트', '디자인'], - bio: '프론트엔드 커리어 상담', - topicTypes: ['포트폴리오', '이력서/자소서'], - topic: '프론트엔드 개발자로서의 커리어에 대해 상담하고 싶습니다.\n포트폴리오 제작과 인터뷰 팁도 나누고자 합니다.', - meetingType: '온라인', - guideline: '시간 약속을 꼭 지켜주세요.\n질문은 미리 준비해 오시면 더욱 좋습니다.', + sections: openerProfile?.sections, + bio: openerProfile?.bio, + topicTypes: openerProfile?.topicTypeList, + topic: openerProfile?.topic, + meetingType: openerProfile?.meetingType, + guideline: openerProfile?.guideline, }, }; - if (isPending) { - // TODO: 데이터 get 해올 때의 isPending도 추가 - return ; + if (isDetailPending || isEditPending) { + return ; } return ( - + {(status === 'loading' || status === 'error') && null} + {status === 'success' && openerProfile && memberId === String(me?.id) && !isError ? ( + + ) : null} ); }; diff --git a/src/pages/coffeechat/index.tsx b/src/pages/coffeechat/index.tsx index 8b958ade6..49e0b6b59 100644 --- a/src/pages/coffeechat/index.tsx +++ b/src/pages/coffeechat/index.tsx @@ -1,17 +1,17 @@ -import AuthRequired from "@/components/auth/AuthRequired"; -import CoffeeChatCategory from "@/components/coffeechat/CoffeeChatCategory"; -import CoffeeChatRecentList from "@/components/coffeechat/CoffeeRecentChatList"; -import Header from "@/components/common/Header"; -import { setLayout } from "@/utils/layout"; +import AuthRequired from '@/components/auth/AuthRequired'; +import CoffeeChatCategory from '@/components/coffeechat/CoffeeChatCategory'; +import CoffeeChatRecentList from '@/components/coffeechat/CoffeeRecentChatList'; +import { setLayout } from '@/utils/layout'; -const CoffeeChatMainPage=()=>{ - return ( +const CoffeeChatMainPage = () => { + return ( - - - ) -} + + + + ); +}; setLayout(CoffeeChatMainPage, 'headerFooter'); setLayout(CoffeeChatMainPage, 'header'); setLayout(CoffeeChatMainPage, 'headerOnlyDesktop'); -export default CoffeeChatMainPage; \ No newline at end of file +export default CoffeeChatMainPage; diff --git a/src/pages/coffeechat/upload.tsx b/src/pages/coffeechat/upload.tsx index 662ded0bd..e5672153d 100644 --- a/src/pages/coffeechat/upload.tsx +++ b/src/pages/coffeechat/upload.tsx @@ -1,16 +1,21 @@ -import { useMutation } from '@tanstack/react-query'; +import { DialogOptionType, useDialog, useToast } from '@sopt-makers/ui'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; +import { useRouter } from 'next/router'; +import { playgroundLink } from 'playground-common/export'; +import { FieldValues } from 'react-hook-form'; import { uploadCoffeechat } from '@/api/endpoint/coffeechat/uploadCoffeechat'; import AuthRequired from '@/components/auth/AuthRequired'; +import CoffeechatLoading from '@/components/coffeechat/Loading'; import CoffeechatUploadPage from '@/components/coffeechat/page/CoffeechatUploadPage'; import { CoffeechatFormContent } from '@/components/coffeechat/upload/CoffeechatForm/types'; -import Loading from '@/components/common/Loading'; import { setLayout } from '@/utils/layout'; -import { FieldValues } from 'react-hook-form'; const CoffeechatUpload = () => { - // const router = useRouter(); - // const queryClient = useQueryClient(); + const router = useRouter(); + const queryClient = useQueryClient(); + const { open: toastOpen } = useToast(); + const { open } = useDialog(); const { mutate, isPending } = useMutation({ mutationFn: (reqeustBody: CoffeechatFormContent) => uploadCoffeechat.request({ ...reqeustBody }), @@ -22,42 +27,40 @@ const CoffeechatUpload = () => { mutate( { - memberInfo: { ...memberInfo, career: memberInfo.career ? memberInfo.career[0] : null }, - coffeeChatInfo: { ...coffeeChatInfo }, + memberInfo: { + ...memberInfo, + career: memberInfo.career + ? Array.isArray(memberInfo.career) + ? memberInfo.career[0] + : memberInfo.career + : null, + }, + coffeeChatInfo: { ...coffeeChatInfo, meetingType: coffeeChatInfo.meetingType ?? '온/오프라인' }, }, { onSuccess: async () => { - // TODO: 쿼리 무효화 및 페이지 이동 처리 - // queryClient.invalidateQueries({ queryKey: 'coffeechat' }); - // await router.push(playgroundLink.coffeechat()); + queryClient.invalidateQueries({ + predicate: (query) => ['getRecentCoffeeChat', 'getMembersCoffeeChat'].includes(query.queryKey[0] as string), + }); + toastOpen({ icon: 'success', content: '커피챗이 오픈됐어요! 경험을 나눠주셔서 감사해요.' }); + await router.push(playgroundLink.coffeechat()); }, onError: (error) => { - console.error('업로드 실패:', error); + const option: DialogOptionType = { + title: `${error.message}`, + description: ``, + type: 'single', + typeOptions: { + approveButtonText: '확인', + buttonFunction: async () => await router.push(playgroundLink.coffeechat()), + }, + }; + open(option); }, }, ); }; - // const onSubmit = (data: CoffeechatFormContent) => { - // const { memberInfo, coffeeChatInfo } = data; - // mutate( - // { - // memberInfo: { ...memberInfo, career: memberInfo.career ? memberInfo.career[0] : null }, - // coffeeChatInfo: { ...coffeeChatInfo }, - // }, - // { - // onSuccess: async () => { - // // TODO: 쿼리 무효화 및 페이지 이동 처리 - // // queryClient.invalidateQueries({ queryKey: 'coffeechat' }); - // // await router.push(playgroundLink.coffeechat()); - // }, - // onError: (error) => { - // console.error('업로드 실패:', error); - // }, - // }, - // ); - // }; - const defaultForm = { memberInfo: { career: null, @@ -74,7 +77,7 @@ const CoffeechatUpload = () => { }; if (isPending) { - return ; + return ; } return (