'use client'; import { useActionState, useEffect, useRef, useState } from 'react'; import { FoxButton } from '@fox/core/components/fox-button'; import { FoxFormLabel } from '@fox/core/components/fox-form-label'; 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 { FoxRadio } from '@fox/core/components/fox-radio'; import { FoxRadioGroup } from '@fox/core/components/fox-radio-group'; import { FoxSelect } from '@fox/core/components/fox-select'; import { submitFormAction } from '@/app/_hooks/submit-form-action'; import { useFeedback } from '@/app/_hooks/use-feedback'; import { MERCHANT_CATEGORY_OPTIONS, type Merchant, } from '@/lib/domain/merchant'; import { ADDRESS_DETAIL_MAX_LENGTH, INITIAL_MERCHANT_FORM_STATE, NAME_MAX_LENGTH, OWNER_MAX_LENGTH, } from '@/lib/domain/merchant-form'; import { saveMerchantAction } from '../_actions'; import styles from './merchant-form.module.scss'; interface MerchantFormModalProps { merchant?: Merchant; onClose: () => void; } export function MerchantFormModal({ merchant, onClose }: MerchantFormModalProps) { const isEdit = Boolean(merchant); const { showToast } = useFeedback(); const formRef = useRef(null); const [state, formAction, isPending] = useActionState( saveMerchantAction, INITIAL_MERCHANT_FORM_STATE ); const [categoryCode, setCategoryCode] = useState(merchant?.categoryCode ?? ''); const [isVisible, setIsVisible] = useState(merchant?.isVisible ?? true); // 주소·좌표는 검색 결과가 채운다(기획 ③ Read Only). const [address, setAddress] = useState(merchant?.address ?? ''); const [postalCode, setPostalCode] = useState(merchant?.postalCode ?? ''); const [latitude, setLatitude] = useState(merchant?.latitude ?? ''); const [longitude, setLongitude] = useState(merchant?.longitude ?? ''); useEffect(() => { if (state.status === 'success') { showToast({ variant: 'success', message: isEdit ? '가맹점을 수정했습니다.' : '가맹점을 등록했습니다.', }); onClose(); } }, [state, showToast, onClose, isEdit]); const errors = state.status === 'error' ? (state.errors ?? {}) : {}; // TODO(기획): 주소 검색 서비스가 정해지지 않았다. 연동 전까지 직접 입력으로 받는다. function searchAddress() { const picked = window.prompt('주소를 입력하세요.', address); if (picked === null) { return; } setAddress(picked.trim()); setPostalCode(''); setLatitude(''); setLongitude(''); } return ( formRef.current?.requestSubmit()} /> } >
submitFormAction(event, formAction)} className={styles.fields} > {/* 등록 시에는 코드가 아직 없다 — 저장할 때 서버가 만든다. */} {isEdit && (
)}
({ value: option.value, label: option.label, }))} value={categoryCode} onValueChange={setCategoryCode} placeholder="선택" error={Boolean(errors.categoryCode)} hint={errors.categoryCode} />
주소
{errors.address && ( )}
위도 / 경도
사용여부 setIsVisible(true)} /> setIsVisible(false)} />
{state.status === 'error' && state.message && ( )}
); }