Skip to content

Commit

Permalink
Merge pull request #246 from boostcamp-2020/fix/transaction/total
Browse files Browse the repository at this point in the history
๋ฉ”์ธํŽ˜์ด์ง€ ๋ฏธ๋ถ„๋ฅ˜ ํ•ฉ๊ณ„์—์„œ ์ œ์™ธ ๋ฐ  ์ˆ˜์ž… ์ง€์ถœ ๋ถ„๋ฆฌํ•˜๊ณ  ์ƒ‰์ƒ๊ตฌ๋ณ„
  • Loading branch information
rolled-potatoes authored Dec 16, 2020
2 parents 16ccd28 + 709fc05 commit 299d391
Show file tree
Hide file tree
Showing 13 changed files with 129 additions and 32 deletions.
2 changes: 0 additions & 2 deletions fe/src/components/atoms/Input/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ const Input = ({
inputRef,
...props
}: Props): React.ReactElement => {
console.log({ ...props });

return (
<SInput
id={id}
Expand Down
4 changes: 2 additions & 2 deletions fe/src/components/atoms/PriceTag/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import PriceContainer from './style';

interface Props {
export interface Props {
value: number;
bold?: boolean;
size?: string;
Expand All @@ -17,7 +17,7 @@ const PriceTag: React.FC<Props> = ({
}): React.ReactElement => {
return (
<PriceContainer bold={bold} size={size} color={color} {...props}>
{`${value.toLocaleString()}์›`}
{value === 0 ? '' : `${value.toLocaleString()}์›`}
</PriceContainer>
);
};
Expand Down
12 changes: 10 additions & 2 deletions fe/src/components/molecules/DateMoneyHeader/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,18 @@ export default {
export const DateMoneyHeaderSample = () => {
const date = new Date();
const value = 1000000;

const income = 400000;
const expense = 560000;
const unclassified = 0;
return (
<ThemeProvider theme={theme}>
<DateMoneyHeader totalPayment={value} date={date} />
<DateMoneyHeader
totalPayment={value}
date={date}
income={income}
expense={expense}
unclassified={unclassified}
/>
</ThemeProvider>
);
};
20 changes: 17 additions & 3 deletions fe/src/components/molecules/DateMoneyHeader/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,31 @@
import React from 'react';
import PriceTag from 'components/atoms/PriceTag';
import PriceWithSign from 'components/molecules/PriceWithSign';
import { categoryType } from 'stores/Category';
import { DateMoneyHeaderStyle, ReducedDate } from './style';

export interface Props {
date: Date;
totalPayment: number;
unclassified: number;
income: number;
expense: number;
}

const DateMoneyHeader = ({ date, totalPayment, ...props }: Props) => {
const DateMoneyHeader = ({
date,
totalPayment,
unclassified,
income,
expense,
...props
}: Props) => {
return (
<DateMoneyHeaderStyle {...props}>
<ReducedDate date={date} parseString="ymdz" />
<PriceTag value={totalPayment} bold />
<div className="price-container">
<PriceWithSign price={income} type={categoryType.INCOME} bold />
<PriceWithSign price={expense} type={categoryType.EXPENSE} bold />
</div>
</DateMoneyHeaderStyle>
);
};
Expand Down
4 changes: 4 additions & 0 deletions fe/src/components/molecules/DateMoneyHeader/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,8 @@ export const ReducedDate = styled(DateAtom)`
export const DateMoneyHeaderStyle = styled.div`
display: flex;
justify-content: space-between;
.price-container {
display: flex;
align-items: center;
}
`;
41 changes: 41 additions & 0 deletions fe/src/components/molecules/PriceWithSign/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react';
import { categoryType } from 'stores/Category';
import PriceTag, { Props } from 'components/atoms/PriceTag';
import * as S from './style';

export interface Prop extends Omit<Props, 'value'> {
price: number;
type: string;
}
const getPriceColor = (type: string) => {
switch (type) {
case categoryType.EXPENSE:
return 'red';
case categoryType.INCOME:
return 'brandColor';
default:
return 'black';
}
};
const getSigin = ({ type, price }: { type: string; price: number }) => {
if (price === 0) return '';
switch (type) {
case categoryType.EXPENSE:
return '-';
case categoryType.INCOME:
return '+';
default:
return '';
}
};
const PriceWithSign = ({ price, type, ...props }: Prop) => {
const color = getPriceColor(type);
const sign = getSigin({ type, price });
return (
<S.Price color={color}>
{sign}
<PriceTag value={price} color={color} {...props} />
</S.Price>
);
};
export default PriceWithSign;
16 changes: 16 additions & 0 deletions fe/src/components/molecules/PriceWithSign/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import styled from 'styled-components';

export interface IPrice {
color: string;
theme: {
[propName: string]: any;
};
}
export const Price = styled.div<IPrice>`
display: flex;
align-items: center;
color: ${({ theme, color }) => theme.color[color]};
& + & {
margin-left: 0.5em;
}
`;
5 changes: 4 additions & 1 deletion fe/src/components/molecules/Transaction/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import doubleArrowIcon from 'assets/svg/doubleArrow.svg';
import PriceWithSign from 'components/molecules/PriceWithSign';
import * as S from './style';

export interface Props {
Expand All @@ -9,6 +10,8 @@ export interface Props {

const Transaction = ({ trans, onClick }: Props) => {
const classificationString = `${trans.category} | ${trans.method}`;
const type = trans.categoryType;

return (
<S.TransactionStyle onClick={() => onClick(trans.id)}>
<S.TransactionIcon icon={trans.icon || doubleArrowIcon} size="sm" />
Expand All @@ -17,7 +20,7 @@ const Transaction = ({ trans, onClick }: Props) => {
<S.Client>{trans.client}</S.Client>
<S.Classification>{classificationString}</S.Classification>
</S.PaymentInfo>
<S.Price value={trans.price} />
<PriceWithSign price={trans.price} type={type} />
</S.Text>
</S.TransactionStyle>
);
Expand Down
5 changes: 0 additions & 5 deletions fe/src/components/molecules/Transaction/style.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import styled from 'styled-components';
import Icon from 'components/atoms/Icons';
import PriceTag from 'components/atoms/PriceTag';

export const TransactionStyle = styled.div`
box-sizing: border-box;
Expand Down Expand Up @@ -33,7 +32,3 @@ export const Classification = styled.div`
margin-top: 0.5em;
color: ${({ theme }) => theme.color.subText};
`;

export const Price = styled(PriceTag)`
margin-left: 0.5rem;
`;
33 changes: 25 additions & 8 deletions fe/src/components/organisms/TransactionList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import { categoryConvertBig2Small as convert } from 'stores/Category';
import * as S from './style';

export interface Props {
Expand All @@ -10,6 +11,9 @@ export interface Props {
interface accType {
transList: JSX.Element[];
totalPrice: number;
income: number;
expense: number;
unclassified: number;
}

const TransactionList = ({ date, transactionList, onClick }: Props) => {
Expand All @@ -22,20 +26,33 @@ const TransactionList = ({ date, transactionList, onClick }: Props) => {
/>,
);
acc.totalPrice += transEl.price;
acc[convert(transEl.categoryType)] = transEl.price;
return acc;
};

const { transList, totalPrice } = transactionList.reduce(
reduceTransactionList,
{
transList: [],
totalPrice: 0,
},
);
const {
transList,
totalPrice,
income,
expense,
unclassified,
} = transactionList.reduce(reduceTransactionList, {
transList: [],
totalPrice: 0,
income: 0,
expense: 0,
unclassified: 0,
});

return (
<S.TransactionList>
<S.Header date={date} totalPayment={totalPrice} />
<S.Header
date={date}
totalPayment={totalPrice}
income={income}
expense={expense}
unclassified={unclassified}
/>
{transList}
</S.TransactionList>
);
Expand Down
2 changes: 1 addition & 1 deletion fe/src/stores/Category/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const categoryConverter = (input: string): string => {
return categoryType.UNCLASSIFIED;
}
};
export const categoryConvertBig2Small = (input: string): string => {
export const categoryConvertBig2Small = (input: string) => {
switch (input) {
case categoryType.EXPENSE:
case 'expense':
Expand Down
7 changes: 3 additions & 4 deletions fe/src/stores/Transaction/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,9 @@ export const TransactionStore = makeAutoObservable({
return calTotalPriceByDateAndType(this.transactions, categoryType.EXPENSE);
},
get totalPrices(): { income: number; expense: number } {
if (this.isFiltered) {
return sumAllPricesByType(this.filteredTransactionList);
}
return calTotalPrices(this.getTransactions());
return this.isFiltered
? sumAllPricesByType(this.filteredTransactionList)
: calTotalPrices(this.getTransactions());
},
get filteredTransactionList(): types.TransactionDBType[] {
if (!this.isFiltered) return [];
Expand Down
10 changes: 6 additions & 4 deletions fe/src/stores/Transaction/transactionStoreUtils.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import math from 'utils/math';
import { IDateTotalprice, TransactionDBType, IDateTransactionObj } from 'types';
import { TransactionStore } from 'stores/Transaction';
import { categoryConvertBig2Small, categoryType } from 'stores/Category';
import { categoryConvertBig2Small } from 'stores/Category';
import dateUtil from 'utils/date';

export const initTotalPrice = {
income: 0,
expense: 0,
unclassified: 0,
};

export const sumAllPricesByType = (transactions: TransactionDBType[]) => {
return transactions.reduce((summedPriceByType, transaction) => {
const type =
transaction.category.type === categoryType.INCOME ? 'income' : 'expense';
const type = categoryConvertBig2Small(transaction.category.type);
return {
...summedPriceByType,
[type]: summedPriceByType[type] + transaction.price,
Expand Down Expand Up @@ -48,18 +48,20 @@ export const convertTransactionDBTypetoTransactionType = (input: any[]) => {
id: _id,
category: category.title,
method: method.title,
categoryType: category.type,
},
];
}, []);
};

export const calTotalPrices = (list: IDateTransactionObj) => {
return Object.values<TransactionDBType[]>(list).reduce(
(acc: { income: number; expense: number }, transactions) => {
(acc, transactions) => {
const summedPrices = sumAllPricesByType(transactions);
return {
income: acc.income + summedPrices.income,
expense: acc.expense + summedPrices.expense,
unclassified: acc.unclassified + summedPrices.unclassified,
};
},
initTotalPrice,
Expand Down

0 comments on commit 299d391

Please sign in to comment.