├── .dockerignore
├── .gitignore
├── API.md
├── Dockerfile
├── README.md
├── app.py
├── exception.py
├── model.py
├── package-lock.json
├── package.json
├── requirements.txt
└── results
├── AnJaeSeongS2
├── .babelrc
├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .postcssrc.js
├── .prettierrc
├── README.md
├── babel.config.js
├── cypress.json
├── doc
│ └── image
│ │ ├── login.png
│ │ └── userInfo.png
├── jest.config.js
├── package.json
├── pilot-auth api.postman_collection.json
├── public
│ ├── favicon.ico
│ └── icons
│ │ ├── favicon-128x128.png
│ │ ├── favicon-16x16.png
│ │ ├── favicon-32x32.png
│ │ └── favicon-96x96.png
├── quasar.conf.js
├── quasar.extensions.json
├── quasar.testing.json
├── src
│ ├── App.vue
│ ├── assets
│ │ └── quasar-logo-vertical.svg
│ ├── boot
│ │ ├── .gitkeep
│ │ └── axios.ts
│ ├── components
│ │ └── models.ts
│ ├── css
│ │ ├── app.scss
│ │ └── quasar.variables.scss
│ ├── index.template.html
│ ├── layouts
│ │ └── MainLayout.vue
│ ├── pages
│ │ ├── Error404.vue
│ │ ├── Index.vue
│ │ ├── Login.vue
│ │ └── users
│ │ │ ├── Info.vue
│ │ │ └── InfoItem.vue
│ ├── router
│ │ ├── index.ts
│ │ └── routes.ts
│ ├── shims-vue.d.ts
│ └── store
│ │ ├── index.ts
│ │ ├── loginToken
│ │ ├── actions.ts
│ │ ├── getters.ts
│ │ ├── index.ts
│ │ ├── mutations.ts
│ │ └── state.ts
│ │ └── store-flag.d.ts
├── test
│ ├── cypress
│ │ ├── .eslintrc.js
│ │ ├── .gitignore
│ │ ├── fixtures
│ │ │ └── example.json
│ │ ├── integration
│ │ │ └── home.spec.ts
│ │ ├── plugins
│ │ │ └── index.ts
│ │ ├── support
│ │ │ ├── commands.ts
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ └── jest
│ │ ├── .eslintrc.js
│ │ ├── .gitignore
│ │ ├── __tests__
│ │ └── pages
│ │ │ └── users
│ │ │ └── Info.test.ts
│ │ └── jest.setup.ts
└── tsconfig.json
├── Kim-Jaemin420
└── pilot-react
│ ├── .eslintrc
│ ├── .gitignore
│ ├── .nvmrc
│ ├── .prettierrc
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
│ ├── src
│ ├── App.test.js
│ ├── App.tsx
│ ├── FetchData
│ │ ├── HttpFetch.ts
│ │ ├── LoginData.ts
│ │ └── UserData.ts
│ ├── components
│ │ ├── Home.tsx
│ │ ├── Login.tsx
│ │ └── common
│ │ │ └── CommonBtn.tsx
│ ├── hooks
│ │ └── useInputChange.ts
│ ├── index.tsx
│ └── styles
│ │ └── GlobalStyle.ts
│ └── tsconfig.json
├── boksilab
├── .firebase
│ └── hosting.YnVpbGQ.cache
├── .firebaserc
├── .gitignore
├── README.md
├── firebase.json
├── package-lock.json
├── package.json
├── public
│ ├── Login.gltf
│ ├── favicon.ico
│ ├── font
│ │ ├── D2.json
│ │ └── Godo.json
│ ├── image
│ │ ├── blackhole.png
│ │ └── skybox
│ │ │ ├── B.jpg
│ │ │ ├── D.jpg
│ │ │ ├── F.jpg
│ │ │ ├── L.jpg
│ │ │ ├── R.jpg
│ │ │ └── U.jpg
│ ├── index.html
│ └── sfx
│ │ ├── fall1.wav
│ │ ├── fall2.wav
│ │ ├── fall3.wav
│ │ └── fall4.wav
├── src
│ ├── Api.tsx
│ ├── App.test.tsx
│ ├── App.tsx
│ ├── Godo.ttf
│ ├── Phase.ts
│ ├── Response.ts
│ ├── TabIndex.ts
│ ├── UserInfo.ts
│ ├── components
│ │ ├── Blackhole.tsx
│ │ ├── Button.tsx
│ │ ├── Camera.tsx
│ │ ├── Canvas.tsx
│ │ ├── Card.tsx
│ │ ├── Character.tsx
│ │ ├── Credit.tsx
│ │ ├── InputField.tsx
│ │ ├── Lights.tsx
│ │ ├── LogoutButton.tsx
│ │ ├── ProgressBar.tsx
│ │ ├── Skybox.tsx
│ │ ├── Sound.tsx
│ │ ├── StaticText.tsx
│ │ ├── Text.tsx
│ │ ├── TextStatic.tsx
│ │ ├── UserInfoView.tsx
│ │ └── Warp.tsx
│ ├── index.css
│ ├── index.tsx
│ ├── react-app-env.d.ts
│ ├── reportWebVitals.ts
│ └── setupTests.ts
└── tsconfig.json
├── byeongukchoi
├── .browserslistrc
├── .eslintrc.js
├── .gitignore
├── README.md
├── babel.config.js
├── package.json
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── App.vue
│ ├── api
│ │ └── index.ts
│ ├── assets
│ │ └── logo.png
│ ├── components
│ │ └── Profile.vue
│ ├── main.ts
│ ├── models
│ │ ├── LoginRequest.ts
│ │ ├── LoginResponse.ts
│ │ ├── Token.ts
│ │ └── User.ts
│ ├── router
│ │ └── index.ts
│ ├── shims-tsx.d.ts
│ ├── shims-vue.d.ts
│ ├── store
│ │ └── index.ts
│ ├── utils
│ │ └── cookies.ts
│ └── views
│ │ ├── Home.vue
│ │ └── Login.vue
├── tests
│ └── unit
│ │ └── example.spec.ts
└── tsconfig.json
├── cozy60
├── .gitignore
├── .prettierrc
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
├── src
│ ├── App.css
│ ├── App.test.tsx
│ ├── App.tsx
│ ├── components
│ │ ├── Button
│ │ │ ├── Button.tsx
│ │ │ └── index.ts
│ │ ├── Card
│ │ │ ├── Card.tsx
│ │ │ └── index.ts
│ │ ├── ErrorMessage
│ │ │ ├── ErrorMessage.tsx
│ │ │ └── index.ts
│ │ ├── Footer
│ │ │ ├── Footer.tsx
│ │ │ └── index.ts
│ │ ├── Form
│ │ │ ├── Form.tsx
│ │ │ └── index.ts
│ │ ├── Input
│ │ │ ├── Input.tsx
│ │ │ └── index.ts
│ │ ├── Layouts
│ │ │ ├── Container.tsx
│ │ │ └── index.ts
│ │ └── UserInfo
│ │ │ ├── UserInfo.tsx
│ │ │ └── index.ts
│ ├── index.css
│ ├── index.tsx
│ ├── library
│ │ ├── api
│ │ │ ├── apiClient.ts
│ │ │ └── auth
│ │ │ │ └── auth.ts
│ │ ├── styles
│ │ │ └── palette.ts
│ │ └── utils
│ │ │ └── children.ts
│ ├── pages
│ │ ├── LoginPage.tsx
│ │ └── UserInfoPage.tsx
│ ├── react-app-env.d.ts
│ └── setupTests.ts
└── tsconfig.json
├── hayoung-jeremy
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
├── src
│ ├── App.test.tsx
│ ├── App.tsx
│ ├── components
│ │ ├── button
│ │ │ ├── Button.tsx
│ │ │ └── index.ts
│ │ ├── form
│ │ │ ├── Form.tsx
│ │ │ └── index.ts
│ │ ├── index.ts
│ │ ├── input
│ │ │ ├── Input.tsx
│ │ │ └── index.ts
│ │ └── pageTemplate
│ │ │ ├── PageTemplate.tsx
│ │ │ └── index.ts
│ ├── index.tsx
│ ├── logo.svg
│ ├── pages
│ │ ├── Login
│ │ │ ├── LoginPage.tsx
│ │ │ └── index.ts
│ │ ├── Profile
│ │ │ ├── ProfilePage.tsx
│ │ │ └── index.ts
│ │ └── index.ts
│ ├── react-app-env.d.ts
│ ├── reportWebVitals.ts
│ ├── service
│ │ └── api.ts
│ ├── setupTests.ts
│ ├── store
│ │ ├── authSlice.ts
│ │ ├── loginSlice.ts
│ │ ├── rootReducer.ts
│ │ └── store.ts
│ ├── style
│ │ ├── GlobalStyle.ts
│ │ ├── index.ts
│ │ └── palette.ts
│ └── types
│ │ └── auth.ts
└── tsconfig.json
├── hojongs
├── .browserslistrc
├── .eslintrc.js
├── .gitignore
├── README.md
├── jest.config.js
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── config.ts
│ ├── dto
│ │ ├── auth.ts
│ │ └── user.ts
│ ├── entry
│ │ ├── main.ts
│ │ └── user.ts
│ ├── service
│ │ ├── api_service.ts
│ │ └── url_param_service.ts
│ ├── shims-tsx.d.ts
│ ├── shims-vue.d.ts
│ └── view
│ │ ├── Login.vue
│ │ └── User.vue
├── tests
│ └── unit
│ │ └── service
│ │ └── api_service.spec.ts
├── tsconfig.json
└── vue.config.js
├── imhojeong
├── .eslinitignore
├── .eslintrc.js
├── .gitignore
├── .prettierrc
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
├── src
│ ├── apis
│ │ └── modules
│ │ │ └── auth.ts
│ ├── app
│ │ ├── App.css
│ │ ├── App.test.tsx
│ │ ├── App.tsx
│ │ ├── hooks.ts
│ │ ├── react-app-env.d.ts
│ │ └── setupTests.ts
│ ├── components
│ │ ├── LoginContainer.tsx
│ │ └── UserContainer.tsx
│ ├── index.css
│ ├── index.tsx
│ ├── pages
│ │ ├── LoginPage.tsx
│ │ └── UserInfoPage.tsx
│ ├── react-app-env.d.ts
│ ├── reducers
│ │ └── user.ts
│ ├── reportWebVitals.ts
│ ├── routes
│ │ └── index.tsx
│ ├── store
│ │ └── store.ts
│ └── styles
│ │ ├── global-style.ts
│ │ ├── styled.d.ts
│ │ └── theme.ts
└── tsconfig.json
├── jho2301
├── .eslintrc.json
├── .prettierrc
├── .storybook
│ ├── main.js
│ └── preview.js
├── README.md
├── REQUIREMENTS.md
├── package.json
├── public
│ └── index.html
├── src
│ ├── App.tsx
│ ├── Global.styles.ts
│ ├── __test__
│ │ ├── login.test.tsx
│ │ ├── setupTests.ts
│ │ ├── testUtil.tsx
│ │ └── user.test.tsx
│ ├── components
│ │ ├── @shared
│ │ │ ├── Button
│ │ │ │ ├── Button.stories.tsx
│ │ │ │ ├── Button.styles.ts
│ │ │ │ └── Button.tsx
│ │ │ ├── Input
│ │ │ │ ├── Input.stories.tsx
│ │ │ │ ├── Input.styles.ts
│ │ │ │ └── Input.tsx
│ │ │ └── Template
│ │ │ │ ├── Template.styles.ts
│ │ │ │ └── Template.tsx
│ │ ├── Login
│ │ │ └── Form
│ │ │ │ ├── LoginForm.stories.tsx
│ │ │ │ ├── LoginForm.styles.ts
│ │ │ │ └── LoginForm.tsx
│ │ ├── PrivateRoute
│ │ │ └── PrivateRoute.tsx
│ │ └── User
│ │ │ └── UserInfo
│ │ │ ├── UserInfo.stories.tsx
│ │ │ ├── UserInfo.styles.ts
│ │ │ └── UserInfo.tsx
│ ├── constants
│ │ ├── palette.ts
│ │ └── storage.ts
│ ├── index.tsx
│ ├── mock
│ │ ├── handlers.ts
│ │ └── server.ts
│ ├── pages
│ │ ├── Login
│ │ │ ├── LoginPage.stories.tsx
│ │ │ └── LoginPage.tsx
│ │ └── User
│ │ │ ├── UserPage.stories.tsx
│ │ │ └── UserPage.tsx
│ ├── service
│ │ ├── auth.ts
│ │ ├── hooks
│ │ │ ├── useAuth.ts
│ │ │ ├── useLoginForm.ts
│ │ │ └── useUser.ts
│ │ └── request
│ │ │ ├── index.ts
│ │ │ ├── login.ts
│ │ │ └── user.ts
│ ├── state
│ │ ├── login.ts
│ │ └── user.ts
│ ├── types.ts
│ └── util
│ │ └── API.ts
├── tsconfig.json
└── webpack.config.ts
├── kimbiyam
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
├── src
│ ├── App.tsx
│ ├── api
│ │ ├── apiClient.ts
│ │ ├── authApi.ts
│ │ └── userApi.ts
│ ├── components
│ │ ├── LoadingBackdrop.tsx
│ │ ├── LoginForm.tsx
│ │ ├── MainButton.tsx
│ │ ├── MainTextField.tsx
│ │ ├── PrivateRoute.tsx
│ │ └── UserProfile.tsx
│ ├── constants
│ │ └── constants.ts
│ ├── hooks
│ │ ├── __test__
│ │ │ ├── useCheckUserEffect.test.tsx
│ │ │ ├── useInput.test.tsx
│ │ │ ├── useLogin.test.tsx
│ │ │ └── useUserProfileQuery.test.tsx
│ │ ├── useCheckUserEffect.ts
│ │ ├── useInput.ts
│ │ ├── useLogin.ts
│ │ └── useUserProfileQuery.ts
│ ├── index.tsx
│ ├── models
│ │ ├── LoginData.ts
│ │ └── User.ts
│ ├── pages
│ │ ├── LoginPage.tsx
│ │ ├── NotFoundPage.tsx
│ │ └── UserProfilePage.tsx
│ ├── react-app-env.d.ts
│ ├── reportWebVitals.ts
│ ├── setupTests.ts
│ ├── styles
│ │ └── globalTheme.ts
│ └── utils
│ │ └── tokenStorage.ts
└── tsconfig.json
├── leehaeun0
├── .env.development
├── .env.production
├── .eslintrc.js
├── .gitignore
├── .prettierrc
├── README.md
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
├── src
│ ├── App.test.tsx
│ ├── App.tsx
│ ├── apis
│ │ └── api.ts
│ ├── components
│ │ ├── Button.tsx
│ │ ├── CenterBox.tsx
│ │ ├── FormInput.tsx
│ │ ├── LoginForm.tsx
│ │ ├── Main.tsx
│ │ ├── ReactHelmet.tsx
│ │ └── UserInfo.tsx
│ ├── hooks
│ │ └── useAsync.ts
│ ├── index.tsx
│ ├── pages
│ │ ├── LoadingPage.tsx
│ │ ├── LoginPage.tsx
│ │ └── UserPage.tsx
│ ├── react-app-env.d.ts
│ ├── reportWebVitals.ts
│ ├── routes
│ │ ├── MainRouter.tsx
│ │ ├── PrivateRoute.tsx
│ │ └── PublicRoute.tsx
│ ├── setupTests.ts
│ ├── styles
│ │ ├── GlobalStyle.ts
│ │ └── theme.ts
│ └── utils
│ │ ├── auth.ts
│ │ └── img
│ │ ├── profile-image.png
│ │ └── result.gif
└── tsconfig.json
└── rolancia
├── .env.development
├── .gitignore
├── README.md
├── package.json
├── public
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
└── manifest.json
├── src
├── App.module.css
├── App.test.tsx
├── App.tsx
├── components
│ ├── Login
│ │ ├── Login.module.css
│ │ └── Login.tsx
│ └── UserInfo
│ │ ├── UserInfo.module.css
│ │ └── UserInfo.tsx
├── index.css
├── index.tsx
├── model
│ ├── entity.ts
│ └── interfaces.ts
├── react-app-env.d.ts
├── service
│ └── httpClient.ts
├── setupTests.ts
└── test
│ └── httpClient.test.ts
└── tsconfig.json
/.dockerignore:
--------------------------------------------------------------------------------
1 | results
2 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3
2 |
3 | WORKDIR /app
4 |
5 | COPY . /app
6 |
7 | RUN pip install --no-cache-dir -r requirements.txt
8 |
9 | EXPOSE 5000
10 |
11 | CMD ["python", "./app.py"]
12 |
--------------------------------------------------------------------------------
/exception.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from abc import ABCMeta, abstractproperty
4 |
5 |
6 | class PilotException(Exception, metaclass=ABCMeta):
7 |
8 | errors = None
9 |
10 | def __init__(self, errors=None):
11 | self.errors = errors
12 | super().__init__(self.message)
13 |
14 | @abstractproperty
15 | def code(self):
16 | pass
17 |
18 | @abstractproperty
19 | def message(self):
20 | pass
21 |
22 |
23 | class Unauthorized(PilotException):
24 |
25 | @property
26 | def code(self):
27 | return 401
28 |
29 | @property
30 | def message(self):
31 | return "로그인이 필요합니다."
32 |
33 | def __str__(self):
34 | return self.__class__.__name__
35 |
36 |
37 | class AccessDenied(PilotException):
38 |
39 | @property
40 | def code(self):
41 | return 403
42 |
43 | @property
44 | def message(self):
45 | return "접근할 수 없습니다."
46 |
47 |
48 | class InvalidLogin(PilotException):
49 |
50 | @property
51 | def code(self):
52 | return 400
53 |
54 | @property
55 | def message(self):
56 | return "아이디 혹은 비밀번호가 옳바르지 않습니다."
57 |
58 |
59 | class InvalidRequest(PilotException):
60 |
61 | @property
62 | def code(self):
63 | return 400
64 |
65 | @property
66 | def message(self):
67 | return "입력값을 확인해주세요."
68 |
--------------------------------------------------------------------------------
/model.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from marshmallow import Schema, fields, validate, EXCLUDE
4 |
5 |
6 | class Login(Schema):
7 | class Meta:
8 | unknown = EXCLUDE
9 |
10 | account = fields.Str(required=True,
11 | error_messages={"required": "아이디를 입력해주세요."},
12 | validate=[validate.Length(min=1, max=10, error="1~3글자로 입력해주세요")])
13 | password = fields.Str(required=True,
14 | error_messages={"required": "비밀번호를 입력해주세요."})
15 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pilot-react",
3 | "lockfileVersion": 2,
4 | "requires": true,
5 | "packages": {
6 | "": {
7 | "dependencies": {
8 | "prettier": "^2.3.2"
9 | }
10 | },
11 | "node_modules/prettier": {
12 | "version": "2.3.2",
13 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz",
14 | "integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==",
15 | "bin": {
16 | "prettier": "bin-prettier.js"
17 | },
18 | "engines": {
19 | "node": ">=10.13.0"
20 | }
21 | }
22 | },
23 | "dependencies": {
24 | "prettier": {
25 | "version": "2.3.2",
26 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz",
27 | "integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ=="
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "prettier": "^2.3.2"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | Flask==2.0.1
2 | marshmallow==3.12.1
3 | Flask-Cors==3.0.10
4 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": ["@babel/plugin-syntax-dynamic-import"],
3 | "env": {
4 | "test": {
5 | "plugins": ["dynamic-import-node"],
6 | "presets": [
7 | [
8 | "@babel/preset-env",
9 | {
10 | "modules": "commonjs",
11 | "targets": {
12 | "node": "current"
13 | }
14 | }
15 | ]
16 | ]
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/.eslintignore:
--------------------------------------------------------------------------------
1 | /dist
2 | /src-bex/www
3 | /src-capacitor
4 | /src-cordova
5 | /.quasar
6 | /node_modules
7 | .eslintrc.js
8 | babel.config.js
9 | /src-ssr
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .thumbs.db
3 | node_modules
4 |
5 | # Quasar core related directories
6 | .quasar
7 | /dist
8 |
9 | # Cordova related directories and files
10 | /src-cordova/node_modules
11 | /src-cordova/platforms
12 | /src-cordova/plugins
13 | /src-cordova/www
14 |
15 | # Capacitor related directories and files
16 | /src-capacitor/www
17 | /src-capacitor/node_modules
18 |
19 | # BEX related directories and files
20 | /src-bex/www
21 | /src-bex/js/core
22 |
23 | # Log files
24 | npm-debug.log*
25 | yarn-debug.log*
26 | yarn-error.log*
27 |
28 | # Editor directories and files
29 | .idea
30 | *.suo
31 | *.ntvs*
32 | *.njsproj
33 | *.sln
34 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | plugins: [
5 | // to edit target browsers: use "browserslist" field in package.json
6 | require('autoprefixer')
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "semi": true
4 | }
5 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/README.md:
--------------------------------------------------------------------------------
1 | # Pilot-auth-ui app
2 |
3 | ## 개요
4 | [Quasar Framework v2](https://quasar.dev/) 을 사용한 app 입니다. 따라서, vue.js v3 과 webpack v5 이 사용됐습니다.
5 |
6 | 1. postman을 사용하길 원한다면, [pilot-auth api.postman_collection.json](./pilot-auth api.postman_collection.json) 을 import하길 바랍니다.
7 | 2. 현재 server host를 http://localhost:5000 으로 가정하고 작성된 소스코드입니다. 따라서, 바꾸고 싶다면, [src/boot/axios.ts](./src/boot/axios.ts) 파일의 baseURL 값을 변경 바랍니다.
8 | 3. 앱 사진:
9 |
10 | 로그인 페이지 | 사용자 정보 페이지
11 | :-------------------------:|:-------------------------:
12 |  | 
13 |
14 | [comment]: <> (
)
15 |
16 | ## Install the dependencies
17 | ```bash
18 | yarn
19 | ```
20 |
21 | ### Start the app in development mode (hot-code reloading, error reporting, etc.)
22 | ```bash
23 | quasar dev
24 | ```
25 |
26 | ### Lint the files
27 | ```bash
28 | yarn run lint
29 | ```
30 |
31 | ### Build the app for production
32 | ```bash
33 | quasar build
34 | ```
35 |
36 | ### Customize the configuration
37 | See [Configuring quasar.conf.js](https://v2.quasar.dev/quasar-cli/quasar-conf-js).
38 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/babel.config.js:
--------------------------------------------------------------------------------
1 | /* eslint-env node */
2 | // eslint-disable-next-line @typescript-eslint/no-var-requires
3 | const fs = require('fs-extra');
4 | let extend = undefined;
5 |
6 | /**
7 | * The .babelrc file has been created to assist Jest for transpiling.
8 | * You should keep your application's babel rules in this file.
9 | */
10 |
11 | if (fs.existsSync('./.babelrc')) {
12 | extend = './.babelrc';
13 | }
14 |
15 | module.exports = {
16 | presets: ['@quasar/babel-preset-app'],
17 | extends: extend,
18 | };
19 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/cypress.json:
--------------------------------------------------------------------------------
1 | {
2 | "baseUrl": "http://localhost:8080/",
3 | "fixturesFolder": "test/cypress/fixtures",
4 | "integrationFolder": "test/cypress/integration",
5 | "pluginsFile": "test/cypress/plugins/index.ts",
6 | "screenshotsFolder": "test/cypress/screenshots",
7 | "supportFile": "test/cypress/support/index.ts",
8 | "videosFolder": "test/cypress/videos",
9 | "video": true
10 | }
11 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/doc/image/login.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/AnJaeSeongS2/doc/image/login.png
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/doc/image/userInfo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/AnJaeSeongS2/doc/image/userInfo.png
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/AnJaeSeongS2/public/favicon.ico
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/public/icons/favicon-128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/AnJaeSeongS2/public/icons/favicon-128x128.png
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/public/icons/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/AnJaeSeongS2/public/icons/favicon-16x16.png
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/public/icons/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/AnJaeSeongS2/public/icons/favicon-32x32.png
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/public/icons/favicon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/AnJaeSeongS2/public/icons/favicon-96x96.png
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/quasar.extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "@quasar/testing-e2e-cypress": {
3 | "options": [
4 | "scripts",
5 | "typescript"
6 | ]
7 | },
8 | "@quasar/testing-security": {
9 | "options": [],
10 | "zapbrowser": "Chrome"
11 | },
12 | "@quasar/testing": {
13 | "harnesses": [
14 | "unit-jest",
15 | "e2e-cypress",
16 | "security"
17 | ]
18 | },
19 | "@quasar/testing-unit-jest": {
20 | "babel": "babelrc",
21 | "options": [
22 | "scripts",
23 | "typescript"
24 | ]
25 | }
26 | }
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/quasar.testing.json:
--------------------------------------------------------------------------------
1 | {
2 | "unit-jest": {
3 | "runnerCommand": "jest --ci"
4 | },
5 | "e2e-cypress": {
6 | "runnerCommand": "cross-env E2E_TEST=true start-test \"quasar dev\" http-get://localhost:8080 \"cypress run\""
7 | }
8 | }
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
20 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/src/boot/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/AnJaeSeongS2/src/boot/.gitkeep
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/src/boot/axios.ts:
--------------------------------------------------------------------------------
1 | import { boot } from 'quasar/wrappers';
2 | import axios, { AxiosInstance } from 'axios';
3 |
4 | declare module '@vue/runtime-core' {
5 | interface ComponentCustomProperties {
6 | $axios: AxiosInstance;
7 | }
8 | }
9 |
10 | // Be careful when using SSR for cross-request state pollution
11 | // due to creating a Singleton instance here;
12 | // If any client changes this (global) instance, it might be a
13 | // good idea to move this instance creation inside of the
14 | // "export default () => {}" function below (which runs individually
15 | // for each client)
16 | const api = axios.create({
17 | baseURL: 'http://localhost:5000',
18 | });
19 |
20 | export default boot(({app}) => {
21 | // for use inside Vue files (Options API) through this.$axios and this.$api
22 |
23 | app.config.globalProperties.$axios = axios;
24 | // ^ ^ ^ this will allow you to use this.$axios (for Vue Options API form)
25 | // so you won't necessarily have to import axios in each vue file
26 |
27 | app.config.globalProperties.$api = api;
28 | // ^ ^ ^ this will allow you to use this.$api (for Vue Options API form)
29 | // so you can easily perform requests against your app's API
30 | });
31 |
32 | export { api };
33 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/src/components/models.ts:
--------------------------------------------------------------------------------
1 | export interface UserLoginFormat {
2 | account: string,
3 | password: string,
4 | }
5 |
6 | export interface LoginToken {
7 | accessToken: string,
8 | }
9 |
10 | export interface User {
11 | account: string,
12 | name: string,
13 | id: number,
14 | level: number,
15 | }
16 |
17 | export interface Response {
18 | code: number,
19 | message: string,
20 | validate: unknown,
21 | }
22 |
23 | export interface InfoItem {
24 | iconName: string,
25 | colorName: string,
26 | textLabel: string,
27 | textBody: string,
28 | }
29 |
30 | export interface Error {
31 | code: number,
32 | message: string,
33 | }
34 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/src/css/app.scss:
--------------------------------------------------------------------------------
1 | // app global css in SCSS form
2 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/src/css/quasar.variables.scss:
--------------------------------------------------------------------------------
1 | // Quasar SCSS (& Sass) Variables
2 | // --------------------------------------------------
3 | // To customize the look and feel of this app, you can override
4 | // the Sass/SCSS variables found in Quasar's source Sass/SCSS files.
5 |
6 | // Check documentation for full list of Quasar variables
7 |
8 | // Your own variables (that are declared here) and Quasar's own
9 | // ones will be available out of the box in your .vue/.scss/.sass files
10 |
11 | // It's highly recommended to change the default colors
12 | // to match your app's branding.
13 | // Tip: Use the "Theme Builder" on Quasar's documentation website.
14 |
15 | $primary : #1976D2;
16 | $secondary : #26A69A;
17 | $accent : #9C27B0;
18 |
19 | $dark : #1D1D1D;
20 |
21 | $positive : #21BA45;
22 | $negative : #C10015;
23 | $info : #31CCEC;
24 | $warning : #F2C037;
25 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/src/index.template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | <%= productName %>
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/src/pages/Error404.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 404
6 |
7 |
8 |
9 | Oops. Nothing here...
10 |
11 |
12 |
21 |
22 |
23 |
24 |
25 |
32 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/src/pages/Index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
25 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/src/pages/users/InfoItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {{ textLabel }}
9 | {{ textBody }}
10 |
11 |
12 |
13 |
14 |
39 |
40 |
43 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/src/router/index.ts:
--------------------------------------------------------------------------------
1 | import { route } from 'quasar/wrappers';
2 | import {
3 | createMemoryHistory,
4 | createRouter,
5 | createWebHashHistory,
6 | createWebHistory,
7 | } from 'vue-router';
8 | import { StateInterface } from '../store';
9 | import routes from './routes';
10 |
11 | /*
12 | * If not building with SSR mode, you can
13 | * directly export the Router instantiation;
14 | *
15 | * The function below can be async too; either use
16 | * async/await or return a Promise which resolves
17 | * with the Router instance.
18 | */
19 |
20 | export default route(function (/* { store, ssrContext } */) {
21 | const createHistory = process.env.SERVER
22 | ? createMemoryHistory
23 | : (process.env.VUE_ROUTER_MODE === 'history' ? createWebHistory : createWebHashHistory);
24 |
25 | const Router = createRouter({
26 | scrollBehavior: () => ({left: 0, top: 0}),
27 | routes,
28 |
29 | // Leave this as is and make changes in quasar.conf.js instead!
30 | // quasar.conf.js -> build -> vueRouterMode
31 | // quasar.conf.js -> build -> publicPath
32 | history: createHistory(
33 | process.env.MODE === 'ssr' ? void 0 : process.env.VUE_ROUTER_BASE,
34 | ),
35 | });
36 |
37 | return Router;
38 | });
39 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/src/router/routes.ts:
--------------------------------------------------------------------------------
1 | import { RouteRecordRaw } from 'vue-router';
2 |
3 | const routes: RouteRecordRaw[] = [
4 | {
5 | path: '/',
6 | component: () => import('layouts/MainLayout.vue'),
7 | redirect: '/users/me',
8 | children: [{
9 | path: 'users/me',
10 | component: () => import('pages/users/Info.vue'),
11 | }, {
12 | path: 'login',
13 | component: () => import('pages/Login.vue'),
14 | }],
15 | },
16 |
17 | // Always leave this as last one,
18 | // but you can also remove it
19 | {
20 | path: '/:catchAll(.*)*',
21 | component: () => import('pages/Error404.vue'),
22 | },
23 | ];
24 |
25 | export default routes;
26 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | // Mocks all files ending in `.vue` showing them as plain Vue instances
2 | declare module '*.vue' {
3 | import { ComponentOptions } from 'vue'
4 | const component: ComponentOptions
5 | export default component
6 | }
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/src/store/loginToken/actions.ts:
--------------------------------------------------------------------------------
1 | import { ActionTree } from 'vuex';
2 | import { StateInterface } from '../index';
3 | import { LoginToken } from './state';
4 |
5 | const actions: ActionTree = {
6 | someAction(/* context */) {
7 | // your code
8 | },
9 | };
10 |
11 | export default actions;
12 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/src/store/loginToken/getters.ts:
--------------------------------------------------------------------------------
1 | import { GetterTree } from 'vuex';
2 | import { StateInterface } from '../index';
3 | import { LoginToken } from './state';
4 |
5 | const getters: GetterTree = {
6 | someGetter(/* context */) {
7 | // your code
8 | },
9 | };
10 |
11 | export default getters;
12 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/src/store/loginToken/index.ts:
--------------------------------------------------------------------------------
1 | import { Module } from 'vuex';
2 | import { StateInterface } from '../index';
3 | import state, { LoginToken } from './state';
4 | import actions from './actions';
5 | import getters from './getters';
6 | import mutations from './mutations';
7 |
8 | const loginToken: Module = {
9 | namespaced: true,
10 | actions,
11 | getters,
12 | mutations,
13 | state,
14 | };
15 |
16 | export default loginToken;
17 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/src/store/loginToken/mutations.ts:
--------------------------------------------------------------------------------
1 | import { MutationTree } from 'vuex';
2 | import { LoginToken } from './state';
3 |
4 | const mutation: MutationTree = {
5 | saveLoginToken(state: LoginToken, nextState: LoginToken) {
6 | state.accessToken = nextState.accessToken;
7 | localStorage.setItem('accessToken', state.accessToken);
8 | },
9 | clearLoginToken(state: LoginToken) {
10 | state.accessToken = '';
11 | localStorage.removeItem('accessToken');
12 | },
13 | };
14 |
15 | export default mutation;
16 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/src/store/loginToken/state.ts:
--------------------------------------------------------------------------------
1 | import { LoginToken } from 'components/models';
2 |
3 | function state(): LoginToken {
4 | return {
5 | accessToken: '',
6 | };
7 | }
8 |
9 | export default state;
10 | export { LoginToken };
11 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/src/store/store-flag.d.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | // THIS FEATURE-FLAG FILE IS AUTOGENERATED,
3 | // REMOVAL OR CHANGES WILL CAUSE RELATED TYPES TO STOP WORKING
4 | import 'quasar/dist/types/feature-flag';
5 |
6 | declare module 'quasar/dist/types/feature-flag' {
7 | interface QuasarFeatureFlags {
8 | store: true;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/test/cypress/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // ESLint "parserOptions" options should be overrided to point to the same tsconfig used
3 | // by fork-ts-checker (check the app extension "index.js") or type errors won't be emitted (only linting ones will)
4 | parserOptions: {
5 | project: './tsconfig.json',
6 | tsconfigRootDir: __dirname
7 | },
8 |
9 | extends: [
10 | // Add Cypress-specific lint rules, globals and Cypress plugin
11 | // See https://github.com/cypress-io/eslint-plugin-cypress#rules
12 | 'plugin:cypress/recommended'
13 | ]
14 | };
15 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/test/cypress/.gitignore:
--------------------------------------------------------------------------------
1 | videos/*
2 | screenshots/*
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/test/cypress/fixtures/example.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Using fixtures to represent data",
3 | "email": "hello@cypress.io",
4 | "body": "Fixtures are a great way to mock data for responses to routes"
5 | }
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/test/cypress/plugins/index.ts:
--------------------------------------------------------------------------------
1 | /* eslint-env node */
2 | // ***********************************************************
3 | // This example plugins/index.ts can be used to load plugins
4 | //
5 | // You can change the location of this file or turn off loading
6 | // the plugins file with the 'pluginsFile' configuration option.
7 | //
8 | // You can read more here:
9 | // https://on.cypress.io/plugins-guide
10 | // ***********************************************************
11 |
12 | // This function is called when a project is opened or re-opened (e.g. due to
13 | // the project's config changing)
14 |
15 | // cypress/plugins/index.ts
16 |
17 | const pluginConfig: Cypress.PluginConfig = (/*on, config*/) => {
18 | //
19 | };
20 |
21 | export default pluginConfig;
22 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/test/cypress/support/index.ts:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/index.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // Import commands.js using ES2015 syntax:
17 | import './commands';
18 |
19 | const resizeObserverLoopError = 'ResizeObserver loop limit exceeded';
20 |
21 | Cypress.on('uncaught:exception', (err) => {
22 | if (err.message.includes(resizeObserverLoopError)) {
23 | // returning false here prevents Cypress from
24 | // failing the test
25 | return false;
26 | }
27 | });
28 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/test/cypress/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig",
3 | "compilerOptions": {
4 | // If you enabled IE support while creating the project, root tsconfig target is set to ES5 instead
5 | // Cypress tests and support files are written in ES6 and this option enforce the right target regardless of root configuration
6 | "target": "es6",
7 | // Importing "cypress" types into project-root tsconfig won't work for unknown reasons,
8 | // using folder-local tsconfig is better to avoid globals conflicts (eg. with Jest)
9 | "types": ["cypress"]
10 | },
11 | // Reset excluded files list, as it excluded Cypress files in the first place
12 | // and other exclusions do not apply into tests nested folder
13 | "exclude": []
14 | }
15 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/test/jest/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: [
3 | // Removes 'no-undef' lint errors for Jest global functions (`describe`, `it`, etc),
4 | // add Jest-specific lint rules and Jest plugin
5 | // See https://github.com/jest-community/eslint-plugin-jest#recommended
6 | 'plugin:jest/recommended',
7 | // Uncomment following line to apply style rules
8 | // 'plugin:jest/style',
9 | ],
10 | };
11 |
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/test/jest/.gitignore:
--------------------------------------------------------------------------------
1 | coverage/*
--------------------------------------------------------------------------------
/results/AnJaeSeongS2/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@quasar/app/tsconfig-preset",
3 | "compilerOptions": {
4 | "baseUrl": ".",
5 | "esModuleInterop": true,
6 | "types": [
7 | "jest",
8 | "quasar"
9 | ]
10 | },
11 | "exclude": [
12 | "test/cypress",
13 | "/dist",
14 | ".quasar",
15 | "node_modules"
16 | ]
17 | }
--------------------------------------------------------------------------------
/results/Kim-Jaemin420/pilot-react/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
25 | .env
26 |
--------------------------------------------------------------------------------
/results/Kim-Jaemin420/pilot-react/.nvmrc:
--------------------------------------------------------------------------------
1 | 14.15.1
2 |
--------------------------------------------------------------------------------
/results/Kim-Jaemin420/pilot-react/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "typescript",
3 | "singleQuote": true,
4 | "printWidth": 110,
5 | "tabWidth": 2,
6 | "useTabs": false,
7 | "semi": true,
8 | "quoteProps": "as-needed",
9 | "jsxSingleQuote": true,
10 | "trailingComma": "all",
11 | "arrowParens": "always",
12 | "endOfLine": "auto",
13 | "bracketSpacing": true,
14 | "jsxBracketSameLine": false,
15 | "requirePragma": false,
16 | "insertPragma": false,
17 | "proseWrap": "preserve",
18 | "vueIndentScriptAndStyle": false
19 | }
20 |
--------------------------------------------------------------------------------
/results/Kim-Jaemin420/pilot-react/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/Kim-Jaemin420/pilot-react/public/favicon.ico
--------------------------------------------------------------------------------
/results/Kim-Jaemin420/pilot-react/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/Kim-Jaemin420/pilot-react/public/logo192.png
--------------------------------------------------------------------------------
/results/Kim-Jaemin420/pilot-react/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/Kim-Jaemin420/pilot-react/public/logo512.png
--------------------------------------------------------------------------------
/results/Kim-Jaemin420/pilot-react/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/results/Kim-Jaemin420/pilot-react/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/results/Kim-Jaemin420/pilot-react/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { renderHook, act } from '@testing-library/react-hooks';
4 |
5 | import useInputChange from '../src/hooks/useInputChange';
6 |
7 | test('**useInputChange test**', () => {
8 | const { result } = renderHook(({ initialValue }) => useInputChange(initialValue), {
9 | initialProps: {initialValue: ''}
10 | });
11 |
12 | act(() => {
13 | result.current[1]({target: {value: 'hello'}});
14 | });
15 |
16 | expect(result.current[0]).toBe('hello');
17 | });
18 |
19 |
20 |
--------------------------------------------------------------------------------
/results/Kim-Jaemin420/pilot-react/src/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Switch, Route, BrowserRouter } from 'react-router-dom';
3 |
4 | import Login from './components/Login';
5 | import Home from './components/Home';
6 |
7 |
8 | const App = () => {
9 | return (
10 |
11 |
12 |
13 |
14 |
15 |
16 | );
17 | }
18 |
19 | export default App;
20 |
--------------------------------------------------------------------------------
/results/Kim-Jaemin420/pilot-react/src/FetchData/HttpFetch.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | class HttpFetch {
4 | private readonly url: string;
5 | private readonly data: any;
6 |
7 | constructor(url: string, data: any = null) {
8 | this.url = url;
9 | this.data = data;
10 | }
11 |
12 | PostFetch = async () => {
13 | try {
14 | const res = await axios.post(this.url, this.data);
15 | return res.data;
16 |
17 | } catch (e) {
18 | console.error(e);
19 | return e.response.data;
20 | }
21 | };
22 |
23 | GetFetch = async () => {
24 | try {
25 | const res = await axios.get(this.url,{
26 | headers: {
27 | Authorization: `Bearer ${sessionStorage.getItem('token')}`,
28 | },
29 | });
30 | return res;
31 | } catch (e) {
32 | console.error(e);
33 | return e;
34 | }
35 | };
36 | }
37 |
38 | export default HttpFetch;
39 |
--------------------------------------------------------------------------------
/results/Kim-Jaemin420/pilot-react/src/FetchData/LoginData.ts:
--------------------------------------------------------------------------------
1 | export class LoginData {
2 | account: string;
3 | password: string;
4 |
5 | constructor(account: string, password: string) {
6 | this.account = account;
7 | this.password = password;
8 | }
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/results/Kim-Jaemin420/pilot-react/src/FetchData/UserData.ts:
--------------------------------------------------------------------------------
1 | export class UserData {
2 | account: string;
3 | id: number;
4 | level: number;
5 | name: string;
6 |
7 | constructor(info: { account: string, id: number, level: number, name: string} | null) {
8 | this.account = info ? info.account : '';
9 | this.id = info ? info.id : 0;
10 | this.level = info ? info.level : 0;
11 | this.name = info ? info.name : '';
12 | }
13 |
14 | }
15 |
16 |
--------------------------------------------------------------------------------
/results/Kim-Jaemin420/pilot-react/src/components/common/CommonBtn.tsx:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import { Button } from 'antd';
3 |
4 | const CommonButton = styled(Button)`
5 | background-color: #409eff;
6 | color: #fff;
7 | width: 150px;
8 | text-align: center;
9 | margin: 0 auto;
10 | `;
11 |
12 | const CommonBtn = ({children, onClick, type, style}: any) => {
13 | return {children}
14 | };
15 |
16 | export default CommonBtn;
17 |
18 |
--------------------------------------------------------------------------------
/results/Kim-Jaemin420/pilot-react/src/hooks/useInputChange.ts:
--------------------------------------------------------------------------------
1 | import { useState, useCallback } from 'react';
2 |
3 | const useInputChange = (initialState = '') => {
4 | const [input, setInput] = useState(initialState);
5 |
6 | const onChange = useCallback(({ target }) => {
7 | setInput(target.value);
8 | }, []);
9 |
10 | return [input, onChange, setInput] as const;
11 | };
12 |
13 | export default useInputChange;
14 |
--------------------------------------------------------------------------------
/results/Kim-Jaemin420/pilot-react/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import 'antd/dist/antd.css';
4 | import GlobalStyle from './styles/GlobalStyle';
5 |
6 | import App from './App';
7 |
8 | ReactDOM.render(
9 |
10 |
11 |
12 | ,
13 | document.getElementById('root')
14 | );
15 |
--------------------------------------------------------------------------------
/results/Kim-Jaemin420/pilot-react/src/styles/GlobalStyle.ts:
--------------------------------------------------------------------------------
1 | import { createGlobalStyle } from 'styled-components';
2 | import reset from 'styled-reset';
3 |
4 | const GlobalStyle = createGlobalStyle`
5 | ${reset};
6 | body {
7 | margin: 0;
8 | padding: 0;
9 | font-family: AppleSDGothicNeoR, AppleSDGothicNeo, "돋움", dotum, Helvetica, sans-serif;
10 | }
11 | h1 {
12 | font-size: 25px;
13 | font-weight: 600;
14 | }
15 | ul, li {
16 | margin: 0;
17 | padding: 0 30px;
18 | list-style: none;
19 | display: inline-block;
20 | }
21 | .a11y-hidden {
22 | position: absolute;
23 | width: 1px;
24 | height: 1px;
25 | overflow: hidden;
26 | margin: -1px;
27 | clip-path: polygon(0 0, 0 0, 0 0);
28 | clip: rect(0 0 0 0);
29 | clip: rect(0, 0, 0, 0);
30 | }
31 | `;
32 |
33 | export default GlobalStyle;
34 |
--------------------------------------------------------------------------------
/results/Kim-Jaemin420/pilot-react/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 | "allowJs": true,
10 | "skipLibCheck": true,
11 | "esModuleInterop": true,
12 | "allowSyntheticDefaultImports": true,
13 | "strict": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "noFallthroughCasesInSwitch": true,
16 | "module": "esnext",
17 | "moduleResolution": "node",
18 | "resolveJsonModule": true,
19 | "isolatedModules": true,
20 | "noEmit": true,
21 | "jsx": "react-jsx"
22 | },
23 | "include": [
24 | "src"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/results/boksilab/.firebaserc:
--------------------------------------------------------------------------------
1 | {
2 | "projects": {
3 | "default": "project-login-34e2b"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/results/boksilab/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/results/boksilab/README.md:
--------------------------------------------------------------------------------
1 | ## LIVE DEMO
2 | [🚀DEMO](https://boksilab-login.netlify.app/)
3 |
4 | ## Available Scripts
5 |
6 | In the project directory, you can run:
7 |
8 | ### `npm start`
9 |
10 | Runs the app in the development mode.\
11 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
12 |
--------------------------------------------------------------------------------
/results/boksilab/firebase.json:
--------------------------------------------------------------------------------
1 | {
2 | "hosting": {
3 | "public": "build",
4 | "ignore": [
5 | "firebase.json",
6 | "**/.*",
7 | "**/node_modules/**"
8 | ]
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/results/boksilab/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/boksilab/public/favicon.ico
--------------------------------------------------------------------------------
/results/boksilab/public/image/blackhole.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/boksilab/public/image/blackhole.png
--------------------------------------------------------------------------------
/results/boksilab/public/image/skybox/B.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/boksilab/public/image/skybox/B.jpg
--------------------------------------------------------------------------------
/results/boksilab/public/image/skybox/D.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/boksilab/public/image/skybox/D.jpg
--------------------------------------------------------------------------------
/results/boksilab/public/image/skybox/F.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/boksilab/public/image/skybox/F.jpg
--------------------------------------------------------------------------------
/results/boksilab/public/image/skybox/L.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/boksilab/public/image/skybox/L.jpg
--------------------------------------------------------------------------------
/results/boksilab/public/image/skybox/R.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/boksilab/public/image/skybox/R.jpg
--------------------------------------------------------------------------------
/results/boksilab/public/image/skybox/U.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/boksilab/public/image/skybox/U.jpg
--------------------------------------------------------------------------------
/results/boksilab/public/sfx/fall1.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/boksilab/public/sfx/fall1.wav
--------------------------------------------------------------------------------
/results/boksilab/public/sfx/fall2.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/boksilab/public/sfx/fall2.wav
--------------------------------------------------------------------------------
/results/boksilab/public/sfx/fall3.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/boksilab/public/sfx/fall3.wav
--------------------------------------------------------------------------------
/results/boksilab/public/sfx/fall4.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/boksilab/public/sfx/fall4.wav
--------------------------------------------------------------------------------
/results/boksilab/src/App.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render, screen } from '@testing-library/react';
3 | import App from './App';
4 |
5 | test('renders learn react link', () => {
6 | render();
7 | const linkElement = screen.getByText(/learn react/i);
8 | expect(linkElement).toBeInTheDocument();
9 | });
10 |
--------------------------------------------------------------------------------
/results/boksilab/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { Suspense } from 'react';
2 | import { SnackbarProvider } from 'notistack';
3 | import Canvas from './components/Canvas';
4 | import ProgressBar from './components/ProgressBar';
5 |
6 | function App() {
7 | return (
8 |
17 |
18 | }>
19 |
20 |
21 |
22 |
23 | );
24 | }
25 |
26 | export default App;
27 |
--------------------------------------------------------------------------------
/results/boksilab/src/Godo.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/boksilab/src/Godo.ttf
--------------------------------------------------------------------------------
/results/boksilab/src/Phase.ts:
--------------------------------------------------------------------------------
1 | export default class Phase {
2 | static initial = 0;
3 | static pending = 1;
4 | static error = 2;
5 | static glitch = 3;
6 | static warpToCamPos2 = 4;
7 | static warp1Complete = 5;
8 | static warpToCamPos3 = 6;
9 | static warp2Complete = 7;
10 | }
11 |
--------------------------------------------------------------------------------
/results/boksilab/src/Response.ts:
--------------------------------------------------------------------------------
1 | import UserInfo from './UserInfo';
2 | export default class Response {
3 | constructor(type: string, message?: string, userInfo?: UserInfo, token?: string) {
4 | this._type = type;
5 | this._message = message;
6 | this._userInfo = userInfo;
7 | this._token = token;
8 | }
9 | private _type: string;
10 | private _message: string | undefined;
11 | private _userInfo: UserInfo | undefined;
12 | private _token: string | undefined;
13 |
14 | get type() {
15 | return this._type;
16 | }
17 | get message() {
18 | return this._message;
19 | }
20 | get userInfo() {
21 | return this._userInfo;
22 | }
23 | get token() {
24 | return this._token;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/results/boksilab/src/TabIndex.ts:
--------------------------------------------------------------------------------
1 | export default class TabIndex {
2 | static none = 0;
3 | static input1 = 1;
4 | static input2 = 2;
5 | static button = 3;
6 | static next(value: number) {
7 | return value >= 3 ? 0 : value + 1;
8 | }
9 | static prev(value: number) {
10 | return value <= 0 ? 3 : value - 1;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/results/boksilab/src/UserInfo.ts:
--------------------------------------------------------------------------------
1 | export default class UserInfo {
2 | constructor(account: string, password?: string, id?: number, level?: number, name?: string) {
3 | this._account = account;
4 | this._password = password;
5 | this._id = id;
6 | this._level = level;
7 | this._name = name;
8 | }
9 | private _account: string;
10 | private _password: string | undefined;
11 | private _id: number | undefined;
12 | private _level: number | undefined;
13 | private _name: string | undefined;
14 | set id(value: number | undefined) {
15 | this._id = value;
16 | }
17 | set level(value: number | undefined) {
18 | this._level = value;
19 | }
20 | set name(value: string | undefined) {
21 | this._name = value;
22 | }
23 | get account() {
24 | return this._account;
25 | }
26 | get password(): string | undefined {
27 | return this._password;
28 | }
29 | get id(): number | undefined {
30 | return this._id;
31 | }
32 | get level(): number | undefined {
33 | return this._level;
34 | }
35 | get name(): string | undefined {
36 | return this._name;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/results/boksilab/src/components/Blackhole.tsx:
--------------------------------------------------------------------------------
1 | import React, { useRef } from 'react';
2 | import * as Three from 'three';
3 | import { useFrame } from '@react-three/fiber';
4 |
5 | export default React.memo(
6 | function Blackhole({ blackholeTexture }: { blackholeTexture: Three.Texture }) {
7 | const mesh = useRef(null!);
8 | const geometry = useRef(null!);
9 | const material = useRef(null!);
10 | useFrame(() => {
11 | mesh.current.rotation.z -= 0.003;
12 | });
13 | return (
14 |
15 |
16 |
32 |
33 | );
34 | },
35 | () => true
36 | );
37 |
--------------------------------------------------------------------------------
/results/boksilab/src/components/Lights.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default React.memo(
4 | function Lights() {
5 | return (
6 | <>
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | >
18 | );
19 | },
20 | () => true
21 | );
22 |
--------------------------------------------------------------------------------
/results/boksilab/src/components/ProgressBar.tsx:
--------------------------------------------------------------------------------
1 | import { useProgress } from '@react-three/drei';
2 |
3 | // interface asset {
4 | // [key: string]: {
5 | // total: number;
6 | // loaded: number;
7 | // progress: number;
8 | // };
9 | // }
10 | const numOfAssets = 16;
11 | export default function ProgressBar() {
12 | // const { item, total, progress, loaded } = useProgress();
13 | const { loaded } = useProgress();
14 |
15 | return (
16 |
50 | );
51 | }
52 |
--------------------------------------------------------------------------------
/results/boksilab/src/components/Sound.tsx:
--------------------------------------------------------------------------------
1 | import React, { useRef, useState, useEffect } from 'react';
2 | import * as Three from 'three';
3 | import { useThree } from '@react-three/fiber';
4 | import { MathUtils } from 'three';
5 |
6 | export default function PositionalAudioScene({
7 | sfxBuffer,
8 | distance,
9 | play,
10 | }: {
11 | sfxBuffer: AudioBuffer[];
12 | distance: number;
13 | play: boolean;
14 | }) {
15 | const sound = useRef();
16 | const { camera } = useThree();
17 | const [listener] = useState(() => new Three.AudioListener());
18 |
19 | useEffect(() => {
20 | sound.current?.setBuffer(sfxBuffer[MathUtils.randInt(0, 3)]);
21 | sound.current?.setRefDistance(distance);
22 | sound.current?.setVolume(0.2);
23 | camera.add(listener);
24 | return () => {
25 | camera.remove(listener);
26 | };
27 | }, []);
28 | useEffect(() => {
29 | if (play) {
30 | sound.current?.play();
31 | }
32 | }, [play]);
33 | return (
34 | <>
35 |
36 |
37 |
38 | >
39 | );
40 | }
41 |
--------------------------------------------------------------------------------
/results/boksilab/src/components/StaticText.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import TextStatic from './TextStatic';
3 | import { ITextConfig } from './Canvas';
4 |
5 | export default React.memo(
6 | function StaticText({ textConfig }: { textConfig: ITextConfig | undefined }) {
7 | return (
8 | <>
9 |
16 |
23 |
30 |
31 |
32 |
39 | >
40 | );
41 | },
42 | (prev, next) => prev.textConfig === next.textConfig
43 | );
44 |
--------------------------------------------------------------------------------
/results/boksilab/src/components/TextStatic.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { ITextConfig } from './Canvas';
3 |
4 | interface IProps {
5 | config: ITextConfig | undefined;
6 | children: string;
7 | position?: number[];
8 | rotation?: number[];
9 | color?: string;
10 | size?: number;
11 | }
12 |
13 | export default React.memo(
14 | function TextStatic({ config, position, rotation, children, color = 'black', size = 1 }: IProps) {
15 | return (
16 | // @ts-ignore
17 |
18 | {config && (
19 |
20 |
21 |
22 |
23 | )}
24 |
25 | );
26 | },
27 | (prev, next) => prev.config === next.config && prev.position === next.position
28 | );
29 |
--------------------------------------------------------------------------------
/results/boksilab/src/index.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'Godo';
3 | src: url('Godo.ttf');
4 | }
5 |
6 | * {
7 | font-family: 'Godo';
8 | user-select: none;
9 | }
10 |
11 | body {
12 | width: 100vw;
13 | height: 100vh;
14 | background-color: black;
15 | margin: 0;
16 | }
17 |
18 | #canvas-container {
19 | position: absolute;
20 | width: 100%;
21 | height: 100%;
22 | min-height: 600px;
23 | }
24 |
--------------------------------------------------------------------------------
/results/boksilab/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import reportWebVitals from './reportWebVitals';
6 |
7 | ReactDOM.render(
8 |
9 |
10 | ,
11 | document.getElementById('root')
12 | );
13 |
14 | reportWebVitals();
15 |
--------------------------------------------------------------------------------
/results/boksilab/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/results/boksilab/src/reportWebVitals.ts:
--------------------------------------------------------------------------------
1 | import { ReportHandler } from 'web-vitals';
2 |
3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => {
4 | if (onPerfEntry && onPerfEntry instanceof Function) {
5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
6 | getCLS(onPerfEntry);
7 | getFID(onPerfEntry);
8 | getFCP(onPerfEntry);
9 | getLCP(onPerfEntry);
10 | getTTFB(onPerfEntry);
11 | });
12 | }
13 | };
14 |
15 | export default reportWebVitals;
16 |
--------------------------------------------------------------------------------
/results/boksilab/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom';
6 |
--------------------------------------------------------------------------------
/results/boksilab/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 | "allowJs": true,
10 | "skipLibCheck": true,
11 | "esModuleInterop": true,
12 | "allowSyntheticDefaultImports": true,
13 | "strict": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "noFallthroughCasesInSwitch": true,
16 | "module": "esnext",
17 | "moduleResolution": "node",
18 | "resolveJsonModule": true,
19 | "isolatedModules": true,
20 | "noEmit": true,
21 | "jsx": "react-jsx"
22 | },
23 | "include": [
24 | "src"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/results/byeongukchoi/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/results/byeongukchoi/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true,
5 | },
6 | extends: [
7 | "plugin:vue/essential",
8 | "eslint:recommended",
9 | "@vue/typescript/recommended",
10 | "@vue/prettier",
11 | "@vue/prettier/@typescript-eslint",
12 | ],
13 | parserOptions: {
14 | ecmaVersion: 2020,
15 | },
16 | rules: {
17 | "no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
18 | "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
19 | },
20 | overrides: [
21 | {
22 | files: [
23 | "**/__tests__/*.{j,t}s?(x)",
24 | "**/tests/unit/**/*.spec.{j,t}s?(x)",
25 | ],
26 | env: {
27 | mocha: true,
28 | },
29 | },
30 | ],
31 | };
32 |
--------------------------------------------------------------------------------
/results/byeongukchoi/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/results/byeongukchoi/README.md:
--------------------------------------------------------------------------------
1 | # pilot-vue
2 |
3 | ## spec
4 | - vue2
5 | - typescript
6 |
7 | ## 후기
8 | 저의 부족함을 많이 느끼게된 프로젝트였습니다.
9 | 테스트 코드 구현하지 못하였습니다.
10 |
11 | ### Run
12 | ```
13 | yarn serve
14 | ```
15 |
--------------------------------------------------------------------------------
/results/byeongukchoi/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ["@vue/cli-plugin-babel/preset"],
3 | };
4 |
--------------------------------------------------------------------------------
/results/byeongukchoi/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/byeongukchoi/public/favicon.ico
--------------------------------------------------------------------------------
/results/byeongukchoi/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | <%= htmlWebpackPlugin.options.title %>
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/results/byeongukchoi/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/results/byeongukchoi/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/byeongukchoi/src/assets/logo.png
--------------------------------------------------------------------------------
/results/byeongukchoi/src/components/Profile.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 아이디 |
6 | {{ user.account }} |
7 |
8 |
9 | 이름 |
10 | {{ user.name }} |
11 |
12 |
13 | 레벨 |
14 | {{ user.level }} |
15 |
16 |
17 |
18 |
19 |
20 |
41 |
--------------------------------------------------------------------------------
/results/byeongukchoi/src/main.ts:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import App from "./App.vue";
3 | import router from "./router";
4 | import store from "./store";
5 |
6 | Vue.config.productionTip = false;
7 |
8 | new Vue({
9 | router,
10 | store,
11 | render: (h) => h(App),
12 | }).$mount("#app");
13 |
--------------------------------------------------------------------------------
/results/byeongukchoi/src/models/LoginRequest.ts:
--------------------------------------------------------------------------------
1 | export default class LoginRequest {
2 | account: string;
3 | password: string;
4 |
5 | constructor(account: string, password: string) {
6 | this.account = account;
7 | this.password = password;
8 | }
9 |
10 | public isValid(): boolean {
11 | return !(!this.account || !this.password);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/results/byeongukchoi/src/models/LoginResponse.ts:
--------------------------------------------------------------------------------
1 | export interface ILoginResponse {
2 | code: number;
3 | message: string;
4 | }
5 |
6 | export class LoginResponseDTO implements ILoginResponse {
7 | code = 0;
8 | message = "";
9 | validate? = {};
10 | }
11 |
12 | export default class LoginResponse extends LoginResponseDTO {
13 | constructor(dto: LoginResponseDTO) {
14 | super();
15 | Object.assign(this, dto);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/results/byeongukchoi/src/models/Token.ts:
--------------------------------------------------------------------------------
1 | export default class LoginRequest {
2 | accessToken: string;
3 |
4 | constructor(accessToken: string) {
5 | this.accessToken = accessToken;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/results/byeongukchoi/src/models/User.ts:
--------------------------------------------------------------------------------
1 | export interface IUser {
2 | account: string;
3 | name: string;
4 | password: string;
5 | }
6 |
7 | export class UserDTO implements IUser {
8 | account = "";
9 | name = "";
10 | password = "";
11 | }
12 |
13 | export default class User extends UserDTO {
14 | constructor(dto?: UserDTO) {
15 | super();
16 | Object.assign(this, dto);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/results/byeongukchoi/src/router/index.ts:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import VueRouter, { RouteConfig } from "vue-router";
3 | import store from "../store";
4 | import Home from "../views/Home.vue";
5 |
6 | Vue.use(VueRouter);
7 |
8 | const routes: Array = [
9 | {
10 | path: "/",
11 | name: "Home",
12 | component: Home,
13 | beforeEnter(to, from, next) {
14 | store.getters.isLoggedIn() ? next() : next("/login");
15 | },
16 | },
17 | {
18 | path: "/login",
19 | name: "Login",
20 | component: () => import("../views/Login.vue"),
21 | beforeEnter(to, from, next) {
22 | store.getters.isLoggedIn() ? next("/") : next();
23 | },
24 | },
25 | ];
26 |
27 | const router = new VueRouter({
28 | mode: "history",
29 | base: process.env.BASE_URL,
30 | routes,
31 | });
32 |
33 | export default router;
34 |
--------------------------------------------------------------------------------
/results/byeongukchoi/src/shims-tsx.d.ts:
--------------------------------------------------------------------------------
1 | import Vue, { VNode } from "vue";
2 |
3 | declare global {
4 | namespace JSX {
5 | // tslint:disable no-empty-interface
6 | interface Element extends VNode {}
7 | // tslint:disable no-empty-interface
8 | interface ElementClass extends Vue {}
9 | interface IntrinsicElements {
10 | [elem: string]: any;
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/results/byeongukchoi/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | declare module "*.vue" {
2 | import Vue from "vue";
3 | export default Vue;
4 | }
5 |
--------------------------------------------------------------------------------
/results/byeongukchoi/src/utils/cookies.ts:
--------------------------------------------------------------------------------
1 | function saveAccessTokenToCookie(value: string): void {
2 | document.cookie = `devbadak_auth=${value}`;
3 | }
4 |
5 | function getAccessTokenFromCookie(): string {
6 | return document.cookie.replace(
7 | /(?:(?:^|.*;\s*)devbadak_auth\s*=\s*([^;]*).*$)|^.*$/,
8 | "$1"
9 | );
10 | }
11 |
12 | function deleteAccessTokenFromCookie(): void {
13 | document.cookie = "devbadak_auth=; expires=Thu, 01 Jan 1970 00:00:01 GMT;";
14 | }
15 |
16 | export {
17 | saveAccessTokenToCookie,
18 | getAccessTokenFromCookie,
19 | deleteAccessTokenFromCookie,
20 | };
21 |
--------------------------------------------------------------------------------
/results/byeongukchoi/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
24 |
--------------------------------------------------------------------------------
/results/byeongukchoi/tests/unit/example.spec.ts:
--------------------------------------------------------------------------------
1 | import { expect } from "chai";
2 | import { shallowMount } from "@vue/test-utils";
3 | import Login from "@/views/Login.vue";
4 |
5 | describe("HelloWorld.vue", () => {
6 | it("renders props.msg when passed", () => {
7 | const msg = "new message";
8 | const wrapper = shallowMount(Login, {
9 | propsData: { msg },
10 | });
11 | expect(wrapper.text()).to.include(msg);
12 | });
13 | });
14 |
--------------------------------------------------------------------------------
/results/byeongukchoi/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "strict": true,
6 | "jsx": "preserve",
7 | "importHelpers": true,
8 | "moduleResolution": "node",
9 | "skipLibCheck": true,
10 | "esModuleInterop": true,
11 | "allowSyntheticDefaultImports": true,
12 | "sourceMap": true,
13 | "baseUrl": ".",
14 | "types": [
15 | "webpack-env",
16 | "mocha",
17 | "chai"
18 | ],
19 | "paths": {
20 | "@/*": [
21 | "src/*"
22 | ]
23 | },
24 | "lib": [
25 | "esnext",
26 | "dom",
27 | "dom.iterable",
28 | "scripthost"
29 | ]
30 | },
31 | "include": [
32 | "src/**/*.ts",
33 | "src/**/*.tsx",
34 | "src/**/*.vue",
35 | "tests/**/*.ts",
36 | "tests/**/*.tsx"
37 | ],
38 | "exclude": [
39 | "node_modules"
40 | ]
41 | }
42 |
--------------------------------------------------------------------------------
/results/cozy60/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/results/cozy60/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": true,
3 | "singleQuote": true,
4 | "endOfLine": "lf",
5 | "tabWidth": 2,
6 | "useTabs": false
7 | }
8 |
--------------------------------------------------------------------------------
/results/cozy60/README.md:
--------------------------------------------------------------------------------
1 | # Pilot React Project
2 |
3 | ## 요구 사항
4 |
5 | - [x] git (github)
6 | - [ ] webstorm // vscode 사용했습니다
7 | - [x] React
8 | - [x] Typescript
9 | - [ ] Test Case 작성
10 | - [x] 자바스크립트 Object `{}` (type object 포함)의 사용을 하지말아보자! // 노력해봤는데 맞는 시도인지 자신이 없네요..^_ㅠ
11 | - [x] API 요청, 응답 데이터는 클래스를 이용
--------------------------------------------------------------------------------
/results/cozy60/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cozy60",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@emotion/core": "^11.0.0",
7 | "@emotion/react": "^11.4.0",
8 | "@testing-library/jest-dom": "^5.14.1",
9 | "@testing-library/react": "^11.2.7",
10 | "@testing-library/user-event": "^12.8.3",
11 | "@types/jest": "^26.0.24",
12 | "@types/node": "^12.20.16",
13 | "@types/react": "^17.0.14",
14 | "@types/react-dom": "^17.0.9",
15 | "axios": "^0.21.1",
16 | "react": "^17.0.2",
17 | "react-dom": "^17.0.2",
18 | "react-router-dom": "^5.2.0",
19 | "react-scripts": "4.0.3",
20 | "typescript": "^4.3.5",
21 | "web-vitals": "^1.1.2"
22 | },
23 | "scripts": {
24 | "start": "react-scripts start",
25 | "build": "react-scripts build",
26 | "test": "react-scripts test",
27 | "eject": "react-scripts eject"
28 | },
29 | "eslintConfig": {
30 | "extends": [
31 | "react-app",
32 | "react-app/jest"
33 | ]
34 | },
35 | "browserslist": {
36 | "production": [
37 | ">0.2%",
38 | "not dead",
39 | "not op_mini all"
40 | ],
41 | "development": [
42 | "last 1 chrome version",
43 | "last 1 firefox version",
44 | "last 1 safari version"
45 | ]
46 | },
47 | "devDependencies": {
48 | "@types/react-router-dom": "^5.1.8"
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/results/cozy60/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/cozy60/public/favicon.ico
--------------------------------------------------------------------------------
/results/cozy60/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/cozy60/public/logo192.png
--------------------------------------------------------------------------------
/results/cozy60/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/cozy60/public/logo512.png
--------------------------------------------------------------------------------
/results/cozy60/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/results/cozy60/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/results/cozy60/src/App.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
--------------------------------------------------------------------------------
/results/cozy60/src/App.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render, screen } from '@testing-library/react';
3 | import App from './App';
4 |
5 | test('renders learn react link', () => {
6 | render();
7 | const linkElement = screen.getByText(/learn react/i);
8 | expect(linkElement).toBeInTheDocument();
9 | });
10 |
--------------------------------------------------------------------------------
/results/cozy60/src/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import './App.css';
3 | import { Route } from 'react-router-dom';
4 | import LoginPage from './pages/LoginPage';
5 | import UserInfoPage from './pages/UserInfoPage';
6 |
7 | function App() {
8 | return (
9 |
10 |
11 |
12 |
13 | );
14 | }
15 |
16 | export default App;
17 |
--------------------------------------------------------------------------------
/results/cozy60/src/components/Button/Button.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import { css } from '@emotion/react';
3 | import React from 'react';
4 | import palette from '../../library/styles/palette';
5 | import Children from '../../library/utils/children';
6 |
7 | export class ButtonType extends Children {
8 | type: 'button' | 'submit' | 'reset';
9 | color: 'blue' | 'red';
10 |
11 | constructor(
12 | type: 'button' | 'submit' | 'reset',
13 | color: 'blue' | 'red',
14 | children: React.ReactNode
15 | ) {
16 | super(children);
17 | this.type = type;
18 | this.color = color;
19 | }
20 | }
21 |
22 | function Button({ type, color, children }: ButtonType) {
23 | return (
24 |
27 | );
28 | }
29 |
30 | const buttonStyle = (color: 'blue' | 'red') => css`
31 | display: block;
32 | width: 100%;
33 | padding: 10px;
34 | font-weight: 700;
35 | cursor: pointer;
36 | border: none;
37 | border-radius: 8px;
38 | color: ${palette.white};
39 | background-color: ${palette[color]};
40 |
41 | :focus {
42 | outline: none;
43 | }
44 |
45 | :active {
46 | opacity: 0.7;
47 | }
48 | `;
49 |
50 | export default Button;
51 |
--------------------------------------------------------------------------------
/results/cozy60/src/components/Button/index.ts:
--------------------------------------------------------------------------------
1 | export { default } from './Button';
2 |
--------------------------------------------------------------------------------
/results/cozy60/src/components/Card/Card.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import { css } from '@emotion/react';
3 | import React from 'react';
4 | import palette from '../../library/styles/palette';
5 | import Children from '../../library/utils/children';
6 |
7 | function Card({ children }: Children) {
8 | return (
9 |
10 |
11 |
12 | );
13 | }
14 |
15 | const sectionStyle = css`
16 | display: flex;
17 | width: 100%;
18 | height: 100vh;
19 | justify-content: center;
20 | align-items: center;
21 | `;
22 |
23 | const borderStyle = css`
24 | padding: 30px 40px;
25 | background-color: ${palette.white};
26 | border: 2px solid ${palette.border};
27 | border-radius: 9px;
28 | `;
29 |
30 | export default Card;
31 |
--------------------------------------------------------------------------------
/results/cozy60/src/components/Card/index.ts:
--------------------------------------------------------------------------------
1 | export { default } from './Card';
2 |
--------------------------------------------------------------------------------
/results/cozy60/src/components/ErrorMessage/ErrorMessage.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import { css } from '@emotion/react';
3 | import React from 'react';
4 | import palette from '../../library/styles/palette';
5 | import Children from '../../library/utils/children';
6 |
7 | function ErrorMessage({ children }: Children) {
8 | return {children}
;
9 | }
10 |
11 | const errorMessageStyle = css`
12 | font-family: 'Noto Sans KR', sans-serif;
13 | font-weight: 600;
14 | text-align: center;
15 | color: ${palette.red};
16 | `;
17 |
18 | export default ErrorMessage;
19 |
--------------------------------------------------------------------------------
/results/cozy60/src/components/ErrorMessage/index.ts:
--------------------------------------------------------------------------------
1 | export { default } from './ErrorMessage';
2 |
--------------------------------------------------------------------------------
/results/cozy60/src/components/Footer/Footer.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import { css } from '@emotion/react';
3 | import React from 'react';
4 | import Children from '../../library/utils/children';
5 |
6 | function Footer({ children }: Children) {
7 | return ;
8 | }
9 |
10 | const footerStyle = css`
11 | margin-top: 20px;
12 | margin-bottom: 14px;
13 | `;
14 |
15 | export default Footer;
16 |
--------------------------------------------------------------------------------
/results/cozy60/src/components/Footer/index.ts:
--------------------------------------------------------------------------------
1 | export { default } from './Footer';
2 |
--------------------------------------------------------------------------------
/results/cozy60/src/components/Form/Form.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import { css } from '@emotion/react';
3 | import React from 'react';
4 | import palette from '../../library/styles/palette';
5 | import Children from '../../library/utils/children';
6 |
7 | class FormType extends Children {
8 | onSubmit?: React.FormEventHandler;
9 |
10 | constructor(
11 | onSubmit: React.FormEventHandler,
12 | children: React.ReactNode
13 | ) {
14 | super(children);
15 | this.onSubmit = onSubmit;
16 | }
17 | }
18 |
19 | function Form({ onSubmit, children }: FormType) {
20 | return (
21 |
24 | );
25 | }
26 |
27 | const formStyle = css`
28 | display: flex;
29 | justify-content: center;
30 |
31 | fieldset {
32 | width: 100%;
33 | border: none;
34 | }
35 |
36 | label {
37 | display: block;
38 | font: bold 15px/24px 'Haas Grot Text R Web', 'Helvetica Neue', Helvetica,
39 | Arial, sans-serif;
40 | margin: 14px 0 4px;
41 | color: ${palette.dark};
42 | }
43 |
44 | footer {
45 | margin-top: 20px;
46 | margin-bottom: 14px;
47 | }
48 | `;
49 |
50 | export default Form;
51 |
--------------------------------------------------------------------------------
/results/cozy60/src/components/Form/index.ts:
--------------------------------------------------------------------------------
1 | export { default } from './Form';
2 |
--------------------------------------------------------------------------------
/results/cozy60/src/components/Input/Input.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import { css } from '@emotion/react';
3 | import React from 'react';
4 | import palette from '../../library/styles/palette';
5 |
6 | class InputProps {
7 | type: string;
8 | name: string;
9 | id: string;
10 | onChange?: React.ChangeEventHandler;
11 |
12 | constructor(
13 | type: string,
14 | name: string,
15 | id: string,
16 | onChange: React.ChangeEventHandler
17 | ) {
18 | this.type = type;
19 | this.name = name;
20 | this.id = id;
21 | this.onChange = onChange;
22 | }
23 | }
24 |
25 | function Input({ type, name, id, onChange }: InputProps) {
26 | return (
27 |
34 | );
35 | }
36 |
37 | const inputStyle = css`
38 | width: 300px;
39 | height: 36px;
40 | background-color: ${palette.input};
41 | font-size: 14px;
42 | padding: 10px 16px;
43 | border: 1px solid ${palette.border};
44 | border-radius: 8px;
45 |
46 | :focus {
47 | outline: none;
48 | }
49 | `;
50 |
51 | export default Input;
52 |
--------------------------------------------------------------------------------
/results/cozy60/src/components/Input/index.ts:
--------------------------------------------------------------------------------
1 | export { default } from './Input';
2 |
--------------------------------------------------------------------------------
/results/cozy60/src/components/Layouts/Container.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import React from 'react';
3 | import { css } from '@emotion/react';
4 | import Children from '../../library/utils/children';
5 | import palette from '../../library/styles/palette';
6 |
7 | function Container({ children }: Children) {
8 | return {children};
9 | }
10 |
11 | const containerStyle = css`
12 | /* display: flex;
13 | width: 100%;
14 | height: 100vh;
15 | max-width: 400px;
16 | justify-content: center;
17 | align-items: center; */
18 | `;
19 |
20 | export default Container;
21 |
--------------------------------------------------------------------------------
/results/cozy60/src/components/Layouts/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Container } from './Container';
2 |
--------------------------------------------------------------------------------
/results/cozy60/src/components/UserInfo/UserInfo.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import { css } from '@emotion/react';
3 | import React from 'react';
4 |
5 | class UsreInfoType {
6 | dt: string;
7 | dd: string | number | undefined;
8 |
9 | constructor(dt: string, dd: string | number | undefined) {
10 | this.dt = dt;
11 | this.dd = dd;
12 | }
13 | }
14 |
15 | function UserInfo({ dt, dd }: UsreInfoType) {
16 | return (
17 |
18 | - {dt}
19 | - {dd}
20 |
21 | );
22 | }
23 |
24 | const userInfoStyle = css`
25 | & {
26 | font-family: 'Noto Sans KR', sans-serif;
27 | }
28 |
29 | dt,
30 | dd {
31 | display: inline-block;
32 | }
33 |
34 | dt {
35 | margin-right: 16px;
36 | font-weight: 700;
37 | }
38 |
39 | dd {
40 | margin: 0;
41 | }
42 | `;
43 |
44 | export default UserInfo;
45 |
--------------------------------------------------------------------------------
/results/cozy60/src/components/UserInfo/index.ts:
--------------------------------------------------------------------------------
1 | export { default } from './UserInfo';
2 |
--------------------------------------------------------------------------------
/results/cozy60/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/results/cozy60/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import { BrowserRouter } from 'react-router-dom';
4 | import './index.css';
5 | import App from './App';
6 |
7 | ReactDOM.render(
8 |
9 |
10 |
11 |
12 | ,
13 | document.getElementById('root')
14 | );
15 |
--------------------------------------------------------------------------------
/results/cozy60/src/library/api/apiClient.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | const apiClient = axios.create({
4 | baseURL: 'http://localhost:5000',
5 | });
6 |
7 | const token = window.sessionStorage.getItem('accessToken');
8 |
9 | apiClient.defaults.headers['Access-Control-Allow-Origin'] =
10 | 'http://localhost:5000';
11 | apiClient.defaults.headers['Access-Control-Allow-Credentials'] = 'true';
12 | apiClient.defaults.headers['Authorization'] = `Bearer ${token}`;
13 |
14 | export default apiClient;
15 |
--------------------------------------------------------------------------------
/results/cozy60/src/library/api/auth/auth.ts:
--------------------------------------------------------------------------------
1 | import apiClient from '../apiClient';
2 |
3 | export class AuthApi {
4 | static async signIn(account: string, password: string) {
5 | const res = await apiClient.post('/auth/login', {
6 | account: account,
7 | password: password,
8 | });
9 | window.sessionStorage.setItem('accessToken', res.data?.accessToken);
10 |
11 | return res;
12 | }
13 |
14 | static async signOut() {
15 | const res = await apiClient.get('/auth/logout');
16 | sessionStorage.clear();
17 |
18 | return res;
19 | }
20 |
21 | static async getUserInfo() {
22 | const res = await apiClient.get('/v1/users/me');
23 |
24 | return res;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/results/cozy60/src/library/styles/palette.ts:
--------------------------------------------------------------------------------
1 | class Palette {
2 | black: string;
3 | dark: string;
4 | input: string;
5 | border: string;
6 | red: string;
7 | blue: string;
8 | white: string;
9 |
10 | constructor() {
11 | this.black = '#000';
12 | this.dark = '#191a20';
13 | this.input = '#f3f3f4';
14 | this.border = '#e0e2e7';
15 | this.red = '#f86d7d';
16 | this.blue = '#3da5f5';
17 | this.white = '#fff';
18 | }
19 | }
20 |
21 | const palette = new Palette();
22 |
23 | export default palette;
24 |
--------------------------------------------------------------------------------
/results/cozy60/src/library/utils/children.ts:
--------------------------------------------------------------------------------
1 | class Children {
2 | children: React.ReactNode;
3 |
4 | constructor(children: React.ReactNode) {
5 | this.children = children;
6 | }
7 | }
8 |
9 | export default Children;
10 |
--------------------------------------------------------------------------------
/results/cozy60/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/results/cozy60/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom';
6 |
--------------------------------------------------------------------------------
/results/cozy60/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 | "allowJs": true,
10 | "skipLibCheck": true,
11 | "esModuleInterop": true,
12 | "allowSyntheticDefaultImports": true,
13 | "strict": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "noFallthroughCasesInSwitch": true,
16 | "module": "esnext",
17 | "moduleResolution": "node",
18 | "resolveJsonModule": true,
19 | "isolatedModules": true,
20 | "noEmit": true,
21 | "jsx": "react-jsx"
22 | },
23 | "include": [
24 | "src"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/hayoung-jeremy/public/favicon.ico
--------------------------------------------------------------------------------
/results/hayoung-jeremy/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/hayoung-jeremy/public/logo192.png
--------------------------------------------------------------------------------
/results/hayoung-jeremy/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/hayoung-jeremy/public/logo512.png
--------------------------------------------------------------------------------
/results/hayoung-jeremy/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/App.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render, screen } from '@testing-library/react';
3 | import App from './App';
4 |
5 | test('renders learn react link', () => {
6 | render();
7 | const linkElement = screen.getByText(/learn react/i);
8 | expect(linkElement).toBeInTheDocument();
9 | });
10 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/App.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import GlobalStyle from "./style/GlobalStyle";
3 | import { BrowserRouter, Route, Switch, Redirect } from "react-router-dom";
4 | import { LoginPage, ProfilePage } from "pages";
5 |
6 | function App() {
7 | return (
8 | <>
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | >
18 | );
19 | }
20 |
21 | export default App;
22 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/components/button/Button.tsx:
--------------------------------------------------------------------------------
1 | import React, { ButtonHTMLAttributes } from "react";
2 | import styled from "styled-components";
3 | import { lighten, darken } from "polished";
4 |
5 | // custom
6 | import { PALETTE } from "style";
7 |
8 | const Button = ({
9 | children,
10 | ...rest
11 | }: ButtonHTMLAttributes) => {
12 | return {children};
13 | };
14 |
15 | // style
16 | const StyledButton = styled.button`
17 | display: inline-flex;
18 | justify-content: center;
19 | align-items: center;
20 | width: 100%;
21 | padding: 12px 20px;
22 | border: 1px solid ${PALETTE.GRAY};
23 | border-radius: 4px;
24 | color: ${darken(0.2, PALETTE.GRAY)};
25 | font-size: 14px;
26 | background-color: transparent;
27 | transition: 0.2s;
28 |
29 | &:not(:first-of-type) {
30 | margin-top: 8px;
31 | }
32 | &:hover {
33 | border-color: ${PALETTE.MAIN};
34 | color: ${darken(0.1, PALETTE.MAIN)};
35 | transform: perspective(1000px) translateZ(-5px);
36 | }
37 | &:active {
38 | border-color: ${darken(0.08, PALETTE.MAIN)};
39 | background-color: ${lighten(0.185, PALETTE.MAIN)};
40 | transform: perspective(1000px) translateZ(-15px);
41 | }
42 | `;
43 |
44 | export default Button;
45 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/components/button/index.ts:
--------------------------------------------------------------------------------
1 | export { default } from "./Button";
2 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/components/form/Form.tsx:
--------------------------------------------------------------------------------
1 | import React, { FormHTMLAttributes } from "react";
2 | import styled from "styled-components";
3 | // custom
4 | import { PALETTE } from "style";
5 |
6 | const Form = ({ children, ...rest }: FormHTMLAttributes) => {
7 | return {children};
8 | };
9 |
10 | // style
11 | const StyledForm = styled.form`
12 | padding: 40px 0;
13 | & .errorMessage {
14 | height: 14px;
15 | margin-bottom: 60px;
16 | text-indent: 8px;
17 | font-size: 14px;
18 | color: ${PALETTE.RED};
19 | }
20 | `;
21 |
22 | export default Form;
23 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/components/form/index.ts:
--------------------------------------------------------------------------------
1 | export { default } from "./Form";
2 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/components/index.ts:
--------------------------------------------------------------------------------
1 | export { default as PageTemplate } from "./pageTemplate";
2 | export { default as Form } from "./form";
3 | export { default as Button } from "./button";
4 | export { default as Input } from "./input";
5 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/components/input/Input.tsx:
--------------------------------------------------------------------------------
1 | import React, { InputHTMLAttributes } from "react";
2 | import styled, { css } from "styled-components";
3 | import { PALETTE } from "style";
4 | import { darken, lighten } from "polished";
5 |
6 | const Input = (props: InputHTMLAttributes) => {
7 | return ;
8 | };
9 |
10 | // style
11 | const StyledInput = styled.input`
12 | width: 100%;
13 | padding: 8px 12px;
14 | outline: none;
15 | border: none;
16 | border-bottom: 1px solid ${PALETTE.GRAY};
17 |
18 | font-size: 16px;
19 | transition: 0.2s;
20 | ${(props) =>
21 | props.value !== ""
22 | ? css`
23 | color: ${darken(0.2, PALETTE.MAIN)};
24 | border-color: ${PALETTE.MAIN};
25 | `
26 | : css`
27 | color: ${lighten(0.2, PALETTE.BLACK)};
28 | `}
29 |
30 | &:not(:first-of-type) {
31 | margin-top: 16px;
32 | }
33 | &:last-of-type {
34 | margin-bottom: 12px;
35 | }
36 | &::placeholder {
37 | color: ${PALETTE.GRAY};
38 | transition: 0.3s;
39 | }
40 | &:focus {
41 | border-color: ${PALETTE.MAIN};
42 | color: ${darken(0.2, PALETTE.MAIN)};
43 | &::placeholder {
44 | color: transparent;
45 | }
46 | }
47 | `;
48 |
49 | export default Input;
50 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/components/input/index.ts:
--------------------------------------------------------------------------------
1 | export {default} from "./Input"
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/components/pageTemplate/PageTemplate.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import styled from "styled-components";
3 | import { darken, lighten } from "polished";
4 |
5 | // custom
6 | import { PALETTE } from "style";
7 |
8 | interface PageProps {
9 | children?: React.ReactNode;
10 | title?: string;
11 | }
12 | const PageTemplate = ({ children, title }: PageProps) => {
13 | return (
14 |
15 |
16 |
{title}
17 | {children}
18 |
19 |
20 | );
21 | };
22 |
23 | // style
24 | const StyledMain = styled.main`
25 | height: 100%;
26 | display: flex;
27 | justify-content: center;
28 | align-items: center;
29 | & .container {
30 | width: 520px;
31 | margin-top: 4vw;
32 | padding: 32px 24px;
33 | border-radius: 12px;
34 | background-color: white;
35 | box-shadow: 0 0 4px rgba(0, 0, 0, 0.1);
36 | }
37 | & .title {
38 | margin-bottom: 20px;
39 | font-size: 28px;
40 | font-weight: 500;
41 | color: ${lighten(0.2, PALETTE.BLACK)};
42 | }
43 | & .userInfo {
44 | margin-bottom: 20px;
45 | font-size: 20px;
46 | color: ${darken(0.2, PALETTE.MAIN)};
47 | }
48 | `;
49 |
50 | export default PageTemplate;
51 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/components/pageTemplate/index.ts:
--------------------------------------------------------------------------------
1 | export { default } from "./PageTemplate";
2 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 | import { Provider } from "react-redux";
4 |
5 | // custom
6 | import App from "./App";
7 | import reportWebVitals from "./reportWebVitals";
8 | import { store } from "store/store";
9 |
10 | ReactDOM.render(
11 |
12 |
13 |
14 |
15 | ,
16 | document.getElementById("root")
17 | );
18 |
19 | // If you want to start measuring performance in your app, pass a function
20 | // to log results (for example: reportWebVitals(console.log))
21 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
22 | reportWebVitals();
23 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/pages/Login/index.ts:
--------------------------------------------------------------------------------
1 | export { default } from "./LoginPage";
2 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/pages/Profile/index.ts:
--------------------------------------------------------------------------------
1 | export { default } from "./ProfilePage";
2 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/pages/index.ts:
--------------------------------------------------------------------------------
1 | export { default as LoginPage } from "./Login";
2 | export { default as ProfilePage } from "./Profile";
3 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/reportWebVitals.ts:
--------------------------------------------------------------------------------
1 | import { ReportHandler } from 'web-vitals';
2 |
3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => {
4 | if (onPerfEntry && onPerfEntry instanceof Function) {
5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
6 | getCLS(onPerfEntry);
7 | getFID(onPerfEntry);
8 | getFCP(onPerfEntry);
9 | getLCP(onPerfEntry);
10 | getTTFB(onPerfEntry);
11 | });
12 | }
13 | };
14 |
15 | export default reportWebVitals;
16 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom';
6 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/store/rootReducer.ts:
--------------------------------------------------------------------------------
1 | import { combineReducers } from "@reduxjs/toolkit";
2 | import { loginReducer } from "./loginSlice";
3 | import { getUserReducer } from "./authSlice";
4 |
5 | const rootReducer = combineReducers({
6 | login: loginReducer,
7 | getUser: getUserReducer,
8 | });
9 |
10 | export default rootReducer;
11 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/store/store.ts:
--------------------------------------------------------------------------------
1 | import { configureStore } from "@reduxjs/toolkit";
2 | import rootReducer from "./rootReducer";
3 | import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
4 |
5 | export const store = configureStore({
6 | reducer: rootReducer,
7 | });
8 |
9 | export type RootState = ReturnType;
10 | export type AppDispatch = typeof store.dispatch;
11 |
12 | // hooks :
13 | // 각각의 component 에서 useSelector 를 사용할 때마다 훅의 parameter 로 매번 RootState 를 가져와서 선언해주는 수고로움을 덜어줌
14 | // dispatch 역시 위와 동일
15 | export const useTypedSelector: TypedUseSelectorHook = useSelector;
16 | export const useAppDispatch = () => useDispatch();
17 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/style/GlobalStyle.ts:
--------------------------------------------------------------------------------
1 | import { createGlobalStyle } from "styled-components";
2 | import { reset } from "styled-reset";
3 | import PALETTE from "./palette";
4 |
5 | const GlobalStyle = createGlobalStyle`
6 | ${reset}
7 | *,*:before,*:after{
8 | box-sizing: border-box;
9 | }
10 | body{
11 | font-family: "Montserrat", "Noto Sans KR", sans-serif;
12 | background-color: ${PALETTE.BACKGROUND};
13 | }
14 | a{
15 | text-decoration: none;
16 | }
17 | button{
18 | outline: none;
19 | font-family: "Montserrat", "Noto Sans KR", sans-serif;
20 | cursor: pointer;
21 | }
22 | `;
23 |
24 | export default GlobalStyle;
25 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/style/index.ts:
--------------------------------------------------------------------------------
1 | export { default as GlobalStyle } from "./GlobalStyle";
2 | export { default as PALETTE } from "./palette";
3 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/style/palette.ts:
--------------------------------------------------------------------------------
1 | const PALETTE = {
2 | MAIN: "#97d8ff",
3 | BACKGROUND: "#f7f7f7",
4 | BLACK: "#333",
5 | GRAY: "#e5e5e5",
6 | RED: "#f7989b",
7 | };
8 |
9 | export default PALETTE;
10 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/src/types/auth.ts:
--------------------------------------------------------------------------------
1 | export interface loginInfo {
2 | account: string;
3 | password: string;
4 | }
5 |
6 | export interface userInfo {
7 | id?: number;
8 | account?: string;
9 | name?: string;
10 | level?: number;
11 | }
12 |
--------------------------------------------------------------------------------
/results/hayoung-jeremy/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 | "baseUrl": "./src",
10 | "allowJs": true,
11 | "skipLibCheck": true,
12 | "esModuleInterop": true,
13 | "allowSyntheticDefaultImports": true,
14 | "strict": true,
15 | "forceConsistentCasingInFileNames": true,
16 | "noFallthroughCasesInSwitch": true,
17 | "module": "esnext",
18 | "moduleResolution": "node",
19 | "resolveJsonModule": true,
20 | "isolatedModules": true,
21 | "noEmit": true,
22 | "jsx": "react-jsx"
23 | },
24 | "include": [
25 | "src"
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/results/hojongs/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/results/hojongs/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | 'extends': [
7 | 'plugin:vue/essential',
8 | 'eslint:recommended',
9 | '@vue/typescript/recommended'
10 | ],
11 | parserOptions: {
12 | ecmaVersion: 2020
13 | },
14 | rules: {
15 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
16 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
17 | },
18 | overrides: [
19 | {
20 | files: [
21 | '**/__tests__/*.{j,t}s?(x)',
22 | '**/tests/unit/**/*.spec.{j,t}s?(x)'
23 | ],
24 | env: {
25 | jest: true
26 | }
27 | }
28 | ]
29 | }
30 |
--------------------------------------------------------------------------------
/results/hojongs/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/results/hojongs/README.md:
--------------------------------------------------------------------------------
1 | # hojongs
2 |
3 | hojongs's pilot project based on Vue.js 2
4 |
5 | ## Project setup
6 | ```
7 | npm install
8 | ```
9 |
10 | ### Compiles and hot-reloads for development
11 | ```
12 | npm run serve
13 | ```
14 |
15 | ### Compiles and minifies for production
16 | ```
17 | npm run build
18 | ```
19 |
20 | ### Run your unit tests
21 | ```
22 | npm run test:unit
23 | ```
24 |
25 | ### Lints and fixes files
26 | ```
27 | npm run lint
28 | ```
29 |
30 | ### Customize configuration
31 | See [Configuration Reference](https://cli.vuejs.org/config/).
32 |
--------------------------------------------------------------------------------
/results/hojongs/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: '@vue/cli-plugin-unit-jest/presets/typescript'
3 | }
4 |
--------------------------------------------------------------------------------
/results/hojongs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hojongs",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "test:unit": "vue-cli-service test:unit",
9 | "lint": "vue-cli-service lint"
10 | },
11 | "dependencies": {
12 | "vue": "^2.6.11",
13 | "vue-class-component": "^7.2.3",
14 | "vue-property-decorator": "^9.1.2"
15 | },
16 | "devDependencies": {
17 | "@types/jest": "^24.0.19",
18 | "@typescript-eslint/eslint-plugin": "^4.18.0",
19 | "@typescript-eslint/parser": "^4.18.0",
20 | "@vue/cli-plugin-eslint": "~4.5.0",
21 | "@vue/cli-plugin-typescript": "~4.5.0",
22 | "@vue/cli-plugin-unit-jest": "~4.5.0",
23 | "@vue/cli-service": "~4.5.0",
24 | "@vue/eslint-config-typescript": "^7.0.0",
25 | "@vue/test-utils": "^1.0.3",
26 | "eslint": "^6.7.2",
27 | "eslint-plugin-vue": "^6.2.2",
28 | "typescript": "~4.1.5",
29 | "vue-template-compiler": "^2.6.11"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/results/hojongs/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/hojongs/public/favicon.ico
--------------------------------------------------------------------------------
/results/hojongs/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/results/hojongs/src/config.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | baseUrl: "http://localhost:5000"
3 | }
4 |
--------------------------------------------------------------------------------
/results/hojongs/src/dto/auth.ts:
--------------------------------------------------------------------------------
1 | export default class Auth {
2 | account: string;
3 | password: string;
4 |
5 | constructor(account: string, password: string) {
6 | this.account = account;
7 | this.password = password;
8 | }
9 |
10 | public toString(): string {
11 | return `Auth(account=${this.account},password=${this.password})`;
12 | }
13 | }
--------------------------------------------------------------------------------
/results/hojongs/src/dto/user.ts:
--------------------------------------------------------------------------------
1 | export default class User {
2 | id: number;
3 | account: string;
4 | name: string;
5 | level: number;
6 |
7 | constructor(id: number, account: string, name: string, level: number) {
8 | this.id = id;
9 | this.account = account;
10 | this.name = name;
11 | this.level = level;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/results/hojongs/src/entry/main.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Login from '@/view/login.vue'
3 |
4 | Vue.config.productionTip = false
5 |
6 | new Vue({
7 | render: h => h(Login),
8 | }).$mount('#app')
9 |
--------------------------------------------------------------------------------
/results/hojongs/src/entry/user.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import User from '@/view/user.vue'
3 |
4 | Vue.config.productionTip = false
5 |
6 | new Vue({
7 | render: h => h(User),
8 | }).$mount('#app')
9 |
--------------------------------------------------------------------------------
/results/hojongs/src/service/url_param_service.ts:
--------------------------------------------------------------------------------
1 | export default class UrlParamService {
2 | getAccessTokenOrThrow(): string {
3 | const accessToken = new URL(location.href).searchParams.get("accessToken");
4 | if (accessToken == null) throw "accessToken was null";
5 | return accessToken;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/results/hojongs/src/shims-tsx.d.ts:
--------------------------------------------------------------------------------
1 | import Vue, { VNode } from 'vue'
2 |
3 | declare global {
4 | namespace JSX {
5 | // tslint:disable no-empty-interface
6 | interface Element extends VNode {}
7 | // tslint:disable no-empty-interface
8 | interface ElementClass extends Vue {}
9 | interface IntrinsicElements {
10 | [elem: string]: any
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/results/hojongs/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.vue' {
2 | import Vue from 'vue'
3 | export default Vue
4 | }
5 |
--------------------------------------------------------------------------------
/results/hojongs/src/view/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
41 |
42 |
44 |
--------------------------------------------------------------------------------
/results/hojongs/src/view/User.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
id : {{ user.id }}
4 |
account : {{ user.account }}
5 |
name : {{ user.name }}
6 |
level : {{ user.level }}
7 |
8 |
9 |
10 |
41 |
42 |
44 |
--------------------------------------------------------------------------------
/results/hojongs/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "esnext",
5 | "strict": true,
6 | "jsx": "preserve",
7 | "importHelpers": true,
8 | "moduleResolution": "node",
9 | "experimentalDecorators": true,
10 | "skipLibCheck": true,
11 | "esModuleInterop": true,
12 | "allowSyntheticDefaultImports": true,
13 | "sourceMap": true,
14 | "baseUrl": ".",
15 | "types": [
16 | "webpack-env",
17 | "jest"
18 | ],
19 | "paths": {
20 | "@/*": [
21 | "src/*"
22 | ]
23 | },
24 | "lib": [
25 | "esnext",
26 | "dom",
27 | "dom.iterable",
28 | "scripthost"
29 | ]
30 | },
31 | "include": [
32 | "src/**/*.ts",
33 | "src/**/*.tsx",
34 | "src/**/*.vue",
35 | "tests/**/*.ts",
36 | "tests/**/*.tsx"
37 | ],
38 | "exclude": [
39 | "node_modules"
40 | ]
41 | }
42 |
--------------------------------------------------------------------------------
/results/hojongs/vue.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // https://cli.vuejs.org/config/#pages
3 | pages: {
4 | index: 'src/entry/main.ts',
5 | user: 'src/entry/user.ts',
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/results/imhojeong/.eslinitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
--------------------------------------------------------------------------------
/results/imhojeong/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | browser: true,
5 | node: true,
6 | },
7 | extends: [
8 | 'eslint:recommended',
9 | 'plugin:@typescript-eslint/eslint-recommended',
10 | 'plugin:@typescript-eslint/recommended',
11 | ],
12 | plugins: ['prettier', '@typescript-eslint'],
13 | rules: {
14 | 'prettier/prettier': [
15 | 'error',
16 | {
17 | singleQuote: true,
18 | semi: true,
19 | useTabs: false,
20 | tabWidth: 2,
21 | printWidth: 80,
22 | bracketSpacing: true,
23 | arrowParens: 'avoid',
24 | endOfLine: 'auto',
25 | },
26 | ],
27 | },
28 | parserOptions: {
29 | parser: '@typescript-eslint/parser',
30 | },
31 | };
32 |
--------------------------------------------------------------------------------
/results/imhojeong/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/results/imhojeong/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote" : true,
3 | "parser": "typescript",
4 | "semi": true,
5 | "useTabs" : false,
6 | "tabWidth" : 2,
7 | "printWidth": 120,
8 | "arrowParens": "always",
9 | }
--------------------------------------------------------------------------------
/results/imhojeong/README.md:
--------------------------------------------------------------------------------
1 | ### Login Test 페이지 입니다.
2 |
3 | - 부족한 개발 실력으로 한번 작성해 보았습니다.
--------------------------------------------------------------------------------
/results/imhojeong/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/imhojeong/public/favicon.ico
--------------------------------------------------------------------------------
/results/imhojeong/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/imhojeong/public/logo192.png
--------------------------------------------------------------------------------
/results/imhojeong/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/imhojeong/public/logo512.png
--------------------------------------------------------------------------------
/results/imhojeong/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/results/imhojeong/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/results/imhojeong/src/app/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-spin infinite 20s linear;
13 | }
14 | }
15 |
16 | .App-header {
17 | background-color: #282c34;
18 | min-height: 100vh;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: calc(10px + 2vmin);
24 | color: white;
25 | }
26 |
27 | .App-link {
28 | color: #61dafb;
29 | }
30 |
31 | @keyframes App-logo-spin {
32 | from {
33 | transform: rotate(0deg);
34 | }
35 | to {
36 | transform: rotate(360deg);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/results/imhojeong/src/app/App.tsx:
--------------------------------------------------------------------------------
1 | import LoginPage from '../pages/LoginPage';
2 | import './App.css';
3 |
4 | function App(): JSX.Element {
5 | return (
6 | <>
7 |
8 | >
9 | );
10 | }
11 |
12 | export default App;
13 |
--------------------------------------------------------------------------------
/results/imhojeong/src/app/hooks.ts:
--------------------------------------------------------------------------------
1 | import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
2 | import type { RootState, AppDispatch } from '../store/store';
3 |
4 | export const useAppDispatch = () => useDispatch();
5 | export const useAppSelector: TypedUseSelectorHook = useSelector;
6 |
--------------------------------------------------------------------------------
/results/imhojeong/src/app/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/results/imhojeong/src/app/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom';
6 |
--------------------------------------------------------------------------------
/results/imhojeong/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/results/imhojeong/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import reportWebVitals from './reportWebVitals';
5 | import { store } from './store/store';
6 | import { Provider } from 'react-redux';
7 | import { Router } from './routes';
8 | import { ThemeProvider } from 'styled-components';
9 | import { theme } from './styles/theme';
10 | import GlobalStyle from './styles/global-style';
11 |
12 | ReactDOM.render(
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | ,
21 | document.getElementById('root')
22 | );
23 |
24 | // If you want to start measuring performance in your app, pass a function
25 | // to log results (for example: reportWebVitals(console.log))
26 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
27 | reportWebVitals();
28 |
--------------------------------------------------------------------------------
/results/imhojeong/src/pages/LoginPage.tsx:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from 'react';
2 | import { LoginContainer } from '../components/LoginContainer';
3 | import { store } from '../store/store';
4 |
5 | function LoginPage(): JSX.Element {
6 | const [isLoggedIn, setIsLoggedIn] = useState(false);
7 | useEffect(() => {
8 | setIsLoggedIn(store.getState().user.isLoggedIn);
9 | }, [isLoggedIn]);
10 | return (
11 | <>
12 |
13 | >
14 | );
15 | }
16 |
17 | export default LoginPage;
18 |
--------------------------------------------------------------------------------
/results/imhojeong/src/pages/UserInfoPage.tsx:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from 'react';
2 | import { UserContainer } from '../components/UserContainer';
3 | import { store } from '../store/store';
4 |
5 | function UserInfoPage(): JSX.Element {
6 | const [isLoggedIn, setIsLoggedIn] = useState(false);
7 | useEffect(() => {
8 | setIsLoggedIn(store.getState().user.isLoggedIn);
9 | }, [isLoggedIn]);
10 | return (
11 | <>
12 |
13 | >
14 | );
15 | }
16 |
17 | export default UserInfoPage;
18 |
--------------------------------------------------------------------------------
/results/imhojeong/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/results/imhojeong/src/reducers/user.ts:
--------------------------------------------------------------------------------
1 | import { createSlice, PayloadAction } from '@reduxjs/toolkit';
2 | import type { RootState } from '../store/store';
3 |
4 | interface UserState {
5 | id: string;
6 | password: string;
7 | isLoggedIn: boolean;
8 | accessToken: string;
9 | }
10 |
11 | const initialState: UserState = {
12 | id: '',
13 | password: '',
14 | isLoggedIn: false,
15 | accessToken: '',
16 | };
17 |
18 | export const userSlice = createSlice({
19 | name: 'user',
20 | initialState,
21 | reducers: {
22 | change: (state, action: PayloadAction) => {
23 | state.id = action.payload[0];
24 | state.password = action.payload[1];
25 | },
26 | changeLoggedState: state => {
27 | state.isLoggedIn = !state.isLoggedIn;
28 | },
29 | changeAccessToken: (state, action: PayloadAction) => {
30 | state.accessToken = action.payload;
31 | },
32 | },
33 | });
34 |
35 | export const { change, changeLoggedState, changeAccessToken } =
36 | userSlice.actions;
37 |
38 | export const userCount = (state: RootState) => state.user.id;
39 |
40 | export default userSlice.reducer;
41 |
--------------------------------------------------------------------------------
/results/imhojeong/src/reportWebVitals.ts:
--------------------------------------------------------------------------------
1 | import { ReportHandler } from 'web-vitals';
2 |
3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => {
4 | if (onPerfEntry && onPerfEntry instanceof Function) {
5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
6 | getCLS(onPerfEntry);
7 | getFID(onPerfEntry);
8 | getFCP(onPerfEntry);
9 | getLCP(onPerfEntry);
10 | getTTFB(onPerfEntry);
11 | });
12 | }
13 | };
14 |
15 | export default reportWebVitals;
16 |
--------------------------------------------------------------------------------
/results/imhojeong/src/routes/index.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { BrowserRouter, Switch, Route, Redirect } from 'react-router-dom';
3 | import LoginPage from '../pages/LoginPage';
4 | import UserInfoPage from '../pages/UserInfoPage';
5 |
6 | export const Router: React.FC = () => (
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | );
15 |
--------------------------------------------------------------------------------
/results/imhojeong/src/store/store.ts:
--------------------------------------------------------------------------------
1 | import { configureStore } from '@reduxjs/toolkit';
2 | import userReducer from '../reducers/user';
3 |
4 | export const store = configureStore({
5 | reducer: {
6 | user: userReducer,
7 | },
8 | });
9 |
10 | export type RootState = ReturnType;
11 |
12 | export type AppDispatch = typeof store.dispatch;
13 |
--------------------------------------------------------------------------------
/results/imhojeong/src/styles/global-style.ts:
--------------------------------------------------------------------------------
1 | import { createGlobalStyle } from 'styled-components';
2 | import { normalize } from 'styled-normalize';
3 |
4 | export const GlobalStyle = createGlobalStyle`
5 | ${normalize}
6 |
7 | html,
8 | body {
9 | overflow: hidden;
10 | }
11 |
12 | * {
13 | box-sizing: border-box;
14 | }
15 |
16 | `;
17 |
18 | export default GlobalStyle;
19 |
--------------------------------------------------------------------------------
/results/imhojeong/src/styles/styled.d.ts:
--------------------------------------------------------------------------------
1 | import 'styled-components';
2 |
3 | declare module 'styled-components' {
4 | export interface DefaultTheme {
5 | basicWidth: string;
6 |
7 | color: {
8 | main: string;
9 | sub: string;
10 | };
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/results/imhojeong/src/styles/theme.ts:
--------------------------------------------------------------------------------
1 | import { DefaultTheme } from 'styled-components';
2 |
3 | const theme: DefaultTheme = {
4 | basicWidth: '320px',
5 |
6 | color: {
7 | main: '#1c1f25',
8 | sub: '#fff',
9 | },
10 | };
11 |
12 | const nextTheme: DefaultTheme = {
13 | basicWidth: '320px',
14 |
15 | color: {
16 | main: '#1c1f25',
17 | sub: '#fff',
18 | },
19 | };
20 |
21 | export { theme, nextTheme };
22 |
--------------------------------------------------------------------------------
/results/imhojeong/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es6",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 |
10 | "noImplicitAny": true,
11 | "allowJs": true,
12 | "skipLibCheck": true,
13 | "esModuleInterop": true,
14 | "allowSyntheticDefaultImports": true,
15 | "strict": true,
16 | "forceConsistentCasingInFileNames": true,
17 | "noFallthroughCasesInSwitch": true,
18 | "module": "esnext",
19 | "moduleResolution": "node",
20 | "resolveJsonModule": true,
21 | "isolatedModules": true,
22 | "noEmit": true,
23 | "jsx": "react-jsx",
24 | "outDir" : "./dist",
25 | "typeRoots": ["./node_modules/@types", "types"]
26 | },
27 | "include": [
28 | "src",
29 | "./src/**/*"
30 | ]
31 | }
32 |
--------------------------------------------------------------------------------
/results/jho2301/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "es2021": true,
5 | "node": true
6 | },
7 | "extends": [
8 | "eslint:recommended",
9 | "plugin:react/recommended",
10 | "plugin:@typescript-eslint/recommended"
11 | ],
12 | "parser": "@typescript-eslint/parser",
13 | "parserOptions": {
14 | "ecmaFeatures": {
15 | "jsx": true
16 | },
17 | "ecmaVersion": 12,
18 | "sourceType": "module"
19 | },
20 | "plugins": ["react", "@typescript-eslint"],
21 | "rules": {
22 | "react/react-in-jsx-scope": "off",
23 | "@typescript-eslint/explicit-module-boundary-types": "off",
24 | "@typescript-eslint/no-empty-function": "off"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/results/jho2301/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 100,
3 | "singleQuote": true,
4 | "quoteProps": "consistent"
5 | }
6 |
--------------------------------------------------------------------------------
/results/jho2301/.storybook/main.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "stories": [
3 | "../src/**/*.stories.mdx",
4 | "../src/**/*.stories.@(js|jsx|ts|tsx)"
5 | ],
6 | "addons": [
7 | "@storybook/addon-links",
8 | "@storybook/addon-essentials"
9 | ]
10 | }
--------------------------------------------------------------------------------
/results/jho2301/.storybook/preview.js:
--------------------------------------------------------------------------------
1 | import { RecoilRoot } from 'recoil';
2 | import GlobalStyle from '../src/Global.styles';
3 |
4 | export const parameters = {
5 | actions: { argTypesRegex: '^on[A-Z].*' },
6 | controls: {
7 | matchers: {
8 | color: /(background|color)$/i,
9 | date: /Date$/,
10 | },
11 | },
12 | };
13 |
14 | export const decorators = [
15 | (Story) => (
16 | <>
17 |
18 |
19 |
20 |
21 |
22 |
23 | >
24 | ),
25 | ];
26 |
--------------------------------------------------------------------------------
/results/jho2301/README.md:
--------------------------------------------------------------------------------
1 | ## Pilot React App
2 |
3 | 로그인 과정을 구현합니다!
4 |
--------------------------------------------------------------------------------
/results/jho2301/REQUIREMENTS.md:
--------------------------------------------------------------------------------
1 | # 기능 요구 사항
2 |
3 | - 사용자는 로그인을 할 수 있다.
4 |
5 | - 회원이 아닐시 에러를 표시한다.
6 |
7 | - 사용자는 로그아웃을 할 수 있다.
8 |
9 | - 로그인한 사용자는 회원정보를 확인할 수 있다.
10 |
--------------------------------------------------------------------------------
/results/jho2301/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | React Pilot App
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/results/jho2301/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { Suspense } from 'react';
2 | import { ErrorBoundary } from 'react-error-boundary';
3 | import { Switch } from 'react-router-dom';
4 | import { useRecoilValue } from 'recoil';
5 |
6 | import PrivateRoute from './components/PrivateRoute/PrivateRoute';
7 | import LoginPage from './pages/Login/LoginPage';
8 | import UserPage from './pages/User/UserPage';
9 | import { accessTokenState } from './state/login';
10 |
11 | const App = () => {
12 | const accessToken = useRecoilValue(accessTokenState);
13 |
14 | return (
15 | }>
25 |
26 |
32 |
33 |
34 |
35 |
36 | );
37 | };
38 |
39 | export default App;
40 |
--------------------------------------------------------------------------------
/results/jho2301/src/Global.styles.ts:
--------------------------------------------------------------------------------
1 | import { createGlobalStyle } from 'styled-components';
2 | import reset from 'styled-reset';
3 |
4 | import PALETTE from '../src/constants/palette';
5 |
6 | const GlobalStyle = createGlobalStyle`
7 | ${reset}
8 |
9 | * {
10 | box-sizing: border-box;
11 | outline: none;
12 | color: ${PALETTE.GRAY_900};
13 | user-select: none;
14 | }
15 | `;
16 |
17 | export default GlobalStyle;
18 |
--------------------------------------------------------------------------------
/results/jho2301/src/__test__/setupTests.ts:
--------------------------------------------------------------------------------
1 | import { server } from '../mock/server';
2 |
3 | beforeAll(() => {
4 | global.fetch = require('node-fetch');
5 | server.listen();
6 | });
7 |
8 | afterEach(() => {
9 | server.resetHandlers();
10 | });
11 |
12 | afterAll(() => {
13 | server.close();
14 | });
15 |
--------------------------------------------------------------------------------
/results/jho2301/src/__test__/testUtil.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react';
2 | import { Suspense } from 'react';
3 | import { BrowserRouter } from 'react-router-dom';
4 | import { RecoilRoot } from 'recoil';
5 |
6 | export const createPushMock = () => {
7 | const pushMock = jest.fn();
8 |
9 | jest.mock('react-router-dom', () => ({
10 | ...Object.assign({}, jest.requireActual('react-router-dom')),
11 | useHistory: () => ({ push: pushMock }),
12 | }));
13 |
14 | return pushMock;
15 | };
16 |
17 | export const createAlertMock = () => {
18 | const alertMock = jest.fn();
19 |
20 | global.alert = alertMock;
21 |
22 | return alertMock;
23 | };
24 |
25 | export const myRender = (children: React.ReactNode) =>
26 | render(
27 |
28 |
29 | {children}
30 |
31 |
32 | );
33 |
--------------------------------------------------------------------------------
/results/jho2301/src/__test__/user.test.tsx:
--------------------------------------------------------------------------------
1 | import { fireEvent, screen, waitFor } from '@testing-library/react';
2 |
3 | import UserPage from '../pages/User/UserPage';
4 | import { myRender } from './testUtil';
5 |
6 | describe('USER', () => {
7 | test('로그인한 사용자는 회원정보를 확인할 수 있다.', async () => {
8 | myRender();
9 |
10 | await screen.findByText(/닉네임/g);
11 | await screen.findByText(/999/g);
12 | });
13 |
14 | test('사용자는 로그아웃을 할 수 있다.', async () => {
15 | myRender();
16 |
17 | const $logoutButton = screen.getByText('로그아웃');
18 |
19 | fireEvent.click($logoutButton);
20 |
21 | await waitFor(() => expect(window.location.pathname).toEqual('/login'));
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/results/jho2301/src/components/@shared/Button/Button.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import Button from './Button';
4 |
5 | export default {
6 | title: 'Components/shared/Button',
7 | component: Button,
8 | } as Meta;
9 |
10 | const Template: Story = (args) => {
11 | return ;
12 | };
13 |
14 | export const Default = Template.bind({});
15 |
16 | Default.args = {};
17 |
--------------------------------------------------------------------------------
/results/jho2301/src/components/@shared/Button/Button.styles.ts:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | import PALETTE from '../../../constants/palette';
4 |
5 | const StyledButton = styled.button`
6 | background-color: transparent;
7 | border: 1px solid ${PALETTE.GRAY_400};
8 | padding: 0.75rem 2rem;
9 | border-radius: 0.375rem;
10 | cursor: pointer;
11 | transition: 0.2s all;
12 | width: 100%;
13 |
14 | &:hover {
15 | background-color: ${PALETTE.GRAY_100};
16 | border: 1px solid ${PALETTE.GRAY_200};
17 | }
18 |
19 | &:active {
20 | background-color: ${PALETTE.GRAY_200};
21 | border: 1px solid ${PALETTE.GRAY_400};
22 | }
23 | `;
24 |
25 | export default StyledButton;
26 |
--------------------------------------------------------------------------------
/results/jho2301/src/components/@shared/Button/Button.tsx:
--------------------------------------------------------------------------------
1 | import { ButtonHTMLAttributes } from 'react';
2 |
3 | import StyledButton from './Button.styles';
4 |
5 | const Button = ({ children, ...props }: ButtonHTMLAttributes) => {
6 | return {children};
7 | };
8 |
9 | export default Button;
10 |
--------------------------------------------------------------------------------
/results/jho2301/src/components/@shared/Input/Input.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import Input from './Input';
4 |
5 | export default {
6 | title: 'Components/shared/Input',
7 | component: Input,
8 | } as Meta;
9 |
10 | const Template: Story = (args) => {
11 | return ;
12 | };
13 |
14 | export const Default = Template.bind({});
15 |
16 | Default.args = {
17 | placeholder: '입력해주세요.',
18 | };
19 |
--------------------------------------------------------------------------------
/results/jho2301/src/components/@shared/Input/Input.styles.ts:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | import PALETTE from '../../../constants/palette';
4 |
5 | const StyledInput = styled.input`
6 | border: none;
7 | border-bottom: 1px solid ${PALETTE.GRAY_200};
8 | padding: 0.5rem;
9 | width: 100%;
10 | transition: 0.8s border-bottom;
11 |
12 | &:focus {
13 | border-bottom: 1px solid ${PALETTE.GRAY_900};
14 | }
15 |
16 | &::placeholder {
17 | color: ${PALETTE.GRAY_400};
18 | }
19 | `;
20 |
21 | export default StyledInput;
22 |
--------------------------------------------------------------------------------
/results/jho2301/src/components/@shared/Input/Input.tsx:
--------------------------------------------------------------------------------
1 | import { InputHTMLAttributes } from 'react';
2 | import StyledInput from './Input.styles';
3 |
4 | const Input = (props: InputHTMLAttributes) => {
5 | return ;
6 | };
7 |
8 | export default Input;
9 |
--------------------------------------------------------------------------------
/results/jho2301/src/components/@shared/Template/Template.styles.ts:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | export const StyledTemplate = styled.main`
4 | width: 100vw;
5 | height: 100vh;
6 | display: flex;
7 | justify-content: center;
8 | align-items: center;
9 | `;
10 |
--------------------------------------------------------------------------------
/results/jho2301/src/components/@shared/Template/Template.tsx:
--------------------------------------------------------------------------------
1 | import { StyledTemplate } from './Template.styles';
2 |
3 | interface TemplateProps {
4 | children: React.ReactNode;
5 | }
6 |
7 | const Template = ({ children }: TemplateProps) => {
8 | return {children};
9 | };
10 |
11 | export default Template;
12 |
--------------------------------------------------------------------------------
/results/jho2301/src/components/Login/Form/LoginForm.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import LoginForm from './LoginForm';
4 |
5 | export default {
6 | title: 'Components/LoginForm',
7 | component: LoginForm,
8 | } as Meta;
9 |
10 | const Template: Story = (args) => {
11 | return ;
12 | };
13 |
14 | export const Default = Template.bind({});
15 |
16 | Default.args = {};
17 |
--------------------------------------------------------------------------------
/results/jho2301/src/components/Login/Form/LoginForm.styles.ts:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import PALETTE from '../../../constants/palette';
3 | import Input from '../../@shared/Input/Input';
4 |
5 | export const StyledLoginForm = styled.form`
6 | width: 26rem;
7 | display: flex;
8 | flex-direction: column;
9 | padding: 2.25rem 3rem 2rem;
10 | border: 1px solid ${PALETTE.GRAY_200};
11 | align-items: center;
12 | border-radius: 1rem;
13 | `;
14 |
15 | export const LoginTitle = styled.h1`
16 | font-size: 1.75rem;
17 | font-weight: 700;
18 | margin-bottom: 2.25rem;
19 | `;
20 |
21 | export const LoginInput = styled(Input)`
22 | margin-bottom: 2rem;
23 |
24 | & + & {
25 | margin-bottom: 1rem;
26 | }
27 | `;
28 |
29 | export const MemoryCheckboxLabel = styled.label`
30 | display: flex;
31 | align-items: center;
32 | align-self: flex-end;
33 | margin-bottom: 2rem;
34 | font-size: 0.75rem;
35 | `;
36 |
--------------------------------------------------------------------------------
/results/jho2301/src/components/PrivateRoute/PrivateRoute.tsx:
--------------------------------------------------------------------------------
1 | import { Redirect, Route, RouteProps, useHistory } from 'react-router-dom';
2 |
3 | interface PrivateRouteProps extends RouteProps {
4 | isAuthed: boolean;
5 | redirectTo: string;
6 | }
7 |
8 | const PrivateRoute = ({ isAuthed, redirectTo, ...props }: PrivateRouteProps) => {
9 | return isAuthed ? : ;
10 | };
11 |
12 | export default PrivateRoute;
13 |
--------------------------------------------------------------------------------
/results/jho2301/src/components/User/UserInfo/UserInfo.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import UserInfo from './UserInfo';
4 |
5 | export default {
6 | title: 'Components/UserInfo',
7 | component: UserInfo,
8 | } as Meta;
9 |
10 | const Template: Story = (args) => {
11 | return ;
12 | };
13 |
14 | export const Default = Template.bind({});
15 |
16 | Default.args = {};
17 |
--------------------------------------------------------------------------------
/results/jho2301/src/components/User/UserInfo/UserInfo.styles.ts:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import PALETTE from '../../../constants/palette';
3 | import Button from '../../@shared/Button/Button';
4 | import Input from '../../@shared/Input/Input';
5 |
6 | export const StyledUserInfo = styled.section`
7 | width: 26rem;
8 | height: 20rem;
9 | display: flex;
10 | flex-direction: column;
11 | padding: 0 3rem;
12 | border: 1px solid ${PALETTE.GRAY_200};
13 | align-items: center;
14 | border-radius: 1rem;
15 | `;
16 |
17 | export const UserInfoTitle = styled.h1`
18 | font-size: 1.75rem;
19 | font-weight: 700;
20 | margin: 2.25rem 0;
21 | `;
22 |
23 | export const UserInfoText = styled.p`
24 | font-size: 1.125rem;
25 | font-weight: 500;
26 | margin: 1.5rem 0;
27 | align-self: flex-start;
28 | `;
29 |
30 | export const LogoutButton = styled(Button)`
31 | margin-top: 1rem;
32 | `;
33 |
--------------------------------------------------------------------------------
/results/jho2301/src/components/User/UserInfo/UserInfo.tsx:
--------------------------------------------------------------------------------
1 | import { LogoutButton, StyledUserInfo, UserInfoText, UserInfoTitle } from './UserInfo.styles';
2 | import useUser from '../../../service/hooks/useUser';
3 | import useAuth from '../../../service/hooks/useAuth';
4 |
5 | const UserInfo = () => {
6 | const { userInfo } = useUser();
7 | const { logout } = useAuth();
8 |
9 | return (
10 |
11 | 회원 정보
12 | 이름: {userInfo.name}
13 | 레벨: {userInfo.level}
14 | 로그아웃
15 |
16 | );
17 | };
18 |
19 | export default UserInfo;
20 |
--------------------------------------------------------------------------------
/results/jho2301/src/constants/palette.ts:
--------------------------------------------------------------------------------
1 | const PALETTE = {
2 | GRAY_100: '#eeeeee',
3 | GRAY_200: '#dddddd',
4 | GRAY_400: '#999999',
5 | GRAY_600: '#777777',
6 | GRAY_800: '#555555',
7 | GRAY_900: '#222222',
8 |
9 | GREEN_200: '#ebffeb',
10 | GREEN_300: '##d9fad9',
11 | GREEN_400: '#b2f7b0',
12 | GREEN_500: '#9ad698',
13 | GREEN_600: '#8bc28a',
14 | };
15 |
16 | export default PALETTE;
17 |
--------------------------------------------------------------------------------
/results/jho2301/src/constants/storage.ts:
--------------------------------------------------------------------------------
1 | export const STORAGE_KEY = {
2 | ACCESS_TOKEN: 'accessToken',
3 | };
4 |
--------------------------------------------------------------------------------
/results/jho2301/src/index.tsx:
--------------------------------------------------------------------------------
1 | import ReactDOM from 'react-dom';
2 | import { BrowserRouter } from 'react-router-dom';
3 | import { RecoilRoot } from 'recoil';
4 |
5 | import App from './App';
6 | import GlobalStyle from './Global.styles';
7 |
8 | const $root = document.getElementById('root');
9 |
10 | ReactDOM.render(
11 | <>
12 |
13 |
14 |
15 |
16 |
17 |
18 | >,
19 | $root
20 | );
21 |
--------------------------------------------------------------------------------
/results/jho2301/src/mock/handlers.ts:
--------------------------------------------------------------------------------
1 | import { LoginForm, User } from './../types';
2 | import { rest } from 'msw';
3 |
4 | export const loginHandlers = [
5 | rest.post('http://localhost:5000/auth/login', (req, res, ctx) => {
6 | const { account, password } = req.body;
7 |
8 | if (account !== 'devbadak' || password !== '1234') {
9 | return res(ctx.status(400), ctx.json({ message: 'wrong!' }));
10 | }
11 |
12 | return res(
13 | ctx.json({
14 | accessToken: 'xxxxxxxxxxxxxxx',
15 | })
16 | );
17 | }),
18 | rest.get('http://localhost:5000/auth/logout', (req, res, ctx) => {
19 | return res(ctx.status(204), ctx.text(''));
20 | }),
21 | ];
22 |
23 | export const userHandlers = [
24 | rest.get('http://localhost:5000/v1/users/me', (req, res, ctx) => {
25 | return res(
26 | ctx.json({
27 | name: '닉네임',
28 | level: 999,
29 | })
30 | );
31 | }),
32 | ];
33 |
--------------------------------------------------------------------------------
/results/jho2301/src/mock/server.ts:
--------------------------------------------------------------------------------
1 | import { loginHandlers, userHandlers } from './handlers';
2 | import { setupServer } from 'msw/node';
3 |
4 | export const server = setupServer(...loginHandlers, ...userHandlers);
5 |
--------------------------------------------------------------------------------
/results/jho2301/src/pages/Login/LoginPage.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import LoginPage from './LoginPage';
4 |
5 | export default {
6 | title: 'Pages/Login',
7 | component: LoginPage,
8 | } as Meta;
9 |
10 | const Template: Story = (args) => {
11 | return ;
12 | };
13 |
14 | export const Default = Template.bind({});
15 |
16 | Default.args = {};
17 |
--------------------------------------------------------------------------------
/results/jho2301/src/pages/Login/LoginPage.tsx:
--------------------------------------------------------------------------------
1 | import LoginForm from '../../components/Login/Form/LoginForm';
2 | import Template from '../../components/@shared/Template/Template';
3 |
4 | const LoginPage = () => {
5 | return (
6 |
7 |
8 |
9 | );
10 | };
11 |
12 | export default LoginPage;
13 |
--------------------------------------------------------------------------------
/results/jho2301/src/pages/User/UserPage.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import UserPage from './UserPage';
4 |
5 | export default {
6 | title: 'Pages/User',
7 | component: UserPage,
8 | } as Meta;
9 |
10 | const Template: Story = (args) => {
11 | return ;
12 | };
13 |
14 | export const Default = Template.bind({});
15 |
16 | Default.args = {};
17 |
--------------------------------------------------------------------------------
/results/jho2301/src/pages/User/UserPage.tsx:
--------------------------------------------------------------------------------
1 | import Template from '../../components/@shared/Template/Template';
2 | import UserInfo from '../../components/User/UserInfo/UserInfo';
3 |
4 | const LoginPage = () => {
5 | return (
6 |
7 |
8 |
9 | );
10 | };
11 |
12 | export default LoginPage;
13 |
--------------------------------------------------------------------------------
/results/jho2301/src/service/auth.ts:
--------------------------------------------------------------------------------
1 | import { STORAGE_KEY } from '../constants/storage';
2 |
3 | export const clearAccessTokenStorage = () => {
4 | sessionStorage.removeItem(STORAGE_KEY.ACCESS_TOKEN);
5 | localStorage.removeItem(STORAGE_KEY.ACCESS_TOKEN);
6 | };
7 |
--------------------------------------------------------------------------------
/results/jho2301/src/service/hooks/useLoginForm.ts:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 |
3 | import { LoginForm } from './../../types';
4 |
5 | const useLoginForm = () => {
6 | const [form, setForm] = useState({ account: '', password: '' });
7 | const [willTokenStored, setWillTokenStored] = useState(false);
8 |
9 | const setAccount = (account: string) => setForm({ ...form, account });
10 |
11 | const setPassword = (password: string) => setForm({ ...form, password });
12 |
13 | return { form, willTokenStored, setAccount, setPassword, setWillTokenStored };
14 | };
15 |
16 | export default useLoginForm;
17 |
--------------------------------------------------------------------------------
/results/jho2301/src/service/hooks/useUser.ts:
--------------------------------------------------------------------------------
1 | import { useRecoilValueLoadable, useSetRecoilState } from 'recoil';
2 |
3 | import { clearAccessTokenStorage } from '../../service/auth';
4 | import { accessTokenState } from '../../state/login';
5 | import { userInfoQuery } from '../../state/user';
6 | import { User } from '../../types';
7 |
8 | const useUser = () => {
9 | const userInfoLoadable = useRecoilValueLoadable(userInfoQuery);
10 | const setAccessToken = useSetRecoilState(accessTokenState);
11 |
12 | const userInfo: User =
13 | userInfoLoadable.state === 'hasValue'
14 | ? userInfoLoadable.contents
15 | : { account: '', name: '', id: -1, level: -1 };
16 |
17 | if (userInfoLoadable.state === 'hasError') {
18 | clearAccessTokenStorage();
19 | setAccessToken('');
20 | }
21 |
22 | return { userInfo };
23 | };
24 |
25 | export default useUser;
26 |
--------------------------------------------------------------------------------
/results/jho2301/src/service/request/index.ts:
--------------------------------------------------------------------------------
1 | import APIClient from '../../util/API';
2 |
3 | const BASE_URL = 'http://localhost:5000';
4 |
5 | const apiClient = new APIClient(BASE_URL);
6 |
7 | export default apiClient;
8 |
--------------------------------------------------------------------------------
/results/jho2301/src/service/request/login.ts:
--------------------------------------------------------------------------------
1 | import apiClient from '.';
2 |
3 | import { LoginForm } from './../../types';
4 |
5 | export const requestLogin = (form: LoginForm): Promise<{ accessToken: string }> =>
6 | apiClient.post('/auth/login', form);
7 |
8 | export const requestLogout = () => apiClient.get('/auth/logout');
9 |
--------------------------------------------------------------------------------
/results/jho2301/src/service/request/user.ts:
--------------------------------------------------------------------------------
1 | import apiClient from '.';
2 | import { User } from '../../types';
3 |
4 | export const requestGetUserInfo = (accessToken: string) => {
5 | return apiClient.get('/v1/users/me', accessToken);
6 | };
7 |
--------------------------------------------------------------------------------
/results/jho2301/src/state/login.ts:
--------------------------------------------------------------------------------
1 | import { atom } from 'recoil';
2 |
3 | import { STORAGE_KEY } from '../constants/storage';
4 |
5 | const getAccessTokenDefaultValue = () => {
6 | const local = localStorage.getItem(STORAGE_KEY.ACCESS_TOKEN);
7 | const session = sessionStorage.getItem(STORAGE_KEY.ACCESS_TOKEN);
8 |
9 | if (local) return local;
10 | if (session) return session;
11 | return '';
12 | };
13 |
14 | export const accessTokenState = atom({
15 | key: 'accessToken',
16 | default: getAccessTokenDefaultValue(),
17 | });
18 |
--------------------------------------------------------------------------------
/results/jho2301/src/state/user.ts:
--------------------------------------------------------------------------------
1 | import { selector } from 'recoil';
2 |
3 | import { requestGetUserInfo } from '../service/request/user';
4 | import { User } from '../types';
5 | import { accessTokenState } from './login';
6 |
7 | export const userInfoQuery = selector({
8 | key: 'userInfoQuery',
9 | get: ({ get }) => {
10 | const accessToken = get(accessTokenState);
11 |
12 | return requestGetUserInfo(accessToken);
13 | },
14 | });
15 |
--------------------------------------------------------------------------------
/results/jho2301/src/types.ts:
--------------------------------------------------------------------------------
1 | export interface LoginForm {
2 | account: string;
3 | password: string;
4 | }
5 |
6 | export type UserId = number;
7 |
8 | export type Level = number;
9 |
10 | export interface User {
11 | id: UserId;
12 | account: string;
13 | name: string;
14 | level: Level;
15 | }
16 |
--------------------------------------------------------------------------------
/results/jho2301/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "CommonJS",
4 | "target": "es5",
5 | "jsx": "react-jsx",
6 | "sourceMap": true,
7 | "allowJs": true,
8 | "strict": true,
9 | "allowSyntheticDefaultImports": true,
10 | "esModuleInterop": true
11 | },
12 | "files": ["src/index.tsx"]
13 | }
14 |
--------------------------------------------------------------------------------
/results/kimbiyam/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/results/kimbiyam/README.md:
--------------------------------------------------------------------------------
1 | # Pilot React
2 |
3 | ## Project Stack
4 |
5 | - React
6 | - Typescript
7 | - React Router Dom
8 | - React Query
9 | - jest
10 | - React Testing Library
11 | - Material-Ui
12 |
13 | ### Run
14 | ```shell
15 | $ npm run start
16 | ```
17 |
18 | ### Test
19 | ```shell
20 | $ npm run test
21 | ```
--------------------------------------------------------------------------------
/results/kimbiyam/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/kimbiyam/public/favicon.ico
--------------------------------------------------------------------------------
/results/kimbiyam/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/kimbiyam/public/logo192.png
--------------------------------------------------------------------------------
/results/kimbiyam/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/kimbiyam/public/logo512.png
--------------------------------------------------------------------------------
/results/kimbiyam/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/results/kimbiyam/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { Switch, Route } from "react-router-dom";
2 | import useCheckUserEffect from "./hooks/useCheckUserEffect";
3 | import LoginPage from "./pages/LoginPage";
4 | import NotFoundPage from "./pages/NotFoundPage";
5 | import UserProfilePage from "./pages/UserProfilePage";
6 | import tokenStorage from "./utils/tokenStorage";
7 |
8 | const App = () => {
9 | const isLoggedIn = !!tokenStorage.getToken();
10 |
11 | useCheckUserEffect({
12 | isLoggedIn: isLoggedIn,
13 | successPagePath: "/user/profile",
14 | failurePagePath: "/",
15 | });
16 |
17 | return (
18 |
19 |
20 |
21 |
22 |
23 | );
24 | };
25 |
26 | export default App;
27 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/api/apiClient.ts:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import { SERVER_URL, TOKEN_PREFIX } from "../constants/constants";
3 | import tokenStorage from "../utils/tokenStorage";
4 |
5 | const apiClient = axios.create({ baseURL: SERVER_URL });
6 |
7 | apiClient.interceptors.request.use((config) => {
8 | const accessToken = tokenStorage.getToken();
9 |
10 | config.headers.Authorization = `${TOKEN_PREFIX} ${accessToken}` || "";
11 |
12 | return config;
13 | });
14 |
15 | export default apiClient;
16 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/api/authApi.ts:
--------------------------------------------------------------------------------
1 | import LoginData from "../models/LoginData";
2 | import apiClient from "./apiClient";
3 |
4 | const API_LOGIN = "/auth/login";
5 | const API_LOGOUT = "/auth/logout";
6 |
7 | const login = async (loginData: LoginData) => {
8 | try {
9 | const response = await apiClient.post(API_LOGIN, loginData.toJson());
10 | const { data } = response;
11 |
12 | const { accessToken } = data;
13 |
14 | return accessToken;
15 | } catch (e) {
16 | const { message } = e.response.data;
17 | throw message;
18 | }
19 | };
20 |
21 | const logout = async () => {
22 | try {
23 | const response = await apiClient.get(API_LOGOUT);
24 | const { data } = response;
25 |
26 | return data;
27 | } catch (e) {
28 | throw e;
29 | }
30 | };
31 |
32 | const authApi = { login, logout };
33 |
34 | export default authApi;
35 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/api/userApi.ts:
--------------------------------------------------------------------------------
1 | import User from "../models/User";
2 | import apiClient from "./apiClient";
3 |
4 | const API_USERS_ME = "/v1/users/me";
5 |
6 | const getUserProfile = async () => {
7 | try {
8 | const response = await apiClient.get(API_USERS_ME);
9 | const { data } = response;
10 |
11 | const user = new User({ ...data });
12 |
13 | return user;
14 | } catch (e) {
15 | console.error(e);
16 | throw e;
17 | }
18 | };
19 |
20 | const userApi = { getUserProfile };
21 |
22 | export default userApi;
23 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/components/LoadingBackdrop.tsx:
--------------------------------------------------------------------------------
1 | import { Backdrop, CircularProgress, makeStyles } from "@material-ui/core";
2 |
3 | const useStyles = makeStyles({
4 | backdrop: {
5 | zIndex: 10,
6 | color: "#fff",
7 | },
8 | });
9 |
10 | export type LoadingBackdropProps = {
11 | open: boolean;
12 | };
13 |
14 | const LoadingBackdrop = ({ open }: LoadingBackdropProps) => {
15 | const classes = useStyles();
16 |
17 | return (
18 |
19 |
20 |
21 | );
22 | };
23 |
24 | export default LoadingBackdrop;
25 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/components/MainButton.tsx:
--------------------------------------------------------------------------------
1 | import { Button, ButtonProps, makeStyles } from "@material-ui/core";
2 |
3 | const useStyles = makeStyles({
4 | button: {
5 | width: "120px",
6 | },
7 | });
8 |
9 | export type MainButtonProps = ButtonProps & {
10 | label: string;
11 | };
12 |
13 | const MainButton = ({ label, ...rest }: MainButtonProps) => {
14 | const classes = useStyles();
15 |
16 | return (
17 |
25 | );
26 | };
27 |
28 | export default MainButton;
29 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/components/MainTextField.tsx:
--------------------------------------------------------------------------------
1 | import { makeStyles, TextField, TextFieldProps } from "@material-ui/core";
2 | import { memo } from "react";
3 |
4 | const useStyles = makeStyles({
5 | input: {
6 | margin: "16px 0",
7 | },
8 | });
9 |
10 | export type MainTextFieldProps = TextFieldProps & {
11 | label: string;
12 | };
13 |
14 | const MainTextField = memo(({ label, ...rest }: MainTextFieldProps) => {
15 | const classes = useStyles();
16 |
17 | return (
18 |
24 | );
25 | });
26 |
27 | export default MainTextField;
28 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/components/PrivateRoute.tsx:
--------------------------------------------------------------------------------
1 | import { Redirect, Route, RouteProps } from "react-router";
2 |
3 | export type PrivateRouteProps = RouteProps & {
4 | isLoggedIn: boolean;
5 | redirect: string;
6 | };
7 |
8 | const PrivateRoute = ({ isLoggedIn, redirect, ...rest }: PrivateRouteProps) => {
9 | return isLoggedIn ? : ;
10 | };
11 |
12 | export default PrivateRoute;
13 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/constants/constants.ts:
--------------------------------------------------------------------------------
1 | export const SERVER_URL = "http://localhost:5000";
2 | export const TOKEN_PREFIX = "Bearer";
3 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/hooks/__test__/useInput.test.tsx:
--------------------------------------------------------------------------------
1 | import { renderHook, act } from "@testing-library/react-hooks";
2 | import { ChangeEvent } from "react";
3 | import useInput from "../useInput";
4 | import faker from "faker";
5 |
6 | describe("useInput hook", () => {
7 | it("should change value when use onChange function", async () => {
8 | // given
9 | const { result } = renderHook(() => useInput());
10 | const input = faker.internet.userName();
11 |
12 | // when
13 | act(() => {
14 | const event = {
15 | target: {
16 | value: input,
17 | },
18 | } as ChangeEvent;
19 |
20 | result.current.onChange(event);
21 | });
22 |
23 | //then
24 | expect(result.current.value).toEqual(input);
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/hooks/useCheckUserEffect.ts:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 | import { useHistory } from "react-router-dom";
3 |
4 | const useCheckUserEffect = ({
5 | isLoggedIn,
6 | successPagePath,
7 | failurePagePath,
8 | }: {
9 | isLoggedIn: boolean;
10 | successPagePath: string;
11 | failurePagePath: string;
12 | }) => {
13 | const history = useHistory();
14 |
15 | useEffect(() => {
16 | if (isLoggedIn) {
17 | history.push(successPagePath);
18 | return;
19 | }
20 |
21 | history.push(failurePagePath);
22 | }, [isLoggedIn, successPagePath, failurePagePath, history]);
23 | };
24 |
25 | export default useCheckUserEffect;
26 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/hooks/useInput.ts:
--------------------------------------------------------------------------------
1 | import { ChangeEvent, useState } from "react";
2 |
3 | const useInput = () => {
4 | const [value, setValue] = useState("");
5 |
6 | const onChange = (e: ChangeEvent) => {
7 | const { value } = e.target;
8 | setValue(value);
9 | };
10 |
11 | return { value, onChange };
12 | };
13 |
14 | export default useInput;
15 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/hooks/useLogin.ts:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import { useHistory } from "react-router-dom";
3 | import authApi from "../api/authApi";
4 | import LoginData from "../models/LoginData";
5 | import tokenStorage from "../utils/tokenStorage";
6 |
7 | const useLogin = () => {
8 | const history = useHistory();
9 | const [errMsg, setErrMsg] = useState("");
10 | const [isLoading, setIsLoading] = useState(false);
11 |
12 | const login = async (loginData: LoginData) => {
13 | try {
14 | setIsLoading(true);
15 | setErrMsg("");
16 |
17 | const accessToken = await authApi.login(loginData);
18 |
19 | setIsLoading(false);
20 |
21 | tokenStorage.setToken(accessToken);
22 | history.push("/user/profile");
23 | } catch (e) {
24 | setErrMsg(e);
25 | setIsLoading(false);
26 | }
27 | };
28 |
29 | return { errMsg, isLoading, login };
30 | };
31 |
32 | export default useLogin;
33 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/hooks/useUserProfileQuery.ts:
--------------------------------------------------------------------------------
1 | import { AxiosError } from "axios";
2 | import { useQuery, UseQueryOptions } from "react-query";
3 | import userApi from "../api/userApi";
4 | import User from "../models/User";
5 |
6 | const useUserProfileQuery = (
7 | options: UseQueryOptions = {}
8 | ) => {
9 | return useQuery("myProfile", userApi.getUserProfile, { ...options });
10 | };
11 |
12 | export default useUserProfileQuery;
13 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 | import App from "./App";
4 | import reportWebVitals from "./reportWebVitals";
5 | import CssBaseline from "@material-ui/core/CssBaseline";
6 | import { ThemeProvider } from "@material-ui/styles";
7 | import { globalTheme } from "./styles/globalTheme";
8 | import { QueryClientProvider, QueryClient } from "react-query";
9 | import { BrowserRouter as Router } from "react-router-dom";
10 |
11 | const queryClient = new QueryClient();
12 |
13 | ReactDOM.render(
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | ,
22 | document.getElementById("root")
23 | );
24 |
25 | // If you want to start measuring performance in your app, pass a function
26 | // to log results (for example: reportWebVitals(console.log))
27 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
28 | reportWebVitals();
29 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/models/LoginData.ts:
--------------------------------------------------------------------------------
1 | class LoginData {
2 | constructor(account: string, password: string) {
3 | this._account = account;
4 | this._password = password;
5 | }
6 |
7 | private _account: string;
8 | private _password: string;
9 |
10 | toJson = () => {
11 | return { account: this._account, password: this._password };
12 | };
13 | }
14 |
15 | export default LoginData;
16 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/models/User.ts:
--------------------------------------------------------------------------------
1 | class User {
2 | constructor({
3 | id,
4 | account,
5 | name,
6 | level,
7 | }: {
8 | id: number;
9 | account: string;
10 | name: string;
11 | level: number;
12 | }) {
13 | this._id = id;
14 | this._account = account;
15 | this._name = name;
16 | this._level = level;
17 | }
18 |
19 | private _id: number;
20 | private _account: string;
21 | private _name: string;
22 | private _level: number;
23 |
24 | getId = () => this._id;
25 | getAccount = () => this._account;
26 | getName = () => this._name;
27 | getLevel = () => this._level;
28 | }
29 |
30 | export default User;
31 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/pages/LoginPage.tsx:
--------------------------------------------------------------------------------
1 | import { makeStyles, Box } from "@material-ui/core";
2 | import LoginForm from "../components/LoginForm";
3 |
4 | const useStyles = makeStyles({
5 | box: {
6 | width: "100%",
7 | height: "100%",
8 | display: "flex",
9 | flexDirection: "column",
10 | justifyContent: "center",
11 | alignItems: "center",
12 | },
13 | inner: {
14 | width: "50%",
15 | height: "50%",
16 | border: "black 1px solid",
17 | display: "flex",
18 | flexDirection: "column",
19 | justifyContent: "center",
20 | alignItems: "center",
21 | },
22 | });
23 |
24 | const LoginPage = () => {
25 | const classes = useStyles();
26 |
27 | return (
28 |
29 |
30 |
31 | );
32 | };
33 |
34 | export default LoginPage;
35 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/pages/NotFoundPage.tsx:
--------------------------------------------------------------------------------
1 | import { Box } from "@material-ui/core";
2 |
3 | export type NotFoundPageProps = {};
4 |
5 | const NotFoundPage = () => {
6 | return Not Found!;
7 | };
8 |
9 | export default NotFoundPage;
10 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/pages/UserProfilePage.tsx:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/core/styles";
2 | import UserProfile from "../components/UserProfile";
3 | import { Box, CircularProgress } from "@material-ui/core";
4 | import useUserProfileQuery from "../hooks/useUserProfileQuery";
5 | import tokenStorage from "../utils/tokenStorage";
6 | import { useHistory } from "react-router-dom";
7 | import authApi from "../api/authApi";
8 |
9 | const useStyles = makeStyles({
10 | box: {
11 | width: "100%",
12 | height: "100%",
13 | display: "flex",
14 | justifyContent: "center",
15 | alignItems: "center",
16 | },
17 | });
18 |
19 | const UserProfilePage = () => {
20 | const classes = useStyles();
21 | const history = useHistory();
22 | const { data: user, isLoading, isSuccess } = useUserProfileQuery();
23 |
24 | const handleOnClickLogout = async () => {
25 | await authApi.logout();
26 | tokenStorage.clearToken();
27 | history.push("/");
28 | };
29 |
30 | return (
31 |
32 | {isLoading && }
33 | {isSuccess && user && (
34 |
35 | )}
36 |
37 | );
38 | };
39 |
40 | export default UserProfilePage;
41 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/reportWebVitals.ts:
--------------------------------------------------------------------------------
1 | import { ReportHandler } from 'web-vitals';
2 |
3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => {
4 | if (onPerfEntry && onPerfEntry instanceof Function) {
5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
6 | getCLS(onPerfEntry);
7 | getFID(onPerfEntry);
8 | getFCP(onPerfEntry);
9 | getLCP(onPerfEntry);
10 | getTTFB(onPerfEntry);
11 | });
12 | }
13 | };
14 |
15 | export default reportWebVitals;
16 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom';
6 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/styles/globalTheme.ts:
--------------------------------------------------------------------------------
1 | import { createTheme } from "@material-ui/core";
2 |
3 | export const globalTheme = createTheme({
4 | overrides: {
5 | MuiCssBaseline: {
6 | "@global": {
7 | "html, body, div#root": {
8 | width: "100%",
9 | height: "100%",
10 | },
11 | },
12 | },
13 | },
14 | });
15 |
--------------------------------------------------------------------------------
/results/kimbiyam/src/utils/tokenStorage.ts:
--------------------------------------------------------------------------------
1 | const ACCESS_TOKEN = "ACCESS_TOKEN";
2 |
3 | const getToken = () => {
4 | return localStorage.getItem(ACCESS_TOKEN);
5 | };
6 |
7 | const setToken = (accessToken: string) => {
8 | localStorage.setItem(ACCESS_TOKEN, accessToken);
9 | };
10 |
11 | const clearToken = () => {
12 | localStorage.removeItem(ACCESS_TOKEN);
13 | };
14 |
15 | const tokenStorage = {
16 | getToken,
17 | setToken,
18 | clearToken,
19 | };
20 |
21 | export default tokenStorage;
22 |
--------------------------------------------------------------------------------
/results/kimbiyam/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 | "allowJs": true,
10 | "skipLibCheck": true,
11 | "esModuleInterop": true,
12 | "allowSyntheticDefaultImports": true,
13 | "strict": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "noFallthroughCasesInSwitch": true,
16 | "module": "esnext",
17 | "moduleResolution": "node",
18 | "resolveJsonModule": true,
19 | "isolatedModules": true,
20 | "noEmit": true,
21 | "jsx": "react-jsx"
22 | },
23 | "include": [
24 | "src"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/results/leehaeun0/.env.development:
--------------------------------------------------------------------------------
1 | REACT_APP_BASEURL=http://localhost:5000
--------------------------------------------------------------------------------
/results/leehaeun0/.env.production:
--------------------------------------------------------------------------------
1 | REACT_APP_BASEURL=http://localhost:5000
--------------------------------------------------------------------------------
/results/leehaeun0/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: '@typescript-eslint/parser',
3 | plugins: ['@typescript-eslint', 'simple-import-sort', 'prettier', 'react', 'react-hooks'],
4 | extends: [
5 | 'plugin:react/recommended',
6 | 'plugin:import/errors',
7 | 'plugin:import/warnings',
8 | 'plugin:@typescript-eslint/recommended',
9 | 'plugin:prettier/recommended',
10 | 'prettier',
11 | ],
12 | rules: {
13 | // eslint rules
14 | 'react/prop-types': 'off',
15 | 'react/jsx-filename-extension': 0,
16 | '@typescript-eslint/explicit-module-boundary-types': 'off',
17 | // simple-import-sort plugin
18 | 'simple-import-sort/imports': 'warn',
19 | // react-hooks plugin
20 | 'react-hooks/rules-of-hooks': 'error',
21 | 'react-hooks/exhaustive-deps': 'warn',
22 | },
23 | settings: {
24 | 'import/resolver': {
25 | typescript: {},
26 | node: {
27 | extensions: ['.js', '.jsx', '.ts', '.tsx'],
28 | },
29 | },
30 | },
31 | };
32 |
--------------------------------------------------------------------------------
/results/leehaeun0/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/results/leehaeun0/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "all",
3 | "tabWidth": 2,
4 | "useTabs": false,
5 | "semi": true,
6 | "singleQuote": true,
7 | "printWidth": 100
8 | }
--------------------------------------------------------------------------------
/results/leehaeun0/README.md:
--------------------------------------------------------------------------------
1 | # Pilot React App
2 |
3 | [Leehaeun0](https://github.com/Leehaeun0)'s pilot project based on React
4 |
5 | ## 구현
6 |
7 | 
8 |
9 | ## 요구사항
10 |
11 | - [x] git (github)
12 | - [x] webstorm
13 | - [x] React
14 | - [x] Typescript
15 | - [ ] Test Case 작성
16 | - [x] 자바스크립트 Object `{}` (type object 포함)의 사용을 하지말아보자!
17 | - [x] API 요청, 응답 데이터는 클래스를 이용
18 |
19 | ## local 실행
20 |
21 | ```bash
22 | $ yarn install
23 | $ yarn start
24 | ```
25 |
26 | ## 후기
27 |
28 | 리액트는 형식이 자유로운 게 양날의 검이라는 걸 다시 한번 느꼈습니다...ㅎㅎ 컴포넌트나 파일 구조 짜는 게 제일 고민인 것 같습니다.
29 | 테스트 코드는 정말 아쉽지만 혼자서 시간 내서 더 공부해봐야 할 것 같습니다ㅠ
30 | 프론트엔드로 재밌는 이벤트 열어주셔서 감사합니다!! 덕분에 다른 분들 코드도 보면서 공부 많이 되었습니다.
31 |
--------------------------------------------------------------------------------
/results/leehaeun0/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/leehaeun0/public/favicon.ico
--------------------------------------------------------------------------------
/results/leehaeun0/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/leehaeun0/public/logo192.png
--------------------------------------------------------------------------------
/results/leehaeun0/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/leehaeun0/public/logo512.png
--------------------------------------------------------------------------------
/results/leehaeun0/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/results/leehaeun0/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/results/leehaeun0/src/App.test.tsx:
--------------------------------------------------------------------------------
1 | import { render, screen } from '@testing-library/react';
2 | import React from 'react';
3 |
4 | import App from './App';
5 |
6 | test('renders learn react link', () => {
7 | render();
8 | const linkElement = screen.getByText(/learn react/i);
9 | expect(linkElement).toBeInTheDocument();
10 | });
11 |
--------------------------------------------------------------------------------
/results/leehaeun0/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { SnackbarProvider } from 'notistack';
2 | import React, { Suspense } from 'react';
3 | import { HelmetProvider } from 'react-helmet-async';
4 | import { BrowserRouter } from 'react-router-dom';
5 | import { ThemeProvider } from 'styled-components';
6 |
7 | import LoadingPage from './pages/LoadingPage';
8 | import MainRouter from './routes/MainRouter';
9 | import GlobalStyle from './styles/GlobalStyle';
10 | import theme from './styles/theme';
11 |
12 | function App() {
13 | return (
14 |
15 |
16 |
17 |
18 |
24 |
25 | }>
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | );
34 | }
35 |
36 | export default App;
37 |
--------------------------------------------------------------------------------
/results/leehaeun0/src/apis/api.ts:
--------------------------------------------------------------------------------
1 | import axios, { AxiosInstance } from 'axios';
2 |
3 | import { AsyncFc } from '../hooks/useAsync';
4 | import Auth from '../utils/auth';
5 |
6 | export type AuthResponse = {
7 | accessToken: string;
8 | };
9 |
10 | export type User = {
11 | id: number;
12 | account: string;
13 | name: string;
14 | level: number;
15 | };
16 |
17 | class Api {
18 | private readonly apiClient: AxiosInstance;
19 |
20 | constructor() {
21 | this.apiClient = axios.create({
22 | baseURL: process.env.REACT_APP_BASEURL,
23 | timeout: 1000,
24 | });
25 | }
26 |
27 | public login: AsyncFc = async (config, payload) => {
28 | const response = await this.apiClient.post('/auth/login', payload, config);
29 |
30 | Auth.set(response.data.accessToken);
31 | return response.data;
32 | };
33 |
34 | public logout: AsyncFc = async (config) => {
35 | const response = await this.apiClient.get('/auth/logout', config);
36 |
37 | Auth.remove();
38 | return response.data;
39 | };
40 |
41 | public getUser: AsyncFc = async (config): Promise => {
42 | const response = await this.apiClient.get('/v1/users/me', config);
43 |
44 | return response.data;
45 | };
46 | }
47 |
48 | export default new Api();
49 |
--------------------------------------------------------------------------------
/results/leehaeun0/src/components/Button.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styled from 'styled-components';
3 |
4 | interface ButtonProps extends React.ButtonHTMLAttributes {
5 | children: React.ReactChild;
6 | icon?: React.ReactNode | null;
7 | }
8 |
9 | function Button({ children, icon, ...rest }: ButtonProps) {
10 | return (
11 |
12 | {children}
13 | {icon}
14 |
15 | );
16 | }
17 |
18 | const StyledButton = styled.button`
19 | display: flex;
20 | align-items: center;
21 | justify-content: center;
22 | width: 100%;
23 | padding: 14px;
24 | color: white;
25 | border: none;
26 | border-radius: 3px;
27 | background-color: ${({ theme }) => theme.color.main};
28 |
29 | div.MuiCircularProgress-root {
30 | margin-left: 8px;
31 | svg circle {
32 | color: white;
33 | }
34 | }
35 | `;
36 |
37 | export default Button;
38 |
--------------------------------------------------------------------------------
/results/leehaeun0/src/components/CenterBox.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styled from 'styled-components';
3 |
4 | type CenterBoxProps = {
5 | children: React.ReactNode;
6 | };
7 |
8 | function CenterBox({ children }: CenterBoxProps) {
9 | return (
10 |
11 | {children}
12 |
13 | );
14 | }
15 |
16 | const StyledWrapper = styled.div`
17 | position: fixed;
18 | top: 50%;
19 | left: 50%;
20 | transform: translate(-50%, -50%);
21 | display: flex;
22 | justify-content: center;
23 | width: 460px;
24 | max-width: 90%;
25 | padding: 50px 0;
26 | border-radius: 12px;
27 | background-color: ${({ theme }) => theme.color.white};
28 | box-shadow: ${({ theme }) => theme.boxShadow};
29 |
30 | & > div {
31 | width: 73%;
32 | text-align: center;
33 | }
34 | `;
35 |
36 | export default CenterBox;
37 |
--------------------------------------------------------------------------------
/results/leehaeun0/src/components/FormInput.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styled from 'styled-components';
3 |
4 | interface FormInputProps extends React.InputHTMLAttributes {
5 | id: string;
6 | label: string;
7 | }
8 |
9 | function FormInput({ id, label, ...rest }: FormInputProps) {
10 | return (
11 | <>
12 |
15 |
16 | >
17 | );
18 | }
19 |
20 | const StyledInput = styled.input`
21 | display: block;
22 | min-width: 100%;
23 | max-width: 100%;
24 | width: 300px;
25 | padding: 11px 46px 11px 16px;
26 | font-size: 16px;
27 | border: 1px solid transparent;
28 | border-radius: 3px;
29 | background-color: ${({ theme }) => theme.color.lightGray};
30 | outline: 0;
31 | transition: all 0.3s;
32 |
33 | &::placeholder {
34 | color: ${({ theme }) => theme.color.gray};
35 | }
36 | &:focus {
37 | border-color: ${({ theme }) => theme.color.main};
38 | }
39 | `;
40 |
41 | export default FormInput;
42 |
--------------------------------------------------------------------------------
/results/leehaeun0/src/components/Main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styled from 'styled-components';
3 |
4 | type MainProps = {
5 | children: React.ReactNode;
6 | };
7 |
8 | function Main({ children }: MainProps) {
9 | return {children};
10 | }
11 |
12 | const StyledMain = styled.main`
13 | min-height: 100vh;
14 | background-color: ${({ theme }) => theme.color.lightGray};
15 | `;
16 |
17 | export default Main;
18 |
--------------------------------------------------------------------------------
/results/leehaeun0/src/components/ReactHelmet.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Helmet } from 'react-helmet-async';
3 |
4 | type ReactHelmetProps = {
5 | title: string;
6 | description: string;
7 | };
8 |
9 | function ReactHelmet({ title, description }: ReactHelmetProps) {
10 | return (
11 |
12 | {title}
13 |
14 |
15 | );
16 | }
17 |
18 | export default ReactHelmet;
19 |
--------------------------------------------------------------------------------
/results/leehaeun0/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 |
4 | import App from './App';
5 | import reportWebVitals from './reportWebVitals';
6 |
7 | ReactDOM.render(
8 |
9 |
10 | ,
11 | document.getElementById('root'),
12 | );
13 |
14 | // If you want to start measuring performance in your app, pass a function
15 | // to log results (for example: reportWebVitals(console.log))
16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
17 | reportWebVitals();
18 |
--------------------------------------------------------------------------------
/results/leehaeun0/src/pages/LoadingPage.tsx:
--------------------------------------------------------------------------------
1 | import CircularProgress from '@material-ui/core/CircularProgress';
2 | import React from 'react';
3 | import styled from 'styled-components';
4 |
5 | import Main from '../components/Main';
6 |
7 | const LoadingPage: React.FC = () => {
8 | return (
9 |
10 |
11 |
12 |
13 |
14 | );
15 | };
16 |
17 | const StyledWrapper = styled.div`
18 | position: fixed;
19 | top: 50%;
20 | left: 50%;
21 | transform: translate(-50%, -50%);
22 | z-index: 100;
23 | svg circle {
24 | color: ${({ theme }) => theme.color.main};
25 | }
26 | `;
27 |
28 | export default LoadingPage;
29 |
--------------------------------------------------------------------------------
/results/leehaeun0/src/pages/LoginPage.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import LoginForm from '../components/LoginForm';
4 | import ReactHelmet from '../components/ReactHelmet';
5 |
6 | function LoginPage() {
7 | return (
8 | <>
9 |
10 |
11 | >
12 | );
13 | }
14 |
15 | export default LoginPage;
16 |
--------------------------------------------------------------------------------
/results/leehaeun0/src/pages/UserPage.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import ReactHelmet from '../components/ReactHelmet';
4 | import UserInfo from '../components/UserInfo';
5 |
6 | function UserPage() {
7 | return (
8 | <>
9 |
10 |
11 | >
12 | );
13 | }
14 |
15 | export default UserPage;
16 |
--------------------------------------------------------------------------------
/results/leehaeun0/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/results/leehaeun0/src/reportWebVitals.ts:
--------------------------------------------------------------------------------
1 | import { ReportHandler } from 'web-vitals';
2 |
3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => {
4 | if (onPerfEntry && onPerfEntry instanceof Function) {
5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
6 | getCLS(onPerfEntry);
7 | getFID(onPerfEntry);
8 | getFCP(onPerfEntry);
9 | getLCP(onPerfEntry);
10 | getTTFB(onPerfEntry);
11 | });
12 | }
13 | };
14 |
15 | export default reportWebVitals;
16 |
--------------------------------------------------------------------------------
/results/leehaeun0/src/routes/MainRouter.tsx:
--------------------------------------------------------------------------------
1 | import { lazy } from '@loadable/component';
2 | import React from 'react';
3 | import { Redirect, Switch } from 'react-router-dom';
4 |
5 | import Auth from '../utils/auth';
6 | import PrivateRoute from './PrivateRoute';
7 | import PublicRoute from './PublicRoute';
8 |
9 | const LoginPage = lazy(() => import('../pages/LoginPage'));
10 | const UserPage = lazy(() => import('../pages/UserPage'));
11 |
12 | function MainRouter() {
13 | const accessToken = Auth.get();
14 |
15 | return (
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | {accessToken ? : }
24 |
25 | );
26 | }
27 |
28 | export default MainRouter;
29 |
--------------------------------------------------------------------------------
/results/leehaeun0/src/routes/PrivateRoute.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Redirect, Route, RouteProps } from 'react-router-dom';
3 |
4 | import Auth from '../utils/auth';
5 |
6 | interface PrivateRouteProps extends RouteProps {
7 | children: React.ReactChild;
8 | path: string;
9 | redirect: string;
10 | }
11 |
12 | function PrivateRoute({ children, path, redirect, ...rest }: PrivateRouteProps) {
13 | const accessToken = Auth.get();
14 |
15 | return (
16 |
17 | {accessToken ? children : }
18 |
19 | );
20 | }
21 |
22 | export default PrivateRoute;
23 |
--------------------------------------------------------------------------------
/results/leehaeun0/src/routes/PublicRoute.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Redirect, Route, RouteProps } from 'react-router-dom';
3 |
4 | import Auth from '../utils/auth';
5 |
6 | interface PublicRouteProps extends RouteProps {
7 | children: React.ReactChild;
8 | path: string;
9 | redirect: string;
10 | }
11 |
12 | function PublicRoute({ children, path, redirect, ...rest }: PublicRouteProps) {
13 | const accessToken = Auth.get();
14 |
15 | return (
16 |
17 | {!accessToken ? children : }
18 |
19 | );
20 | }
21 |
22 | export default PublicRoute;
23 |
--------------------------------------------------------------------------------
/results/leehaeun0/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom';
6 |
--------------------------------------------------------------------------------
/results/leehaeun0/src/styles/GlobalStyle.ts:
--------------------------------------------------------------------------------
1 | import { createGlobalStyle } from 'styled-components';
2 | import reset from 'styled-reset';
3 |
4 | import theme from './theme';
5 |
6 | const GlobalStyle = createGlobalStyle`
7 | ${reset}
8 |
9 | * {
10 | box-sizing: border-box;
11 | color: ${theme.color.black};
12 | font-size: 16px;
13 | font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Ubuntu,Arial,sans-serif;
14 | }
15 |
16 | .a11yHidden {
17 | position: absolute;
18 | width: 1px;
19 | height: 1px;
20 | overflow: hidden;
21 | margin: -1px;
22 | clip: rect(0, 0, 0, 0);
23 | }
24 | `;
25 |
26 | export default GlobalStyle;
27 |
--------------------------------------------------------------------------------
/results/leehaeun0/src/styles/theme.ts:
--------------------------------------------------------------------------------
1 | const theme = {
2 | color: {
3 | white: '#FFFFFF',
4 | lightGray: '#F7F7F7',
5 | gray: '#B0B0B0',
6 | main: '#396afc',
7 | error: '#FF1616',
8 | black: '#222222',
9 | },
10 | boxShadow: 'rgb(100 100 111 / 15%) 7px 23px 62px',
11 | };
12 |
13 | export default theme;
14 |
--------------------------------------------------------------------------------
/results/leehaeun0/src/utils/auth.ts:
--------------------------------------------------------------------------------
1 | class Auth {
2 | private readonly storageKey: string;
3 |
4 | constructor() {
5 | this.storageKey = 'AUTH_KEY';
6 | }
7 |
8 | public get = () => sessionStorage.getItem(this.storageKey);
9 |
10 | public set = (token: string) => sessionStorage.setItem(this.storageKey, token);
11 |
12 | public remove = () => sessionStorage.removeItem(this.storageKey);
13 | }
14 |
15 | export default new Auth();
16 |
--------------------------------------------------------------------------------
/results/leehaeun0/src/utils/img/profile-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/leehaeun0/src/utils/img/profile-image.png
--------------------------------------------------------------------------------
/results/leehaeun0/src/utils/img/result.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/leehaeun0/src/utils/img/result.gif
--------------------------------------------------------------------------------
/results/leehaeun0/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 | "allowJs": true,
10 | "skipLibCheck": true,
11 | "esModuleInterop": true,
12 | "allowSyntheticDefaultImports": true,
13 | "strict": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "noFallthroughCasesInSwitch": true,
16 | "module": "esnext",
17 | "moduleResolution": "node",
18 | "resolveJsonModule": true,
19 | "isolatedModules": true,
20 | "noEmit": true,
21 | "jsx": "react-jsx",
22 | "baseUrl": "./src"
23 | },
24 | "include": [
25 | "src"
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/results/rolancia/.env.development:
--------------------------------------------------------------------------------
1 | REACT_APP_API_END_POINT = http://localhost:5000
--------------------------------------------------------------------------------
/results/rolancia/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/results/rolancia/README.md:
--------------------------------------------------------------------------------
1 | # Pilot Project
2 |
3 | ## 요구 사항
4 |
5 | - [x] git (github)
6 | - [ ] webstorm // vscode 사용...
7 | - [x] React
8 | - [x] Typescript
9 | - [ ] Test Case 작성 // 미숙
10 | - [x] 자바스크립트 Object {} (type object 포함)의 사용을 하지말아보자!
11 | - [x] API 요청, 응답 데이터는 클래스를 이용
12 |
13 | ## 후기
14 |
15 | 개인적으로 프로젝트 초기 세팅과 테스트 관련해서 부족함을 많이 느꼈습니다... 주니어 개발자를 위해서 이런 이벤트를 기획해주셔서 감사합니다.
16 |
--------------------------------------------------------------------------------
/results/rolancia/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rolancia",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.11.4",
7 | "@testing-library/react": "^11.1.0",
8 | "@testing-library/user-event": "^12.1.10",
9 | "@types/jest": "^26.0.15",
10 | "@types/node": "^12.0.0",
11 | "@types/react": "^17.0.0",
12 | "@types/react-dom": "^17.0.0",
13 | "@types/react-router-dom": "^5.1.8",
14 | "axios": "^0.21.1",
15 | "react": "^17.0.2",
16 | "react-dom": "^17.0.2",
17 | "react-scripts": "4.0.3",
18 | "typescript": "^4.1.2",
19 | "web-vitals": "^1.0.1"
20 | },
21 | "scripts": {
22 | "start": "react-scripts start",
23 | "build": "react-scripts build",
24 | "test": "react-scripts test",
25 | "eject": "react-scripts eject"
26 | },
27 | "eslintConfig": {
28 | "extends": [
29 | "react-app",
30 | "react-app/jest"
31 | ]
32 | },
33 | "browserslist": {
34 | "production": [
35 | ">0.2%",
36 | "not dead",
37 | "not op_mini all"
38 | ],
39 | "development": [
40 | "last 1 chrome version",
41 | "last 1 firefox version",
42 | "last 1 safari version"
43 | ]
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/results/rolancia/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/rolancia/public/favicon.ico
--------------------------------------------------------------------------------
/results/rolancia/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/rolancia/public/logo192.png
--------------------------------------------------------------------------------
/results/rolancia/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leejaycoke/pilot-react/9098444a3f7b6c3438ed1d8749375ef1278222d0/results/rolancia/public/logo512.png
--------------------------------------------------------------------------------
/results/rolancia/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/results/rolancia/src/App.module.css:
--------------------------------------------------------------------------------
1 | .container {
2 | display: flex;
3 | flex-direction: column;
4 | align-items: center;
5 | justify-content: center;
6 | height: 100vh;
7 | }
8 |
--------------------------------------------------------------------------------
/results/rolancia/src/App.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render, screen } from '@testing-library/react';
3 | import App from './App';
4 |
5 | test('renders learn react link', () => {
6 | render();
7 | const linkElement = screen.getByText(/learn react/i);
8 | expect(linkElement).toBeInTheDocument();
9 | });
10 |
--------------------------------------------------------------------------------
/results/rolancia/src/App.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import styles from "./App.module.css";
3 | import { BrowserRouter, Switch, Route } from "react-router-dom";
4 | import Login from "./components/Login/Login";
5 | import UserInfo from "./components/UserInfo/UserInfo";
6 | import { HttpClientProps } from "./model/interfaces";
7 |
8 | const App: React.FC = ({ httpClient }: HttpClientProps) => {
9 | return (
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | );
25 | };
26 |
27 | export default App;
28 |
--------------------------------------------------------------------------------
/results/rolancia/src/components/Login/Login.module.css:
--------------------------------------------------------------------------------
1 | .form {
2 | display: flex;
3 | flex-direction: column;
4 | width: 25em;
5 | }
6 |
7 | .form__row {
8 | display: flex;
9 | width: 100%;
10 | }
11 |
12 | .form__row.two {
13 | display: flex;
14 | justify-content: space-between;
15 | align-items: center;
16 | }
17 |
18 | .input__id,
19 | .input__pwd {
20 | font-size: 1rem;
21 | width: 100%;
22 | padding: 1em;
23 | margin: 0.5em;
24 | border-radius: 0.3em;
25 | outline: none;
26 | border: 0.5px solid #d7dbe6;
27 | }
28 |
29 | .input__id::placeholder,
30 | .input__pwd::placeholder {
31 | color: #c2c4cb;
32 | }
33 |
34 | .save__id {
35 | display: flex;
36 | align-items: center;
37 | }
38 |
39 | #save__id__check {
40 | zoom: 1.5;
41 | }
42 |
43 | .save__id__label {
44 | font-weight: bolder;
45 | }
46 |
47 | .menus {
48 | display: flex;
49 | list-style: none;
50 | padding-left: 0;
51 | }
52 |
53 | .menu {
54 | font-size: 0.8rem;
55 | font-weight: bold;
56 | color: #ab9e9f;
57 | margin: 0.2em;
58 | }
59 |
60 | .menu__btn {
61 | color: #ab9e9f;
62 | }
63 |
64 | .login__btn {
65 | width: 100%;
66 | background-color: #3d5cff;
67 | color: white;
68 | font-size: 1.2rem;
69 | font-weight: bold;
70 | padding: 0.5em 0.3em;
71 | margin: 0.3em;
72 | border-radius: 0.3em;
73 | }
74 |
--------------------------------------------------------------------------------
/results/rolancia/src/components/UserInfo/UserInfo.module.css:
--------------------------------------------------------------------------------
1 | .userInfo {
2 | display: flex;
3 | flex-direction: column;
4 | width: 25em;
5 | }
6 |
7 | .userInfo .form__row {
8 | display: flex;
9 | align-items: center;
10 | width: 100%;
11 | }
12 |
13 | .userInfo__label {
14 | flex: 20%;
15 | font-weight: bold;
16 | }
17 |
18 | .userInfo input {
19 | flex: 80%;
20 | }
21 |
22 | .input__id,
23 | .input__pwd {
24 | font-size: 1rem;
25 | width: 100%;
26 | padding: 1em;
27 | margin: 0.5em;
28 | border-radius: 0.3em;
29 | outline: none;
30 | border: 0.5px solid #d7dbe6;
31 | }
32 |
33 | .input__id::placeholder,
34 | .input__pwd::placeholder {
35 | color: #c2c4cb;
36 | }
37 |
38 | .logout__btn {
39 | width: 100%;
40 | background-color: #3d5cff;
41 | color: white;
42 | font-size: 1.2rem;
43 | font-weight: bold;
44 | padding: 0.5em 0.3em;
45 | margin: 0.3em;
46 | border-radius: 0.3em;
47 | }
48 |
--------------------------------------------------------------------------------
/results/rolancia/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu",
4 | "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
5 | -webkit-font-smoothing: antialiased;
6 | -moz-osx-font-smoothing: grayscale;
7 | box-sizing: border-box;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
12 | }
13 |
14 | button {
15 | outline: none;
16 | border: none;
17 | background-color: transparent;
18 | cursor: pointer;
19 | }
20 |
--------------------------------------------------------------------------------
/results/rolancia/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import HttpClient from './service/httpClient';
6 |
7 | const httpClient = new HttpClient();
8 |
9 | ReactDOM.render(
10 |
11 |
12 | ,
13 | document.getElementById('root')
14 | );
15 |
--------------------------------------------------------------------------------
/results/rolancia/src/model/entity.ts:
--------------------------------------------------------------------------------
1 | export class LoginEntity {
2 | constructor(private readonly account: string, private readonly password: string) {}
3 | }
4 |
5 | export class UserEntity {
6 | constructor(
7 | public readonly id: string,
8 | public readonly account: string,
9 | public readonly name: string,
10 | public readonly level: string
11 | ) {}
12 | }
13 |
--------------------------------------------------------------------------------
/results/rolancia/src/model/interfaces.ts:
--------------------------------------------------------------------------------
1 | import HttpClient from "../service/httpClient";
2 |
3 | export interface HttpClientProps {
4 | httpClient: HttpClient;
5 | }
6 |
--------------------------------------------------------------------------------
/results/rolancia/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/results/rolancia/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom';
6 |
--------------------------------------------------------------------------------
/results/rolancia/src/test/httpClient.test.ts:
--------------------------------------------------------------------------------
1 | import { LoginEntity } from "../model/entity";
2 | import HttpClient from "../service/httpClient";
3 |
4 | // 테스트는... 잘 안되서 나중에 제대로 공부하려고 합니다... 흑흑... 삽질을 엄청했어요..
5 | describe("httpClient.ts", () => {
6 | it("login test", async () => {
7 | let httpClient = new HttpClient();
8 | const res = await httpClient.login(new LoginEntity("devbadak", "1234"));
9 | const accessToken = res.data.accessToken;
10 | expect(accessToken).toMatch("idonknow");
11 | });
12 |
13 | it("getUserinfo test", async () => {
14 | let httpClient = new HttpClient();
15 | const userInfo = await httpClient.getUserInfo();
16 | expect(userInfo).toMatch("maybe... devbadak's info?");
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/results/rolancia/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 | "allowJs": true,
10 | "skipLibCheck": true,
11 | "esModuleInterop": true,
12 | "allowSyntheticDefaultImports": true,
13 | "strict": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "noFallthroughCasesInSwitch": true,
16 | "module": "esnext",
17 | "moduleResolution": "node",
18 | "resolveJsonModule": true,
19 | "isolatedModules": true,
20 | "noEmit": true,
21 | "jsx": "react-jsx"
22 | },
23 | "include": [
24 | "src"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------