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 { FoxSelect } from '@fox/core/components/fox-select';
import { useFeedback } from '@/app/_hooks/use-feedback';
import {
CODE_ID_PREFIXES,
DEFAULT_CODE_ID_PREFIX,
applyCodeIdPrefix,
readCodeIdPrefix,
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의 읽기 전용 여부**만 다르고 입력 항목이 같아 한 조각으로 둔다.
*
* **분류코드는 저장되지 않는다.** `TB_SYS_COM_CD`에 해당 컬럼이 없어(확인함) 이 셀렉트는 코드ID
* 접두사를 채워 주는 입력 보조로만 동작한다 — 시안 목록이 전부 `CMS004`처럼 접두사 3자 + 일련번호라
* 그 작명 규칙을 화면이 거드는 것이다(사용자 확정 사항). 저장되는 값은 코드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 ?? '');
const [prefix, setPrefix] = useState(
group ? readCodeIdPrefix(group.comCd) : DEFAULT_CODE_ID_PREFIX
);
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>
{!isEdit && (
<div className={styles.field}>
<FoxSelect
size="md"
label="분류코드"
options={CODE_ID_PREFIXES.map((value) => ({
value,
label: value,
}))}
value={prefix}
onValueChange={(next) => {
setPrefix(next);
setComCd((current) => applyCodeIdPrefix(current, next));
}}
hint="코드ID 앞에 붙는 분류입니다. 별도로 저장되지 않습니다."
/>
</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>
);
}