diff --git a/frontend/src/constants/eventName.ts b/frontend/src/constants/eventName.ts index 2becdfb4e..f4de46e73 100644 --- a/frontend/src/constants/eventName.ts +++ b/frontend/src/constants/eventName.ts @@ -45,6 +45,8 @@ export const ADMIN_EVENT = { FORGOT_PASSWORD_BUTTON_CLICKED: '비밀번호 찾기 버튼클릭', // 사이드바 + CLUB_COVER_UPLOAD_BUTTON_CLICKED: '동아리 커버 업로드 버튼클릭', + CLUB_COVER_RESET_BUTTON_CLICKED: '동아리 커버 초기화 버튼클릭', CLUB_LOGO_UPLOAD_BUTTON_CLICKED: '동아리 로고 업로드 버튼클릭', CLUB_LOGO_EDIT_BUTTON_CLICKED: '동아리 로고 수정 버튼클릭', CLUB_LOGO_RESET_BUTTON_CLICKED: '동아리 로고 초기화 버튼클릭', diff --git a/frontend/src/pages/AdminPage/components/ClubCoverEditor/ClubCoverEditor.tsx b/frontend/src/pages/AdminPage/components/ClubCoverEditor/ClubCoverEditor.tsx index 9589f7672..b685bbb68 100644 --- a/frontend/src/pages/AdminPage/components/ClubCoverEditor/ClubCoverEditor.tsx +++ b/frontend/src/pages/AdminPage/components/ClubCoverEditor/ClubCoverEditor.tsx @@ -3,6 +3,10 @@ import defaultCover from '@/assets/images/logos/default_profile_image.svg'; import { ADMIN_EVENT } from '@/constants/eventName'; import { MAX_FILE_SIZE } from '@/constants/uploadLimit'; import { useAdminClubContext } from '@/context/AdminClubContext'; +import { + useDeleteCover, + useUploadCover, +} from '@/hooks/queries/club/cover/useCoverMutation'; import useMixpanelTrack from '@/hooks/useMixpanelTrack'; import * as Styled from './ClubCoverEditor.styles'; @@ -17,12 +21,13 @@ const ClubCoverEditor = ({ coverImage }: ClubCoverEditorProps) => { if (!clubId) return null; - // TODO: useCoverMutation 추가 예정 - // const uploadMutation = useUploadCover(); - // const deleteMutation = useDeleteCover(); + const uploadMutation = useUploadCover(); + const deleteMutation = useDeleteCover(); const isCoverImageEmpty = !coverImage?.trim(); - const displayedCover = isCoverImageEmpty ? defaultCover : coverImage; + const displayedCover: string = isCoverImageEmpty + ? defaultCover + : (coverImage ?? defaultCover); const handleFileSelect = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; @@ -36,9 +41,8 @@ const ClubCoverEditor = ({ coverImage }: ClubCoverEditorProps) => { return; } - trackEvent(ADMIN_EVENT.CLUB_LOGO_UPLOAD_BUTTON_CLICKED); - // TODO: uploadMutation.mutate({ clubId, file }); - console.log('Cover image upload:', file); + trackEvent(ADMIN_EVENT.CLUB_COVER_UPLOAD_BUTTON_CLICKED); + uploadMutation.mutate({ clubId, file }); }; const triggerFileInput = () => { @@ -54,9 +58,8 @@ const ClubCoverEditor = ({ coverImage }: ClubCoverEditorProps) => { if (!window.confirm('정말 커버 이미지를 기본 이미지로 되돌릴까요?')) return; - trackEvent(ADMIN_EVENT.CLUB_LOGO_RESET_BUTTON_CLICKED); - // TODO: deleteMutation.mutate(clubId); - console.log('Cover image delete'); + trackEvent(ADMIN_EVENT.CLUB_COVER_RESET_BUTTON_CLICKED); + deleteMutation.mutate(clubId); }; return ( diff --git a/frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx b/frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx index 15885bf26..bf9b26ad9 100644 --- a/frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx +++ b/frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx @@ -8,8 +8,8 @@ import { SNS_CONFIG } from '@/constants/snsConfig'; import { useUpdateClubDetail } from '@/hooks/queries/club/useUpdateClubDetail'; import useMixpanelTrack from '@/hooks/useMixpanelTrack'; import useTrackPageView from '@/hooks/useTrackPageView'; -import ClubLogoEditor from '@/pages/AdminPage/components/ClubLogoEditor/ClubLogoEditor'; import ClubCoverEditor from '@/pages/AdminPage/components/ClubCoverEditor/ClubCoverEditor'; +import ClubLogoEditor from '@/pages/AdminPage/components/ClubLogoEditor/ClubLogoEditor'; import { ContentSection } from '@/pages/AdminPage/components/ContentSection/ContentSection'; import MakeTags from '@/pages/AdminPage/tabs/ClubInfoEditTab/components/MakeTags/MakeTags'; import SelectTags from '@/pages/AdminPage/tabs/ClubInfoEditTab/components/SelectTags/SelectTags'; @@ -119,7 +119,6 @@ const ClubInfoEditTab = () => { } const updatedData = { - id: clubDetail.id, name: clubName, category: selectedCategory, division: selectedDivision, @@ -128,6 +127,7 @@ const ClubInfoEditTab = () => { presidentName: clubPresidentName, presidentPhoneNumber: telephoneNumber, socialLinks: socialLinks, + description: clubDetail.description, }; updateClub(updatedData, { diff --git a/frontend/src/pages/AdminPage/tabs/ClubIntroTab/ClubIntroTab.tsx b/frontend/src/pages/AdminPage/tabs/ClubIntroTab/ClubIntroTab.tsx index 3ad3eeccb..60274a4d4 100644 --- a/frontend/src/pages/AdminPage/tabs/ClubIntroTab/ClubIntroTab.tsx +++ b/frontend/src/pages/AdminPage/tabs/ClubIntroTab/ClubIntroTab.tsx @@ -8,27 +8,11 @@ import { useUpdateClubDetail } from '@/hooks/queries/club/useUpdateClubDetail'; import useMixpanelTrack from '@/hooks/useMixpanelTrack'; import useTrackPageView from '@/hooks/useTrackPageView'; import { ContentSection } from '@/pages/AdminPage/components/ContentSection/ContentSection'; -import { ClubDetail } from '@/types/club'; +import { Award, ClubDetail, FAQ, IdealCandidate } from '@/types/club'; import * as Styled from './ClubIntroTab.styles'; import AwardEditor from './components/AwardEditor/AwardEditor'; import FAQEditor from './components/FAQEditor/FAQEditor'; -export interface Award { - semester: string; - achievements: string[]; -} - -export interface FAQ { - id: string; - question: string; - answer: string; -} - -export interface IdealCandidate { - tags: string[]; - content: string; -} - const ClubIntroTab = () => { const trackEvent = useMixpanelTrack(); useTrackPageView(PAGE_VIEW.CLUB_INFO_EDIT_PAGE); @@ -49,14 +33,15 @@ const ClubIntroTab = () => { const queryClient = useQueryClient(); useEffect(() => { - if (clubDetail) { - // TODO: API 연동 시 실제 데이터로 대체 - setIntroDescription(''); - setActivityDescription(''); - setAwards([]); - setIdealCandidate({ tags: [], content: '' }); - setBenefits(''); - setFaqs([]); + if (clubDetail?.description) { + setIntroDescription(clubDetail.description.introDescription || ''); + setActivityDescription(clubDetail.description.activityDescription || ''); + setAwards(clubDetail.description.awards || []); + setIdealCandidate( + clubDetail.description.idealCandidate || { tags: [], content: '' }, + ); + setBenefits(clubDetail.description.benefits || ''); + setFaqs(clubDetail.description.faqs || []); } }, [clubDetail]); @@ -69,17 +54,25 @@ const ClubIntroTab = () => { trackEvent(ADMIN_EVENT.UPDATE_CLUB_BUTTON_CLICKED); const updatedData = { - id: clubDetail.id, - introDescription, - activityDescription, - awards, - idealCandidate, - benefits, - faqs, + name: clubDetail.name, + category: clubDetail.category, + division: clubDetail.division, + tags: clubDetail.tags, + introduction: clubDetail.introduction, + presidentName: clubDetail.presidentName, + presidentPhoneNumber: clubDetail.presidentPhoneNumber, + socialLinks: clubDetail.socialLinks, + description: { + introDescription, + activityDescription, + awards, + idealCandidate, + benefits, + faqs, + }, }; - // TODO: API 연동 - updateClub(updatedData as any, { + updateClub(updatedData, { onSuccess: () => { alert('동아리 상세 정보가 성공적으로 수정되었습니다.'); queryClient.invalidateQueries({ diff --git a/frontend/src/types/club.ts b/frontend/src/types/club.ts index d04bdf898..6e41f36ff 100644 --- a/frontend/src/types/club.ts +++ b/frontend/src/types/club.ts @@ -15,15 +15,19 @@ export interface Club { export type SNSPlatform = keyof typeof SNS_CONFIG; export interface ClubDetail extends Club { - description: string; + description: DetailedDescription; + state: string; feeds: string[]; + presidentName: string; presidentPhoneNumber: string; + recruitmentForm: string; recruitmentStart: string | null; recruitmentEnd: string | null; recruitmentTarget: string; + socialLinks: Record; externalApplicationUrl?: string; }