diff --git a/solution/frontend/src/pages/LoginPage.tsx b/solution/frontend/src/pages/LoginPage.tsx
index 88a4183..4ff1a0f 100644
--- a/solution/frontend/src/pages/LoginPage.tsx
+++ b/solution/frontend/src/pages/LoginPage.tsx
@@ -1,117 +1,42 @@
-import {useState, type FormEvent} from 'react';
import {Navigate, useLocation, useNavigate} from 'react-router';
-import {LogIn} from 'lucide-react';
-import {login, me, UserRole} from '@/api';
-import {Button} from '@/components/ui/button';
-import {Input} from '@/components/ui/input';
-import {notifyApiError} from '@/lib/notify';
-import {toAuthUser, useAuthStore} from '@/stores/auth';
+import {SignInForm} from '@/features/auth/SignInForm';
+import {useAuthStore} from '@/stores/auth';
export function LoginPage() {
const navigate = useNavigate();
const location = useLocation();
const user = useAuthStore((s) => s.user);
- const signIn = useAuthStore((s) => s.signIn);
-
- const [id, setId] = useState('');
- const [password, setPassword] = useState('');
- const [isSubmitting, setIsSubmitting] = useState(false);
// ★ 기본 도착지를 '/' 로 둔다. 앱마다 홈이 다르고(사장님 → 빌더, 내부 → 사업장 목록)
-// 각 라우터의 '/' 리다이렉트가 이미 그걸 안다. 여기 경로를 박으면 한쪽에서 404 다.
-const from = (location.state as {from?: string} | null)?.from ?? '/';
+ // 각 라우터의 '/' 리다이렉트가 이미 그걸 안다. 여기 경로를 박으면 한쪽에서 404 다.
+ const from = (location.state as {from?: string} | null)?.from ?? '/';
if (user) return
;
- const handleSubmit = async (event: FormEvent) => {
- event.preventDefault();
- setIsSubmitting(true);
- try {
- const res = await login({id, password});
- if (res.result?.success === false) {
- notifyApiError({data: res}, '아이디 또는 비밀번호를 확인해 주세요.');
- return;
- }
- // ★ RemoveNoneResponse 라 성공 응답에서도 토큰 필드가 빠져 올 수 있다.
- // 빈 토큰으로 로그인 상태를 만들면 이후 모든 요청이 401 로 흐른다 — 여기서 끊는다.
- if (!res.access_token || !res.refresh_token) {
- notifyApiError({data: res}, '로그인 응답에 토큰이 없습니다.');
- return;
- }
- const tokens = {accessToken: res.access_token, refreshToken: res.refresh_token};
-
- // 토큰을 먼저 심어야 뒤이은 me() 가 Authorization 을 달고 나간다.
- signIn(tokens, {userId: '', id, role: UserRole.USER});
-
- const meRes = await me();
- // 신원이 안 왔으면 방금 심은 임시 사용자를 그대로 둔다 — 토큰은 유효하므로 화면은 진행시킨다.
- if (meRes.user_id && meRes.id) signIn(tokens, toAuthUser(meRes));
- navigate(from, {replace: true});
- } catch (error) {
- notifyApiError(error, '로그인에 실패했습니다.');
- } finally {
- setIsSubmitting(false);
- }
- };
-
return (
);
}