11import * as Common from "@frontend/common" ;
2- import { KeyOff } from "@mui/icons-material" ;
3- import { Button , ButtonProps , CircularProgress , Dialog , DialogActions , DialogContent , DialogContentText , DialogTitle } from "@mui/material" ;
2+ import { ContentCopy , KeyOff } from "@mui/icons-material" ;
3+ import {
4+ Button ,
5+ ButtonProps ,
6+ CircularProgress ,
7+ Dialog ,
8+ DialogActions ,
9+ DialogContent ,
10+ DialogContentText ,
11+ DialogTitle ,
12+ IconButton ,
13+ InputAdornment ,
14+ TextField ,
15+ } from "@mui/material" ;
416import { ErrorBoundary , Suspense } from "@suspensive/react" ;
517import * as React from "react" ;
618import { useParams } from "react-router-dom" ;
@@ -9,53 +21,104 @@ import { addErrorSnackbar, addSnackbar } from "../../../utils/snackbar";
921import { AdminEditor } from "../../layouts/admin_editor" ;
1022
1123type PageStateType = {
12- isDialogOpen : boolean ;
24+ isConfirmDialogOpen : boolean ;
25+ isResultDialogOpen : boolean ;
26+ newPassword : string | null ;
1327} ;
1428
1529export const AdminUserExtEditor : React . FC = ErrorBoundary . with (
1630 { fallback : Common . Components . ErrorFallback } ,
1731 Suspense . with ( { fallback : < CircularProgress /> } , ( ) => {
1832 const { id } = useParams < { id ?: string } > ( ) ;
19- const [ pageState , setPageState ] = React . useState < PageStateType > ( { isDialogOpen : false } ) ;
20- const openDialog = ( ) => setPageState ( ( ps ) => ( { ...ps , isDialogOpen : true } ) ) ;
21- const closeDialog = ( ) => setPageState ( ( ps ) => ( { ...ps , isDialogOpen : false } ) ) ;
33+ const [ pageState , setPageState ] = React . useState < PageStateType > ( {
34+ isConfirmDialogOpen : false ,
35+ isResultDialogOpen : false ,
36+ newPassword : null ,
37+ } ) ;
38+ const openConfirmDialog = ( ) => setPageState ( ( ps ) => ( { ...ps , isConfirmDialogOpen : true } ) ) ;
39+ const closeConfirmDialog = ( ) => setPageState ( ( ps ) => ( { ...ps , isConfirmDialogOpen : false } ) ) ;
40+ const closeResultDialog = ( ) => setPageState ( ( ps ) => ( { ...ps , isResultDialogOpen : false , newPassword : null } ) ) ;
2241
2342 const backendAdminClient = Common . Hooks . BackendAdminAPI . useBackendAdminClient ( ) ;
2443 const useResetPasswordMutation = Common . Hooks . BackendAdminAPI . useResetUserPasswordMutation ( backendAdminClient , id || "" ) ;
2544
2645 const resetUserPassword = ( ) => {
27- closeDialog ( ) ;
46+ closeConfirmDialog ( ) ;
2847 if ( id ) {
2948 useResetPasswordMutation . mutate ( undefined , {
30- onSuccess : ( ) => addSnackbar ( "비밀번호가 초기화되었습니다." , "success" ) ,
49+ onSuccess : ( data ) => {
50+ setPageState ( ( ps ) => ( {
51+ ...ps ,
52+ isResultDialogOpen : true ,
53+ newPassword : data . password ,
54+ } ) ) ;
55+ } ,
3156 onError : addErrorSnackbar ,
3257 } ) ;
3358 }
3459 } ;
3560
61+ const copyPasswordToClipboard = ( ) => {
62+ if ( pageState . newPassword ) {
63+ navigator . clipboard . writeText ( pageState . newPassword ) . then (
64+ ( ) => addSnackbar ( "비밀번호가 클립보드에 복사되었습니다." , "success" ) ,
65+ ( ) => addSnackbar ( "클립보드 복사에 실패했습니다." , "error" )
66+ ) ;
67+ }
68+ } ;
69+
3670 const resetUserPasswordButton : ButtonProps = {
3771 variant : "outlined" ,
3872 color : "error" ,
3973 size : "small" ,
4074 startIcon : < KeyOff /> ,
4175 children : "비밀번호 초기화" ,
42- onClick : ( ) => id && openDialog ( ) ,
76+ onClick : ( ) => id && openConfirmDialog ( ) ,
4377 } ;
4478
4579 return (
4680 < >
47- < Dialog open = { pageState . isDialogOpen } >
81+ < Dialog open = { pageState . isConfirmDialogOpen } >
4882 < DialogTitle > 비밀번호 초기화</ DialogTitle >
4983 < DialogContent >
5084 < DialogContentText > 정말 이 사용자의 비밀번호를 초기화하시겠습니까?</ DialogContentText >
5185 </ DialogContent >
5286 < DialogActions >
53- < Button color = "error" onClick = { closeDialog } autoFocus >
87+ < Button color = "error" onClick = { closeConfirmDialog } autoFocus >
5488 취소
5589 </ Button >
5690 < Button onClick = { resetUserPassword } > 초기화</ Button >
5791 </ DialogActions >
5892 </ Dialog >
93+
94+ < Dialog open = { pageState . isResultDialogOpen } maxWidth = "sm" fullWidth >
95+ < DialogTitle > 비밀번호가 초기화되었습니다</ DialogTitle >
96+ < DialogContent >
97+ < DialogContentText sx = { { mb : 2 } } >
98+ 새로운 비밀번호가 생성되었습니다. 이 비밀번호는 다시 확인할 수 없으니 반드시 복사해 두세요.
99+ </ DialogContentText >
100+ < TextField
101+ fullWidth
102+ value = { pageState . newPassword || "" }
103+ slotProps = { {
104+ input : {
105+ readOnly : true ,
106+ endAdornment : (
107+ < InputAdornment position = "end" >
108+ < IconButton onClick = { copyPasswordToClipboard } edge = "end" >
109+ < ContentCopy />
110+ </ IconButton >
111+ </ InputAdornment >
112+ ) ,
113+ } ,
114+ } }
115+ />
116+ </ DialogContent >
117+ < DialogActions >
118+ < Button onClick = { closeResultDialog } > 닫기</ Button >
119+ </ DialogActions >
120+ </ Dialog >
121+
59122 < AdminEditor app = "user" resource = "userext" id = { id } extraActions = { [ resetUserPasswordButton ] } />
60123 </ >
61124 ) ;
0 commit comments