--- app/(protected)/(basic)/admins/_actions.ts
+++ app/(protected)/(basic)/admins/_actions.ts
... | ... | @@ -9,7 +9,6 @@ |
| 9 | 9 |
isAdminLoginIdTaken, |
| 10 | 10 |
updateAdminMember, |
| 11 | 11 |
} from '@/lib/data/repositories/admin-member-repository'; |
| 12 |
-import { ADMIN_MENU_OPTIONS } from '@/lib/domain/admin-member';
|
|
| 13 | 12 |
import {
|
| 14 | 13 |
formatPhoneNumber, |
| 15 | 14 |
validateAdminLoginId, |
... | ... | @@ -31,15 +30,6 @@ |
| 31 | 30 |
return typeof value === 'string' ? value : ''; |
| 32 | 31 |
} |
| 33 | 32 |
|
| 34 |
-function readMenuCodes(formData: FormData): string[] {
|
|
| 35 |
- return formData |
|
| 36 |
- .getAll('menuCodes')
|
|
| 37 |
- .filter((value): value is string => typeof value === 'string') |
|
| 38 |
- .filter((value) => |
|
| 39 |
- ADMIN_MENU_OPTIONS.some((option) => option.value === value) |
|
| 40 |
- ); |
|
| 41 |
-} |
|
| 42 |
- |
|
| 43 | 33 |
function readEditableValues(formData: FormData): AdminMemberEditableValues {
|
| 44 | 34 |
const phoneNumber = formatPhoneNumber(readString(formData, 'phoneNumber')); |
| 45 | 35 |
|
... | ... | @@ -48,7 +38,6 @@ |
| 48 | 38 |
phoneNumber: phoneNumber ?? '', |
| 49 | 39 |
email: readString(formData, 'email'), |
| 50 | 40 |
roleCode: readString(formData, 'roleCode'), |
| 51 |
- menuCodes: readMenuCodes(formData), |
|
| 52 | 41 |
}; |
| 53 | 42 |
} |
| 54 | 43 |
|
--- app/(protected)/(basic)/admins/_components/admin-member-create-modal.tsx
+++ app/(protected)/(basic)/admins/_components/admin-member-create-modal.tsx
... | ... | @@ -72,7 +72,6 @@ |
| 72 | 72 |
const [emailValue, setEmailValue] = useState(`@${EMAIL_DOMAIN_OPTIONS[0]}`);
|
| 73 | 73 |
const [isEmailTouched, setIsEmailTouched] = useState(false); |
| 74 | 74 |
const [roleCode, setRoleCode] = useState<string>(DEFAULT_ADMIN_ROLE_CODE); |
| 75 |
- const [menuCodes, setMenuCodes] = useState<string[]>([]); |
|
| 76 | 75 |
|
| 77 | 76 |
useEffect(() => {
|
| 78 | 77 |
if (state.status === 'success') {
|
... | ... | @@ -196,8 +195,6 @@ |
| 196 | 195 |
onPhoneNumberChange={setPhoneNumber}
|
| 197 | 196 |
roleCode={roleCode}
|
| 198 | 197 |
onRoleCodeChange={setRoleCode}
|
| 199 |
- menuCodes={menuCodes}
|
|
| 200 |
- onMenuCodesChange={setMenuCodes}
|
|
| 201 | 198 |
errors={errors}
|
| 202 | 199 |
emailField={
|
| 203 | 200 |
<> |
--- app/(protected)/(basic)/admins/_components/admin-member-edit-modal.tsx
+++ app/(protected)/(basic)/admins/_components/admin-member-edit-modal.tsx
... | ... | @@ -49,7 +49,6 @@ |
| 49 | 49 |
const [roleCode, setRoleCode] = useState( |
| 50 | 50 |
member.roleCode || DEFAULT_ADMIN_ROLE_CODE |
| 51 | 51 |
); |
| 52 |
- const [menuCodes, setMenuCodes] = useState<string[]>(member.menuCodes); |
|
| 53 | 52 |
const [isActive, setIsActive] = useState(!(member.isLocked ?? false)); |
| 54 | 53 |
|
| 55 | 54 |
useEffect(() => {
|
... | ... | @@ -135,8 +134,6 @@ |
| 135 | 134 |
onPhoneNumberChange={setPhoneNumber}
|
| 136 | 135 |
roleCode={roleCode}
|
| 137 | 136 |
onRoleCodeChange={setRoleCode}
|
| 138 |
- menuCodes={menuCodes}
|
|
| 139 |
- onMenuCodesChange={setMenuCodes}
|
|
| 140 | 137 |
errors={errors}
|
| 141 | 138 |
emailField={
|
| 142 | 139 |
<FoxInput |
--- app/(protected)/(basic)/admins/_components/admin-member-form-fields.tsx
+++ app/(protected)/(basic)/admins/_components/admin-member-form-fields.tsx
... | ... | @@ -1,15 +1,10 @@ |
| 1 | 1 |
'use client'; |
| 2 | 2 |
|
| 3 | 3 |
import { useId, type ReactNode } from 'react';
|
| 4 |
-import { FoxChip } from '@fox/core/components/fox-chip';
|
|
| 5 |
-import { FoxChipArea } from '@fox/core/components/fox-chip-area';
|
|
| 6 | 4 |
import { FoxFormLabel } from '@fox/core/components/fox-form-label';
|
| 7 | 5 |
import { FoxPhoneNumber } from '@fox/core/components/fox-phone-number';
|
| 8 | 6 |
import { FoxSelect } from '@fox/core/components/fox-select';
|
| 9 |
-import {
|
|
| 10 |
- ADMIN_MENU_OPTIONS, |
|
| 11 |
- ADMIN_ROLE_OPTIONS, |
|
| 12 |
-} from '@/lib/domain/admin-member'; |
|
| 7 |
+import { ADMIN_ROLE_OPTIONS } from '@/lib/domain/admin-member';
|
|
| 13 | 8 |
import type { AdminMemberFormErrors } from '@/lib/domain/admin-member-form';
|
| 14 | 9 |
import { MOBILE_PHONE_PREFIXES } from '@/lib/domain/phone-number';
|
| 15 | 10 |
import styles from './admin-member-modal.module.scss'; |
... | ... | @@ -19,8 +14,6 @@ |
| 19 | 14 |
onPhoneNumberChange: (phoneNumber: string) => void; |
| 20 | 15 |
roleCode: string; |
| 21 | 16 |
onRoleCodeChange: (roleCode: string) => void; |
| 22 |
- menuCodes: string[]; |
|
| 23 |
- onMenuCodesChange: (menuCodes: string[]) => void; |
|
| 24 | 17 |
emailField: ReactNode; |
| 25 | 18 |
errors: AdminMemberFormErrors; |
| 26 | 19 |
} |
... | ... | @@ -30,24 +23,10 @@ |
| 30 | 23 |
onPhoneNumberChange, |
| 31 | 24 |
roleCode, |
| 32 | 25 |
onRoleCodeChange, |
| 33 |
- menuCodes, |
|
| 34 |
- onMenuCodesChange, |
|
| 35 | 26 |
emailField, |
| 36 | 27 |
errors, |
| 37 | 28 |
}: AdminMemberFormFieldsProps) {
|
| 38 | 29 |
const phoneLabelId = useId(); |
| 39 |
- const menuLabelId = useId(); |
|
| 40 |
- |
|
| 41 |
- const allMenuValues = ADMIN_MENU_OPTIONS.map((option) => option.value); |
|
| 42 |
- const isAllSelected = menuCodes.length === allMenuValues.length; |
|
| 43 |
- |
|
| 44 |
- function toggleMenu(value: string) {
|
|
| 45 |
- onMenuCodesChange( |
|
| 46 |
- menuCodes.includes(value) |
|
| 47 |
- ? menuCodes.filter((code) => code !== value) |
|
| 48 |
- : [...menuCodes, value] |
|
| 49 |
- ); |
|
| 50 |
- } |
|
| 51 | 30 |
|
| 52 | 31 |
return ( |
| 53 | 32 |
<> |
... | ... | @@ -81,34 +60,6 @@ |
| 81 | 60 |
hint={errors.roleCode}
|
| 82 | 61 |
/> |
| 83 | 62 |
<input type="hidden" name="roleCode" value={roleCode} />
|
| 84 |
- |
|
| 85 |
- <div className={styles.field} role="group" aria-labelledby={menuLabelId}>
|
|
| 86 |
- <FoxFormLabel as="span" id={menuLabelId} requirement="required">
|
|
| 87 |
- 메뉴 선택 |
|
| 88 |
- </FoxFormLabel> |
|
| 89 |
- <FoxChipArea size="md" wrap labelledBy={menuLabelId}>
|
|
| 90 |
- <FoxChip |
|
| 91 |
- type="check" |
|
| 92 |
- label="전체" |
|
| 93 |
- checked={isAllSelected}
|
|
| 94 |
- onCheckedChange={(checked) =>
|
|
| 95 |
- onMenuCodesChange(checked ? allMenuValues : []) |
|
| 96 |
- } |
|
| 97 |
- /> |
|
| 98 |
- {ADMIN_MENU_OPTIONS.map((option) => (
|
|
| 99 |
- <FoxChip |
|
| 100 |
- key={option.value}
|
|
| 101 |
- type="check" |
|
| 102 |
- label={option.label}
|
|
| 103 |
- checked={menuCodes.includes(option.value)}
|
|
| 104 |
- onCheckedChange={() => toggleMenu(option.value)}
|
|
| 105 |
- /> |
|
| 106 |
- ))} |
|
| 107 |
- </FoxChipArea> |
|
| 108 |
- </div> |
|
| 109 |
- {menuCodes.map((code) => (
|
|
| 110 |
- <input key={code} type="hidden" name="menuCodes" value={code} />
|
|
| 111 |
- ))} |
|
| 112 | 63 |
</> |
| 113 | 64 |
); |
| 114 | 65 |
} |
--- lib/data/repositories/admin-member-repository.ts
+++ lib/data/repositories/admin-member-repository.ts
... | ... | @@ -57,8 +57,6 @@ |
| 57 | 57 |
phoneNumber: readOptionalString(raw, 'admTelNo'), |
| 58 | 58 |
email: readOptionalString(raw, 'admEmlAddr'), |
| 59 | 59 |
roleCode: readOptionalString(raw, 'admRoleCd') ?? '', |
| 60 |
- // 이슈: 백엔드에 관리자별 메뉴 권한이 없어 저장도 조회도 되지 않는다. |
|
| 61 |
- menuCodes: [], |
|
| 62 | 60 |
createdAt: readOptionalString(raw, 'frstRegDtStr'), |
| 63 | 61 |
isLocked: parseYesNo(raw.acctLockYn), |
| 64 | 62 |
isActive: parseYesNo(raw.useYn), |
--- lib/domain/admin-member-form.ts
+++ lib/domain/admin-member-form.ts
... | ... | @@ -6,7 +6,6 @@ |
| 6 | 6 |
type FoxValidator, |
| 7 | 7 |
} from '@fox/core/validation'; |
| 8 | 8 |
import {
|
| 9 |
- ADMIN_MENU_OPTIONS, |
|
| 10 | 9 |
ADMIN_ROLE_OPTIONS, |
| 11 | 10 |
type AdminRoleCode, |
| 12 | 11 |
} from '@/lib/domain/admin-member'; |
... | ... | @@ -66,7 +65,6 @@ |
| 66 | 65 |
phoneNumber: string; |
| 67 | 66 |
email: string; |
| 68 | 67 |
roleCode: AdminRoleCode; |
| 69 |
- menuCodes: string[]; |
|
| 70 | 68 |
}; |
| 71 | 69 |
|
| 72 | 70 |
export type AdminMemberCreateValues = AdminMemberEditableValues & {
|
... | ... | @@ -146,11 +144,7 @@ |
| 146 | 144 |
errors.roleCode = '역할을 선택해 주세요.'; |
| 147 | 145 |
} |
| 148 | 146 |
|
| 149 |
- const menuCodes = values.menuCodes.filter((code) => |
|
| 150 |
- ADMIN_MENU_OPTIONS.some((option) => option.value === code) |
|
| 151 |
- ); |
|
| 152 |
- |
|
| 153 |
- return { password, phoneNumber, email, roleCode: values.roleCode, menuCodes };
|
|
| 147 |
+ return { password, phoneNumber, email, roleCode: values.roleCode };
|
|
| 154 | 148 |
} |
| 155 | 149 |
|
| 156 | 150 |
export function validateAdminMemberCreate( |
--- lib/domain/admin-member.ts
+++ lib/domain/admin-member.ts
... | ... | @@ -29,11 +29,6 @@ |
| 29 | 29 |
email: string | null; |
| 30 | 30 |
/** 백엔드 `admRoleCd`. 표기용 이름은 `formatAdminRoleLabel`이 만든다. */ |
| 31 | 31 |
roleCode: AdminRoleCode; |
| 32 |
- /** |
|
| 33 |
- * 접근 가능 메뉴 코드 목록(시안 ADM_ADM_102_p ③ "메뉴 선택", 다중 선택). |
|
| 34 |
- * 백엔드 목록 응답에 없어 mock으로 등록/수정한 행에만 값이 있다 — 빈 배열은 "미지정"이다. |
|
| 35 |
- */ |
|
| 36 |
- menuCodes: string[]; |
|
| 37 | 32 |
/** ISO 형식(YYYY-MM-DD) 문자열. 백엔드 목록 응답에 없다(정렬에만 쓰이고 select되지 않는다). */ |
| 38 | 33 |
createdAt: string | null; |
| 39 | 34 |
/** 백엔드 `acctLockYn` — 계정 잠김 여부. 시안의 "잠김여부"는 이 값의 반대(활성/비활성)다. */ |
... | ... | @@ -107,35 +102,3 @@ |
| 107 | 102 |
return isLocked ? '비활성' : '활성'; |
| 108 | 103 |
} |
| 109 | 104 |
|
| 110 |
-/** |
|
| 111 |
- * 접근 가능 메뉴 목록(시안 ADM_ADM_102_p ③ "메뉴 선택"). |
|
| 112 |
- * |
|
| 113 |
- * **백엔드에 관리자 메뉴 API가 없어 mock 카탈로그다.** 값은 시안 사이드바의 대메뉴 구성을 그대로 |
|
| 114 |
- * 옮겼다 — 실제 메뉴 API가 생기면 이 상수를 지우고 그 응답으로 대체한다. |
|
| 115 |
- */ |
|
| 116 |
-export const ADMIN_MENU_OPTIONS: ReadonlyArray<{
|
|
| 117 |
- value: string; |
|
| 118 |
- label: string; |
|
| 119 |
-}> = [ |
|
| 120 |
- { value: 'MEMBER', label: '회원정보관리' },
|
|
| 121 |
- { value: 'ADMIN', label: '관리자정보관리' },
|
|
| 122 |
- { value: 'DECO_ITEM', label: '꾸미기아이템관리' },
|
|
| 123 |
- { value: 'BOARD', label: '게시판관리(고객센터)' },
|
|
| 124 |
- { value: 'POINT', label: '포인트관리' },
|
|
| 125 |
- { value: 'CONTENTS', label: '콘텐츠관리' },
|
|
| 126 |
- { value: 'SYSTEM', label: '시스템관리' },
|
|
| 127 |
-]; |
|
| 128 |
- |
|
| 129 |
-/** 선택된 메뉴 코드를 화면 표기로 바꾼다. 하나도 없으면 `-`. */ |
|
| 130 |
-export function formatAdminMenuLabels(menuCodes: string[]): string {
|
|
| 131 |
- if (menuCodes.length === 0) {
|
|
| 132 |
- return EMPTY_FIELD_PLACEHOLDER; |
|
| 133 |
- } |
|
| 134 |
- |
|
| 135 |
- return menuCodes |
|
| 136 |
- .map( |
|
| 137 |
- (code) => |
|
| 138 |
- ADMIN_MENU_OPTIONS.find((option) => option.value === code)?.label ?? code |
|
| 139 |
- ) |
|
| 140 |
- .join(', ');
|
|
| 141 |
-} |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?