diff --git a/README.md b/README.md
index 56633c23..5331e413 100644
--- a/README.md
+++ b/README.md
@@ -1,24 +1,135 @@
-## N석봉
+## N석봉 - 가계부 서비스
+
+
+
-> Project16-A-Account-Book
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+## 🏠 [HOME PAGE](http://xn--n-b22fl8h.kro.kr)
-## 💸 [HOME PAGE](http://xn--n-b22fl8h.kro.kr/login)
+돈은 너가 쓰거라 🤑, 관리는 내가 할테니 😎
-돈은 너가 쓰거라, 관리는 내가 할테니
+## 📌 가계부 서비스 소개
+### 👩👩👧👦 개인 또는 공용으로 관리할 수 있는 자산관리 가계부 서비스
+> - 혼자만의 가계부를 관리할 수 있습니다.
+> - 친구를 초대하여 함께 가계부를 관리할 수 있습니다.
+### 📈 지출과 수입에 대한 통계 제공
+> - 그동안의 지출내역과 수입을 **분석**하여 입출금 현황을 파악할 수 있습니다.
+### ✔️ 내가 보고 싶은 것들만 필터링
+> - 원하는 내역만 **필터링**해서 볼 수 있는 기능을 제공합니다.
+### 📆 달력을 통한 거래내역 확인
+> - 달 별로 돈의 사용 내역을 확인할 수 있습니다!
+### 📩 MMS를 입력하여 바로 거래내역에 추가
+> - 문자로 온 거래내역을 치기만 하면, 바로 거래내역에 추가할 수 있습니다.
-## 📌 소개
+
+## 📌 [기술 및 논의 정리 - WIKI](https://github.com/boostcamp-2020/Project16-A-Account-Book/wiki)
-💰 개인 또는 공용으로 이용 할 수 있는 자산관리 서비스 입니다.
+## 📌 주요 기능
-📈 입력된 데이터를 시작화하여 분석 및 파악 할 수 있는 기능을 제공합니다.
+|[🔗 로그인](https://github.com/boostcamp-2020/Project16-A-Account-Book/wiki/%EC%A3%BC%EC%9A%94-%EA%B8%B0%EB%8A%A5-%EC%86%8C%EA%B0%9C#-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%ED%8E%98%EC%9D%B4%EC%A7%80%EA%B8%B0%EB%8A%A5-%EC%86%8C%EA%B0%9C)|[🔗 가계부리스트](https://github.com/boostcamp-2020/Project16-A-Account-Book/wiki/%EC%A3%BC%EC%9A%94-%EA%B8%B0%EB%8A%A5-%EC%86%8C%EA%B0%9C#-%EA%B3%B5%EC%9C%A0-%EA%B0%80%EA%B3%84%EB%B6%80-%ED%8E%98%EC%9D%B4%EC%A7%80)|[🔗 메인페이지](https://github.com/boostcamp-2020/Project16-A-Account-Book/wiki/%EC%A3%BC%EC%9A%94-%EA%B8%B0%EB%8A%A5-%EC%86%8C%EA%B0%9C#-%EB%A9%94%EC%9D%B8-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%86%8C%EA%B0%9C)|[🔗 달력페이지](https://github.com/boostcamp-2020/Project16-A-Account-Book/wiki/%EC%A3%BC%EC%9A%94-%EA%B8%B0%EB%8A%A5-%EC%86%8C%EA%B0%9C#-%EB%8B%AC%EB%A0%A5-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%86%8C%EA%B0%9C)|
+|:--:|:--:|:--:|:--:|
+|![](https://i.imgur.com/Vh06k4p.png)|![](https://i.imgur.com/lfBYG9C.png)|![](https://i.imgur.com/fp18GM8.png)|![](https://i.imgur.com/QqL7sad.png)|
+
+|[🔗 통계페이지](https://github.com/boostcamp-2020/Project16-A-Account-Book/wiki/%EC%A3%BC%EC%9A%94-%EA%B8%B0%EB%8A%A5-%EC%86%8C%EA%B0%9C#-%ED%86%B5%EA%B3%84-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%86%8C%EA%B0%9C)|[🔗 채팅페이지](https://github.com/boostcamp-2020/Project16-A-Account-Book/wiki/%EC%A3%BC%EC%9A%94-%EA%B8%B0%EB%8A%A5-%EC%86%8C%EA%B0%9C#-%EC%B1%84%ED%8C%85-%ED%8E%98%EC%9D%B4%EC%A7%80%EA%B8%B0%EB%8A%A5-%EC%86%8C%EA%B0%9C)|[🔗 태그페이지](https://github.com/boostcamp-2020/Project16-A-Account-Book/wiki/%EC%A3%BC%EC%9A%94-%EA%B8%B0%EB%8A%A5-%EC%86%8C%EA%B0%9C#-%ED%83%9C%EA%B7%B8-%ED%8E%98%EC%9D%B4%EC%A7%80)|[🔗 알람 모달](https://github.com/boostcamp-2020/Project16-A-Account-Book/wiki/%EC%A3%BC%EC%9A%94-%EA%B8%B0%EB%8A%A5-%EC%86%8C%EA%B0%9C#-%EC%95%8C%EB%9E%8C-%EB%AA%A8%EB%8B%AC)|
+|:--:|:--:|:--:|:--:|
+|![](https://i.imgur.com/RDIQb3Q.png)|![](https://i.imgur.com/rhwIsA1.png)|![](https://i.imgur.com/36NIY7b.png)| |
+
+## 📌서비스 흐름
+![](https://i.imgur.com/w2UftIk.png)
+
+
+## ⚙️ 프로젝트 구동 방법
+
+우선 Repository clone한 후, Project16-A-Account-Book 폴더에 들어간다.
+
+**1. 몽고디비 설치 후 데이터베이스 생성**
+**2. 백엔드**
+- 백엔드 환경 변수 설정
+ - be 폴더 바로 밑에 .env 파일 생성
+ - .env-template 안에 있는 내용 작성
+ - .env 예시
+ - mongodb cloud의 경우 DB_PORT는 작성하지 않기
+ ```
+ DB_USER=[데이터베이스 유저 이름 (ex. test)]
+
+ DB_PASSWORD=[데이터베이스 password (ex. 123123)]
+
+ DB_HOST=[데이터베이스 호스트 이름 (ex. cluster0.3v1lt.mongodb.net)]
+
+ DB_DATABASE=[데이터베이스 이름 (ex. account?retryWrites=true&w=majority)]
+
+ DB_PORT=[데이터베이스 포트 (ex. 27017)]
+
+ JWT_SECRET=[JWT secret key (ex. ajsdFAG430tu04qkn) ]
+
+ GITHUB_ID=[GitHub_OAuth_Client_Id (ex. 6df23f10bc0622c89804)]
+
+ GITHUB_SECRET=[GitHub_OAuth_Client_Secret]
+
+ HOST=[서버 주소 (ex. http://localhost)]
+
+ BE_PORT=[백엔드엔드 서버 포트 (ex. 4000)]
+
+ FE_PORT=[프론트엔드 서버 포트 (ex. 3000)]
+
+ EXPIRES_IN=[JWT 토큰 만료 시간 (ex. 24h)]
+ ```
+
+- 실행
+
+ ```jsx
+ cd be
+ yarn
+ yarn dev
+ ```
+ or
+ ```jsx
+ cd be
+ npm install
+ npm run dev
+ ```
+
+**3. 프론트엔드**
+- 프론트엔드 환경 변수 설정
+ - fe 폴더 바로 밑에 .env.development 파일 생성
+ - .env_sample에 있는 내용 작성
+ - .env 예시
+ ```
+ REACT_APP_API_URL=[서버 주소 (ex. http://localhost)]
+
+ REACT_APP_API_PORT=[프론트엔드 서버 포트 (ex. 4000)]
+ ```
+
+- 실행
+ ```jsx
+ cd fe
+ yarn
+ yarn start
+ ```
+ or
+ ```jsx
+ cd fe
+ npm install
+ npm run start
+ ```
## 📌 팀원소개
@@ -27,6 +138,4 @@
| | | | |
| [dbstjrwnekd](https://github.com/dbstjrwnekd) | [yejineee](https://github.com/yejineee) | [pkiop](https://github.com/pkiop) | [rolled-potatoes](https://github.com/rolled-potatoes) |
-## 📌 기술 스택
-
diff --git a/be/package.json b/be/package.json
index e1df9b41..e2c81722 100644
--- a/be/package.json
+++ b/be/package.json
@@ -1,6 +1,6 @@
{
"scripts": {
- "dev": "cd src && nodemon --exec ts-node -r tsconfig-paths/register app.ts",
+ "dev": "cd src && NODE_ENV=development nodemon --exec ts-node -r tsconfig-paths/register app.ts",
"seed": "cd src && NODE_ENV=SEED ts-node -r tsconfig-paths/register seed.ts",
"unseed": "cd src && NODE_ENV=UNSEED ts-node -r tsconfig-paths/register seed.ts",
"seed-dev": "npm run seed && npm run dev",
diff --git a/be/src/.env-template b/be/src/.env-template
index deb03f71..c76643b1 100644
--- a/be/src/.env-template
+++ b/be/src/.env-template
@@ -8,5 +8,4 @@ GITHUB_ID=
GITHUB_SECRET=
HOST=
BE_PORT=
-FE_PORT=
EXPIRES_IN=
\ No newline at end of file
diff --git a/be/src/app.ts b/be/src/app.ts
index f0eb06e9..e08346bd 100644
--- a/be/src/app.ts
+++ b/be/src/app.ts
@@ -17,8 +17,8 @@ app.use(async (ctx, next) => {
ctx.body = err;
}
});
-app.use(cors(corsOptions));
+app.use(cors(corsOptions));
app.use(bodyParser());
app.use(Router.routes());
app.use(Router.allowedMethods());
diff --git a/be/src/config/index.ts b/be/src/config/index.ts
index 9f963bd4..2fa2d5f6 100644
--- a/be/src/config/index.ts
+++ b/be/src/config/index.ts
@@ -34,12 +34,9 @@ export const getDbUri = () => {
return dbConfig.port ? localUri : srvUri;
};
-export const getHostUrl = () => {
- return `${hostConfig.url}:${hostConfig.backPort}`;
-};
-
export const getFrontUrl = () => {
- return `${hostConfig.url}:${hostConfig.frontPort}`;
+ const port = process.env.NODE_ENV === 'development' ? ':3000' : '';
+ return `${hostConfig.url}${port}`;
};
export const corsOptions = {
diff --git a/be/src/controllers/user/index.ts b/be/src/controllers/user/index.ts
index 47c4fbee..fec804af 100644
--- a/be/src/controllers/user/index.ts
+++ b/be/src/controllers/user/index.ts
@@ -18,6 +18,7 @@ export const getUserByAccessToken = async (ctx: Context) => {
ctx.status = 200;
ctx.body = ctx.request.body.user;
};
+
export const getInvitation = async (ctx: Context) => {
const { user } = ctx.request.body;
const accounts = await userService.getInvitation(user);
@@ -26,8 +27,16 @@ export const getInvitation = async (ctx: Context) => {
title: account.title,
ownerName: account.ownerName,
host: user.invitations[idx].host,
+ imageUrl: account.imageUrl,
}));
ctx.body = invitations;
};
+export const deleteInvitation = async (ctx: Context) => {
+ const { user } = ctx.request.body;
+ const { accountObjId } = ctx.params;
+ await userService.denyInvitation(user, accountObjId);
+ ctx.status = 204;
+ ctx.res.end();
+};
export default titleByAccountId;
diff --git a/be/src/routers/api/user/account.ts b/be/src/routers/api/user/account.ts
index efe0b925..f5354ede 100644
--- a/be/src/routers/api/user/account.ts
+++ b/be/src/routers/api/user/account.ts
@@ -1,7 +1,9 @@
import Router from 'koa-router';
-import { getInvitation } from 'controllers/user';
+import { getInvitation, deleteInvitation } from 'controllers/user';
const router = new Router();
router.get('/', getInvitation);
+router.delete('/:accountObjId', deleteInvitation);
+
export default router;
diff --git a/be/src/services/user/index.ts b/be/src/services/user/index.ts
index c3e42969..58b7a6f9 100644
--- a/be/src/services/user/index.ts
+++ b/be/src/services/user/index.ts
@@ -1,5 +1,5 @@
import { UserModel, IUserDocument } from 'models/user';
-import { AccountModel, IAccountDocument } from 'models/account';
+import { AccountModel } from 'models/account';
export const titleByAccountId = async (accountId: String) => {
const account = await AccountModel.findOne(
@@ -14,14 +14,28 @@ export const getUserList = async () => {
const allUserList = await UserModel.find({}).exec();
return allUserList;
};
+
export const getInvitation = async (user: IUserDocument) => {
const account: any = user.invitations?.map((invitation) =>
AccountModel.findById(invitation.accounts).select(
- 'title _id ownerName accountProfile',
+ 'title _id ownerName imageUrl',
),
);
const results = await Promise.all(account);
return results;
};
+export const denyInvitation = async (
+ user: IUserDocument,
+ accountObjId: string,
+) => {
+ const prevInvitaionLength = user.invitations?.length;
+ // eslint-disable-next-line no-param-reassign
+ user.invitations = user.invitations?.filter(
+ (invitation) => String(invitation.accounts) !== accountObjId,
+ );
+ if (user.invitations?.length === prevInvitaionLength)
+ return Promise.resolve();
+ return user.save();
+};
export default titleByAccountId;
diff --git a/fe/package.json b/fe/package.json
index 5ae95d73..e5245038 100644
--- a/fe/package.json
+++ b/fe/package.json
@@ -64,6 +64,7 @@
"last 1 safari version"
]
},
+ "proxy":"http://localhost:4000",
"devDependencies": {
"@babel/core": "^7.12.3",
"@storybook/addon-actions": "^6.0.28",
diff --git a/fe/public/favicon.ico b/fe/public/favicon.ico
new file mode 100644
index 00000000..50a6caad
Binary files /dev/null and b/fe/public/favicon.ico differ
diff --git a/fe/public/index.html b/fe/public/index.html
index 1c0b14f7..6e98ad39 100644
--- a/fe/public/index.html
+++ b/fe/public/index.html
@@ -2,6 +2,7 @@
+
diff --git a/fe/src/apis/axios.ts b/fe/src/apis/axios.ts
index 655c4fbb..58bf25ed 100644
--- a/fe/src/apis/axios.ts
+++ b/fe/src/apis/axios.ts
@@ -2,7 +2,6 @@ import axios from 'axios';
const instance = axios.create({
withCredentials: true,
- baseURL: `${process.env.REACT_APP_API_URL}:${process.env.REACT_APP_API_PORT}`,
});
instance.interceptors.response.use(
diff --git a/fe/src/components/atoms/DatePicker/index.stories.tsx b/fe/src/components/atoms/DatePicker/index.stories.tsx
new file mode 100644
index 00000000..ac600360
--- /dev/null
+++ b/fe/src/components/atoms/DatePicker/index.stories.tsx
@@ -0,0 +1,21 @@
+import React, { useState } from 'react';
+
+import GlobalThemeProvider from 'styles/GlobalThemeProvider';
+import DatePicker from '.';
+
+export default {
+ title: 'atoms/DatePicker',
+ component: DatePicker,
+};
+
+export const datePicker = () => {
+ const [date, setDates] = useState(null);
+ const onChnage = (d: Date) => {
+ setDates(d);
+ };
+ return (
+
+
+
+ );
+};
diff --git a/fe/src/components/molecules/DatePicker/index.tsx b/fe/src/components/atoms/DatePicker/index.tsx
similarity index 64%
rename from fe/src/components/molecules/DatePicker/index.tsx
rename to fe/src/components/atoms/DatePicker/index.tsx
index 6a5de441..94e97b43 100644
--- a/fe/src/components/molecules/DatePicker/index.tsx
+++ b/fe/src/components/atoms/DatePicker/index.tsx
@@ -5,35 +5,39 @@ import ReactDatePicker, {
} from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
import ko from 'date-fns/locale/ko';
-import DateRange from '../DateRange';
import * as S from './style';
registerLocale('ko', ko);
setDefaultLocale('ko');
export interface IDatePicker {
- dates: {
- startDate: Date | null;
- endDate: Date | null;
- };
+ date: Date | null;
+ name?: string;
onChange: any;
+ disabled: boolean;
}
export interface IButton {
onClick?: any;
}
+export interface ICustomInput {
+ value?: any;
+ onClick?: any;
+}
-const DatePicker = ({ dates, onChange }: IDatePicker) => {
+const DatePicker = ({
+ date,
+ onChange,
+ name = 'startDate',
+ disabled,
+}: IDatePicker) => {
return (
-
onChange(d, name)}
className="my-react-picker"
locale={ko}
+ disabled={disabled}
+ dateFormat="yy.MM.dd"
popperPlacement="auto"
popperModifiers={{ preventOverflow: { enabled: true } }}
/>
diff --git a/fe/src/components/molecules/DatePicker/style.ts b/fe/src/components/atoms/DatePicker/style.ts
similarity index 83%
rename from fe/src/components/molecules/DatePicker/style.ts
rename to fe/src/components/atoms/DatePicker/style.ts
index 97dfa8c2..b774bfde 100644
--- a/fe/src/components/molecules/DatePicker/style.ts
+++ b/fe/src/components/atoms/DatePicker/style.ts
@@ -15,6 +15,11 @@ export const Container = styled.div`
.react-datepicker__month-container {
font-family: 'Bmeuljiro';
}
+ .my-react-picker {
+ background-color: ${({ theme }) => theme.color.white};
+ border: none;
+ outline: none;
+ }
`;
export const DecsContainer = styled.div`
diff --git a/fe/src/components/molecules/DatePicker/index.stories.tsx b/fe/src/components/molecules/DatePicker/index.stories.tsx
deleted file mode 100644
index e6c50b27..00000000
--- a/fe/src/components/molecules/DatePicker/index.stories.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import React, { useState } from 'react';
-
-import GlobalThemeProvider from 'styles/GlobalThemeProvider';
-import DatePicker from '.';
-
-export default {
- title: 'molecules/DatePicker',
- component: DatePicker,
-};
-export interface IDatePicker {
- dates: {
- startDate: Date;
- endDate: Date | null;
- };
- onChange: any;
-}
-export const datePicker = () => {
- const [dates, setDates] = useState<{
- startDate: Date;
- endDate: Date | null;
- }>({
- startDate: new Date(),
- endDate: new Date(),
- });
- const onChnage = (date: [Date, Date]) => {
- setDates({ startDate: date[0], endDate: date[1] });
- };
- return (
-
-
-
- );
-};
diff --git a/fe/src/components/molecules/DateRange/index.stories.tsx b/fe/src/components/molecules/DateRange/index.stories.tsx
index 064a6ba0..b513d834 100644
--- a/fe/src/components/molecules/DateRange/index.stories.tsx
+++ b/fe/src/components/molecules/DateRange/index.stories.tsx
@@ -12,9 +12,10 @@ export const dateRange = () => {
startDate: new Date(),
endDate: new Date(),
};
+ const onchange = () => {};
return (
-
+
);
};
diff --git a/fe/src/components/molecules/DateRange/index.tsx b/fe/src/components/molecules/DateRange/index.tsx
index 47aa1449..ae49be05 100644
--- a/fe/src/components/molecules/DateRange/index.tsx
+++ b/fe/src/components/molecules/DateRange/index.tsx
@@ -1,30 +1,39 @@
import React from 'react';
-import 'react-datepicker/dist/react-datepicker.css';
-import dateUtils from 'utils/date';
+import DatePicker from 'components/atoms/DatePicker';
import * as S from './style';
export interface IDateRange {
dates: {
- startDate: Date | string | null;
- endDate: Date | string | null;
+ startDate: Date | null;
+ endDate: Date | null;
};
+ onChange?: any;
+ disabled?: boolean;
}
-const DateRange = ({ dates }: IDateRange) => {
+const DateRange = ({ dates, onChange, disabled = false }: IDateRange) => {
return (
시작일
- {dates.startDate &&
- dateUtils.dateCustomFormatter(dates.startDate, 'YY.MM.DD')}
+
마지막일
- {dates.endDate &&
- dateUtils.dateCustomFormatter(dates.endDate, 'YY.MM.DD')}
+
diff --git a/fe/src/components/molecules/InvitationItem/index.stories.tsx b/fe/src/components/molecules/InvitationItem/index.stories.tsx
index ac33c932..17a55a3d 100644
--- a/fe/src/components/molecules/InvitationItem/index.stories.tsx
+++ b/fe/src/components/molecules/InvitationItem/index.stories.tsx
@@ -19,7 +19,7 @@ export const invitationItem = () => {
host={host}
accountObjId={accountObjId}
ownerName={owner}
- accountProfile={src}
+ imageUrl={src}
title={title}
/>
diff --git a/fe/src/components/molecules/InvitationItem/index.tsx b/fe/src/components/molecules/InvitationItem/index.tsx
index 4ed8c689..cfafe3ef 100644
--- a/fe/src/components/molecules/InvitationItem/index.tsx
+++ b/fe/src/components/molecules/InvitationItem/index.tsx
@@ -12,13 +12,13 @@ const InvitationItem = ({
host,
ownerName,
title,
- accountProfile,
+ imageUrl,
onClick,
}: Prop) => {
return (
-
+
diff --git a/fe/src/components/molecules/ModalContainer/style.ts b/fe/src/components/molecules/ModalContainer/style.ts
index 9ae056c0..cc997d5b 100644
--- a/fe/src/components/molecules/ModalContainer/style.ts
+++ b/fe/src/components/molecules/ModalContainer/style.ts
@@ -24,7 +24,7 @@ const Container = styled.div
`
width: 100vw;
height: 100vh;
display: flex;
- z-index: 100;
+ z-index: 1;
justify-content: ${({ justify }) => positionConverter(justify)};
align-items: ${({ align }) => positionConverter(align)};
background: ${({ theme }) => rgba(theme.color.black, 0.5)};
diff --git a/fe/src/components/organisms/InvitationList/index.tsx b/fe/src/components/organisms/InvitationList/index.tsx
index a33cf39f..f07de1ab 100644
--- a/fe/src/components/organisms/InvitationList/index.tsx
+++ b/fe/src/components/organisms/InvitationList/index.tsx
@@ -6,7 +6,7 @@ import Container from './style';
export interface IInvitaion {
accountObjId: string;
title: string;
- accountProfile: string;
+ imageUrl: string;
ownerName: string;
host: string;
}
diff --git a/fe/src/components/organisms/MainFilterForm/SubComponents/DatePickerList.tsx b/fe/src/components/organisms/MainFilterForm/SubComponents/DatePickerList.tsx
index 3d1c4e18..29872afb 100644
--- a/fe/src/components/organisms/MainFilterForm/SubComponents/DatePickerList.tsx
+++ b/fe/src/components/organisms/MainFilterForm/SubComponents/DatePickerList.tsx
@@ -1,13 +1,7 @@
import React from 'react';
import * as S from '../style';
-const DatePickerList = ({
- onClick,
- onClickFix,
-}: {
- onClick: any;
- onClickFix: any;
-}) => {
+const DatePickerList = ({ onClickFix }: { onClickFix: any }) => {
const innerTexts = ['오늘', '이번주', '이번달', '올 해'];
return (
@@ -18,7 +12,6 @@ const DatePickerList = ({
);
})}
- 기간 설정
);
};
diff --git a/fe/src/components/organisms/MainFilterForm/SubComponents/Modal.tsx b/fe/src/components/organisms/MainFilterForm/SubComponents/Modal.tsx
deleted file mode 100644
index 6b12f612..00000000
--- a/fe/src/components/organisms/MainFilterForm/SubComponents/Modal.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import React from 'react';
-import DataPicker, { IDatePicker } from '../../../molecules/DatePicker';
-import * as S from '../style';
-
-interface IModal extends IDatePicker {
- ref: any;
-}
-
-const Modal = ({ dates, onChange, ref }: IModal) => {
- return (
-
-
-
-
-
- );
-};
-
-export default Modal;
diff --git a/fe/src/components/organisms/MainFilterForm/SubComponents/index.ts b/fe/src/components/organisms/MainFilterForm/SubComponents/index.ts
index 0b298cdf..94cd83d9 100644
--- a/fe/src/components/organisms/MainFilterForm/SubComponents/index.ts
+++ b/fe/src/components/organisms/MainFilterForm/SubComponents/index.ts
@@ -1,4 +1,3 @@
-export { default as Modal } from './Modal';
export { default as CategoryFilterList } from './CategoryFilterList';
export { default as DatePickerList } from './DatePickerList';
export { default as TopFilter } from './TopFilter';
diff --git a/fe/src/components/organisms/MainFilterForm/index.tsx b/fe/src/components/organisms/MainFilterForm/index.tsx
index ad56a6f6..51db26b7 100644
--- a/fe/src/components/organisms/MainFilterForm/index.tsx
+++ b/fe/src/components/organisms/MainFilterForm/index.tsx
@@ -1,6 +1,5 @@
/* eslint-disable react/jsx-curly-newline */
-import React, { useRef, useReducer, useEffect } from 'react';
-import useVisible from 'hooks/useVisible';
+import React, { useReducer, useEffect } from 'react';
import { MethodStore } from 'stores/Method';
import {
CategoryStore,
@@ -15,12 +14,7 @@ import DateRange from '../../molecules/DateRange';
import DropdownHeader from '../../molecules/DropdownHeader';
import Dropdown from '../../molecules/Dropdown';
import { reducer, actions } from './filterReducer';
-import {
- TopFilter,
- CategoryFilterList,
- Modal,
- DatePickerList,
-} from './SubComponents';
+import { TopFilter, CategoryFilterList, DatePickerList } from './SubComponents';
const SELECT_ALL_TYPE = 'ALL';
@@ -28,15 +22,15 @@ const MainFilterForm = () => {
const [state, dispatch] = useReducer(reducer, {
dates: {
startDate: TransactionStore.getOriginDates().startDate,
- endDate: dateUtils.subTractDate(TransactionStore.getDates().endDate),
+ endDate: new Date(
+ dateUtils.subTractDate(TransactionStore.getDates().endDate),
+ ),
},
...TransactionStore.getFilter(),
});
const { dates, categories, methods } = state;
const { income, expense, unclassified } = categories;
- const container = useRef(null);
- const [visible, toggleVisible] = useVisible(container);
const selectAll = (type: string) => {
const fetchedCategories = CategoryStore.getCategories(type);
const selectedCategoryIdList =
@@ -90,11 +84,12 @@ const MainFilterForm = () => {
}
}
};
-
- const onChangeDate = (dateList: [Date | null, Date | null]) => {
- const [startDate, endDate] = dateList;
- dispatch(actions.setDates(startDate, endDate));
- if (endDate) toggleVisible();
+ const onChangeDate = (date: Date, name: string) => {
+ const targetDates = {
+ ...dates,
+ [name]: date,
+ };
+ dispatch(actions.setDates(targetDates.startDate, targetDates.endDate));
};
const onClickCategory = ({ type, _id }: { type: string; _id: string }) => {
@@ -135,21 +130,14 @@ const MainFilterForm = () => {
document.body.click();
};
return (
-
+
-
+
- toggleVisible}
- className="range-container"
- >
-
+
+
@@ -162,9 +150,6 @@ const MainFilterForm = () => {
title="결제수단"
/>
- {visible && (
-
- )}
카테고리
diff --git a/fe/src/components/organisms/MonthInfoHeader/index.tsx b/fe/src/components/organisms/MonthInfoHeader/index.tsx
index 5b4284b5..8b5a97c1 100644
--- a/fe/src/components/organisms/MonthInfoHeader/index.tsx
+++ b/fe/src/components/organisms/MonthInfoHeader/index.tsx
@@ -8,10 +8,7 @@ import DateRange from 'components/molecules/DateRange';
import { MonthInfoHeaderContainer, MonthButton } from './style';
interface MonthInfoHeaderInterface {
- date?: {
- startDate: string;
- endDate: string;
- };
+ date?: any;
total?: {
income: number;
expense: number;
@@ -25,8 +22,10 @@ type Params = {
const MonthInfoHeader = ({
date = {
- startDate: TransactionStore.getDates().startDate,
- endDate: dateUtils.subTractDate(TransactionStore.getDates().endDate),
+ startDate: TransactionStore.getOriginDates().startDate,
+ endDate: new Date(
+ dateUtils.subTractDate(TransactionStore.getDates().endDate),
+ ),
},
total = TransactionStore.totalPrices,
}: MonthInfoHeaderInterface) => {
@@ -34,7 +33,7 @@ const MonthInfoHeader = ({
const baseUrl = `/transactions/${owner}/${title}`;
return (
-
+
diff --git a/fe/src/hooks/useVisible.ts b/fe/src/hooks/useVisible.ts
index b6c9d5f7..2e59532f 100644
--- a/fe/src/hooks/useVisible.ts
+++ b/fe/src/hooks/useVisible.ts
@@ -4,11 +4,9 @@ const useVisible = (ref: RefObject): [boolean, Function] => {
const [visible, setVisible] = useState(false);
const outsideClickHandler = (event: any) => {
- event.stopPropagation();
- event.preventDefault();
+ if (event.target.classList.contains('react-datepicker__day')) return;
if (!ref.current) return;
if (event.target.closest('#date-picker')) return;
-
if (ref && !ref.current.contains(event.target)) {
setVisible(false);
}