Skip to content

Commit

Permalink
Merge pull request #65 from Hana4Team/feat/#53
Browse files Browse the repository at this point in the history
[Feature/#53] ์†Œ๋น„ํŒจํ„ด api ์—ฐ๊ฒฐ
  • Loading branch information
abcxj123 authored Jun 10, 2024
2 parents 3a4b8ce + 4663f16 commit 35ef5ee
Show file tree
Hide file tree
Showing 12 changed files with 567 additions and 106 deletions.
58 changes: 56 additions & 2 deletions src/apis/apiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import {
OpenedDepositSavingReqType,
OpendDepositSavingSuccessResType,
} from '../types/account';
import { alarmApi } from './interfaces/alarmApi';
import { API_BASE_URL } from './url';
import { SpendListType } from '../types/spend';
import { spendApi } from './interfaces/spendApi';
import { BudgetReqType, BudgetResType } from '../types/budget';
import { budgetApi } from './interfaces/budgetApi';
import { depositsavingType } from '../types/depositsaving';
import { HomeType } from '../types/home';
import { depositsavingApi } from './interfaces/depositsavingApi';
Expand Down Expand Up @@ -58,6 +60,8 @@ export class ApiClient
transactionApi,
depositsavingApi,
newsApi,
budgetApi,
spendApi,
{
private static instance: ApiClient;
private axiosInstance: AxiosInstance;
Expand Down Expand Up @@ -207,6 +211,56 @@ export class ApiClient
return response.data;
}

//---------spend---------
async getSpendList(year: number, month: number) {
const response = await this.axiosInstance.request<SpendListType>({
method: 'get',
url: `/spend?year=${year}&month=${month}`,
});
return response.data;
}

//---------budget---------
async getTotalBudget() {
const response = await this.axiosInstance.request<{ sum: number }>({
method: 'get',
url: '/budget',
});
return response.data;
}

async updateTotalBudget(sum: number) {
const response = await this.axiosInstance.request<{
isInitialUpdate: boolean;
}>({
method: 'put',
url: '/budget',
data: { sum },
});
return response.data;
}

async getCategoryBudget() {
const response = await this.axiosInstance.request<BudgetResType>({
method: 'get',
url: '/budget/category',
});
return response.data;
}

async updateCategoryBudget(budget: BudgetReqType) {
const response = await this.axiosInstance.request<{
success: boolean;
type: string;
message: string;
}>({
method: 'put',
url: '/budget/category',
data: budget,
});
return response.data;
}

//---------transaction---------
async getTransactionHistory(accountId: number, year: number, month: number) {
const response = await this.axiosInstance.request<TransactionHistoryType>({
Expand Down
10 changes: 10 additions & 0 deletions src/apis/interfaces/budgetApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { BudgetReqType, BudgetResType } from '../../types/budget';

export interface budgetApi {
getTotalBudget(): Promise<{ sum: number }>;
updateTotalBudget(sum: number): Promise<{ isInitialUpdate: boolean }>;
getCategoryBudget(): Promise<BudgetResType>;
updateCategoryBudget(
budget: BudgetReqType
): Promise<{ success: boolean; type: string; message: string }>;
}
5 changes: 5 additions & 0 deletions src/apis/interfaces/spendApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { SpendListType } from '../../types/spend';

export interface spendApi {
getSpendList(year: number, month: number): Promise<SpendListType>;
}
2 changes: 1 addition & 1 deletion src/components/molecules/CategoryEditItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const CategoryEditItem: FC<IProps> = ({

useEffect(() => {
inputRef.current!.value = balance.toString();
}, []);
}, [balance]);

return (
<div className='flex flex-row w-full py-3 justify-between items-center'>
Expand Down
4 changes: 2 additions & 2 deletions src/components/molecules/CategoryItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React, { FC } from 'react';
interface IProps {
color: string;
name: string;
balance: number;
balance?: number;
}

export const CategoryItem: FC<IProps> = ({ color, name, balance }) => {
Expand All @@ -13,7 +13,7 @@ export const CategoryItem: FC<IProps> = ({ color, name, balance }) => {
<div className={`h-4 w-4 rounded-full bg-[${color}]`} />
<p className='font-hanaMedium text-2xl'>{name}</p>
</div>
<p className='font-hanaCM text-2xl'>{balance.toLocaleString()}์›</p>
<p className='font-hanaCM text-2xl'>{balance?.toLocaleString()}์›</p>
</div>
);
};
42 changes: 37 additions & 5 deletions src/components/organisms/BudgetInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,35 @@
import { FC, useState } from 'react';
import { useMutation } from '@tanstack/react-query';
import { FC, useEffect, useState } from 'react';
import { RiPencilFill } from 'react-icons/ri';
import { ApiClient } from '../../apis/apiClient';

interface Iprops {
month: number;
balance: number;
balance?: number;
lastSpend?: number;
initialFunc?: () => void;
}

export const BudgetInfo: FC<Iprops> = ({ month, balance, lastSpend }) => {
export const BudgetInfo: FC<Iprops> = ({
month,
balance,
lastSpend,
initialFunc,
}) => {
const [isEdit, SetIsEdit] = useState<boolean>(false);
const [value, setValue] = useState(balance.toLocaleString());
const [value, setValue] = useState(balance?.toLocaleString());

const {
mutate: updateBudget,
isSuccess: isSuccessUpdate,
data: budgetRes,
} = useMutation({
mutationKey: ['updateBudget'],
mutationFn: (sum: number) => {
const res = ApiClient.getInstance().updateTotalBudget(sum);
return res;
},
});

const valueChangeHandler = (e: any) => {
let inputPrice = e.target.value;
Expand All @@ -24,16 +44,28 @@ export const BudgetInfo: FC<Iprops> = ({ month, balance, lastSpend }) => {
};

const onClickConfirm = () => {
const realValue = Number(value!.replace(/[^0-9]/g, ''));
updateBudget(realValue);
SetIsEdit(false);
};

useEffect(() => {
if (isSuccessUpdate && budgetRes.isInitialUpdate) {
initialFunc!();
}
}, [isSuccessUpdate]);

useEffect(() => {
setValue(balance?.toLocaleString());
}, [balance]);

return (
<div className='flex flex-col w-full p-7 bg-white'>
<p className='font-hanaRegular text-2xl mb-3'>{month}์›” ์˜ˆ์‚ฐ</p>
{/* ๋ณด๊ธฐ ๋ชจ๋“œ */}
{!isEdit && (
<div className='flex flex-row mt-2 mb-3 items-center gap-2'>
<p className='font-hanaHeavy text-5xl'>{value.toLocaleString()}์›</p>
<p className='font-hanaHeavy text-5xl'>{value?.toLocaleString()}์›</p>
<RiPencilFill
size={25}
color='545454'
Expand Down
29 changes: 14 additions & 15 deletions src/components/organisms/CategorySpendCard.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
import React, { FC, useState } from 'react';
import React, { FC, useEffect, useState } from 'react';
import { IoIosArrowBack, IoIosArrowForward } from 'react-icons/io';
import { ArcElement, Chart } from 'chart.js';
import { Doughnut } from 'react-chartjs-2';
import { CategoryItem } from '../molecules/CategoryItem';
import { dateMonth, dateYear } from '../../utils/getDate';

type DataType = {
name: string;
balance: number;
};
import { SpendType } from '../../types/spend';

interface Iprops {
datas: DataType[];
datas: SpendType[];
year: number;
month: number;
balance: number;
Expand All @@ -31,27 +27,28 @@ export const CategorySpendCard: FC<Iprops> = ({
}) => {
const [showAll, setShowAll] = useState<boolean>(false);
const [text, setText] = useState<string>('์ „์ฒด๋ณด๊ธฐ');
const [re, setRe] = useState<boolean>(false);

Chart.register(ArcElement);

const extra =
datas.length <= 4
? null
: datas.slice(5).reduce((acc, val) => acc + val.balance, 0);
: datas.slice(5).reduce((acc, val) => acc + val.amount, 0);

const colors = ['#28B2A5', '#E90061', '#FFC700', '#AD9A5F', '#B5B5B5'];

const data = {
labels: [
...datas.slice(0, Math.min(datas.length, 4)).map((item) => item.name),
...datas.slice(0, Math.min(datas.length, 4)).map((item) => item.type),
'๊ธฐํƒ€',
],
datasets: [
{
data: [
...datas
.slice(0, Math.min(datas.length, 4))
.map((item) => item.balance),
.map((item) => item.amount),
extra,
],
borderWidth: 2,
Expand Down Expand Up @@ -138,9 +135,10 @@ export const CategorySpendCard: FC<Iprops> = ({
</div>
{datas.slice(0, Math.min(datas.length, 4)).map((item, idx) => (
<CategoryItem
key={idx}
color={colors[idx]}
name={item.name}
balance={item.balance}
name={item.type}
balance={item.amount}
/>
))}
{extra && (
Expand All @@ -151,11 +149,12 @@ export const CategorySpendCard: FC<Iprops> = ({
{showAll &&
datas
.slice(5)
.map((item) => (
.map((item, idx) => (
<CategoryItem
key={idx}
color={colors[4]}
name={item.name}
balance={item.balance}
name={item.type}
balance={item.amount}
/>
))}
<div
Expand Down
Loading

0 comments on commit 35ef5ee

Please sign in to comment.