Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…nt-R2 into feature/에러_페이지_처리_#666
  • Loading branch information
publdaze committed Oct 3, 2023
2 parents 2d0248f + 9a9dec1 commit 47b1247
Show file tree
Hide file tree
Showing 14 changed files with 138 additions and 44 deletions.
7 changes: 6 additions & 1 deletion src/api/studyApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ const useDeleteStudyMutation = () => {
return axios.delete(`/studies/${studyId}`);
};

return useMutation(fetcher);
const queryClient = useQueryClient();
return useMutation(fetcher, {
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['studies'] });
},
});
};

const useGetStudyListQuery = ({ year, season }: { year: number; season: number }) => {
Expand Down
27 changes: 21 additions & 6 deletions src/components/Input/EmailAuthInput.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import React, { forwardRef } from 'react';
import { StandardTextFieldProps } from '@mui/material';
import { CircularProgress, StandardTextFieldProps } from '@mui/material';
import { VscCheck } from 'react-icons/vsc';
import FilledButton from '@components/Button/FilledButton';
import StandardInput from './StandardInput';

interface EmailAuthInputProps extends StandardTextFieldProps {
value: string;
onChange: React.ChangeEventHandler<HTMLInputElement>;
isLoading?: boolean;
isSuccess?: boolean;
inputDisabled?: boolean;
buttonDisabled?: boolean;
onAuthButtonClick: () => void;
Expand All @@ -17,13 +20,29 @@ const EmailAuthInput = forwardRef(
className,
value,
onChange,
isLoading,
isSuccess,
inputDisabled,
buttonDisabled,
onAuthButtonClick,
...standardTextFieldProps
}: EmailAuthInputProps,
ref?: React.ForwardedRef<HTMLDivElement>,
) => {
const renderEndAdornment = () => {
if (isLoading) {
return <CircularProgress size={24} />;
}
if (isSuccess) {
return <VscCheck size={24} className="fill-pointBlue" />;
}
return (
<FilledButton small disabled={buttonDisabled} onClick={onAuthButtonClick}>
인증 요청
</FilledButton>
);
};

return (
<StandardInput
ref={ref}
Expand All @@ -34,11 +53,7 @@ const EmailAuthInput = forwardRef(
value={value}
onChange={onChange}
{...standardTextFieldProps}
endAdornment={
<FilledButton small disabled={buttonDisabled} onClick={onAuthButtonClick}>
인증 요청
</FilledButton>
}
endAdornment={renderEndAdornment()}
/>
);
},
Expand Down
23 changes: 23 additions & 0 deletions src/pages/Library/Button/NavigateProfileButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import { useNavigate } from 'react-router-dom';
import { useRecoilValue } from 'recoil';
import memberState from '@recoil/member.recoil';
import OutlinedButton from '@components/Button/OutlinedButton';

const NavigateProfileButton = () => {
const userInfo = useRecoilValue(memberState);
const navigate = useNavigate();

return (
<OutlinedButton
small
onClick={() => {
navigate(`/profile/${userInfo?.memberId}/book`);
}}
>
내 서재 가기
</OutlinedButton>
);
};

export default NavigateProfileButton;
16 changes: 7 additions & 9 deletions src/pages/Library/Card/BookCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,15 @@ interface BookCardProps {
const BookCard = ({ bookInfo, onRequestBook }: BookCardProps) => {
return (
<div className="flex h-fit bg-mainBlack p-2">
<div className="mr-2 flex h-[120px] w-[85px] bg-middleBlack">
<div className="mr-2 flex h-[120px] w-[85px] shrink-0 bg-middleBlack">
<ServerImg src={bookInfo?.thumbnailPath} alt="library thumbnail" />
</div>
<div className="relative grow p-2">
<div>
<Typography className="!mb-2 font-semibold">{bookInfo.title}</Typography>
<div className="flex space-x-2">
<Typography>저자 : {bookInfo.author}</Typography>
<span className="text-pointBlue"> | </span>
<Typography>권수 : {bookInfo.bookQuantity}</Typography>
</div>
<div className="relative grow overflow-auto p-2">
<Typography className="!mb-2 truncate !font-semibold">{bookInfo.title}</Typography>
<div className="flex space-x-2 overflow-auto">
<Typography className="truncate">저자 : {bookInfo.author}</Typography>
<span className="text-pointBlue"> | </span>
<Typography className="shrink-0">권수 : {bookInfo.bookQuantity}</Typography>
</div>

<div className="absolute bottom-0 right-0">
Expand Down
4 changes: 3 additions & 1 deletion src/pages/Library/Library.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useGetBookListQuery, useRequestBorrowBookMutation, useGetBookBorrowsQue
import usePagination from '@hooks/usePagination';
import StandardTablePagination from '@components/Pagination/StandardTablePagination';
import PageTitle from '@components/Typography/PageTitle';
import NavigateProfileButton from './Button/NavigateProfileButton';
import BookCard from './Card/BookCard';
import RequestBookModal from './Modal/RequestBookModal';
import LibrarySearchSection from './SearchSection/LibrarySearchSection';
Expand Down Expand Up @@ -42,12 +43,13 @@ const Library = () => {
<PageTitle>도서검색</PageTitle>
<div className="mb-2 flex w-full flex-col items-start justify-between md:mb-5 md:flex-row md:items-center">
<LibrarySearchSection />
<div className="mt-2 flex w-full justify-end md:mt-0">
<div className="items-ends mt-2 flex w-full justify-end space-x-4 md:mt-0">
<BorrowStatus
librarian={librarian}
borrowedBookCount={borrowedBookListData?.totalElement || 0}
maxBorrowableBooks={MAX_BORROWABLE_BOOKS}
/>
<NavigateProfileButton />
</div>
</div>
<div className="h-[804px] bg-middleBlack md:h-[402px]">
Expand Down
6 changes: 4 additions & 2 deletions src/pages/Library/Status/BorrowStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ interface BorrowStatusProps {

const BorrowStatus = ({ librarian, borrowedBookCount, maxBorrowableBooks }: BorrowStatusProps) => {
return borrowedBookCount !== maxBorrowableBooks ? (
<Typography className="text-pointBlue">
<Typography className="!flex !items-end text-pointBlue">
신청 가능 권수 : {maxBorrowableBooks - borrowedBookCount}/{maxBorrowableBooks}
</Typography>
) : (
Expand All @@ -26,7 +26,9 @@ const BorrowStatus = ({ librarian, borrowedBookCount, maxBorrowableBooks }: Borr
}}
placement="bottom"
>
<Typography className="text-subRed">신청 가능 권 수({maxBorrowableBooks}권)을 초과했습니다.</Typography>
<Typography className="!flex !items-end !text-small text-subRed md:!text-paragraph">
신청 가능 권 수({maxBorrowableBooks}권)을 초과했습니다.
</Typography>
</Tooltip>
);
};
Expand Down
8 changes: 7 additions & 1 deletion src/pages/Profile/Modal/EditAccountModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ const EditEmailSection = () => {
email: getValues('email'),
enabled: isEmailSent,
});
const { mutate: newEmailAuth } = useNewEmailAuthMutation();
const {
mutate: newEmailAuth,
isLoading: isEmailSendLoading,
isSuccess: isEmailSendSuccess,
} = useNewEmailAuthMutation();
const { mutate: editEmail } = useEditEmailMutation();

const handleRequestVerificationCode = () => {
Expand Down Expand Up @@ -123,6 +127,8 @@ const EditEmailSection = () => {
<EmailAuthInput
label="새 이메일"
{...field}
isLoading={isEmailSendLoading}
isSuccess={isEmailSendSuccess}
error={Boolean(error)}
helperText={error?.message}
inputDisabled={isEmailSent && checkEmailDuplicationSuccess}
Expand Down
4 changes: 3 additions & 1 deletion src/pages/SignUp/Section/SignUpThirdInputSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const SignUpThirdInputSection = () => {
enabled: isEmailSent,
});

const { mutate: emailAuth } = useEmailAuthMutation();
const { mutate: emailAuth, isLoading: isEmailSendLoading, isSuccess: isEmailSendSuccess } = useEmailAuthMutation();
const { mutate: signUp } = useSignUpMutation();

const handleRequestVerificationCode = () => {
Expand Down Expand Up @@ -103,6 +103,8 @@ const SignUpThirdInputSection = () => {
<EmailAuthInput
label="이메일"
{...field}
isLoading={isEmailSent && isEmailSendLoading}
isSuccess={isEmailSent && isEmailSendSuccess}
error={Boolean(error)}
helperText={error?.message}
inputDisabled={isEmailSent && checkEmailDuplicationSuccess}
Expand Down
7 changes: 5 additions & 2 deletions src/pages/Study/Accordion/StudyAccordion.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React from 'react';
import React, { useState } from 'react';
import { Accordion, AccordionActions, AccordionDetails, AccordionSummary } from '@mui/material';
import { VscChevronDown } from 'react-icons/vsc';

import useCheckAuth from '@hooks/useCheckAuth';
import ActionButton from '@components/Button/ActionButton';
import StudyAccordionBody from './StudyAccordionBody';
import StudyAccordionHeader from './StudyAccordionHeader';
import StudyDeleteModal from '../Modal/StudyDeleteModal';
import type { StudyInfo } from '@api/dto';

interface StudyAccordionProps {
Expand All @@ -16,14 +17,15 @@ interface StudyAccordionProps {

const StudyAccordion = ({ study, setStudyModalOpen, setSelectedStudyInfo }: StudyAccordionProps) => {
const { checkIsMyId } = useCheckAuth();
const [studyDeleteModalOpen, setStudyDeleteModalOpen] = useState(false);

const handleStudyEditButtonClick = () => {
setStudyModalOpen(true);
setSelectedStudyInfo(study);
};

const handleStudyDeleteButtonClick = () => {
// TODO 스터디 제거 API 호출 후 새로고침(기능 구현 후 console 삭제 예정)
setStudyDeleteModalOpen(true);
};

return (
Expand All @@ -47,6 +49,7 @@ const StudyAccordion = ({ study, setStudyModalOpen, setSelectedStudyInfo }: Stud
</ActionButton>
</AccordionActions>
)}
{study && <StudyDeleteModal study={study} open={studyDeleteModalOpen} setOpen={setStudyDeleteModalOpen} />}
</Accordion>
);
};
Expand Down
45 changes: 45 additions & 0 deletions src/pages/Study/Modal/StudyDeleteModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from 'react';
import { Typography } from '@mui/material';
import { StudyInfo } from '@api/dto';
import { useDeleteStudyMutation } from '@api/studyApi';
import ActionModal from '@components/Modal/ActionModal';

interface StudyDeleteModalProps {
open: boolean;
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
study: StudyInfo;
}

const StudyDeleteModal = ({ study, open, setOpen }: StudyDeleteModalProps) => {
const { mutate: deleteStudy } = useDeleteStudyMutation();

const handleClose = () => {
setOpen(false);
};

const handleDeleteStudy = () => {
deleteStudy(
{ studyId: study.studyId },
{
onSuccess: () => {
handleClose();
},
},
);
};

return (
<ActionModal
open={open}
onClose={handleClose}
title="스터디 삭제"
modalWidth="xs"
actionButtonName="삭제"
onActionButonClick={handleDeleteStudy}
>
<Typography>{study?.title} 스터디를 삭제하시겠습니까?</Typography>
</ActionModal>
);
};

export default StudyDeleteModal;
2 changes: 1 addition & 1 deletion src/pages/admin/SeminarManage/SeminarManage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const SeminarManage = () => {
}, [seminarList]);

const childComponent = ({ key, value }: ChildComponent<AttendSeminarInfo>) => {
if (key.slice(0, 4) === 'date') {
if (key.slice(0, 4) === 'date' && value) {
return <SeminarAttendStatus status={(value as MemberSeminarAttendance).attendanceStatus} hasIcon={false} />;
}
return value;
Expand Down
15 changes: 1 addition & 14 deletions src/pages/login/Login.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,11 @@
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import { Box, Container, Divider, Stack } from '@mui/material';
import { Container, Divider, Stack } from '@mui/material';
import useLoginMutation from '@api/logInApi';
import { ReactComponent as Logo } from '@assets/logo/logo_neon.svg';
import OutlinedButton from '@components/Button/OutlinedButton';
import StandardInput from '@components/Input/StandardInput';

const HorizonLine = () => {
return (
<Box
sx={{
width: '100%',
borderBottom: '1px solid #56CFE1',
opacity: '30%',
margin: '10px 0 10px',
}}
/>
);
};

const Login = () => {
const [form, setForm] = useState({
id: '',
Expand Down
6 changes: 3 additions & 3 deletions src/pages/login/Search/SearchID.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import { Divider, Typography, useMediaQuery, useTheme } from '@mui/material';
import { CircularProgress, Divider, Typography, useMediaQuery, useTheme } from '@mui/material';
import { useSearchIdMutation } from '@api/SearchAccountApi';
import { validateEmail } from '@utils/validateEmail';
import OutlinedButton from '@components/Button/OutlinedButton';
Expand All @@ -15,7 +15,7 @@ const SearchID = () => {
const [mailAuthenticationModalOpen, setMailAuthenticationModalOpen] = useState(false);
const [matchInfoModalOpen, setMatchInfoModalOpen] = useState(false);

const { mutate: searchId } = useSearchIdMutation();
const { mutate: searchId, isLoading: isEmailSendLoading } = useSearchIdMutation();
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));

Expand Down Expand Up @@ -75,7 +75,7 @@ const SearchID = () => {
<Divider className="bg-pointBlue" />
<div className="mt-10 text-center">
<OutlinedButton className="w-full sm:w-1/5" onClick={handleConfirmClick} disabled={!isValidEmail}>
확인
{isEmailSendLoading ? <CircularProgress className="my-1" size={24} /> : <>확인</>}
</OutlinedButton>
</div>
<WarningModal
Expand Down
12 changes: 9 additions & 3 deletions src/pages/login/Search/SearchPWFirstStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ interface SearchPWFirstStepProps {
}

const SearchPWFirstStep = ({ setCurrentStep, form, setForm }: SearchPWFirstStepProps) => {
const { mutate: requestAuthcode } = useRequestAuthCodeMutation();
const {
mutate: requestAuthcode,
isLoading: isEmailSendLoading,
isSuccess: isEmailSendSuccess,
} = useRequestAuthCodeMutation();
const { data: checkAuthcodeData } = useCheckAuthCodeQuery({
loginId: form.id,
email: form.email,
Expand Down Expand Up @@ -53,12 +57,12 @@ const SearchPWFirstStep = ({ setCurrentStep, form, setForm }: SearchPWFirstStepP
};

const handleRequestVerificationCode = () => {
setIsSent(true);
if (form.id && form.email) {
requestAuthcode(
{ loginId: form.id, email: form.email },
{
onSuccess: () => {
setIsSent(true);
setMatchInfoModalOpen(false);
},
onError: () => {
Expand Down Expand Up @@ -112,6 +116,8 @@ const SearchPWFirstStep = ({ setCurrentStep, form, setForm }: SearchPWFirstStepP
<EmailAuthInput
className="w-full sm:w-[70%]"
inputDisabled={isSent}
isLoading={isSent && isEmailSendLoading}
isSuccess={isSent && isEmailSendSuccess}
value={form.email}
onChange={handleChange}
buttonDisabled={!isValidEmail || isSent}
Expand All @@ -133,7 +139,7 @@ const SearchPWFirstStep = ({ setCurrentStep, form, setForm }: SearchPWFirstStepP
name="verificationCode"
value={form.verificationCode}
onChange={handleChange}
disabled={!isSent}
disabled={!(isSent && isEmailSendSuccess)}
expirationTime={DateTime.now().plus({ seconds: TIMER_DURATION_SECOND })}
/>
</div>
Expand Down

0 comments on commit 47b1247

Please sign in to comment.