[RAPID-micro] 메일관리 UX 개선: 비밀번호 토글, 검색 빈 결과, 이메일→사용자명 자동완성

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-01 14:45:59 +09:00
parent e1d396bec3
commit e31cfba014

View File

@@ -55,6 +55,8 @@ import {
FolderOpen,
Send,
Download,
Eye,
EyeOff,
} from "lucide-react";
import DOMPurify from "isomorphic-dompurify";
import {
@@ -128,6 +130,7 @@ export default function ImapMailPage() {
const [composeSending, setComposeSending] = useState(false);
const [pendingDeleteMail, setPendingDeleteMail] = useState<ReceivedMail | null>(null);
const [pendingDeleteAccount, setPendingDeleteAccount] = useState<UserMailAccount | null>(null);
const [showPassword, setShowPassword] = useState(false);
const detailCacheRef = useRef<Map<string, MailDetail>>(new Map());
const prefetchingRef = useRef<Set<string>>(new Set());
@@ -412,6 +415,7 @@ export default function ImapMailPage() {
setEditingAccount(null);
setForm(DEFAULT_FORM);
setTestResult(null);
setShowPassword(false);
setShowDialog(true);
}
@@ -428,6 +432,7 @@ export default function ImapMailPage() {
password: "",
});
setTestResult(null);
setShowPassword(false);
setShowDialog(true);
}
@@ -661,7 +666,7 @@ export default function ImapMailPage() {
) : filteredMails.length === 0 ? (
<div className="flex flex-col items-center justify-center h-full text-muted-foreground gap-2">
<Inbox className="h-8 w-8 opacity-30" />
<p className="text-sm"> </p>
<p className="text-sm">{searchTerm ? `"${searchTerm}" 검색 결과가 없습니다` : "메일이 없습니다"}</p>
</div>
) : (
<>
@@ -901,7 +906,7 @@ export default function ImapMailPage() {
<Input
type="email"
value={form.email}
onChange={(e) => setForm((p) => ({ ...p, email: e.target.value }))}
onChange={(e) => setForm((p) => ({ ...p, email: e.target.value, username: e.target.value }))}
placeholder="user@example.com"
/>
</div>
@@ -937,12 +942,22 @@ export default function ImapMailPage() {
</div>
<div className="space-y-1">
<Label className="text-xs"> {editingAccount && "(변경 시에만 입력)"}</Label>
<Input
type="password"
value={form.password}
onChange={(e) => setForm((p) => ({ ...p, password: e.target.value }))}
placeholder="••••••••"
/>
<div className="relative">
<Input
type={showPassword ? "text" : "password"}
value={form.password}
onChange={(e) => setForm((p) => ({ ...p, password: e.target.value }))}
placeholder="••••••••"
className="pr-9"
/>
<button
type="button"
className="absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground"
onClick={() => setShowPassword((v) => !v)}
>
{showPassword ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
</button>
</div>
</div>
{editingAccount && (
<div>