Compare commits

..

2 Commits

Author SHA1 Message Date
wallace
3d226a65f7 회원가입 icon 정리리 2025-11-10 11:34:06 +09:00
wallace
c40a40bf58 메인페이지 작업시작작 2025-11-10 10:54:07 +09:00
9 changed files with 490 additions and 216 deletions

0
app/lecturelist/page.tsx Normal file
View File

237
app/myinfo/page.tsx Normal file
View File

@@ -0,0 +1,237 @@
"use client";
import { useEffect, useState } from 'react';
import { useRouter } from 'next/navigation';
import LoginPage from '../login/page';
const imgImage2 = "http://localhost:3845/assets/89fda8e949171025b1232bae70fc9d442e4e70c8.png";
const imgLine2 = "http://localhost:3845/assets/6ee8cf4ebb6bc2adb14aab8c9940b3002c20af35.svg";
export default function MyLecturePage() {
const router = useRouter();
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
// 로그인 상태 확인
const loginStatus = localStorage.getItem('isLoggedIn') === 'true';
setIsLoggedIn(loginStatus);
setIsLoading(false);
}, []);
if (isLoading) {
return null; // 로딩 중
}
// 로그인되지 않았으면 로그인 페이지 표시
if (!isLoggedIn) {
return <LoginPage />;
}
return (
<div className="bg-white relative min-h-screen w-full">
{/* 헤더 */}
<header className="absolute content-stretch flex items-center justify-between left-[calc(12.5%+91px)] top-[43px] w-[1332px]">
<div className="content-stretch flex gap-[99px] items-center relative shrink-0">
{/* 로고 */}
<div className="h-[74px] relative shrink-0 w-[72px]">
<div className="absolute inset-0 overflow-hidden pointer-events-none">
<img alt="" className="absolute h-[291.74%] left-[-100%] max-w-none top-[-95.73%] w-[301.18%]" src={imgImage2} />
</div>
</div>
{/* 메뉴 */}
<div className="content-stretch flex gap-[24px] items-center relative shrink-0">
<div className="content-stretch flex gap-[150px] items-center relative shrink-0">
<div className="box-border content-stretch flex gap-[10px] items-center justify-center p-[10px] relative shrink-0">
<p className="font-bold leading-[normal] not-italic relative shrink-0 text-[#515151] text-[24px] text-nowrap whitespace-pre">
</p>
</div>
</div>
<div className="content-stretch flex gap-[150px] items-center relative shrink-0">
<div className="box-border content-stretch flex gap-[10px] items-center justify-center p-[10px] relative shrink-0">
<p className="font-bold leading-[normal] not-italic relative shrink-0 text-[#515151] text-[24px] text-nowrap whitespace-pre">
</p>
</div>
</div>
<div className="content-stretch flex gap-[150px] items-center relative shrink-0">
<div className="box-border content-stretch flex gap-[10px] items-center justify-center p-[10px] relative shrink-0">
<p className="font-bold leading-[normal] not-italic relative shrink-0 text-[#515151] text-[24px] text-nowrap whitespace-pre">
</p>
</div>
</div>
</div>
</div>
{/* 사용자 메뉴 */}
<div className="content-stretch flex gap-[20px] items-center relative shrink-0">
<div className="box-border content-stretch flex gap-[10px] items-center justify-center p-[10px] relative shrink-0">
<p className="font-medium leading-[normal] not-italic relative shrink-0 text-[#1669ca] text-[18px] text-nowrap whitespace-pre">
</p>
</div>
<button
onClick={() => {
localStorage.removeItem('isLoggedIn');
setIsLoggedIn(false);
router.push('/');
}}
className="box-border content-stretch flex gap-[10px] items-center justify-center p-[10px] relative shrink-0 cursor-pointer group transition-colors"
>
<p className="font-medium leading-[normal] not-italic relative shrink-0 text-[#515151] text-[18px] text-nowrap whitespace-pre group-hover:text-blue-500 transition-colors">
</p>
</button>
</div>
</header>
{/* 구분선 */}
<div className="absolute h-0 left-1/2 top-[150px] translate-x-[-50%] w-full">
<div className="absolute bottom-0 left-0 right-0 top-[-1px]">
<img alt="" className="block max-w-none size-full" src={imgLine2} />
</div>
</div>
{/* 사이드바 */}
<div className="absolute box-border content-stretch flex flex-col items-center left-[37px] pb-0 pt-4 px-0 top-[192px] w-[250px]">
<div className="box-border content-stretch flex flex-col gap-2 items-start p-3 relative shrink-0 w-full">
<button
onClick={() => router.push('/mylecture')}
className="bg-[#f7f7f7] box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer"
>
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
</p>
</div>
</button>
<button
onClick={() => router.push('/mylecture')}
className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer"
>
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
</p>
</div>
</button>
<button className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer">
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
</p>
</div>
</button>
<button className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer">
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
</p>
</div>
</button>
</div>
</div>
{/* 메인 콘텐츠 - 내 정보 수정 */}
<div className="absolute content-stretch flex flex-col gap-6 items-start left-[calc(31.25%+35px)] top-[243px] w-[784px]">
<div className="content-stretch flex gap-[10px] items-center relative shrink-0 w-full">
<div className="flex flex-col font-bold justify-center leading-[0] not-italic relative shrink-0 text-[24px] text-[#1d1d1d] text-nowrap">
<p className="leading-[1.6] whitespace-pre"> </p>
</div>
</div>
<div className="content-stretch flex flex-col gap-4 items-start relative shrink-0">
{/* 아이디 */}
<div className="content-stretch flex flex-col gap-4 items-start relative shrink-0 w-[789px]">
<div className="bg-white border border-[#b9b9b9] border-solid box-border content-stretch flex gap-[138px] items-center justify-center p-5 relative rounded-2xl shrink-0 w-full">
<p className="font-medium leading-[normal] not-italic relative shrink-0 text-[14px] text-[#515151] text-nowrap whitespace-pre">
</p>
<div className="flex flex-row items-center self-stretch">
<div className="bg-white box-border content-stretch flex gap-[10px] h-full items-center overflow-clip px-2 py-[10px] relative rounded-lg shrink-0 w-[559px]">
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[#b9b9b9] text-[14px] text-nowrap">
qwer1234@naver.com
</p>
</div>
</div>
</div>
</div>
{/* 비밀번호 변경 */}
<div className="content-stretch flex flex-col gap-4 items-start relative shrink-0 w-[789px]">
<div className="bg-white border border-[#b9b9b9] border-solid box-border content-stretch flex gap-[109px] items-center p-5 relative rounded-2xl shrink-0 w-full">
<p className="font-medium leading-[normal] not-italic relative shrink-0 text-[14px] text-[#515151] text-nowrap whitespace-pre">
</p>
<div className="box-border content-stretch flex gap-2 items-center px-0 py-[9px] relative shrink-0">
<button className="bg-white border border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] items-center justify-center px-2 py-1 relative rounded-md shrink-0 w-[256px] cursor-pointer hover:bg-gray-50 transition-colors">
<p className="font-medium leading-[1.6] not-italic relative shrink-0 text-[14px] text-black text-center text-nowrap whitespace-pre">
</p>
</button>
</div>
</div>
</div>
{/* 회원 탈퇴 */}
<div className="content-stretch flex flex-col gap-4 items-start relative shrink-0 w-[789px]">
<div className="bg-white border border-[#b9b9b9] border-solid box-border content-stretch flex gap-[109px] items-center p-5 relative rounded-2xl shrink-0 w-full">
<p className="font-medium leading-[normal] not-italic relative shrink-0 text-[14px] text-[#515151] w-[77px]">
</p>
<div className="box-border content-stretch flex gap-2 items-center px-0 py-[9px] relative shrink-0">
<button className="bg-white border border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] items-center justify-center px-2 py-1 relative rounded-md shrink-0 w-[256px] cursor-pointer hover:bg-gray-50 transition-colors">
<p className="font-medium leading-[1.6] not-italic relative shrink-0 text-[14px] text-black text-center text-nowrap whitespace-pre">
</p>
</button>
</div>
</div>
</div>
</div>
</div>
{/* 푸터 */}
<footer className="absolute bg-[#f7f7f7] box-border content-stretch flex flex-col gap-[10px] h-[225px] items-start left-0 px-[243px] py-[39px] top-[854px] w-full">
<div className="content-stretch flex gap-[49px] items-center relative shrink-0">
{/* 로고 */}
<div className="h-[74px] relative shrink-0 w-[72px]">
<div className="absolute inset-0 overflow-hidden pointer-events-none">
<img alt="" className="absolute h-[291.74%] left-[-100%] max-w-none top-[-95.73%] w-[301.18%]" src={imgImage2} />
</div>
</div>
{/* 푸터 정보 */}
<div className="content-stretch flex flex-col gap-[5px] items-start relative shrink-0 w-[479px]">
<div className="content-stretch flex gap-[27px] items-center relative shrink-0 w-full">
<div className="box-border content-stretch flex gap-[10px] items-center justify-center p-[10px] relative shrink-0">
<p className="font-bold leading-[normal] not-italic relative shrink-0 text-[#515151] text-[18px] text-nowrap whitespace-pre">
</p>
</div>
<div className="box-border content-stretch flex gap-[10px] items-center justify-center p-[10px] relative shrink-0">
<p className="font-bold leading-[normal] not-italic relative shrink-0 text-[#515151] text-[18px] text-nowrap whitespace-pre">
</p>
</div>
<div className="box-border content-stretch flex gap-[10px] items-center justify-center p-[10px] relative shrink-0">
<p className="font-bold leading-[normal] not-italic relative shrink-0 text-[#515151] text-[18px] text-nowrap whitespace-pre">
</p>
</div>
</div>
<div className="box-border content-stretch flex flex-col font-medium gap-[10px] items-center justify-center leading-[normal] not-italic p-[10px] relative shrink-0 text-[#515151] text-[16px]">
<p className="relative shrink-0 w-[400px]">
(12345) 123-12(1)
</p>
<p className="relative shrink-0 w-[400px]">
문의: 1234-1234 ( 09:00 ~ 18:00)
</p>
<p className="relative shrink-0 w-[400px]">
이메일: qwer1234@go.or.kr
</p>
</div>
</div>
</div>
</footer>
</div>
);
}

View File

@@ -2,13 +2,53 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import Image from 'next/image';
import LoginPage from './login/page'; import LoginPage from './login/page';
import logo from './logo.svg';
const imgImage2 = "http://localhost:3845/assets/89fda8e949171025b1232bae70fc9d442e4e70c8.png";
const imgImage7 = "http://localhost:3845/assets/a4e4d09643b890b56084560cc24d6e532a03487b.png";
const imgLine2 = "http://localhost:3845/assets/6ee8cf4ebb6bc2adb14aab8c9940b3002c20af35.svg";
const imgFrame2616314 = "http://localhost:3845/assets/17f021e324ee315bdf2fe96554a2260813957042.svg";
const imgRectangle1737 = "http://localhost:3845/assets/ae523ea10901c105fdbfda27ed21dd658fc4a7c2.png";
const imgRectangle1738 = "http://localhost:3845/assets/50e850999bbdd551763a187d402169c28ffecec5.png";
export default function HomePage() { export default function HomePage() {
const router = useRouter(); const router = useRouter();
const [isLoggedIn, setIsLoggedIn] = useState(false); const [isLoggedIn, setIsLoggedIn] = useState(false);
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
// 임시 데이터 - 실제로는 API에서 가져올 데이터
const [courses, setCourses] = useState([
{ id: 1, title: '원자로 운전 및 계통', image: imgRectangle1737 },
{ id: 2, title: '핵 연료', image: imgRectangle1738 },
{ id: 3, title: '방사선 안전', image: imgRectangle1737 },
{ id: 4, title: '방사성 폐기물', image: imgRectangle1737 },
]);
const [myCourses, setMyCourses] = useState([
{ id: 1, title: '원자로 기본 원리와 주요 계통 이해 - 이론 1', date: '2025-12-12(화)' },
{ id: 2, title: '원자로 기동 및 정상운전 절차 - 이론2', date: '2025-12-12(화)' },
{ id: 3, title: '비상 시 운전원 조치와 안전 계통 운용', date: '2025-12-12(화)' },
{ id: 4, title: '운전 사례 분석 및 시뮬레이션 실습', date: '2025-12-12(화)' },
{ id: 5, title: '핵분열과 핵연로 주기 이해', date: '2025-12-12(화)' },
{ id: 6, title: '핵연료 제조 공정 및 특성', date: '2025-12-12(화)' },
{ id: 7, title: '핵연로 성능 평가와 열수력 해석', date: '2025-12-12(화)' },
]);
const [notices, setNotices] = useState([
{ id: 1, title: '[점검] 방사선 폐기 VR 실습 서버 정기점검 안내', date: '2025-12-12(화)' },
{ id: 2, title: '[점검] 방사선 폐기 VR 실습 서버 정기점검 안내', date: '2025-12-12(화)' },
{ id: 3, title: '[점검] 방사선 폐기 VR 실습 서버 정기점검 안내', date: '2025-12-12(화)' },
{ id: 4, title: '[점검] 방사선 폐기 VR 실습 서버 정기점검 안내', date: '2025-12-12(화)' },
{ id: 5, title: '[점검] 방사선 폐기 VR 실습 서버 정기점검 안내', date: '2025-12-12(화)' },
{ id: 6, title: '[점검] 방사선 폐기 VR 실습 서버 정기점검 안내', date: '2025-12-12(화)' },
{ id: 7, title: '[점검] 방사선 폐기 VR 실습 서버 정기점검 안내', date: '2025-12-12(화)' },
{ id: 8, title: '[점검] 방사선 폐기 VR 실습 서버 정기점검 안내', date: '2025-12-12(화)' },
{ id: 9, title: '[점검] 방사선 폐기 VR 실습 서버 정기점검 안내', date: '2025-12-12(화)' },
{ id: 10, title: '[점검] 방사선 폐기 VR 실습 서버 정기점검 안내', date: '2025-12-12(화)' },
]);
useEffect(() => { useEffect(() => {
// 로그인 상태 확인 // 로그인 상태 확인
const loginStatus = localStorage.getItem('isLoggedIn') === 'true'; const loginStatus = localStorage.getItem('isLoggedIn') === 'true';
@@ -27,21 +67,181 @@ export default function HomePage() {
// 로그인되었으면 메인 페이지 표시 // 로그인되었으면 메인 페이지 표시
return ( return (
<div className="min-h-screen bg-gray-50"> <div className="bg-white relative min-h-screen w-full">
<div className="container mx-auto px-4 py-8"> {/* 헤더 */}
<h1 className="text-3xl font-bold mb-4"> </h1> <header className="absolute content-stretch flex items-center justify-between left-[calc(12.5%+91.375px)] top-[43px] w-[1332px]">
<p className="text-gray-600"> .</p> <div className="content-stretch flex gap-[99px] items-center relative shrink-0">
{/* 로고 */}
<div className="h-[74px] relative shrink-0 w-[72px]">
<div className="absolute inset-0 overflow-hidden pointer-events-none">
<img alt="" className="absolute h-[291.74%] left-[-100%] max-w-none top-[-95.73%] w-[301.18%]" src={imgImage2} />
</div>
</div>
{/* 메뉴 */}
<div className="content-stretch flex gap-[24px] items-center relative shrink-0">
<div className="content-stretch flex gap-[150px] items-center relative shrink-0">
<div className="box-border content-stretch flex gap-[10px] items-center justify-center p-[10px] relative shrink-0">
<p className="font-bold leading-[normal] not-italic relative shrink-0 text-[#515151] text-[24px] text-nowrap whitespace-pre">
</p>
</div>
</div>
<div className="content-stretch flex gap-[150px] items-center relative shrink-0">
<div className="box-border content-stretch flex gap-[10px] items-center justify-center p-[10px] relative shrink-0">
<p className="font-bold leading-[normal] not-italic relative shrink-0 text-[#515151] text-[24px] text-nowrap whitespace-pre">
</p>
</div>
</div>
<div className="content-stretch flex gap-[150px] items-center relative shrink-0">
<div className="box-border content-stretch flex gap-[10px] items-center justify-center p-[10px] relative shrink-0">
<p className="font-bold leading-[normal] not-italic relative shrink-0 text-[#515151] text-[24px] text-nowrap whitespace-pre">
</p>
</div>
</div>
</div>
</div>
{/* 사용자 메뉴 */}
<div className="content-stretch flex gap-[20px] items-center relative shrink-0">
<button
onClick={() => router.push('/myinfo')}
className="box-border content-stretch flex gap-[10px] items-center justify-center p-[10px] relative shrink-0 cursor-pointer group transition-colors"
>
<p className="font-medium leading-[normal] not-italic relative shrink-0 text-[#515151] text-[18px] text-nowrap whitespace-pre group-hover:text-blue-500 transition-colors">
</p>
</button>
<button
onClick={() => {
localStorage.removeItem('isLoggedIn');
setIsLoggedIn(false);
router.push('/');
}}
className="box-border content-stretch flex gap-[10px] items-center justify-center p-[10px] relative shrink-0 cursor-pointer group transition-colors"
>
<p className="font-medium leading-[normal] not-italic relative shrink-0 text-[#515151] text-[18px] text-nowrap whitespace-pre group-hover:text-blue-500 transition-colors">
</p>
</button>
</div>
</header>
{/* 로그아웃 버튼 */} {/* 구분선 */}
<button <div className="absolute h-0 left-[calc(50%+0.5px)] top-[150px] translate-x-[-50%] w-full">
onClick={() => { <div className="absolute bottom-0 left-0 right-0 top-[-1px]">
localStorage.removeItem('isLoggedIn'); <img alt="" className="block max-w-none size-full" src={imgLine2} />
router.push('/'); </div>
}} </div>
className="mt-4 px-4 py-2 bg-red-500 text-white rounded-md hover:bg-red-600"
> {/* Hero 배너 */}
<div className="absolute h-[402px] left-[-1px] top-[272px] w-full">
</button> <div className="absolute inset-0 overflow-hidden pointer-events-none">
<img alt="" className="absolute h-[257.2%] left-[-0.04%] max-w-none top-0 w-[100.07%]" src={imgImage7} />
</div>
</div>
{/* 전체 교육 과정 (4개) */}
<div className="absolute content-stretch flex flex-col gap-[7px] items-start justify-end left-[43px] top-[748px] w-[1435px]">
<div className="content-stretch flex gap-[150px] items-center relative shrink-0">
<div className="box-border content-stretch flex gap-[10px] items-center justify-center p-[10px] relative shrink-0">
<p className="font-bold leading-[normal] not-italic relative shrink-0 text-[#515151] text-[28px] text-nowrap whitespace-pre">
({courses.length})
</p>
</div>
</div>
</div>
{/* 지도보기 아이콘 */}
<div className="absolute h-[17px] left-[calc(43.75%+28.313px)] top-[692px] w-[128px]">
<img alt="" className="block max-w-none size-full" src={imgFrame2616314} />
</div>
{/* 교육 과정 카드들 - 데이터가 있을 때 */}
{courses.length > 0 ? (
<div className="absolute content-stretch flex gap-[23px] items-center left-[43px] top-[817px]">
{courses.map((course) => (
<div key={course.id} className="content-stretch flex flex-col gap-[18px] h-[326px] items-start relative shrink-0 w-[437px]">
<div className="h-[253px] relative shrink-0 w-full">
<div aria-hidden="true" className="absolute inset-0 pointer-events-none">
<img alt="" className="absolute max-w-none object-50%-50% object-cover size-full" src={course.image} />
</div>
</div>
<div className="content-stretch flex flex-col gap-[10px] items-start relative shrink-0 w-[392px]">
<p className="font-bold leading-[normal] not-italic relative shrink-0 text-[#515151] text-[20px] w-full">
{course.title}
</p>
</div>
</div>
))}
</div>
) : (
/* 등록된 교육 과정이 없습니다 메시지 - 데이터가 없을 때 */
<p className="absolute font-medium leading-[normal] left-[calc(43.75%+122.563px)] not-italic text-[#b9b9b9] text-[18px] text-center top-[964px] translate-x-[-50%] w-[268.5px]">
.
</p>
)}
{/* 나의 수강 강좌 목록 */}
<div className="absolute content-stretch flex flex-col gap-[7px] items-start justify-end left-[43px] top-[1213px] w-[866px]">
<div className="content-stretch flex gap-[150px] items-center relative shrink-0">
<div className="box-border content-stretch flex gap-[10px] items-center justify-center p-[10px] relative shrink-0">
<p className="font-bold leading-[normal] not-italic relative shrink-0 text-[#515151] text-[28px] text-nowrap whitespace-pre">
({myCourses.length})
</p>
</div>
</div>
<div className="border border-[#b9b9b9] border-solid box-border content-stretch flex flex-col items-start p-[20px] relative rounded-[10px] shrink-0 w-full">
{myCourses.length > 0 ? (
myCourses.map((course) => (
<div key={course.id} className="box-border content-stretch flex font-medium gap-[269px] items-center justify-center leading-[normal] not-italic p-[10px] relative shrink-0 text-[#515151] text-[18px] w-full">
<p className="relative shrink-0 w-[342px]">
{course.title}
</p>
<p className="basis-0 grow min-h-px min-w-px relative shrink-0 text-right">
{course.date}
</p>
</div>
))
) : (
<div className="box-border content-stretch flex gap-[269px] items-center justify-center p-[10px] relative shrink-0 w-full">
<p className="basis-0 font-medium grow leading-[normal] min-h-px min-w-px not-italic relative shrink-0 text-[#b9b9b9] text-[18px]">
.
</p>
</div>
)}
</div>
</div>
{/* 공지사항 */}
<div className="absolute content-stretch flex flex-col gap-[7px] items-start justify-end left-[calc(50%-9.5px)] top-[1213px] w-[914px]">
<div className="content-stretch flex gap-[150px] items-center relative shrink-0">
<div className="box-border content-stretch flex gap-[10px] items-center justify-center p-[10px] relative shrink-0">
<p className="font-bold leading-[normal] not-italic relative shrink-0 text-[#515151] text-[28px] text-nowrap whitespace-pre">
</p>
</div>
</div>
<div className="border border-[#b9b9b9] border-solid box-border content-stretch flex flex-col h-[498px] items-start p-[20px] relative rounded-[10px] shrink-0 w-full">
{notices.length > 0 ? (
notices.map((notice) => (
<div key={notice.id} className="box-border content-stretch flex font-medium items-center justify-between leading-[normal] not-italic p-[10px] relative shrink-0 text-[#515151] text-[18px] w-full">
<p className="basis-0 grow min-h-px min-w-px relative shrink-0">
{notice.title}
</p>
<p className="basis-0 grow min-h-px min-w-px relative shrink-0 text-right">
{notice.date}
</p>
</div>
))
) : (
<div className="box-border content-stretch flex gap-[269px] items-center justify-center p-[10px] relative shrink-0 w-full">
<p className="basis-0 font-medium grow leading-[normal] min-h-px min-w-px not-italic relative shrink-0 text-[#b9b9b9] text-[18px]">
.
</p>
</div>
)}
</div>
</div> </div>
</div> </div>
); );

View File

@@ -3,6 +3,10 @@
import { useState } from 'react'; import { useState } from 'react';
import Link from 'next/link'; import Link from 'next/link';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import RadioOff from '../../public/svg/radio_off';
import RadioOn from '../../public/svg/radio_on';
import CheckOff from '../../public/svg/check_off';
import CheckOn from '../../public/svg/check_on';
const imgRiCheckboxCircleLine = "http://localhost:3845/assets/e4c498605e2559d2764a3112ae9a9019e6ad798e.svg"; const imgRiCheckboxCircleLine = "http://localhost:3845/assets/e4c498605e2559d2764a3112ae9a9019e6ad798e.svg";
const imgFormkitRadio = "http://localhost:3845/assets/ea30a9a80d95ced4bfb1174d3a8475a4a1dbbabb.svg"; const imgFormkitRadio = "http://localhost:3845/assets/ea30a9a80d95ced4bfb1174d3a8475a4a1dbbabb.svg";
@@ -408,11 +412,7 @@ export default function RegisterPage() {
className="flex items-center gap-[10px]" className="flex items-center gap-[10px]"
onClick={() => handleGenderChange('male')} onClick={() => handleGenderChange('male')}
> >
<img {formData.gender === 'male' ? <RadioOn /> : <RadioOff />}
src={formData.gender === 'male' ? imgFormkitRadio : imgAkarIconsRadio}
alt=""
className="w-[24px] h-[24px]"
/>
<span className="text-[#515151] text-[14px] font-medium leading-[1.6]"> <span className="text-[#515151] text-[14px] font-medium leading-[1.6]">
</span> </span>
@@ -422,11 +422,7 @@ export default function RegisterPage() {
className="flex items-center gap-[10px]" className="flex items-center gap-[10px]"
onClick={() => handleGenderChange('female')} onClick={() => handleGenderChange('female')}
> >
<img {formData.gender === 'female' ? <RadioOn /> : <RadioOff />}
src={formData.gender === 'female' ? imgFormkitRadio : imgAkarIconsRadio}
alt=""
className="w-[24px] h-[24px]"
/>
<span className="text-[#515151] text-[14px] font-medium leading-[1.6]"> <span className="text-[#515151] text-[14px] font-medium leading-[1.6]">
</span> </span>
@@ -508,11 +504,7 @@ export default function RegisterPage() {
className="flex items-center gap-[16px] cursor-pointer select-none mb-[17px]" className="flex items-center gap-[16px] cursor-pointer select-none mb-[17px]"
onClick={() => handleAgreementChange('all')} onClick={() => handleAgreementChange('all')}
> >
<img {agreements.all ? <CheckOn /> : <CheckOff />}
src={imgRiCheckboxCircleLine}
alt=""
className={`w-[24px] h-[24px] ${agreements.all ? 'opacity-100' : 'opacity-50'}`}
/>
<span className="font-bold text-[20px] text-[#515151]"> <span className="font-bold text-[20px] text-[#515151]">
. .
</span> </span>
@@ -522,11 +514,7 @@ export default function RegisterPage() {
<div className="flex flex-col gap-[17px]"> <div className="flex flex-col gap-[17px]">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="flex items-center gap-[16px] cursor-pointer" onClick={() => handleAgreementChange('age14')}> <div className="flex items-center gap-[16px] cursor-pointer" onClick={() => handleAgreementChange('age14')}>
<img {agreements.age14 ? <CheckOn /> : <CheckOff />}
src={imgRiCheckboxCircleLine}
alt=""
className={`w-[24px] h-[24px] ${agreements.age14 ? 'opacity-100' : 'opacity-50'}`}
/>
<span className="text-[#515151] text-[16px] font-medium leading-[1.6]"> <span className="text-[#515151] text-[16px] font-medium leading-[1.6]">
14 . () 14 . ()
</span> </span>
@@ -540,11 +528,7 @@ export default function RegisterPage() {
</div> </div>
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="flex items-center gap-[16px] cursor-pointer" onClick={() => handleAgreementChange('terms')}> <div className="flex items-center gap-[16px] cursor-pointer" onClick={() => handleAgreementChange('terms')}>
<img {agreements.terms ? <CheckOn /> : <CheckOff />}
src={imgRiCheckboxCircleLine}
alt=""
className={`w-[24px] h-[24px] ${agreements.terms ? 'opacity-100' : 'opacity-50'}`}
/>
<span className="text-[#515151] text-[16px] font-medium leading-[1.6]"> <span className="text-[#515151] text-[16px] font-medium leading-[1.6]">
() ()
</span> </span>
@@ -558,11 +542,7 @@ export default function RegisterPage() {
</div> </div>
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="flex items-center gap-[16px] cursor-pointer" onClick={() => handleAgreementChange('privacy')}> <div className="flex items-center gap-[16px] cursor-pointer" onClick={() => handleAgreementChange('privacy')}>
<img {agreements.privacy ? <CheckOn /> : <CheckOff />}
src={imgRiCheckboxCircleLine}
alt=""
className={`w-[24px] h-[24px] ${agreements.privacy ? 'opacity-100' : 'opacity-50'}`}
/>
<span className="text-[#515151] text-[16px] font-medium leading-[1.6]"> <span className="text-[#515151] text-[16px] font-medium leading-[1.6]">
() ()
</span> </span>

View File

@@ -1,172 +0,0 @@
'use client';
import { useState } from 'react';
import Link from 'next/link';
export default function RegisterAgreementPage() {
const [allAgreed, setAllAgreed] = useState(false);
const [ageAgreed, setAgeAgreed] = useState(false);
const [termsAgreed, setTermsAgreed] = useState(false);
const [privacyAgreed, setPrivacyAgreed] = useState(false);
// 전체 동의 핸들러
const handleAllAgreed = (checked: boolean) => {
setAllAgreed(checked);
setAgeAgreed(checked);
setTermsAgreed(checked);
setPrivacyAgreed(checked);
};
// 개별 체크박스 변경 시 전체 동의 상태 업데이트
const updateAllAgreed = () => {
if (ageAgreed && termsAgreed && privacyAgreed) {
setAllAgreed(true);
} else {
setAllAgreed(false);
}
};
// 개별 체크박스 핸들러
const handleAgeAgreed = (checked: boolean) => {
setAgeAgreed(checked);
updateAllAgreed();
};
const handleTermsAgreed = (checked: boolean) => {
setTermsAgreed(checked);
updateAllAgreed();
};
const handlePrivacyAgreed = (checked: boolean) => {
setPrivacyAgreed(checked);
updateAllAgreed();
};
// 다음 단계 진행 가능 여부
const canProceed = ageAgreed && termsAgreed && privacyAgreed;
return (
<div className="min-h-screen flex items-center justify-center bg-white">
<div className="w-full max-w-2xl px-4">
{/* 회원가입 카드 */}
<div className="bg-white rounded-lg shadow-lg p-8">
{/* 제목 */}
<h1 className="text-2xl font-bold text-center mb-8"></h1>
{/* 단계 표시 */}
<div className="flex items-center justify-center mb-8 text-sm">
<div className="flex items-center">
<span className="px-3 py-1 bg-blue-500 text-white rounded-md font-semibold">
01
</span>
<span className="mx-2 text-gray-400">&gt;</span>
<span className="px-3 py-1 text-gray-500">02 </span>
<span className="mx-2 text-gray-400">&gt;</span>
<span className="px-3 py-1 text-gray-500">03 </span>
</div>
</div>
{/* 약관 동의 섹션 */}
<div className="space-y-4">
{/* 전체 동의 */}
<div className="pb-4 border-b border-gray-300">
<label className="flex items-center cursor-pointer">
<input
type="checkbox"
checked={allAgreed}
onChange={(e) => handleAllAgreed(e.target.checked)}
className="w-5 h-5 mr-3 text-blue-500 rounded focus:ring-2 focus:ring-blue-500"
/>
<span className="text-base font-medium"> .</span>
</label>
</div>
{/* 개별 약관 */}
<div className="space-y-4">
{/* 만 14세 이상 */}
<div className="flex items-center justify-between">
<label className="flex items-center cursor-pointer flex-1">
<input
type="checkbox"
checked={ageAgreed}
onChange={(e) => handleAgeAgreed(e.target.checked)}
className="w-5 h-5 mr-3 text-blue-500 rounded focus:ring-2 focus:ring-blue-500"
/>
<span className="text-sm">
14 . <span className="text-red-500">()</span>
</span>
</label>
<button className="text-sm text-gray-500 hover:text-gray-700">
&gt;
</button>
</div>
{/* 이용 약관 */}
<div className="flex items-center justify-between">
<label className="flex items-center cursor-pointer flex-1">
<input
type="checkbox"
checked={termsAgreed}
onChange={(e) => handleTermsAgreed(e.target.checked)}
className="w-5 h-5 mr-3 text-blue-500 rounded focus:ring-2 focus:ring-blue-500"
/>
<span className="text-sm">
<span className="text-red-500">()</span>
</span>
</label>
<button className="text-sm text-gray-500 hover:text-gray-700">
&gt;
</button>
</div>
{/* 개인정보 수집 및 이용 */}
<div className="flex items-center justify-between">
<label className="flex items-center cursor-pointer flex-1">
<input
type="checkbox"
checked={privacyAgreed}
onChange={(e) => handlePrivacyAgreed(e.target.checked)}
className="w-5 h-5 mr-3 text-blue-500 rounded focus:ring-2 focus:ring-blue-500"
/>
<span className="text-sm">
<span className="text-red-500">()</span>
</span>
</label>
<button className="text-sm text-gray-500 hover:text-gray-700">
&gt;
</button>
</div>
</div>
</div>
{/* 버튼 영역 */}
<div className="mt-8 flex space-x-4">
<Link
href="/login"
className="flex-1 py-3 bg-gray-200 text-gray-700 rounded-md text-center hover:bg-gray-300 transition font-medium"
>
</Link>
<Link
href={canProceed ? '/register' : '#'}
className={`flex-1 py-3 rounded-md text-center font-medium transition ${
canProceed
? 'bg-blue-500 text-white hover:bg-blue-600'
: 'bg-gray-300 text-gray-500 cursor-not-allowed pointer-events-none'
}`}
onClick={(e) => !canProceed && e.preventDefault()}
>
</Link>
</div>
</div>
{/* 카피라이트 */}
<div className="mt-8 text-center text-sm text-gray-500">
Copyright © 2025 XL LMS. All rights reserved
</div>
</div>
</div>
);
}

7
public/svg/check_off.tsx Normal file
View File

@@ -0,0 +1,7 @@
export default function CheckOff() {
return (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4 12C4 9.87827 4.84285 7.84344 6.34315 6.34315C7.84344 4.84285 9.87827 4 12 4C14.1217 4 16.1566 4.84285 17.6569 6.34315C19.1571 7.84344 20 9.87827 20 12C20 14.1217 19.1571 16.1566 17.6569 17.6569C16.1566 19.1571 14.1217 20 12 20C9.87827 20 7.84344 19.1571 6.34315 17.6569C4.84285 16.1566 4 14.1217 4 12ZM12 2C6.477 2 2 6.477 2 12C2 17.523 6.477 22 12 22C17.523 22 22 17.523 22 12C22 6.477 17.523 2 12 2Z" fill="#2C83E8" />
</svg>
);
}

7
public/svg/check_on.tsx Normal file
View File

@@ -0,0 +1,7 @@
export default function CheckOn() {
return (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4 12C4 9.87827 4.84285 7.84344 6.34315 6.34315C7.84344 4.84285 9.87827 4 12 4C14.1217 4 16.1566 4.84285 17.6569 6.34315C19.1571 7.84344 20 9.87827 20 12C20 14.1217 19.1571 16.1566 17.6569 17.6569C16.1566 19.1571 14.1217 20 12 20C9.87827 20 7.84344 19.1571 6.34315 17.6569C4.84285 16.1566 4 14.1217 4 12ZM12 2C6.477 2 2 6.477 2 12C2 17.523 6.477 22 12 22C17.523 22 22 17.523 22 12C22 6.477 17.523 2 12 2ZM17.457 9.457L16.043 8.043L11 13.086L8.207 10.293L6.793 11.707L11 15.914L17.457 9.457Z" fill="#2B82E8" />
</svg>
);
}

7
public/svg/radio_off.tsx Normal file
View File

@@ -0,0 +1,7 @@
export default function RadioOff() {
return (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 12C3 10.8181 3.23279 9.64778 3.68508 8.55585C4.13738 7.46392 4.80031 6.47177 5.63604 5.63604C6.47177 4.80031 7.46392 4.13738 8.55585 3.68508C9.64778 3.23279 10.8181 3 12 3C13.1819 3 14.3522 3.23279 15.4442 3.68508C16.5361 4.13738 17.5282 4.80031 18.364 5.63604C19.1997 6.47177 19.8626 7.46392 20.3149 8.55585C20.7672 9.64778 21 10.8181 21 12C21 14.3869 20.0518 16.6761 18.364 18.364C16.6761 20.0518 14.3869 21 12 21C9.61305 21 7.32387 20.0518 5.63604 18.364C3.94821 16.6761 3 14.3869 3 12Z" stroke="#969696" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
</svg>
);
}

8
public/svg/radio_on.tsx Normal file
View File

@@ -0,0 +1,8 @@
export default function RadioOn() {
return (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 22.5C6.21 22.5 1.5 17.79 1.5 12C1.5 6.21 6.21 1.5 12 1.5C17.79 1.5 22.5 6.21 22.5 12C22.5 17.79 17.79 22.5 12 22.5ZM12 3C7.035 3 3 7.035 3 12C3 16.965 7.035 21 12 21C16.965 21 21 16.965 21 12C21 7.035 16.965 3 12 3Z" fill="#404040" />
<path d="M12 18C15.3137 18 18 15.3137 18 12C18 8.68629 15.3137 6 12 6C8.68629 6 6 8.68629 6 12C6 15.3137 8.68629 18 12 18Z" fill="#404040" />
</svg>
);
}