메뉴별 권한 관리 기능 개선
- defaultGrant 값에 따른 권한 항목 조건부 표시 구현 - 권한 상태 관리 로직 개선 (초기값과 기본값 분리) - API 응답 구조 타입 수정 및 처리 로직 개선 - 거래취소 비밀번호 변경 페이지 오타 수정 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -13,7 +13,7 @@ export const UserAccountAuthWrap = ({
|
|||||||
}: UserAccountAuthWrapProps) => {
|
}: UserAccountAuthWrapProps) => {
|
||||||
const [currentStatus, setCurrentStatus] = useState(status);
|
const [currentStatus, setCurrentStatus] = useState(status);
|
||||||
const [currentIdCL, setCurrentIdCl] = useState(idCL);
|
const [currentIdCL, setCurrentIdCl] = useState(idCL);
|
||||||
const [menuGrants, setMenuGrants] = useState<Array<UserMenuPermissionData>>([]);
|
const [permissions, setPermissions] = useState<Array<UserMenuPermissionData>>([]);
|
||||||
const [hasChanges, setHasChanges] = useState(false);
|
const [hasChanges, setHasChanges] = useState(false);
|
||||||
console.log('mid : ', mid);
|
console.log('mid : ', mid);
|
||||||
console.log('usrid : ', usrid);
|
console.log('usrid : ', usrid);
|
||||||
@@ -24,20 +24,21 @@ export const UserAccountAuthWrap = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (mid && usrid) {
|
if (mid && usrid) {
|
||||||
console.log('userMenuPermissions');
|
console.log('userMenuPermissions');
|
||||||
userMenuPermissions({mid: mid, usrid: usrid}).then((res) => {
|
userMenuPermissions({mid: mid, usrid: usrid}).then((res: any) => {
|
||||||
console.log('res : ', res);
|
console.log('res : ', res);
|
||||||
setMenuGrants(res?.data || res || []);
|
console.log('permissions : ', res?.permissions);
|
||||||
|
setPermissions(res?.permissions || []);
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
console.error('Failed to fetch menu permissions:', error);
|
console.error('Failed to fetch menu permissions:', error);
|
||||||
setMenuGrants([]);
|
setPermissions([]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [mid, usrid]);
|
}, [mid, usrid]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('menuGrants : ', menuGrants);
|
console.log('permissions : ', permissions);
|
||||||
}, [menuGrants]);
|
}, [permissions]);
|
||||||
|
|
||||||
// 변경 사항 감지
|
// 변경 사항 감지
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -139,7 +140,7 @@ export const UserAccountAuthWrap = ({
|
|||||||
idCL={ currentIdCL }
|
idCL={ currentIdCL }
|
||||||
status={ currentStatus }
|
status={ currentStatus }
|
||||||
menuItems={ menuItems }
|
menuItems={ menuItems }
|
||||||
menuGrants={ menuGrants }
|
menuGrants={ permissions }
|
||||||
></UserAccountAuthPermList>
|
></UserAccountAuthPermList>
|
||||||
|
|
||||||
<div className="apply-row bottom-padding">
|
<div className="apply-row bottom-padding">
|
||||||
|
|||||||
@@ -110,8 +110,7 @@ export interface UserMenuPermissionsParams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface UserMenuPermissionsResponse {
|
export interface UserMenuPermissionsResponse {
|
||||||
status: boolean;
|
permissions: Array<UserMenuPermissionData>;
|
||||||
data: Array<UserMenuPermissionData>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UserMenuPermissionsSaveParams {
|
export interface UserMenuPermissionsSaveParams {
|
||||||
@@ -129,6 +128,7 @@ export interface UserMenuPermissionData {
|
|||||||
menuId: number;
|
menuId: number;
|
||||||
usrid: string;
|
usrid: string;
|
||||||
grant: number;
|
grant: number;
|
||||||
|
defaultGrant: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ChangePasswordParams {
|
export interface ChangePasswordParams {
|
||||||
|
|||||||
@@ -14,14 +14,14 @@ import { snackBar } from '@/shared/lib/toast';
|
|||||||
export const PasswordModifyCancelPasswordPage = () => {
|
export const PasswordModifyCancelPasswordPage = () => {
|
||||||
const { navigate } = useNavigate();
|
const { navigate } = useNavigate();
|
||||||
const [mid, setMid] = useState<string>('nictest00m');
|
const [mid, setMid] = useState<string>('nictest00m');
|
||||||
const [newPassword, setNewPassword] = useState<string>('');
|
const [password, setPassword] = useState<string>('');
|
||||||
const [confirmPassword, setConfirmPassword] = useState<string>('');
|
const [confirmPassword, setConfirmPassword] = useState<string>('');
|
||||||
|
|
||||||
const changeCancelPasswordMutation = useUserChangeCancelPasswordMutation({
|
const changeCancelPasswordMutation = useUserChangeCancelPasswordMutation({
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
snackBar('비밀번호가 성공적으로 변경되었습니다.');
|
snackBar('비밀번호가 성공적으로 변경되었습니다.');
|
||||||
// Clear form
|
// Clear form
|
||||||
setNewPassword('');
|
setPassword('');
|
||||||
setConfirmPassword('');
|
setConfirmPassword('');
|
||||||
// Navigate back
|
// Navigate back
|
||||||
navigate(PATHS.account.password.manage);
|
navigate(PATHS.account.password.manage);
|
||||||
@@ -32,6 +32,7 @@ export const PasswordModifyCancelPasswordPage = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const midList = [
|
const midList = [
|
||||||
|
{ value: 'nictest00', label: 'nictest00' },
|
||||||
{ value: 'nictest00m', label: 'nictest00m' },
|
{ value: 'nictest00m', label: 'nictest00m' },
|
||||||
{ value: 'nictest01m', label: 'nictest01m' },
|
{ value: 'nictest01m', label: 'nictest01m' },
|
||||||
{ value: 'nictest02m', label: 'nictest02m' },
|
{ value: 'nictest02m', label: 'nictest02m' },
|
||||||
@@ -47,9 +48,9 @@ export const PasswordModifyCancelPasswordPage = () => {
|
|||||||
// 저장 버튼 활성화 조건 체크
|
// 저장 버튼 활성화 조건 체크
|
||||||
const isFormValid = () => {
|
const isFormValid = () => {
|
||||||
return (
|
return (
|
||||||
newPassword.length >= 8 &&
|
password.length >= 8 &&
|
||||||
confirmPassword.length >= 8 &&
|
confirmPassword.length >= 8 &&
|
||||||
newPassword === confirmPassword
|
password === confirmPassword
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -60,7 +61,7 @@ export const PasswordModifyCancelPasswordPage = () => {
|
|||||||
// TODO: Validate current password before submitting
|
// TODO: Validate current password before submitting
|
||||||
changeCancelPasswordMutation.mutate({
|
changeCancelPasswordMutation.mutate({
|
||||||
mid,
|
mid,
|
||||||
password: newPassword
|
password: password
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -82,24 +83,24 @@ export const PasswordModifyCancelPasswordPage = () => {
|
|||||||
<div className="ua-row">
|
<div className="ua-row">
|
||||||
<div className="ua-label">변경 비밀번호 <span className="red">*</span></div>
|
<div className="ua-label">변경 비밀번호 <span className="red">*</span></div>
|
||||||
<input
|
<input
|
||||||
className={`wid-100 ${confirmPassword && newPassword !== confirmPassword ? 'error' : ''}`}
|
className={`wid-100 ${confirmPassword && password !== confirmPassword ? 'error' : ''}`}
|
||||||
type="password"
|
type="password"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
value={newPassword}
|
value={password}
|
||||||
onChange={(e) => setNewPassword(e.target.value)}
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="ua-row">
|
<div className="ua-row">
|
||||||
<div className="ua-label">변경 비밀번호 재입력 <span className="red">*</span></div>
|
<div className="ua-label">변경 비밀번호 재입력 <span className="red">*</span></div>
|
||||||
<input
|
<input
|
||||||
className={`wid-100 ${confirmPassword && newPassword !== confirmPassword ? 'error' : ''}`}
|
className={`wid-100 ${confirmPassword && password !== confirmPassword ? 'error' : ''}`}
|
||||||
type="password"
|
type="password"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
value={confirmPassword}
|
value={confirmPassword}
|
||||||
onChange={(e) => setConfirmPassword(e.target.value)}
|
onChange={(e) => setConfirmPassword(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{confirmPassword && newPassword !== confirmPassword && (
|
{confirmPassword && password !== confirmPassword && (
|
||||||
<div className="ua-help error">입력 정보 불일치</div>
|
<div className="ua-help error">입력 정보 불일치</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -30,11 +30,19 @@ export const UserMenuAuthPage = () => {
|
|||||||
// 메뉴별 권한 상태 관리
|
// 메뉴별 권한 상태 관리
|
||||||
const [permissions, setPermissions] = useState<Record<number, number>>({});
|
const [permissions, setPermissions] = useState<Record<number, number>>({});
|
||||||
const [initialPermissions, setInitialPermissions] = useState<Record<number, number>>({});
|
const [initialPermissions, setInitialPermissions] = useState<Record<number, number>>({});
|
||||||
|
const [defaultPermissions, setDefaultPermissions] = useState<Record<number, number>>({});
|
||||||
const [hasChanges, setHasChanges] = useState(false);
|
const [hasChanges, setHasChanges] = useState(false);
|
||||||
const savePermissionsMutation = useUserMenuPermissionsSaveMutation({
|
const savePermissionsMutation = useUserMenuPermissionsSaveMutation({
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
snackBar('권한이 성공적으로 저장되었습니다.');
|
snackBar('권한이 성공적으로 저장되었습니다.');
|
||||||
navigate(PATHS.account.password.manage);
|
navigate(PATHS.account.user.accountAuth, {
|
||||||
|
state: {
|
||||||
|
mid,
|
||||||
|
usrid,
|
||||||
|
idCl: location.state?.idCl,
|
||||||
|
status: location.state?.status
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
snackBar(error?.response?.data?.message || '권한 저장에 실패했습니다.');
|
snackBar(error?.response?.data?.message || '권한 저장에 실패했습니다.');
|
||||||
@@ -84,12 +92,15 @@ export const UserMenuAuthPage = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (menuGrants && Array.isArray(menuGrants) && menuGrants.length > 0) {
|
if (menuGrants && Array.isArray(menuGrants) && menuGrants.length > 0) {
|
||||||
// menuGrants 데이터가 있으면 사용
|
// menuGrants 데이터가 있으면 사용
|
||||||
const initial: Record<number, number> = {};
|
const grants: Record<number, number> = {};
|
||||||
menuGrants.forEach((grant: { menuId: number; grant: number }) => {
|
const defaultGrants: Record<number, number> = {};
|
||||||
initial[grant.menuId] = grant.grant || 0;
|
menuGrants.forEach((grant: { menuId: number; grant: number; defaultGrant: number }) => {
|
||||||
|
grants[grant.menuId] = grant.grant || 0;
|
||||||
|
defaultGrants[grant.menuId] = grant.defaultGrant || 0;
|
||||||
});
|
});
|
||||||
setPermissions(initial);
|
setPermissions(grants);
|
||||||
setInitialPermissions(initial);
|
setInitialPermissions(grants); // 초기값은 현재 grant 값으로 설정
|
||||||
|
setDefaultPermissions(defaultGrants); // defaultGrant는 별도로 관리
|
||||||
} else {
|
} else {
|
||||||
// menuGrants가 없거나 빈 배열이면 API에서 권한 조회
|
// menuGrants가 없거나 빈 배열이면 API에서 권한 조회
|
||||||
// loadPermissions();
|
// loadPermissions();
|
||||||
@@ -114,6 +125,11 @@ export const UserMenuAuthPage = () => {
|
|||||||
return (grant & flag) === flag;
|
return (grant & flag) === flag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const hasDefaultPermission = (menuId: number, flag: number): boolean => {
|
||||||
|
const grant = defaultPermissions[menuId] || 0;
|
||||||
|
return (grant & flag) === flag;
|
||||||
|
};
|
||||||
|
|
||||||
// 권한 토글 처리
|
// 권한 토글 처리
|
||||||
const togglePermission = (menuId: number, flag: number) => {
|
const togglePermission = (menuId: number, flag: number) => {
|
||||||
setPermissions(prev => {
|
setPermissions(prev => {
|
||||||
@@ -152,7 +168,8 @@ export const UserMenuAuthPage = () => {
|
|||||||
([menuId, grant]) => ({
|
([menuId, grant]) => ({
|
||||||
menuId: Number(menuId),
|
menuId: Number(menuId),
|
||||||
usrid: usrid,
|
usrid: usrid,
|
||||||
grant: grant
|
grant: grant,
|
||||||
|
defaultGrant: defaultPermissions[Number(menuId)] || 0
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -210,6 +227,7 @@ export const UserMenuAuthPage = () => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="set-divider"></div>
|
<div className="set-divider"></div>
|
||||||
|
{hasDefaultPermission(menu.menuId, PERMISSION.SAVE) && (
|
||||||
<div className="settings-row">
|
<div className="settings-row">
|
||||||
<span className="settings-row-title bd-sub dot">저장</span>
|
<span className="settings-row-title bd-sub dot">저장</span>
|
||||||
<label className="settings-switch">
|
<label className="settings-switch">
|
||||||
@@ -221,6 +239,9 @@ export const UserMenuAuthPage = () => {
|
|||||||
<span className="slider"></span>
|
<span className="slider"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{hasDefaultPermission(menu.menuId, PERMISSION.EXECUTE) && (
|
||||||
<div className="settings-row">
|
<div className="settings-row">
|
||||||
<span className="settings-row-title bd-sub dot">실행</span>
|
<span className="settings-row-title bd-sub dot">실행</span>
|
||||||
<label className="settings-switch">
|
<label className="settings-switch">
|
||||||
@@ -232,6 +253,9 @@ export const UserMenuAuthPage = () => {
|
|||||||
<span className="slider"></span>
|
<span className="slider"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{hasDefaultPermission(menu.menuId, PERMISSION.DOWNLOAD) && (
|
||||||
<div className="settings-row">
|
<div className="settings-row">
|
||||||
<span className="settings-row-title bd-sub dot">다운로드</span>
|
<span className="settings-row-title bd-sub dot">다운로드</span>
|
||||||
<label className="settings-switch">
|
<label className="settings-switch">
|
||||||
@@ -243,6 +267,7 @@ export const UserMenuAuthPage = () => {
|
|||||||
<span className="slider"></span>
|
<span className="slider"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="ht-20"></div>
|
<div className="ht-20"></div>
|
||||||
|
|||||||
@@ -42,6 +42,6 @@ export const API_URL_USER = {
|
|||||||
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/password`;
|
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/password`;
|
||||||
},
|
},
|
||||||
userChangeCancelPassword: () => {
|
userChangeCancelPassword: () => {
|
||||||
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/cancel/change`;
|
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/cancle/change`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user