Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

connect apiFnd005 #1285

Merged
merged 1 commit into from
Dec 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions packages/api/src/feature/funding/funding.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
Param,
Post,
Put,
Query,
UsePipes,
} from "@nestjs/common";
import apiFnd001, {
Expand All @@ -26,7 +27,7 @@ import apiFnd004, {
ApiFnd004ResponseOk,
} from "@sparcs-clubs/interface/api/funding/endpoint/apiFnd004";
import apiFnd005, {
ApiFnd005RequestBody,
ApiFnd005RequestQuery,
ApiFnd005ResponseOk,
} from "@sparcs-clubs/interface/api/funding/endpoint/apiFnd005";
import apiFnd006, {
Expand Down Expand Up @@ -102,9 +103,9 @@ export default class FundingController {
@UsePipes(new ZodPipe(apiFnd005))
async getStudentFundings(
@GetStudent() user: GetStudent,
@Body() body: ApiFnd005RequestBody,
@Query() query: ApiFnd005RequestQuery,
): Promise<ApiFnd005ResponseOk> {
return this.fundingService.getStudentFundings(user.studentId, body);
return this.fundingService.getStudentFundings(user.studentId, query);
}

@Student()
Expand Down
6 changes: 3 additions & 3 deletions packages/api/src/feature/funding/funding.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
ApiFnd003RequestParam,
} from "@sparcs-clubs/interface/api/funding/endpoint/apiFnd003";
import { ApiFnd004RequestParam } from "@sparcs-clubs/interface/api/funding/endpoint/apiFnd004";
import { ApiFnd005RequestBody } from "@sparcs-clubs/interface/api/funding/endpoint/apiFnd005";
import { ApiFnd005RequestQuery } from "@sparcs-clubs/interface/api/funding/endpoint/apiFnd005";
import {
ApiFnd006RequestBody,
ApiFnd006RequestParam,
Expand Down Expand Up @@ -264,7 +264,7 @@ export default class FundingService {
return this.fundingRepository.deleteStudentFunding(param.id);
}

async getStudentFundings(studentId: number, body: ApiFnd005RequestBody) {
async getStudentFundings(studentId: number, query: ApiFnd005RequestQuery) {
const user = await this.userPublicService.getStudentById({ id: studentId });
if (!user) {
throw new HttpException("Student not found", HttpStatus.NOT_FOUND);
Expand All @@ -276,7 +276,7 @@ export default class FundingService {

const fundings =
await this.fundingRepository.selectFundingsSemesterByClubId(
body.clubId,
query.clubId,
thisSemester,
);

Expand Down
11 changes: 6 additions & 5 deletions packages/interface/src/api/funding/endpoint/apiFnd005.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,25 @@ import { FundingOrderStatusEnum } from "@sparcs-clubs/interface/common/enum/fund
* @description 현재 학기의 지원금 신청을 조회합니다.
*/

const url = "/student/fundings";
const url = () => "/student/fundings";
const method = "GET";

const requestParam = z.object({});

const requestQuery = z.object({});

const requestBody = z.object({
const requestQuery = z.object({
clubId: z.coerce.number().int().min(1),
});

const requestBody = z.object({});

const responseBodyMap = {
[HttpStatusCode.Ok]: z.object({
fundings: z.array(
z.object({
id: z.coerce.number().int().min(1),
fundingOrderStatusEnumId: z.nativeEnum(FundingOrderStatusEnum),
activityName: z.coerce.string().max(255),
name: z.coerce.string().max(255),
expenditureAmount: z.coerce.number().int().min(0),
approvedAmount: z.coerce.number().int().min(0).optional(),
}),
Expand Down Expand Up @@ -53,8 +54,8 @@ type ApiFnd005ResponseOk = z.infer<(typeof apiFnd005.responseBodyMap)[200]>;
export default apiFnd005;

export type {
ApiFnd005RequestBody,
ApiFnd005RequestParam,
ApiFnd005RequestQuery,
ApiFnd005RequestBody,
ApiFnd005ResponseOk,
};
47 changes: 30 additions & 17 deletions packages/web/src/app/manage-club/funding/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import React from "react";

import { ApiClb015ResponseOk } from "@sparcs-clubs/interface/api/club/endpoint/apiClb015";

import AsyncBoundary from "@sparcs-clubs/web/common/components/AsyncBoundary";
import FlexWrapper from "@sparcs-clubs/web/common/components/FlexWrapper";
import PageHead from "@sparcs-clubs/web/common/components/PageHead";
import {
Expand All @@ -11,23 +14,33 @@ import {
} from "@sparcs-clubs/web/constants/manageClubFunding";
import NewFundingListSection from "@sparcs-clubs/web/features/manage-club/funding/components/NewFundingListSection";
import PastFundingListSection from "@sparcs-clubs/web/features/manage-club/funding/components/PastFundingListSection";
import { useGetMyManageClub } from "@sparcs-clubs/web/features/manage-club/services/getMyManageClub";

const Funding: React.FC = () => {
const { data, isLoading, isError } = useGetMyManageClub() as {
data: ApiClb015ResponseOk;
isLoading: boolean;
isError: boolean;
};

const Funding: React.FC = () => (
<FlexWrapper direction="column" gap={60}>
<PageHead
items={[
{ name: "대표 동아리 관리", path: "/manage-club" },
{
name: manageClubFundingPageBreadCrumbName,
path: manageClubFundingPagePath,
},
]}
title={manageClubFundingPageName}
/>
{/* TODO: API 구현 이후엔 테이블 데이터 전부 프레임에서 주입해줄 것! */}
<NewFundingListSection />
<PastFundingListSection />
</FlexWrapper>
);
return (
<FlexWrapper direction="column" gap={60}>
<PageHead
items={[
{ name: "대표 동아리 관리", path: "/manage-club" },
{
name: manageClubFundingPageBreadCrumbName,
path: manageClubFundingPagePath,
},
]}
title={manageClubFundingPageName}
/>
<AsyncBoundary isLoading={isLoading} isError={isError}>
<NewFundingListSection clubId={data?.clubId} />
<PastFundingListSection />
</AsyncBoundary>
</FlexWrapper>
);
};

export default Funding;
28 changes: 14 additions & 14 deletions packages/web/src/constants/tableTagList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
} from "@sparcs-clubs/interface/common/enum/activity.enum";
import { ActivityCertificateOrderStatusEnum } from "@sparcs-clubs/interface/common/enum/activityCertificate.enum";
import { CommonSpaceUsageOrderStatusEnum } from "@sparcs-clubs/interface/common/enum/commonSpace.enum";
import { FundingOrderStatusEnum } from "@sparcs-clubs/interface/common/enum/funding.enum";
import { PromotionalPrintingOrderStatusEnum } from "@sparcs-clubs/interface/common/enum/promotionalPrinting.enum";
import {
RegistrationStatusEnum,
Expand All @@ -16,7 +17,6 @@ import { DivisionType } from "@sparcs-clubs/web/types/divisions.types";
import { TagColor } from "../common/components/Tag";
import {
ActivityProfessorApprovalEnum,
FundingStatusEnum,
MemberStatusEnum,
} from "../features/manage-club/services/_mock/mockManageClub";
import { StatusDetail } from "../utils/getTagDetail";
Expand Down Expand Up @@ -92,12 +92,12 @@ const MemTagList: {
};

const FundingTagList: {
[key in FundingStatusEnum]: StatusDetail;
[key in FundingOrderStatusEnum]: StatusDetail;
} = {
[FundingStatusEnum.Applied]: { text: "신청", color: "BLUE" },
[FundingStatusEnum.Committee]: { text: "운위", color: "YELLOW" },
[FundingStatusEnum.Approved]: { text: "승인", color: "GREEN" },
[FundingStatusEnum.Rejected]: { text: "반려", color: "RED" },
[FundingOrderStatusEnum.Applied]: { text: "신청", color: "BLUE" },
[FundingOrderStatusEnum.Committee]: { text: "운위", color: "YELLOW" },
[FundingOrderStatusEnum.Approved]: { text: "승인", color: "GREEN" },
[FundingOrderStatusEnum.Rejected]: { text: "반려", color: "RED" },
};

// TODO: interface enum 사용
Expand Down Expand Up @@ -187,17 +187,17 @@ const DivisionTypeTagList: { [key in DivisionType]: StatusDetail } = {

export {
AcfTagList,
ActStatusTagList,
ActTypeTagList,
ApplyTagList,
CmsTagList,
PrtTagList,
RntTagList,
DivisionTypeTagList,
FundingTagList,
MemTagList,
ApplyTagList,
ActStatusTagList,
ProfessorApprovalTagList,
ProfessorIsApprovedTagList,
ActTypeTagList,
FundingTagList,
RegistrationTypeTagList,
PrtTagList,
RegistrationStatusTagList,
DivisionTypeTagList,
RegistrationTypeTagList,
RntTagList,
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useRouter } from "next/navigation";

import styled from "styled-components";

import AsyncBoundary from "@sparcs-clubs/web/common/components/AsyncBoundary";
import IconButton from "@sparcs-clubs/web/common/components/Buttons/IconButton";
import FlexWrapper from "@sparcs-clubs/web/common/components/FlexWrapper";
import FoldableSectionTitle from "@sparcs-clubs/web/common/components/FoldableSectionTitle";
Expand All @@ -17,6 +18,8 @@ import {
newFundingOrderButtonText,
} from "@sparcs-clubs/web/constants/manageClubFunding";

import useGetNewFundingList from "../services/useGetNewFundingList";

import NewFundingListTable from "./_atomic/NewFundingListTable";

const NewFundingOrderButtonRow = styled.div`
Expand All @@ -35,12 +38,20 @@ const NewFundingOrderButtonRow = styled.div`
flex-grow: 0; */
`;

const NewFundingListSection: React.FC = () => {
const NewFundingListSection: React.FC<{ clubId: number }> = ({ clubId }) => {
const router = useRouter();
const createFundingClick = () => {
router.push(`/manage-club/funding/create`);
};

const {
data: newFundingList,
isLoading: isLoadingNewFundingList,
isError: isErrorNewFundingList,
} = useGetNewFundingList({
clubId,
});

return (
<FoldableSectionTitle title={newFundingListSectionTitle}>
<FlexWrapper direction="column" gap={20}>
Expand All @@ -51,8 +62,12 @@ const NewFundingListSection: React.FC = () => {
{newFundingOrderButtonText}
</IconButton>
</NewFundingOrderButtonRow>
{/* TODO: ManageClubFundingMainFrame으로부터 주입받은 테이블 데이터 전달하기 */}
<NewFundingListTable />
<AsyncBoundary
isLoading={isLoadingNewFundingList}
isError={isErrorNewFundingList}
>
<NewFundingListTable newFundingList={newFundingList?.fundings} />
</AsyncBoundary>
</FlexWrapper>
</FoldableSectionTitle>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,35 @@ import Tag from "@sparcs-clubs/web/common/components/Tag";
import { numberToKrWon } from "@sparcs-clubs/web/constants/manageClubFunding";

import { FundingTagList } from "@sparcs-clubs/web/constants/tableTagList";
import {
Funding,
mockupManageFunding,
} from "@sparcs-clubs/web/features/manage-club/services/_mock/mockManageClub";
import { NewFundingData } from "@sparcs-clubs/web/features/manage-club/funding/types/funding";
import { getTagDetail } from "@sparcs-clubs/web/utils/getTagDetail";

const columnHelper = createColumnHelper<Funding>();
interface NewFundingListTableProps {
newFundingList?: NewFundingData[];
}

const columnHelper = createColumnHelper<NewFundingData>();

const columns = [
columnHelper.accessor("status", {
columnHelper.accessor("fundingOrderStatusEnumId", {
header: "상태",
cell: info => {
const { color, text } = getTagDetail(info.getValue(), FundingTagList);
return <Tag color={color}>{text}</Tag>;
},
size: 10,
}),
columnHelper.accessor("name", {
columnHelper.accessor("activityName", {
header: "활동명",
cell: info => info.getValue(),
size: 45,
}),
columnHelper.accessor("itemName", {
columnHelper.accessor("name", {
header: "항목명",
cell: info => info.getValue(),
size: 15,
}),
columnHelper.accessor("requestedAmount", {
columnHelper.accessor("expenditureAmount", {
header: "신청 금액",
cell: info => `${info.getValue().toLocaleString("ko-KR")}원`,
size: 15,
Expand All @@ -56,34 +57,36 @@ const columns = [
}),
];

const NewFundingListTable: React.FC = () => {
const NewFundingListTable: React.FC<NewFundingListTableProps> = ({
newFundingList = [],
}) => {
const table = useReactTable({
columns,
data: mockupManageFunding,
data: newFundingList,
getCoreRowModel: getCoreRowModel(),
enableSorting: false,
});

return (
<Table
table={table}
count={mockupManageFunding.length}
count={newFundingList.length}
footer={
<TableRow>
<TableCell type="Default" width="70%">
{"\t"}
</TableCell>
<TableCell type="Default" width="15%">
{numberToKrWon(
mockupManageFunding.reduce(
(acc, data) => acc + data.requestedAmount,
newFundingList.reduce(
(acc, data) => acc + data.expenditureAmount,
0,
),
)}
</TableCell>
<TableCell type="Default" width="15%">
{numberToKrWon(
mockupManageFunding.reduce(
newFundingList.reduce(
(acc, data) => acc + (data.approvedAmount ?? 0),
0,
),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import apiFnd005, {
ApiFnd005RequestQuery,
ApiFnd005ResponseOk,
} from "@sparcs-clubs/interface/api/funding/endpoint/apiFnd005";
import { useQuery } from "@tanstack/react-query";

import { mockupManageFunding } from "@sparcs-clubs/web/features/manage-club/services/_mock/mockManageClub";
import {
axiosClientWithAuth,
defineAxiosMock,
} from "@sparcs-clubs/web/lib/axios";

export const newActivityReportListQueryKey = (clubId: number) => [
apiFnd005.url(),
clubId,
];

const useGetNewFundingList = (query: ApiFnd005RequestQuery) =>
useQuery<ApiFnd005ResponseOk, Error>({
queryKey: newActivityReportListQueryKey(query.clubId),
queryFn: async (): Promise<ApiFnd005ResponseOk> => {
const { data } = await axiosClientWithAuth.get(apiFnd005.url(), {
params: query,
});

return apiFnd005.responseBodyMap[200].parse(data);
},
});

export default useGetNewFundingList;

defineAxiosMock(mock => {
mock.onGet(apiFnd005.url()).reply(() => [
200,
{
fundings: mockupManageFunding,
},
]);
});
Loading