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 { FoxButtonGroup } from '@fox/core/components/fox-button-group';
import { FoxFormLabel } from '@fox/core/components/fox-form-label';
import { FoxInput } from '@fox/core/components/fox-input';
import { FoxModal } from '@fox/core/components/fox-modal';
import { FoxToggleSwitch } from '@fox/core/components/fox-toggle-switch';
import { foxPasswordValidator } from '@fox/core/validation';
import { useFeedback } from '@/app/_hooks/use-feedback';
import { DEFAULT_ADMIN_ROLE_CODE, type AdminMember } from '@/lib/domain/admin-member';
import {
ADMIN_EMAIL_MESSAGES,
ADMIN_PASSWORD_ERROR_TEXT,
ADMIN_PASSWORD_HELP_TEXT,
ADMIN_PASSWORD_POLICY,
INITIAL_ADMIN_MEMBER_FORM_STATE,
adminEmailValidators,
toPhoneDigits,
} from '@/lib/domain/admin-member-form';
import { updateAdminMemberAction } from '../_actions';
import { AdminMemberFormFields } from './admin-member-form-fields';
import styles from './admin-member-modal.module.scss';
import { submitFormAction } from '@/app/_hooks/submit-form-action';
import { DEFAULT_MOBILE_PHONE_PREFIX } from '@/lib/domain/phone-number';
interface AdminMemberEditModalProps {
member: AdminMember;
onClose: () => void;
}
export function AdminMemberEditModal({
member,
onClose,
}: AdminMemberEditModalProps) {
const { showToast } = useFeedback();
const [state, formAction, isPending] = useActionState(
updateAdminMemberAction,
INITIAL_ADMIN_MEMBER_FORM_STATE
);
const formRef = useRef<HTMLFormElement>(null);
const [isPasswordEditable, setIsPasswordEditable] = useState(false);
const [phoneNumber, setPhoneNumber] = useState(
() => toPhoneDigits(member.phoneNumber) || DEFAULT_MOBILE_PHONE_PREFIX
);
const [email, setEmail] = useState(member.email ?? '');
const [roleCode, setRoleCode] = useState(
member.roleCode || DEFAULT_ADMIN_ROLE_CODE
);
const [isActive, setIsActive] = useState(!(member.isLocked ?? false));
useEffect(() => {
if (state.status === 'success') {
showToast({ variant: 'success', message: '관리자 정보를 수정했습니다.' });
onClose();
}
}, [state, showToast, onClose]);
const errors = state.status === 'error' ? (state.errors ?? {}) : {};
return (
<FoxModal
dismissible={false}
open
onClose={onClose}
size="sm"
title="관리자 수정"
actions={
<FoxButtonGroup size="md">
<FoxButton type="default" size="md" label="취소" onAction={onClose} />
<FoxButton
type="primary"
size="md"
label="저장"
loading={isPending}
onAction={() => formRef.current?.requestSubmit()}
/>
</FoxButtonGroup>
}
>
<form ref={formRef} onSubmit={(event) => submitFormAction(event, formAction)} className={styles.formList}>
<input type="hidden" name="id" value={member.id} />
<FoxInput
size="md"
label="이름"
requirement="required"
value={member.name}
readOnly
/>
<FoxInput
size="md"
label="ID"
requirement="required"
value={member.loginId}
readOnly
/>
<div className={styles.fieldWithAction}>
<FoxInput
size="md"
type="password"
name="password"
label="비밀번호"
requirement="required"
placeholder="비밀번호를 입력하세요."
autoComplete="new-password"
disabled={!isPasswordEditable}
message={
errors.password ??
(isPasswordEditable ? ADMIN_PASSWORD_HELP_TEXT : undefined)
}
messageIcon={
isPasswordEditable ? <i className="fox-ico fox-ico-ChatCenteredDots" aria-hidden="true" /> : undefined
}
invalid={Boolean(errors.password)}
validators={[foxPasswordValidator(ADMIN_PASSWORD_POLICY)]}
validationMessages={{ minlength: ADMIN_PASSWORD_ERROR_TEXT }}
/>
<FoxButton
type="secondary"
size="md"
fullWidth
label="비밀번호 변경"
disabled={isPasswordEditable}
onAction={() => setIsPasswordEditable(true)}
/>
</div>
<AdminMemberFormFields
phoneNumber={phoneNumber}
onPhoneNumberChange={setPhoneNumber}
roleCode={roleCode}
onRoleCodeChange={setRoleCode}
errors={errors}
emailField={
<FoxInput
size="md"
type="email"
name="email"
label="이메일"
placeholder="이메일을 입력하세요."
value={email}
onChange={setEmail}
message={errors.email}
invalid={Boolean(errors.email)}
validators={adminEmailValidators(false)}
validationMessages={ADMIN_EMAIL_MESSAGES}
/>
}
/>
<div className={styles.field}>
<FoxFormLabel as="span">잠김여부</FoxFormLabel>
<FoxToggleSwitch
size="md"
label={isActive ? '활성' : '비활성'}
checked={isActive}
onChange={setIsActive}
/>
</div>
<input type="hidden" name="isLocked" value={String(!isActive)} />
{state.status === 'error' && state.message && (
<p role="alert">{state.message}</p>
)}
</form>
</FoxModal>
);
}