diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 88209359..d6c90e0f 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -16,15 +16,16 @@ module.exports = { parser: '@typescript-eslint/parser', plugins: ['react-refresh'], rules: { - 'import/no-extraneous-dependencies': "off", + 'import/no-extraneous-dependencies': 'off', + 'import/prefer-default-export': 'off', 'react-refresh/only-export-components': [ 'warn', { allowConstantExport: true }, ], - "react/react-in-jsx-scope": "off" + 'react/react-in-jsx-scope': 'off', }, parserOptions: { tsconfigRootDir: './', - project: ['./tsconfig.json', './tsconfig.app.json', './tsconfig.node.json'] + project: ['./tsconfig.json', './tsconfig.app.json', './tsconfig.node.json'], }, }; diff --git a/package-lock.json b/package-lock.json index 19ec8fa7..f20a4e0b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,9 @@ "@reduxjs/toolkit": "^2.2.6", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-redux": "^9.1.2" + "react-icons": "^5.2.1", + "react-redux": "^9.1.2", + "react-router-dom": "^6.25.1" }, "devDependencies": { "@testing-library/jest-dom": "^6.4.6", @@ -1178,6 +1180,14 @@ } } }, + "node_modules/@remix-run/router": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.18.0.tgz", + "integrity": "sha512-L3jkqmqoSVBVKHfpGZmLrex0lxR5SucGA0sUfFzGctehw+S/ggL9L/0NnC5mw6P8HUWpFZ3nQw3cRApjjWx9Sw==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.18.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.1.tgz", @@ -6605,6 +6615,14 @@ "react": "^18.3.1" } }, + "node_modules/react-icons": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.2.1.tgz", + "integrity": "sha512-zdbW5GstTzXaVKvGSyTaBalt7HSfuK5ovrzlpyiWHAFXndXTdd/1hdDHI4xBM1Mn7YriT6aqESucFl9kEXzrdw==", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -6642,6 +6660,36 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "6.25.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.25.1.tgz", + "integrity": "sha512-u8ELFr5Z6g02nUtpPAggP73Jigj1mRePSwhS/2nkTrlPU5yEkH1vYzWNyvSnSzeeE2DNqWdH+P8OhIh9wuXhTw==", + "dependencies": { + "@remix-run/router": "1.18.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.25.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.25.1.tgz", + "integrity": "sha512-0tUDpbFvk35iv+N89dWNrJp+afLgd+y4VtorJZuOCXK0kkCWjEvb3vTJM++SYvMEpbVwXKf3FjeVveVEb6JpDQ==", + "dependencies": { + "@remix-run/router": "1.18.0", + "react-router": "6.25.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", diff --git a/package.json b/package.json index 944995a5..48dad6c4 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,9 @@ "@reduxjs/toolkit": "^2.2.6", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-redux": "^9.1.2" + "react-icons": "^5.2.1", + "react-redux": "^9.1.2", + "react-router-dom": "^6.25.1" }, "devDependencies": { "@testing-library/jest-dom": "^6.4.6", diff --git a/public/air-jordan-row.jpeg b/public/air-jordan-row.jpeg new file mode 100644 index 00000000..318207ad Binary files /dev/null and b/public/air-jordan-row.jpeg differ diff --git a/src/App.tsx b/src/App.tsx index 6489bcd2..fc4c6204 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,16 @@ -import React from 'react'; +import { RouterProvider, createBrowserRouter } from 'react-router-dom'; + +import Home from './pages/home'; function App() { - return
app
; + const router = createBrowserRouter([ + { + path: '/', + element: , + }, + ]); + + return ; } + export default App; diff --git a/src/components/CategoryList.tsx b/src/components/CategoryList.tsx new file mode 100644 index 00000000..fd2a6fb5 --- /dev/null +++ b/src/components/CategoryList.tsx @@ -0,0 +1,26 @@ +import { categories } from '../constants/categories'; + +function CategoryItem({ name }: { name: string }) { + return ( +
+ air-jordan-row +
{name}
+
+ ); +} + +function CategoryList() { + return ( +
+ {Object.values(categories).map((value: string) => ( + + ))} +
+ ); +} + +export default CategoryList; diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx new file mode 100644 index 00000000..11898f78 --- /dev/null +++ b/src/components/Footer.tsx @@ -0,0 +1,19 @@ +import { + AiOutlineBell, + AiOutlineHeart, + AiOutlineHome, + AiOutlineUser, +} from 'react-icons/ai'; + +function Footer() { + return ( +
+ + + + +
+ ); +} + +export default Footer; diff --git a/src/components/Header.tsx b/src/components/Header.tsx new file mode 100644 index 00000000..aa34e151 --- /dev/null +++ b/src/components/Header.tsx @@ -0,0 +1,9 @@ +function Header({ name }: { name: string }) { + return ( +
+ {name} +
+ ); +} + +export default Header; diff --git a/src/components/HomeItem.tsx b/src/components/HomeItem.tsx new file mode 100644 index 00000000..7f758562 --- /dev/null +++ b/src/components/HomeItem.tsx @@ -0,0 +1,24 @@ +import { AiOutlineUsergroupDelete } from 'react-icons/ai'; + +function HomeItem() { + return ( +
+
+ air-jordan-row +
+ 16시간 남음 +
+
+
+
[나이키] 신발
+
10,000원 (시작가)
+
+ + 11명 참여 중 +
+
+
+ ); +} + +export default HomeItem; diff --git a/src/components/HomeItemList.tsx b/src/components/HomeItemList.tsx new file mode 100644 index 00000000..3a100849 --- /dev/null +++ b/src/components/HomeItemList.tsx @@ -0,0 +1,20 @@ +import { ReactNode } from 'react'; + +function HomeItemList({ + children, + name, +}: { + children: ReactNode; + name: string; +}) { + return ( +
+
{name}
+
+ {children} +
+
+ ); +} + +export default HomeItemList; diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx new file mode 100644 index 00000000..1a052515 --- /dev/null +++ b/src/components/Layout.tsx @@ -0,0 +1,23 @@ +import { ReactNode } from 'react'; + +interface LayoutProps { + header: ReactNode; + children: ReactNode; + footer: ReactNode; +} + +function Layout({ header, children, footer }: LayoutProps) { + return ( +
+
+ {header} +
+ {children} +
+ {footer && footer} +
+
+ ); +} + +export default Layout; diff --git a/src/constants/categories.ts b/src/constants/categories.ts new file mode 100644 index 00000000..a9b2542e --- /dev/null +++ b/src/constants/categories.ts @@ -0,0 +1,10 @@ +export const categories = Object.freeze({ + Electronics: '전자기기', + HomeAppliances: '가전제품', + FashionClothing: '패션 및 의류', + FurnitureInterior: '가구 및 인테리어', + BooksMedia: '도서 및 미디어', + SportsLeisure: '스포츠 및 레저', + ToysHobbies: '장난감 및 취미', + Others: '기타', +}); diff --git a/src/pages/home.tsx b/src/pages/home.tsx new file mode 100644 index 00000000..695a071d --- /dev/null +++ b/src/pages/home.tsx @@ -0,0 +1,39 @@ +import CategoryList from '../components/CategoryList'; +import Footer from '../components/Footer'; +import Header from '../components/Header'; +import HomeItem from '../components/HomeItem'; +import HomeItemList from '../components/HomeItemList'; +import Layout from '../components/Layout'; + +function Home() { + return ( + } footer={