Skip to content

Commit

Permalink
입/출금 내역 api (#104)
Browse files Browse the repository at this point in the history
* feat: instance에 return문 추가

* feat: 데이터 값에 맞게 각 컴포넌트 수정

* feat: 총 거래 계산 함수 데이터 값에 맞춤

* feat: 입 출금 내역 api 코드 작성

* feat: 입/출금 내역 api hook

* feat: 입/출금 내역 - month store

* feat: 입/출금 내역 임시 화면

* refactor: build 에러 해결

* refactor: 비밀번호 변경 관련 middleware 재설정

* style: 무한스크롤 관련 loading... -> 로딩중... 으로 변경

* refactor: 목록 페이지 무한스크롤 버그 관련 고침

* refactor: MonthComponent 현재 달부터 보이도록

* feat: 달 선택 carousel에서 select로 변경

* feat: 입/출금 내역 api 연결
  • Loading branch information
xxxjinn authored Aug 17, 2024
1 parent 0281610 commit 0b0906c
Show file tree
Hide file tree
Showing 19 changed files with 278 additions and 116 deletions.
9 changes: 9 additions & 0 deletions src/app/event/[organization]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,20 @@

import useEvent from '@/features/contentList/model/useEvent';
import ListLayoutComponent from '@/features/contentList/ui/ListLayoutComponent';
import { useQueryClient } from '@tanstack/react-query';
import { useEffect } from 'react';

const page = () => {
const queryClient = useQueryClient();
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading } =
useEvent();

useEffect(() => {
return () => {
queryClient.resetQueries();
};
}, [queryClient]);

const allContent = data?.pages.flatMap((page) => page.content);
return (
<ListLayoutComponent
Expand Down
9 changes: 9 additions & 0 deletions src/app/notice/[organization]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,20 @@

import useNotice from '@/features/contentList/model/useNotice';
import ListLayoutComponent from '@/features/contentList/ui/ListLayoutComponent';
import { useQueryClient } from '@tanstack/react-query';
import { useEffect } from 'react';

const page = () => {
const queryClient = useQueryClient();
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading } =
useNotice();

useEffect(() => {
return () => {
queryClient.resetQueries();
};
}, [queryClient]);

const allContent = data?.pages.flatMap((page) => page.content);
return (
<ListLayoutComponent
Expand Down
9 changes: 9 additions & 0 deletions src/app/proceeding/[organization]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,20 @@

import useProceeding from '@/features/contentList/model/useProceeding';
import ListLayoutComponent from '@/features/contentList/ui/ListLayoutComponent';
import { useQueryClient } from '@tanstack/react-query';
import { useEffect } from 'react';

const page = () => {
const queryClient = useQueryClient();
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading } =
useProceeding();

useEffect(() => {
return () => {
queryClient.resetQueries();
};
}, [queryClient]);

const allContent = data?.pages.flatMap((page) => page.content);
return (
<ListLayoutComponent
Expand Down
9 changes: 9 additions & 0 deletions src/app/rule/[organization]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,20 @@

import useRule from '@/features/contentList/model/useRule';
import ListLayoutComponent from '@/features/contentList/ui/ListLayoutComponent';
import { useQueryClient } from '@tanstack/react-query';
import { useEffect } from 'react';

const page = () => {
const queryClient = useQueryClient();
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading } =
useRule();

useEffect(() => {
return () => {
queryClient.resetQueries();
};
}, [queryClient]);

const allContent = data?.pages.flatMap((page) => page.content);
return (
<ListLayoutComponent
Expand Down
48 changes: 39 additions & 9 deletions src/app/transaction/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,58 @@
'use client';

import { transactionItems } from '@/shared/mock/contentList';
import MonthComponent from '@/views/transaction/MonthComponent';
import { useEffect, useState } from 'react';
import useTransactionDetail from '@/features/content/model/useTransactionDetail';
import TotalAmount from '@/views/transaction/TotalAmount';
import TransactionListComponent from '@/views/transaction/TransactionListComponent';
import Title from '@/widgets/Title';
import { usePathname } from 'next/navigation';
import { GetTransactionDetailResData } from '@/features/content/api/types';
import { useMonthStore } from '@/features/content/model/useTransactionMonthStore';
import MonthSelectComponent from '@/views/transaction/MonthSelectComponent';

const page = () => {
const Page = () => {
const pathname = usePathname();
const id = pathname.split('/')[2];
const organization = pathname.split('/')[2];
const { selectMonth } = useMonthStore();

const [transactionItems, setTransactionItems] = useState<
GetTransactionDetailResData[]
>([]);
const { data, isLoading } = useTransactionDetail(
organization,
new Date().getFullYear(),
selectMonth,
);

useEffect(() => {
if (data) {
setTransactionItems(data);
}
}, [data]);

return (
<div className="flex flex-col space-y-10">
<Title
text={`${id === 'studentCouncil' ? '총학생회' : id === 'college' ? '단과대' : '학과'} 입/출금 내역`}
text={`${
organization === 'studentCouncil'
? '총학생회'
: organization === 'college'
? '단과대'
: '학과'
} 입/출금 내역`}
/>
<div className="flex flex-col space-y-12">
<MonthComponent />
<TotalAmount items={transactionItems} />
<TransactionListComponent list={transactionItems} />
<MonthSelectComponent />
<>
<TotalAmount items={transactionItems} isLoading={isLoading} />
<TransactionListComponent
list={transactionItems}
isLoading={isLoading}
/>
</>
</div>
</div>
);
};

export default page;
export default Page;
21 changes: 21 additions & 0 deletions src/features/content/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
GetEventDetailResData,
GetRuleDetailResData,
GetProceedingDetailResData,
GetTransactionDetailResData,
} from './types';

export const NOTICE_DETAIL_API = {
Expand Down Expand Up @@ -46,6 +47,26 @@ export const EVENT_DETAIL_API = {
}
},
};

export const TRANSACTION_DETAIL_API = {
transaction: async (affiliation: string, year: number, month: number) => {
try {
const response = await instance.get<
ApiResponse<GetTransactionDetailResData[]>
>('/transactions', {
params: {
affiliation,
year,
month,
},
});
return response.data.data;
} catch (error) {
throw error;
}
},
};

//학칙/회칙 detail api
export const RULE_DETAIL_API = {
ruleDetail: async (ruleId: number) => {
Expand Down
42 changes: 13 additions & 29 deletions src/features/content/api/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,9 @@ import { AxiosError } from 'axios';
import {
GetNoticeDetailResData,
GetEventDetailResData,
GetProceedingDetailResData,
GetRuleDetailResData,
GetTransactionDetailResData,
} from './types';
import {
EVENT_DETAIL_API,
NOTICE_DETAIL_API,
PROCEEDING_DETAIL_API,
RULE_DETAIL_API,
} from '.';
import { EVENT_DETAIL_API, NOTICE_DETAIL_API, TRANSACTION_DETAIL_API } from '.';

//학교 공지 detail
export const useGetCampusNoticeDetail = (
Expand Down Expand Up @@ -55,30 +49,20 @@ export const useGetEventDetail = (
});
};

//학칙/회칙 detail
export const useGetRuleDetail = (
ruleId: number,
options?: UseQueryOptions<GetRuleDetailResData, AxiosError>,
) => {
return useQuery({
queryKey: ['ruleDetail', ruleId],
queryFn: async () => {
const data = await RULE_DETAIL_API.ruleDetail(ruleId);
return data;
},
...options,
});
};

//회의록 detail
export const useGetProceedingDetail = (
proceedingId: number,
options?: UseQueryOptions<GetProceedingDetailResData, AxiosError>,
export const useGetTransactionDetail = (
affiliation: string,
year: number,
month: number,
options?: UseQueryOptions<GetTransactionDetailResData[], AxiosError>,
) => {
return useQuery({
queryKey: ['proceedingDetail', proceedingId],
queryKey: ['transactionDetail', affiliation, year, month],
queryFn: async () => {
const data = await PROCEEDING_DETAIL_API.proceedingDetail(proceedingId);
const data = await TRANSACTION_DETAIL_API.transaction(
affiliation,
year,
month,
);
return data;
},
...options,
Expand Down
12 changes: 12 additions & 0 deletions src/features/content/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,15 @@ export interface GetProceedingDetailResData {
affiliationId: number;
fileInfo: DetailFileInfo[];
}

/** 입/출금 내역 detail */
export interface GetTransactionDetailResData {
transactionId: number;
accountNumber: string;
date: string;
type: string;
amount: number;
balance: number;
description: string;
note: string | null;
}
9 changes: 7 additions & 2 deletions src/features/content/model/usePdfDetail.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { useGetProceedingDetail, useGetRuleDetail } from '../api/queries';

const usePdfDetail = () => {
//회칙/학칙 detail
const returnRuleDetailItem = (organization: string, id: number) => {
Expand Down Expand Up @@ -51,3 +49,10 @@ const usePdfDetail = () => {
};

export default usePdfDetail;
function useGetRuleDetail(id: number): { data: any; isSuccess: any } {
throw new Error('Function not implemented.');
}

function useGetProceedingDetail(id: number): { data: any; isSuccess: any } {
throw new Error('Function not implemented.');
}
25 changes: 25 additions & 0 deletions src/features/content/model/useTransactionDetail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useGetTransactionDetail } from '../api/queries';

const useTransactionDetail = (
organization: string,
year: number,
month: number,
) => {
let affiliation;
if (organization === 'studentCouncil') {
affiliation = '총학';
} else if (organization === 'college') {
affiliation = '단과대';
} else if (organization === 'department') {
affiliation = '학과';
}

const queryResult = useGetTransactionDetail(
affiliation as string,
year,
month,
);
return queryResult;
};

export default useTransactionDetail;
19 changes: 19 additions & 0 deletions src/features/content/model/useTransactionMonthStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { create } from 'zustand';
import { persist } from 'zustand/middleware';

interface MonthState {
selectMonth: number;
setSelectMonth: (month: number) => void;
}

export const useMonthStore = create<MonthState>()(
persist(
(set) => ({
selectMonth: new Date().getMonth() + 1,
setSelectMonth: (month: number) => set({ selectMonth: month }),
}),
{
name: 'transaction-month-storage',
},
),
);
2 changes: 1 addition & 1 deletion src/features/contentList/ui/ListLayoutComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const ListLayoutComponent = ({
className="border-none"
>
{isLoadingMore ? (
'Loading...'
'로딩중...'
) : (
<>
<IoIosArrowDown /> 더보기
Expand Down
3 changes: 3 additions & 0 deletions src/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ export function middleware(req: NextRequest) {
}

if (!isAuthenticated) {
if (pathname.includes('/changePw')) {
return NextResponse.next();
}
const url = req.nextUrl.clone();
url.pathname = '/login';
return NextResponse.redirect(url);
Expand Down
2 changes: 2 additions & 0 deletions src/shared/api/instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,15 @@ instance.interceptors.response.use(
deleteToken();
alert('세션이 만료되었습니다. 다시 로그인해주세요.');
window.location.replace('/login');
return;
}
}
// Refresh 토큰이 만료된 경우
else if (errorCode === 'TOKEN_002') {
deleteToken();
alert('세션이 만료되었습니다. 다시 로그인해주세요.');
window.location.replace('/login');
return;
}
}
return Promise.reject(error);
Expand Down
12 changes: 6 additions & 6 deletions src/shared/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
TransactionItem,
} from '../types/type';
import { deleteCookie } from 'cookies-next';
import { GetTransactionDetailResData } from '@/features/content/api/types';

export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
Expand Down Expand Up @@ -74,16 +75,15 @@ export const getContent = (item: ListItem): string => {
};

/** 입/출금내역 총 거래 계산 함수 */
export const calculateTotals = (items: TransactionItem[]) => {
export const calculateTotals = (items: GetTransactionDetailResData[]) => {
let totalDeposit = 0;
let totalWithdraw = 0;

items.forEach((item) => {
if (item.deposit) {
totalDeposit += parseInt(item.deposit.replace(/,/g, ''), 10);
}
if (item.withdraw) {
totalWithdraw += parseInt(item.withdraw.replace(/,/g, ''), 10);
if (item.amount > 0) {
totalDeposit += item.amount;
} else if (item.amount < 0) {
totalWithdraw += -item.amount;
}
});

Expand Down
Loading

0 comments on commit 0b0906c

Please sign in to comment.