From 180c632b3d72fd4972ba4b3ac6ea2703860e0252 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9E=A5=EC=A0=95=EC=95=88?= <126966681+ExceptAnyone@users.noreply.github.com> Date: Sun, 15 Sep 2024 22:04:03 +0900 Subject: [PATCH 1/2] =?UTF-8?q?[design/#260]=20=EB=8B=89=EB=84=A4=EC=9E=84?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=20=EB=AA=A8=EB=8B=AC=20=EA=B5=AC=ED=98=84?= =?UTF-8?q?=20(#288)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: ic_edit_20 아이콘 추가 * Comment: Input 컴포넌트 min-width 주석처리 * feat: 게스트 닉네임 변경 api 함수 작성 * feat: width 100% 삭제 * feat: 쿼리키 추가 * feat: Input 컴포넌트 내 커스텀 스타일 추가 * feat: 닉네임 변경 모달 오픈 로직 * feat: 게스트 닉네임 변경 모달 뷰 구현 * feat: onChange 함수 내 validation 수정 * feat: 닉네임 변경 모달 내 활성화 된 버튼 스타일 수정 * feat: Input 공통 컴포넌트 내 customBorderColor prop 추가 * feat: 닉네임 변경 모달 내 validation에 따른 border color 수정 * feat: 콘솔로그로 데이터 추적 -> undefined 이슈 * feat: import 순서 정렬 * feat: 닉네임 변경 시 화면에 바로 반영되게 수정 * feat: 콘솔로그 제거 * feat: 콘솔로그 제거 * feat: 타입 단언 수정 * feat: useState 내 자동 타입추론으로 인한 제네릭 제거 * feat: return값에서 null 제거 --- public/svg/ic_edit_20.svg | 4 + src/apis/domains/guest/useFetchGuestInfo.ts | 5 +- .../domains/guest/usePatchGuestNickname.ts | 41 ++++++ src/apis/queryKeys/queryKeys.ts | 1 + src/assets/svg/IcEdit20.tsx | 11 ++ src/assets/svg/index.ts | 1 + .../SimpleUserProfile.style.ts | 1 - .../common/inputs/Input/Input.style.ts | 45 ++++--- src/components/common/inputs/Input/Input.tsx | 13 +- .../ChangeNicknameModal.style.ts | 92 ++++++++++++++ .../ChangeNicknameModal.tsx | 117 ++++++++++++++++++ .../page/GuestMyPage/GuestMyPage.style.ts | 9 ++ .../myPage/page/GuestMyPage/GuestMyPage.tsx | 22 +++- 13 files changed, 336 insertions(+), 26 deletions(-) create mode 100644 public/svg/ic_edit_20.svg create mode 100644 src/apis/domains/guest/usePatchGuestNickname.ts create mode 100644 src/assets/svg/IcEdit20.tsx create mode 100644 src/pages/myPage/components/ChangeNicknameModal/ChangeNicknameModal.style.ts create mode 100644 src/pages/myPage/components/ChangeNicknameModal/ChangeNicknameModal.tsx diff --git a/public/svg/ic_edit_20.svg b/public/svg/ic_edit_20.svg new file mode 100644 index 00000000..d715a208 --- /dev/null +++ b/public/svg/ic_edit_20.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/apis/domains/guest/useFetchGuestInfo.ts b/src/apis/domains/guest/useFetchGuestInfo.ts index e1b7fd9c..1cc61e79 100644 --- a/src/apis/domains/guest/useFetchGuestInfo.ts +++ b/src/apis/domains/guest/useFetchGuestInfo.ts @@ -1,4 +1,4 @@ -import { useSuspenseQuery } from '@tanstack/react-query'; +import { useQuery } from '@tanstack/react-query'; import { get } from '@apis/api'; import { QUERY_KEY } from '@apis/queryKeys/queryKeys'; @@ -18,8 +18,9 @@ const getGuestInfo = async (guestId: string): Promise = }; export const useFetchGuestInfo = (guestId: string) => { - return useSuspenseQuery({ + return useQuery({ queryKey: [QUERY_KEY.GUEST_INFO], queryFn: () => getGuestInfo(guestId), + enabled: !!guestId, }); }; diff --git a/src/apis/domains/guest/usePatchGuestNickname.ts b/src/apis/domains/guest/usePatchGuestNickname.ts new file mode 100644 index 00000000..b7cf0107 --- /dev/null +++ b/src/apis/domains/guest/usePatchGuestNickname.ts @@ -0,0 +1,41 @@ +import { useMutation, useQueryClient } from '@tanstack/react-query'; + +import { patch } from '@apis/api'; +import { QUERY_KEY } from '@apis/queryKeys/queryKeys'; + +import { components } from '@schema'; +import { ApiResponseType, ErrorType } from '@types'; + +type GuestUpdateRequest = components['schemas']['GuestUpdateRequest']; +const patchGuestNickname = async ( + guestId: number, + guestNickname: string +): Promise => { + try { + const response = await patch>(`/v2/guest/${guestId}`, { + guestNickname, + }); + + return response.data.data; + } catch (err) { + console.error('API error:', err); + throw err; + } +}; + +export const usePatchGuestNickname = (guestId: number, setErrorMessage: (msg: string) => void) => { + const queryClient = useQueryClient(); + return useMutation({ + mutationFn: (guestNickname: string) => patchGuestNickname(guestId, guestNickname), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: [QUERY_KEY.GUEST_INFO] }); + }, + onError: (error: ErrorType) => { + if (error.status === 40008) { + setErrorMessage('* 이미 존재하는 닉네임이에요.'); + } else { + setErrorMessage('닉네임 변경 중 오류가 발생했습니다. 다시 시도해 주세요.'); + } + }, + }); +}; diff --git a/src/apis/queryKeys/queryKeys.ts b/src/apis/queryKeys/queryKeys.ts index e0d6343a..79f5f627 100644 --- a/src/apis/queryKeys/queryKeys.ts +++ b/src/apis/queryKeys/queryKeys.ts @@ -10,6 +10,7 @@ export const QUERY_KEY = { MY_HOST_INFO: 'myHostInfo', GUEST_PARTICIPATE: 'guestParticipateMoim', GUEST_APPLY: 'guestApplyMoim', + GUEST_NICKNAME_CHANGE: 'guestNicknameChange', HOST_MOIM_INFO: 'hostMoimInfo', MOIM_DETAIL: 'moimDetail', APPLICANT_LIST: 'applicantList', diff --git a/src/assets/svg/IcEdit20.tsx b/src/assets/svg/IcEdit20.tsx new file mode 100644 index 00000000..fec5b332 --- /dev/null +++ b/src/assets/svg/IcEdit20.tsx @@ -0,0 +1,11 @@ +import type { SVGProps } from 'react'; +const SvgIcEdit20 = (props: SVGProps) => ( + + + + +); +export default SvgIcEdit20; diff --git a/src/assets/svg/index.ts b/src/assets/svg/index.ts index d6ee9cba..aaab3e00 100644 --- a/src/assets/svg/index.ts +++ b/src/assets/svg/index.ts @@ -25,6 +25,7 @@ export { default as IcDropdownPlatformDown } from './IcDropdownPlatformDown'; export { default as IcDropdownPlatformUp } from './IcDropdownPlatformUp'; export { default as IcDropdownRight } from './IcDropdownRight'; export { default as IcDropdownUp } from './IcDropdownUp'; +export { default as IcEdit20 } from './IcEdit20'; export { default as IcEdit } from './IcEdit'; export { default as IcEmploymentActive } from './IcEmploymentActive'; export { default as IcEmploymentBlack } from './IcEmploymentBlack'; diff --git a/src/components/common/SimpleUserProfile/SimpleUserProfile.style.ts b/src/components/common/SimpleUserProfile/SimpleUserProfile.style.ts index 7b26074a..8abfdbff 100644 --- a/src/components/common/SimpleUserProfile/SimpleUserProfile.style.ts +++ b/src/components/common/SimpleUserProfile/SimpleUserProfile.style.ts @@ -5,7 +5,6 @@ import { flexGenerator } from '@styles/generator'; export const profileWrapperStyle = css` ${flexGenerator('row', 'flex-start', 'center')} gap: 1rem; - width: 100%; `; export const profileWrapperSizeStyle = { xlarge: css` diff --git a/src/components/common/inputs/Input/Input.style.ts b/src/components/common/inputs/Input/Input.style.ts index be55ebc4..bfad1ab5 100644 --- a/src/components/common/inputs/Input/Input.style.ts +++ b/src/components/common/inputs/Input/Input.style.ts @@ -12,7 +12,7 @@ export const labelAndInputWrapper = css` ${flexGenerator('column', 'center', 'flex-start')} gap: 0.8rem; width: 100%; - min-width: 33.5rem; + /* min-width: 33.5rem; 삭제 모달 내 input 크기를 위해 주석처리 */ `; export const inputLabelStyle = (theme: Theme) => css` @@ -27,27 +27,34 @@ export const inputWrapperStyle = css` position: relative; `; -export const inputStyle = (isError: boolean, isFocused: boolean) => (theme: Theme) => css` - width: 100%; - height: 5.2rem; - padding: 1.5rem; - padding-right: 6rem; - border: 1px solid ${isError && isFocused ? theme.color.error : theme.color.lightgray1}; - border-radius: 10px; +export const inputStyle = + (isError: boolean, isFocused: boolean, customBorderColor?: string) => (theme: Theme) => css` + width: 100%; + height: 5.2rem; + padding: 1.5rem; + padding-right: 6rem; + border: 1px solid + ${isError && isFocused ? theme.color.error : theme.color.lightgray1 || customBorderColor}; + border-radius: 10px; - color: ${theme.color.blackgray}; - background-color: ${theme.color.white}; - ${theme.font['body01-r-15']} + color: ${theme.color.blackgray}; + background-color: ${theme.color.white}; + ${theme.font['body01-r-15']} - &::placeholder { - color: ${theme.color.midgray1}; - ${theme.font['body06-m-15']} - } + &::placeholder { + color: ${theme.color.midgray1}; + ${theme.font['body06-m-15']} + } - &:focus { - outline: none; - } -`; + &:focus { + outline: none; + } + &:focus-within { + ${customBorderColor && !isError + ? `border: 1px solid ${theme.color.purple1} ` + : `${theme.color.error}`} + } + `; export const deleteButtonStyle = css` position: absolute; diff --git a/src/components/common/inputs/Input/Input.tsx b/src/components/common/inputs/Input/Input.tsx index c97bc45a..19504f3f 100644 --- a/src/components/common/inputs/Input/Input.tsx +++ b/src/components/common/inputs/Input/Input.tsx @@ -1,3 +1,4 @@ +import { SerializedStyles } from '@emotion/react'; import React, { InputHTMLAttributes, forwardRef, useState } from 'react'; import { IcDelete20 } from '@svg'; @@ -21,6 +22,8 @@ export interface InputProps extends InputHTMLAttributes { inputLabel?: string; errorMessage?: string; isCountValue: boolean; + customStyle?: SerializedStyles; + customBorderColor?: string; } const Input = forwardRef( @@ -34,6 +37,8 @@ const Input = forwardRef( errorMessage, maxLength = 10, isCountValue = false, + customStyle, + customBorderColor, }, ref ) => { @@ -82,7 +87,7 @@ const Input = forwardRef(
(
- {isFocused && displayErrorMessage && ( + {isFocused && displayErrorMessage ? ( {displayErrorMessage} + ) : ( +
)} {isCountValue && ( - {value.length}/{maxLength} + {value?.length}/{maxLength} )}
diff --git a/src/pages/myPage/components/ChangeNicknameModal/ChangeNicknameModal.style.ts b/src/pages/myPage/components/ChangeNicknameModal/ChangeNicknameModal.style.ts new file mode 100644 index 00000000..5d82bf73 --- /dev/null +++ b/src/pages/myPage/components/ChangeNicknameModal/ChangeNicknameModal.style.ts @@ -0,0 +1,92 @@ +import { css, Theme } from '@emotion/react'; +import { flexGenerator } from '@styles/generator'; + +export const changeNicknameModalLayout = (theme: Theme) => css` + ${flexGenerator('column', 'center', 'center')}; + + width: 28.3rem; + height: 28.2rem; + padding: 3.7rem 1rem 1rem 1rem; + + border-radius: 10px; + background: ${theme.color.white}; + + gap: 2rem; +`; + +export const changeNicknameModalWrapper = css` + ${flexGenerator('column', 'center', 'center')}; + width: 100%; + gap: 2rem; +`; + +export const modalTitleWrapper = css` + ${flexGenerator('column', 'center', 'center')} + width: 100%; + gap: 3rem; +`; + +export const modalTitle = css` + ${flexGenerator('column', 'center', 'center')} + gap: 0.6rem; +`; + +export const titleStyle = (theme: Theme) => css` + color: ${theme.color.black}; + text-align: center; + ${theme.font['head03-b-18']} +`; + +export const blueColor = (theme: Theme) => css` + color: ${theme.color.purple1}; + text-align: center; + ${theme.font['subhead06-m-14']} +`; + +export const descriptionWrapper = css` + display: flex; + gap: 0.3rem; +`; + +export const descriptionStyle = (theme: Theme) => css` + color: ${theme.color.midgray2}; + text-align: center; + ${theme.font['body02-r-14']} +`; + +export const modalHeaderWrapper = css` + ${flexGenerator('column', 'center', 'center')} + gap: 0.3rem +`; + +export const inputWrapper = css` + width: 100%; +`; + +export const buttonWrapper = css` + ${flexGenerator()} + min-width: 26.3rem; + width: 100%; + gap: 0.9rem; +`; + +export const cancelButtonStyle = (theme: Theme) => css` + background-color: ${theme.color.lightgray1}; + text-align: center; + color: ${theme.color.midgray2}; + ${theme.font['subhead03-m-16']} +`; + +export const disabledStyle = (theme: Theme) => css` + border-radius: 5px; + background: ${theme.color.midgray1}; + color: ${theme.color.white}; + ${theme.font['subhead03-m-16']} +`; + +export const abledStyle = (theme: Theme) => css` + border-radius: 5px; + background: ${theme.color.purple1}; + color: ${theme.color.white}; + ${theme.font['subhead03-m-16']} +`; diff --git a/src/pages/myPage/components/ChangeNicknameModal/ChangeNicknameModal.tsx b/src/pages/myPage/components/ChangeNicknameModal/ChangeNicknameModal.tsx new file mode 100644 index 00000000..b3390412 --- /dev/null +++ b/src/pages/myPage/components/ChangeNicknameModal/ChangeNicknameModal.tsx @@ -0,0 +1,117 @@ +import { useAtom } from 'jotai'; +import { useState } from 'react'; + +import { usePatchGuestNickname } from '@apis/domains/guest/usePatchGuestNickname'; + +import { Button, Input } from '@components'; +import { userAtom } from '@stores'; +import theme from '@styles/theme'; + +import { + abledStyle, + blueColor, + buttonWrapper, + cancelButtonStyle, + changeNicknameModalLayout, + changeNicknameModalWrapper, + descriptionStyle, + descriptionWrapper, + disabledStyle, + inputWrapper, + modalHeaderWrapper, + modalTitle, + modalTitleWrapper, + titleStyle, +} from './ChangeNicknameModal.style'; + +interface ChangeNicknameModalProps { + onClose: () => void; +} + +const ChangeNicknameModal = ({ onClose }: ChangeNicknameModalProps) => { + const [user, setUser] = useAtom(userAtom); + const [value, setValue] = useState(user.guestNickname ?? ''); + const [hasError, setHasError] = useState(false); + const [errorMessage, setErrorMessage] = useState(''); + const { mutateAsync: changeNickname, isError } = usePatchGuestNickname( + user.guestId ?? 0, + setErrorMessage + ); + const handleInputChange = (e: React.ChangeEvent) => { + const newValue = e.target.value; + setValue(newValue); + + // 길이가 0 이상이고 15자 이하일 때는 에러 없음 + if (newValue.length > 0 && newValue.length <= 15) { + setErrorMessage(''); + setHasError(false); + } else { + setHasError(true); + } + }; + + const handleButtonClick = () => { + if (!isError) { + changeNickname(value).then(() => { + setUser({ ...user, guestNickname: value }); + + const storedUser = localStorage.getItem('user'); + if (storedUser) { + const updatedUser = JSON.parse(storedUser); + updatedUser.guestNickname = value; + + localStorage.setItem('user', JSON.stringify(updatedUser)); + } + }); + onClose(); + } else { + setErrorMessage('닉네임 변경 중 오류가 발생했습니다. 다시 시도해 주세요.'); + } + }; + + return ( +
+
+
+
+

닉네임 변경

+
+
+

잠깐!

+

신청한 클래스가 있다면

+
+

입금 확인을 위해 현재 닉네임을 유지해 주세요.

+
+
+
+ +
+
+
+ + {user.guestNickname === value || value?.length === 0 || value?.length > 15 ? ( + + ) : ( + + )} +
+
+
+ ); +}; + +export default ChangeNicknameModal; diff --git a/src/pages/myPage/page/GuestMyPage/GuestMyPage.style.ts b/src/pages/myPage/page/GuestMyPage/GuestMyPage.style.ts index 4ef315e3..84df572c 100644 --- a/src/pages/myPage/page/GuestMyPage/GuestMyPage.style.ts +++ b/src/pages/myPage/page/GuestMyPage/GuestMyPage.style.ts @@ -20,7 +20,9 @@ export const selectedTabStyle = (theme: Theme) => css` `; export const profileWrapper = css` + ${flexGenerator('row', 'flex-start', 'center')} padding: 0 2rem 2.8rem; + gap: 0.8rem; `; export const navigateBoxWrapper = css` @@ -47,7 +49,14 @@ export const logoutTextStyle = (theme: Theme) => css` ${theme.font['subhead03-m-16']} color: ${theme.color.blackgray} `; + export const iconStyle = css` width: 2.4rem; height: 2.4rem; `; + +export const editIconStyle = css` + ${flexGenerator('row', 'center', 'flex-end')} + width: 2.4rem; + height: 2.4rem; +`; diff --git a/src/pages/myPage/page/GuestMyPage/GuestMyPage.tsx b/src/pages/myPage/page/GuestMyPage/GuestMyPage.tsx index 81f4fe35..ae302568 100644 --- a/src/pages/myPage/page/GuestMyPage/GuestMyPage.tsx +++ b/src/pages/myPage/page/GuestMyPage/GuestMyPage.tsx @@ -7,9 +7,10 @@ import { useFetchGuestInfo } from '@apis/domains/guest/useFetchGuestInfo'; import { LogoHeader, Modal, NavigateBox, SimpleUserProfile } from '@components'; import { routePath } from '@constants'; import { useEasyNavigate } from '@hooks'; +import ChangeNicknameModal from '@pages/myPage/components/ChangeNicknameModal/ChangeNicknameModal'; import LogoutModal from '@pages/myPage/components/LogoutModal/LogoutModal'; import { userAtom } from '@stores'; -import { IcNext } from '@svg'; +import { IcEdit20, IcNext } from '@svg'; import { isLoggedIn } from '@utils'; import { @@ -22,6 +23,7 @@ import { selectedTabStyle, divdier, profileWrapper, + editIconStyle, } from './GuestMyPage.style'; const GuestMyPage = () => { @@ -32,6 +34,7 @@ const GuestMyPage = () => { const { data: guestInfo } = useFetchGuestInfo(user.guestId as unknown as string); const [isModalOpen, setIsModalOpen] = useState(false); + const [isChangeNicknameModalOpen, setIsChangeNicknameModalOpen] = useState(false); const handleModalOpen = () => { setIsModalOpen(true); @@ -41,6 +44,14 @@ const GuestMyPage = () => { setIsModalOpen(false); }; + const handleChangeNicknameModalOpen = () => { + setIsChangeNicknameModalOpen(true); + }; + + const handleChangeNicknameModalClose = () => { + setIsChangeNicknameModalOpen(false); + }; + const handleOpenKakaoClick = () => { window.open(`${import.meta.env.VITE_OPEN_KAKAO_URL}`, '_blank'); }; @@ -72,6 +83,9 @@ const GuestMyPage = () => { userImgUrl={guestInfo?.guestImageUrl} username={guestInfo?.guestNickname || user.guestNickname || ''} /> + + +
@@ -95,6 +109,12 @@ const GuestMyPage = () => { )} + + {isChangeNicknameModalOpen && ( + + + + )} ) ); From 71028e705ff56250502d6365931fbfe9697b9f51 Mon Sep 17 00:00:00 2001 From: thisishwarang <101498590+thisishwarang@users.noreply.github.com> Date: Sun, 15 Sep 2024 23:44:05 +0900 Subject: [PATCH 2/2] =?UTF-8?q?[Fix/#287]=20=EA=B8=B0=EB=8A=A5=20QA=20(#28?= =?UTF-8?q?9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 기능 qa 반영 * fix: 클래스 뷰 리뷰 탭 suspense 수정 * fix: 리뷰 쓰기 버튼 클릭 시 라우팅 수정 * fix: 클래스 뷰 탭 height 수정 * fix: line-height 삭제 --- ...review_empty.png => image_review_empty.png} | Bin .../HostInfoCard/HostInfoCard.style.ts | 2 -- src/pages/class/page/Class/Class.style.ts | 2 ++ src/pages/class/page/Class/Class.tsx | 17 ++++++++--------- .../guest/components/MoimCard/MoimCard.tsx | 5 ++++- src/pages/host/components/StepTwo/StepTwo.tsx | 2 +- src/styles/theme.ts | 2 +- 7 files changed, 16 insertions(+), 14 deletions(-) rename public/image/graphics/{img_review_empty.png => image_review_empty.png} (100%) diff --git a/public/image/graphics/img_review_empty.png b/public/image/graphics/image_review_empty.png similarity index 100% rename from public/image/graphics/img_review_empty.png rename to public/image/graphics/image_review_empty.png diff --git a/src/pages/class/components/HostInfoCard/HostInfoCard.style.ts b/src/pages/class/components/HostInfoCard/HostInfoCard.style.ts index 204ab7b2..490edfb5 100644 --- a/src/pages/class/components/HostInfoCard/HostInfoCard.style.ts +++ b/src/pages/class/components/HostInfoCard/HostInfoCard.style.ts @@ -58,13 +58,11 @@ export const hostNameStyle = (theme: Theme) => css` export const hostKeywordStyle = (theme: Theme) => css` color: ${theme.color.purple2}; ${theme.font['body03-r-12']}; - line-height: 140%; `; export const hostDescriptionWrapper = (theme: Theme) => css` color: ${theme.color.midgray2}; ${theme.font['body03-r-12']}; - line-height: 140%; display: -webkit-box; -webkit-line-clamp: 2; diff --git a/src/pages/class/page/Class/Class.style.ts b/src/pages/class/page/Class/Class.style.ts index cb090830..5f2239d4 100644 --- a/src/pages/class/page/Class/Class.style.ts +++ b/src/pages/class/page/Class/Class.style.ts @@ -74,6 +74,8 @@ export const tabButtonStyle = (isSelected: boolean) => (theme: Theme) => css` export const tabSectionStyle = (theme: Theme) => css` background-color: ${theme.color.bg_white0}; + width: 100%; + min-height: 75rem; padding: 2.8rem 2rem; `; diff --git a/src/pages/class/page/Class/Class.tsx b/src/pages/class/page/Class/Class.tsx index e0f1ba78..13de6b14 100644 --- a/src/pages/class/page/Class/Class.tsx +++ b/src/pages/class/page/Class/Class.tsx @@ -1,5 +1,5 @@ import { useAtom } from 'jotai'; -import { useState } from 'react'; +import { Suspense, useState } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import { Pagination } from 'swiper/modules'; import { Swiper, SwiperSlide } from 'swiper/react'; @@ -64,9 +64,7 @@ const Class = () => { const { data: moimDescription, isLoading: isMoimDescriptionLoading } = useFetchMoimDescription( moimId ?? '' ); - const { data: moimNoticeList, isLoading: isMoimNoticeListLoading } = useFetchMoimNoticeList( - moimId ?? '' - ); + const { data: moimNoticeList } = useFetchMoimNoticeList(moimId ?? ''); if (isMoimDetailLoading || isMoimDescriptionLoading) { return ; } @@ -100,7 +98,6 @@ const Class = () => { showToast(); } }; - return (
@@ -161,14 +158,16 @@ const Class = () => {
{selectTab === '클래스소개' && } {selectTab === '공지사항' && - (isMoimNoticeListLoading ? ( - - ) : (moimNoticeList || []).length === 0 ? ( + ((moimNoticeList || []).length === 0 ? ( ) : ( ))} - {selectTab === '리뷰' && } + {selectTab === '리뷰' && ( + }> + + + )}
{selectTab === '공지사항' && moimDetail?.hostId === hostId && (
{ const handleCardClick = () => { navigate(`/class/${moimId}`); }; + const handleWriteReviewClick = () => { + navigate(`/mypage/guest/myclass/${moimId}/review/write`); + }; return (
@@ -81,7 +84,7 @@ const MoimCard = ({ guestMyClassData }: MoimCardProps) => { ) : null} {moimSubmissionState === 'completed' && ( - )} diff --git a/src/pages/host/components/StepTwo/StepTwo.tsx b/src/pages/host/components/StepTwo/StepTwo.tsx index 9a84da7e..9c6acecd 100644 --- a/src/pages/host/components/StepTwo/StepTwo.tsx +++ b/src/pages/host/components/StepTwo/StepTwo.tsx @@ -107,7 +107,7 @@ const StepTwo = ({ onNext }: StepProps) => { onChange={(e) => handleInputChange(e, 'email')} placeholder="ex. pickple@gmail.com" isValid={isEmailValid} - errorMessage="유효한 이메일 주소를 \n입력해 주세요." + errorMessage="유효한 이메일 주소를 입력해 주세요." isCountValue={false} /> diff --git a/src/styles/theme.ts b/src/styles/theme.ts index 51152c90..042e7572 100644 --- a/src/styles/theme.ts +++ b/src/styles/theme.ts @@ -135,7 +135,7 @@ const theme = { ${PretendardFont}; font-size: 1.2rem; font-weight: 400; - line-height: normal; + line-height: 140%; letter-spacing: 0px; `, 'body04-m-12': css`