Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/components/org/OrgAdmin/AboutSection/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ import Schedule from './Schedule';
interface AboutSectionProps {
selectedExec: EXEC_TYPE;
onChangeSelectedExec: (member: EXEC_TYPE) => void;
onEditModeChange: (isEditing: boolean) => void;
}

const AboutSectionContent = ({
selectedExec,
onChangeSelectedExec,
onEditModeChange,
}: AboutSectionProps) => {
const [editStep, setEditStep] = useState<EditStep>(EDIT_STEP.VIEW);

Expand All @@ -39,6 +41,7 @@ const AboutSectionContent = ({
getValues,
setValue,
setError,
setFocus,
clearErrors,
formState: { isDirty },
} = useFormContext();
Expand All @@ -47,6 +50,10 @@ const AboutSectionContent = ({
const isDeployModalOpen = editStep === EDIT_STEP.DEPLOY;
const hasUnsavedChanges = isEditMode && isDirty;

useEffect(() => {
onEditModeChange(isEditMode);
}, [isEditMode, onEditModeChange]);

useEffect(() => {
syncAboutFormFromAdminData(data, setValue);
}, [data, setValue]);
Expand Down Expand Up @@ -79,6 +86,8 @@ const AboutSectionContent = ({
validationAboutInputs(
getValues,
setError,
setFocus,
onChangeSelectedExec,
data?.headerImage,
data?.coreValue,
data?.member,
Expand Down
17 changes: 14 additions & 3 deletions src/components/org/OrgAdmin/CommonSection/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import RecruitSchedule from './RecruitSchedule';
interface CommonSectionProps {
group: Group;
onChangeGroup: (group: Group) => void;
onEditModeChange: (isEditing: boolean) => void;
}

const COMMON_FIELD_NAMES = [
Expand All @@ -31,15 +32,19 @@ const COMMON_FIELD_NAMES = [
'brandingColor',
];

const CommonSectionContent = ({ group, onChangeGroup }: CommonSectionProps) => {
const CommonSectionContent = ({
group,
onChangeGroup,
onEditModeChange,
}: CommonSectionProps) => {
const [editStep, setEditStep] = useState<EditStep>(EDIT_STEP.VIEW);
const [snapshot, setSnapshot] = useState<unknown[] | null>(null);

const { data } = useAdminInfoQuery();
const { mutate: deployCommon, isLoading: isDeploying } =
useDeployCommonMutation();

const { control, getValues, setValue, setError, clearErrors } =
const { control, getValues, setValue, setError, setFocus, clearErrors } =
useFormContext();

const watchedValues = useWatch({ control, name: COMMON_FIELD_NAMES });
Expand All @@ -51,6 +56,10 @@ const CommonSectionContent = ({ group, onChangeGroup }: CommonSectionProps) => {
snapshot !== null &&
JSON.stringify(watchedValues) !== JSON.stringify(snapshot);

useEffect(() => {
onEditModeChange(isEditMode);
}, [isEditMode, onEditModeChange]);

useEffect(() => {
syncCommonFormFromAdminData(data, setValue);
}, [data, setValue]);
Expand Down Expand Up @@ -95,7 +104,9 @@ const CommonSectionContent = ({ group, onChangeGroup }: CommonSectionProps) => {
onStartEdit={startEditMode}
onCancel={cancelEditMode}
onDeploy={() => {
if (validationCommonInputs(getValues, setError, onChangeGroup)) {
if (
validationCommonInputs(getValues, setError, setFocus, onChangeGroup)
) {
setEditStep(EDIT_STEP.DEPLOY);
}
}}
Expand Down
24 changes: 17 additions & 7 deletions src/components/org/OrgAdmin/HomeSection/HomeSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ type HomeDraft = {
const EMPTY_REVIEWS: Review[] = [];
const EMPTY_NEWS: News[] = [];

const HomeSectionContent = () => {
interface HomeSectionProps {
onEditModeChange: (isEditing: boolean) => void;
}

const HomeSectionContent = ({ onEditModeChange }: HomeSectionProps) => {
const [editStep, setEditStep] = useState<EditStep>(EDIT_STEP.VIEW);
const [draft, setDraft] = useState<HomeDraft>({
reviews: EMPTY_REVIEWS,
Expand All @@ -48,7 +52,7 @@ const HomeSectionContent = () => {

const initialReviews = reviewsData ?? EMPTY_REVIEWS;
const latestNews = data?.latestNews ?? EMPTY_NEWS;
const { control, getValues, setError, setValue, clearErrors } =
const { control, getValues, setError, setFocus, setValue, clearErrors } =
useFormContext();
const homeHeaderImage = useWatch({
control,
Expand All @@ -73,9 +77,14 @@ const HomeSectionContent = () => {
};

const hasUnsavedChanges =
Boolean(homeHeaderImage?.file) ||
!isSameOrder(initialReviews, draft.reviews) ||
!isSameOrder(latestNews, draft.news);
isEditMode &&
(Boolean(homeHeaderImage?.file) ||
!isSameOrder(initialReviews, draft.reviews) ||
!isSameOrder(latestNews, draft.news));

useEffect(() => {
onEditModeChange(isEditMode);
}, [isEditMode, onEditModeChange]);

const validateHomeInputs = () => {
const { homeHeaderImageFileName } = getValues();
Expand All @@ -85,6 +94,7 @@ const HomeSectionContent = () => {
type: 'required',
message: VALIDATION_CHECK.required.errorText,
});
setFocus('homeHeaderImageFileName');
return false;
}

Expand Down Expand Up @@ -162,11 +172,11 @@ const HomeSectionContent = () => {
);
};

const HomeSection = () => {
const HomeSection = (props: HomeSectionProps) => {
return (
<StContainer>
<ToastProvider>
<HomeSectionContent />
<HomeSectionContent {...props} />
</ToastProvider>
</StContainer>
);
Expand Down
42 changes: 26 additions & 16 deletions src/components/org/OrgAdmin/MyDropzone/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import { type MouseEvent, useCallback } from 'react';
import { type MouseEvent, type MutableRefObject, useCallback } from 'react';
import { useDropzone } from 'react-dropzone';
import { type UseFormReturn, useWatch } from 'react-hook-form';

Expand Down Expand Up @@ -78,7 +78,7 @@ const MyDropzone = ({
e.preventDefault();
};

const { getRootProps, getInputProps, isDragActive } = useDropzone({
const { getRootProps, getInputProps, inputRef, isDragActive } = useDropzone({
onDrop,
disabled,
accept: {
Expand All @@ -87,6 +87,27 @@ const MyDropzone = ({
'image/png': [],
},
});
const { ref: formRef, ...formInputProps } = register(label, {
validate: (value) => {
if (!required) {
return true;
}

if (value?.fileName || defaultPreviewUrl) {
return true;
}

return VALIDATION_CHECK.required.errorText;
},
});
const dropzoneInputProps = getInputProps();
const setInputRef = useCallback(
(element: HTMLInputElement | null) => {
formRef(element);
(inputRef as MutableRefObject<HTMLInputElement | null>).current = element;
},
[formRef, inputRef],
);

return (
<StImgButtonWrapper>
Expand All @@ -100,20 +121,9 @@ const MyDropzone = ({
isError={errorMsg}
isDisabled={disabled}>
<input
{...register(label, {
validate: (value) => {
if (!required) {
return true;
}

if (value?.fileName || defaultPreviewUrl) {
return true;
}

return VALIDATION_CHECK.required.errorText;
},
})}
{...getInputProps()}
{...formInputProps}
{...dropzoneInputProps}
ref={setInputRef}
disabled={disabled}
/>
{previewUrl ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useFormContext } from 'react-hook-form';

import Modal from '@/components/org/OrgAdmin/common/Modal';
import useModal from '@/components/org/OrgAdmin/common/Modal/useModal';
import { CURRICULUM_WEEK_COUNT } from '@/components/org/OrgAdmin/RecruitSection/_constants/constants';
import { PART_KO, PART_LIST, VALIDATION_CHECK } from '@/utils/org';

import { StInput, StTitle, StWrapper } from '../../../AboutSection/style';
Expand All @@ -17,7 +18,7 @@ import { StItem, StList, StWeek } from './style';

const CURRICULUM = PART_LIST.reduce(
(acc, part) => {
acc[part] = Array.from({ length: 8 });
acc[part] = Array.from({ length: CURRICULUM_WEEK_COUNT });
return acc;
},
{} as Record<string, string[]>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ const PartIntroSection = ({
};

const contentRegister = register(contentFieldName);
const oneLineRegister = register(oneLineFieldName);
const preferenceRegister = register(preferenceFieldName);

return (
<StSectionWrapper>
Expand Down Expand Up @@ -212,6 +214,7 @@ const PartIntroSection = ({

<StTextAreaContainer ref={textAreaContainerRef}>
<TextArea
{...oneLineRegister}
topAddon={{
labelText: '파트 한줄 소개',
descriptionText:
Expand Down Expand Up @@ -260,6 +263,7 @@ const PartIntroSection = ({
{preferenceItems.map((item, index) => (
<StPreferenceItem key={index}>
<StPartIntroductionTextArea
ref={index === 0 ? preferenceRegister.ref : undefined}
topAddon={
index === 0
? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ export const ERROR_MESSAGES = {

export const PREFERENCE_DEFAULT_COUNT = 3;
export const PREFERENCE_MAX_COUNT = 10;
export const CURRICULUM_WEEK_COUNT = 8;
export const ONE_LINE_MAX_LENGTH = 50;
export const ONE_LINE_MAX_LENGTH_ERROR_MESSAGE = '50자 이내로 입력해 주세요.';
34 changes: 13 additions & 21 deletions src/components/org/OrgAdmin/RecruitSection/api.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
import type { FieldValues } from 'react-hook-form';

import type { AddAdminRecruitRequestDto } from '@/__generated__/org-types/data-contracts';
import {
extractFileNameFromUrl,
uploadToS3,
} from '@/components/org/OrgAdmin/HomeSection/api';
import { uploadToS3 } from '@/components/org/OrgAdmin/HomeSection/api';
import { CURRICULUM_WEEK_COUNT } from '@/components/org/OrgAdmin/RecruitSection/_constants/constants';
import { ACTIVITY_GENERATION } from '@/utils/generation';
import { FAQ_MAX_QUESTION_COUNT, PART_LIST } from '@/utils/org';

import { soptFetcher } from '../api';

const CURRICULUM_WEEK_COUNT = 8;

type RecruitHeaderImageField = {
fileName?: string;
file?: File;
Expand Down Expand Up @@ -42,7 +38,7 @@ export const postRecruitTabConfirm = async () => {
};

export type DeployRecruitInput = {
recruitHeaderImageFileName: string;
recruitHeaderImageFileName?: string;
recruitHeaderImageFile?: File;
partIntroduction: AddAdminRecruitRequestDto['partIntroduction'];
partCurriculum: AddAdminRecruitRequestDto['partCurriculum'];
Expand Down Expand Up @@ -88,12 +84,13 @@ export const buildDeployRecruitInputFromForm = (

export const resolveRecruitHeaderImageFileName = (
recruitHeaderImage: RecruitHeaderImageField | undefined,
existingRecruitHeaderImageUrl?: string,
) =>
recruitHeaderImage?.fileName ??
(existingRecruitHeaderImageUrl
? extractFileNameFromUrl(existingRecruitHeaderImageUrl)
: '');
) => {
const { file, fileName } = recruitHeaderImage ?? {};

if (!file || !fileName) return undefined;

return `${file.lastModified}-${file.size}-${fileName}`;
};

export const deployRecruitTab = async ({
recruitHeaderImageFileName,
Expand Down Expand Up @@ -126,19 +123,14 @@ export const deployRecruitTab = async ({
return postRecruitTabConfirm();
};

export const deployRecruitTabFromForm = async (
values: FieldValues,
existingRecruitHeaderImageUrl?: string,
) => {
export const deployRecruitTabFromForm = async (values: FieldValues) => {
const recruitHeaderImage = values.recruitHeaderImage as
| RecruitHeaderImageField
| undefined;

return deployRecruitTab({
recruitHeaderImageFileName: resolveRecruitHeaderImageFileName(
recruitHeaderImage,
existingRecruitHeaderImageUrl,
),
recruitHeaderImageFileName:
resolveRecruitHeaderImageFileName(recruitHeaderImage),
recruitHeaderImageFile: recruitHeaderImage?.file,
...buildDeployRecruitInputFromForm(values),
});
Expand Down
Loading