diff --git a/src/components/org/OrgAdmin/AboutSection/api.ts b/src/components/org/OrgAdmin/AboutSection/api.ts index 0e001c97..16e82966 100644 --- a/src/components/org/OrgAdmin/AboutSection/api.ts +++ b/src/components/org/OrgAdmin/AboutSection/api.ts @@ -5,7 +5,10 @@ import type { AddAdminActivityScheduleRequestDto, AddAdminMemberRequestDto, } from '@/__generated__/org-types/data-contracts'; -import { uploadToS3 } from '@/components/org/OrgAdmin/HomeSection/api'; +import { + extractFileNameFromUrl, + uploadToS3, +} from '@/components/org/OrgAdmin/HomeSection/api'; import { ACTIVITY_GENERATION } from '@/utils/generation'; import { soptFetcher } from '../api'; @@ -51,25 +54,36 @@ type MemberInput = AddAdminMemberRequestDto & { export const buildCoreValuesFromForm = ( values: FieldValues, + existingCoreValues?: { image?: string }[], ): CoreValueInput[] => [1, 2, 3].map((index) => { const coreValue = values[`coreValue${index}`] ?? {}; const imageFileName = coreValue.imageFileName as ImageField; + const existingImage = existingCoreValues?.[index - 1]?.image; return { value: coreValue.value ?? '', description: coreValue.description ?? '', detailDescription: coreValue.detailDescription ?? '', - imageFileName: imageFileName?.fileName, + // 이미지를 새로 올리지 않았다면(=폼 값이 비어있으면) 기존 이미지 URL에서 파일명을 재사용한다. + imageFileName: + imageFileName?.fileName ?? + (existingImage ? extractFileNameFromUrl(existingImage) : undefined), file: imageFileName?.file, }; }); -export const buildMembersFromForm = (values: FieldValues): MemberInput[] => +export const buildMembersFromForm = ( + values: FieldValues, + existingMembers?: { role: string; profileImage?: string }[], +): MemberInput[] => EXEC_ROLE_LIST.map((role) => { const member = values.member?.[role]; const apiRole = toMemberRole(role); const profileImageFileName = member?.profileImageFileName as ImageField; + const existingImage = existingMembers?.find( + (item) => item.role === apiRole, + )?.profileImage; return { role: apiRole, @@ -82,7 +96,9 @@ export const buildMembersFromForm = (values: FieldValues): MemberInput[] => github: member?.sns?.github ?? '', behance: member?.sns?.behance ?? '', }, - profileImageFileName: profileImageFileName?.fileName, + profileImageFileName: + profileImageFileName?.fileName ?? + (existingImage ? extractFileNameFromUrl(existingImage) : undefined), file: profileImageFileName?.file, }; // 이름이 없으면 실존 인물이 아니라 빈 슬롯이다(이미지만 우연히 붙어도 마찬가지). @@ -184,14 +200,28 @@ export const deployAboutTab = async ({ return postAboutTabConfirm(); }; -export const deployAboutTabFromForm = async (values: FieldValues) => { +export type ExistingAboutData = { + headerImage?: string; + coreValue?: { image?: string }[]; + member?: { role: string; profileImage?: string }[]; +}; + +export const deployAboutTabFromForm = async ( + values: FieldValues, + existingData?: ExistingAboutData, +) => { const headerImageFileName = values.headerImageFileName as ImageField; + const existingHeaderImage = existingData?.headerImage; return deployAboutTab({ - headerImageFileName: headerImageFileName?.fileName, + headerImageFileName: + headerImageFileName?.fileName ?? + (existingHeaderImage + ? extractFileNameFromUrl(existingHeaderImage) + : undefined), headerImageFile: headerImageFileName?.file, - coreValues: buildCoreValuesFromForm(values), - members: buildMembersFromForm(values), + coreValues: buildCoreValuesFromForm(values, existingData?.coreValue), + members: buildMembersFromForm(values, existingData?.member), activitySchedule: buildActivityScheduleFromForm(values), }); }; diff --git a/src/components/org/OrgAdmin/AboutSection/index.tsx b/src/components/org/OrgAdmin/AboutSection/index.tsx index 8c7d5b4c..380e14f1 100644 --- a/src/components/org/OrgAdmin/AboutSection/index.tsx +++ b/src/components/org/OrgAdmin/AboutSection/index.tsx @@ -66,7 +66,14 @@ const AboutSectionContent = ({ const handleDeploy = () => { deployAbout( - { values: getValues() }, + { + values: getValues(), + existingData: { + headerImage: data?.headerImage, + coreValue: data?.coreValue, + member: data?.member, + }, + }, { onSuccess: () => setEditStep(EDIT_STEP.VIEW), }, diff --git a/src/components/org/OrgAdmin/AboutSection/queries.ts b/src/components/org/OrgAdmin/AboutSection/queries.ts index f517eb89..216b5238 100644 --- a/src/components/org/OrgAdmin/AboutSection/queries.ts +++ b/src/components/org/OrgAdmin/AboutSection/queries.ts @@ -4,10 +4,11 @@ import { useMutation, useQueryClient } from 'react-query'; import { DEPLOY_TOAST_OPTION } from '@/components/org/OrgAdmin/HomeSection/_constants/constants'; -import { deployAboutTabFromForm } from './api'; +import { deployAboutTabFromForm, type ExistingAboutData } from './api'; type DeployAboutTabFromFormInput = { values: FieldValues; + existingData?: ExistingAboutData; }; export const useDeployAboutMutation = () => { @@ -15,8 +16,8 @@ export const useDeployAboutMutation = () => { const { open } = useToast(); return useMutation({ - mutationFn: ({ values }: DeployAboutTabFromFormInput) => - deployAboutTabFromForm(values), + mutationFn: ({ values, existingData }: DeployAboutTabFromFormInput) => + deployAboutTabFromForm(values, existingData), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['admin'] }); open(DEPLOY_TOAST_OPTION.success);