-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: 지출 내역 생성 api 연결 및 유효성 검사 * feat: Funnel 파일 분리 및 member 생성 api 로직 변경 * fix: AddBillFunnel route 수정 * style: lint 적용 * refactor: BillStep hook 분리 * style: lint 적용 * fix: postMember api 요청 변경 * fix: addBill route 수정 * fix: TitleStep에서 PriceStep으로 이동했을 때, billInfo.price 초기화되던 오류 수정 * fix: MSW mocking 해제 * rename: AddBillFunnel 경로 수정 * fix: mutateAsync를 이용하여 postMembers 이후 postBills 요청을 보내도록 수정 * fix: API 변경에 맞추어 수정 * style: lint 적용
- Loading branch information
Showing
20 changed files
with
539 additions
and
292 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
const REGEXP = { | ||
eventPassword: /^[0-9]*$/, | ||
memberName: /^[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z\s]*$/, | ||
purchaseTitle: /^[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z0-9\s]*$/, | ||
eventUrl: /\/event\/([a-zA-Z0-9-]+)\//, | ||
billTitle: /^([ㄱ-ㅎ가-힣a-zA-Z0-9ㆍᆢ]\s?)*$/, | ||
memberName: /^([ㄱ-ㅎ가-힣a-zA-Zㆍᆢ]\s?)*$/, | ||
}; | ||
|
||
export default REGEXP; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import {useEffect, useState} from 'react'; | ||
|
||
import {BillInfo} from '@pages/AddBillFunnel/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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import {useEffect, useState} from 'react'; | ||
import {useNavigate} from 'react-router-dom'; | ||
|
||
import {BillInfo} from '@pages/AddBillFunnel/AddBillFunnel'; | ||
import {Member} from 'types/serviceType'; | ||
|
||
import getEventIdByUrl from '@utils/getEventIdByUrl'; | ||
|
||
import REGEXP from '@constants/regExp'; | ||
|
||
import useRequestPostMembers from './queries/member/useRequestPostMembers'; | ||
import useRequestPostBill from './queries/bill/useRequestPostBill'; | ||
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 {postMembersAsync, 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)) { | ||
const newMembers = await postMembersAsync({ | ||
members: billInfo.members | ||
.filter(({id}) => id === -1) | ||
.map(({name}) => ({ | ||
name, | ||
})), | ||
}); | ||
postBill({ | ||
title: billInfo.title, | ||
price: Number(billInfo.price.replace(',', '')), | ||
memberIds: billInfo.members.map(member => | ||
member.id === -1 ? newMembers.members.find(m => m.name === member.name)?.id || member.id : member.id, | ||
), | ||
}); | ||
} else { | ||
postBill({ | ||
title: billInfo.title, | ||
price: Number(billInfo.price.replace(',', '')), | ||
memberIds: billInfo.members.map(({id}) => id), | ||
}); | ||
} | ||
}; | ||
|
||
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import {useCallback} from 'react'; | ||
|
||
import {BillInfo} from '@pages/AddBillFunnel/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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import {useState} from 'react'; | ||
|
||
import {BillInfo} from '@pages/AddBillFunnel/AddBillFunnel'; | ||
|
||
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>>; | ||
} | ||
|
||
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.