로그인페이지
This commit is contained in:
9
memo.txt
Normal file
9
memo.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
font-100 : font-thin
|
||||
font-200 : font-extralight
|
||||
font-300 : font-light
|
||||
font-400 : font-normal
|
||||
font-500 : font-medium
|
||||
font-600 : font-semibold
|
||||
font-700 : font-bold
|
||||
font-800 : font-extrabold
|
||||
font-900 : font-black
|
||||
@@ -12,21 +12,20 @@ export default function LoginPage() {
|
||||
|
||||
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
|
||||
e.preventDefault();
|
||||
// TODO: 실제 인증 연동 시 이곳에서 처리
|
||||
// 현재는 UI만 구현
|
||||
/* todo */
|
||||
console.log({ userId, password, rememberId, autoLogin });
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen w-full flex flex-col items-center justify-center">
|
||||
{/* 카드 컨테이너 */}
|
||||
<div className="w-[480px] rounded-xl bg-white p-8 ">
|
||||
<div className="min-h-screen w-full flex flex-col items-center justify-between">
|
||||
<div></div>
|
||||
<div className="rounded-xl bg-white max-w-[560px] px-[40px] w-full">
|
||||
{/* 로고 영역 */}
|
||||
<div className="mb-10 flex flex-col items-center">
|
||||
<div className="my-10 flex flex-col items-center">
|
||||
<div className="mb-[7px]">
|
||||
<MainLogo/>
|
||||
</div>
|
||||
<div className="text-[28.8px] font-[800] leading-[145%] text-neutral-700" >
|
||||
<div className="text-[28.8px] font-extrabold leading-[145%] text-neutral-700" >
|
||||
XR LMS
|
||||
</div>
|
||||
</div>
|
||||
@@ -45,13 +44,12 @@ export default function LoginPage() {
|
||||
value={userId}
|
||||
onChange={(e) => setUserId(e.target.value)}
|
||||
placeholder="아이디 (이메일)"
|
||||
className="w-[480px] h-[56px] px-[12px] py-[7px] rounded-[8px] border border-neutral-40
|
||||
|
||||
className="
|
||||
h-[56px] 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-[400] leading-[150%] placeholder:text-input-placeholder-text "
|
||||
|
||||
text-[18px] text-neutral-700 font-normal leading-[150%] placeholder:text-input-placeholder-text
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
{/* 비밀번호 */}
|
||||
@@ -66,38 +64,35 @@ export default function LoginPage() {
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
placeholder="비밀번호"
|
||||
className="h-14 w-full rounded-lg border px-4 text-[15px] outline-none transition-shadow"
|
||||
className="
|
||||
h-[56px] 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
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 체크박스들 */}
|
||||
<div className="flex items-center justify-start gap-6">
|
||||
<label className="flex cursor-pointer select-none items-center gap-2 text-[15px]"
|
||||
style={{ color: "var(--color-basic-text)" }}>
|
||||
<label className="flex cursor-pointer select-none items-center gap-2 text-[15px] font-normal text-basic-text">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={rememberId}
|
||||
onChange={(e) => setRememberId(e.target.checked)}
|
||||
className="h-[18px] w-[18px] cursor-pointer rounded border"
|
||||
style={{
|
||||
accentColor: "var(--color-input-border-select)",
|
||||
borderColor: "var(--color-inactive-checkbox)",
|
||||
}}
|
||||
className="h-[18px] w-[18px] cursor-pointer rounded border
|
||||
accent-input-border-select border-inactive-checkbox"
|
||||
/>
|
||||
아이디 기억하기
|
||||
</label>
|
||||
<label className="flex cursor-pointer select-none items-center gap-2 text-[15px]"
|
||||
style={{ color: "var(--color-basic-text)" }}>
|
||||
<label className="flex cursor-pointer select-none items-center gap-2 text-[15px] font-normal text-basic-text">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={autoLogin}
|
||||
onChange={(e) => setAutoLogin(e.target.checked)}
|
||||
className="h-[18px] w-[18px] cursor-pointer rounded border"
|
||||
style={{
|
||||
accentColor: "var(--color-input-border-select)",
|
||||
borderColor: "var(--color-inactive-checkbox)",
|
||||
}}
|
||||
className="h-[18px] w-[18px] cursor-pointer rounded border
|
||||
accent-input-border-select border-inactive-checkbox"
|
||||
/>
|
||||
자동 로그인
|
||||
</label>
|
||||
@@ -106,8 +101,7 @@ export default function LoginPage() {
|
||||
{/* 로그인 버튼 */}
|
||||
<button
|
||||
type="submit"
|
||||
className="h-14 w-full rounded-lg text-[16px] font-semibold text-white transition-opacity cursor-pointer"
|
||||
style={{ backgroundColor: "var(--color-active-button)" }}
|
||||
className="h-14 w-full rounded-lg text-[16px] font-semibold text-white transition-opacity cursor-pointer bg-inactive-button"
|
||||
>
|
||||
로그인
|
||||
</button>
|
||||
@@ -115,33 +109,27 @@ export default function LoginPage() {
|
||||
{/* 하단 링크들 */}
|
||||
<div className="flex items-center justify-between text-[15px]">
|
||||
<Link
|
||||
href="#"
|
||||
className="underline-offset-2 hover:underline"
|
||||
style={{ color: "var(--color-basic-text)" }}
|
||||
href="/register"
|
||||
className="underline-offset-2 text-basic-text"
|
||||
>
|
||||
회원가입
|
||||
</Link>
|
||||
<div
|
||||
className="flex items-center gap-3"
|
||||
style={{ color: "var(--color-basic-text)" }}
|
||||
className="flex items-center gap-3 text-basic-text"
|
||||
>
|
||||
<Link href="#" className="underline-offset-2 hover:underline">
|
||||
<Link href="#" className="underline-offset-2">
|
||||
아이디 찾기
|
||||
</Link>
|
||||
<span className="h-3 w-px bg-[var(--color-input-border)]" />
|
||||
<Link href="#" className="underline-offset-2 hover:underline">
|
||||
<span className="h-3 w-px bg-input-border" />
|
||||
<Link href="#" className="underline-offset-2">
|
||||
비밀번호 재설정
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{/* 카피라이트 */}
|
||||
<p
|
||||
className="mt-10 text-center text-[15px]"
|
||||
style={{ color: "var(--color-basic-text)" }}
|
||||
>
|
||||
<div></div>
|
||||
<p className="text-center py-[40px] text-[15px] text-basic-text">
|
||||
Copyright ⓒ 2025 XL LMS. All rights reserved
|
||||
</p>
|
||||
</div>
|
||||
|
||||
613
src/app/register/page.tsx
Normal file
613
src/app/register/page.tsx
Normal file
@@ -0,0 +1,613 @@
|
||||
\"use client\";
|
||||
|
||||
import { useState } from \"react\";
|
||||
import Link from \"next/link\";
|
||||
import MainLogo from \"@/app/svgs/mainlogosvg\";
|
||||
|
||||
export default function RegisterPage() {
|
||||
const [name, setName] = useState(\"\");
|
||||
const [phone, setPhone] = useState(\"\");
|
||||
const [email, setEmail] = useState(\"\");
|
||||
const [password, setPassword] = useState(\"\");
|
||||
const [confirmPassword, setConfirmPassword] = useState(\"\");
|
||||
const [gender, setGender] = useState<\"male\" | \"female\" | \"\">(\"\");
|
||||
const [birth, setBirth] = useState(\"\");
|
||||
|
||||
const [agreeAll, setAgreeAll] = useState(false);
|
||||
const [agreeAge, setAgreeAge] = useState(false);
|
||||
const [agreeTos, setAgreeTos] = useState(false);
|
||||
const [agreePrivacy, setAgreePrivacy] = useState(false);
|
||||
|
||||
function syncAgreeAll(nextAll: boolean) {
|
||||
setAgreeAll(nextAll);
|
||||
setAgreeAge(nextAll);
|
||||
setAgreeTos(nextAll);
|
||||
setAgreePrivacy(nextAll);
|
||||
}
|
||||
|
||||
function handleIndividualAgree(next: { age?: boolean; tos?: boolean; privacy?: boolean }) {
|
||||
const nextAge = next.age ?? agreeAge;
|
||||
const nextTos = next.tos ?? agreeTos;
|
||||
const nextPrivacy = next.privacy ?? agreePrivacy;
|
||||
setAgreeAge(nextAge);
|
||||
setAgreeTos(nextTos);
|
||||
setAgreePrivacy(nextPrivacy);
|
||||
setAgreeAll(nextAge && nextTos && nextPrivacy);
|
||||
}
|
||||
|
||||
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
|
||||
e.preventDefault();
|
||||
// TODO: 서버 연동 시 실제 제출 로직으로 교체
|
||||
console.log({
|
||||
name,
|
||||
phone,
|
||||
email,
|
||||
password,
|
||||
confirmPassword,
|
||||
gender,
|
||||
birth,
|
||||
agree: { all: agreeAll, age: agreeAge, tos: agreeTos, privacy: agreePrivacy },
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div className=\"min-h-screen w-full flex flex-col items-center justify-between\">
|
||||
<div></div>
|
||||
<div className=\"rounded-xl bg-white max-w-[480px] w-full\">
|
||||
{/* 로고/타이틀 */}
|
||||
<div className=\"mb-10 flex flex-col items-center\">
|
||||
<div className=\"mb-[7px]\">
|
||||
<MainLogo />
|
||||
</div>
|
||||
<div className=\"text-[24px] font-[700] leading-[150%] text-neutral-700\">회원가입</div>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className=\"space-y-6\">
|
||||
<div className=\"space-y-4\">
|
||||
{/* 이름 */}
|
||||
<div className=\"space-y-2\">
|
||||
<label className=\"text-[15px] font-[600] text-[var(--color-basic-text)]\">이름</label>
|
||||
<input
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
placeholder=\"이름을 입력해 주세요.\"
|
||||
className=\"h-[40px] px-[12px] py-[8px] w-full rounded-[8px] border border-neutral-40 text-[16px] text-neutral-700 placeholder:text-input-placeholder-text focus:outline-none focus:border-neutral-700\"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 휴대폰 번호 */}
|
||||
<div className=\"space-y-2\">
|
||||
<label className=\"text-[15px] font-[600] text-[var(--color-basic-text)]\">휴대폰 번호</label>
|
||||
<input
|
||||
value={phone}
|
||||
onChange={(e) => setPhone(e.target.value)}
|
||||
placeholder=\"-없이 입력해 주세요.\"
|
||||
className=\"h-[40px] px-[12px] py-[8px] w-full rounded-[8px] border border-neutral-40 text-[16px] text-neutral-700 placeholder:text-input-placeholder-text focus:outline-none focus:border-neutral-700\"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 아이디(이메일) + 인증번호 전송 */}
|
||||
<div className=\"space-y-2\">
|
||||
<label className=\"text-[15px] font-[600] text-[var(--color-basic-text)]\">아이디 (이메일)</label>
|
||||
<div className=\"flex gap-2\">
|
||||
<input
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder=\"이메일을 입력해 주세요.\"
|
||||
className=\"h-[40px] px-[12px] py-[8px] w-full rounded-[8px] border border-neutral-40 text-[16px] text-neutral-700 placeholder:text-input-placeholder-text focus:outline-none focus:border-neutral-700\"
|
||||
/>
|
||||
<button
|
||||
type=\"button\"
|
||||
className=\"h-[40px] px-[12px] rounded-[8px] bg-[#f1f3f5] text-[16px] font-[600] text-[#4c5561]\"
|
||||
>
|
||||
인증번호 전송
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 비밀번호 */}
|
||||
<div className=\"space-y-2\">
|
||||
<label className=\"text-[15px] font-[600] text-[var(--color-basic-text)]\">비밀번호</label>
|
||||
<input
|
||||
type=\"password\"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
placeholder=\"8~16자의 영문/숫자/특수문자를 조합해서 입력해 주세요.\"
|
||||
className=\"h-[40px] px-[12px] py-[8px] w-full rounded-[8px] border border-neutral-40 text-[16px] text-neutral-700 placeholder:text-input-placeholder-text focus:outline-none focus:border-neutral-700\"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 비밀번호 확인 */}
|
||||
<div className=\"space-y-2\">
|
||||
<label className=\"text-[15px] font-[600] text-[var(--color-basic-text)]\">비밀번호 확인</label>
|
||||
<input
|
||||
type=\"password\"
|
||||
value={confirmPassword}
|
||||
onChange={(e) => setConfirmPassword(e.target.value)}
|
||||
placeholder=\"비밀번호를 다시 입력해 주세요.\"
|
||||
className=\"h-[40px] px-[12px] py-[8px] w-full rounded-[8px] border border-neutral-40 text-[16px] text-neutral-700 placeholder:text-input-placeholder-text focus:outline-none focus:border-neutral-700\"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 성별 */}
|
||||
<div className=\"space-y-2\">
|
||||
<label className=\"text-[15px] font-[600] text-[var(--color-basic-text)]\">성별</label>
|
||||
<div className=\"flex items-center gap-5 h-[40px]\">
|
||||
<label className=\"flex items-center gap-2 text-[15px] text-neutral-700\">
|
||||
<input
|
||||
type=\"radio\"
|
||||
name=\"gender\"
|
||||
checked={gender === \"male\"}
|
||||
onChange={() => setGender(\"male\")}
|
||||
className=\"h-[18px] w-[18px] cursor-pointer\"
|
||||
style={{ accentColor: \"var(--color-input-border-select)\" }}
|
||||
/>
|
||||
남성
|
||||
</label>
|
||||
<label className=\"flex items-center gap-2 text-[15px] text-neutral-700\">
|
||||
<input
|
||||
type=\"radio\"
|
||||
name=\"gender\"
|
||||
checked={gender === \"female\"}
|
||||
onChange={() => setGender(\"female\")}
|
||||
className=\"h-[18px] w-[18px] cursor-pointer\"
|
||||
style={{ accentColor: \"var(--color-input-border-select)\" }}
|
||||
/>
|
||||
여성
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 생년월일 */}
|
||||
<div className=\"space-y-2\">
|
||||
<label className=\"text-[15px] font-[600] text-[var(--color-basic-text)]\">생년월일</label>
|
||||
<input
|
||||
type=\"date\"
|
||||
value={birth}
|
||||
onChange={(e) => setBirth(e.target.value)}
|
||||
className=\"h-[40px] px-[12px] py-[8px] w-full rounded-[8px] border border-neutral-40 text-[16px] text-neutral-700 focus:outline-none focus:border-neutral-700\"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 약관 */}
|
||||
<div className=\"space-y-4\">
|
||||
<label className=\"flex items-center gap-2 text-[18px] font-[600] text-neutral-700 cursor-pointer\">
|
||||
<input
|
||||
type=\"checkbox\"
|
||||
checked={agreeAll}
|
||||
onChange={(e) => syncAgreeAll(e.target.checked)}
|
||||
className=\"h-[20px] w-[20px] cursor-pointer rounded border\"
|
||||
style={{ accentColor: \"var(--color-input-border-select)\", borderColor: \"var(--color-inactive-checkbox)\" }}
|
||||
/>
|
||||
모든 항목에 동의합니다.
|
||||
</label>
|
||||
|
||||
<div className=\"h-px w-full bg-[var(--color-input-border)]\" />
|
||||
|
||||
<div className=\"space-y-3\">
|
||||
<label className=\"flex items-center justify-between text-[15px]\">
|
||||
<span className=\"flex items-center gap-2 text-neutral-700\">
|
||||
<input
|
||||
type=\"checkbox\"
|
||||
checked={agreeAge}
|
||||
onChange={(e) => handleIndividualAgree({ age: e.target.checked })}
|
||||
className=\"h-[18px] w-[18px] cursor-pointer rounded border\"
|
||||
style={{ accentColor: \"var(--color-input-border-select)\", borderColor: \"var(--color-inactive-checkbox)\" }}
|
||||
/>
|
||||
<span>
|
||||
만 14세 이상입니다. <span className=\"text-[#384fbf]\">(필수)</span>
|
||||
</span>
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<label className=\"flex items-center justify-between text-[15px]\">
|
||||
<span className=\"flex items-center gap-2 text-neutral-700\">
|
||||
<input
|
||||
type=\"checkbox\"
|
||||
checked={agreeTos}
|
||||
onChange={(e) => handleIndividualAgree({ tos: e.target.checked })}
|
||||
className=\"h-[18px] w-[18px] cursor-pointer rounded border\"
|
||||
style={{ accentColor: \"var(--color-input-border-select)\", borderColor: \"var(--color-inactive-checkbox)\" }}
|
||||
/>
|
||||
<span>
|
||||
이용 약관 동의 <span className=\"text-[#384fbf]\">(필수)</span>
|
||||
</span>
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<label className=\"flex items-center justify-between text-[15px]\">
|
||||
<span className=\"flex items-center gap-2 text-neutral-700\">
|
||||
<input
|
||||
type=\"checkbox\"
|
||||
checked={agreePrivacy}
|
||||
onChange={(e) => handleIndividualAgree({ privacy: e.target.checked })}
|
||||
className=\"h-[18px] w-[18px] cursor-pointer rounded border\"
|
||||
style={{ accentColor: \"var(--color-input-border-select)\", borderColor: \"var(--color-inactive-checkbox)\" }}
|
||||
/>
|
||||
<span>
|
||||
개인정보 수집 및 이용 동의 <span className=\"text-[#384fbf]\">(필수)</span>
|
||||
</span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 버튼들 */}
|
||||
<div className=\"flex gap-3\">
|
||||
<Link
|
||||
href=\"/login\"
|
||||
className=\"h-14 flex-1 rounded-[12px] bg-[#f1f3f5] text-center grid place-items-center text-[18px] font-[600] text-[#4c5561]\"
|
||||
>
|
||||
돌아가기
|
||||
</Link>
|
||||
<button
|
||||
type=\"submit\"
|
||||
className=\"h-14 flex-1 rounded-[12px] text-[18px] font-[600] text-white\"
|
||||
style={{ backgroundColor: \"var(--color-active-button)\" }}
|
||||
disabled={!(agreeAge && agreeTos && agreePrivacy)}
|
||||
>
|
||||
회원 가입 완료
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div></div>
|
||||
<p className=\"text-center text-[15px] text-basic-text\">
|
||||
Copyright ⓒ 2025 XL LMS. All rights reserved
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
"use client";
|
||||
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import Link from "next/link";
|
||||
|
||||
export default function RegisterPage() {
|
||||
// form states
|
||||
const [name, setName] = useState("");
|
||||
const [phone, setPhone] = useState("");
|
||||
const [email, setEmail] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [passwordConfirm, setPasswordConfirm] = useState("");
|
||||
const [gender, setGender] = useState<"male" | "female">("male");
|
||||
const [birth, setBirth] = useState("");
|
||||
|
||||
// agreements
|
||||
const [agreeAge, setAgreeAge] = useState(false);
|
||||
const [agreeTos, setAgreeTos] = useState(false);
|
||||
const [agreePrivacy, setAgreePrivacy] = useState(false);
|
||||
const agreeAll = useMemo(
|
||||
() => agreeAge && agreeTos && agreePrivacy,
|
||||
[agreeAge, agreeTos, agreePrivacy],
|
||||
);
|
||||
|
||||
function handleToggleAll(next: boolean) {
|
||||
setAgreeAge(next);
|
||||
setAgreeTos(next);
|
||||
setAgreePrivacy(next);
|
||||
}
|
||||
|
||||
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
|
||||
e.preventDefault();
|
||||
if (!agreeAge || !agreeTos || !agreePrivacy) {
|
||||
alert("필수 약관에 동의해 주세요.");
|
||||
return;
|
||||
}
|
||||
if (password.length < 8 || password.length > 16) {
|
||||
alert("비밀번호는 8~16자여야 합니다.");
|
||||
return;
|
||||
}
|
||||
if (password !== passwordConfirm) {
|
||||
alert("비밀번호가 일치하지 않습니다.");
|
||||
return;
|
||||
}
|
||||
// TODO: 실제 API 연동
|
||||
console.log({
|
||||
name,
|
||||
phone,
|
||||
email,
|
||||
password,
|
||||
gender,
|
||||
birth,
|
||||
agreements: { agreeAge, agreeTos, agreePrivacy },
|
||||
});
|
||||
alert("회원가입 폼이 제출되었습니다. (데모)");
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen w-full flex flex-col items-center justify-between">
|
||||
<div></div>
|
||||
<div className="rounded-xl bg-white max-w-[480px] w-full">
|
||||
{/* 헤더 타이틀 */}
|
||||
<div className="mb-10 flex flex-col items-center">
|
||||
<div className="text-[24px] font-[700] leading-[150%] text-neutral-700">
|
||||
회원가입
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 폼 */}
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
<div className="space-y-4">
|
||||
{/* 이름 */}
|
||||
<div className="space-y-2">
|
||||
<label
|
||||
htmlFor="name"
|
||||
className="text-[15px] font-[600]"
|
||||
style={{ color: "var(--color-basic-text)" }}
|
||||
>
|
||||
이름
|
||||
</label>
|
||||
<input
|
||||
id="name"
|
||||
name="name"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
placeholder="이름을 입력해 주세요."
|
||||
className="
|
||||
h-10 px-[12px] py-[8px] 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-[16px] text-neutral-700 font-[400] leading-[150%] placeholder:text-input-placeholder-text
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 휴대폰 번호 */}
|
||||
<div className="space-y-2">
|
||||
<label
|
||||
htmlFor="phone"
|
||||
className="text-[15px] font-[600]"
|
||||
style={{ color: "var(--color-basic-text)" }}
|
||||
>
|
||||
휴대폰 번호
|
||||
</label>
|
||||
<input
|
||||
id="phone"
|
||||
name="phone"
|
||||
value={phone}
|
||||
onChange={(e) => setPhone(e.target.value)}
|
||||
placeholder="-없이 입력해 주세요."
|
||||
className="
|
||||
h-10 px-[12px] py-[8px] 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-[16px] text-neutral-700 font-[400] leading-[150%] placeholder:text-input-placeholder-text
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 아이디(이메일) + 인증번호 전송 */}
|
||||
<div className="space-y-2">
|
||||
<label
|
||||
htmlFor="email"
|
||||
className="text-[15px] font-[600]"
|
||||
style={{ color: "var(--color-basic-text)" }}
|
||||
>
|
||||
아이디 (이메일)
|
||||
</label>
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
id="email"
|
||||
name="email"
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder="이메일을 입력해 주세요."
|
||||
className="
|
||||
h-10 px-[12px] py-[8px] 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-[16px] text-neutral-700 font-[400] leading-[150%] placeholder:text-input-placeholder-text
|
||||
"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
className="h-10 w-[136px] rounded-[8px] text-[16px] font-[600] bg-[#f9fafb] text-[#b1b8c0]"
|
||||
>
|
||||
인증번호 전송
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 비밀번호 */}
|
||||
<div className="space-y-2">
|
||||
<label
|
||||
htmlFor="password"
|
||||
className="text-[15px] font-[600]"
|
||||
style={{ color: "var(--color-basic-text)" }}
|
||||
>
|
||||
비밀번호
|
||||
</label>
|
||||
<input
|
||||
id="password"
|
||||
name="password"
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
placeholder="8~16자의 영문/숫자/특수문자를 조합해서 입력해 주세요."
|
||||
className="
|
||||
h-10 px-[12px] py-[8px] 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-[16px] text-neutral-700 font-[400] leading-[150%] placeholder:text-input-placeholder-text
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 비밀번호 확인 */}
|
||||
<div className="space-y-2">
|
||||
<label
|
||||
htmlFor="passwordConfirm"
|
||||
className="text-[15px] font-[600]"
|
||||
style={{ color: "var(--color-basic-text)" }}
|
||||
>
|
||||
비밀번호 확인
|
||||
</label>
|
||||
<input
|
||||
id="passwordConfirm"
|
||||
name="passwordConfirm"
|
||||
type="password"
|
||||
value={passwordConfirm}
|
||||
onChange={(e) => setPasswordConfirm(e.target.value)}
|
||||
placeholder="비밀번호를 다시 입력해 주세요."
|
||||
className="
|
||||
h-10 px-[12px] py-[8px] 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-[16px] text-neutral-700 font-[400] leading-[150%] placeholder:text-input-placeholder-text
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 성별 */}
|
||||
<div className="space-y-2">
|
||||
div className="text-[15px] font-[600]" style={{ color: "var(--color-basic-text)" }}>
|
||||
성별
|
||||
</div>
|
||||
<div className="flex items-center gap-5 h-10">
|
||||
<label className="flex items-center gap-2 text-[15px] text-neutral-700">
|
||||
<input
|
||||
type="radio"
|
||||
name="gender"
|
||||
checked={gender === "male"}
|
||||
onChange={() => setGender("male")}
|
||||
className="h-[18px] w-[18px] rounded-full"
|
||||
style={{ accentColor: "var(--color-active-button)" }}
|
||||
/>
|
||||
남성
|
||||
</label>
|
||||
<label className="flex items-center gap-2 text-[15px] text-neutral-700">
|
||||
<input
|
||||
type="radio"
|
||||
name="gender"
|
||||
checked={gender === "female"}
|
||||
onChange={() => setGender("female")}
|
||||
className="h-[18px] w-[18px] rounded-full"
|
||||
style={{ accentColor: "var(--color-input-border)" }}
|
||||
/>
|
||||
여성
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 생년월일 */}
|
||||
<div className="space-y-2">
|
||||
<label
|
||||
htmlFor="birth"
|
||||
className="text-[15px] font-[600]"
|
||||
style={{ color: "var(--color-basic-text)" }}
|
||||
>
|
||||
생년월일
|
||||
</label>
|
||||
<input
|
||||
id="birth"
|
||||
name="birth"
|
||||
type="date"
|
||||
value={birth}
|
||||
onChange={(e) => setBirth(e.target.value)}
|
||||
className="
|
||||
h-10 px-[12px] py-[8px] 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-[16px] text-neutral-700 font-[400] leading-[150%]
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 약관 동의 */}
|
||||
<div className="space-y-4">
|
||||
<label className="flex cursor-pointer select-none items-center gap-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={agreeAll}
|
||||
onChange={(e) => handleToggleAll(e.target.checked)}
|
||||
className="h-[20px] w-[20px] cursor-pointer rounded border"
|
||||
style={{
|
||||
accentColor: "var(--color-input-border-select)",
|
||||
borderColor: "var(--color-inactive-checkbox)",
|
||||
}}
|
||||
/>
|
||||
<span className="text-[18px] font-[600] text-neutral-700">모든 항목에 동의합니다.</span>
|
||||
</label>
|
||||
<div className="h-px w-full bg-neutral-200" />
|
||||
<div className="space-y-3">
|
||||
<label className="flex cursor-pointer select-none items-center justify-between">
|
||||
<span className="flex items-center gap-2 text-[15px]" style={{ color: "var(--color-basic-text)" }}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={agreeAge}
|
||||
onChange={(e) => setAgreeAge(e.target.checked)}
|
||||
className="h-[20px] w-[20px] cursor-pointer rounded border"
|
||||
style={{
|
||||
accentColor: "var(--color-input-border-select)",
|
||||
borderColor: "var(--color-inactive-checkbox)",
|
||||
}}
|
||||
/>
|
||||
만 14세 이상입니다. <span className="text-[#384fbf]">(필수)</span>
|
||||
</span>
|
||||
</label>
|
||||
<label className="flex cursor-pointer select-none items-center justify-between">
|
||||
<span className="flex items-center gap-2 text-[15px]" style={{ color: "var(--color-basic-text)" }}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={agreeTos}
|
||||
onChange={(e) => setAgreeTos(e.target.checked)}
|
||||
className="h-[20px] w-[20px] cursor-pointer rounded border"
|
||||
style={{
|
||||
accentColor: "var(--color-input-border-select)",
|
||||
borderColor: "var(--color-inactive-checkbox)",
|
||||
}}
|
||||
/>
|
||||
이용 약관 동의 <span className="text-[#384fbf]">(필수)</span>
|
||||
</span>
|
||||
</label>
|
||||
<label className="flex cursor-pointer select-none items-center justify-between">
|
||||
<span className="flex items-center gap-2 text-[15px]" style={{ color: "var(--color-basic-text)" }}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={agreePrivacy}
|
||||
onChange={(e) => setAgreePrivacy(e.target.checked)}
|
||||
className="h-[20px] w-[20px] cursor-pointer rounded border"
|
||||
style={{
|
||||
accentColor: "var(--color-input-border-select)",
|
||||
borderColor: "var(--color-inactive-checkbox)",
|
||||
}}
|
||||
/>
|
||||
개인정보 수집 및 이용 동의 <span className="text-[#384fbf]">(필수)</span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 하단 버튼 */}
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<Link
|
||||
href="/login"
|
||||
className="h-14 rounded-[12px] bg-[#f1f3f5] text-[18px] font-[600] text-center flex items-center justify-center"
|
||||
style={{ color: "var(--color-basic-text)" }}
|
||||
>
|
||||
돌아가기
|
||||
</Link>
|
||||
<button
|
||||
type="submit"
|
||||
className="h-14 rounded-[12px] text-[18px] font-[600] text-white"
|
||||
style={{ backgroundColor: "var(--color-inactive-button)" }}
|
||||
>
|
||||
회원 가입 완료
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div></div>
|
||||
<p className="text-center text-[15px] text-basic-text">
|
||||
Copyright ⓒ 2025 XL LMS. All rights reserved
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
9
src/app/svgs/logincheckboxactivesvg.tsx
Normal file
9
src/app/svgs/logincheckboxactivesvg.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import React from "react";
|
||||
|
||||
export default function LoginCheckboxActiveSvg() {
|
||||
return (
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15.1719 0C16.7343 0.000217172 18 1.26658 18 2.8291V15.1719C17.9998 16.7342 16.7342 17.9998 15.1719 18H2.8291C1.26658 18 0.000217172 16.7343 0 15.1719V2.8291C0 1.26645 1.26645 0 2.8291 0H15.1719ZM13.7695 6.28906C13.4081 5.92762 12.8215 5.92776 12.46 6.28906L7.97168 10.7783L5.54004 8.34668C5.17861 7.98543 4.59294 7.98554 4.23145 8.34668C3.87012 8.70822 3.86999 9.2948 4.23145 9.65625L7.31641 12.7422C7.67782 13.1034 8.26449 13.1033 8.62598 12.7422L13.7695 7.59863C14.1308 7.23716 14.1308 6.65053 13.7695 6.28906Z" fill="#1F2B91"/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
11
src/app/svgs/logincheckboxinactivesvg.tsx
Normal file
11
src/app/svgs/logincheckboxinactivesvg.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import React from "react";
|
||||
|
||||
export default function LoginCheckboxInactiveSvg() {
|
||||
return (
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="18" height="18" fill="white" />
|
||||
<path d="M15.1719 0C16.7343 0.000217172 18 1.26658 18 2.8291V15.1719L17.9854 15.4609C17.8503 16.7925 16.7925 17.8503 15.4609 17.9854L15.1719 18H2.8291L2.54004 17.9854C1.11332 17.8407 0.000203611 16.6368 0 15.1719V2.8291C0 1.36402 1.11319 0.159369 2.54004 0.0146484L2.8291 0H15.1719ZM2.8291 1.125C1.88777 1.125 1.125 1.88777 1.125 2.8291V15.1719C1.12513 16.1127 1.88743 16.875 2.8291 16.875H15.1719C16.113 16.8749 16.8749 16.113 16.875 15.1719V2.8291C16.875 1.94613 16.2049 1.22087 15.3457 1.13379L15.1719 1.125H2.8291Z" fill="#C2C8CF"/>
|
||||
<path d="M12.4604 6.2896C12.8219 5.92827 13.408 5.92814 13.7694 6.2896C14.1307 6.65107 14.1307 7.23717 13.7694 7.59864L8.62608 12.742C8.26461 13.1033 7.6785 13.1033 7.31703 12.742L4.23125 9.65623C3.86979 9.29478 3.86993 8.70872 4.23125 8.34719C4.59277 7.98566 5.17877 7.98566 5.54029 8.34719L7.97155 10.7784L12.4604 6.2896Z" fill="#C2C8CF"/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user