diff --git a/src/components/Footer.js b/src/components/Footer.js new file mode 100644 index 00000000..8703a441 --- /dev/null +++ b/src/components/Footer.js @@ -0,0 +1,7 @@ +const Footer = () => ` + +`; + +export default Footer; diff --git a/src/components/Header.js b/src/components/Header.js new file mode 100644 index 00000000..0842f3ff --- /dev/null +++ b/src/components/Header.js @@ -0,0 +1,15 @@ +const Header = () => ` +
+

항해플러스

+
+ + + `; + +export default Header; diff --git a/src/main.js b/src/main.js index 036c2a38..d65079c0 100644 --- a/src/main.js +++ b/src/main.js @@ -1,241 +1,186 @@ -const MainPage = () => ` -
-
-
-

항해플러스

-
- - - -
-
- - -
- -
- -
-
- 프로필 -
-

홍길동

-

5분 전

-
-
-

오늘 날씨가 정말 좋네요. 다들 좋은 하루 보내세요!

-
- - - -
-
- -
-
- 프로필 -
-

김철수

-

15분 전

-
-
-

새로운 프로젝트를 시작했어요. 열심히 코딩 중입니다!

-
- - - -
-
- -
-
- 프로필 -
-

이영희

-

30분 전

-
-
-

오늘 점심 메뉴 추천 받습니다. 뭐가 좋을까요?

-
- - - -
-
- -
-
- 프로필 -
-

박민수

-

1시간 전

-
-
-

주말에 등산 가실 분 계신가요? 함께 가요!

-
- - - -
-
- -
-
- 프로필 -
-

정수연

-

2시간 전

-
-
-

새로 나온 영화 재미있대요. 같이 보러 갈 사람?

-
- - - -
-
-
-
- - -
-
-`; - -const ErrorPage = () => ` -
-
-

항해플러스

-

404

-

페이지를 찾을 수 없습니다

-

- 요청하신 페이지가 존재하지 않거나 이동되었을 수 있습니다. -

- - 홈으로 돌아가기 - -
-
-`; - -const LoginPage = () => ` -
-
-

항해플러스

-
-
- -
-
- -
- -
- -
-
- -
-
-
-`; - -const ProfilePage = () => ` -
-
-
-
-

항해플러스

-
- - - -
-
-

- 내 프로필 -

-
-
- - -
-
- - -
-
- - -
- -
-
-
- - -
-
-
-`; - -document.body.innerHTML = ` - ${MainPage()} - ${ProfilePage()} - ${LoginPage()} - ${ErrorPage()} -`; +import MainPage from "./pages/MainPage"; +import ProfilePage from "./pages/ProfilePage"; +import LoginPage from "./pages/LoginPage"; +import NotFoundPage from "./pages/NotFoundPage"; +import { setUser, getUser, deleteUser } from "./store/useState.js"; + +function createRouter(routes) { + return function (path) { + const route = routes[path] || routes["404"]; + return route(); + }; +} + +const routes = { + "/": () => MainPage(), + "/profile": () => ProfilePage(), + "/login": () => LoginPage(), + 404: () => NotFoundPage(), +}; + +const hashRoutes = { + "#/": () => MainPage(), + "#/profile": () => ProfilePage(), + "#/login": () => LoginPage(), + 404: () => NotFoundPage(), +}; + +const router = createRouter(routes); +const hashRouter = createRouter(hashRoutes); + +function updateContent() { + let path = window.location.pathname; + let hash = window.location.hash; + const user = getUser(); + + // 로그인된 사용자가 로그인 페이지 접근 시 메인 페이지로 리다이렉트 + if (user && (path === "/login" || hash === "#/login")) { + if (hash) { + renderHash("#/"); + } else { + render("/"); + } + return; + } + + // 비로그인 사용자가 /profile 경로 접근 시 로그인 페이지로 리다이렉트 + if (!user && (path === "/profile" || hash === "#/profile")) { + if (hash) { + renderHash("#/login"); + } else { + render("/login"); + } + return; // 추가 렌더링 방지 + } + + if (hash) { + renderHash(hash); + } else { + render(path); + } + + // 프로필 페이지인 경우 사용자 정보 렌더링 + if ((path === "/profile" || hash === "#/profile") && user) { + const { username, email, bio } = user; + document.getElementById("username").value = username; + document.getElementById("email").value = email; + document.getElementById("bio").value = bio; + } +} + +// submit 이벤트 처리 함수 +function handleSubmitEvent(event) { + event.preventDefault(); + + const target = event.target; // 이벤트가 발생한 요소 + const isHashRouting = window.location.hash !== ""; // 해시 라우팅 여부 확인 + + // 로그인 이벤트 처리 + if (target.id === "login-form") { + const username = document.getElementById("username").value; + + // 로컬스토리지에 저장 + if (username) { + setUser({ username, email: "", bio: "" }); + + updateContent(); + + if (isHashRouting) { + renderHash("#/profile"); + } else { + render("/profile"); + } + } else { + console.error("사용자 ID 또는 비밀번호가 비어 있습니다."); + } + } else if (target.id === "profile-form") { + // 프로필 업데이트 이벤트 처리 + const username = document.getElementById("username").value; + const email = document.getElementById("email").value; + const bio = document.getElementById("bio").value; + + setUser({ username, email, bio }); + } +} + +// 클릭 이벤트 처리 +function handleClickEvent(event) { + if (event.target.type === "submit") return; + event.preventDefault(); + + const target = event.target; // 이벤트가 발생한 요소 + const isHashRouting = window.location.hash !== ""; // 해시 라우팅 여부 확인 + + if (target.id === "logout") { + logout(isHashRouting); + } else if (target.id === "profile") { + moveToProfile(isHashRouting); + } else if (target.id === "home") { + moveToHome(isHashRouting); + } +} + +function logout(isHashRouting) { + deleteUser(); + if (isHashRouting) { + renderHash("#/login"); + } else { + render("/login"); + } +} + +function moveToProfile(isHashRouting) { + if (isHashRouting) { + renderHash("#/profile"); + } else { + render("/profile"); + } + + const user = getUser(); + + if (!user) { + console.error("사용자 정보가 없습니다."); + return; + } + + // 사용자 정보 입력 + const usernameField = document.getElementById("username"); + const emailField = document.getElementById("email"); + const bioField = document.getElementById("bio"); + + if (usernameField) usernameField.value = JSON.parse(user).username || ""; + if (emailField) emailField.value = JSON.parse(user).email || ""; + if (bioField) bioField.value = JSON.parse(user).bio || ""; +} + +function moveToHome(isHashRouting) { + if (isHashRouting) { + renderHash("#/"); + } else { + render("/"); + } +} + +// 렌더 함수 +function render(path) { + console.log("path", path); + window.history.pushState(null, "", path); + document.getElementById("root").innerHTML = router(path); +} + +function renderHash(hash) { + window.history.pushState(null, "", hash); + document.getElementById("root").innerHTML = hashRouter(hash); +} + +const root = document.getElementById("root"); +root.removeEventListener("submit", handleSubmitEvent); +root.addEventListener("submit", handleSubmitEvent); + +// 클릭 이벤트도 정리 후 추가 +root.removeEventListener("click", handleClickEvent); +root.addEventListener("click", handleClickEvent); + +window.addEventListener("hashchange", updateContent); +window.addEventListener("popstate", updateContent); +window.addEventListener("load", updateContent); diff --git a/src/pages/LoginPage.js b/src/pages/LoginPage.js new file mode 100644 index 00000000..8f194f83 --- /dev/null +++ b/src/pages/LoginPage.js @@ -0,0 +1,25 @@ +const LoginPage = () => ` +
+
+

항해플러스

+
+
+ +
+
+ +
+ +
+ +
+
+ +
+
+
+`; + +export default LoginPage; diff --git a/src/pages/MainPage.js b/src/pages/MainPage.js new file mode 100644 index 00000000..bbc79b5e --- /dev/null +++ b/src/pages/MainPage.js @@ -0,0 +1,104 @@ +import Header from "../components/Header"; +import Footer from "../components/Footer"; + +const MainPage = () => ` +
+
+ ${Header()} + +
+
+ + +
+ +
+ +
+
+ 프로필 +
+

홍길동

+

5분 전

+
+
+

오늘 날씨가 정말 좋네요. 다들 좋은 하루 보내세요!

+
+ + + +
+
+ +
+
+ 프로필 +
+

김철수

+

15분 전

+
+
+

새로운 프로젝트를 시작했어요. 열심히 코딩 중입니다!

+
+ + + +
+
+ +
+
+ 프로필 +
+

이영희

+

30분 전

+
+
+

오늘 점심 메뉴 추천 받습니다. 뭐가 좋을까요?

+
+ + + +
+
+ +
+
+ 프로필 +
+

박민수

+

1시간 전

+
+
+

주말에 등산 가실 분 계신가요? 함께 가요!

+
+ + + +
+
+ +
+
+ 프로필 +
+

정수연

+

2시간 전

+
+
+

새로 나온 영화 재미있대요. 같이 보러 갈 사람?

+
+ + + +
+
+
+
+ + ${Footer()} +
+
+`; + +export default MainPage; diff --git a/src/pages/NotFoundPage.js b/src/pages/NotFoundPage.js new file mode 100644 index 00000000..a401678f --- /dev/null +++ b/src/pages/NotFoundPage.js @@ -0,0 +1,17 @@ +const NotFoundPage = () => ` +
+
+

항해플러스

+

404

+

페이지를 찾을 수 없습니다

+

+ 요청하신 페이지가 존재하지 않거나 이동되었을 수 있습니다. +

+ + 홈으로 돌아가기 + +
+
+`; + +export default NotFoundPage; diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js new file mode 100644 index 00000000..4e4abe8c --- /dev/null +++ b/src/pages/ProfilePage.js @@ -0,0 +1,76 @@ +import Header from "../components/Header"; +import Footer from "../components/Footer"; + +const ProfilePage = () => { + return ` +
+
+
+ ${Header()} + +
+
+

+ 내 프로필 +

+
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+ + ${Footer()} +
+
+
+ `; +}; + +export default ProfilePage; diff --git a/src/store/useState.js b/src/store/useState.js new file mode 100644 index 00000000..3e056bc0 --- /dev/null +++ b/src/store/useState.js @@ -0,0 +1,17 @@ +const userState = { + user: JSON.parse(localStorage.getItem("user")) || null, +}; + +export function setUser(user) { + localStorage.setItem("user", JSON.stringify(user)); + userState.user = user; +} + +export function deleteUser() { + localStorage.removeItem("user"); + userState.user = null; +} + +export function getUser() { + return userState.user; +}