Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

사전과제 제출 #199

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# EditorConfig is awesome: https://EditorConfig.org

# top-most EditorConfig file
root = true

[*.{js, jsx, ts, tsx}]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
9 changes: 9 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Dont`t lint node_modules
node_modules

# Dont`t lint build output
dist

# Dont`t lint configuration
.eslintrc.json
.tsconfig.json
55 changes: 55 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": ["prettier", "plugin:import/typescript"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": "latest",
"sourceType": "module"
},
"overrides": [
{
"files": ["*.ts", "*.tsx"]
}
],

"plugins": ["react", "import"],
"rules": {
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/triple-slash-reference": "off",
"react/react-in-jsx-scope": "off",
"no-var": "error",
"no-unused-vars": ["error", { "args": "none" }],
"eqeqeq": "off",
"no-console": "off",
"import/order": [
"error",
{
"groups": ["builtin", "external", "internal", ["sibling", "parent", "index"], "type", "unknown"],
"pathGroups": [
{
"pattern": "{react,react-router**,react-dom/**}",
"group": "builtin",
"position": "after"
},
{
"pattern": "@src/**",
"group": "external",
"position": "after"
}
],
"pathGroupsExcludedImportTypes": ["react"],
"newlines-between": "always",
"alphabetize": {
"order": "asc",
"caseInsensitive": true
}
}
]
}
}
30 changes: 30 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

# eslint
.eslintcache

# env
.env
4 changes: 4 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx lint-staged
10 changes: 10 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"semi": true,
"singleQuote": true,
"useTabs": true,
"trailingComma": "all",
"arrowParens": "always",
"tabWidth": 2,
"printWidth": 130,
"endOfLine": "auto"
}
35 changes: 11 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,22 @@
# 3월 원티드 프리온보딩 프론트엔드 과정 사전과제

수강생 여러분 안녕하세요!

3월 프론트엔드 프리온보딩 과정 진행을 위해, 아래의 내용을 읽고 사전 과제를 수행해 주세요.

사전 과제는 해당 레포지토리를 포크하여 진행해 주시면 됩니다.



### 만들어야 할 것
# wanted-pre-onboarding-3-FE-quest
3월 원티드 프리온보딩 프론트엔드 과정 사전과제

## 만들어야 할 것
이번 프리온보딩에서는 레이아웃 패턴과 로그인에 대해서 다룹니다. 사전 과제에서는 현재 수강생 여러분이 가지고 있는 리액트 라우터 구성 및 레이아웃 구성에 대한 지식을 확인해 보고자 합니다.

사전 과제로써 다음 요구사항을 충족하는 리액트 어플리케이션을 구성합니다.

- NextJS 등의 SSR 어플리케이션이 아닌, CSR 어플리케이션을 구축한다.
- 최소 3개 이상의 페이지를 가지도록 구현한다.
- 모든 페이지에 공통으로 반복되는 헤더와 사이드바가 있도록 구성한다.
- [x] NextJS 등의 SSR 어플리케이션이 아닌, CSR 어플리케이션을 구축한다.
- [x] 최소 3개 이상의 페이지를 가지도록 구현한다.
- [x] 모든 페이지에 공통으로 반복되는 헤더와 사이드바가 있도록 구성한다.

즉, 다음 이미지와 같은 형태로 구현합니다.

![sample-image](./sample.jpg)
## 구현화면
<img width="1180" alt="스크린샷 2023-03-06 오전 2 45 30" src="https://user-images.githubusercontent.com/108744804/222976966-2b54f8d8-70d7-46f9-9da5-15ec329da38d.png">

이 때, 아래의 내용을 고민하며 과제를 진행해 주시면 더욱 도움이 됩니다.
## 추가 과제

- 3개의 페이지가 고정되는 앱이 아니라, 여러 개의 페이지가 언제든 추가될 수 있다고 생각하고 프로젝트를 수행해 보세요.
- 만들어진 페이지별로 로그인 여부를 판단하고자 한다면 어떻게 구조를 확장해야할지 고민해 보세요.
- HOC나 PrivateRouter를 통해 로그인 여부 판단?
- 로그인 페이지 만들기

추가로, 여유가 있다면 유저네임과 비밀번호를 받아 로그인을 수행할 수 있는 페이지를 만들어 보세요. 실제 API는 연결하지 않아도 되며, 로그인 페이지는 공통 레이아웃(상단 네비게이션 바 및 사이드바)이 적용되지 않도록 만들어 주세요.

### 질문하기 & 제출하기

- 과제 관련 질문은 해당 레포지토리에 이슈로 남겨주세요! 확인하는 대로 답변 드리도록 하겠습니다.
- 과제를 완료하셨다면 해당 레포지토리에 pull request를 남겨 제출해 주세요.
13 changes: 13 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>wanted-pre-onboarding-3</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/index.tsx"></script>
</body>
</html>
49 changes: 49 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"name": "wanted-pre-onboarding-3-fe-quest",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"prepare": "husky install",
"lint": "eslint . --fix --cache --max-warnings=0",
"pretty": "prettier . --write --cache"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.8.2",
"styled-components": "^5.3.8",
"styled-reset": "^4.4.5"
},
"devDependencies": {
"@types/react": "^18.0.27",
"@types/react-dom": "^18.0.10",
"@types/styled-components": "^5.1.26",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@vitejs/plugin-react": "^3.1.0",
"eslint": "^8.0.1",
"eslint-config-prettier": "^8.5.0",
"eslint-config-standard-with-typescript": "^34.0.0",
"eslint-import-resolver-typescript": "^3.5.2",
"eslint-import-resolver-webpack": "^0.13.2",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-n": "^15.0.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-react": "^7.32.2",
"lint-staged": "^13.0.4",
"prettier": "^2.8.0",
"husky": "^8.0.0",
"typescript": "*",
"vite": "^4.1.0"
},
"lint-staged": {
"**/*.{js,jsx,ts,tsx}": [
"yarn run pretty",
"yarn run lint"
]
}
}
1 change: 1 addition & 0 deletions public/vite.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed sample.jpg
Binary file not shown.
11 changes: 11 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Layout from './layouts';
import Router from './router';

const App = () => {
return (
<Layout>
<Router />
</Layout>
);
};
export default App;
1 change: 1 addition & 0 deletions src/assets/react.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/constants/sidebarList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const sidebarList = [
{ id: 1, name: 'Home', keyword: '' },
{ id: 2, name: 'PageA', keyword: 'a' },
{ id: 3, name: 'PageB', keyword: 'b' },
{ id: 4, name: 'PageC', keyword: 'c' },
];
19 changes: 19 additions & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';

import { ThemeProvider } from 'styled-components';

import App from './App';
import { GlobalStyle, theme } from './styles';

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode>
<BrowserRouter>
<ThemeProvider theme={theme}>
<GlobalStyle />
<App />
</ThemeProvider>
</BrowserRouter>
</React.StrictMode>,
);
11 changes: 11 additions & 0 deletions src/layouts/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as S from './styled';

const Header = () => {
return (
<S.HeaderContainer>
<S.Header>Wanted Pre-onboarding course</S.Header>
</S.HeaderContainer>
);
};

export default Header;
21 changes: 21 additions & 0 deletions src/layouts/Header/styled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import styled from 'styled-components';

export const HeaderContainer = styled.header`
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #ddd;
padding: 0 1rem;
height: 100px;
`;

export const Header = styled.div`
position: relative;
display: flex;
justify-content: flex-start;
align-items: center;
margin-left: 2rem;
width: 100%;
height: 100%;
font-weight: 700;
`;
30 changes: 30 additions & 0 deletions src/layouts/Sidebar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useEffect, useState } from 'react';
import { Link, useLocation } from 'react-router-dom';

import * as S from './styled';
import { sidebarList } from '../../constants/sidebarList';

const Sidebar = () => {
const [bgColor, setBgColor] = useState('');
const location = useLocation();
useEffect(() => {
const splitedPathname = location.pathname.split('/')[1];
const filteredName = sidebarList.filter((prev) => prev.keyword === splitedPathname)[0].name;
setBgColor(filteredName);
}, [location]);

return (
<S.SidebarContainer>
{sidebarList &&
sidebarList.map((el) => (
<S.SidebarContent bgColor={bgColor} selectedTab={el.name}>
<Link to={`/${el.keyword}`} key={el.id}>
<p>{el.name}</p>
</Link>
</S.SidebarContent>
))}
</S.SidebarContainer>
);
};

export default Sidebar;
24 changes: 24 additions & 0 deletions src/layouts/Sidebar/styled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import styled from 'styled-components';

export const SidebarContainer = styled.header`
width: 100px;
height: 100%;
border-right: 1px solid #ddd;
height: calc(100vh - 100px);
display: flex;
flex-direction: column;
a {
}
`;

export const SidebarContent = styled.div<{ bgColor: string; selectedTab: string }>`
a {
color: black;
text-decoration-line: none;

p {
margin: 1rem 0;
color: ${({ bgColor, selectedTab }) => (bgColor === selectedTab ? 'blueviolet' : 'black')};
}
}
`;
19 changes: 19 additions & 0 deletions src/layouts/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { PropsWithChildren } from 'react';

import Header from './Header';
import Sidebar from './Sidebar';
import * as S from './styled';

const Layout = (props: PropsWithChildren) => {
return (
<S.Container>
<Header />
<S.LayoutInner>
<Sidebar />
<S.PageContent className="contentDiv">{props.children}</S.PageContent>
</S.LayoutInner>
</S.Container>
);
};

export default Layout;
Loading