diff --git a/client/src/components/InputAndDeleteButton/InputAndDeleteButton.style.ts b/client/src/components/InputAndDeleteButton/InputAndDeleteButton.style.ts new file mode 100644 index 000000000..ff9f6cf6e --- /dev/null +++ b/client/src/components/InputAndDeleteButton/InputAndDeleteButton.style.ts @@ -0,0 +1,9 @@ +import {css} from '@emotion/react'; + +export const InputAndDeleteButtonContainer = () => + css({ + display: 'flex', + alignItems: 'center', + width: '100%', + gap: '1rem', + }); diff --git a/client/src/components/InputAndDeleteButton/InputAndDeleteButton.tsx b/client/src/components/InputAndDeleteButton/InputAndDeleteButton.tsx new file mode 100644 index 000000000..5ce491099 --- /dev/null +++ b/client/src/components/InputAndDeleteButton/InputAndDeleteButton.tsx @@ -0,0 +1,18 @@ +import {Icon, IconButton, LabelGroupInput} from 'haengdong-design'; + +import {InputAndDeleteButtonContainer} from './InputAndDeleteButton.style'; + +const InputAndDeleteButton = () => { + return ( +
+
+ +
+ + + +
+ ); +}; + +export default InputAndDeleteButton; diff --git a/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx b/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx new file mode 100644 index 000000000..83e6c58f1 --- /dev/null +++ b/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx @@ -0,0 +1,46 @@ +import {SetAllMemberListModal, SetInitialMemberListModal, SetActionListModal} from '@components/Modal/index'; + +interface ModalBasedOnMemberCountProps { + memberNameList: string[]; + isOpenBottomSheet: boolean; + isOpenAllMemberListButton: boolean; + setOrder: React.Dispatch>; + setIsOpenBottomSheet: React.Dispatch>; + setIsOpenAllMemberListButton: React.Dispatch>; +} + +const ModalBasedOnMemberCount = ({ + memberNameList, + isOpenBottomSheet, + isOpenAllMemberListButton, + setOrder, + setIsOpenBottomSheet, + setIsOpenAllMemberListButton, +}: ModalBasedOnMemberCountProps) => { + if (isOpenAllMemberListButton) { + return ( + + ); + } + switch (memberNameList.length) { + case 0: + return ( + + ); + + default: + return ( + + ); + } +}; + +export default ModalBasedOnMemberCount; diff --git a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx index 8fac562f5..c59388472 100644 --- a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx +++ b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx @@ -8,11 +8,11 @@ import useDynamicBillActionInput from '@hooks/useDynamicBillActionInput'; import style from './AddBillActionListModalContent.style'; interface AddBillActionListModalContentProps { - setOpenBottomSheet: React.Dispatch>; + setIsOpenBottomSheet: React.Dispatch>; setOrder: React.Dispatch>; } -const AddBillActionListModalContent = ({setOpenBottomSheet, setOrder}: AddBillActionListModalContentProps) => { +const AddBillActionListModalContent = ({setIsOpenBottomSheet, setOrder}: AddBillActionListModalContentProps) => { const { inputPairList, inputRefList, @@ -28,7 +28,7 @@ const AddBillActionListModalContent = ({setOpenBottomSheet, setOrder}: AddBillAc // TODO: (@weadie) 요청 실패시 오류 핸들 필요 addBill(getFilledInputPairList().map(({title, price}) => ({title, price: Number(price)}))); // TODO: (@weadie) DTO같은게 다이내믹에 필요할까? - setOpenBottomSheet(false); + setIsOpenBottomSheet(false); }; return ( diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx index aff2764c8..b88befbb5 100644 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx @@ -11,10 +11,10 @@ import style from './AddMemberActionListModalContent.style'; interface AddMemberActionListModalContentProps { inOutAction: MemberType; - setOpenBottomSheet: React.Dispatch>; + setIsOpenBottomSheet: React.Dispatch>; } -const AddMemberActionListModalContent = ({inOutAction, setOpenBottomSheet}: AddMemberActionListModalContentProps) => { +const AddMemberActionListModalContent = ({inOutAction, setIsOpenBottomSheet}: AddMemberActionListModalContentProps) => { const { inputList, inputRefList, @@ -30,7 +30,7 @@ const AddMemberActionListModalContent = ({inOutAction, setOpenBottomSheet}: AddM const handleUpdateMemberListSubmit = () => { updateMemberList({memberNameList: getFilledInputList().map(({value}) => value), type: inOutAction}); - setOpenBottomSheet(false); + setIsOpenBottomSheet(false); }; return ( diff --git a/client/src/components/Modal/SetActionModal/SetActionListModal.tsx b/client/src/components/Modal/SetActionModal/SetActionListModal.tsx index a4c38e6c4..9b4b7facf 100644 --- a/client/src/components/Modal/SetActionModal/SetActionListModal.tsx +++ b/client/src/components/Modal/SetActionModal/SetActionListModal.tsx @@ -10,12 +10,12 @@ import style from './SetActionListModal.style'; export type ActionType = '지출' | '인원'; interface SetActionModalContentProps { - openBottomSheet: boolean; - setOpenBottomSheet: React.Dispatch>; + isOpenBottomSheet: boolean; + setIsOpenBottomSheet: React.Dispatch>; setOrder: React.Dispatch>; } -const SetActionListModal = ({openBottomSheet, setOpenBottomSheet, setOrder}: SetActionModalContentProps) => { +const SetActionListModal = ({isOpenBottomSheet, setIsOpenBottomSheet, setOrder}: SetActionModalContentProps) => { const [action, setAction] = useState('지출'); const [inOutAction, setInOutAction] = useState('탈주'); @@ -28,7 +28,7 @@ const SetActionListModal = ({openBottomSheet, setOpenBottomSheet, setOrder}: Set }; return ( - setOpenBottomSheet(false)}> + setIsOpenBottomSheet(false)}>
@@ -38,12 +38,12 @@ const SetActionListModal = ({openBottomSheet, setOpenBottomSheet, setOrder}: Set
{action === '지출' && ( - + )} {action === '인원' && ( )}
diff --git a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts new file mode 100644 index 000000000..b703e43de --- /dev/null +++ b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts @@ -0,0 +1,28 @@ +import {css} from '@emotion/react'; + +export const allMemberListModalStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + gap: '1rem', + width: '100%', + height: '100%', + }); + +export const allMemberListModalTitleStyle = () => + css({ + display: 'flex', + justifyContent: 'space-between', + width: '100%', + padding: '0 1.5rem', + }); + +export const allMemberListModalLabelGroupInputStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + padding: '0 1rem', + paddingBottom: '10rem', + + overflow: 'auto', + }); diff --git a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx new file mode 100644 index 000000000..7eb4ab1fb --- /dev/null +++ b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx @@ -0,0 +1,48 @@ +import {BottomSheet, Text, LabelGroupInput, FixedButton} from 'haengdong-design'; + +import InputAndDeleteButton from '@components/InputAndDeleteButton/InputAndDeleteButton'; + +import { + allMemberListModalLabelGroupInputStyle, + allMemberListModalStyle, + allMemberListModalTitleStyle, +} from './SetAllMemberListModal.style'; + +interface SetAllMemberListModalProps { + isOpenBottomSheet: boolean; + setIsOpenBottomSheet: React.Dispatch>; + setIsOpenAllMemberListButton: React.Dispatch>; +} + +const SetAllMemberListModal = ({ + isOpenBottomSheet, + setIsOpenBottomSheet, + setIsOpenAllMemberListButton, +}: SetAllMemberListModalProps) => { + const handleCloseAllMemberListModal = () => { + setIsOpenAllMemberListButton(prev => !prev); + setIsOpenBottomSheet(false); + }; + + return ( + +
+
+ 전체 참여자 수정하기 + {/* TODO: (@soha): 인원 텍스트 색 수정 필요 */} + + 총 N명 + +
+
+ + + +
+ +
+
+ ); +}; + +export default SetAllMemberListModal; diff --git a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx index d273c5e6a..070ff7cd1 100644 --- a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx +++ b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx @@ -11,11 +11,11 @@ import { } from './SetInitialMemberListModal.style'; interface SetInitialMemberListProps { - openBottomSheet: boolean; - setOpenBottomSheet: React.Dispatch>; + isOpenBottomSheet: boolean; + setIsOpenBottomSheet: React.Dispatch>; } -const SetInitialMemberListModal = ({openBottomSheet, setOpenBottomSheet}: SetInitialMemberListProps) => { +const SetInitialMemberListModal = ({isOpenBottomSheet, setIsOpenBottomSheet}: SetInitialMemberListProps) => { const { inputList, inputRefList, @@ -30,11 +30,11 @@ const SetInitialMemberListModal = ({openBottomSheet, setOpenBottomSheet}: SetIni const handleSubmit = () => { updateMemberList({memberNameList: getFilledInputList().map(({value}) => value), type: 'IN'}); - setOpenBottomSheet(false); + setIsOpenBottomSheet(false); }; return ( - setOpenBottomSheet(false)}> + setIsOpenBottomSheet(false)}>
초기 인원 설정하기
diff --git a/client/src/components/Modal/index.ts b/client/src/components/Modal/index.ts index a6e55f84a..7a9d0eaa4 100644 --- a/client/src/components/Modal/index.ts +++ b/client/src/components/Modal/index.ts @@ -1,2 +1,3 @@ export {default as SetActionListModal} from './SetActionModal/SetActionListModal'; export {default as SetInitialMemberListModal} from './SetInitialMemberListModal/SetInitialMemberListModal'; +export {default as SetAllMemberListModal} from './SetAllMemberListModal/SetAllMemberListModal'; diff --git a/client/src/components/StepList/BillStepItem.tsx b/client/src/components/StepList/BillStepItem.tsx index a386aec30..9a0474e5d 100644 --- a/client/src/components/StepList/BillStepItem.tsx +++ b/client/src/components/StepList/BillStepItem.tsx @@ -8,11 +8,12 @@ import {PutAndDeleteBillActionModal} from '@components/Modal/SetActionModal/PutA interface BillStepItemProps { step: BillStep; isOpenBottomSheet: boolean; - setOpenBottomSheet: React.Dispatch>; + setIsOpenBottomSheet: React.Dispatch>; } const BillStepItem: React.FC = ({step, isOpenBottomSheet, setOpenBottomSheet}) => { const [clickedIndex, setClickedIndex] = useState(-1); + const totalPrice = step.actions.reduce((acc, cur) => acc + cur.price, 0); const handleDragHandleItemClick = (index: number) => { diff --git a/client/src/components/StepList/MemberStepItem.tsx b/client/src/components/StepList/MemberStepItem.tsx index 8d93b373d..9a482c665 100644 --- a/client/src/components/StepList/MemberStepItem.tsx +++ b/client/src/components/StepList/MemberStepItem.tsx @@ -7,23 +7,23 @@ import {DeleteMemberActionModal} from '@components/Modal/SetActionModal/DeleteMe interface MemberStepItemProps { step: MemberStep; isOpenBottomSheet: boolean; - setOpenBottomSheet: React.Dispatch>; + setIsOpenBottomSheet: React.Dispatch>; } -const MemberStepItem: React.FC = ({step, isOpenBottomSheet, setOpenBottomSheet}) => { +const MemberStepItem: React.FC = ({step, isOpenBottomSheet, setIsOpenBottomSheet}) => { return ( <> name).join(', ')} ${step.type === 'IN' ? '들어옴' : '나감'}`} - onClick={() => setOpenBottomSheet(prev => !prev)} + onClick={() => setIsOpenBottomSheet(prev => !prev)} /> {isOpenBottomSheet && ( )} diff --git a/client/src/components/StepList/Step.tsx b/client/src/components/StepList/Step.tsx index 859085800..4d0f08903 100644 --- a/client/src/components/StepList/Step.tsx +++ b/client/src/components/StepList/Step.tsx @@ -10,12 +10,16 @@ interface StepProps { } const Step = ({step}: StepProps) => { - const [isOpenBottomSheet, setOpenBottomSheet] = useState(false); + const [isOpenBottomSheet, setIsOpenBottomSheet] = useState(false); if (step.type === 'BILL') { - return ; + return ( + + ); } else if (step.type === 'IN' || step.type === 'OUT') { - return ; + return ( + + ); } else { return <>; } diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.style.ts b/client/src/pages/EventPage/AdminPage/AdminPage.style.ts index 2025006d4..6fea4be3b 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.style.ts +++ b/client/src/pages/EventPage/AdminPage/AdminPage.style.ts @@ -1,6 +1,6 @@ import {css} from '@emotion/react'; -export const ReceiptStyle = () => +export const receiptStyle = () => css({ display: 'flex', flexDirection: 'column', @@ -8,3 +8,9 @@ export const ReceiptStyle = () => padding: '0 8px', paddingBottom: '8.75rem', }); + +export const titleAndListButtonContainerStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + }); diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index 2c4ccd5a9..0918aa1da 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -1,52 +1,22 @@ import {useEffect, useState} from 'react'; -import {Title, FixedButton} from 'haengdong-design'; +import {Title, FixedButton, ListButton} from 'haengdong-design'; import StepList from '@components/StepList/StepList'; import {useStepList} from '@hooks/useStepList/useStepList'; import {requestGetEventName} from '@apis/request/event'; import useEventId from '@hooks/useEventId/useEventId'; +import ModalBasedOnMemberCount from '@components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount'; -import {SetActionListModal, SetInitialMemberListModal} from '@components/Modal'; - -import {ReceiptStyle} from './AdminPage.style'; - -interface ModalBasedOnMemberCountProps { - memberNameList: string[]; - openBottomSheet: boolean; - setOrder: React.Dispatch>; - setOpenBottomSheet: React.Dispatch>; -} - -const ModalBasedOnMemberCount = ({ - memberNameList, - openBottomSheet, - setOrder, - setOpenBottomSheet, -}: ModalBasedOnMemberCountProps) => { - switch (memberNameList.length) { - case 0: - return ; - - default: - return ( - - ); - } -}; +import {receiptStyle, titleAndListButtonContainerStyle} from './AdminPage.style'; const AdminPage = () => { - const [openBottomSheet, setOpenBottomSheet] = useState(false); + const [isOpenFixedButtonBottomSheet, setIsOpenFixedBottomBottomSheet] = useState(false); const [order, setOrder] = useState(1); + const [isOpenAllMemberListButton, setIsOpenAllMemberListButton] = useState(false); // TODO: (@weadie) eventName이 새로고침시 공간이 없다가 생겨나 레이아웃이 움직이는 문제 const [eventName, setEventName] = useState(' '); - const {getTotalPrice, memberNameList} = useStepList(); - const {eventId} = useEventId(); // TODO: (@weadie) 아래 로직을 훅으로 분리합니다. @@ -62,26 +32,41 @@ const AdminPage = () => { getEventName(); }, [eventId]); + const handleOpenAllMemberListButton = () => { + setIsOpenFixedBottomBottomSheet(prev => !prev); + setIsOpenAllMemberListButton(prev => !prev); + }; + return ( <> - - <section css={ReceiptStyle}> + <div css={titleAndListButtonContainerStyle}> + <Title + title={eventName} + description="“초기인원 설정하기” 버튼을 눌러서 행사 초기 인원을 설정해 주세요." + price={getTotalPrice()} + /> + {memberNameList.length !== 0 && ( + <ListButton + prefix="전체 참여자" + suffix={`${memberNameList.length}명`} + onClick={handleOpenAllMemberListButton} + /> + )} + </div> + <section css={receiptStyle}> <StepList /> - {/* TODO: (@soha) 추후 버튼 width 화면에 맞게 수정 */} <FixedButton children={memberNameList.length === 0 ? '초기인원 설정하기' : '행동 추가하기'} - onClick={() => setOpenBottomSheet(prev => !prev)} + onClick={() => setIsOpenFixedBottomBottomSheet(prev => !prev)} /> - {openBottomSheet && ( + {isOpenFixedButtonBottomSheet && ( <ModalBasedOnMemberCount memberNameList={memberNameList} setOrder={setOrder} - setOpenBottomSheet={setOpenBottomSheet} - openBottomSheet={openBottomSheet} + setIsOpenBottomSheet={setIsOpenFixedBottomBottomSheet} + isOpenBottomSheet={isOpenFixedButtonBottomSheet} + isOpenAllMemberListButton={isOpenAllMemberListButton} + setIsOpenAllMemberListButton={setIsOpenAllMemberListButton} /> )} </section>