From 8a020c5ecceb0a0bf5af0bf2db67df0bedbc7bb4 Mon Sep 17 00:00:00 2001 From: seojisoosoo <76681519+seojisoosoo@users.noreply.github.com> Date: Wed, 6 Nov 2024 22:49:05 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=BB=A4=ED=94=BC=EC=B1=97=20QA=20(#16?= =?UTF-8?q?65)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 진행 방식 디폴트 선택 방식 변경 * feat: 수정 후, 멤버 정보 리패치 추가 * feat: mds ui 버전 업 * feat: 딤드 처리 * feat: css 수정 * feat: 커피챗 존재하는 경우 여부 서버 데이터 받아오기 * feat: 이미 커피챗을 연 유저가 url로 업로드 페이지 접속 시 예외처리 * fix: 빌드 타입 에러 수정 * feat: 삭제 후 me 데이터 리패치 * feat: 진행방식 defaultValue 수정 * feat: 예외처리 수정 * feat: hasCoffeeChat 변경 및 비활성된 커피챗 예외처리 --- package.json | 4 +-- .../coffeechat/getCoffeechatDetail.ts | 6 ++--- src/api/endpoint/members/getMemberOfMe.ts | 1 + .../coffeechat/CoffeeRecentChatList/index.tsx | 11 +++----- .../detail/CoffeechatContents/index.tsx | 2 +- .../coffeechat/detail/OpenerProfile/index.tsx | 20 ++++++++++++-- .../coffeechat/detail/SeemoreSelect/index.tsx | 8 +++--- .../detail/ShowCoffeechatToggle/index.tsx | 3 ++- src/components/coffeechat/detail/index.tsx | 26 ++++++++++++++++--- .../layout/MobileCoffeechatUploadLayout.tsx | 7 ++--- .../CoffeechatInfoForm/index.tsx | 5 +--- src/pages/coffeechat/edit/[id].tsx | 10 ++++--- src/pages/coffeechat/upload.tsx | 24 ++++++++++++++--- yarn.lock | 23 +++++++++++----- 14 files changed, 104 insertions(+), 46 deletions(-) diff --git a/package.json b/package.json index 0b28d9b80..8321b5dc4 100644 --- a/package.json +++ b/package.json @@ -42,10 +42,10 @@ "@radix-ui/react-slot": "^1.0.1", "@radix-ui/react-tabs": "^1.0.2", "@radix-ui/react-tooltip": "^1.0.5", - "@sopt-makers/colors": "^3.0.0", + "@sopt-makers/colors": "^3.0.2", "@sopt-makers/fonts": "^1.0.0", "@sopt-makers/icons": "^1.0.5", - "@sopt-makers/ui": "^2.7.1", + "@sopt-makers/ui": "^2.7.6", "@tanstack/react-query": "^5.4.3", "@toss/emotion-utils": "^1.1.10", "@toss/error-boundary": "^1.4.6", diff --git a/src/api/endpoint/coffeechat/getCoffeechatDetail.ts b/src/api/endpoint/coffeechat/getCoffeechatDetail.ts index e67cbc11d..c9f7f0e91 100644 --- a/src/api/endpoint/coffeechat/getCoffeechatDetail.ts +++ b/src/api/endpoint/coffeechat/getCoffeechatDetail.ts @@ -10,11 +10,11 @@ const CoffeechatDetailSchema = z.object({ career: z.string(), organization: z.string().nullable(), memberCareerTitle: z.string().nullable(), - phone: z.string(), + phone: z.string().nullable(), email: z.string(), - introduction: z.string(), + introduction: z.string().nullable(), // TODO: 커피챗 오픈 후, nullable 삭제 필요 topicTypeList: z.array(z.string()), - topic: z.string(), + topic: z.string().nullable(), // TODO: 커피챗 오픈 후, nullable 삭제 필요 meetingType: z.string(), guideline: z.string().nullable(), isMine: z.boolean().nullable(), diff --git a/src/api/endpoint/members/getMemberOfMe.ts b/src/api/endpoint/members/getMemberOfMe.ts index 3bf9068c4..639c51c67 100644 --- a/src/api/endpoint/members/getMemberOfMe.ts +++ b/src/api/endpoint/members/getMemberOfMe.ts @@ -18,6 +18,7 @@ export const getMemberOfMe = createEndpoint({ hasProfile: z.boolean(), profileImage: z.string().nullable(), editActivitiesAble: z.boolean(), + hasCoffeeChat: z.boolean(), }), }); diff --git a/src/components/coffeechat/CoffeeRecentChatList/index.tsx b/src/components/coffeechat/CoffeeRecentChatList/index.tsx index 70c223b91..ee197ccca 100644 --- a/src/components/coffeechat/CoffeeRecentChatList/index.tsx +++ b/src/components/coffeechat/CoffeeRecentChatList/index.tsx @@ -6,6 +6,7 @@ import { useRouter } from 'next/router'; import { playgroundLink } from 'playground-common/export'; import { ReactNode, startTransition, useEffect, useState } from 'react'; +import { useGetMemberOfMe } from '@/api/endpoint/members/getMemberOfMe'; import { useGetRecentCoffeeChat } from '@/api/endpoint/members/getRecentCoffeeChats'; import CoffeeChatCard from '@/components/coffeechat/CoffeeChatCard'; import ScrollCarousel from '@/components/coffeechat/CoffeeRecentChatList/scrollCarousel'; @@ -44,7 +45,7 @@ export default function CoffeeChatList() { const { logClickEvent } = useEventLogger(); const { open } = useDialog(); const { data, isLoading } = useGetRecentCoffeeChat(); - + const { data: me } = useGetMemberOfMe(); const isEmptyData = data?.coffeeChatList == null; const dataList = !isEmptyData ? data.coffeeChatList : COFFECHAT_SAMPLE_DATA.coffeeChatList; const formatSoptActivities = (soptActivities: string[])=> { @@ -166,8 +167,6 @@ export default function CoffeeChatList() { }, }); }; - // TODO: 서버 데이터로 변경 - const hasCoffeechat = false; return ( @@ -180,8 +179,7 @@ export default function CoffeeChatList() { size='lg' theme='white' onClick={() => { - router.push(playgroundLink.coffeechatUpload()); - hasCoffeechat ? alreadyOpenedOption() : startOpenOption(); + me?.hasCoffeeChat ? alreadyOpenedOption() : startOpenOption(); }} > 커피챗 오픈하기 @@ -194,8 +192,7 @@ export default function CoffeeChatList() { size='md' theme='white' onClick={() => { - router.push(playgroundLink.coffeechatUpload()); - hasCoffeechat ? alreadyOpenedOption() : startOpenOption(); + me?.hasCoffeeChat ? alreadyOpenedOption() : startOpenOption(); }} > 커피챗 오픈하기 diff --git a/src/components/coffeechat/detail/CoffeechatContents/index.tsx b/src/components/coffeechat/detail/CoffeechatContents/index.tsx index 5ad1ff0c1..8e4fe7cf2 100644 --- a/src/components/coffeechat/detail/CoffeechatContents/index.tsx +++ b/src/components/coffeechat/detail/CoffeechatContents/index.tsx @@ -16,7 +16,7 @@ export default function CoffeechatContents({ memberId }: CoffeechatContentsProps <> {openerProfile && ( - {openerProfile.introduction.trim() && ( + {openerProfile.introduction && openerProfile.introduction.trim() && ( {openerProfile.introduction} diff --git a/src/components/coffeechat/detail/OpenerProfile/index.tsx b/src/components/coffeechat/detail/OpenerProfile/index.tsx index a5ffce937..90c3069d4 100644 --- a/src/components/coffeechat/detail/OpenerProfile/index.tsx +++ b/src/components/coffeechat/detail/OpenerProfile/index.tsx @@ -11,6 +11,7 @@ import RegisterCoffeechatButton from '@/components/coffeechat/detail/RegisterCof import ShowCoffeechatToggle from '@/components/coffeechat/detail/ShowCoffeechatToggle'; import useModalState from '@/components/common/Modal/useModalState'; import { MOBILE_MEDIA_QUERY } from '@/styles/mediaQuery'; +import { useDialog } from '@sopt-makers/ui'; interface OpenerProfileProps { memberId: string; @@ -19,6 +20,21 @@ interface OpenerProfileProps { export default function OpenerProfile({ memberId }: OpenerProfileProps) { const { data: openerProfile } = useGetCoffeechatDetail(memberId); const { isOpen: isOpenMessageModal, onOpen: onOpenMessageModal, onClose: onCloseMessageModal } = useModalState(); + const { open } = useDialog(); + + const handleImpossibleToRegister = () => { + open({ + title: `비활성화된 커피챗이에요.`, + description: ``, + type: 'single', + typeOptions: { + approveButtonText: '확인', + buttonFunction: async () => { + // + }, + }, + }); + }; return ( <> @@ -57,7 +73,7 @@ export default function OpenerProfile({ memberId }: OpenerProfileProps) { ) : ( { - onOpenMessageModal(); + openerProfile.isCoffeeChatActivate ? onOpenMessageModal() : handleImpossibleToRegister(); }} /> )} @@ -174,7 +190,7 @@ const OpenerProfileSection = styled.section<{ isMine: boolean }>` grid: [row1-start] 'profileImageBox profileInfoBox buttonSection' auto [row1-end]/ auto; grid-template-columns: 1fr 5fr 2fr; gap: 28px; - align-items: ${({ isMine }) => (isMine ? 'flex-end' : 'center')}; + align-items: center; justify-content: space-between; width: 100%; diff --git a/src/components/coffeechat/detail/SeemoreSelect/index.tsx b/src/components/coffeechat/detail/SeemoreSelect/index.tsx index 01f2949a9..2aa17a753 100644 --- a/src/components/coffeechat/detail/SeemoreSelect/index.tsx +++ b/src/components/coffeechat/detail/SeemoreSelect/index.tsx @@ -71,6 +71,7 @@ export default function SeemoreSelect({ memberId }: SeemoreSelectProp) { queryClient.invalidateQueries({ predicate: (query) => ['getRecentCoffeeChat', 'getMembersCoffeeChat'].includes(query.queryKey[0] as string), }); + queryClient.invalidateQueries({ queryKey: ['getMemberOfMe'] }); toastOpen({ icon: 'success', content: '커피챗이 삭제되었어요. 다음에 또 만나요!' }); await router.push(playgroundLink.coffeechat()); }, @@ -128,9 +129,6 @@ const BottomSheetSeemore = ({ onEdit, onDelete }: SeemoreContentProps) => { - - - { + ); @@ -163,7 +162,7 @@ const Overlay = styled.div` position: fixed; inset: 0; z-index: 101; - background-color: rgb(0 0 0 / 70%); + background-color: ${colors.backgroundDimmed}; animation: overlay-show 0.3s cubic-bezier(0.16, 1, 0.3, 1); @keyframes overlay-show { @@ -183,6 +182,7 @@ const StyledContent = styled.div` gap: 6px; border-radius: 13px; background-color: ${colors.gray800}; + cursor: pointer; padding: 8px; @media ${MOBILE_MEDIA_QUERY} { diff --git a/src/components/coffeechat/detail/ShowCoffeechatToggle/index.tsx b/src/components/coffeechat/detail/ShowCoffeechatToggle/index.tsx index 242697cdd..d45a8152b 100644 --- a/src/components/coffeechat/detail/ShowCoffeechatToggle/index.tsx +++ b/src/components/coffeechat/detail/ShowCoffeechatToggle/index.tsx @@ -53,12 +53,13 @@ const ToggleSection = styled.div` display: flex; gap: 8px; justify-content: flex-end; - margin-bottom: 8px; + margin-top: 85px; color: ${colors.gray300}; ${fonts.BODY_16_R}; @media ${MOBILE_MEDIA_QUERY} { float: left; + margin-top: 0; margin-bottom: 0; } diff --git a/src/components/coffeechat/detail/index.tsx b/src/components/coffeechat/detail/index.tsx index c90c6a80b..39c7f8cd4 100644 --- a/src/components/coffeechat/detail/index.tsx +++ b/src/components/coffeechat/detail/index.tsx @@ -1,7 +1,7 @@ import styled from '@emotion/styled'; import { colors } from '@sopt-makers/colors'; import { fonts } from '@sopt-makers/fonts'; -import { useMemo } from 'react'; +import { useEffect, useMemo } from 'react'; import { useGetCoffeechatDetail } from '@/api/endpoint/coffeechat/getCoffeechatDetail'; import { useGetMemberOfMe } from '@/api/endpoint/members/getMemberOfMe'; @@ -17,16 +17,20 @@ import ProjectSection from '@/components/members/detail/ProjectSection'; import SoptActivitySection from '@/components/members/detail/SoptActivitySection'; import { MOBILE_MEDIA_QUERY } from '@/styles/mediaQuery'; import { safeParseInt } from '@/utils'; +import { useDialog } from '@sopt-makers/ui'; +import { useRouter } from 'next/router'; +import { playgroundLink } from 'playground-common/export'; interface CoffeechatDetailProp { memberId: string; } export default function CoffeechatDetail({ memberId }: CoffeechatDetailProp) { - const { data: openerProfile } = useGetCoffeechatDetail(memberId); + const { data: openerProfile, isError, error } = useGetCoffeechatDetail(memberId); const { data: profile } = useGetMemberProfileById(safeParseInt(memberId) ?? undefined); - const { data: me } = useGetMemberOfMe(); + const router = useRouter(); + const { open } = useDialog(); const sortedSoptActivities = useMemo(() => { if (!profile?.soptActivities) { @@ -37,6 +41,21 @@ export default function CoffeechatDetail({ memberId }: CoffeechatDetailProp) { return sorted; }, [profile?.soptActivities]); + useEffect(() => { + isError && + open({ + title: `커피챗 정보를 확인할 수 없는 유저입니다.`, + description: `${error.message}`, + type: 'single', + typeOptions: { + approveButtonText: '확인', + buttonFunction: async () => { + await router.push(playgroundLink.coffeechat()); + }, + }, + }); + }, [isError]); + return ( @@ -44,7 +63,6 @@ export default function CoffeechatDetail({ memberId }: CoffeechatDetailProp) { <> {openerProfile.bio} - {/* TODO: 더보기 버튼 기능 구현 */} <>{openerProfile.isMine && } diff --git a/src/components/coffeechat/page/layout/MobileCoffeechatUploadLayout.tsx b/src/components/coffeechat/page/layout/MobileCoffeechatUploadLayout.tsx index e771afb8a..6e4d65489 100644 --- a/src/components/coffeechat/page/layout/MobileCoffeechatUploadLayout.tsx +++ b/src/components/coffeechat/page/layout/MobileCoffeechatUploadLayout.tsx @@ -1,8 +1,9 @@ -import { COFFEECHAT_MOBILE_MEDIA_QUERY } from '@/components/coffeechat/mediaQuery'; -import { MOBILE_MEDIA_QUERY } from '@/styles/mediaQuery'; import styled from '@emotion/styled'; import { ReactNode } from 'react'; +import { COFFEECHAT_MOBILE_MEDIA_QUERY } from '@/components/coffeechat/mediaQuery'; +import { MOBILE_MEDIA_QUERY } from '@/styles/mediaQuery'; + interface MobileCoffeechatUploadLayoutProps { main: ReactNode; submitButton: ReactNode; @@ -28,7 +29,7 @@ const Layout = styled.div` } @media ${COFFEECHAT_MOBILE_MEDIA_QUERY} { - margin-top: 0; + margin-top: 30px; } `; diff --git a/src/components/coffeechat/upload/CoffeechatForm/CoffeechatInfoForm/index.tsx b/src/components/coffeechat/upload/CoffeechatForm/CoffeechatInfoForm/index.tsx index 267db727c..833b7c404 100644 --- a/src/components/coffeechat/upload/CoffeechatForm/CoffeechatInfoForm/index.tsx +++ b/src/components/coffeechat/upload/CoffeechatForm/CoffeechatInfoForm/index.tsx @@ -128,10 +128,7 @@ export default function CoffeechatInfoForm() { option.value === field.value) ?? - MEETING_TYPE_OPTIONS[MEETING_TYPE_OPTIONS.length - 1] - } + defaultValue={MEETING_TYPE_OPTIONS.find((option) => option.value === field.value)} onChange={(value) => field.onChange(value)} > diff --git a/src/pages/coffeechat/edit/[id].tsx b/src/pages/coffeechat/edit/[id].tsx index 2867de6da..39c4d40ac 100644 --- a/src/pages/coffeechat/edit/[id].tsx +++ b/src/pages/coffeechat/edit/[id].tsx @@ -5,7 +5,7 @@ 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 { getCoffeechatDetail, 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'; @@ -44,21 +44,23 @@ const CoffeechatEdit = () => { : memberInfo.career : null, }, - coffeeChatInfo: { ...coffeeChatInfo, meetingType: coffeeChatInfo.meetingType ?? '온/오프라인' }, + coffeeChatInfo: { ...coffeeChatInfo }, }, { onSuccess: async () => { queryClient.invalidateQueries({ predicate: (query) => ['getRecentCoffeeChat', 'getMembersCoffeeChat'].includes(query.queryKey[0] as string), }); + + queryClient.invalidateQueries({ queryKey: getCoffeechatDetail.cacheKey(memberId) }); toastOpen({ icon: 'success', content: '커피챗이 오픈됐어요! 경험을 나눠주셔서 감사해요.' }); logSubmitEvent('editCoffeechat'); await router.push(playgroundLink.coffeechatDetail(me?.id ?? '')); }, onError: (error) => { const option: DialogOptionType = { - title: `${error.message}`, - description: ``, + title: `오류가 발생했어요.`, + description: `${error.message}`, type: 'single', typeOptions: { approveButtonText: '확인', diff --git a/src/pages/coffeechat/upload.tsx b/src/pages/coffeechat/upload.tsx index 09a9af964..8ad872f60 100644 --- a/src/pages/coffeechat/upload.tsx +++ b/src/pages/coffeechat/upload.tsx @@ -2,7 +2,7 @@ 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 { useMemo } from 'react'; +import { useEffect, useMemo } from 'react'; import { FieldValues } from 'react-hook-form'; import { uploadCoffeechat } from '@/api/endpoint/coffeechat/uploadCoffeechat'; @@ -25,6 +25,21 @@ const CoffeechatUpload = () => { const { data: me } = useGetMemberOfMe(); const { data: profile } = useGetMemberProfileById(me?.id ?? undefined); + useEffect(() => { + me?.hasCoffeeChat && + open({ + title: `이미 오픈한 커피챗이 있어요!`, + description: `커피챗은 한 개만 오픈할 수 있어요. 등록된 커피챗을 삭제한 후 다시 시도해주세요.`, + type: 'single', + typeOptions: { + approveButtonText: '확인', + buttonFunction: async () => { + await router.push(playgroundLink.coffeechat()); + }, + }, + }); + }, [me?.hasCoffeeChat]); + const sortedSoptActivities = useMemo(() => { if (!profile?.soptActivities) { return []; @@ -55,13 +70,14 @@ const CoffeechatUpload = () => { : memberInfo.career : null, }, - coffeeChatInfo: { ...coffeeChatInfo, meetingType: coffeeChatInfo.meetingType ?? '온/오프라인' }, + coffeeChatInfo: { ...coffeeChatInfo }, }, { onSuccess: async () => { queryClient.invalidateQueries({ predicate: (query) => ['getRecentCoffeeChat', 'getMembersCoffeeChat'].includes(query.queryKey[0] as string), }); + queryClient.invalidateQueries({ queryKey: ['getMemberOfMe'] }); logSubmitEvent('openCoffeechat', { career: memberInfo.career ? Array.isArray(memberInfo.career) @@ -88,8 +104,8 @@ const CoffeechatUpload = () => { }, onError: (error) => { const option: DialogOptionType = { - title: `${error.message}`, - description: ``, + title: `오류가 발생했어요.`, + description: `${error.message}`, type: 'single', typeOptions: { approveButtonText: '확인', diff --git a/yarn.lock b/yarn.lock index e8046a405..a9c0dd7cf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6247,6 +6247,15 @@ __metadata: languageName: node linkType: hard +"@sopt-makers/icons@npm:^1.0.6": + version: 1.0.6 + resolution: "@sopt-makers/icons@npm:1.0.6" + peerDependencies: + react: ^18.2.0 + checksum: 372f5853f04a847c48e437200d8fb2a8f58da025785e6078e7c66bfb1ea943fc69072b9c1e5503f2778c1d5935509c2319c6fe8593b35c513c3e0daa380f659b + languageName: node + linkType: hard + "@sopt-makers/playground-common@workspace:playground-common": version: 0.0.0-use.local resolution: "@sopt-makers/playground-common@workspace:playground-common" @@ -6263,22 +6272,22 @@ __metadata: languageName: unknown linkType: soft -"@sopt-makers/ui@npm:^2.7.1": - version: 2.7.1 - resolution: "@sopt-makers/ui@npm:2.7.1" +"@sopt-makers/ui@npm:^2.7.6": + version: 2.7.6 + resolution: "@sopt-makers/ui@npm:2.7.6" dependencies: "@radix-ui/react-dialog": ^1.0.5 "@radix-ui/react-switch": ^1.0.3 "@sopt-makers/colors": ^3.0.2 "@sopt-makers/fonts": ^2.0.1 - "@sopt-makers/icons": ^1.0.5 + "@sopt-makers/icons": ^1.0.6 "@vanilla-extract/css": ^1.14.0 "@vanilla-extract/sprinkles": 1.6.1 tsup: ^8.0.2 peerDependencies: react: ^18.2.0 react-dom: ^18.2.0 - checksum: edd1ca53740b1881b2c4cfdb21902665a4a606d33a4eb2d52b1c591a651529f7a9fef4bf14327d8cba4da713236c06017ae319b708190184f7824bfa703e39c2 + checksum: e9ffee288f06f44c35a62bcfa661ba48c0fb8a27e23fc5be4df986c144dfabb55ebb7c4ef487b2f87f689e6834bcee468632ad5a042497a0aff718730203e8e0 languageName: node linkType: hard @@ -19800,10 +19809,10 @@ __metadata: "@radix-ui/react-slot": ^1.0.1 "@radix-ui/react-tabs": ^1.0.2 "@radix-ui/react-tooltip": ^1.0.5 - "@sopt-makers/colors": ^3.0.0 + "@sopt-makers/colors": ^3.0.2 "@sopt-makers/fonts": ^1.0.0 "@sopt-makers/icons": ^1.0.5 - "@sopt-makers/ui": ^2.7.1 + "@sopt-makers/ui": ^2.7.6 "@storybook/addon-actions": ^7.0.23 "@storybook/addon-docs": ^7.0.23 "@storybook/addon-essentials": ^7.0.23