This commit is contained in:
focp212@naver.com
2025-09-29 16:59:34 +09:00
5 changed files with 80 additions and 53 deletions

View File

@@ -13,7 +13,7 @@ export const UserAccountAuthWrap = ({
}: UserAccountAuthWrapProps) => {
const [currentStatus, setCurrentStatus] = useState(status);
const [currentIdCL, setCurrentIdCl] = useState(idCL);
const [menuGrants, setMenuGrants] = useState<Array<UserMenuPermissionData>>([]);
const [permissions, setPermissions] = useState<Array<UserMenuPermissionData>>([]);
const [hasChanges, setHasChanges] = useState(false);
console.log('mid : ', mid);
console.log('usrid : ', usrid);
@@ -24,20 +24,21 @@ export const UserAccountAuthWrap = ({
useEffect(() => {
if (mid && usrid) {
console.log('userMenuPermissions');
userMenuPermissions({mid: mid, usrid: usrid}).then((res) => {
userMenuPermissions({mid: mid, usrid: usrid}).then((res: any) => {
console.log('res : ', res);
setMenuGrants(res?.data || res || []);
console.log('permissions : ', res?.permissions);
setPermissions(res?.permissions || []);
}).catch((error) => {
console.error('Failed to fetch menu permissions:', error);
setMenuGrants([]);
setPermissions([]);
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [mid, usrid]);
useEffect(() => {
console.log('menuGrants : ', menuGrants);
}, [menuGrants]);
console.log('permissions : ', permissions);
}, [permissions]);
// 변경 사항 감지
useEffect(() => {
@@ -50,7 +51,7 @@ export const UserAccountAuthWrap = ({
{menuId: '30', parent: '30', menuName: '거래조회', subMenu:
[
{menuId: '31', parent: '30', menuName: '거래내역조회'},
{menuId: '32', parent: '30', menuName: '현금영수증 발행'},
{menuId: '32', parent: '30', menuName: '현금영수증발행'},
{menuId: '33', parent: '30', menuName: '에스크로'},
{menuId: '34', parent: '30', menuName: '빌링'}
]
@@ -61,15 +62,15 @@ export const UserAccountAuthWrap = ({
{menuId: '37', parent: '35', menuName: '정산내역'},
]
},
{menuId: '38', parent: '38', menuName: '가맹점 관리', subMenu:
{menuId: '38', parent: '38', menuName: '가맹점관리', subMenu:
[
{menuId: '39', parent: '38', menuName: '가맹점 정보'},
{menuId: '40', parent: '38', menuName: '등록 현황'},
{menuId: '39', parent: '38', menuName: '가맹점정보'},
{menuId: '40', parent: '38', menuName: '등록현황'},
]
},
{menuId: '41', parent: '41', menuName: '결제 관리', subMenu:
{menuId: '41', parent: '41', menuName: '결제관리', subMenu:
[
{menuId: '42', parent: '41', menuName: '결제 정보'},
{menuId: '42', parent: '41', menuName: '결제정보'},
{menuId: '43', parent: '41', menuName: '결제데이터통보'},
]
},
@@ -81,7 +82,7 @@ export const UserAccountAuthWrap = ({
},
{menuId: '47', parent: '47', menuName: '부가세신고자료', subMenu:
[
{menuId: '48', parent: '47', menuName: '부가세신고자료'},
{menuId: '48', parent: '47', menuName: '세금계산서'},
{menuId: '49', parent: '47', menuName: '부가세참고'},
]
},
@@ -89,14 +90,14 @@ export const UserAccountAuthWrap = ({
[
{menuId: '51', parent: '50', menuName: '부가서비스소개'},
{menuId: '52', parent: '50', menuName: '신용카드ARS카드결제'},
{menuId: '53', parent: '50', menuName: '계좌이체ARS카드결제'},
{menuId: '54', parent: '50', menuName: '가상계좌ARS카드결제'},
{menuId: '55', parent: '50', menuName: '휴대폰ARS카드결제'},
{menuId: '56', parent: '50', menuName: '계좌간편결제ARS카드결제'},
{menuId: '57', parent: '50', menuName: 'SSG머니ARS카드결제'},
{menuId: '58', parent: '50', menuName: 'SSG은행계좌ARS카드결제'},
{menuId: '59', parent: '50', menuName: '문화상품권ARS카드결제'},
{menuId: '60', parent: '50', menuName: '티머니페이ARS카드결제'},
{menuId: '53', parent: '50', menuName: '지급대행'},
{menuId: '54', parent: '50', menuName: '링크결제'},
{menuId: '55', parent: '50', menuName: '자금이체'},
{menuId: '56', parent: '50', menuName: 'KEY-IN결제'},
{menuId: '57', parent: '50', menuName: 'SMS결제통보'},
{menuId: '58', parent: '50', menuName: '알림톡결제통보'},
{menuId: '59', parent: '50', menuName: '계좌점유인증'},
{menuId: '60', parent: '50', menuName: '계좌성명조회'},
]
},
{menuId: '61', parent: '61', menuName: '고객지원', subMenu:
@@ -139,7 +140,7 @@ export const UserAccountAuthWrap = ({
idCL={ currentIdCL }
status={ currentStatus }
menuItems={ menuItems }
menuGrants={ menuGrants }
menuGrants={ permissions }
></UserAccountAuthPermList>
<div className="apply-row bottom-padding">

View File

@@ -115,8 +115,7 @@ export interface UserMenuPermissionsParams {
}
export interface UserMenuPermissionsResponse {
status: boolean;
data: Array<UserMenuPermissionData>;
permissions: Array<UserMenuPermissionData>;
}
export interface UserMenuPermissionsSaveParams {
@@ -134,6 +133,7 @@ export interface UserMenuPermissionData {
menuId: number;
usrid: string;
grant: number;
defaultGrant: number;
}
export interface ChangePasswordParams {

View File

@@ -14,14 +14,14 @@ import { snackBar } from '@/shared/lib/toast';
export const PasswordModifyCancelPasswordPage = () => {
const { navigate } = useNavigate();
const [mid, setMid] = useState<string>('nictest00m');
const [newPassword, setNewPassword] = useState<string>('');
const [password, setPassword] = useState<string>('');
const [confirmPassword, setConfirmPassword] = useState<string>('');
const changeCancelPasswordMutation = useUserChangeCancelPasswordMutation({
onSuccess: () => {
snackBar('비밀번호가 성공적으로 변경되었습니다.');
// Clear form
setNewPassword('');
setPassword('');
setConfirmPassword('');
// Navigate back
navigate(PATHS.account.password.manage);
@@ -32,6 +32,7 @@ export const PasswordModifyCancelPasswordPage = () => {
});
const midList = [
{ value: 'nictest00', label: 'nictest00' },
{ value: 'nictest00m', label: 'nictest00m' },
{ value: 'nictest01m', label: 'nictest01m' },
{ value: 'nictest02m', label: 'nictest02m' },
@@ -47,9 +48,9 @@ export const PasswordModifyCancelPasswordPage = () => {
// 저장 버튼 활성화 조건 체크
const isFormValid = () => {
return (
newPassword.length >= 8 &&
password.length >= 8 &&
confirmPassword.length >= 8 &&
newPassword === confirmPassword
password === confirmPassword
);
};
@@ -60,7 +61,7 @@ export const PasswordModifyCancelPasswordPage = () => {
// TODO: Validate current password before submitting
changeCancelPasswordMutation.mutate({
mid,
password: newPassword
password: password
});
};
@@ -82,24 +83,24 @@ export const PasswordModifyCancelPasswordPage = () => {
<div className="ua-row">
<div className="ua-label"> <span className="red">*</span></div>
<input
className={`wid-100 ${confirmPassword && newPassword !== confirmPassword ? 'error' : ''}`}
className={`wid-100 ${confirmPassword && password !== confirmPassword ? 'error' : ''}`}
type="password"
placeholder=""
value={newPassword}
onChange={(e) => setNewPassword(e.target.value)}
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<div className="ua-row">
<div className="ua-label"> <span className="red">*</span></div>
<input
className={`wid-100 ${confirmPassword && newPassword !== confirmPassword ? 'error' : ''}`}
className={`wid-100 ${confirmPassword && password !== confirmPassword ? 'error' : ''}`}
type="password"
placeholder=""
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
/>
</div>
{confirmPassword && newPassword !== confirmPassword && (
{confirmPassword && password !== confirmPassword && (
<div className="ua-help error"> </div>
)}
</div>

View File

@@ -30,11 +30,19 @@ export const UserMenuAuthPage = () => {
// 메뉴별 권한 상태 관리
const [permissions, setPermissions] = useState<Record<number, number>>({});
const [initialPermissions, setInitialPermissions] = useState<Record<number, number>>({});
const [defaultPermissions, setDefaultPermissions] = useState<Record<number, number>>({});
const [hasChanges, setHasChanges] = useState(false);
const savePermissionsMutation = useUserMenuPermissionsSaveMutation({
onSuccess: () => {
snackBar('권한이 성공적으로 저장되었습니다.');
navigate(PATHS.account.password.manage);
navigate(PATHS.account.user.accountAuth, {
state: {
mid,
usrid,
idCl: location.state?.idCl,
status: location.state?.status
}
});
},
onError: (error) => {
snackBar(error?.response?.data?.message || '권한 저장에 실패했습니다.');
@@ -84,12 +92,15 @@ export const UserMenuAuthPage = () => {
useEffect(() => {
if (menuGrants && Array.isArray(menuGrants) && menuGrants.length > 0) {
// menuGrants 데이터가 있으면 사용
const initial: Record<number, number> = {};
menuGrants.forEach((grant: { menuId: number; grant: number }) => {
initial[grant.menuId] = grant.grant || 0;
const grants: Record<number, number> = {};
const defaultGrants: Record<number, number> = {};
menuGrants.forEach((grant: { menuId: number; grant: number; defaultGrant: number }) => {
grants[grant.menuId] = grant.grant || 0;
defaultGrants[grant.menuId] = grant.defaultGrant || 0;
});
setPermissions(initial);
setInitialPermissions(initial);
setPermissions(grants);
setInitialPermissions(grants); // 초기값은 현재 grant 값으로 설정
setDefaultPermissions(defaultGrants); // defaultGrant는 별도로 관리
} else {
// menuGrants가 없거나 빈 배열이면 API에서 권한 조회
// loadPermissions();
@@ -114,6 +125,11 @@ export const UserMenuAuthPage = () => {
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) => {
setPermissions(prev => {
@@ -152,7 +168,8 @@ export const UserMenuAuthPage = () => {
([menuId, grant]) => ({
menuId: Number(menuId),
usrid: usrid,
grant: grant
grant: grant,
defaultGrant: defaultPermissions[Number(menuId)] || 0
})
);
@@ -210,17 +227,21 @@ export const UserMenuAuthPage = () => {
}}
>
<div className="set-divider"></div>
<div className="settings-row">
<span className="settings-row-title bd-sub dot"></span>
<label className="settings-switch">
<input
type="checkbox"
checked={hasPermission(menu.menuId, PERMISSION.SAVE)}
onChange={() => togglePermission(menu.menuId, PERMISSION.SAVE)}
/>
<span className="slider"></span>
</label>
</div>
{hasDefaultPermission(menu.menuId, PERMISSION.SAVE) && (
<div className="settings-row">
<span className="settings-row-title bd-sub dot"></span>
<label className="settings-switch">
<input
type="checkbox"
checked={hasPermission(menu.menuId, PERMISSION.SAVE)}
onChange={() => togglePermission(menu.menuId, PERMISSION.SAVE)}
/>
<span className="slider"></span>
</label>
</div>
)}
{hasDefaultPermission(menu.menuId, PERMISSION.EXECUTE) && (
<div className="settings-row">
<span className="settings-row-title bd-sub dot"></span>
<label className="settings-switch">
@@ -232,6 +253,9 @@ export const UserMenuAuthPage = () => {
<span className="slider"></span>
</label>
</div>
)}
{hasDefaultPermission(menu.menuId, PERMISSION.DOWNLOAD) && (
<div className="settings-row">
<span className="settings-row-title bd-sub dot"></span>
<label className="settings-switch">
@@ -243,6 +267,7 @@ export const UserMenuAuthPage = () => {
<span className="slider"></span>
</label>
</div>
)}
</div>
</div>
<div className="ht-20"></div>

View File

@@ -42,6 +42,6 @@ export const API_URL_USER = {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/password`;
},
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`;
}
}