diff --git a/package.json b/package.json index c1935d3..dde7350 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "dependencies": { "eslint-import-resolver-typescript": "^4.4.4", "react": "^19.2.0", - "react-dom": "^19.2.0" + "react-dom": "^19.2.0", + "react-router-dom": "^7.11.0" }, "devDependencies": { "@eslint/js": "^9.39.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8c3bcfe..d674ae1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,9 @@ importers: react-dom: specifier: ^19.2.0 version: 19.2.3(react@19.2.3) + react-router-dom: + specifier: ^7.11.0 + version: 7.11.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) devDependencies: '@eslint/js': specifier: ^9.39.1 @@ -1226,6 +1229,10 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cookie@1.1.1: + resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} + engines: {node: '>=18'} + cosmiconfig@8.3.6: resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} engines: {node: '>=14'} @@ -2160,6 +2167,23 @@ packages: react-is@17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + react-router-dom@7.11.0: + resolution: {integrity: sha512-e49Ir/kMGRzFOOrYQBdoitq3ULigw4lKbAyKusnvtDu2t4dBX4AGYPrzNvorXmVuOyeakai6FUPW5MmibvVG8g==} + engines: {node: '>=20.0.0'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + + react-router@7.11.0: + resolution: {integrity: sha512-uI4JkMmjbWCZc01WVP2cH7ZfSzH91JAZUDd7/nIprDgWxBV1TkkmLToFh7EbMTcMak8URFRa2YoBL/W8GWnCTQ==} + engines: {node: '>=20.0.0'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + peerDependenciesMeta: + react-dom: + optional: true + react@19.2.3: resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==} engines: {node: '>=0.10.0'} @@ -2229,6 +2253,9 @@ packages: engines: {node: '>=10'} hasBin: true + set-cookie-parser@2.7.2: + resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} + set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -3666,6 +3693,8 @@ snapshots: convert-source-map@2.0.0: {} + cookie@1.1.1: {} + cosmiconfig@8.3.6(typescript@5.9.3): dependencies: import-fresh: 3.3.1 @@ -4728,6 +4757,20 @@ snapshots: react-is@17.0.2: {} + react-router-dom@7.11.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3): + dependencies: + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + react-router: 7.11.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + + react-router@7.11.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3): + dependencies: + cookie: 1.1.1 + react: 19.2.3 + set-cookie-parser: 2.7.2 + optionalDependencies: + react-dom: 19.2.3(react@19.2.3) + react@19.2.3: {} recast@0.23.11: @@ -4837,6 +4880,8 @@ snapshots: semver@7.7.3: {} + set-cookie-parser@2.7.2: {} + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 diff --git a/src/app/App.tsx b/src/app/App.tsx index d9f3bb9..d8a6add 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -1,9 +1,11 @@ -import { HomePage } from "@/pages/home/home-page"; +import { RouterProvider } from "react-router-dom"; + +import { router } from "./routes/app-router"; const App = () => { return ( <> - + ); }; diff --git a/src/app/routes/app-router.tsx b/src/app/routes/app-router.tsx new file mode 100644 index 0000000..7c84f81 --- /dev/null +++ b/src/app/routes/app-router.tsx @@ -0,0 +1,18 @@ +import { createBrowserRouter } from "react-router-dom"; + +import { protectedRoutes } from "./protected-routes"; +import { publicRoutes } from "./public-routes"; + +export const router = createBrowserRouter([ + { + path: "/", + // element: , TODO: RootLayout 추가 + children: [ + ...publicRoutes, + + // TODO: auth에 따른 처리 추가 + ...protectedRoutes, + // TODO: paths 이외의 경로 접근 시 error 처리 + ], + }, +]); diff --git a/src/app/routes/paths.ts b/src/app/routes/paths.ts new file mode 100644 index 0000000..3072bf7 --- /dev/null +++ b/src/app/routes/paths.ts @@ -0,0 +1,18 @@ +export const ROUTES = { + HOME: "/", + LOGIN: "/login", + ONBOARDING: "/onboarding", + COMPANY: (id = ":id") => `/company/${id}`, // 기업 상세 + EXPERIENCE_MATCHING: "/experience-matching", // 경험x기업 매칭 + + MATCHING_LIST: "/matching", // 경험x기업 매칭 결과 리스트 + MATCHING_DETAIL: (id = ":id") => `/matching/${id}`, // 매칭 결과 상세 + + EXPERIENCE: "/experience", // 경험 목록 + EXPERIENCE_CREATE: "/experience/create", // 경험 생성 + EXPERIENCE_DETAIL: (id = ":id") => `/experience/${id}`, // 경험 상세 + EXPERIENCE_EDIT: (id = ":id") => `/experience/${id}/edit`, // 경험 수정 + + MYPAGE: "/mypage", + BOOKMARK: "/bookmark", +}; diff --git a/src/app/routes/protected-routes.tsx b/src/app/routes/protected-routes.tsx new file mode 100644 index 0000000..808c71b --- /dev/null +++ b/src/app/routes/protected-routes.tsx @@ -0,0 +1,42 @@ +import { BookmarkPage } from "@/pages/bookmark/bookmark-page"; +import { CompanyDetailPage } from "@/pages/company-detail/company-detail-page"; +import { ExperiencePage } from "@/pages/experience/experience-page"; +import { ExperienceDetailPage } from "@/pages/experience-detail/experience-detail-page"; +import { ExperienceMatchingPage } from "@/pages/experience-matching/experience-matching-page"; +import { HomePage } from "@/pages/home/home-page"; +import { MatchingDetailPage } from "@/pages/matching-detail/matching-detail-page"; +import { MatchingListPage } from "@/pages/matching-list/matching-list-page"; +import { MyPage } from "@/pages/my-page/my-page"; +import { OnboardingPage } from "@/pages/onboarding/onboarding-page"; + +import { ROUTES } from "./paths"; + +export const protectedRoutes = [ + { path: ROUTES.HOME, element: }, + { path: ROUTES.ONBOARDING, element: }, + + { path: ROUTES.COMPANY(), element: }, + { path: ROUTES.EXPERIENCE_MATCHING, element: }, + + // 매칭 결과 + { path: ROUTES.MATCHING_LIST, element: }, + { path: ROUTES.MATCHING_DETAIL(), element: }, + + // 경험 + { path: ROUTES.EXPERIENCE, element: }, + { + path: ROUTES.EXPERIENCE_CREATE, + element: , + }, + { + path: ROUTES.EXPERIENCE_DETAIL(), + element: , + }, + { + path: ROUTES.EXPERIENCE_EDIT(), + element: , + }, + + { path: ROUTES.MYPAGE, element: }, + { path: ROUTES.BOOKMARK, element: }, +]; diff --git a/src/app/routes/public-routes.tsx b/src/app/routes/public-routes.tsx new file mode 100644 index 0000000..d37f285 --- /dev/null +++ b/src/app/routes/public-routes.tsx @@ -0,0 +1,5 @@ +import { LoginPage } from "@/pages/login/login-page"; + +import { ROUTES } from "./paths"; + +export const publicRoutes = [{ path: ROUTES.LOGIN, element: }]; diff --git a/src/pages/bookmark/.gitkeep b/src/pages/bookmark/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/pages/bookmark/bookmark-page.tsx b/src/pages/bookmark/bookmark-page.tsx new file mode 100644 index 0000000..b6b2512 --- /dev/null +++ b/src/pages/bookmark/bookmark-page.tsx @@ -0,0 +1,9 @@ +const BookmarkPage = () => { + return ( +
+

Welcome to the Bookmark Page

+
+ ); +}; + +export { BookmarkPage }; \ No newline at end of file diff --git a/src/pages/company-analyze/.gitkeep b/src/pages/company-analyze/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/pages/company-detail/company-detail-page.tsx b/src/pages/company-detail/company-detail-page.tsx new file mode 100644 index 0000000..39b312d --- /dev/null +++ b/src/pages/company-detail/company-detail-page.tsx @@ -0,0 +1,12 @@ +import { useParams } from "react-router-dom"; + +const CompanyDetailPage = () => { + const { id } = useParams<{ id: string }>(); + return ( +
+

Company Detail Page - {id}

+
+ ); +}; + +export { CompanyDetailPage }; diff --git a/src/pages/experience-detail/experience-detail-page.tsx b/src/pages/experience-detail/experience-detail-page.tsx new file mode 100644 index 0000000..417104b --- /dev/null +++ b/src/pages/experience-detail/experience-detail-page.tsx @@ -0,0 +1,24 @@ +import { useParams } from "react-router-dom"; + +import { ExperienceForm } from "./ui/experience-form"; +import { ExperienceViewer } from "./ui/experience-viewer"; + +type mode = "view" | "edit" | "create"; + +interface ExperiencePageProps { + mode: mode; +} + +const ExperienceDetailPage = ({ mode }: ExperiencePageProps) => { + const { id } = useParams<{ id: string }>(); + switch (mode) { + case "view": + return ; + + case "create": + case "edit": + return ; + } +}; + +export { ExperienceDetailPage }; diff --git a/src/pages/experience-detail/ui/experience-form.tsx b/src/pages/experience-detail/ui/experience-form.tsx new file mode 100644 index 0000000..23243ab --- /dev/null +++ b/src/pages/experience-detail/ui/experience-form.tsx @@ -0,0 +1,19 @@ +type mode = "create" | "edit"; + +interface ExperienceFormProps { + mode: mode; + id?: string; +} + +const ExperienceForm = ({ mode, id }: ExperienceFormProps) => { + // TODO: mode에 따라 isEdit 모드 분기 처리 + return ( +
+

+ Experience Form - {mode} {mode === "edit" && `${id}`} +

+
+ ); +}; + +export { ExperienceForm }; diff --git a/src/pages/experience-detail/ui/experience-viewer.tsx b/src/pages/experience-detail/ui/experience-viewer.tsx new file mode 100644 index 0000000..7f978e8 --- /dev/null +++ b/src/pages/experience-detail/ui/experience-viewer.tsx @@ -0,0 +1,12 @@ +import { useParams } from "react-router-dom"; + +const ExperienceViewer = () => { + const { id } = useParams<{ id: string }>(); + return ( +
+

Experience Viewer - {id}

+
+ ); +}; + +export { ExperienceViewer }; diff --git a/src/pages/experience-matching/experience-matching-page.tsx b/src/pages/experience-matching/experience-matching-page.tsx new file mode 100644 index 0000000..d0f59e6 --- /dev/null +++ b/src/pages/experience-matching/experience-matching-page.tsx @@ -0,0 +1,9 @@ +const ExperienceMatchingPage = () => { + return ( +
+

Welcome to the Experience Matching Page

+
+ ); +}; + +export { ExperienceMatchingPage }; \ No newline at end of file diff --git a/src/pages/experience/.gitkeep b/src/pages/experience/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/pages/experience/experience-page.tsx b/src/pages/experience/experience-page.tsx new file mode 100644 index 0000000..3b429f0 --- /dev/null +++ b/src/pages/experience/experience-page.tsx @@ -0,0 +1,9 @@ +const ExperiencePage = () => { + return ( +
+

Experience List Page

+
+ ); +}; + +export { ExperiencePage }; diff --git a/src/pages/home/home-page.tsx b/src/pages/home/home-page.tsx index 71d0dcf..0be0346 100644 --- a/src/pages/home/home-page.tsx +++ b/src/pages/home/home-page.tsx @@ -1,12 +1,12 @@ +import Heart from "@icons/heart.svg?react"; import KERORO from "@images/comfit_web_status.jpg"; -import Heart from "@icons/heart.svg?react" const HomePage = () => { return (

Welcome to the Home Page

Keroro - +
); }; diff --git a/src/pages/login/.gitkeep b/src/pages/login/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/pages/login/login-page.tsx b/src/pages/login/login-page.tsx new file mode 100644 index 0000000..e36f0b1 --- /dev/null +++ b/src/pages/login/login-page.tsx @@ -0,0 +1,9 @@ +const LoginPage = () => { + return ( +
+

Welcome to the Login Page

+
+ ); +}; + +export { LoginPage }; \ No newline at end of file diff --git a/src/pages/matching-detail/matching-detail-page.tsx b/src/pages/matching-detail/matching-detail-page.tsx new file mode 100644 index 0000000..3132b5c --- /dev/null +++ b/src/pages/matching-detail/matching-detail-page.tsx @@ -0,0 +1,12 @@ +import { useParams } from "react-router-dom"; + +const MatchingDetailPage = () => { + const { id } = useParams<{ id: string }>(); + return ( +
+

Welcome to the Matching Detail Page - {id}

+
+ ); +}; + +export { MatchingDetailPage }; diff --git a/src/pages/matching-list/matching-list-page.tsx b/src/pages/matching-list/matching-list-page.tsx new file mode 100644 index 0000000..d0efe40 --- /dev/null +++ b/src/pages/matching-list/matching-list-page.tsx @@ -0,0 +1,9 @@ +const MatchingListPage = () => { + return ( +
+

Welcome to the Matching List Page

+
+ ); +}; + +export { MatchingListPage }; diff --git a/src/pages/my-page/.gitkeep b/src/pages/my-page/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/pages/my-page/my-page.tsx b/src/pages/my-page/my-page.tsx new file mode 100644 index 0000000..ffa4ab3 --- /dev/null +++ b/src/pages/my-page/my-page.tsx @@ -0,0 +1,9 @@ +const MyPage = () => { + return ( +
+

Welcome to the My Page

+
+ ); +}; + +export { MyPage }; \ No newline at end of file diff --git a/src/pages/onboarding/.gitkeep b/src/pages/onboarding/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/pages/onboarding/onboarding-page.tsx b/src/pages/onboarding/onboarding-page.tsx new file mode 100644 index 0000000..ff445eb --- /dev/null +++ b/src/pages/onboarding/onboarding-page.tsx @@ -0,0 +1,9 @@ +const OnboardingPage = () => { + return ( +
+

Welcome to the Onboarding Page

+
+ ); +}; + +export { OnboardingPage }; \ No newline at end of file diff --git a/src/pages/register/.gitkeep b/src/pages/register/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/pages/register/register-page.tsx b/src/pages/register/register-page.tsx new file mode 100644 index 0000000..227c5b8 --- /dev/null +++ b/src/pages/register/register-page.tsx @@ -0,0 +1,9 @@ +const RegisterPage = () => { + return ( +
+

Welcome to the Register Page

+
+ ); +}; + +export { RegisterPage }; \ No newline at end of file