From 0c60ea9d6d7e3f8a99c6b1fe169369f940b61438 Mon Sep 17 00:00:00 2001 From: Jay Sheen Date: Fri, 14 Nov 2025 18:33:43 +0900 Subject: [PATCH] =?UTF-8?q?showConfirm=20Hook=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EA=B3=84=EC=A0=95=EA=B6=8C?= =?UTF-8?q?=ED=95=9C=20=ED=83=AD=EC=97=90=20=EC=82=AD=EC=A0=9C=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 문제: - showConfirm 함수 내부에서 useTranslation Hook 호출 - "Invalid hook call" 에러 발생 수정 사항: 1. showConfirm Hook 에러 수정 - ConfirmDialog 컴포넌트 분리 - 컴포넌트 내부에서 useTranslation 호출 - showConfirm은 일반 함수로 유지 2. 계정권한 탭에 삭제 버튼 추가 - account-auth-page.tsx에 삭제 기능 추가 - login-auth-info-page.tsx와 동일한 로직 적용 - 현재 로그인한 사용자가 아닐 경우에만 표시 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/pages/account/user/account-auth-page.tsx | 33 +++++++++++- src/widgets/show-confirm/index.tsx | 53 +++++++++++++++----- 2 files changed, 71 insertions(+), 15 deletions(-) diff --git a/src/pages/account/user/account-auth-page.tsx b/src/pages/account/user/account-auth-page.tsx index ccfe07c..ffff6f4 100644 --- a/src/pages/account/user/account-auth-page.tsx +++ b/src/pages/account/user/account-auth-page.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react'; +import { useState } from 'react'; import { useLocation } from 'react-router'; import { useTranslation } from 'react-i18next'; import { PATHS } from '@/shared/constants/paths'; @@ -11,16 +11,41 @@ import { useSetHeaderTitle, useSetHeaderType, useSetFooterMode, - useSetOnBack + useSetOnBack, + useSetOnRightClick } from '@/widgets/sub-layout/use-sub-layout'; +import { useStore } from '@/shared/model/store'; +import { useUserDeleteMutation } from '@/entities/user/api/use-user-delete-mutation'; +import { showConfirm } from '@/widgets/show-confirm'; +import { snackBar } from '@/shared/lib'; export const UserAccountAuthPage = () => { const { t } = useTranslation(); const { navigate } = useNavigate(); const location = useLocation(); const { mid, usrid, idCL, status } = location.state || {}; + const { mutateAsync: userDelete } = useUserDeleteMutation(); + const currentUsrid = useStore.getState().UserStore.userInfo.usrid; const [activeTab, ] = useState(AccountUserTabKeys.AccountAuth); + + const handleDeleteUser = async () => { + const confirmed = await showConfirm(t('account.deleteUserConfirm', '사용자를 삭제하시겠습니까?')); + if (!confirmed) return; + + try { + const result = await userDelete({ mid, usrid }); + if (result.status) { + snackBar(t('account.deleteUserSuccess', '사용자 삭제를 성공했습니다.')); + navigate(PATHS.account.user.manage, { state: { refresh: true } }); + } else { + snackBar(result.error?.message || t('account.deleteUserFailed', '사용자 삭제를 실패했습니다.')); + } + } catch (error: any) { + snackBar(error.message || t('account.deleteUserFailed', '사용자 삭제를 실패했습니다.')); + } + }; + useSetHeaderTitle(t('account.userSettings')); useSetHeaderType(HeaderType.LeftArrow); useSetFooterMode(false); @@ -28,6 +53,10 @@ export const UserAccountAuthPage = () => { navigate(PATHS.account.user.manage); }); + // 현재 로그인한 사용자가 아닌 경우에만 삭제 버튼 표시 + const isDeleteAllowed = usrid && currentUsrid && usrid !== currentUsrid; + useSetOnRightClick(isDeleteAllowed ? handleDeleteUser : undefined); + return ( <> diff --git a/src/widgets/show-confirm/index.tsx b/src/widgets/show-confirm/index.tsx index dfe6c76..eb05f23 100644 --- a/src/widgets/show-confirm/index.tsx +++ b/src/widgets/show-confirm/index.tsx @@ -2,10 +2,41 @@ import { Dialog } from '@/shared/ui/dialogs/dialog'; import { overlay } from 'overlay-kit'; import { useTranslation } from 'react-i18next'; +const ConfirmDialog = ({ + msg, + isOpen, + close, + unmount, + onConfirm, + onCancel +}: { + msg: string; + isOpen: boolean; + close: () => void; + unmount: () => void; + onConfirm: () => void; + onCancel: () => void; +}) => { + const { t } = useTranslation(); + + return ( + { + onCancel(); + close(); + }} + message={ msg } + buttonLabel={ [t('common.cancel'), t('common.confirm')] } + onConfirmClick={ onConfirm } + onCancelClick={ onCancel } + /> + ); +}; + export const showConfirm = (msg: string): Promise => { return new Promise((resolve) => { - const { t } = useTranslation(); - const onConfirmClick = () => { resolve(true); }; @@ -20,17 +51,13 @@ export const showConfirm = (msg: string): Promise => { unmount }) => { return ( - { - resolve(false); - close(); - }} - message={ msg } - buttonLabel={ [t('common.cancel'), t('common.confirm')] } - onConfirmClick={ onConfirmClick } - onCancelClick={ onCancelClick } + ); });