diff --git a/packages/api/src/feature/activity/service/activity.activity-term.service.ts b/packages/api/src/feature/activity/service/activity.activity-term.service.ts index a9c1de3a9..bd8a6951b 100644 --- a/packages/api/src/feature/activity/service/activity.activity-term.service.ts +++ b/packages/api/src/feature/activity/service/activity.activity-term.service.ts @@ -91,14 +91,7 @@ export default class ActivityActivityTermService { id: row.id, name: row.name, activityTypeEnumId: row.activityTypeEnumId, - startTerm: duration.reduce( - (prev, curr) => (prev < curr.startTerm ? prev : curr.startTerm), - duration[0].startTerm, - ), - endTerm: duration.reduce( - (prev, curr) => (prev > curr.endTerm ? prev : curr.endTerm), - duration[0].endTerm, - ), + durations: duration, }; }), ); diff --git a/packages/api/src/feature/activity/service/activity.service.ts b/packages/api/src/feature/activity/service/activity.service.ts index 3c9932a04..42ebe32dc 100644 --- a/packages/api/src/feature/activity/service/activity.service.ts +++ b/packages/api/src/feature/activity/service/activity.service.ts @@ -214,14 +214,7 @@ export default class ActivityService { await this.activityRepository.selectDurationByActivityId(row.id); return { ...row, - startTerm: duration.reduce( - (prev, curr) => (prev < curr.startTerm ? prev : curr.startTerm), - duration[0].startTerm, - ), - endTerm: duration.reduce( - (prev, curr) => (prev > curr.endTerm ? prev : curr.endTerm), - duration[0].endTerm, - ), + durations: duration, }; }), ); @@ -231,8 +224,7 @@ export default class ActivityService { activityStatusEnumId: row.activityStatusEnumId, name: row.name, activityTypeEnumId: row.activityTypeEnumId, - startTerm: row.startTerm, - endTerm: row.endTerm, + durations: row.durations, professorApprovedAt: row.professorApprovedAt, })); } diff --git a/packages/interface/src/api/activity/endpoint/apiAct005.ts b/packages/interface/src/api/activity/endpoint/apiAct005.ts index 0a6a5cb1f..a8b28f13f 100644 --- a/packages/interface/src/api/activity/endpoint/apiAct005.ts +++ b/packages/interface/src/api/activity/endpoint/apiAct005.ts @@ -29,8 +29,12 @@ const responseBodyMap = { activityStatusEnumId: z.nativeEnum(ActivityStatusEnum), name: z.string().max(255), activityTypeEnumId: z.nativeEnum(ActivityTypeEnum), - startTerm: z.coerce.date(), - endTerm: z.coerce.date(), + durations: z.array( + z.object({ + startTerm: z.coerce.date(), + endTerm: z.coerce.date(), + }), + ), professorApprovedAt: z.coerce.date().nullable(), }) .array(), diff --git a/packages/interface/src/api/activity/endpoint/apiAct006.ts b/packages/interface/src/api/activity/endpoint/apiAct006.ts index c9d7f17a9..f000cfa7f 100644 --- a/packages/interface/src/api/activity/endpoint/apiAct006.ts +++ b/packages/interface/src/api/activity/endpoint/apiAct006.ts @@ -30,8 +30,12 @@ const responseBodyMap = { id: z.coerce.number().int().min(1), name: z.string().max(255), activityTypeEnumId: z.nativeEnum(ActivityTypeEnum), - startTerm: z.coerce.date(), - endTerm: z.coerce.date(), + durations: z.array( + z.object({ + startTerm: z.coerce.date(), + endTerm: z.coerce.date(), + }), + ), }), ), }), diff --git a/packages/web/src/features/activity-report/_mock/professor.ts b/packages/web/src/features/activity-report/_mock/activityReportList.ts similarity index 99% rename from packages/web/src/features/activity-report/_mock/professor.ts rename to packages/web/src/features/activity-report/_mock/activityReportList.ts index 76d5f1fdf..988802e36 100644 --- a/packages/web/src/features/activity-report/_mock/professor.ts +++ b/packages/web/src/features/activity-report/_mock/activityReportList.ts @@ -5,7 +5,7 @@ import { import { ActivityProfessorApprovalEnum } from "@sparcs-clubs/web/features/manage-club/services/_mock/mockManageClub"; -export const mockProfessorActivityReportData = [ +export const mockActivityReportData = [ { id: 1, name: "2024 가을학기 신입생 프로그래밍 교육", diff --git a/packages/web/src/features/activity-report/components/NewActivityReportList.tsx b/packages/web/src/features/activity-report/components/CurrentActivityReportTable.tsx similarity index 51% rename from packages/web/src/features/activity-report/components/NewActivityReportList.tsx rename to packages/web/src/features/activity-report/components/CurrentActivityReportTable.tsx index 2b9a7d3f2..573267547 100644 --- a/packages/web/src/features/activity-report/components/NewActivityReportList.tsx +++ b/packages/web/src/features/activity-report/components/CurrentActivityReportTable.tsx @@ -7,36 +7,27 @@ import { } from "@tanstack/react-table"; import { useRouter } from "next/navigation"; +import AsyncBoundary from "@sparcs-clubs/web/common/components/AsyncBoundary"; import Table from "@sparcs-clubs/web/common/components/Table"; import Tag from "@sparcs-clubs/web/common/components/Tag"; + import { ActTypeTagList, ApplyTagList, + ProfessorApprovalTagList, } from "@sparcs-clubs/web/constants/tableTagList"; + import { formatDate } from "@sparcs-clubs/web/utils/Date/formatDate"; import { getTagDetail } from "@sparcs-clubs/web/utils/getTagDetail"; -import { type NewActivityReport } from "../types/activityReport"; +import useGetCurrentActivityReportList from "../hooks/useGetCurrentActivityReportList"; +import { ActivityReportTableData } from "../types/table"; -interface ActivityReportListProps { - data?: NewActivityReport[]; +interface CurrentActivityReportTableProps { + clubId: number; } -const columnHelper = createColumnHelper(); -// TODO(ym). 지도교수 승인이 활보 정책 문서 보면 필요없을 것 같지만 혹시 몰라 동연측에 문의 중(결과 확인 후 삭제 예정) -// const getProfessorApprovalTagColor = (professorApproval: string): TagColor => { -// switch (professorApproval) { -// case "대기": -// return "GRAY"; -// case "완료": -// return "GREEN"; -// case "반려": -// return "RED"; -// default: -// return "GRAY"; -// } -// }; - +const columnHelper = createColumnHelper(); const columns = [ columnHelper.accessor("activityStatusEnumId", { header: "상태", @@ -46,17 +37,18 @@ const columns = [ }, size: 0, }), - // TODO(ym). 지도교수 승인이 활보 정책 문서 보면 필요없을 것 같지만 혹시 몰라 동연측에 문의 중(결과 확인 후 삭제 예정) - // columnHelper.accessor("professorApproval", { - // id: "professorApproval", - // header: "지도교수", - // cell: info => ( - // - // {info.getValue()} - // - // ), - // size: 0, - // }), + columnHelper.accessor("professorApproval", { + id: "professorApproval", + header: "지도교수", + cell: info => { + const { color, text } = getTagDetail( + info.getValue(), + ProfessorApprovalTagList, + ); + return {text}; + }, + size: 0, + }), columnHelper.accessor("name", { id: "activity", header: "활동명", @@ -72,7 +64,8 @@ const columns = [ size: 32, }), columnHelper.accessor( - row => `${formatDate(row.startTerm)} ~ ${formatDate(row.endTerm)}`, + row => + `${formatDate(row.durations[0].startTerm)} ~ ${formatDate(row.durations[0].endTerm)}${row.durations.length > 1 ? ` 외 ${row.durations.length - 1}개` : ""}`, { id: "date-range", header: "활동 기간", @@ -82,23 +75,29 @@ const columns = [ ), ]; -const NewActivityReportList: React.FC = ({ - data = [], +const CurrentActivityReportTable: React.FC = ({ + clubId, }) => { const router = useRouter(); + + const { data, isLoading, isError } = useGetCurrentActivityReportList(clubId); + const table = useReactTable({ columns, data, getCoreRowModel: getCoreRowModel(), enableSorting: false, }); + return ( - router.push(`/manage-club/activity-report/${row.id}`)} - /> + +
router.push(`/manage-club/activity-report/${row.id}`)} + /> + ); }; -export default NewActivityReportList; +export default CurrentActivityReportTable; diff --git a/packages/web/src/features/activity-report/components/PastActivityReportList.tsx b/packages/web/src/features/activity-report/components/PastActivityReportTable.tsx similarity index 61% rename from packages/web/src/features/activity-report/components/PastActivityReportList.tsx rename to packages/web/src/features/activity-report/components/PastActivityReportTable.tsx index 0ba9909a6..64337b37c 100644 --- a/packages/web/src/features/activity-report/components/PastActivityReportList.tsx +++ b/packages/web/src/features/activity-report/components/PastActivityReportTable.tsx @@ -1,6 +1,5 @@ import React from "react"; -import { ApiAct006ResponseOk } from "@sparcs-clubs/interface/api/activity/endpoint/apiAct006"; import { createColumnHelper, getCoreRowModel, @@ -16,20 +15,18 @@ import Tag from "@sparcs-clubs/web/common/components/Tag"; import { ActTypeTagList } from "@sparcs-clubs/web/constants/tableTagList"; import { formatDate } from "@sparcs-clubs/web/utils/Date/formatDate"; - import { getTagDetail } from "@sparcs-clubs/web/utils/getTagDetail"; -import useGetPastActivityReportList from "../services/useGetPastActivityReportList"; -import { ActivityTerm } from "../types/activityReport"; +import useGetActivityTerm from "../hooks/useGetActivityTerm"; +import useGetPastActivityReportList from "../hooks/useGetPastActivityReportList"; +import { PastActivityReportTableData } from "../types/table"; -interface ActivityReportListProps { - term: ActivityTerm; +interface PastActivityReportTableProps { + termId: number; clubId: number; } -const columnHelper = - createColumnHelper(); - +const columnHelper = createColumnHelper(); const columns = [ columnHelper.accessor("name", { id: "activity", @@ -46,7 +43,8 @@ const columns = [ size: 32, }), columnHelper.accessor( - row => `${formatDate(row.startTerm)} ~ ${formatDate(row.endTerm)}`, + row => + `${formatDate(row.durations[0].startTerm)} ~ ${formatDate(row.durations[0].endTerm)}${row.durations.length > 1 ? ` 외 ${row.durations.length - 1}개` : ""}`, { id: "date-range", header: "활동 기간", @@ -56,35 +54,39 @@ const columns = [ ), ]; -const PastActivityReportList: React.FC = ({ - term, +const PastActivityReportTable: React.FC = ({ + termId, clubId, }) => { const router = useRouter(); - const { data, isLoading, isError } = useGetPastActivityReportList(term.id, { + + const { data: activityTerm } = useGetActivityTerm(clubId, termId); + const { data, isLoading, isError } = useGetPastActivityReportList( + termId, clubId, - }); + ); + const table = useReactTable({ columns, - data: data?.activities ?? [], + data, getCoreRowModel: getCoreRowModel(), enableSorting: false, }); return ( - - + +
router.push(`/manage-club/activity-report/${row.id}`)} - count={data?.activities.length} + count={data.length} /> - - + + ); }; -export default PastActivityReportList; +export default PastActivityReportTable; diff --git a/packages/web/src/features/activity-report/components/tables/ProfessorActivityReportTable.tsx b/packages/web/src/features/activity-report/components/tables/ProfessorActivityReportTable.tsx index f62eb3cc0..df8f29e07 100644 --- a/packages/web/src/features/activity-report/components/tables/ProfessorActivityReportTable.tsx +++ b/packages/web/src/features/activity-report/components/tables/ProfessorActivityReportTable.tsx @@ -24,8 +24,9 @@ import { } from "@sparcs-clubs/web/constants/tableTagList"; import useGetProfessorActivityReportList from "@sparcs-clubs/web/features/activity-report/hooks/useGetProfessorActivityReportList"; -import useProfessorApproveActivityReport from "@sparcs-clubs/web/features/activity-report/services/useProfessorApproveActivityReport"; -import { ProfessorActivityReportTableData } from "@sparcs-clubs/web/features/activity-report/types/table"; +import usePostProfessorApproveActivityReport from "@sparcs-clubs/web/features/activity-report/services/useProfessorApproveActivityReport"; + +import { ActivityReportTableData } from "@sparcs-clubs/web/features/activity-report/types/table"; import ProfessorApprovalEnum from "@sparcs-clubs/web/types/professorApproval"; @@ -36,7 +37,7 @@ interface ProfessorActivityReportTableProps { clubId: number; } -const columnHelper = createColumnHelper(); +const columnHelper = createColumnHelper(); const columns = [ columnHelper.accessor("activityStatusEnumId", { header: "상태", @@ -87,10 +88,12 @@ const columns = [ const ProfessorActivityReportTable: React.FC< ProfessorActivityReportTableProps > = ({ clubId }) => { + const router = useRouter(); + const { data, isLoading, isError } = useGetProfessorActivityReportList(clubId); - - const { mutate: approveActivityReport } = useProfessorApproveActivityReport(); + const { mutate: approveActivityReport } = + usePostProfessorApproveActivityReport(); const table = useReactTable({ columns, @@ -98,7 +101,6 @@ const ProfessorActivityReportTable: React.FC< getCoreRowModel: getCoreRowModel(), enableSorting: false, }); - const router = useRouter(); const hasActivitiesToApprove = data.some( activity => activity.professorApproval === ProfessorApprovalEnum.Pending, @@ -128,8 +130,6 @@ const ProfessorActivityReportTable: React.FC< )); }; - if (!data) return null; - return ( diff --git a/packages/web/src/features/activity-report/frames/ActivityReportDetailFrame.tsx b/packages/web/src/features/activity-report/frames/ActivityReportDetailFrame.tsx index d18ad0486..3fccd761c 100644 --- a/packages/web/src/features/activity-report/frames/ActivityReportDetailFrame.tsx +++ b/packages/web/src/features/activity-report/frames/ActivityReportDetailFrame.tsx @@ -38,8 +38,8 @@ import { import { getActivityReportProgress } from "../constants/activityReportProgress"; import useGetActivityReportDetail from "../hooks/useGetActivityReportDetail"; +import useProfessorApproveSingleActivityReport from "../hooks/useProfessorApproveSingleActivityReport"; import { useDeleteActivityReport } from "../services/useDeleteActivityReport"; -import useProfessorApproveActivityReport from "../services/useProfessorApproveActivityReport"; interface ActivitySectionProps extends React.PropsWithChildren { label: string; @@ -116,7 +116,8 @@ const ActivityReportDetailFrame: React.FC = ({ const { data, isLoading, isError } = useGetActivityReportDetail(Number(id)); const { mutate: deleteActivityReport } = useDeleteActivityReport(); - const { mutate: approveActivityReport } = useProfessorApproveActivityReport(); + const { mutate: approveActivityReport } = + useProfessorApproveSingleActivityReport(); const isProgressVisible = profile.type === "undergraduate" || profile.type === "executive"; @@ -156,33 +157,26 @@ const ActivityReportDetailFrame: React.FC = ({ }, [deleteActivityReport, id]); const handleProfessorApproval = useCallback(() => { - approveActivityReport( - { - body: { - activities: [{ id: Number(id) }], - }, + approveActivityReport(Number(id), { + onSuccess: () => { + overlay.open(({ isOpen, close }) => ( + + + 활동 보고서 승인이 완료되었습니다. + + + )); }, - { - onSuccess: () => { - overlay.open(({ isOpen, close }) => ( - - - 활동 보고서 승인이 완료되었습니다. - - - )); - }, - onError: () => { - overlay.open(({ isOpen, close }) => ( - - - 활동 보고서 승인에 실패했습니다. - - - )); - }, + onError: () => { + overlay.open(({ isOpen, close }) => ( + + + 활동 보고서 승인에 실패했습니다. + + + )); }, - ); + }); }, [approveActivityReport, id]); if (isError) { @@ -210,7 +204,7 @@ const ActivityReportDetailFrame: React.FC = ({ if (profile.type === "professor") { return (