Skip to content

Commit

Permalink
[Feat/#335] 클래스 생성 시 각 단계별 새로고침 대응 & 리뷰 순서 최신순으로 정렬 (#337)
Browse files Browse the repository at this point in the history
* fix: X 버튼 관련 QA 수정

* feat: 클래스 생성 시 localStorage 내 classpostData 리셋

* feat: classPostAtom을 atomWithStorage로 설정

* feat: 공통 컴포넌트 button 전부에 type 속성 추가

* fix: 겹치는 css 속성 제거

* feat: 클래스 개설완료 뒤 유저가 뒤로가기 진행 후 다시 개설하는 플로우 토스트로 에러메세지

* feat: 리뷰 순서 최신순으로 정렬

* feat: 리뷰 최신순으로 정렬 (sort제거 & reverse로)

* feat: 콘솔로그 제거

* feat: Input 공통 컴포넌트 내 width height 복구
  • Loading branch information
ExceptAnyone authored Oct 13, 2024
1 parent 82b9ab5 commit 2d54c52
Show file tree
Hide file tree
Showing 11 changed files with 41 additions and 26 deletions.
5 changes: 5 additions & 0 deletions src/apis/domains/moim/usePostMoim.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useAtom } from 'jotai';
import { RESET } from 'jotai/utils';

import { post } from '@apis/api';
import { QUERY_KEY } from '@apis/queryKeys/queryKeys';

import { classPostAtom } from 'src/stores/classPostData';
import { ClassPostDataType } from 'src/stores/types/classPostDataType';
import { transformClassPostState } from 'src/utils/postMoimTypeChange';

Expand All @@ -29,11 +32,13 @@ const postMoim = async (classPostState: ClassPostDataType) => {

export const usePostMoim = () => {
const queryClient = useQueryClient();
const [, setClassPostState] = useAtom(classPostAtom);

return useMutation({
mutationFn: (classPostState: ClassPostDataType) => postMoim(classPostState),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: [QUERY_KEY.POST_MOIM] });
setClassPostState(RESET);
},
});
};
6 changes: 6 additions & 0 deletions src/components/common/QuestionInput/QuestionInput.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const questionInputStyle = (theme: Theme) => css`
gap: 1rem;
position: relative;
padding: 1rem;
padding-right: 3.8rem;
border: 1px solid ${theme.color.lightgray1};
border-radius: 10px;
background-color: ${theme.color.bg_white0};
Expand Down Expand Up @@ -62,3 +63,8 @@ export const textLengthStyle = (theme: Theme) => css`
color: ${theme.color.midgray1};
${theme.font['body02-r-14']}
`;

export const deleteIconStyle = css`
width: 1.8rem;
height: 1.8rem;
`;
6 changes: 4 additions & 2 deletions src/components/common/QuestionInput/QuestionInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
questionInputContainer,
} from 'src/components/common/QuestionInput/QuestionInput.style';

import { deleteButtonStyle } from '../inputs/Input/Input.style';
import { deleteButtonStyle, deleteIconStyle } from '../inputs/Input/Input.style';

export interface QuestionInputProps extends InputHTMLAttributes<HTMLInputElement> {
numberLabel: string;
Expand Down Expand Up @@ -54,7 +54,9 @@ const QuestionInput = ({
/>
{isFocused && value && value.length > 0 && (
<div css={deleteButtonStyle} onMouseDown={handleInputDelete}>
<IcDelete20 />
<span css={deleteIconStyle}>
<IcDelete20 />
</span>
</div>
)}
</div>
Expand Down
7 changes: 4 additions & 3 deletions src/components/common/buttons/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
customStyle?: ((theme: Theme) => SerializedStyles) | SerializedStyles;
}

const Button = ({ variant, disabled, customStyle, onClick, children }: ButtonProps) => {
const Button = ({ variant, disabled, customStyle, children, ...props }: ButtonProps) => {
return (
<button
type="button"
css={[buttonStyle, buttonSize[variant], disabled && disabledStyle, customStyle]}
onClick={onClick}
disabled={disabled}>
disabled={disabled}
{...props}>
{children}
</button>
);
Expand Down
15 changes: 2 additions & 13 deletions src/components/common/buttons/CategoryButton/CategoryButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,13 @@ interface CategoryButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
icon: React.ReactNode;
isSelected: boolean;
setIsSelected?: React.Dispatch<React.SetStateAction<boolean>>;
handleClick: (event: React.MouseEvent<HTMLButtonElement>) => void;
}

const CategoryButton = ({
children,
icon,
isSelected = false,
handleClick,
...props
}: CategoryButtonProps) => {
const CategoryButton = ({ children, icon, isSelected = false, ...props }: CategoryButtonProps) => {
return (
<section css={categoryButtonContainer}>
<div css={[categoryButtonWrapper(isSelected)]}>
<button
type="button"
onClick={handleClick}
css={[categoryButtonStyle(isSelected)]}
{...props}>
<button type="button" css={[categoryButtonStyle(isSelected)]} {...props}>
<span css={iconWrapper(isSelected)}>{icon}</span>
</button>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const ClipboardCopyButton = () => {
}
};
return (
<button css={buttonWrapperStyle} onClick={handleCopyClick}>
<button type="button" css={buttonWrapperStyle} onClick={handleCopyClick}>
<span css={accountNumberStyle}>{accountNumber}</span>
<span css={iconStyle}>
<IcClipboardCopy />
Expand Down
4 changes: 2 additions & 2 deletions src/components/common/buttons/IconButton/IconButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ interface IconButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
icon?: React.ReactNode;
}

const IconButton = ({ onClick, icon, children }: IconButtonProps) => {
const IconButton = ({ icon, children, ...props }: IconButtonProps) => {
return (
<button css={buttonStyle} onClick={onClick} type={'button'}>
<button css={buttonStyle} type="button" {...props}>
<span css={iconWrapperStyle}>{icon}</span>
{children}
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,12 @@ const InterestCategoryButton = ({
children,
variant = 'default',
icon,
onClick,
...props
}: InterestCategoryButtonProps) => {
return (
<button
type="button"
css={[InterestCategoryButtonStyle, InterestCategoryButtonVariant[variant]]}
onClick={onClick}
{...props}>
<span css={iconWrapperStyle}>{icon}</span>
{children}
Expand Down
3 changes: 2 additions & 1 deletion src/pages/class/components/ClassReviewTab/ClassReviewTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ const ClassReviewTab = ({ moimId }: ClassReviewTabProps) => {
}
return (
<section css={reviewSectionStyle}>
{moimReviewList?.map((review, i) => <Review key={i} reviewData={review} />)}
{/* reverse메서드로 최신순으로 정렬 */}
{moimReviewList?.map((review, i) => <Review key={i} reviewData={review} />).reverse()}
</section>
);
};
Expand Down
13 changes: 12 additions & 1 deletion src/pages/class/components/StepThree/StepThree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { useEffect, useState } from 'react';
import { usePostMoim } from '@apis/domains/moim/usePostMoim';
import { usePutS3Upload } from '@apis/domains/presignedUrl/usePutS3Upload';

import { Button, ImageSelect, Input, ProgressBar, Spinner, TextArea } from '@components';
import { Button, ImageSelect, Input, ProgressBar, Spinner, TextArea, Toast } from '@components';
import { useToast } from '@hooks';
import { useClassPostInputChange, useClassPostInputValidation } from '@pages/class/hooks';
import { smoothScroll } from '@utils';
import { moimIdAtom } from 'src/stores/classPostData';
Expand Down Expand Up @@ -34,6 +35,7 @@ const StepThree = ({ onNext }: StepProps) => {

const { mutateAsync: putS3UploadMutateAsync, isPending: putS3IsPending } = usePutS3Upload();
const { mutateAsync: postMutateAsync, isPending: postIsPending } = usePostMoim();
const { showToast, isToastVisible } = useToast();

const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
const [isAllValid, setIsAllValid] = useState(false);
Expand Down Expand Up @@ -64,6 +66,9 @@ const StepThree = ({ onNext }: StepProps) => {
.catch((error: ErrorType) => {
const { status, message } = error;
console.error(status, message);
if (error.status === 40004) {
showToast();
}
});
}
};
Expand Down Expand Up @@ -120,6 +125,12 @@ const StepThree = ({ onNext }: StepProps) => {
클래스 개설하기
</Button>
</footer>
{isToastVisible && (
<Toast isVisible={isToastVisible} toastBottom={10}>
필수 입력 칸이 비어있어요.
{/* 정안TODO 에러 메세지 기획과 논의 후 수정 */}
</Toast>
)}
</div>
</>
);
Expand Down
3 changes: 2 additions & 1 deletion src/stores/classPostData.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { atom } from 'jotai';
import { atomWithStorage } from 'jotai/utils';

import { ClassPostDataType } from './types/classPostDataType';

export const classPostAtom = atom<ClassPostDataType>({
export const classPostAtom = atomWithStorage<ClassPostDataType>('classPost', {
categoryList: {
category1: '',
category2: '',
Expand Down

0 comments on commit 2d54c52

Please sign in to comment.