Skip to content

Commit

Permalink
feat: 행사 관리 페이지 구현 (#107)
Browse files Browse the repository at this point in the history
* style: eslint 적용

* chore: typescript with invalid interface loaded  as resolver 해결을 위한 eslint-import-resolver-typescript 설치

* chore: SetInitialParticipatns & SetActionModalContent를 Modal의 index.ts에서 export 추가

* design: HDesignProvider 적용

* design: 행사 관리 페이지 퍼블리싱

* design: 초기 인원 설정 Modal 퍼블리싱

* design: 지출내역 생성 Modal 내부 퍼블리싱

* design: 인원 변동 내역 Modal 내부 퍼블리싱

* feat: TopNav 추가 및 props 추가

* design: BottomSheet 내부 퍼블리싱 (Input overflow시 scroll)

* design: 행사 지출/인원 변동 내역 생성 퍼블리싱

* design: switch와 container의 gap 추가

* design: scroll시 모든 자식 요소가 안 보이는 에러 해결

* design: MainLayout 적용 및 root 태그에 height 적용

* design: 지출 내역 생성 Modal 내부 퍼블리싱

* design: 인원 변동 내역 생성 Modal 내부 퍼블리싱

* chore: develop 브랜치 merge로 인한 수정

* chore: 불필요한 import 삭제

* chore: haengdong-design 버전 업데이트 설치

* remove: 사용하지 않는 파일 제거

* chore: TopNav 수정된 디자인 시스템 설치 및 StepList 수정 주석 추가

* style: lint 적용

* feat: Input 값 입력시 다음 Input이 생성되는 hook 기능 구현

* feat: useDynamicInput에 auto focus 및 scrollIntoView 기능 추가

* feat: 초기 인원 설정 및 인원 변동 내역 Modal에 useDynamicInput 적용

* feat: 지출 내역에 대한 기능 구현 (useDynamicInputPairs 훅 생성)

* chore: 불필요한 props 제거 및 backlog 주석 추가

* fix: BottomSheet의 onClick을 통해 submit되는 오류 수정

* fix: setParticipants를 분리하여 참여 인원 관리

* fix: setOrder를 분리하여 지출 내역 차수 관리

* chore: 사용하지 않는 상태 제거

* chore: haengdong-design 버전 업데이트 반영

* fix: 작성된 값을 수정할 수 없는 에러 해결

* chore: 에러 발생 수정에 대한 주석 추가

* chore: 디자인시스템 버전 업데이트 반영
  • Loading branch information
soi-ha authored Jul 25, 2024
1 parent 3e2c5b0 commit 7b92958
Show file tree
Hide file tree
Showing 34 changed files with 459 additions and 362 deletions.
3 changes: 3 additions & 0 deletions client/eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ export default [
'react/react-in-jsx-scope': 'off',
'react/prop-types': 'off',
'react/jsx-uses-vars': 'error',
// '@typescript-eslint/no-use-before-define': ['error'],
// '@typescript-eslint/explicit-module-boundary-types': 'error',
// "import/no-unresolved": "error",
'import/order': [
'error',
{
Expand Down
8 changes: 4 additions & 4 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@
},
"dependencies": {
"@emotion/react": "^11.11.4",
"haengdong-design": "^0.1.20",
"@types/dotenv-webpack": "^7.0.7",
"dotenv-webpack": "^8.1.0",
"haengdong-design": "^0.1.28",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.24.1"
Expand Down
3 changes: 2 additions & 1 deletion client/src/apis/request/bill.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {Bill} from 'types/stepList';

import {BASE_URL} from '@apis/baseUrl';
import {TEMP_PREFIX} from '@apis/tempPrefix';
import {requestPost} from '@apis/fetcher';
import {WithEventId} from '@apis/withEventId.type';
import {Bill} from 'types/stepList';

type RequestAddBillList = {
BillList: Bill[];
Expand Down
3 changes: 2 additions & 1 deletion client/src/apis/request/event.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {StepList} from 'types/stepList';

import {BASE_URL} from '@apis/baseUrl';
import {TEMP_PREFIX} from '@apis/tempPrefix';
import {requestGet} from '@apis/fetcher';
import {StepList} from 'types/stepList';

type RequestCreateNewEvent = {
name: string;
Expand Down
3 changes: 2 additions & 1 deletion client/src/apis/request/member.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {Member} from 'types/stepList';

import {BASE_URL} from '@apis/baseUrl';
import {TEMP_PREFIX} from '@apis/tempPrefix';
import {requestPost} from '@apis/fetcher';
import {WithEventId} from '@apis/withEventId.type';
import {Member} from 'types/stepList';

type RequestUpdateMemberList = {
MemberList: Member[];
Expand Down
3 changes: 2 additions & 1 deletion client/src/apis/request/report.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {MemberReport} from 'types/stepList';

import {BASE_URL} from '@apis/baseUrl';
import {TEMP_PREFIX} from '@apis/tempPrefix';
import {requestGet} from '@apis/fetcher';
import {WithEventId} from '@apis/withEventId.type';
import {MemberReport} from 'types/stepList';

type ResponseMemberReportList = {
reports: MemberReport[];
Expand Down
3 changes: 2 additions & 1 deletion client/src/apis/request/stepList.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {Bill, Member, StepList} from 'types/stepList';

import {BASE_URL} from '@apis/baseUrl';
import {TEMP_PREFIX} from '@apis/tempPrefix';
import {requestGet, requestPost} from '@apis/fetcher';
import {WithEventId} from '@apis/withEventId.type';
import {Bill, Member, StepList} from 'types/stepList';

// TODO: (@weadie) 현재 토큰을 어떻게 관리할지.. 계속 사용되는데
export const requestStepList = async ({eventId}: WithEventId) => {
Expand Down
3 changes: 2 additions & 1 deletion client/src/components/MemberReportList/MemberReportList.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import useSearchMemberReportList from '@hooks/useSearchMemberReportList/useSearchMemberReportList';
import {ExpenseList, Flex, Input} from 'haengdong-design';
import React, {useState} from 'react';

import useSearchMemberReportList from '@hooks/useSearchMemberReportList/useSearchMemberReportList';

const MemberReportList = () => {
const [name, setName] = useState('');
const {memberReportSearchList} = useSearchMemberReportList({name, eventId: '므와아아아'});
Expand Down
20 changes: 0 additions & 20 deletions client/src/components/Modal/Modal.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {css} from '@emotion/react';

export const setActionModalContentStyle = css({
display: 'flex',
flexDirection: 'column',
width: '100%',
height: '100%',
padding: '0 1.5rem',
gap: '1.5rem',
});

export const setActionModalContentSwitchContainerStyle = css({
display: 'flex',
width: '100%',
justifyContent: 'space-between',
});

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,58 +1,60 @@
import {useState} from 'react';
import {BottomSheet, Switch} from 'haengdong-design';

import {Switch} from '@components/Switch';
import {InOutType, ParticipantType, PurchaseInformation} from '@pages/Event/Event';

import SetPurchase from './SetPurchase';
import UpdateParticipants from './UpdateParticipants';
import {switchContainerStyle} from './SetActionModalContent.style';
import {setActionModalContentStyle, setActionModalContentSwitchContainerStyle} from './SetActionModalContent.style';

// type ActionType = '지출' | '인원';
export type ActionType = '지출' | '인원';

interface SetActionModalContentProps {
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
participants: string[];
setParticipants: React.Dispatch<React.SetStateAction<string[]>>;
purchaseInformation: any;
setPurchaseInformation: any;
openBottomSheet: boolean;

setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>;
setOrder: React.Dispatch<React.SetStateAction<number>>;
}

const SetActionModalContent = ({
setOpen,
participants,
setParticipants,
purchaseInformation,
setPurchaseInformation,
openBottomSheet,

setOpenBottomSheet,
setOrder,
}: SetActionModalContentProps) => {
const [actionType, setActionType] = useState('지출');
const [participantType, setParticipantType] = useState('늦참');
const [action, setAction] = useState<ActionType>('지출');
const [participantAction, setParticipantAction] = useState<InOutType>('탈주');

const handleActionTypeChange = (value: string) => {
setAction(value as ActionType);
};

const handleParticipantTypeChange = (value: string) => {
setParticipantAction(value as InOutType);
};

return (
<>
<div css={switchContainerStyle}>
<Switch buttonList={['지출', '인원']} curSwitch={actionType} setSwitch={setActionType} />
{actionType === '인원' && (
<Switch buttonList={['늦참', '탈주']} curSwitch={participantType} setSwitch={setParticipantType} />
<BottomSheet isOpened={openBottomSheet} onChangeClose={() => setOpenBottomSheet(false)}>
<div css={setActionModalContentStyle}>
<div css={setActionModalContentSwitchContainerStyle}>
<Switch value={action} onChange={handleActionTypeChange} values={['지출', '인원']} />
{action === '인원' && (
<Switch values={['늦참', '탈주']} value={participantAction} onChange={handleParticipantTypeChange} />
)}
</div>

{action === '지출' && <SetPurchase setOpenBottomSheet={setOpenBottomSheet} setOrder={setOrder} />}
{action === '인원' && (
<UpdateParticipants
participantAction={participantAction}
participants={participants}
setOpenBottomSheet={setOpenBottomSheet}
/>
)}
</div>

{actionType === '지출' && (
<SetPurchase
setOpen={setOpen}
setPurchaseInformation={setPurchaseInformation}
purchaseInformation={purchaseInformation}
/>
)}
{actionType === '인원' && (
<UpdateParticipants
setOpen={setOpen}
participantType={participantType}
participants={participants}
setParticipants={setParticipants}
setPurchaseInformation={setPurchaseInformation}
purchaseInformation={purchaseInformation}
/>
)}
</>
</BottomSheet>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {css} from '@emotion/react';

export const setPurchaseStyle = () =>
css({
height: '100%',
});

export const setPurchaseInputContainerStyle = () =>
css({
display: 'flex',
height: '100%',
flexDirection: 'column',
gap: '1.5rem',
overflow: 'auto',
paddingBottom: '14rem',
});

export const setPurchaseInputStyle = () =>
css({
display: 'flex',
flexDirection: 'column',
gap: '0.5rem',
});
69 changes: 40 additions & 29 deletions client/src/components/Modal/SetActionModalContent/SetPurchase.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,53 @@
import {useState} from 'react';
import {Input, FixedButton} from 'haengdong-design';

import {PurchaseInformation} from '@pages/Event/Event';
import useDynamicInputPairs from '@hooks/useDynamicInputPairs';

import {setPurchaseInputStyle, setPurchaseStyle, setPurchaseInputContainerStyle} from './SetPurchase.style';

interface SetPurchaseProps {
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
setPurchaseInformation: any;
purchaseInformation: any;
setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>;
setOrder: React.Dispatch<React.SetStateAction<number>>;
}

const SetPurchase = ({setOpen, setPurchaseInformation}: SetPurchaseProps) => {
const [newPurchaseInformation, setNewPurchaseInformation] = useState<PurchaseInformation>({
name: '',
price: 0,
});

const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setNewPurchaseInformation({...newPurchaseInformation, name: e.target.value});
};

const handlePriceChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setNewPurchaseInformation({...newPurchaseInformation, price: parseFloat(e.target.value)});
};
const SetPurchase = ({setOpenBottomSheet, setOrder}: SetPurchaseProps) => {
const {inputPairs, inputRefs, handleInputChange, handleInputBlur} = useDynamicInputPairs();

const addPurchaseInformation = () => {
setPurchaseInformation((prev: PurchaseInformation[]) => [...prev, newPurchaseInformation]);
setOpen(false);
const handleSetPurchaseSubmit = () => {
setOrder(prev => prev + 1);
// TODO: (@soha) api 요청시 inputPairs를 보내면 됨
setOpenBottomSheet(false);
};

return (
<>
<div style={{display: 'flex', flexDirection: 'column'}}>
<input type="text" value={newPurchaseInformation.name} onChange={handleNameChange} placeholder="지출 내역" />
<input type="number" value={newPurchaseInformation.price} onChange={handlePriceChange} placeholder="금액" />
<div css={setPurchaseStyle}>
<div css={setPurchaseInputContainerStyle}>
{inputPairs.map((pair, index) => (
<div key={index} css={setPurchaseInputStyle}>
<Input
type="text"
value={pair.name}
onChange={e => handleInputChange(index, 'name', e.target.value)}
onBlur={() => handleInputBlur(index)}
placeholder="지출 내역"
ref={el => (inputRefs.current[index * 2] = el)}
/>
<Input
type="number"
value={pair.price}
onChange={e => handleInputChange(index, 'price', e.target.value)}
onBlur={() => handleInputBlur(index)}
placeholder="금액"
ref={el => (inputRefs.current[index * 2 + 1] = el)}
/>
</div>
))}
</div>
<button style={{backgroundColor: 'lightGreen'}} onClick={addPurchaseInformation}>
지출 내역 작성 완료
</button>
</>
<FixedButton
variants={inputPairs.length - 1 ? 'primary' : 'tertiary'}
children={'추가하기'}
onClick={handleSetPurchaseSubmit}
/>
</div>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {css} from '@emotion/react';

export const updateParticipantsStyle = () =>
css({
display: 'flex',
flexDirection: 'column',
gap: '1.5rem',
height: '100%',
});

export const updateParticipantsInputStyle = () =>
css({
display: 'flex',
flexDirection: 'column',
gap: '1rem',
overflow: 'auto',
paddingBottom: '14rem',
});
Loading

0 comments on commit 7b92958

Please sign in to comment.