File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
'use client';
import { useActionState, useEffect, useRef, useState } from 'react';
import { FoxButton } from '@fox/core/components/fox-button';
import { FoxHelperText } from '@fox/core/components/fox-helper-text';
import { FoxInput } from '@fox/core/components/fox-input';
import { FoxModal } from '@fox/core/components/fox-modal';
import { useFeedback } from '@/app/_hooks/use-feedback';
import { type CommonCodeGroup } from '@/lib/domain/common-code';
import { INITIAL_COMMON_CODE_FORM_STATE } from '@/lib/domain/common-code-form';
import { createCodeGroupAction, updateCodeGroupAction } from '../_actions';
import styles from './code-form.module.scss';
import { submitFormAction } from '@/app/_hooks/submit-form-action';
interface CodeGroupModalProps {
/** 수정 대상. 없으면 등록 팝업이다. */
group?: CommonCodeGroup;
onClose: () => void;
}
/**
* 공통코드 등록/수정 팝업 — 기획 1842:16056 / 1842:16122.
*
* 두 팝업은 제목·버튼 글자와 **코드ID의 읽기 전용 여부**만 다르고 입력 항목이 같아 한 조각으로 둔다.
*
* 저장 버튼은 foot 슬롯에 그려져 폼의 자손이 아니다 — ref로 직접 제출한다(다른 팝업과 같은 방식).
*/
export function CodeGroupModal({ group, onClose }: CodeGroupModalProps) {
const isEdit = group !== undefined;
const { showToast } = useFeedback();
const formRef = useRef<HTMLFormElement>(null);
const [state, formAction, isPending] = useActionState(
isEdit ? updateCodeGroupAction : createCodeGroupAction,
INITIAL_COMMON_CODE_FORM_STATE
);
const [comCd, setComCd] = useState(group?.comCd ?? '');
useEffect(() => {
if (state.status === 'success') {
showToast({
variant: 'success',
message: isEdit ? '공통코드를 수정했습니다.' : '공통코드를 등록했습니다.',
});
onClose();
}
}, [state, showToast, onClose, isEdit]);
const errors = state.status === 'error' ? (state.errors ?? {}) : {};
return (
<FoxModal
open
size="sm"
title={isEdit ? '공통코드 수정' : '공통코드 등록'}
onClose={onClose}
actions={
<>
<FoxButton type="default" size="md" label="취소" onAction={onClose} />
<FoxButton
type="primary"
size="md"
label={isPending ? '저장 중...' : '저장'}
disabled={isPending}
onAction={() => formRef.current?.requestSubmit()}
/>
</>
}
>
<form ref={formRef} onSubmit={(event) => submitFormAction(event, formAction)} className={styles.fields}>
{/* 수정 대상은 읽기 전용 칸이 아니라 이 값으로 정해진다 — 칸이 위조돼도 대상은 안 바뀐다. */}
{isEdit && (
<input type="hidden" name="targetComCd" value={group.comCd} />
)}
<div className={styles.field}>
<FoxInput
size="md"
name={isEdit ? undefined : 'comCd'}
label="코드ID"
requirement="required"
value={comCd}
onChange={setComCd}
readOnly={isEdit}
placeholder="코드ID를 입력하세요."
invalid={Boolean(errors.comCd)}
message={errors.comCd}
maxLength={50}
/>
</div>
<div className={styles.field}>
<FoxInput
size="md"
name="name"
label="코드ID명"
requirement="required"
defaultValue={group?.name ?? ''}
placeholder="코드ID명을 입력하세요."
invalid={Boolean(errors.name)}
message={errors.name}
maxLength={100}
/>
</div>
<div className={styles.field}>
<FoxInput
size="md"
name="description"
label="코드ID설명"
defaultValue={group?.description ?? ''}
placeholder="코드ID설명을 입력하세요."
invalid={Boolean(errors.description)}
message={errors.description}
maxLength={500}
/>
</div>
{state.status === 'error' && state.message && (
<FoxHelperText type="danger" message={state.message} />
)}
</form>
</FoxModal>
);
}