From 5918c15e27ab281fe5e994c7297cc401605b232d Mon Sep 17 00:00:00 2001 From: Woojeong Choi Date: Wed, 22 Jan 2025 13:34:26 +0900 Subject: [PATCH 01/15] fix: fix ActivityReportStatistic --- .../components/ActivityReportStatistic.tsx | 52 ++------------- .../ActivityReportStatisticContent.tsx | 65 +++++++++++++++++++ 2 files changed, 71 insertions(+), 46 deletions(-) create mode 100644 packages/web/src/features/executive/activity-report/components/ActivityReportStatisticContent.tsx diff --git a/packages/web/src/features/executive/activity-report/components/ActivityReportStatistic.tsx b/packages/web/src/features/executive/activity-report/components/ActivityReportStatistic.tsx index 4c604e063..814eabe40 100644 --- a/packages/web/src/features/executive/activity-report/components/ActivityReportStatistic.tsx +++ b/packages/web/src/features/executive/activity-report/components/ActivityReportStatistic.tsx @@ -1,14 +1,8 @@ import React from "react"; -import { Divider } from "@mui/material"; import { ApiAct023ResponseOk } from "@sparcs-clubs/interface/api/activity/endpoint/apiAct023"; -import Card from "@sparcs-clubs/web/common/components/Card"; -import FlexWrapper from "@sparcs-clubs/web/common/components/FlexWrapper"; -import Tag from "@sparcs-clubs/web/common/components/Tag"; -import Toggle from "@sparcs-clubs/web/common/components/Toggle"; -import Typography from "@sparcs-clubs/web/common/components/Typography"; -import { TotalContentsContainer } from "@sparcs-clubs/web/features/executive/register-member/components/StatusInfoFrame"; +import ActivityReportStatisticContent from "./ActivityReportStatisticContent"; interface ActivityReportStatisticProps { activities: ApiAct023ResponseOk; @@ -29,47 +23,13 @@ const ActivityReportStatistic: React.FC = ({ (acc, item) => acc + item.rejectedActivitiesCount, 0, ); - const reviewdTotalCount = approvedTotalCount + rejectedTotalCount; - const totalCount = - pendingTotalCount + approvedTotalCount + rejectedTotalCount; return ( - - 활동 보고서 통계}> - - - - 검토율 - - - {reviewdTotalCount}개 / {totalCount}개 ( - {((reviewdTotalCount / totalCount) * 100).toFixed(1)}%) - - - - - - 대기 - - {pendingTotalCount}개 - - - - 승인 - - {approvedTotalCount}개 - - - - 반려 - - {rejectedTotalCount}개 - - - - - - + ); }; diff --git a/packages/web/src/features/executive/activity-report/components/ActivityReportStatisticContent.tsx b/packages/web/src/features/executive/activity-report/components/ActivityReportStatisticContent.tsx new file mode 100644 index 000000000..8bf6fcdfa --- /dev/null +++ b/packages/web/src/features/executive/activity-report/components/ActivityReportStatisticContent.tsx @@ -0,0 +1,65 @@ +import React from "react"; + +import { Divider } from "@mui/material"; + +import Card from "@sparcs-clubs/web/common/components/Card"; +import FlexWrapper from "@sparcs-clubs/web/common/components/FlexWrapper"; +import Tag from "@sparcs-clubs/web/common/components/Tag"; +import Toggle from "@sparcs-clubs/web/common/components/Toggle"; +import Typography from "@sparcs-clubs/web/common/components/Typography"; +import { TotalContentsContainer } from "@sparcs-clubs/web/features/executive/register-member/components/StatusInfoFrame"; + +interface ActivityReportStatisticContentProps { + pendingTotalCount: number; + approvedTotalCount: number; + rejectedTotalCount: number; +} + +const ActivityReportStatisticContent: React.FC< + ActivityReportStatisticContentProps +> = ({ pendingTotalCount, approvedTotalCount, rejectedTotalCount }) => { + const reviewdTotalCount = approvedTotalCount + rejectedTotalCount; + const totalCount = + pendingTotalCount + approvedTotalCount + rejectedTotalCount; + + return ( + + 활동 보고서 통계}> + + + + 검토율 + + + {reviewdTotalCount}개 / {totalCount}개 ( + {((reviewdTotalCount / totalCount) * 100).toFixed(1)}%) + + + + + + 대기 + + {pendingTotalCount}개 + + + + 승인 + + {approvedTotalCount}개 + + + + 반려 + + {rejectedTotalCount}개 + + + + + + + ); +}; + +export default ActivityReportStatisticContent; From c1037978e32814bccef07985ad4eeaeed9eed7b3 Mon Sep 17 00:00:00 2001 From: Woojeong Choi Date: Wed, 22 Jan 2025 13:40:36 +0900 Subject: [PATCH 02/15] feat: impl skeleton for ExecutiveActivityReportChargedFrame --- .../activity-report/charged/[id]/page.tsx | 36 ++++++++++++++++++ .../ActivityReportChargedStatistic.tsx | 36 ++++++++++++++++++ .../components/ActivityReportStatistic.tsx | 2 +- .../ActivityReportStatisticContent.tsx | 5 ++- .../ExecutiveActivityReportChargedFrame.tsx | 37 +++++++++++++++++++ 5 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 packages/web/src/app/executive/activity-report/charged/[id]/page.tsx create mode 100644 packages/web/src/features/executive/activity-report/components/ActivityReportChargedStatistic.tsx rename packages/web/src/features/executive/activity-report/components/{ => _atomic}/ActivityReportStatisticContent.tsx (94%) create mode 100644 packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx diff --git a/packages/web/src/app/executive/activity-report/charged/[id]/page.tsx b/packages/web/src/app/executive/activity-report/charged/[id]/page.tsx new file mode 100644 index 000000000..71e594b42 --- /dev/null +++ b/packages/web/src/app/executive/activity-report/charged/[id]/page.tsx @@ -0,0 +1,36 @@ +"use client"; + +import React, { useEffect, useState } from "react"; + +import Custom404 from "@sparcs-clubs/web/app/not-found"; +import AsyncBoundary from "@sparcs-clubs/web/common/components/AsyncBoundary"; +import LoginRequired from "@sparcs-clubs/web/common/frames/LoginRequired"; +import { useAuth } from "@sparcs-clubs/web/common/providers/AuthContext"; +import ExecutiveActivityReportChargedFrame from "@sparcs-clubs/web/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame"; + +const ExecutiveActivityReport = () => { + const { isLoggedIn, login, profile } = useAuth(); + const [loading, setLoading] = useState(true); + + useEffect(() => { + if (isLoggedIn !== undefined || profile !== undefined) { + setLoading(false); + } + }, [isLoggedIn, profile]); + + if (loading) { + return ; + } + + if (!isLoggedIn) { + return ; + } + + if (profile?.type !== "executive") { + return ; + } + + return ; +}; + +export default ExecutiveActivityReport; diff --git a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedStatistic.tsx b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedStatistic.tsx new file mode 100644 index 000000000..1848f9795 --- /dev/null +++ b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedStatistic.tsx @@ -0,0 +1,36 @@ +import React from "react"; + +import { ApiAct023ResponseOk } from "@sparcs-clubs/interface/api/activity/endpoint/apiAct023"; + +import ActivityReportStatisticContent from "./_atomic/ActivityReportStatisticContent"; + +interface ActivityReportStatisticProps { + activities: ApiAct023ResponseOk; // to be changed +} + +const ActivityReportChargedStatistic: React.FC< + ActivityReportStatisticProps +> = ({ activities }) => { + const pendingTotalCount = activities.items.reduce( + (acc, item) => acc + item.pendingActivitiesCount, + 0, + ); + const approvedTotalCount = activities.items.reduce( + (acc, item) => acc + item.approvedActivitiesCount, + 0, + ); + const rejectedTotalCount = activities.items.reduce( + (acc, item) => acc + item.rejectedActivitiesCount, + 0, + ); + + return ( + + ); +}; + +export default ActivityReportChargedStatistic; diff --git a/packages/web/src/features/executive/activity-report/components/ActivityReportStatistic.tsx b/packages/web/src/features/executive/activity-report/components/ActivityReportStatistic.tsx index 814eabe40..62c792efb 100644 --- a/packages/web/src/features/executive/activity-report/components/ActivityReportStatistic.tsx +++ b/packages/web/src/features/executive/activity-report/components/ActivityReportStatistic.tsx @@ -2,7 +2,7 @@ import React from "react"; import { ApiAct023ResponseOk } from "@sparcs-clubs/interface/api/activity/endpoint/apiAct023"; -import ActivityReportStatisticContent from "./ActivityReportStatisticContent"; +import ActivityReportStatisticContent from "./_atomic/ActivityReportStatisticContent"; interface ActivityReportStatisticProps { activities: ApiAct023ResponseOk; diff --git a/packages/web/src/features/executive/activity-report/components/ActivityReportStatisticContent.tsx b/packages/web/src/features/executive/activity-report/components/_atomic/ActivityReportStatisticContent.tsx similarity index 94% rename from packages/web/src/features/executive/activity-report/components/ActivityReportStatisticContent.tsx rename to packages/web/src/features/executive/activity-report/components/_atomic/ActivityReportStatisticContent.tsx index 8bf6fcdfa..13d635052 100644 --- a/packages/web/src/features/executive/activity-report/components/ActivityReportStatisticContent.tsx +++ b/packages/web/src/features/executive/activity-report/components/_atomic/ActivityReportStatisticContent.tsx @@ -32,7 +32,10 @@ const ActivityReportStatisticContent: React.FC< {reviewdTotalCount}개 / {totalCount}개 ( - {((reviewdTotalCount / totalCount) * 100).toFixed(1)}%) + {totalCount === 0 + ? "-" + : ((reviewdTotalCount / totalCount) * 100).toFixed(1)} + %) diff --git a/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx b/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx new file mode 100644 index 000000000..45f8336e8 --- /dev/null +++ b/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx @@ -0,0 +1,37 @@ +import React from "react"; + +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 ActivityReportChargedStatistic from "../components/ActivityReportChargedStatistic"; + +const ExecutiveActivityReportChargedFrame: React.FC = () => { + const executiveName = "집행부"; + const isLoading = false; + const isError = false; + + return ( + + + + + + + ); +}; + +export default ExecutiveActivityReportChargedFrame; From 8876dadf392a0e86f23b5648c0e3a24169796e89 Mon Sep 17 00:00:00 2001 From: Woojeong Choi Date: Sat, 25 Jan 2025 17:55:16 +0900 Subject: [PATCH 03/15] feat: connect act028 --- .../ExecutiveActivityReportChargedFrame.tsx | 13 ++++++----- .../useGetExecutiveChargedActivities.tsx | 22 +++++++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 packages/web/src/features/executive/activity-report/services/useGetExecutiveChargedActivities.tsx diff --git a/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx b/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx index 45f8336e8..8e99b202c 100644 --- a/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx +++ b/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx @@ -1,16 +1,19 @@ import React from "react"; -import AsyncBoundary from "@sparcs-clubs/web/common/components/AsyncBoundary"; +import { useParams } from "next/navigation"; +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 ActivityReportChargedStatistic from "../components/ActivityReportChargedStatistic"; +import useGetExecutiveChargedActivities from "../services/useGetExecutiveChargedActivities"; const ExecutiveActivityReportChargedFrame: React.FC = () => { - const executiveName = "집행부"; - const isLoading = false; - const isError = false; + const { id: executiveId } = useParams(); + const { data, isLoading, isError } = useGetExecutiveChargedActivities({ + executiveId: Number(executiveId), + }); return ( @@ -23,7 +26,7 @@ const ExecutiveActivityReportChargedFrame: React.FC = () => { path: `/executive/activity-report`, }, ]} - title={`활동 보고서 검토 내역 (${executiveName})`} + title={`활동 보고서 검토 내역 (${data?.chargedExecutive.name})`} enableLast /> + useQuery({ + queryKey: [apiAct028.url(query.executiveId)], + queryFn: async (): Promise => { + const { data } = await axiosClientWithAuth.get( + apiAct028.url(query.executiveId), + {}, + ); + + return data; + }, + }); + +export default useGetExecutiveChargedActivities; From df3024ac38ec65efc36fbdb200847b50f95213d4 Mon Sep 17 00:00:00 2001 From: Woojeong Choi Date: Sun, 26 Jan 2025 16:47:13 +0900 Subject: [PATCH 04/15] feat: impl ActivityReportChargedStatistic --- .../ActivityReportChargedStatistic.tsx | 26 +++++++++---------- .../ExecutiveActivityChargedTable.tsx | 6 ++++- .../ExecutiveActivityReportChargedFrame.tsx | 4 +-- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedStatistic.tsx b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedStatistic.tsx index 1848f9795..04abbd973 100644 --- a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedStatistic.tsx +++ b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedStatistic.tsx @@ -1,28 +1,26 @@ import React from "react"; -import { ApiAct023ResponseOk } from "@sparcs-clubs/interface/api/activity/endpoint/apiAct023"; +import { IActivitySummaryExecutiveResponse } from "@sparcs-clubs/interface/api/activity/type/activity.type"; +import { ActivityStatusEnum } from "@sparcs-clubs/interface/common/enum/activity.enum"; import ActivityReportStatisticContent from "./_atomic/ActivityReportStatisticContent"; interface ActivityReportStatisticProps { - activities: ApiAct023ResponseOk; // to be changed + activities: IActivitySummaryExecutiveResponse[]; } const ActivityReportChargedStatistic: React.FC< ActivityReportStatisticProps > = ({ activities }) => { - const pendingTotalCount = activities.items.reduce( - (acc, item) => acc + item.pendingActivitiesCount, - 0, - ); - const approvedTotalCount = activities.items.reduce( - (acc, item) => acc + item.approvedActivitiesCount, - 0, - ); - const rejectedTotalCount = activities.items.reduce( - (acc, item) => acc + item.rejectedActivitiesCount, - 0, - ); + const pendingTotalCount = activities.filter( + activity => activity.activityStatusEnum === ActivityStatusEnum.Applied, + ).length; + const approvedTotalCount = activities.filter( + activity => activity.activityStatusEnum === ActivityStatusEnum.Approved, + ).length; + const rejectedTotalCount = activities.filter( + activity => activity.activityStatusEnum === ActivityStatusEnum.Rejected, + ).length; return ( {countString} - +
`/executive/activity-report/charged/${row.executiveId}`} + /> ); }; diff --git a/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx b/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx index 8e99b202c..9a60c5b0c 100644 --- a/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx +++ b/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx @@ -29,9 +29,7 @@ const ExecutiveActivityReportChargedFrame: React.FC = () => { title={`활동 보고서 검토 내역 (${data?.chargedExecutive.name})`} enableLast /> - + ); From d0bd51c62f73d8f6613b612605cc9605aa525299 Mon Sep 17 00:00:00 2001 From: Woojeong Choi Date: Sun, 26 Jan 2025 18:00:20 +0900 Subject: [PATCH 05/15] feat: impl ActivityReportChargedOtherTable --- .../ActivityReportChargedOtherTable.tsx | 117 ++++++++++++++++++ .../ActivityReportChargedStatistic.tsx | 8 +- .../ExecutiveActivityReportChargedFrame.tsx | 8 ++ 3 files changed, 127 insertions(+), 6 deletions(-) create mode 100644 packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx diff --git a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx new file mode 100644 index 000000000..e3dc07eb0 --- /dev/null +++ b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx @@ -0,0 +1,117 @@ +import React, { useMemo } from "react"; + +import { IActivitySummaryExecutiveResponse } from "@sparcs-clubs/interface/api/activity/type/activity.type"; + +import { ActivityStatusEnum } from "@sparcs-clubs/interface/common/enum/activity.enum"; +import { + createColumnHelper, + getCoreRowModel, + useReactTable, +} from "@tanstack/react-table"; + +import FlexWrapper from "@sparcs-clubs/web/common/components/FlexWrapper"; +import Table from "@sparcs-clubs/web/common/components/Table"; +import Tag from "@sparcs-clubs/web/common/components/Tag"; +import Typography from "@sparcs-clubs/web/common/components/Typography"; +import { + ActStatusTagList, + ActTypeTagList, +} from "@sparcs-clubs/web/constants/tableTagList"; +import { formatDateTime } from "@sparcs-clubs/web/utils/Date/formatDate"; +import { getTagDetail } from "@sparcs-clubs/web/utils/getTagDetail"; + +const columnHelper = + createColumnHelper(); +const columns = [ + columnHelper.accessor("club.name", { + header: "동아리", + cell: info => info.getValue(), + size: 200, + }), + columnHelper.accessor("name", { + header: "활동명", + cell: info => info.getValue(), + size: 252, + }), + columnHelper.accessor("activityTypeEnum", { + header: "활동 분류", + cell: info => { + const { color, text } = getTagDetail(info.getValue(), ActTypeTagList); + return {text}; + }, + size: 248, + }), + // TODO: 검토 일시 시간대 확인 + columnHelper.accessor("commentedAt", { + header: "검토 일시", + cell: info => formatDateTime(info.getValue() ?? new Date()), + size: 220, + }), + columnHelper.accessor("chargedExecutive", { + header: "담당자", + cell: info => + info.getValue() || ( + + (미정) + + ), + size: 120, + }), + columnHelper.accessor("activityStatusEnum", { + header: "상태", + cell: info => { + const { color, text } = getTagDetail(info.getValue(), ActStatusTagList); + return {text}; + }, + size: 120, + }), +]; + +const ActivityReportChargedOtherTable: React.FC<{ + activities: IActivitySummaryExecutiveResponse[]; +}> = ({ activities }) => { + const { length } = activities; + const sortedActivities = useMemo(() => { + const statusOrder = { + [ActivityStatusEnum.Applied]: 0, + [ActivityStatusEnum.Rejected]: 1, + [ActivityStatusEnum.Approved]: 2, + [ActivityStatusEnum.Committee]: 3, + }; + + return activities.sort((a, b) => { + if ( + statusOrder[a.activityStatusEnum] !== statusOrder[b.activityStatusEnum] + ) { + return ( + statusOrder[a.activityStatusEnum] - statusOrder[b.activityStatusEnum] + ); + } + if (a.commentedAt !== b.commentedAt) { + return ( + new Date(b.commentedAt ?? new Date()).getTime() - + new Date(a.commentedAt ?? new Date()).getTime() + ); + } + return 0; + }); + }, [activities]); + + const table = useReactTable({ + data: sortedActivities, + columns, + getCoreRowModel: getCoreRowModel(), + enableSorting: false, + }); + + return ( + + + 담당자가 아님 ({length}개) + +
+ + ); +}; + +export default ActivityReportChargedOtherTable; diff --git a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedStatistic.tsx b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedStatistic.tsx index 04abbd973..f38740a87 100644 --- a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedStatistic.tsx +++ b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedStatistic.tsx @@ -5,13 +5,9 @@ import { ActivityStatusEnum } from "@sparcs-clubs/interface/common/enum/activity import ActivityReportStatisticContent from "./_atomic/ActivityReportStatisticContent"; -interface ActivityReportStatisticProps { +const ActivityReportChargedStatistic: React.FC<{ activities: IActivitySummaryExecutiveResponse[]; -} - -const ActivityReportChargedStatistic: React.FC< - ActivityReportStatisticProps -> = ({ activities }) => { +}> = ({ activities }) => { const pendingTotalCount = activities.filter( activity => activity.activityStatusEnum === ActivityStatusEnum.Applied, ).length; diff --git a/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx b/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx index 9a60c5b0c..030c84960 100644 --- a/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx +++ b/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx @@ -6,6 +6,7 @@ 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 ActivityReportChargedOtherTable from "../components/ActivityReportChargedOtherTable"; import ActivityReportChargedStatistic from "../components/ActivityReportChargedStatistic"; import useGetExecutiveChargedActivities from "../services/useGetExecutiveChargedActivities"; @@ -15,6 +16,10 @@ const ExecutiveActivityReportChargedFrame: React.FC = () => { executiveId: Number(executiveId), }); + const otherActivities = data?.activities.filter( + activity => activity.chargedExecutive?.id !== data.chargedExecutive.id, + ); + return ( @@ -30,6 +35,9 @@ const ExecutiveActivityReportChargedFrame: React.FC = () => { enableLast /> + {otherActivities && otherActivities.length > 0 && ( + + )} ); From 4ca6ae8b5d677818656e7d70b85060acb4ffba53 Mon Sep 17 00:00:00 2001 From: Woojeong Choi Date: Sun, 26 Jan 2025 18:08:59 +0900 Subject: [PATCH 06/15] fix: import type --- .../components/ActivityReportChargedOtherTable.tsx | 4 ++-- .../components/ActivityReportChargedStatistic.tsx | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx index e3dc07eb0..3eeb54748 100644 --- a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx +++ b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx @@ -1,7 +1,5 @@ import React, { useMemo } from "react"; -import { IActivitySummaryExecutiveResponse } from "@sparcs-clubs/interface/api/activity/type/activity.type"; - import { ActivityStatusEnum } from "@sparcs-clubs/interface/common/enum/activity.enum"; import { createColumnHelper, @@ -20,6 +18,8 @@ import { import { formatDateTime } from "@sparcs-clubs/web/utils/Date/formatDate"; import { getTagDetail } from "@sparcs-clubs/web/utils/getTagDetail"; +import type { IActivitySummaryExecutiveResponse } from "@sparcs-clubs/interface/api/activity/type/activity.type"; + const columnHelper = createColumnHelper(); const columns = [ diff --git a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedStatistic.tsx b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedStatistic.tsx index f38740a87..07bc42d63 100644 --- a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedStatistic.tsx +++ b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedStatistic.tsx @@ -1,10 +1,11 @@ import React from "react"; -import { IActivitySummaryExecutiveResponse } from "@sparcs-clubs/interface/api/activity/type/activity.type"; import { ActivityStatusEnum } from "@sparcs-clubs/interface/common/enum/activity.enum"; import ActivityReportStatisticContent from "./_atomic/ActivityReportStatisticContent"; +import type { IActivitySummaryExecutiveResponse } from "@sparcs-clubs/interface/api/activity/type/activity.type"; + const ActivityReportChargedStatistic: React.FC<{ activities: IActivitySummaryExecutiveResponse[]; }> = ({ activities }) => { From eb09d8d438dada4611104b37cbd05519de1de811 Mon Sep 17 00:00:00 2001 From: Woojeong Choi Date: Sun, 26 Jan 2025 21:48:48 +0900 Subject: [PATCH 07/15] feat: impl ActivityReportChargedClubTable --- .../ActivityReportChargedClubTable.tsx | 118 ++++++++++++++++++ .../ActivityReportChargedOtherTable.tsx | 20 ++- .../ExecutiveActivityReportChargedFrame.tsx | 27 ++++ 3 files changed, 159 insertions(+), 6 deletions(-) create mode 100644 packages/web/src/features/executive/activity-report/components/ActivityReportChargedClubTable.tsx diff --git a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedClubTable.tsx b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedClubTable.tsx new file mode 100644 index 000000000..3eda228cb --- /dev/null +++ b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedClubTable.tsx @@ -0,0 +1,118 @@ +import React, { useMemo } from "react"; + +import { ActivityStatusEnum } from "@sparcs-clubs/interface/common/enum/activity.enum"; +import { + createColumnHelper, + getCoreRowModel, + useReactTable, +} from "@tanstack/react-table"; + +import FlexWrapper from "@sparcs-clubs/web/common/components/FlexWrapper"; +import MoreDetailTitle from "@sparcs-clubs/web/common/components/MoreDetailTitle"; +import Table from "@sparcs-clubs/web/common/components/Table"; +import Tag from "@sparcs-clubs/web/common/components/Tag"; +import { + ActStatusTagList, + ActTypeTagList, +} from "@sparcs-clubs/web/constants/tableTagList"; +import { formatDateTime } from "@sparcs-clubs/web/utils/Date/formatDate"; +import { getTagDetail } from "@sparcs-clubs/web/utils/getTagDetail"; + +import type { IActivitySummaryExecutiveResponse } from "@sparcs-clubs/interface/api/activity/type/activity.type"; + +const columnHelper = + createColumnHelper(); +const columns = [ + columnHelper.accessor("name", { + header: "활동명", + cell: info => info.getValue(), + size: 400, + }), + columnHelper.accessor("activityTypeEnum", { + header: "활동 분류", + cell: info => { + const { color, text } = getTagDetail(info.getValue(), ActTypeTagList); + return {text}; + }, + size: 248, + }), + // TODO: 검토 일시 시간대 확인 + columnHelper.accessor("commentedAt", { + header: "검토 일시", + cell: info => { + const date = info.getValue(); + return date ? formatDateTime(date) : "-"; + }, + size: 220, + }), + columnHelper.accessor(row => row.commentedExecutive?.name, { + header: "최종 검토자", + cell: info => info.getValue() || "-", + size: 120, + }), + columnHelper.accessor("activityStatusEnum", { + header: "상태", + cell: info => { + const { color, text } = getTagDetail(info.getValue(), ActStatusTagList); + return {text}; + }, + size: 120, + }), +]; + +const ActivityReportChargedClubTable: React.FC<{ + activities: IActivitySummaryExecutiveResponse[]; +}> = ({ activities }) => { + const { length } = activities; + + const sortedActivities = useMemo(() => { + const statusOrder = { + [ActivityStatusEnum.Applied]: 0, + [ActivityStatusEnum.Rejected]: 1, + [ActivityStatusEnum.Approved]: 2, + [ActivityStatusEnum.Committee]: 3, + }; + + return activities.sort((a, b) => { + if ( + statusOrder[a.activityStatusEnum] !== statusOrder[b.activityStatusEnum] + ) { + return ( + statusOrder[a.activityStatusEnum] - statusOrder[b.activityStatusEnum] + ); + } + if (a.commentedAt !== b.commentedAt) { + if (!a.commentedAt) return -1; + if (!b.commentedAt) return 1; + return ( + new Date(b.commentedAt ?? b.updatedAt).getTime() - + new Date(a.commentedAt ?? a.updatedAt).getTime() + ); + } + return 0; + }); + }, [activities]); + + const table = useReactTable({ + data: sortedActivities, + columns, + getCoreRowModel: getCoreRowModel(), + enableSorting: false, + }); + + return ( + + +
`/executive/activity-report/${row.id}`} + /> + + ); +}; + +export default ActivityReportChargedClubTable; diff --git a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx index 3eeb54748..c28914646 100644 --- a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx +++ b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx @@ -44,10 +44,13 @@ const columns = [ // TODO: 검토 일시 시간대 확인 columnHelper.accessor("commentedAt", { header: "검토 일시", - cell: info => formatDateTime(info.getValue() ?? new Date()), + cell: info => { + const date = info.getValue(); + return date ? formatDateTime(date) : "-"; + }, size: 220, }), - columnHelper.accessor("chargedExecutive", { + columnHelper.accessor(row => row.chargedExecutive?.name, { header: "담당자", cell: info => info.getValue() || ( @@ -88,9 +91,11 @@ const ActivityReportChargedOtherTable: React.FC<{ ); } if (a.commentedAt !== b.commentedAt) { + if (!a.commentedAt) return -1; + if (!b.commentedAt) return 1; return ( - new Date(b.commentedAt ?? new Date()).getTime() - - new Date(a.commentedAt ?? new Date()).getTime() + new Date(b.commentedAt ?? b.updatedAt).getTime() - + new Date(a.commentedAt ?? a.updatedAt).getTime() ); } return 0; @@ -106,10 +111,13 @@ const ActivityReportChargedOtherTable: React.FC<{ return ( - + 담당자가 아님 ({length}개) -
+
`/executive/activity-report/${row.id}`} + /> ); }; diff --git a/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx b/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx index 030c84960..a0a29a601 100644 --- a/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx +++ b/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx @@ -6,6 +6,7 @@ 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 ActivityReportChargedClubTable from "../components/ActivityReportChargedClubTable"; import ActivityReportChargedOtherTable from "../components/ActivityReportChargedOtherTable"; import ActivityReportChargedStatistic from "../components/ActivityReportChargedStatistic"; import useGetExecutiveChargedActivities from "../services/useGetExecutiveChargedActivities"; @@ -16,6 +17,25 @@ const ExecutiveActivityReportChargedFrame: React.FC = () => { executiveId: Number(executiveId), }); + const clubsActivities = data?.activities.reduce( + (acc, activity) => { + if (!activity.club?.id || !activity.chargedExecutive?.id) { + return acc; + } + + const newAcc = { ...acc }; + if (activity.chargedExecutive.id === data.chargedExecutive.id) { + const clubId = activity.club.id; + if (!newAcc[clubId]) { + newAcc[clubId] = []; + } + newAcc[clubId].push(activity); + } + return newAcc; + }, + {} as Record, + ); + const otherActivities = data?.activities.filter( activity => activity.chargedExecutive?.id !== data.chargedExecutive.id, ); @@ -35,6 +55,13 @@ const ExecutiveActivityReportChargedFrame: React.FC = () => { enableLast /> + {clubsActivities && + Object.entries(clubsActivities).map(([clubId, activities]) => ( + + ))} {otherActivities && otherActivities.length > 0 && ( )} From 22349c61126bc64b41058c6b4e1cee2b9d280479 Mon Sep 17 00:00:00 2001 From: Woojeong Choi Date: Sun, 26 Jan 2025 22:04:01 +0900 Subject: [PATCH 08/15] fix: fix type build error --- .../components/ActivityReportChargedClubTable.tsx | 7 +++---- .../components/ActivityReportChargedOtherTable.tsx | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedClubTable.tsx b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedClubTable.tsx index 3eda228cb..236af90e5 100644 --- a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedClubTable.tsx +++ b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedClubTable.tsx @@ -1,5 +1,6 @@ import React, { useMemo } from "react"; +import { ApiAct028ResponseOk } from "@sparcs-clubs/interface/api/activity/endpoint/apiAct028"; import { ActivityStatusEnum } from "@sparcs-clubs/interface/common/enum/activity.enum"; import { createColumnHelper, @@ -18,10 +19,8 @@ import { import { formatDateTime } from "@sparcs-clubs/web/utils/Date/formatDate"; import { getTagDetail } from "@sparcs-clubs/web/utils/getTagDetail"; -import type { IActivitySummaryExecutiveResponse } from "@sparcs-clubs/interface/api/activity/type/activity.type"; - const columnHelper = - createColumnHelper(); + createColumnHelper(); const columns = [ columnHelper.accessor("name", { header: "활동명", @@ -61,7 +60,7 @@ const columns = [ ]; const ActivityReportChargedClubTable: React.FC<{ - activities: IActivitySummaryExecutiveResponse[]; + activities: ApiAct028ResponseOk["activities"]; }> = ({ activities }) => { const { length } = activities; diff --git a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx index c28914646..768b63b95 100644 --- a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx +++ b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx @@ -1,5 +1,6 @@ import React, { useMemo } from "react"; +import { ApiAct028ResponseOk } from "@sparcs-clubs/interface/api/activity/endpoint/apiAct028"; import { ActivityStatusEnum } from "@sparcs-clubs/interface/common/enum/activity.enum"; import { createColumnHelper, @@ -18,10 +19,8 @@ import { import { formatDateTime } from "@sparcs-clubs/web/utils/Date/formatDate"; import { getTagDetail } from "@sparcs-clubs/web/utils/getTagDetail"; -import type { IActivitySummaryExecutiveResponse } from "@sparcs-clubs/interface/api/activity/type/activity.type"; - const columnHelper = - createColumnHelper(); + createColumnHelper(); const columns = [ columnHelper.accessor("club.name", { header: "동아리", @@ -71,7 +70,7 @@ const columns = [ ]; const ActivityReportChargedOtherTable: React.FC<{ - activities: IActivitySummaryExecutiveResponse[]; + activities: ApiAct028ResponseOk["activities"]; }> = ({ activities }) => { const { length } = activities; const sortedActivities = useMemo(() => { From 7229459128a287e0de1e4b80c03e9563e5a31276 Mon Sep 17 00:00:00 2001 From: Woojeong Choi Date: Sun, 26 Jan 2025 22:09:53 +0900 Subject: [PATCH 09/15] fix: fix type build error --- .../components/ActivityReportChargedStatistic.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedStatistic.tsx b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedStatistic.tsx index 07bc42d63..cfa850eb7 100644 --- a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedStatistic.tsx +++ b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedStatistic.tsx @@ -1,13 +1,12 @@ import React from "react"; +import { ApiAct028ResponseOk } from "@sparcs-clubs/interface/api/activity/endpoint/apiAct028"; import { ActivityStatusEnum } from "@sparcs-clubs/interface/common/enum/activity.enum"; import ActivityReportStatisticContent from "./_atomic/ActivityReportStatisticContent"; -import type { IActivitySummaryExecutiveResponse } from "@sparcs-clubs/interface/api/activity/type/activity.type"; - const ActivityReportChargedStatistic: React.FC<{ - activities: IActivitySummaryExecutiveResponse[]; + activities: ApiAct028ResponseOk["activities"]; }> = ({ activities }) => { const pendingTotalCount = activities.filter( activity => activity.activityStatusEnum === ActivityStatusEnum.Applied, From 23ba98cef2c89fb43b719deb783ac7b48e6f45a7 Mon Sep 17 00:00:00 2001 From: Woojeong Choi Date: Mon, 27 Jan 2025 22:30:19 +0900 Subject: [PATCH 10/15] fix: trim executive name --- .../frames/ExecutiveActivityReportChargedFrame.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx b/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx index a0a29a601..80a09f8f7 100644 --- a/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx +++ b/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx @@ -51,7 +51,7 @@ const ExecutiveActivityReportChargedFrame: React.FC = () => { path: `/executive/activity-report`, }, ]} - title={`활동 보고서 검토 내역 (${data?.chargedExecutive.name})`} + title={`활동 보고서 검토 내역 (${data?.chargedExecutive.name.trim()})`} enableLast /> From 43a258badd1c159acc5696533e4d1213f416bd29 Mon Sep 17 00:00:00 2001 From: Woojeong Choi Date: Mon, 27 Jan 2025 23:58:03 +0900 Subject: [PATCH 11/15] chore: change queryKey for act028 --- .../services/useGetExecutiveChargedActivities.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/src/features/executive/activity-report/services/useGetExecutiveChargedActivities.tsx b/packages/web/src/features/executive/activity-report/services/useGetExecutiveChargedActivities.tsx index 743cccd95..eb659901d 100644 --- a/packages/web/src/features/executive/activity-report/services/useGetExecutiveChargedActivities.tsx +++ b/packages/web/src/features/executive/activity-report/services/useGetExecutiveChargedActivities.tsx @@ -8,7 +8,7 @@ import { axiosClientWithAuth } from "@sparcs-clubs/web/lib/axios"; const useGetExecutiveChargedActivities = (query: ApiAct028RequestParam) => useQuery({ - queryKey: [apiAct028.url(query.executiveId)], + queryKey: ["executiveChargedActivities"], // 활동보고서 승인/반려 후 query invalidate를 위해 queryKey에 executiveId를 넣지 않음 queryFn: async (): Promise => { const { data } = await axiosClientWithAuth.get( apiAct028.url(query.executiveId), From 532152ab2de8133aeafbc1cb7e13e352a4d6820f Mon Sep 17 00:00:00 2001 From: Woojeong Choi Date: Sun, 2 Feb 2025 20:55:41 +0900 Subject: [PATCH 12/15] chore: fix typo and delete finished todo --- .../components/ActivityReportChargedClubTable.tsx | 1 - .../components/ActivityReportChargedOtherTable.tsx | 1 - .../components/ActivityReportClubStatistic.tsx | 6 +++--- .../components/_atomic/ActivityReportStatisticContent.tsx | 6 +++--- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedClubTable.tsx b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedClubTable.tsx index 236af90e5..e2655afcb 100644 --- a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedClubTable.tsx +++ b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedClubTable.tsx @@ -35,7 +35,6 @@ const columns = [ }, size: 248, }), - // TODO: 검토 일시 시간대 확인 columnHelper.accessor("commentedAt", { header: "검토 일시", cell: info => { diff --git a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx index 768b63b95..8ae83f42f 100644 --- a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx +++ b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx @@ -40,7 +40,6 @@ const columns = [ }, size: 248, }), - // TODO: 검토 일시 시간대 확인 columnHelper.accessor("commentedAt", { header: "검토 일시", cell: info => { diff --git a/packages/web/src/features/executive/activity-report/components/ActivityReportClubStatistic.tsx b/packages/web/src/features/executive/activity-report/components/ActivityReportClubStatistic.tsx index 33f1b48a2..a8abc108c 100644 --- a/packages/web/src/features/executive/activity-report/components/ActivityReportClubStatistic.tsx +++ b/packages/web/src/features/executive/activity-report/components/ActivityReportClubStatistic.tsx @@ -41,7 +41,7 @@ const ActivityReportClubStatistic: React.FC< acc + (item.activityStatusEnum === ActivityStatusEnum.Rejected ? 1 : 0), 0, ); - const reviewdTotalCount = approvedTotalCount + rejectedTotalCount; + const reviewedTotalCount = approvedTotalCount + rejectedTotalCount; const totalCount = pendingTotalCount + approvedTotalCount + rejectedTotalCount; @@ -67,8 +67,8 @@ const ActivityReportClubStatistic: React.FC< 검토율 - {reviewdTotalCount}개 / {totalCount}개 ( - {((reviewdTotalCount / totalCount) * 100).toFixed(1)}%) + {reviewedTotalCount}개 / {totalCount}개 ( + {((reviewedTotalCount / totalCount) * 100).toFixed(1)}%) diff --git a/packages/web/src/features/executive/activity-report/components/_atomic/ActivityReportStatisticContent.tsx b/packages/web/src/features/executive/activity-report/components/_atomic/ActivityReportStatisticContent.tsx index 13d635052..7128ad4c6 100644 --- a/packages/web/src/features/executive/activity-report/components/_atomic/ActivityReportStatisticContent.tsx +++ b/packages/web/src/features/executive/activity-report/components/_atomic/ActivityReportStatisticContent.tsx @@ -18,7 +18,7 @@ interface ActivityReportStatisticContentProps { const ActivityReportStatisticContent: React.FC< ActivityReportStatisticContentProps > = ({ pendingTotalCount, approvedTotalCount, rejectedTotalCount }) => { - const reviewdTotalCount = approvedTotalCount + rejectedTotalCount; + const reviewedTotalCount = approvedTotalCount + rejectedTotalCount; const totalCount = pendingTotalCount + approvedTotalCount + rejectedTotalCount; @@ -31,10 +31,10 @@ const ActivityReportStatisticContent: React.FC< 검토율 - {reviewdTotalCount}개 / {totalCount}개 ( + {reviewedTotalCount}개 / {totalCount}개 ( {totalCount === 0 ? "-" - : ((reviewdTotalCount / totalCount) * 100).toFixed(1)} + : ((reviewedTotalCount / totalCount) * 100).toFixed(1)} %) From 4fb0a33e7662e934c3837df9618c00ff2491459f Mon Sep 17 00:00:00 2001 From: Woojeong Choi Date: Sun, 2 Feb 2025 21:21:56 +0900 Subject: [PATCH 13/15] chore: move sort logics to utils --- .../ActivityReportChargedClubTable.tsx | 34 +++---------- .../ActivityReportChargedOtherTable.tsx | 33 +++--------- .../ExecutiveClubActivitiesTable.tsx | 26 +++------- .../activity-report/utils/sortActivities.ts | 51 +++++++++++++++++++ 4 files changed, 69 insertions(+), 75 deletions(-) create mode 100644 packages/web/src/features/executive/activity-report/utils/sortActivities.ts diff --git a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedClubTable.tsx b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedClubTable.tsx index e2655afcb..15d60c238 100644 --- a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedClubTable.tsx +++ b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedClubTable.tsx @@ -1,7 +1,6 @@ import React, { useMemo } from "react"; import { ApiAct028ResponseOk } from "@sparcs-clubs/interface/api/activity/endpoint/apiAct028"; -import { ActivityStatusEnum } from "@sparcs-clubs/interface/common/enum/activity.enum"; import { createColumnHelper, getCoreRowModel, @@ -19,6 +18,8 @@ import { import { formatDateTime } from "@sparcs-clubs/web/utils/Date/formatDate"; import { getTagDetail } from "@sparcs-clubs/web/utils/getTagDetail"; +import { sortActivitiesByStatusAndCommentedDate } from "../utils/sortActivities"; + const columnHelper = createColumnHelper(); const columns = [ @@ -63,33 +64,10 @@ const ActivityReportChargedClubTable: React.FC<{ }> = ({ activities }) => { const { length } = activities; - const sortedActivities = useMemo(() => { - const statusOrder = { - [ActivityStatusEnum.Applied]: 0, - [ActivityStatusEnum.Rejected]: 1, - [ActivityStatusEnum.Approved]: 2, - [ActivityStatusEnum.Committee]: 3, - }; - - return activities.sort((a, b) => { - if ( - statusOrder[a.activityStatusEnum] !== statusOrder[b.activityStatusEnum] - ) { - return ( - statusOrder[a.activityStatusEnum] - statusOrder[b.activityStatusEnum] - ); - } - if (a.commentedAt !== b.commentedAt) { - if (!a.commentedAt) return -1; - if (!b.commentedAt) return 1; - return ( - new Date(b.commentedAt ?? b.updatedAt).getTime() - - new Date(a.commentedAt ?? a.updatedAt).getTime() - ); - } - return 0; - }); - }, [activities]); + const sortedActivities = useMemo( + () => sortActivitiesByStatusAndCommentedDate(activities), + [activities], + ); const table = useReactTable({ data: sortedActivities, diff --git a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx index 8ae83f42f..f216a6c28 100644 --- a/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx +++ b/packages/web/src/features/executive/activity-report/components/ActivityReportChargedOtherTable.tsx @@ -1,7 +1,6 @@ import React, { useMemo } from "react"; import { ApiAct028ResponseOk } from "@sparcs-clubs/interface/api/activity/endpoint/apiAct028"; -import { ActivityStatusEnum } from "@sparcs-clubs/interface/common/enum/activity.enum"; import { createColumnHelper, getCoreRowModel, @@ -19,6 +18,8 @@ import { import { formatDateTime } from "@sparcs-clubs/web/utils/Date/formatDate"; import { getTagDetail } from "@sparcs-clubs/web/utils/getTagDetail"; +import { sortActivitiesByStatusAndCommentedDate } from "../utils/sortActivities"; + const columnHelper = createColumnHelper(); const columns = [ @@ -72,33 +73,11 @@ const ActivityReportChargedOtherTable: React.FC<{ activities: ApiAct028ResponseOk["activities"]; }> = ({ activities }) => { const { length } = activities; - const sortedActivities = useMemo(() => { - const statusOrder = { - [ActivityStatusEnum.Applied]: 0, - [ActivityStatusEnum.Rejected]: 1, - [ActivityStatusEnum.Approved]: 2, - [ActivityStatusEnum.Committee]: 3, - }; - return activities.sort((a, b) => { - if ( - statusOrder[a.activityStatusEnum] !== statusOrder[b.activityStatusEnum] - ) { - return ( - statusOrder[a.activityStatusEnum] - statusOrder[b.activityStatusEnum] - ); - } - if (a.commentedAt !== b.commentedAt) { - if (!a.commentedAt) return -1; - if (!b.commentedAt) return 1; - return ( - new Date(b.commentedAt ?? b.updatedAt).getTime() - - new Date(a.commentedAt ?? a.updatedAt).getTime() - ); - } - return 0; - }); - }, [activities]); + const sortedActivities = useMemo( + () => sortActivitiesByStatusAndCommentedDate(activities), + [activities], + ); const table = useReactTable({ data: sortedActivities, diff --git a/packages/web/src/features/executive/activity-report/components/ExecutiveClubActivitiesTable.tsx b/packages/web/src/features/executive/activity-report/components/ExecutiveClubActivitiesTable.tsx index 6d6a7c408..4f5b3680f 100644 --- a/packages/web/src/features/executive/activity-report/components/ExecutiveClubActivitiesTable.tsx +++ b/packages/web/src/features/executive/activity-report/components/ExecutiveClubActivitiesTable.tsx @@ -1,7 +1,6 @@ import React, { useEffect, useMemo, useState } from "react"; import { ApiAct024ResponseOk } from "@sparcs-clubs/interface/api/activity/endpoint/apiAct024"; -import { ActivityStatusEnum } from "@sparcs-clubs/interface/common/enum/activity.enum"; import { createColumnHelper, getCoreRowModel, @@ -20,6 +19,8 @@ import { ActStatusTagList } from "@sparcs-clubs/web/constants/tableTagList"; import { formatDateTime } from "@sparcs-clubs/web/utils/Date/formatDate"; import { getTagDetail } from "@sparcs-clubs/web/utils/getTagDetail"; +import { sortActivitiesByStatusAndActivityId } from "../utils/sortActivities"; + interface ExecutiveClubActivitiesTableProps { data: ApiAct024ResponseOk; searchText: string; @@ -80,25 +81,10 @@ const columns = [ const ExecutiveClubActivitiesTable: React.FC< ExecutiveClubActivitiesTableProps > = ({ data, searchText, selectedActivityIds, setSelectedActivityIds }) => { - const sortedActivities = useMemo(() => { - const statusOrder = { - [ActivityStatusEnum.Applied]: 0, - [ActivityStatusEnum.Rejected]: 1, - [ActivityStatusEnum.Approved]: 2, - [ActivityStatusEnum.Committee]: 3, - }; - - return [...data.items].sort((a, b) => { - if ( - statusOrder[a.activityStatusEnum] !== statusOrder[b.activityStatusEnum] - ) { - return ( - statusOrder[a.activityStatusEnum] - statusOrder[b.activityStatusEnum] - ); - } - return a.activityId < b.activityId ? -1 : 1; - }); - }, [data.items]); + const sortedActivities = useMemo( + () => sortActivitiesByStatusAndActivityId(data.items), + [data.items], + ); const initialRowValues = useMemo( () => diff --git a/packages/web/src/features/executive/activity-report/utils/sortActivities.ts b/packages/web/src/features/executive/activity-report/utils/sortActivities.ts new file mode 100644 index 000000000..d836681f3 --- /dev/null +++ b/packages/web/src/features/executive/activity-report/utils/sortActivities.ts @@ -0,0 +1,51 @@ +import { ApiAct024ResponseOk } from "@sparcs-clubs/interface/api/activity/endpoint/apiAct024"; +import { ApiAct028ResponseOk } from "@sparcs-clubs/interface/api/activity/endpoint/apiAct028"; +import { ActivityStatusEnum } from "@sparcs-clubs/interface/common/enum/activity.enum"; + +const statusOrder = { + [ActivityStatusEnum.Applied]: 0, + [ActivityStatusEnum.Rejected]: 1, + [ActivityStatusEnum.Approved]: 2, + [ActivityStatusEnum.Committee]: 3, +}; + +const sortActivitiesByStatusAndActivityId = ( + activities: ApiAct024ResponseOk["items"], +) => + activities.sort((a, b) => { + if ( + statusOrder[a.activityStatusEnum] !== statusOrder[b.activityStatusEnum] + ) { + return ( + statusOrder[a.activityStatusEnum] - statusOrder[b.activityStatusEnum] + ); + } + return a.activityId < b.activityId ? -1 : 1; + }); + +const sortActivitiesByStatusAndCommentedDate = ( + activities: ApiAct028ResponseOk["activities"], +) => + activities.sort((a, b) => { + if ( + statusOrder[a.activityStatusEnum] !== statusOrder[b.activityStatusEnum] + ) { + return ( + statusOrder[a.activityStatusEnum] - statusOrder[b.activityStatusEnum] + ); + } + if (a.commentedAt !== b.commentedAt) { + if (!a.commentedAt) return -1; + if (!b.commentedAt) return 1; + return ( + new Date(b.commentedAt ?? b.updatedAt).getTime() - + new Date(a.commentedAt ?? a.updatedAt).getTime() + ); + } + return 0; + }); + +export { + sortActivitiesByStatusAndActivityId, + sortActivitiesByStatusAndCommentedDate, +}; From 5ef163fe6dc9a15219f8d8b116d0c116b60ce227 Mon Sep 17 00:00:00 2001 From: Woojeong Choi Date: Sun, 2 Feb 2025 22:26:32 +0900 Subject: [PATCH 14/15] fix: fix query key --- .../services/useGetExecutiveChargedActivities.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/src/features/executive/activity-report/services/useGetExecutiveChargedActivities.tsx b/packages/web/src/features/executive/activity-report/services/useGetExecutiveChargedActivities.tsx index eb659901d..acf88caec 100644 --- a/packages/web/src/features/executive/activity-report/services/useGetExecutiveChargedActivities.tsx +++ b/packages/web/src/features/executive/activity-report/services/useGetExecutiveChargedActivities.tsx @@ -8,7 +8,7 @@ import { axiosClientWithAuth } from "@sparcs-clubs/web/lib/axios"; const useGetExecutiveChargedActivities = (query: ApiAct028RequestParam) => useQuery({ - queryKey: ["executiveChargedActivities"], // 활동보고서 승인/반려 후 query invalidate를 위해 queryKey에 executiveId를 넣지 않음 + queryKey: ["executiveChargedActivities", query.executiveId], queryFn: async (): Promise => { const { data } = await axiosClientWithAuth.get( apiAct028.url(query.executiveId), From bef61e70ec369243819e1ebff611bbb1e87a93ba Mon Sep 17 00:00:00 2001 From: Woojeong Choi Date: Sun, 2 Feb 2025 22:34:51 +0900 Subject: [PATCH 15/15] feat: add state for club view --- .../frames/ExecutiveActivityReportChargedFrame.tsx | 2 ++ .../frames/ExecutiveActivityReportFrame.tsx | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx b/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx index 80a09f8f7..2c6cc98f0 100644 --- a/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx +++ b/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportChargedFrame.tsx @@ -17,6 +17,8 @@ const ExecutiveActivityReportChargedFrame: React.FC = () => { executiveId: Number(executiveId), }); + window.history.replaceState({ isClubView: false }, ""); + const clubsActivities = data?.activities.reduce( (acc, activity) => { if (!activity.club?.id || !activity.chargedExecutive?.id) { diff --git a/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportFrame.tsx b/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportFrame.tsx index d04926942..923cdba71 100644 --- a/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportFrame.tsx +++ b/packages/web/src/features/executive/activity-report/frames/ExecutiveActivityReportFrame.tsx @@ -15,7 +15,9 @@ import ExecutiveActivityClubTable from "../components/ExecutiveActivityClubTable import useGetExecutiveActivities from "../services/useGetExecutiveActivities"; const ExecutiveActivityReportFrame = () => { - const [isClubView, setIsClubView] = useState(true); + const [isClubView, setIsClubView] = useState( + window.history.state.isClubView ?? true, + ); const [searchText, setSearchText] = useState(""); const { data, isLoading, isError } = useGetExecutiveActivities(); @@ -24,6 +26,10 @@ const ExecutiveActivityReportFrame = () => { ChargedChangeClubProps[] >([]); + useEffect(() => { + window.history.replaceState({ isClubView }, ""); + }, [isClubView]); + useEffect(() => { if (data) { setSelectedClubInfos(