diff --git a/frontend/src/pages/Mail.tsx b/frontend/src/pages/Mail.tsx new file mode 100644 index 00000000..d9e1c609 --- /dev/null +++ b/frontend/src/pages/Mail.tsx @@ -0,0 +1,91 @@ +import { useEffect, useCallback } from 'react' +import { mailApi } from '../api/mailApi' +import { useMailStore } from '../store/mailStore' +import FolderTree from '../components/FolderTree' +import MailList from '../components/MailList' +import MailView from '../components/MailView' +import Compose from '../components/Compose' + +export default function Mail() { + const { username, displayName, currentFolder, searchQuery, + setFolders, setMessages, setLoading, composeOpen, openCompose, logout } = useMailStore() + + const loadFolders = useCallback(async () => { + try { + const data = await mailApi.folders() + setFolders(Array.isArray(data) ? data : []) + } catch { /* 폴더 오류 무시 */ } + }, [setFolders]) + + const loadMessages = useCallback(async (page = 1) => { + setLoading(true) + try { + const data = await mailApi.messages(currentFolder, page, searchQuery || undefined) + setMessages(data.messages || [], data.total || 0, page) + } catch { setMessages([], 0, 1) } + finally { setLoading(false) } + }, [currentFolder, searchQuery, setMessages, setLoading]) + + useEffect(() => { loadFolders() }, [loadFolders]) + useEffect(() => { loadMessages(1) }, [currentFolder, searchQuery]) + + // 30초 폴링 + useEffect(() => { + const id = setInterval(() => { loadFolders(); loadMessages(1) }, 30000) + return () => clearInterval(id) + }, [loadFolders, loadMessages]) + + return ( +
+ {/* Header */} +
+
+ + 지오정보기술 메일 +
+
+ +
+
+ + + {displayName || username} + +
+
+ + {/* Body */} +
+ +
+ loadMessages(1)} /> +
+
+ +
+
+ + {composeOpen && } +
+ ) +} + +function SearchBar() { + const { searchQuery, setSearchQuery } = useMailStore() + return ( +
+ 🔍 + setSearchQuery(e.target.value)} + onKeyDown={e => { if (e.key === 'Escape') setSearchQuery('') }} + /> + {searchQuery && ( + + )} +
+ ) +}