diff --git a/app/login/page.tsx b/app/login/page.tsx index 715ed38..0956d4e 100644 --- a/app/login/page.tsx +++ b/app/login/page.tsx @@ -1,84 +1,253 @@ +"use client"; + import Link from 'next/link'; +import Image from 'next/image'; +import { useState, useEffect } from 'react'; +import { useRouter } from 'next/navigation'; +import logo from '../logo.svg'; + +const checkIcon = "http://localhost:3845/assets/68720b08a673d8b68ae6482d642eeab286c9462b.svg"; + +type CheckboxProps = { + checked: boolean; + onChange: () => void; + label: string; +}; + +function Checkbox({ checked, onChange, label }: CheckboxProps) { + return ( +
+ + {label} +
+ ); +} export default function LoginPage() { + const router = useRouter(); + const [username, setUsername] = useState(''); + const [password, setPassword] = useState(''); + const [rememberId, setRememberId] = useState(false); + const [autoLogin, setAutoLogin] = useState(false); + const [usernameError, setUsernameError] = useState(''); + const [passwordError, setPasswordError] = useState(''); + const [showErrorPopup, setShowErrorPopup] = useState(false); + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + setUsernameError(''); + setPasswordError(''); + + // 아이디와 비밀번호가 비어있는지 확인 + const isUsernameEmpty = !username.trim(); + const isPasswordEmpty = !password.trim(); + + if (isUsernameEmpty) { + setUsernameError('이메일을 입력해 주세요.'); + } + + if (isPasswordEmpty) { + setPasswordError('비밀번호를 입력해 주세요.'); + } + + // 둘 중 하나라도 비어있으면 검증 중단 + if (isUsernameEmpty || isPasswordEmpty) { + return; + } + + // 아이디와 비밀번호 검증 + if (username === 'admin' && password === '1234') { + // 로그인 성공 + localStorage.setItem('isLoggedIn', 'true'); + // 아이디 기억하기 체크 시 아이디 저장 + if (rememberId) { + localStorage.setItem('rememberedUsername', username); + } else { + localStorage.removeItem('rememberedUsername'); + } + // 루트 경로로 이동 (루트 페이지에서 로그인 상태를 확인하여 메인 페이지 표시) + window.location.href = '/'; + } else { + // 로그인 실패 - 팝업 표시 + setShowErrorPopup(true); + setUsernameError('아이디 또는 비밀번호가 올바르지 않습니다.'); + setPasswordError('아이디 또는 비밀번호가 올바르지 않습니다.'); + } + }; + + // 아이디 기억하기 기능 - 컴포넌트 마운트 시 저장된 아이디 불러오기 + useEffect(() => { + const rememberedUsername = localStorage.getItem('rememberedUsername'); + if (rememberedUsername) { + setUsername(rememberedUsername); + setRememberId(true); + } + }, []); + return ( -
+
{/* 상단 로고 */}
-

Logo

+ Logo
{/* 로그인 폼 */} -
+ {/* 아이디 입력폼 */} -
- - +
+
+ { + setUsername(e.target.value); + setUsernameError(''); + }} + className={`w-full px-4 py-2.5 border rounded-[8px] focus:outline-none ${usernameError + ? 'border-[#e61a1a] border-solid' + : 'border-gray-300 focus:ring-2 focus:ring-blue-500' + }`} + placeholder="아이디(이메일)" + /> + {usernameError && ( +

+ {usernameError} +

+ )} +
{/* 비밀번호 입력폼 */} -
- - +
+
+ { + setPassword(e.target.value); + setPasswordError(''); + }} + className={`w-full px-4 py-2.5 border rounded-[8px] focus:outline-none ${passwordError + ? 'border-[#e61a1a] border-solid' + : 'border-gray-300 focus:ring-2 focus:ring-blue-500' + }`} + placeholder="비밀번호를 입력하세요" + /> + {passwordError && ( +

+ {passwordError} +

+ )} +
{/* 체크박스 */} -
- - +
+ setRememberId(!rememberId)} + label="아이디 기억하기" + /> + setAutoLogin(!autoLogin)} + label="자동 로그인" + />
{/* 로그인 버튼 */} - +
+ +
{/* 하단 링크 버튼들 */} -
+
회원가입 + +
{/* 카피라이트 */} -
+
© 2024 XR LMS. All rights reserved.
+ + {/* 에러 팝업 */} + {showErrorPopup && ( +
+
+
+
+

아이디 또는 비밀번호가 일치하지 않아요.

+

확인 후 다시 시도해 주세요.

+
+
+
+ +
+
+
+ )}
); } diff --git a/app/logo.svg b/app/logo.svg new file mode 100644 index 0000000..b5adb10 --- /dev/null +++ b/app/logo.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/app/page.tsx b/app/page.tsx index d7dacaa..e637e42 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,164 +1,47 @@ "use client"; -import Link from "next/link"; +import { useEffect, useState } from 'react'; +import { useRouter } from 'next/navigation'; +import LoginPage from './login/page'; -// 이미지 상수 -const imgLogo = "http://localhost:3845/assets/89fda8e949171025b1232bae70fc9d442e4e70c8.png"; +export default function HomePage() { + const router = useRouter(); + const [isLoggedIn, setIsLoggedIn] = useState(false); + const [isLoading, setIsLoading] = useState(true); -type CheckboxProps = { - className?: string; - status?: "Inactive" | "Focused" | "Disabled"; -}; + useEffect(() => { + // 로그인 상태 확인 + const loginStatus = localStorage.getItem('isLoggedIn') === 'true'; + setIsLoggedIn(loginStatus); + setIsLoading(false); + }, []); -function Checkbox({ className, status = "Inactive" }: CheckboxProps) { + if (isLoading) { + return null; // 로딩 중 + } + + // 로그인되지 않았으면 로그인 페이지 표시 + if (!isLoggedIn) { + return ; + } + + // 로그인되었으면 메인 페이지 표시 return ( -
-
-
- ); -} +
+
+

메인 페이지

+

로그인 후 메인 페이지입니다.

-export default function LoginPage() { - return ( -
- {/* 로고 */} -
-
- Logo -
-
- - {/* 콘텐츠 영역 */} -
- {/* 입력 폼 영역 */} -
- {/* 아이디 입력 필드 */} -
-
-
-
- -
-
-
-
- - {/* 비밀번호 입력 필드 */} -
-
-
-
- -
-
-
-
- - {/* 체크박스 영역 */} -
-
- -

- 아이디 기억하기 -

-
-
- -

- 자동 로그인 -

-
-
-
- - {/* 로그인 버튼 */} -
- -
-
- - {/* 하단 링크 영역 */} -
- { + localStorage.removeItem('isLoggedIn'); + router.push('/'); + }} + className="mt-4 px-4 py-2 bg-red-500 text-white rounded-md hover:bg-red-600" > -

- 회원가입 -

- -
-

- | -

-
- -
-

- | -

-
- -
- - {/* 카피라이트 */} -
-

- Copyright ⓒ 2025 XL LMS. All rights reserved -

); diff --git a/next.config.ts b/next.config.ts index e9ffa30..b60527b 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,7 +1,9 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { - /* config options here */ + images: { + unoptimized: false, + }, }; export default nextConfig; diff --git a/public/Divider.svg b/public/Divider.svg new file mode 100644 index 0000000..54d4313 --- /dev/null +++ b/public/Divider.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/logo.png b/public/logo.png deleted file mode 100644 index 4add0d7..0000000 Binary files a/public/logo.png and /dev/null differ diff --git a/public/logo.svg b/public/logo.svg new file mode 100644 index 0000000..b5adb10 --- /dev/null +++ b/public/logo.svg @@ -0,0 +1,9 @@ + + + + + + + + +