diff --git a/apps/shelter/src/pages/my/index.tsx b/apps/shelter/src/pages/my/index.tsx index 32a1ca1b..b6198145 100644 --- a/apps/shelter/src/pages/my/index.tsx +++ b/apps/shelter/src/pages/my/index.tsx @@ -67,7 +67,7 @@ function ShelterMy() { }; return ( - + { - // TODO: VolunteerPost delete API 호출 - console.log('[Delete Volunteer] postId:', postId); + deleteShelterRecruitment(postId); }; function VolunteersDetail() { const setOnDelete = useDetailHeaderStore((state) => state.setOnDelete); + const toast = useToast(); useEffect(() => { setOnDelete(handleDeletePost); @@ -40,15 +47,34 @@ function VolunteersDetail() { }, [setOnDelete]); const navigate = useNavigate(); - const { id: recruitmentId } = useParams(); + const { id } = useParams(); + const recruitmentId = Number(id); const { isOpen, onOpen, onClose } = useDisclosure(); - const { data: recruitment } = useGetVolunteerDetail(Number(recruitmentId)); + const { data: recruitment } = useGetVolunteerDetail(recruitmentId); + + const { mutate: closedRecruitment } = useMutation({ + mutationFn: async (recruitmentId: number) => + closeShelterRecruitment(recruitmentId), + onSuccess: () => { + toast({ + position: 'top', + description: '모집마감되었습니다.', + status: 'success', + duration: 1500, + }); + setIsClosed(true); + }, + onError: (error) => { + console.error(error); + }, + }); const startDate = new Date(recruitment.startTime); const deadline = new Date(recruitment.deadline); const createdAt = new Date(recruitment.createdAt); + const volunteerDateDay = getDDay(recruitment.deadline); const volunteerDate = createFormattedTime(startDate); const volunteerDay = createWeekDayLocalString(startDate); @@ -56,26 +82,16 @@ function VolunteersDetail() { const deadlineDate = createFormattedTime(deadline); const deadlineDay = createWeekDayLocalString(deadline); - const [label, setLabel] = useState({ - labelTitle: '모집중', - type: 'GREEN', - }); - const [isClosed, setIsClosed] = useState(false); - - useEffect(() => { - if (recruitment.isClosed) { - setIsClosed(true); - setLabel({ labelTitle: '마감완료', type: 'GRAY' }); - } - }, [recruitment.isClosed]); + const [isClosed, setIsClosed] = useState( + recruitment.isClosed || volunteerDateDay < 0, + ); const goManageApply = () => navigate(`/manage/apply/${recruitmentId}`); const goManageAttendance = () => navigate(`/manage/attendance/${recruitmentId}`); - const onCloseRecruitment = () => { + const onCloseRecruitment = (recruitmentId: number) => { + closedRecruitment(recruitmentId); onClose(); - setIsClosed(true); - setLabel({ labelTitle: '마감완료', type: 'GRAY' }); }; return ( @@ -84,16 +100,20 @@ function VolunteersDetail() { )} - + {isClosed ? ( + @@ -168,7 +188,7 @@ function VolunteersDetail() { btnTitle="마감하기" isOpen={isOpen} onClose={onClose} - onClick={onCloseRecruitment} + onClick={() => onCloseRecruitment(recruitmentId)} /> ); diff --git a/apps/shelter/src/pages/volunteers/update/index.tsx b/apps/shelter/src/pages/volunteers/update/index.tsx index 41802e6e..51e88a35 100644 --- a/apps/shelter/src/pages/volunteers/update/index.tsx +++ b/apps/shelter/src/pages/volunteers/update/index.tsx @@ -13,10 +13,11 @@ import { } from '@chakra-ui/react'; import { zodResolver } from '@hookform/resolvers/zod'; import { useMutation, useQueryClient } from '@tanstack/react-query'; -import { useCallback, useEffect } from 'react'; +import { Suspense, useCallback, useEffect } from 'react'; import { SubmitHandler, useForm } from 'react-hook-form'; import { useNavigate, useParams } from 'react-router-dom'; import EditPhotoList from 'shared/components/EditPhotoList'; +import Loader from 'shared/components/Loader'; import { usePhotosUpload } from 'shared/hooks/usePhotosUpload'; import { getKoreanTime } from 'shared/utils/date'; import * as z from 'zod'; @@ -31,21 +32,26 @@ import useGetVolunteerDetail, { const recruitmentSchema = z .object({ title: z.string().min(1, '제목은 필수로 입력해주세요'), - startTime: z.coerce.date(), - endTime: z.coerce.date(), - deadline: z.coerce.date(), + startTime: z.string(), + endTime: z.string(), + deadline: z.string(), capacity: z.coerce.number(), content: z .string() .optional() .refine((val) => val?.length && val.length < 500, '에러입니다'), }) - .refine(({ startTime, endTime }) => startTime.getTime() < endTime.getTime(), { - message: '봉사 시작 일시 이후로 입력해주세요 ', - path: ['endTime'], - }) .refine( - ({ startTime, deadline }) => deadline.getTime() <= startTime.getTime(), + ({ startTime, endTime }) => + new Date(startTime).getTime() < new Date(endTime).getTime(), + { + message: '봉사 시작 일시 이후로 입력해주세요 ', + path: ['endTime'], + }, + ) + .refine( + ({ startTime, deadline }) => + new Date(deadline).getTime() <= new Date(startTime).getTime(), { message: '봉사 시작 일시 전으로 입력해주세요', path: ['deadLine'], @@ -56,14 +62,11 @@ type RecruitmentSchema = z.infer; const UPLOAD_LIMIT = 5; -export default function VolunteersUpdatePage() { +const UpdateForm = () => { const { id: recruitmentId } = useParams<{ id: string }>() as { id: string }; const navigate = useNavigate(); const queryClient = useQueryClient(); - // TODO 이 훅에서 startDate, endDate와 같은 날짜데이터를 가공하기 때문에 - // 다른 훅을 만들어서 사용해야 할 것 같습니다. - // 혹은 훅 내의 select 옵션을 수정해야 할 것 같습니다. const { data: recruitment, isPending: isRecruitFetchLoading } = useGetVolunteerDetail(Number(recruitmentId)); @@ -111,9 +114,9 @@ export default function VolunteersUpdatePage() { recruitmentId: Number(recruitmentId), request: { ...data, - startTime: getKoreanTime(startTime).toISOString(), - endTime: getKoreanTime(endTime).toISOString(), - deadline: getKoreanTime(deadline).toISOString(), + startTime: getKoreanTime(new Date(startTime)).toISOString(), + endTime: getKoreanTime(new Date(endTime)).toISOString(), + deadline: getKoreanTime(new Date(deadline)).toISOString(), imageUrls: photos .filter(({ url }) => url !== 'upload-failed') .map(({ url }) => url), @@ -124,9 +127,9 @@ export default function VolunteersUpdatePage() { const setVolunteersRecruitmentFormvalues = useCallback( (recruitment: RecruitmentDetail) => { setValue('title', recruitment.title); - setValue('startTime', new Date(recruitment.startTime)); - setValue('endTime', new Date(recruitment.endTime)); - setValue('deadline', new Date(recruitment.deadline)); + setValue('startTime', recruitment.startTime.slice(0, -3)); + setValue('endTime', recruitment.endTime.slice(0, -3)); + setValue('deadline', recruitment.deadline.slice(0, -3)); setValue('capacity', recruitment.capacity); setValue('content', recruitment?.content ?? ''); setImageUrls(recruitment.imageUrls); @@ -233,4 +236,12 @@ export default function VolunteersUpdatePage() { ); +}; + +export default function VolunteersUpdatePage() { + return ( + }> + + + ); }