find-id 디자인 수정중1
This commit is contained in:
@@ -118,7 +118,7 @@ export default function NavBar() {
|
||||
<Link href="/menu/account" className="px-4 py-2 text-[16px] font-semibold text-white">
|
||||
내 정보
|
||||
</Link>
|
||||
<Link href="/login" className="px-4 py-2 text-[16px] font-semibold text-white">
|
||||
<Link href="/login" className="px-4 py-2 text-[16px] font-semibold text-white ">
|
||||
로그아웃
|
||||
</Link>
|
||||
</>
|
||||
@@ -152,14 +152,23 @@ export default function NavBar() {
|
||||
<Link
|
||||
role="menuitem"
|
||||
href="/menu/account"
|
||||
className="block w-full h-10 px-2 rounded-lg text-left text-[#333C47] text-[16px] font-medium leading-normal hover:bg-[rgba(236,240,255,0.5)] focus:bg-[rgba(236,240,255,0.5)] outline-none"
|
||||
className="flex items-center w-[136px] h-10 px-2 rounded-lg text-left text-[#333C47] text-[16px] font-medium leading-normal hover:bg-[rgba(236,240,255,0.5)] focus:bg-[rgba(236,240,255,0.5)] outline-nonq"
|
||||
onClick={() => setIsUserMenuOpen(false)}
|
||||
>
|
||||
내 정보 수정
|
||||
</Link>
|
||||
<button
|
||||
role="menuitem"
|
||||
className="w-full h-10 px-2 rounded-lg text-left text-[#333C47] text-[16px] font-medium leading-normal hover:bg-[rgba(236,240,255,0.5)] focus:bg-[rgba(236,240,255,0.5)] outline-none"
|
||||
className="flex items-center w-[136px] h-10 px-2 rounded-lg text-left text-[#333C47] text-[16px] font-medium leading-normal hover:bg-[rgba(236,240,255,0.5)] focus:bg-[rgba(236,240,255,0.5)] outline-none"
|
||||
onClick={() => {
|
||||
// 로컬 스토리지에서 토큰 제거
|
||||
localStorage.removeItem('token');
|
||||
localStorage.removeItem('user');
|
||||
// 쿠키에서 토큰 제거 (미들웨어에서 확인하므로)
|
||||
document.cookie = 'token=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
|
||||
// 로그인 페이지로 리다이렉트
|
||||
window.location.href = '/login';
|
||||
}}
|
||||
>
|
||||
로그아웃
|
||||
</button>
|
||||
|
||||
@@ -30,7 +30,7 @@ export default function FindIdPage() {
|
||||
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
|
||||
e.preventDefault();
|
||||
if (!validateAll()) return;
|
||||
|
||||
|
||||
try {
|
||||
const response = await fetch('https://hrdi.coconutmeet.net/auth/find-id', {
|
||||
method: 'POST',
|
||||
@@ -87,7 +87,7 @@ export default function FindIdPage() {
|
||||
/>
|
||||
|
||||
<div className="rounded-xl bg-white max-w-[560px] px-[40px] w-full relative">
|
||||
|
||||
|
||||
<div className="my-15 flex flex-col items-center">
|
||||
<div className="text-[24px] font-extrabold leading-[150%] text-neutral-700">
|
||||
아이디 찾기
|
||||
@@ -111,7 +111,7 @@ export default function FindIdPage() {
|
||||
onFocus={() => setFocused((p) => ({ ...p, name: true }))}
|
||||
onBlur={() => setFocused((p) => ({ ...p, name: false }))}
|
||||
placeholder="이름을 입력해 주세요."
|
||||
className="h-[40px] px-[12px] py-[7px] w-full rounded-[8px] border border-neutral-40 focus:outline-none focus:border-neutral-700 text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px]"
|
||||
className="h-[40px] px-[12px] py-[7px] w-full rounded-[8px] mt-3 border border-neutral-40 focus:outline-none focus:border-neutral-700 text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px]"
|
||||
/>
|
||||
{name.trim().length > 0 && focused.name && (
|
||||
<button
|
||||
@@ -144,7 +144,7 @@ export default function FindIdPage() {
|
||||
onFocus={() => setFocused((p) => ({ ...p, phone: true }))}
|
||||
onBlur={() => setFocused((p) => ({ ...p, phone: false }))}
|
||||
placeholder="-없이 입력해 주세요."
|
||||
className="h-[40px] px-[12px] py-[7px] w-full rounded-[8px] border border-neutral-40 focus:outline-none focus:border-neutral-700 text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px]"
|
||||
className="h-[40px] px-[12px] py-[7px] w-full rounded-[8px] border mt-3 border-neutral-40 focus:outline-none focus:border-neutral-700 text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px]"
|
||||
/>
|
||||
{phone.trim().length > 0 && focused.phone && (
|
||||
<button
|
||||
@@ -164,7 +164,7 @@ export default function FindIdPage() {
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className={`h-[40px] w-full rounded-[12px] text-[18px] font-semibold text-white ${canSubmit ? "bg-active-button" : "bg-inactive-button"} cursor-pointer`}>
|
||||
className={`h-[56px] w-full rounded-[12px] text-[18px] mt-[30px] font-semibold text-white hover:bg-[#1F2B91] ${canSubmit ? "bg-active-button" : "bg-inactive-button"} cursor-pointer`}>
|
||||
다음
|
||||
</button>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
import MainLogo from "@/app/svgs/mainlogosvg"
|
||||
@@ -22,9 +22,43 @@ export default function LoginPage() {
|
||||
const [idError, setIdError] = useState("");
|
||||
const [passwordError, setPasswordError] = useState("");
|
||||
|
||||
// 컴포넌트 마운트 시 저장된 아이디 불러오기
|
||||
useEffect(() => {
|
||||
const savedId = localStorage.getItem('savedUserId');
|
||||
if (savedId) {
|
||||
setUserId(savedId);
|
||||
setRememberId(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// 아이디 기억하기 상태나 아이디가 변경될 때마다 저장 처리
|
||||
useEffect(() => {
|
||||
if (rememberId && userId.trim()) {
|
||||
localStorage.setItem('savedUserId', userId);
|
||||
} else if (!rememberId) {
|
||||
localStorage.removeItem('savedUserId');
|
||||
}
|
||||
}, [rememberId, userId]);
|
||||
|
||||
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
|
||||
e.preventDefault();
|
||||
if (userId.trim().length === 0 || password.trim().length === 0) {
|
||||
|
||||
// 에러 초기화
|
||||
setIdError("");
|
||||
setPasswordError("");
|
||||
|
||||
// 입력 검증
|
||||
let hasError = false;
|
||||
if (userId.trim().length === 0) {
|
||||
setIdError("아이디를 입력해 주세요.");
|
||||
hasError = true;
|
||||
}
|
||||
if (password.trim().length === 0) {
|
||||
setPasswordError("비밀번호를 입력해 주세요.");
|
||||
hasError = true;
|
||||
}
|
||||
|
||||
if (hasError) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -74,6 +108,7 @@ export default function LoginPage() {
|
||||
// 토큰이 없어도 로그인은 성공했으므로 진행
|
||||
}
|
||||
|
||||
|
||||
// 리다이렉트 경로 확인
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
const redirectPath = searchParams.get('redirect') || '/';
|
||||
@@ -112,7 +147,7 @@ export default function LoginPage() {
|
||||
</div>
|
||||
|
||||
{/* 폼 */}
|
||||
<form onSubmit={handleSubmit} className="space-y-5">
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
<div className="space-y-4">
|
||||
{/* 아이디 */}
|
||||
<div className="relative">
|
||||
@@ -123,17 +158,14 @@ export default function LoginPage() {
|
||||
id="userId"
|
||||
name="userId"
|
||||
value={userId}
|
||||
onChange={(e) => setUserId(e.target.value)}
|
||||
onChange={(e) => {
|
||||
setUserId(e.target.value);
|
||||
if (idError) setIdError("");
|
||||
}}
|
||||
onFocus={() => setIsUserIdFocused(true)}
|
||||
onBlur={() => setIsUserIdFocused(false)}
|
||||
placeholder="아이디 (이메일)"
|
||||
className="
|
||||
h-[40px] px-[12px] py-[7px] w-full rounded-[8px] border border-neutral-40
|
||||
focus:outline-none focus:ring-0 focus:ring-offset-0 focus:shadow-none
|
||||
focus:appearance-none focus:border-neutral-700
|
||||
text-[18px] text-neutral-700 font-normal leading-[150%] placeholder:text-input-placeholder-text
|
||||
pr-[40px]
|
||||
"
|
||||
placeholder="아이디(이메일)"
|
||||
className={`h-[56px] px-[12px] py-[7px] w-full rounded-[8px] border focus:outline-none focus:ring-0 focus:ring-offset-0 focus:shadow-none focus:appearance-none text-[18px] text-neutral-700 font-normal leading-[150%] placeholder:text-input-placeholder-text pr-[40px] ${idError ? 'border-error' : 'border-neutral-40 focus:border-neutral-700'}`}
|
||||
/>
|
||||
{userId.trim().length > 0 && isUserIdFocused && (
|
||||
<button
|
||||
@@ -149,6 +181,7 @@ export default function LoginPage() {
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{idError && <p className="text-error text-[13px] leading-tight mt-[10px]">{idError}</p>}
|
||||
{/* 비밀번호 */}
|
||||
<div className="relative">
|
||||
<label htmlFor="password" className="sr-only">
|
||||
@@ -159,17 +192,14 @@ export default function LoginPage() {
|
||||
name="password"
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
onChange={(e) => {
|
||||
setPassword(e.target.value);
|
||||
if (passwordError) setPasswordError("");
|
||||
}}
|
||||
onFocus={() => setIsPasswordFocused(true)}
|
||||
onBlur={() => setIsPasswordFocused(false)}
|
||||
placeholder="비밀번호"
|
||||
className="
|
||||
h-[40px] px-[12px] py-[7px] rounded-[8px] w-full border border-neutral-40
|
||||
focus:outline-none focus:ring-0 focus:ring-offset-0 focus:shadow-none
|
||||
focus:appearance-none focus:border-neutral-700
|
||||
text-[18px] text-neutral-700 font-normal leading-[150%] placeholder:text-input-placeholder-text
|
||||
pr-[40px]
|
||||
"
|
||||
placeholder="비밀번호 입력"
|
||||
className={`h-[56px] px-[12px] py-[7px] rounded-[8px] w-full border focus:outline-none focus:ring-0 focus:ring-offset-0 focus:shadow-none focus:appearance-none text-[18px] text-neutral-700 font-normal leading-[150%] placeholder:text-input-placeholder-text pr-[40px] ${passwordError ? 'border-error' : 'border-neutral-40 focus:border-neutral-700'}`}
|
||||
/>
|
||||
{password.trim().length > 0 && isPasswordFocused && (
|
||||
<button
|
||||
@@ -185,6 +215,7 @@ export default function LoginPage() {
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{passwordError && <p className="text-error text-[13px] leading-tight mt-[4px]">{passwordError}</p>}
|
||||
</div>
|
||||
|
||||
{/* 체크박스들 */}
|
||||
@@ -222,7 +253,7 @@ export default function LoginPage() {
|
||||
{/* 로그인 버튼 */}
|
||||
<button
|
||||
type="submit"
|
||||
className={`h-[40px] w-full rounded-lg text-[16px] font-semibold text-white transition-opacity cursor-pointer mb-3 ${userId.trim().length > 0 && password.trim().length > 0 ? "bg-active-button" : "bg-inactive-button"}`}
|
||||
className={`h-[56px] w-full rounded-lg text-[16px] font-semibold text-white transition-opacity cursor-pointer mb-3 hover:bg-[#1F2B91] ${userId.trim().length > 0 && password.trim().length > 0 ? "bg-active-button" : "bg-inactive-button"}`}
|
||||
>
|
||||
로그인
|
||||
</button>
|
||||
|
||||
@@ -290,7 +290,7 @@ export default function RegisterForm({ onOpenDone, onOpenCodeError }: RegisterFo
|
||||
onFocus={() => setFocused((p) => ({ ...p, name: true }))}
|
||||
onBlur={() => setFocused((p) => ({ ...p, name: false }))}
|
||||
placeholder="이름을 입력해 주세요."
|
||||
className="h-[40px] px-[12px] py-[7px] w-full rounded-[8px] border border-neutral-40 focus:outline-none focus:border-neutral-700 text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px]"
|
||||
className={`h-[40px] px-[12px] py-[7px] w-full rounded-[8px] border focus:outline-none text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px] ${errors.name ? 'border-error' : 'border-neutral-40 focus:border-neutral-700'}`}
|
||||
/>
|
||||
{name.trim().length > 0 && focused.name && (
|
||||
<button
|
||||
@@ -303,7 +303,7 @@ export default function RegisterForm({ onOpenDone, onOpenCodeError }: RegisterFo
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{errors.name && <p className="text-error text-[13px] leading-tight">{errors.name}</p>}
|
||||
{errors.name && <p className="text-error text-[13px] leading-tight mt-[10px]">{errors.name}</p>}
|
||||
</div>
|
||||
|
||||
{/* 휴대폰 번호 */}
|
||||
@@ -320,7 +320,7 @@ export default function RegisterForm({ onOpenDone, onOpenCodeError }: RegisterFo
|
||||
onChange={(e) => setPhone(e.target.value.replace(/[^0-9]/g, ""))}
|
||||
onFocus={() => setFocused((p) => ({ ...p, phone: true }))}
|
||||
onBlur={() => setFocused((p) => ({ ...p, phone: false }))}
|
||||
className="h-[40px] px-[12px] py-[7px] w-full rounded-[8px] border border-neutral-40 focus:outline-none focus:border-neutral-700 text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px]"
|
||||
className={`h-[40px] px-[12px] py-[7px] w-full rounded-[8px] border focus:outline-none text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px] ${errors.phone ? 'border-error' : 'border-neutral-40 focus:border-neutral-700'}`}
|
||||
/>
|
||||
{phone.trim().length > 0 && focused.phone && (
|
||||
<button
|
||||
@@ -333,7 +333,7 @@ export default function RegisterForm({ onOpenDone, onOpenCodeError }: RegisterFo
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{errors.phone && <p className="text-error text-[13px] leading-tight">{errors.phone}</p>}
|
||||
{errors.phone && <p className="text-error text-[13px] leading-tight mt-[10px]">{errors.phone}</p>}
|
||||
</div>
|
||||
|
||||
{/* 아이디(이메일) + 인증번호 전송 */}
|
||||
@@ -361,7 +361,7 @@ export default function RegisterForm({ onOpenDone, onOpenCodeError }: RegisterFo
|
||||
onBlur={() => setFocused((p) => ({ ...p, email: false }))}
|
||||
placeholder="이메일을 입력해 주세요."
|
||||
disabled={emailCodeVerified}
|
||||
className="h-[40px] px-[12px] py-[7px] w-full rounded-[8px] border border-neutral-40 focus:outline-none focus:border-neutral-700 text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px] disabled:bg-gray-100 disabled:cursor-not-allowed"
|
||||
className={`h-[40px] px-[12px] py-[7px] w-full rounded-[8px] border focus:outline-none text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px] disabled:bg-gray-100 disabled:cursor-not-allowed ${emailCodeVerified ? '' : (errors.email ? 'border-error' : 'border-neutral-40 focus:border-neutral-700')}`}
|
||||
/>
|
||||
{email.trim().length > 0 && focused.email && !emailCodeVerified && (
|
||||
<button
|
||||
@@ -383,7 +383,7 @@ export default function RegisterForm({ onOpenDone, onOpenCodeError }: RegisterFo
|
||||
{emailCodeSent && !emailCodeVerified ? "인증번호 재전송" : "인증번호 전송"}
|
||||
</button>
|
||||
</div>
|
||||
{errors.email && <p className="text-error text-[13px] leading-tight">{errors.email}</p>}
|
||||
{errors.email && <p className="text-error text-[13px] leading-tight mt-[10px]">{errors.email}</p>}
|
||||
{emailCodeSent && (
|
||||
<div className="space-y-2" aria-expanded={emailCodeSent}>
|
||||
<label htmlFor="emailCode" className="sr-only">인증번호</label>
|
||||
@@ -452,7 +452,7 @@ export default function RegisterForm({ onOpenDone, onOpenCodeError }: RegisterFo
|
||||
onFocus={() => setFocused((p) => ({ ...p, password: true }))}
|
||||
onBlur={() => setFocused((p) => ({ ...p, password: false }))}
|
||||
placeholder="8~16자의 영문/숫자/특수문자를 조합해서 입력해 주세요."
|
||||
className="h-[40px] px-[12px] py-[7px] w-full rounded-[8px] border border-neutral-40 focus:outline-none focus:border-neutral-700 text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px]"
|
||||
className={`h-[40px] px-[12px] py-[7px] w-full rounded-[8px] border focus:outline-none text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px] ${errors.password ? 'border-error' : 'border-neutral-40 focus:border-neutral-700'}`}
|
||||
/>
|
||||
{password.trim().length > 0 && focused.password && (
|
||||
<button
|
||||
@@ -465,7 +465,7 @@ export default function RegisterForm({ onOpenDone, onOpenCodeError }: RegisterFo
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{errors.password && <p className="text-error text-[13px] leading-tight">{errors.password}</p>}
|
||||
{errors.password && <p className="text-error text-[13px] leading-tight mt-[10px]">{errors.password}</p>}
|
||||
</div>
|
||||
|
||||
{/* 비밀번호 확인 */}
|
||||
@@ -481,7 +481,7 @@ export default function RegisterForm({ onOpenDone, onOpenCodeError }: RegisterFo
|
||||
onFocus={() => setFocused((p) => ({ ...p, passwordConfirm: true }))}
|
||||
onBlur={() => setFocused((p) => ({ ...p, passwordConfirm: false }))}
|
||||
placeholder="비밀번호를 다시 입력해 주세요."
|
||||
className="h-[40px] px-[12px] py-[7px] w-full rounded-[8px] border border-neutral-40 focus:outline-none focus:border-neutral-700 text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px]"
|
||||
className={`h-[40px] px-[12px] py-[7px] w-full rounded-[8px] border focus:outline-none text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px] ${errors.passwordConfirm ? 'border-error' : 'border-neutral-40 focus:border-neutral-700'}`}
|
||||
/>
|
||||
{passwordConfirm.trim().length > 0 && focused.passwordConfirm && (
|
||||
<button
|
||||
@@ -494,7 +494,7 @@ export default function RegisterForm({ onOpenDone, onOpenCodeError }: RegisterFo
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{errors.passwordConfirm && <p className="text-error text-[13px] leading-tight">{errors.passwordConfirm}</p>}
|
||||
{errors.passwordConfirm && <p className="text-error text-[13px] leading-tight mt-[10px]">{errors.passwordConfirm}</p>}
|
||||
</div>
|
||||
|
||||
{/* 성별 */}
|
||||
@@ -530,7 +530,7 @@ export default function RegisterForm({ onOpenDone, onOpenCodeError }: RegisterFo
|
||||
여성
|
||||
</label>
|
||||
</div>
|
||||
{errors.gender && <p className="text-error text-[13px] leading-tight">{errors.gender}</p>}
|
||||
{errors.gender && <p className="text-error text-[13px] leading-tight mt-[10px]">{errors.gender}</p>}
|
||||
</div>
|
||||
|
||||
{/* 생년월일 */}
|
||||
@@ -561,7 +561,7 @@ export default function RegisterForm({ onOpenDone, onOpenCodeError }: RegisterFo
|
||||
}
|
||||
}}
|
||||
placeholder="생년월일"
|
||||
className="h-[40px] px-[12px] w-full rounded-[8px] border border-neutral-40 focus:outline-none focus:border-neutral-700 text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px] flex items-center"
|
||||
className={`h-[40px] px-[12px] w-full rounded-[8px] border focus:outline-none text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px] flex items-center ${errors.birthdate ? 'border-error' : 'border-neutral-40 focus:border-neutral-700'}`}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
@@ -586,7 +586,7 @@ export default function RegisterForm({ onOpenDone, onOpenCodeError }: RegisterFo
|
||||
className="absolute right-50 top-1 h-full w-[20px] opacity-0 cursor-pointer"
|
||||
/>
|
||||
</div>
|
||||
{errors.birthdate && <p className="text-error text-[13px] leading-tight">{errors.birthdate}</p>}
|
||||
{errors.birthdate && <p className="text-error text-[13px] leading-tight mt-[10px]">{errors.birthdate}</p>}
|
||||
</div>
|
||||
|
||||
{/* 약관 동의 */}
|
||||
@@ -640,11 +640,11 @@ export default function RegisterForm({ onOpenDone, onOpenCodeError }: RegisterFo
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
{errors.agreements && <p className="text-error text-[13px] leading-tight">{errors.agreements}</p>}
|
||||
{errors.agreements && <p className="text-error text-[13px] leading-tight mt-[10px]">{errors.agreements}</p>}
|
||||
</div>
|
||||
|
||||
{/* 액션 버튼 */}
|
||||
<div className="flex gap-3">
|
||||
<div className="flex gap-3 pt-[60px]">
|
||||
<Link
|
||||
href="/login"
|
||||
className="h-[40px] flex-1 rounded-[12px] bg-[#f1f3f5] text-[18px] font-semibold text-center flex items-center justify-center text-basic-text"
|
||||
|
||||
Reference in New Issue
Block a user