This commit is contained in:
focp212@naver.com
2025-09-29 13:33:59 +09:00
22 changed files with 259 additions and 76 deletions

View File

@@ -5,7 +5,7 @@ NODE_VERSION = 20
DOCKER_REGISTRY = harbor.jongyeob.com DOCKER_REGISTRY = harbor.jongyeob.com
DOCKER_PROJECT = nicepay DOCKER_PROJECT = nicepay
DOCKER_IMAGE = nice-app-web DOCKER_IMAGE = nice-app-web
DOCKER_TAG = latest DOCKER_TAG = 1.0.0
DOCKER_FULL_IMAGE = $(DOCKER_REGISTRY)/$(DOCKER_PROJECT)/$(DOCKER_IMAGE) DOCKER_FULL_IMAGE = $(DOCKER_REGISTRY)/$(DOCKER_PROJECT)/$(DOCKER_IMAGE)
CONTAINER_NAME = nice-app-web CONTAINER_NAME = nice-app-web
PORT = 80 PORT = 80

View File

@@ -15,7 +15,7 @@ export interface AccountUserTabProps {
activeTab: AccountUserTabKeys; activeTab: AccountUserTabKeys;
mid?: string; mid?: string;
usrid?: string; usrid?: string;
idCl?: string; idCL?: string;
status?: string; status?: string;
}; };
@@ -26,7 +26,7 @@ export interface UserManageAuthListProps {
export interface UserManageAuthItemProps { export interface UserManageAuthItemProps {
usrid?: string; usrid?: string;
mid?: string; mid?: string;
idCl?: string; idCL?: string;
status?: string; status?: string;
}; };
export interface UserLoginAuthInfoWrapProps { export interface UserLoginAuthInfoWrapProps {
@@ -36,7 +36,7 @@ export interface UserLoginAuthInfoWrapProps {
export interface UserAccountAuthWrapProps { export interface UserAccountAuthWrapProps {
mid: string; mid: string;
usrid: string; usrid: string;
idCl: string; idCL: string;
status: string; status: string;
}; };
export interface PermItem { export interface PermItem {
@@ -47,7 +47,7 @@ export interface PermItem {
export interface UserAccountAuthPermListProps { export interface UserAccountAuthPermListProps {
mid: string; mid: string;
usrid: string; usrid: string;
idCl: string; idCL: string;
status: string; status: string;
menuItems: Array<PermItem>; menuItems: Array<PermItem>;
menuGrants: Array<UserMenuPermissionData>; menuGrants: Array<UserMenuPermissionData>;
@@ -55,7 +55,7 @@ export interface UserAccountAuthPermListProps {
export interface UserAccountAuthPermItemProps extends PermItem { export interface UserAccountAuthPermItemProps extends PermItem {
mid: string; mid: string;
usrid: string; usrid: string;
idCl: string; idCL: string;
status: string; status: string;
menuName: string; menuName: string;
subMenu: Array<PermItem>; subMenu: Array<PermItem>;

View File

@@ -9,7 +9,7 @@ export const AccountUserTab = ({
activeTab, activeTab,
mid, mid,
usrid, usrid,
idCl, idCL,
status, status,
}: AccountUserTabProps) => { }: AccountUserTabProps) => {
const { navigate } = useNavigate(); const { navigate } = useNavigate();
@@ -21,7 +21,7 @@ export const AccountUserTab = ({
state: { state: {
mid: mid, mid: mid,
usrid: usrid, usrid: usrid,
idCl: idCl, idCL: idCL,
status: status status: status
} }
}); });
@@ -31,7 +31,7 @@ export const AccountUserTab = ({
state: { state: {
mid: mid, mid: mid,
usrid: usrid, usrid: usrid,
idCl: idCl, idCL: idCL,
status: status status: status
} }
}); });

View File

@@ -4,9 +4,6 @@ import { useNavigate } from '@/shared/lib/hooks/use-navigate';
export const PasswordManageWrap = () => { export const PasswordManageWrap = () => {
const { navigate } = useNavigate(); const { navigate } = useNavigate();
const onClickTonavigation = () => {
navigate(PATHS.account.password.modifyLoginPassword);
};
return ( return (
<> <>
<div className="ing-list"> <div className="ing-list">
@@ -15,11 +12,12 @@ export const PasswordManageWrap = () => {
<button <button
className="btn-44 btn-white pwd-btn" className="btn-44 btn-white pwd-btn"
type="button" type="button"
onClick={ () => onClickTonavigation() } onClick={ () => navigate(PATHS.account.password.modifyLoginPassword) }
> </button> > </button>
<button <button
className="btn-44 btn-white pwd-btn" className="btn-44 btn-white pwd-btn"
type="button" type="button"
onClick={ () => navigate(PATHS.account.password.modifyCancelPassword) }
> </button> > </button>
</div> </div>
</div> </div>

View File

@@ -5,7 +5,7 @@ import { UserAccountAuthPermItemProps } from '../model/types';
export const UserAccountAuthPermItem = ({ export const UserAccountAuthPermItem = ({
mid, mid,
usrid, usrid,
idCl, idCL,
status, status,
menuId, menuId,
menuName, menuName,
@@ -19,7 +19,7 @@ export const UserAccountAuthPermItem = ({
state: { state: {
mid: mid, mid: mid,
usrid: usrid, usrid: usrid,
idCl: idCl, idCl: idCL,
status: status, status: status,
menuId: menuId, menuId: menuId,
menuName: menuName, menuName: menuName,

View File

@@ -4,7 +4,7 @@ import { UserAccountAuthPermItem } from './user-account-auth-perm-item';
export const UserAccountAuthPermList = ({ export const UserAccountAuthPermList = ({
mid, mid,
usrid, usrid,
idCl, idCL,
status, status,
menuItems, menuItems,
menuGrants, menuGrants,
@@ -23,7 +23,7 @@ export const UserAccountAuthPermList = ({
key={`perm-${item.menuId || index}`} key={`perm-${item.menuId || index}`}
mid={mid} mid={mid}
usrid={usrid} usrid={usrid}
idCl={idCl} idCL={idCL}
status={status} status={status}
menuId={item.menuId} menuId={item.menuId}
menuName={item.menuName ?? ''} menuName={item.menuName ?? ''}

View File

@@ -8,16 +8,16 @@ import { UserMenuPermissionData } from '@/entities/user/model/types';
export const UserAccountAuthWrap = ({ export const UserAccountAuthWrap = ({
mid, mid,
usrid, usrid,
idCl, idCL,
status, status,
}: 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 [menuGrants, setMenuGrants] = 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);
console.log('idCl : ', idCl); console.log('idCL : ', idCL);
console.log('status : ', status); console.log('status : ', status);
const { mutateAsync: userMenuPermissions } = useUserMenuPermissionsMutation(); const { mutateAsync: userMenuPermissions } = useUserMenuPermissionsMutation();
const updatePermissionsMutation = useUserUpdatePermissionsMutation(); const updatePermissionsMutation = useUserUpdatePermissionsMutation();
@@ -42,9 +42,9 @@ export const UserAccountAuthWrap = ({
// 변경 사항 감지 // 변경 사항 감지
useEffect(() => { useEffect(() => {
const statusChanged = currentStatus !== status; const statusChanged = currentStatus !== status;
const idClChanged = currentIdCl !== idCl; const idCLChanged = currentIdCL !== idCL;
setHasChanges(statusChanged || idClChanged); setHasChanges(statusChanged || idCLChanged);
}, [currentStatus, currentIdCl, status, idCl]); }, [currentStatus, currentIdCL, status, idCL]);
let menuItems = [ let menuItems = [
{menuId: '30', parent: '30', menuName: '거래조회', subMenu: {menuId: '30', parent: '30', menuName: '거래조회', subMenu:
@@ -123,7 +123,7 @@ export const UserAccountAuthWrap = ({
<div className="perm-field"> <div className="perm-field">
<div className="perm-label"> </div> <div className="perm-label"> </div>
<div className="perm-control"> <div className="perm-control">
<select value={currentIdCl} onChange={(e) => setCurrentIdCl(e.target.value)}> <select value={currentIdCL} onChange={(e) => setCurrentIdCl(e.target.value)}>
<option value="MID">MID</option> <option value="MID">MID</option>
<option value="GID">MID + GID</option> <option value="GID">MID + GID</option>
</select> </select>
@@ -136,7 +136,7 @@ export const UserAccountAuthWrap = ({
<UserAccountAuthPermList <UserAccountAuthPermList
mid={ mid } mid={ mid }
usrid={ usrid } usrid={ usrid }
idCl={ currentIdCl } idCL={ currentIdCL }
status={ currentStatus } status={ currentStatus }
menuItems={ menuItems } menuItems={ menuItems }
menuGrants={ menuGrants } menuGrants={ menuGrants }
@@ -153,7 +153,7 @@ export const UserAccountAuthWrap = ({
{ {
mid: mid, mid: mid,
usrid: usrid, usrid: usrid,
idCl: currentIdCl, idCl: currentIdCL,
status: currentStatus status: currentStatus
}); });
}} }}

View File

@@ -3,15 +3,17 @@ import { useUserFindAuthMethodMutation } from '@/entities/user/api/use-user-find
import { DEFAULT_PAGE_PARAM } from '@/entities/common/model/constant'; import { DEFAULT_PAGE_PARAM } from '@/entities/common/model/constant';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useUserModifyAuthMethodMutation } from '@/entities/user/api/use-user-modify-authmethod-mutation'; import { useUserModifyAuthMethodMutation } from '@/entities/user/api/use-user-modify-authmethod-mutation';
import { snackBar } from '@/shared/lib/toast';
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
export const UserLoginAuthInfoWrap = ({ export const UserLoginAuthInfoWrap = ({
mid, mid,
usrid, usrid,
idCl, idCL,
status, status,
}: UserFindAuthMethodParams) => { }: UserFindAuthMethodParams) => {
const { mutateAsync: userFindAuthMethod } = useUserFindAuthMethodMutation(); const { navigate } = useNavigate();
const { mutateAsync: userModifyAuthMethod } = useUserModifyAuthMethodMutation();
const [pageParam] = useState(DEFAULT_PAGE_PARAM); const [pageParam] = useState(DEFAULT_PAGE_PARAM);
const [authMethodData, setAuthMethodData] = useState<UserAuthMethodData>(); const [authMethodData, setAuthMethodData] = useState<UserAuthMethodData>();
const [initialData, setInitialData] = useState<UserAuthMethodData>(); const [initialData, setInitialData] = useState<UserAuthMethodData>();
@@ -21,8 +23,22 @@ export const UserLoginAuthInfoWrap = ({
const [editablePhoneIndex, setEditablePhoneIndex] = useState<number>(-1); const [editablePhoneIndex, setEditablePhoneIndex] = useState<number>(-1);
const [readOnlyEmails, setReadOnlyEmails] = useState<Set<number>>(new Set()); const [readOnlyEmails, setReadOnlyEmails] = useState<Set<number>>(new Set());
const [readOnlyPhones, setReadOnlyPhones] = useState<Set<number>>(new Set()); const [readOnlyPhones, setReadOnlyPhones] = useState<Set<number>>(new Set());
const { mutateAsync: userFindAuthMethod } = useUserFindAuthMethodMutation();
const { mutateAsync: userModifyAuthMethod } = useUserModifyAuthMethodMutation({
onSuccess: () => {
snackBar('사용자 정보가 성공적으로 저장되었습니다.');
navigate(PATHS.account.user.manage, {
state: {
mid: mid,
}
});
},
onError: (error) => {
snackBar(error?.response?.data?.message || '사용자 정보 저장에 실패했습니다.');
}
});
console.log("UserLoginAuthInfoWrap", mid, usrid, idCl, status); console.log("UserLoginAuthInfoWrap", mid, usrid, idCL, status);
const handleRemoveExistingEmail = (index: number) => { const handleRemoveExistingEmail = (index: number) => {
if (authMethodData?.emails) { if (authMethodData?.emails) {
@@ -42,7 +58,7 @@ export const UserLoginAuthInfoWrap = ({
let params: UserFindAuthMethodParams = { let params: UserFindAuthMethodParams = {
mid: mid, mid: mid,
usrid: usrid, usrid: usrid,
idCl: idCl, idCL: idCL,
status: status, status: status,
page: pageParam page: pageParam
}; };
@@ -283,7 +299,7 @@ export const UserLoginAuthInfoWrap = ({
removeMethods.push({ removeMethods.push({
usrid: usrid, usrid: usrid,
systemAdminClassId: mid, systemAdminClassId: mid,
idCl: "MID", idCl: idCL,
authMethodType: "EMAIL", authMethodType: "EMAIL",
sequence: email.sequence, sequence: email.sequence,
content: email.content content: email.content
@@ -302,7 +318,7 @@ export const UserLoginAuthInfoWrap = ({
removeMethods.push({ removeMethods.push({
usrid: usrid, usrid: usrid,
systemAdminClassId: mid, systemAdminClassId: mid,
idCl: "MID", idCl: idCL,
authMethodType: "PHONE", authMethodType: "PHONE",
sequence: phone.sequence, sequence: phone.sequence,
content: phone.content content: phone.content
@@ -318,7 +334,7 @@ export const UserLoginAuthInfoWrap = ({
addMethods.push({ addMethods.push({
usrid: usrid, usrid: usrid,
systemAdminClassId: mid, systemAdminClassId: mid,
idCl: "MID", idCl: idCL,
authMethodType: "EMAIL", authMethodType: "EMAIL",
sequence: existingEmailCount + index + 1, sequence: existingEmailCount + index + 1,
content: email content: email
@@ -332,7 +348,7 @@ export const UserLoginAuthInfoWrap = ({
addMethods.push({ addMethods.push({
usrid: usrid, usrid: usrid,
systemAdminClassId: mid, systemAdminClassId: mid,
idCl: "MID", idCl: idCL,
authMethodType: "PHONE", authMethodType: "PHONE",
sequence: existingPhoneCount + index + 1, sequence: existingPhoneCount + index + 1,
content: phone content: phone

View File

@@ -5,15 +5,15 @@ import { UserManageAuthItemProps } from '../model/types';
export const UserManageAuthItem = ({ export const UserManageAuthItem = ({
usrid, usrid,
mid, mid,
idCl, idCL,
status, status,
}: UserManageAuthItemProps) => { }: UserManageAuthItemProps) => {
console.log("UserManageAuthItem", usrid, mid, idCl, status); console.log("UserManageAuthItem", usrid, mid, idCL, status);
const { navigate } = useNavigate(); const { navigate } = useNavigate();
const handleClick = () => { const handleClick = () => {
navigate(PATHS.account.user.loginAuthInfo, { navigate(PATHS.account.user.loginAuthInfo, {
state: { mid, usrid, idCl, status } state: { mid, usrid, idCL, status }
}); });
}; };

View File

@@ -13,7 +13,7 @@ export const UserManageAuthList = ({
key={item.usrid} key={item.usrid}
usrid={item.usrid} usrid={item.usrid}
mid={mid} mid={mid}
idCl={item.idCl} idCL={item.idCL}
status={item.status} status={item.status}
/> />
))} ))}

View File

@@ -0,0 +1,29 @@
import axios from 'axios';
import { API_URL_USER } from '@/shared/api/api-url-user';
import { resultify } from '@/shared/lib/resultify';
import { CBDCAxiosError } from '@/shared/@types/error';
import {
ChangeCancelPasswordParams,
ChangeCancelPasswordResponse
} from '../model/types';
import {
useMutation,
UseMutationOptions
} from '@tanstack/react-query';
export const userChangeCancelPassword = (params: ChangeCancelPasswordParams) => {
return resultify(
axios.post<ChangeCancelPasswordResponse>(API_URL_USER.userChangeCancelPassword(), params),
);
};
export const useUserChangeCancelPasswordMutation = (options?: UseMutationOptions<ChangeCancelPasswordResponse, CBDCAxiosError, ChangeCancelPasswordParams>) => {
const mutation = useMutation<ChangeCancelPasswordResponse, CBDCAxiosError, ChangeCancelPasswordParams>({
...options,
mutationFn: (params: ChangeCancelPasswordParams) => userChangeCancelPassword(params),
});
return {
...mutation,
};
};

View File

@@ -39,9 +39,8 @@ export interface UserParams {
export interface UserListItem { export interface UserListItem {
usrid: string; usrid: string;
idCl: string; idCL: string;
status: string; status: string;
tid: string;
} }
export interface UserFindResponse extends DefaulResponsePagination { export interface UserFindResponse extends DefaulResponsePagination {
@@ -60,7 +59,7 @@ export interface UserExistsUseridParams {
export interface UserFindAuthMethodParams { export interface UserFindAuthMethodParams {
mid: string; mid: string;
usrid: string; usrid: string;
idCl: string; idCL: string;
status: string; status: string;
page?: DefaultRequestPagination; page?: DefaultRequestPagination;
}; };
@@ -133,9 +132,9 @@ export interface UserMenuPermissionData {
} }
export interface ChangePasswordParams { export interface ChangePasswordParams {
mid: string;
usrid: string; usrid: string;
password: string; password: string;
newPassword: string;
} }
export interface ChangePasswordResponse { export interface ChangePasswordResponse {
@@ -143,6 +142,16 @@ export interface ChangePasswordResponse {
error?: ErrorResponse; error?: ErrorResponse;
} }
export interface ChangeCancelPasswordParams {
mid: string;
password: string;
}
export interface ChangeCancelPasswordResponse {
status: boolean;
error?: ErrorResponse;
}
export interface VerificationsItem { export interface VerificationsItem {
type: string; type: string;
contact: string; contact: string;

View File

@@ -8,6 +8,7 @@ import { UserMenuAuthPage } from './user/menu-auth-page';
import { UserAddAccountPage } from './user/add-account-page'; import { UserAddAccountPage } from './user/add-account-page';
import { PasswordManagePage } from './password/manage-page'; import { PasswordManagePage } from './password/manage-page';
import { PasswordModifyLoginPasswordPage } from './password/modify-login-password-page'; import { PasswordModifyLoginPasswordPage } from './password/modify-login-password-page';
import { PasswordModifyCancelPasswordPage } from './password/modify-cancel-password-page';
export const AccountPages = () => { export const AccountPages = () => {
@@ -24,6 +25,7 @@ export const AccountPages = () => {
<Route path={ROUTE_NAMES.account.password.base}> <Route path={ROUTE_NAMES.account.password.base}>
<Route path={ROUTE_NAMES.account.password.manage} element={<PasswordManagePage />} /> <Route path={ROUTE_NAMES.account.password.manage} element={<PasswordManagePage />} />
<Route path={ROUTE_NAMES.account.password.modifyLoginPassword} element={<PasswordModifyLoginPasswordPage />} /> <Route path={ROUTE_NAMES.account.password.modifyLoginPassword} element={<PasswordModifyLoginPasswordPage />} />
<Route path={ROUTE_NAMES.account.password.modifyCancelPassword} element={<PasswordModifyCancelPasswordPage />} />
</Route> </Route>
</SentryRoutes> </SentryRoutes>
</> </>

View File

@@ -0,0 +1,121 @@
import { useState } from 'react';
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { HeaderType } from '@/entities/common/model/types';
import {
useSetHeaderTitle,
useSetHeaderType,
useSetFooterMode,
useSetOnBack
} from '@/widgets/sub-layout/use-sub-layout';
import { useUserChangeCancelPasswordMutation } from '@/entities/user/api/use-user-change-cancel-password-mutation';
import { snackBar } from '@/shared/lib/toast';
export const PasswordModifyCancelPasswordPage = () => {
const { navigate } = useNavigate();
const [mid, setMid] = useState<string>('nictest00m');
const [newPassword, setNewPassword] = useState<string>('');
const [confirmPassword, setConfirmPassword] = useState<string>('');
const changeCancelPasswordMutation = useUserChangeCancelPasswordMutation({
onSuccess: () => {
snackBar('비밀번호가 성공적으로 변경되었습니다.');
// Clear form
setNewPassword('');
setConfirmPassword('');
// Navigate back
navigate(PATHS.account.password.manage);
},
onError: (error) => {
snackBar(error?.response?.data?.message || '비밀번호 변경에 실패했습니다.');
}
});
const midList = [
{ value: 'nictest00m', label: 'nictest00m' },
{ value: 'nictest01m', label: 'nictest01m' },
{ value: 'nictest02m', label: 'nictest02m' },
];
useSetHeaderTitle('거래취소 비밀번호 변경');
useSetHeaderType(HeaderType.LeftArrow);
useSetFooterMode(false);
useSetOnBack(() => {
navigate(PATHS.account.password.manage);
});
// 저장 버튼 활성화 조건 체크
const isFormValid = () => {
return (
newPassword.length >= 8 &&
confirmPassword.length >= 8 &&
newPassword === confirmPassword
);
};
// 저장 버튼 클릭 핸들러
const handleSave = () => {
if (!isFormValid()) return;
// TODO: Validate current password before submitting
changeCancelPasswordMutation.mutate({
mid,
password: newPassword
});
};
return (
<>
<main>
<div className="tab-content">
<div className="tab-pane sub active">
<div className="ing-list add">
<div className="user-add">
<div className="ua-row">
<div className="ua-label"> <span className="red">*</span></div>
<select className="wid-100" value={mid} onChange={(e) => setMid(e.target.value)}>
{midList.map((item) => (
<option key={item.value} value={item.value}>{item.label}</option>
))}
</select>
</div>
<div className="ua-row">
<div className="ua-label"> <span className="red">*</span></div>
<input
className={`wid-100 ${confirmPassword && newPassword !== confirmPassword ? 'error' : ''}`}
type="password"
placeholder=""
value={newPassword}
onChange={(e) => setNewPassword(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' : ''}`}
type="password"
placeholder=""
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
/>
</div>
{confirmPassword && newPassword !== confirmPassword && (
<div className="ua-help error"> </div>
)}
</div>
<div className="apply-row bottom-padding">
<button
className="btn-50 btn-blue flex-1"
type="button"
disabled={!isFormValid() || changeCancelPasswordMutation.isPending}
onClick={handleSave}
>{changeCancelPasswordMutation.isPending ? '처리중...' : '저장'}</button>
</div>
</div>
</div>
</div>
</main>
</>
);
};

View File

@@ -13,11 +13,10 @@ import { snackBar } from '@/shared/lib/toast';
export const PasswordModifyLoginPasswordPage = () => { export const PasswordModifyLoginPasswordPage = () => {
const { navigate } = useNavigate(); const { navigate } = useNavigate();
const [mid, setMid] = useState<string>('nictest00m');
const [currentPassword, setCurrentPassword] = useState<string>(''); const [currentPassword, setCurrentPassword] = useState<string>('');
const [newPassword, setNewPassword] = useState<string>(''); const [newPassword, setNewPassword] = useState<string>('');
const [confirmPassword, setConfirmPassword] = useState<string>(''); const [confirmPassword, setConfirmPassword] = useState<string>('');
const [usrid] = useState<string>(''); // TODO: Get actual user ID from context/session const [usrid, ] = useState<string>('nictest00');
const changePasswordMutation = useUserChangePasswordMutation({ const changePasswordMutation = useUserChangePasswordMutation({
onSuccess: () => { onSuccess: () => {
@@ -34,12 +33,6 @@ export const PasswordModifyLoginPasswordPage = () => {
} }
}); });
const midList = [
{ value: 'nictest00m', label: 'nictest00m' },
{ value: 'nictest01m', label: 'nictest01m' },
{ value: 'nictest02m', label: 'nictest02m' },
];
useSetHeaderTitle('로그인 비밀번호 변경'); useSetHeaderTitle('로그인 비밀번호 변경');
useSetHeaderType(HeaderType.LeftArrow); useSetHeaderType(HeaderType.LeftArrow);
useSetFooterMode(false); useSetFooterMode(false);
@@ -63,9 +56,9 @@ export const PasswordModifyLoginPasswordPage = () => {
// TODO: Validate current password before submitting // TODO: Validate current password before submitting
changePasswordMutation.mutate({ changePasswordMutation.mutate({
mid, usrid: usrid,
usrid: usrid || 'test', // TODO: Get actual user ID password: newPassword,
password: newPassword newPassword: newPassword,
}); });
}; };
@@ -76,14 +69,6 @@ export const PasswordModifyLoginPasswordPage = () => {
<div className="tab-pane sub active"> <div className="tab-pane sub active">
<div className="ing-list add"> <div className="ing-list add">
<div className="user-add"> <div className="user-add">
<div className="ua-row">
<div className="ua-label"> <span className="red">*</span></div>
<select className="wid-100" value={mid} onChange={(e) => setMid(e.target.value)}>
{midList.map((item) => (
<option key={item.value} value={item.value}>{item.label}</option>
))}
</select>
</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

View File

@@ -16,7 +16,7 @@ import {
export const UserAccountAuthPage = () => { export const UserAccountAuthPage = () => {
const { navigate } = useNavigate(); const { navigate } = useNavigate();
const location = useLocation(); const location = useLocation();
const { tid, mid, usrid, idCl, status } = location.state || {}; const { mid, usrid, idCL, status } = location.state || {};
const [activeTab, ] = useState<AccountUserTabKeys>(AccountUserTabKeys.AccountAuth); const [activeTab, ] = useState<AccountUserTabKeys>(AccountUserTabKeys.AccountAuth);
useSetHeaderTitle('사용자 설정'); useSetHeaderTitle('사용자 설정');
@@ -26,9 +26,6 @@ export const UserAccountAuthPage = () => {
navigate(PATHS.account.user.manage); navigate(PATHS.account.user.manage);
}); });
useEffect(() => {
console.log('tid : ', tid);
});
return ( return (
<> <>
@@ -39,13 +36,13 @@ export const UserAccountAuthPage = () => {
activeTab={ activeTab } activeTab={ activeTab }
mid={ mid || '' } mid={ mid || '' }
usrid={ usrid || '' } usrid={ usrid || '' }
idCl={ idCl || '' } idCL={ idCL || '' }
status={ status || '' } status={ status || '' }
></AccountUserTab> ></AccountUserTab>
<UserAccountAuthWrap <UserAccountAuthWrap
mid={ mid || '' } mid={ mid || '' }
usrid={ usrid || '' } usrid={ usrid || '' }
idCl={ idCl || '' } idCL={ idCL || '' }
status={ status || '' } status={ status || '' }
></UserAccountAuthWrap> ></UserAccountAuthWrap>
</div> </div>

View File

@@ -12,12 +12,21 @@ import { VerificationItem } from '@/entities/account/model/types';
import { useUserCreateMutation } from '@/entities/user/api/use-user-create-mutation'; import { useUserCreateMutation } from '@/entities/user/api/use-user-create-mutation';
import { useUserExistsUseridQuery } from '@/entities/user/api/use-user-exists-userid-query'; import { useUserExistsUseridQuery } from '@/entities/user/api/use-user-exists-userid-query';
import { useLocation } from 'react-router'; import { useLocation } from 'react-router';
import { snackBar } from '@/shared/lib/toast';
export const UserAddAccountPage = () => { export const UserAddAccountPage = () => {
const { navigate } = useNavigate(); const { navigate } = useNavigate();
const location = useLocation(); const location = useLocation();
const { mid } = location.state || {}; const { mid } = location.state || {};
const { mutateAsync: userCreate, isPending } = useUserCreateMutation();
const { mutateAsync: userCreate, isPending } = useUserCreateMutation({
onSuccess: () => {
snackBar('사용자가 성공적으로 추가되었습니다.');
},
onError: (error) => {
snackBar(error?.response?.data?.message || '사용자 추가에 실패했습니다.');
}
});
// 폼 상태 관리 // 폼 상태 관리
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
@@ -373,6 +382,7 @@ export const UserAddAccountPage = () => {
if (response.status) { if (response.status) {
// 성공 시 사용자 관리 페이지로 이동 // 성공 시 사용자 관리 페이지로 이동
snackBar('사용자가 성공적으로 추가되었습니다.');
navigate(PATHS.account.user.manage); navigate(PATHS.account.user.manage);
} else if (response.error) { } else if (response.error) {
// 에러 처리 // 에러 처리

View File

@@ -15,7 +15,7 @@ import {
export const UserLoginAuthInfoPage = () => { export const UserLoginAuthInfoPage = () => {
const location = useLocation(); const location = useLocation();
const { mid, usrid, idCl, status } = location.state || {}; const { mid, usrid, idCL, status } = location.state || {};
const { navigate } = useNavigate(); const { navigate } = useNavigate();
const [activeTab, ] = useState<AccountUserTabKeys>(AccountUserTabKeys.LoginAuthInfo); const [activeTab, ] = useState<AccountUserTabKeys>(AccountUserTabKeys.LoginAuthInfo);
@@ -35,13 +35,13 @@ export const UserLoginAuthInfoPage = () => {
activeTab={ activeTab } activeTab={ activeTab }
mid={mid || ''} mid={mid || ''}
usrid={usrid || ''} usrid={usrid || ''}
idCl={idCl || ''} idCL={idCL || ''}
status={status || ''} status={status || ''}
></AccountUserTab> ></AccountUserTab>
<UserLoginAuthInfoWrap <UserLoginAuthInfoWrap
mid={mid || ''} mid={mid || ''}
usrid={usrid || ''} usrid={usrid || ''}
idCl={idCl || ''} idCL={idCL || ''}
status={status || ''} status={status || ''}
></UserLoginAuthInfoWrap> ></UserLoginAuthInfoWrap>
</div> </div>

View File

@@ -12,6 +12,7 @@ import { useLocation } from 'react-router';
import { useUserMenuPermissionsSaveMutation } from '@/entities/user/api/use-user-menu-permission-save-mutation'; import { useUserMenuPermissionsSaveMutation } from '@/entities/user/api/use-user-menu-permission-save-mutation';
// import { useUserMenuPermissionsMutation } from '@/entities/user/api/use-user-menu-permission-mutation'; // import { useUserMenuPermissionsMutation } from '@/entities/user/api/use-user-menu-permission-mutation';
import { UserMenuPermissionData } from '@/entities/user/model/types'; import { UserMenuPermissionData } from '@/entities/user/model/types';
import { snackBar } from '@/shared/lib/toast';
// 권한 비트 플래그 (실제 API 데이터 기준) // 권한 비트 플래그 (실제 API 데이터 기준)
const PERMISSION = { const PERMISSION = {
@@ -30,8 +31,15 @@ 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 [hasChanges, setHasChanges] = useState(false); const [hasChanges, setHasChanges] = useState(false);
const savePermissionsMutation = useUserMenuPermissionsSaveMutation(); const savePermissionsMutation = useUserMenuPermissionsSaveMutation({
// const getPermissionsMutation = useUserMenuPermissionsMutation(); onSuccess: () => {
snackBar('권한이 성공적으로 저장되었습니다.');
navigate(PATHS.account.password.manage);
},
onError: (error) => {
snackBar(error?.response?.data?.message || '권한 저장에 실패했습니다.');
}
});
useSetHeaderTitle(menuName); useSetHeaderTitle(menuName);
useSetHeaderType(HeaderType.LeftArrow); useSetHeaderType(HeaderType.LeftArrow);

View File

@@ -41,4 +41,7 @@ export const API_URL_USER = {
changePassword: () => { changePassword: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/password`; return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/password`;
}, },
userChangeCancelPassword: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/cancel/change`;
}
} }

View File

@@ -122,6 +122,10 @@ export const PATHS: RouteNamesType = {
`${ROUTE_NAMES.account.base}${ROUTE_NAMES.account.password.base}`, `${ROUTE_NAMES.account.base}${ROUTE_NAMES.account.password.base}`,
ROUTE_NAMES.account.password.modifyLoginPassword, ROUTE_NAMES.account.password.modifyLoginPassword,
), ),
modifyCancelPassword: generatePath(
`${ROUTE_NAMES.account.base}${ROUTE_NAMES.account.password.base}`,
ROUTE_NAMES.account.password.modifyCancelPassword,
),
} }
}, },
vatReturn: { vatReturn: {

View File

@@ -55,8 +55,9 @@ export const ROUTE_NAMES = {
password: { password: {
base: '/password/*', base: '/password/*',
manage: 'manage', manage: 'manage',
modifyLoginPassword: 'modifyLoginPassword' modifyLoginPassword: 'change-login-password',
} modifyCancelPassword: 'change-cancel-password'
},
}, },
vatReturn: { vatReturn: {
base: '/vat-return/*', base: '/vat-return/*',