Skip to content

Commit

Permalink
refactor: BillStep hook 뢄리
Browse files Browse the repository at this point in the history
  • Loading branch information
Todari committed Sep 23, 2024
1 parent 3077cbf commit 301ea2d
Show file tree
Hide file tree
Showing 8 changed files with 281 additions and 168 deletions.
32 changes: 32 additions & 0 deletions client/src/hooks/useAddBillFunnel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {BillInfo} from '@pages/BillPage/AddBillFunnel';

Check failure on line 1 in client/src/hooks/useAddBillFunnel.ts

View workflow job for this annotation

GitHub Actions / test

There should be at least one empty line between import groups
import {useEffect, useState} from 'react';

Check failure on line 2 in client/src/hooks/useAddBillFunnel.ts

View workflow job for this annotation

GitHub Actions / test

`react` import should occur before import of `@pages/BillPage/AddBillFunnel`

import useRequestGetCurrentMembers from './queries/member/useRequestGetCurrentMembers';

export type BillStep = 'title' | 'price' | 'members';

const useAddBillFunnel = () => {
const {currentMembers} = useRequestGetCurrentMembers();
const [step, setStep] = useState<BillStep>('price');
const [billInfo, setBillInfo] = useState<BillInfo>({
price: '',
title: '',
members: [],
});

useEffect(() => {
document.body.style.overflow = 'hidden';

return () => {
document.body.style.overflow = 'auto';
};
}, []);

useEffect(() => {
currentMembers && setBillInfo(prev => ({...prev, members: currentMembers}));
}, [currentMembers]);

return {step, setStep, billInfo, setBillInfo, currentMembers};
};

export default useAddBillFunnel;
124 changes: 124 additions & 0 deletions client/src/hooks/useMembersStep.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import {BillInfo} from '@pages/BillPage/AddBillFunnel';

Check failure on line 1 in client/src/hooks/useMembersStep.ts

View workflow job for this annotation

GitHub Actions / test

There should be at least one empty line between import groups
import {useEffect, useState} from 'react';

Check failure on line 2 in client/src/hooks/useMembersStep.ts

View workflow job for this annotation

GitHub Actions / test

There should be at least one empty line between import groups

Check failure on line 2 in client/src/hooks/useMembersStep.ts

View workflow job for this annotation

GitHub Actions / test

`react` import should occur before import of `@pages/BillPage/AddBillFunnel`
import {Member} from 'types/serviceType';

Check failure on line 3 in client/src/hooks/useMembersStep.ts

View workflow job for this annotation

GitHub Actions / test

There should be at least one empty line between import groups
import useRequestPostMembers from './queries/member/useRequestPostMembers';
import useRequestPostBill from './queries/bill/useRequestPostBill';

Check failure on line 5 in client/src/hooks/useMembersStep.ts

View workflow job for this annotation

GitHub Actions / test

There should be at least one empty line between import groups
import {useNavigate} from 'react-router-dom';

Check failure on line 6 in client/src/hooks/useMembersStep.ts

View workflow job for this annotation

GitHub Actions / test

There should be at least one empty line between import groups

Check failure on line 6 in client/src/hooks/useMembersStep.ts

View workflow job for this annotation

GitHub Actions / test

`react-router-dom` import should occur before import of `@pages/BillPage/AddBillFunnel`
import getEventIdByUrl from '@utils/getEventIdByUrl';

Check failure on line 7 in client/src/hooks/useMembersStep.ts

View workflow job for this annotation

GitHub Actions / test

There should be at least one empty line between import groups
import REGEXP from '@constants/regExp';
import {BillStep} from './useAddBillFunnel';

interface Props {
billInfo: BillInfo;
setBillInfo: React.Dispatch<React.SetStateAction<BillInfo>>;
setStep: React.Dispatch<React.SetStateAction<BillStep>>;
currentMembers: Member[];
}

const useMembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) => {
const [errorMessage, setErrorMessage] = useState('');
const [nameInput, setNameInput] = useState('');

const {
postMembers,
responseMemberIds,
isSuccess: isSuccessPostMembers,
isPending: isPendingPostMembers,
} = useRequestPostMembers();

const {postBill, isSuccess: isSuccessPostBill, isPending: isPendingPostBill} = useRequestPostBill();
const navigate = useNavigate();
const eventId = getEventIdByUrl();

const onNameInputChange = (value: string) => {
if (REGEXP.memberName.test(value)) {
setNameInput(value);
}
};

const handleNameInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.value.length > 4) {
setErrorMessage('이름은 4μžκΉŒμ§€ μž…λ ₯ κ°€λŠ₯ν•΄μš”');
onNameInputChange(nameInput.slice(0, 4));
} else {
setErrorMessage('');
onNameInputChange(event.target.value);
}
};

const canAddMembers = nameInput && !errorMessage;

const canSubmitMembers = billInfo.members.length !== 0;

const setBillInfoMemberWithId = (name: string) => {
const existingMember = currentMembers.find(currentMember => currentMember.name === name);
if (existingMember) {
setBillInfo(prev => ({...prev, members: [...prev.members, {id: existingMember.id, name: name}]}));
} else {
setBillInfo(prev => ({...prev, members: [...prev.members, {id: -1, name: name}]}));
}
};

const handleNameInputEnter = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.nativeEvent.isComposing) {
return;
}
if (event.key === 'Enter' && canAddMembers) {
event.preventDefault();
if (!billInfo.members.map(({name}) => name).includes(nameInput)) {
setBillInfoMemberWithId(nameInput);
}
setNameInput('');
}
};

const handlePostBill = async () => {
if (billInfo.members.map(({id}) => id).includes(-1)) {
postMembers({
members: billInfo.members.filter(member => member.id === -1),
});
} else {
postBill({
title: billInfo.title,
price: Number(billInfo.price.replace(',', '')),
members: billInfo.members.map(({id}) => id),
});
}
};

useEffect(() => {
if (isSuccessPostMembers && responseMemberIds) {
postBill({
title: billInfo.title,
price: Number(billInfo.price.replace(',', '')),
members: billInfo.members.map(member =>
member.id === -1 ? responseMemberIds.members.find(m => m.name === member.name)?.id || member.id : member.id,
),
});
}
}, [isSuccessPostMembers, responseMemberIds]);

useEffect(() => {
if (isSuccessPostBill) {
navigate(`/event/${eventId}/admin`);
}
}, [isSuccessPostBill]);

const handlePrevStep = () => {
setStep('title');
};

return {
errorMessage,
nameInput,
handleNameInputChange,
handleNameInputEnter,
isPendingPostBill,
isPendingPostMembers,
canSubmitMembers,
handlePostBill,
handlePrevStep,
};
};

export default useMembersStep;
25 changes: 25 additions & 0 deletions client/src/hooks/usePriceStep.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {useCallback} from 'react';
import {BillInfo} from '@pages/BillPage/AddBillFunnel';
import {BillStep} from './useAddBillFunnel';

interface Props {
setStep: React.Dispatch<React.SetStateAction<BillStep>>;
setBillInfo: React.Dispatch<React.SetStateAction<BillInfo>>;
}

const usePriceStep = ({setStep, setBillInfo}: Props) => {
const handleNumberKeyboardChange = useCallback(
(value: string) => {
setBillInfo(prev => ({...prev, price: value}));
},
[setBillInfo],
);

const handleNextStep = () => {
setStep('title');
};

return {handleNumberKeyboardChange, handleNextStep};
};

export default usePriceStep;
61 changes: 61 additions & 0 deletions client/src/hooks/useTitleStep.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import REGEXP from '@constants/regExp';
import {BillInfo} from '@pages/BillPage/AddBillFunnel';
import {useState} from 'react';
import {BillStep} from './useAddBillFunnel';

interface Props {
billInfo: BillInfo;
setBillInfo: React.Dispatch<React.SetStateAction<BillInfo>>;
setStep: React.Dispatch<React.SetStateAction<BillStep>>;
}

const useTitleStep = ({billInfo, setBillInfo, setStep}: Props) => {
const [errorMessage, setErrorMessage] = useState('');

const onTitleInputChange = (value: string) => {
if (REGEXP.billTitle.test(value)) {
setBillInfo(prev => ({...prev, title: value}));
}
};

const handleTitleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.value.length > 12) {
setErrorMessage('μ§€μΆœλ‚΄μ—­μ€ 12μžκΉŒμ§€ μž…λ ₯ κ°€λŠ₯ν•΄μš”');
onTitleInputChange(billInfo.title.slice(0, 12));
} else {
setErrorMessage('');
onTitleInputChange(event.target.value);
}
};

const canSubmitTitleInput = billInfo.title && !errorMessage;

const handleTitleInputEnter = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.nativeEvent.isComposing) {
return;
}
if (event.key === 'Enter' && canSubmitTitleInput) {
event.preventDefault();
setStep('members');
}
};

const handleNextStep = () => {
setStep('members');
};

const handlePrevStep = () => {
setStep('price');
};

return {
errorMessage,
handleTitleInputChange,
handleTitleInputEnter,
canSubmitTitleInput,
handleNextStep,
handlePrevStep,
};
};

export default useTitleStep;
17 changes: 3 additions & 14 deletions client/src/pages/BillPage/AddBillFunnel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import {Back, MainLayout, TopNav} from '@components/Design';
import PriceStep from './steps/PriceStep';
import {TitleStep} from './steps/TitleStep';
import MembersStep from './steps/MembersStep';

export type BillStep = 'title' | 'price' | 'members';
import useAddBillFunnel from '@hooks/useAddBillFunnel';

export interface BillInfo {
price: string;
Expand All @@ -18,17 +17,7 @@ export interface BillInfo {
}

const AddBillFunnel = () => {
const {currentMembers} = useRequestGetCurrentMembers();
const [step, setStep] = useState<BillStep>('price');
const [billInfo, setBillInfo] = useState<BillInfo>({
price: '',
title: '',
members: [],
});

useEffect(() => {
currentMembers && setBillInfo(prev => ({...prev, members: currentMembers}));
}, [currentMembers]);
const {step, setStep, billInfo, setBillInfo, currentMembers} = useAddBillFunnel();

return (
<MainLayout backgroundColor="white">
Expand All @@ -38,7 +27,7 @@ const AddBillFunnel = () => {
{step === 'price' && <PriceStep billInfo={billInfo} setBillInfo={setBillInfo} setStep={setStep} />}
{step === 'title' && <TitleStep billInfo={billInfo} setBillInfo={setBillInfo} setStep={setStep} />}
{step === 'members' && (
<MembersStep billInfo={billInfo} setBillInfo={setBillInfo} setStep={setStep} currentMembers={currentMembers} />
<MembersStep billInfo={billInfo} setBillInfo={setBillInfo} currentMembers={currentMembers} setStep={setStep} />
)}
</MainLayout>
);
Expand Down
Loading

0 comments on commit 301ea2d

Please sign in to comment.