diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..0771b1c --- /dev/null +++ b/.babelrc @@ -0,0 +1,4 @@ +{ + "presets": ["next/babel"], + "plugins": [["styled-components", { "ssr": true }], "inline-react-svg"] +} \ No newline at end of file diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..acc230c --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +NEXT_PUBLIC_RIOT_GAMES_API_KEY=123123123 diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..6dba841 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,26 @@ +module.exports = { + env: { + browser: true, + es2021: true, + node: true, + }, + extends: [ + 'eslint:recommended', + 'plugin:react/recommended', + 'plugin:@typescript-eslint/recommended', + 'prettier', + ], + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + ecmaVersion: 12, + sourceType: 'module', + }, + plugins: ['react', '@typescript-eslint'], + rules: { + 'react/react-in-jsx-scope': 'off', // next.js에서는 React를 자동으로 주입해주기 때문에 import하지 않아도 됨. + '@typescript-eslint/explicit-module-boundary-types': 'off', // Retrun type이 유추되는 경우 Return type을 꼭 명시할 필요는 없음. + }, +}; diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d04302b --- /dev/null +++ b/.gitignore @@ -0,0 +1,35 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build +/dist + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env.local +.env.development.local +.env.test.local +.env.production.local + +# vercel +.vercel diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..555da67 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,10 @@ +{ + "singleQuote": true, + "semi": true, + "arrowParens": "always", + "printWidth": 100, + "tabWidth": 2, + "useTabs": false, + "trailingComma": "all", + "parser": "typescript" +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..5fd41e7 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# 10팀 프로젝트 diff --git a/next-env.d.ts b/next-env.d.ts new file mode 100644 index 0000000..7b7aa2c --- /dev/null +++ b/next-env.d.ts @@ -0,0 +1,2 @@ +/// +/// diff --git a/next.config.js b/next.config.js new file mode 100644 index 0000000..c22fa9f --- /dev/null +++ b/next.config.js @@ -0,0 +1,10 @@ +module.exports = { + distDir: './dist/.next', + future: { + webpack5: true, + }, + i18n: { + locales: ['ko-KR'], + defaultLocale: 'ko-KR', + }, +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..22265cf --- /dev/null +++ b/package.json @@ -0,0 +1,40 @@ +{ + "name": "team10-op-gg-clone", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "NODE_ENV=development ts-node --project tsconfig.server.json src/server.ts", + "prebuild": "rimraf ./dist", + "redev": "npm run prebuild && npm run dev", + "build:server": "tsc --project tsconfig.server.json", + "build:next": "next build", + "build": "npm run build:server && npm run build:next", + "start": "NODE_ENV=production node dist/server.js" + }, + "dependencies": { + "@types/express": "^4.17.11", + "axios": "^0.21.1", + "express": "^4.17.1", + "http-proxy-middleware": "^1.1.0", + "next": "10.1.3", + "react": "17.0.2", + "react-dom": "17.0.2", + "styled-components": "^5.2.3", + "styled-reset": "^4.3.4", + "swr": "^0.5.5" + }, + "devDependencies": { + "@types/react": "^17.0.3", + "@types/styled-components": "^5.1.9", + "@typescript-eslint/eslint-plugin": "^4.20.0", + "@typescript-eslint/parser": "^4.20.0", + "babel-plugin-inline-react-svg": "^2.0.1", + "babel-plugin-styled-components": "^1.12.0", + "eslint": "^7.23.0", + "eslint-config-prettier": "^8.1.0", + "eslint-plugin-react": "^7.23.1", + "rimraf": "^3.0.2", + "ts-node": "^9.1.1", + "typescript": "^4.2.3" + } +} diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..4965832 Binary files /dev/null and b/public/favicon.ico differ diff --git a/src/api/client.ts b/src/api/client.ts new file mode 100644 index 0000000..9a10e5a --- /dev/null +++ b/src/api/client.ts @@ -0,0 +1,6 @@ +import axios, { AxiosInstance, AxiosRequestConfig } from 'axios'; + +const config: AxiosRequestConfig = {}; +const client: AxiosInstance = axios.create(config); + +export default client; diff --git a/src/constants/env.ts b/src/constants/env.ts new file mode 100644 index 0000000..f39a432 --- /dev/null +++ b/src/constants/env.ts @@ -0,0 +1,2 @@ +export const IS_PROD = process.env.NODE_ENV === 'production'; +export const IS_SERVER = typeof window === 'undefined'; diff --git a/src/constants/index.ts b/src/constants/index.ts new file mode 100644 index 0000000..c1532d6 --- /dev/null +++ b/src/constants/index.ts @@ -0,0 +1 @@ +export * from './env'; diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx new file mode 100644 index 0000000..8ff59a1 --- /dev/null +++ b/src/pages/_app.tsx @@ -0,0 +1,17 @@ +import { AppProps } from 'next/app'; +import GlobalStyle from '@/styles/GlobalStyle'; + +function MyApp({ Component, pageProps }: AppProps) { + return ( + <> + +
레이아웃 헤더
+
+ +
+
레이아웃 푸터
+ + ); +} + +export default MyApp; diff --git a/src/pages/_document.tsx b/src/pages/_document.tsx new file mode 100644 index 0000000..7a83574 --- /dev/null +++ b/src/pages/_document.tsx @@ -0,0 +1,29 @@ +import Document, { DocumentContext } from 'next/document'; +import { ServerStyleSheet } from 'styled-components'; + +export default class MyDocument extends Document { + static async getInitialProps(ctx: DocumentContext) { + const sheet = new ServerStyleSheet(); + const originalRenderPage = ctx.renderPage; + + try { + ctx.renderPage = () => + originalRenderPage({ + enhanceApp: (App) => (props) => sheet.collectStyles(), + }); + + const initialProps = await Document.getInitialProps(ctx); + return { + ...initialProps, + styles: ( + <> + {initialProps.styles} + {sheet.getStyleElement()} + + ), + }; + } finally { + sheet.seal(); + } + } +} diff --git a/src/pages/champions/[champion].tsx b/src/pages/champions/[champion].tsx new file mode 100644 index 0000000..3ce44d8 --- /dev/null +++ b/src/pages/champions/[champion].tsx @@ -0,0 +1,15 @@ +import { useRouter } from 'next/router'; + +function Champion() { + const router = useRouter(); + // 챔피언 이름 + const { champion } = router.query; + return ( + <> +

# 챔피언 상세보기

+

{champion}

+ + ); +} + +export default Champion; diff --git a/src/pages/champions/index.tsx b/src/pages/champions/index.tsx new file mode 100644 index 0000000..e602836 --- /dev/null +++ b/src/pages/champions/index.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +function Champions() { + return ( + <> +

# 챔피언 분석

+ + ); +} + +export default Champions; diff --git a/src/pages/index.tsx b/src/pages/index.tsx new file mode 100644 index 0000000..403d620 --- /dev/null +++ b/src/pages/index.tsx @@ -0,0 +1,16 @@ +import client from '@/api/client'; +import { useEffect } from 'react'; +export default function Home() { + useEffect(() => { + const a = async () => { + const response = await client.get('/lol/clash/v1/tournaments'); + console.log(response.data); + }; + a(); + }, []); + return ( + <> +

# 검색 메인페이지

+ + ); +} diff --git a/src/pages/ranking/champions.tsx b/src/pages/ranking/champions.tsx new file mode 100644 index 0000000..ec12c5e --- /dev/null +++ b/src/pages/ranking/champions.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +function ChampionsRangking() { + return ( + <> +

# 챔피온 랭킹

+ + ); +} + +export default ChampionsRangking; diff --git a/src/pages/ranking/index.tsx b/src/pages/ranking/index.tsx new file mode 100644 index 0000000..d0394e9 --- /dev/null +++ b/src/pages/ranking/index.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +function Ranking() { + return ( + <> +

래더 랭킹으로 리다이렉트

+ + ); +} + +export default Ranking; diff --git a/src/pages/ranking/ladder.tsx b/src/pages/ranking/ladder.tsx new file mode 100644 index 0000000..dd7ee06 --- /dev/null +++ b/src/pages/ranking/ladder.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +function LadderRanking() { + return ( + <> +

# 래더 랭킹

+ + ); +} + +export default LadderRanking; diff --git a/src/pages/ranking/level.tsx b/src/pages/ranking/level.tsx new file mode 100644 index 0000000..7d4a10c --- /dev/null +++ b/src/pages/ranking/level.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +function LevelRanking() { + return ( + <> +

# 레벨 랭킹

+ + ); +} + +export default LevelRanking; diff --git a/src/pages/statistics/champions.tsx b/src/pages/statistics/champions.tsx new file mode 100644 index 0000000..21a7bb4 --- /dev/null +++ b/src/pages/statistics/champions.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +function ChampionState() { + return ( + <> +

# 챔피언 통계

+ + ); +} + +export default ChampionState; diff --git a/src/pages/statistics/index.tsx b/src/pages/statistics/index.tsx new file mode 100644 index 0000000..bd35289 --- /dev/null +++ b/src/pages/statistics/index.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +function Statistics() { + return ( + <> +

챔피언 통계로 리다이렉트

+ + ); +} + +export default Statistics; diff --git a/src/pages/statistics/tier.tsx b/src/pages/statistics/tier.tsx new file mode 100644 index 0000000..fce19ef --- /dev/null +++ b/src/pages/statistics/tier.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +function TierState() { + return ( + <> +

# 티어 통계

+ + ); +} + +export default TierState; diff --git a/src/pages/users/[user].tsx b/src/pages/users/[user].tsx new file mode 100644 index 0000000..6677637 --- /dev/null +++ b/src/pages/users/[user].tsx @@ -0,0 +1,15 @@ +import { useRouter } from 'next/router'; +import React from 'react'; + +function User() { + const router = useRouter(); + const { user } = router.query; + return ( + <> +

# 유저 상세보기

+

{user}

+ + ); +} + +export default User; diff --git a/src/pages/users/index.tsx b/src/pages/users/index.tsx new file mode 100644 index 0000000..2721d8f --- /dev/null +++ b/src/pages/users/index.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +function Users() { + return ( + <> +

유저 검색(나중에)

+ + ); +} + +export default Users; diff --git a/src/server.ts b/src/server.ts new file mode 100644 index 0000000..80e08e9 --- /dev/null +++ b/src/server.ts @@ -0,0 +1,35 @@ +import next from 'next'; +import express from 'express'; +import { createProxyMiddleware, Options } from 'http-proxy-middleware'; + +import { IS_PROD } from './constants'; + +const PORT = IS_PROD ? 3000 : 3000; + +async function bootstrap() { + const app = express(); + const nextApp = next({ dev: !IS_PROD }); + await nextApp.prepare(); + + const handle = nextApp.getRequestHandler(); + + app.use( + '/lol', + createProxyMiddleware({ + target: process.env.API_ENDPOINT, + changeOrigin: true, + onProxyReq(proxyRes) { + proxyRes.setHeader('X-Riot-Token', process.env.RIOT_GAMES_API_KEY as string); + }, + }), + ); + app.use(express.json()); + + app.all('*', (req, res) => handle(req, res)); + + app.listen(PORT, () => { + console.log(`>Ready on http://localhost:${PORT} -env ${process.env.NODE_ENV}`); + }); +} + +bootstrap(); diff --git a/src/styles/GlobalStyle.ts b/src/styles/GlobalStyle.ts new file mode 100644 index 0000000..c50dc84 --- /dev/null +++ b/src/styles/GlobalStyle.ts @@ -0,0 +1,25 @@ +import reset from 'styled-reset'; +import { createGlobalStyle, css } from 'styled-components'; + +const globalStyle = css` + ${reset}; + * { + box-sizing: border-box; + } + body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, + 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', + 'Noto Color Emoji'; + font-size: 16px; + line-height: 1.75; + } + a { + text-decoration: none; + } +`; + +const GlobalStyle = createGlobalStyle` + ${globalStyle}; +`; + +export default GlobalStyle; diff --git a/src/types/env.d.ts b/src/types/env.d.ts new file mode 100644 index 0000000..688477a --- /dev/null +++ b/src/types/env.d.ts @@ -0,0 +1,7 @@ +declare namespace NodeJS { + export interface ProcessEnv { + NODE_ENV: 'development' | 'production'; + API_ENDPOINT: string; + RIOT_GAMES_API_KEY: string; + } +} diff --git a/src/types/image.d.ts b/src/types/image.d.ts new file mode 100644 index 0000000..bff9471 --- /dev/null +++ b/src/types/image.d.ts @@ -0,0 +1 @@ +declare module '*.svg'; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..e6a8761 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "typeRoots": ["src/types", "node_modules/types"], + "baseUrl": "./src", + "paths": { + "@/*": ["./*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"] +} diff --git a/tsconfig.server.json b/tsconfig.server.json new file mode 100644 index 0000000..093ce90 --- /dev/null +++ b/tsconfig.server.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "CommonJS", + "outDir": "./dist", + "noEmit": false + }, + "include": ["src/server.ts"] +} \ No newline at end of file