File name
Commit message
Commit date
File name
Commit message
Commit date
09-16
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>
);
}