diff --git a/Project/frontend/src/components/layout/UserInfoButton.tsx b/Project/frontend/src/components/layout/UserInfoButton.tsx index 1c39f82..485bcd5 100644 --- a/Project/frontend/src/components/layout/UserInfoButton.tsx +++ b/Project/frontend/src/components/layout/UserInfoButton.tsx @@ -1,7 +1,9 @@ -import { useState } from 'react'; +import { useState, useEffect } from 'react'; import { createPortal } from 'react-dom'; -import { User, LogOut, X } from 'lucide-react'; +import { User, LogOut, X, UserCog, Key } from 'lucide-react'; import { comms } from '@/communication'; +import { UserInfoDialog } from '@/components/user/UserInfoDialog'; +import { PasswordDialog } from '@/components/user/PasswordDialog'; interface UserInfoButtonProps { userName?: string; @@ -10,8 +12,21 @@ interface UserInfoButtonProps { export function UserInfoButton({ userName, userDept }: UserInfoButtonProps) { const [showLogoutDialog, setShowLogoutDialog] = useState(false); + const [showUserInfoDialog, setShowUserInfoDialog] = useState(false); + const [showPasswordDialog, setShowPasswordDialog] = useState(false); const [processing, setProcessing] = useState(false); + // ESC 키로 다이얼로그 닫기 + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + if (e.key === 'Escape' && showLogoutDialog) { + setShowLogoutDialog(false); + } + }; + window.addEventListener('keydown', handleKeyDown); + return () => window.removeEventListener('keydown', handleKeyDown); + }, [showLogoutDialog]); + const handleLogout = async () => { setProcessing(true); try { @@ -31,6 +46,30 @@ export function UserInfoButton({ userName, userDept }: UserInfoButtonProps) { } }; + const handleUserInfoClick = () => { + setShowLogoutDialog(false); + setShowUserInfoDialog(true); + }; + + const handlePasswordClick = () => { + setShowLogoutDialog(false); + setShowPasswordDialog(true); + }; + + const handlePasswordChange = async (oldPw: string, newPw: string) => { + try { + const result = await comms.changePassword(oldPw, newPw); + if (result.Success) { + alert('비밀번호가 변경되었습니다.'); + } else { + alert(result.Message || '비밀번호 변경에 실패했습니다.'); + } + } catch (error) { + console.error('비밀번호 변경 오류:', error); + alert('비밀번호 변경 중 오류가 발생했습니다.'); + } + }; + if (!userName) return null; return ( @@ -58,8 +97,8 @@ export function UserInfoButton({ userName, userDept }: UserInfoButtonProps) { {/* 헤더 */}

- - 로그아웃 + + 사용자 메뉴

- 로그아웃 하시겠습니까? + 원하시는 작업을 선택하세요.

{/* 푸터 */} -
+
+ +
, document.body )} + + {/* 사용자 정보 수정 다이얼로그 */} + setShowUserInfoDialog(false)} + /> + + {/* 비밀번호 변경 다이얼로그 */} + setShowPasswordDialog(false)} + onConfirm={handlePasswordChange} + /> ); } diff --git a/Project/frontend/src/components/license/LicenseList.tsx b/Project/frontend/src/components/license/LicenseList.tsx index a8f6397..85cb6e0 100644 --- a/Project/frontend/src/components/license/LicenseList.tsx +++ b/Project/frontend/src/components/license/LicenseList.tsx @@ -299,15 +299,15 @@ export function LicenseList() {
{/* 컬럼 헤더 (메모장 디자인 통일) */} -
-
상태
-
제품명 / 제조사
+
+
상태
+
제품명 / 제조사
-
버전
-
수량
-
사용자
-
시리얼 번호
+
버전
+
수량
+
사용자
+
시리얼 번호
{/* 액션/폴더 버튼 공간 */}
diff --git a/Project/frontend/src/components/note/NoteEditModal.tsx b/Project/frontend/src/components/note/NoteEditModal.tsx index 0b01974..aa1eaf0 100644 --- a/Project/frontend/src/components/note/NoteEditModal.tsx +++ b/Project/frontend/src/components/note/NoteEditModal.tsx @@ -26,7 +26,6 @@ export function NoteEditModal({ processing, onClose, onSave, - initialEditMode = false, }: NoteEditModalProps) { const [pdate, setPdate] = useState(''); const [title, setTitle] = useState(''); @@ -34,7 +33,6 @@ export function NoteEditModal({ const [description, setDescription] = useState(''); const [share, setShare] = useState(false); const [guid, setGuid] = useState(''); - const [isEditMode, setIsEditMode] = useState(false); // 현재 로그인 사용자 정보 로드 const [currentUserId, setCurrentUserId] = useState(''); @@ -66,19 +64,17 @@ export function NoteEditModal({ setDescription(editingItem.description || ''); setShare(editingItem.share || false); setGuid(editingItem.guid || ''); - setIsEditMode(initialEditMode); } else { - // 신규 메모 - 편집 모드로 시작 + // 신규 메모 setPdate(new Date().toISOString().split('T')[0]); setTitle(''); setUid(currentUserId); setDescription(''); setShare(false); setGuid(''); - setIsEditMode(true); } } - }, [isOpen, editingItem, currentUserId, initialEditMode]); + }, [isOpen, editingItem, currentUserId]); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); @@ -94,15 +90,15 @@ export function NoteEditModal({ return createPortal(
-
+
{/* 헤더 */} -
-

+
+

{!editingItem ? '새 메모 작성' : '메모 편집'}

@@ -117,47 +113,37 @@ export function NoteEditModal({
- {isEditMode ? ( - setPdate(e.target.value)} - required - disabled={!canEdit} - className="w-full h-10 bg-white/20 border border-white/30 rounded-lg px-3 text-white text-sm focus:outline-none focus:ring-2 focus:ring-primary-400 disabled:opacity-50 disabled:cursor-not-allowed" - /> - ) : ( -
{pdate}
- )} + setPdate(e.target.value)} + required + disabled={!canEdit} + className="w-full h-10 bg-white/20 border border-white/30 rounded-lg px-3 text-white text-sm focus:outline-none focus:ring-2 focus:ring-primary-400 disabled:opacity-50 disabled:cursor-not-allowed" + />
{/* 작성자 */}
- {isEditMode ? ( - <> - setUid(e.target.value)} - required - disabled={!canEdit || !canChangeUser} - className="w-full h-10 bg-white/20 border border-white/30 rounded-lg px-3 text-white text-sm focus:outline-none focus:ring-2 focus:ring-primary-400 disabled:opacity-50 disabled:cursor-not-allowed" - placeholder="사용자 ID" - /> - {!canChangeUser && ( -

- 관리자만 변경 가능 -

- )} - - ) : ( -
{uid}
+ setUid(e.target.value)} + required + disabled={!canEdit || !canChangeUser} + className="w-full h-10 bg-white/20 border border-white/30 rounded-lg px-3 text-white text-sm focus:outline-none focus:ring-2 focus:ring-primary-400 disabled:opacity-50 disabled:cursor-not-allowed" + placeholder="사용자 ID" + /> + {!canChangeUser && ( +

+ 관리자만 변경 가능 +

)}
@@ -166,33 +152,27 @@ export function NoteEditModal({ - {isEditMode ? ( - <> -
- setShare(e.target.checked)} - disabled={!canEdit || !canChangeShare} - className="w-4 h-4 bg-white/20 border border-white/30 rounded focus:ring-2 focus:ring-primary-400 disabled:opacity-50 disabled:cursor-not-allowed" - /> - -
- {!canChangeShare && ( -

- 본인 메모만 변경 가능 -

- )} - - ) : ( -
{share ? '공유됨' : '비공유'}
+
+ setShare(e.target.checked)} + disabled={!canEdit || !canChangeShare} + className="w-4 h-4 bg-white/20 border border-white/30 rounded focus:ring-2 focus:ring-primary-400 disabled:opacity-50 disabled:cursor-not-allowed" + /> + +
+ {!canChangeShare && ( +

+ 본인 메모만 변경 가능 +

)}
- {!canEdit && isEditMode && ( + {!canEdit && (
타인의 자료는 수정할 수 없습니다.
@@ -204,21 +184,17 @@ export function NoteEditModal({ {/* 제목 */}
- {isEditMode ? ( - setTitle(e.target.value)} - required - disabled={!canEdit} - className="w-full h-10 bg-white/20 border border-white/30 rounded-lg px-3 text-white focus:outline-none focus:ring-2 focus:ring-primary-400 disabled:opacity-50 disabled:cursor-not-allowed" - placeholder="메모 제목을 입력하세요" - /> - ) : ( -
{title}
- )} + setTitle(e.target.value)} + required + disabled={!canEdit} + className="w-full h-10 bg-white/20 border border-white/30 rounded-lg px-3 text-white focus:outline-none focus:ring-2 focus:ring-primary-400 disabled:opacity-50 disabled:cursor-not-allowed" + placeholder="메모 제목을 입력하세요" + />
{/* 내용 */} @@ -226,27 +202,21 @@ export function NoteEditModal({ - {isEditMode ? ( -