├── .gitignore
├── .prettierrc
├── 00-template
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── index.html
│ └── site.webmanifest
└── src
│ ├── App.css
│ ├── App.js
│ ├── index.css
│ └── index.js
├── 01-vannila-js
└── index.html
├── 02-react-hello-world
└── index.html
├── 03-react-vs-vannila-js
└── index.html
├── 04-jsx-hello-world
└── index.html
├── 05-react-jsx-green-button
├── index.html
└── script.js
├── 06-create-react-app
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
└── src
│ ├── App.css
│ ├── App.js
│ ├── App.test.js
│ ├── index.css
│ ├── index.js
│ ├── logo.svg
│ ├── reportWebVitals.js
│ └── setupTests.js
├── 07-create-react-app-eject
├── .gitignore
├── README.md
├── config
│ ├── env.js
│ ├── getHttpsConfig.js
│ ├── jest
│ │ ├── babelTransform.js
│ │ ├── cssTransform.js
│ │ └── fileTransform.js
│ ├── modules.js
│ ├── paths.js
│ ├── webpack.config.js
│ ├── webpack
│ │ └── persistentCache
│ │ │ └── createEnvironmentHash.js
│ └── webpackDevServer.config.js
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
├── scripts
│ ├── build.js
│ ├── start.js
│ └── test.js
└── src
│ ├── App.css
│ ├── App.js
│ ├── App.test.js
│ ├── index.css
│ ├── index.js
│ ├── logo.svg
│ ├── reportWebVitals.js
│ └── setupTests.js
├── 08-reusable-components
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── index.html
│ └── site.webmanifest
└── src
│ ├── App.css
│ ├── App.js
│ ├── components
│ ├── MyComponent.js
│ └── OtherComponent.js
│ ├── index.css
│ └── index.js
├── 09-props
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── index.html
│ └── site.webmanifest
└── src
│ ├── App.css
│ ├── App.js
│ ├── components
│ └── PetInfo.js
│ ├── index.css
│ └── index.js
├── 10-conditional-rendering
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── index.html
│ └── site.webmanifest
└── src
│ ├── App.css
│ ├── App.js
│ ├── components
│ └── PetInfo.js
│ ├── index.css
│ └── index.js
├── 11-state
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── index.html
│ └── site.webmanifest
└── src
│ ├── App.css
│ ├── App.js
│ ├── components
│ └── RandomNumber.js
│ ├── index.css
│ ├── index.js
│ └── utils
│ └── generateRandomNum.js
├── 12-state-via-props
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── index.html
│ └── site.webmanifest
└── src
│ ├── App.css
│ ├── App.js
│ ├── components
│ ├── Button.js
│ └── Counter.js
│ ├── index.css
│ └── index.js
├── 13-map
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── index.html
│ └── site.webmanifest
└── src
│ ├── App.css
│ ├── App.js
│ ├── components
│ ├── Button.js
│ └── Counter.js
│ ├── index.css
│ └── index.js
├── 14-map-array-of-objects
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── index.html
│ └── site.webmanifest
└── src
│ ├── App.css
│ ├── App.js
│ ├── components
│ ├── Person.js
│ └── Persons.js
│ ├── data
│ └── persons.js
│ ├── index.css
│ └── index.js
├── 15-logical-and-operator
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── index.html
│ └── site.webmanifest
└── src
│ ├── App.css
│ ├── App.js
│ ├── components
│ ├── Button.js
│ ├── Counter.js
│ └── ResetBtn.js
│ ├── index.css
│ └── index.js
├── 16-react-fragment
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── index.html
│ └── site.webmanifest
└── src
│ ├── App.css
│ ├── App.js
│ ├── components
│ └── Card.js
│ ├── index.css
│ └── index.js
├── 17-uncontrolled-input
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── index.html
│ └── site.webmanifest
└── src
│ ├── App.css
│ ├── App.js
│ ├── components
│ └── Login.js
│ ├── index.css
│ └── index.js
├── 18-controlled-input
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── index.html
│ └── site.webmanifest
└── src
│ ├── App.css
│ ├── App.js
│ ├── components
│ └── Login.js
│ ├── index.css
│ └── index.js
├── 19-children-prop
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── index.html
│ └── site.webmanifest
└── src
│ ├── App.css
│ ├── App.js
│ ├── components
│ └── Wrapper.js
│ ├── index.css
│ └── index.js
├── 20-useEffect
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── index.html
│ └── site.webmanifest
└── src
│ ├── App.css
│ ├── App.js
│ ├── components
│ ├── Post.js
│ └── Posts.js
│ ├── index.css
│ └── index.js
├── 21-jsonplaceholder-posts
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── index.html
│ └── site.webmanifest
└── src
│ ├── App.css
│ ├── App.js
│ ├── components
│ ├── Post.css
│ ├── Post.js
│ └── Posts.js
│ ├── index.css
│ └── index.js
├── 22-useEffect-async-await
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── index.html
│ └── site.webmanifest
└── src
│ ├── App.css
│ ├── App.js
│ ├── components
│ ├── Post.css
│ ├── Post.js
│ └── Posts.js
│ ├── index.css
│ └── index.js
├── 23-css-modules
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── index.html
│ └── site.webmanifest
└── src
│ ├── App.css
│ ├── App.js
│ ├── components
│ ├── Info.css
│ ├── Info.js
│ └── info.module.css
│ ├── index.css
│ └── index.js
├── 24-todo-app-v1
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── index.html
│ └── site.webmanifest
└── src
│ ├── App.css
│ ├── App.js
│ ├── components
│ ├── Todo
│ │ ├── Todo.js
│ │ └── Todo.module.css
│ ├── TodoForm
│ │ ├── TodoForm.js
│ │ └── TodoForm.module.css
│ ├── TodoList
│ │ ├── TodoList.js
│ │ └── TodoList.module.css
│ └── UI
│ │ ├── Button.js
│ │ └── Button.module.css
│ ├── index.css
│ └── index.js
├── 25-todo-app-v2
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── index.html
│ └── site.webmanifest
└── src
│ ├── App.css
│ ├── App.js
│ ├── components
│ ├── Todo
│ │ ├── Todo.js
│ │ └── Todo.module.css
│ ├── TodoForm
│ │ ├── TodoForm.js
│ │ └── TodoForm.module.css
│ ├── TodoList
│ │ ├── TodoList.js
│ │ └── TodoList.module.css
│ ├── TodosActions
│ │ ├── TodosActions.js
│ │ └── TodosActions.module.css
│ └── UI
│ │ ├── Button.js
│ │ └── Button.module.css
│ ├── index.css
│ └── index.js
├── 26-react-router
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── index.html
│ └── site.webmanifest
└── src
│ ├── App.css
│ ├── App.jsx
│ ├── components
│ ├── About.jsx
│ ├── Contacts.jsx
│ ├── Courses.jsx
│ ├── Home.jsx
│ ├── Menu.jsx
│ ├── NotFound.jsx
│ └── SingleCourse.jsx
│ ├── data
│ └── courses.js
│ ├── index.css
│ ├── index.js
│ └── layouts
│ └── MainLayout.jsx
├── 27-context-api
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── index.html
│ └── site.webmanifest
└── src
│ ├── App.css
│ ├── App.js
│ ├── components
│ ├── ChangeUser.jsx
│ ├── User.jsx
│ └── UserInfo.jsx
│ ├── context
│ └── UserContext.js
│ ├── index.css
│ └── index.js
├── 28-reducer
└── reducer.js
├── 29-pure-redux
├── index.html
├── index.js
├── redux
│ ├── reducer.js
│ └── store.js
└── utils
│ └── getCurrentTime.js
├── 30-react-redux
├── api
│ ├── .gitignore
│ ├── README.md
│ ├── data
│ │ └── books.json
│ ├── index.js
│ ├── package-lock.json
│ ├── package.json
│ └── vercel.json
└── frontend
│ ├── .gitignore
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
│ └── src
│ ├── App.css
│ ├── App.js
│ ├── components
│ ├── BookForm
│ │ ├── BookForm.css
│ │ └── BookForm.js
│ ├── BookList
│ │ ├── BookList.css
│ │ └── BookList.js
│ ├── Error
│ │ └── Error.js
│ └── Filter
│ │ ├── Filter.css
│ │ └── Filter.js
│ ├── data
│ └── books.json
│ ├── index.css
│ ├── index.js
│ ├── redux
│ ├── slices
│ │ ├── booksSlice.js
│ │ ├── errorSlice.js
│ │ └── filterSlice.js
│ └── store.js
│ └── utils
│ └── createBookWithID.js
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Mac desktop service store files
2 |
3 | .DS_Store
4 |
5 | # Logs
6 | logs
7 | *.log
8 | npm-debug.log*
9 | yarn-debug.log*
10 | yarn-error.log*
11 |
12 |
13 | # Compiled binary addons (http://nodejs.org/api/addons.html)
14 | build/Release
15 |
16 | # Dependency directories
17 | node_modules/
18 | jspm_packages/
19 |
20 | # Distribution directories
21 | dist/
22 |
23 | # Typescript v1 declaration files
24 | typings/
25 |
26 | # Optional npm cache directory
27 | .npm
28 |
29 | # Optional eslint cache
30 | .eslintcache
31 |
32 | # Optional REPL history
33 | .node_repl_history
34 |
35 | # Output of 'npm pack'
36 | *.tgz
37 |
38 | # Yarn Integrity file
39 | .yarn-integrity
40 |
41 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 80,
3 | "tabWidth": 2,
4 | "useTabs": false,
5 | "semi": true,
6 | "singleQuote": true,
7 | "trailingComma": "all",
8 | "bracketSpacing": true,
9 | "jsxBracketSameLine": false,
10 | "arrowParens": "avoid",
11 | "proseWrap": "always"
12 | }
13 |
--------------------------------------------------------------------------------
/00-template/.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 |
--------------------------------------------------------------------------------
/00-template/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "00-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.3.1",
10 | "react-dom": "^18.3.1",
11 | "react-scripts": "5.0.1",
12 | "web-vitals": "^2.1.4"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/00-template/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/00-template/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/00-template/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/00-template/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/00-template/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/00-template/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/00-template/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/00-template/public/favicon-16x16.png
--------------------------------------------------------------------------------
/00-template/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/00-template/public/favicon-32x32.png
--------------------------------------------------------------------------------
/00-template/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/00-template/public/favicon.ico
--------------------------------------------------------------------------------
/00-template/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 | React App
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/00-template/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/00-template/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | h1 {
6 | font-size: 90px;
7 | margin-top: 20px;
8 | }
9 |
10 | button {
11 | padding: 15px;
12 | font-size: 30px;
13 | border-radius: 5px;
14 | border: 0;
15 | margin: 20px;
16 | cursor: pointer;
17 | }
18 |
--------------------------------------------------------------------------------
/00-template/src/App.js:
--------------------------------------------------------------------------------
1 | import './App.css';
2 |
3 | function App() {
4 | return ;
5 | }
6 |
7 | export default App;
8 |
--------------------------------------------------------------------------------
/00-template/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-family: 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
8 | 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
9 |
10 | color: white;
11 | background-color: #112d49;
12 | }
13 |
--------------------------------------------------------------------------------
/00-template/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render();
8 |
--------------------------------------------------------------------------------
/01-vannila-js/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Vanilla JS
7 |
17 |
18 |
19 |
20 |
23 |
26 |
27 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/02-react-hello-world/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | React Hello World
7 |
8 |
9 |
10 |
14 |
18 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/03-react-vs-vannila-js/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | React Hello World
7 |
8 |
9 |
10 |
11 |
15 |
19 |
27 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/04-jsx-hello-world/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | JSX Hello World
7 |
8 |
9 |
10 |
14 |
18 |
19 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/05-react-jsx-green-button/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | React JSX Green Button
7 |
17 |
18 |
19 |
20 |
24 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/05-react-jsx-green-button/script.js:
--------------------------------------------------------------------------------
1 | const App = ({ initialButtonText, initialClassesList }) => {
2 | const [buttonText, setButtonText] = React.useState(initialButtonText);
3 | const [classesList, setClassesList] = React.useState(initialClassesList);
4 |
5 | const onButtonClick = () => {
6 | setButtonText('Hello from React');
7 | setClassesList('green-btn');
8 | };
9 |
10 | return (
11 |
12 |
15 |
16 | );
17 | };
18 |
19 | const container = document.getElementById('app');
20 | const root = ReactDOM.createRoot(container);
21 | root.render();
22 |
23 | // npx live-server --open=05-react-jsx-green-button
24 |
--------------------------------------------------------------------------------
/06-create-react-app/.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 |
--------------------------------------------------------------------------------
/06-create-react-app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "06-create-react-app",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.3.1",
10 | "react-dom": "^18.3.1",
11 | "react-scripts": "5.0.1",
12 | "web-vitals": "^2.1.4"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/06-create-react-app/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/06-create-react-app/public/favicon.ico
--------------------------------------------------------------------------------
/06-create-react-app/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/06-create-react-app/public/logo192.png
--------------------------------------------------------------------------------
/06-create-react-app/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/06-create-react-app/public/logo512.png
--------------------------------------------------------------------------------
/06-create-react-app/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 |
--------------------------------------------------------------------------------
/06-create-react-app/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/06-create-react-app/src/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 |
--------------------------------------------------------------------------------
/06-create-react-app/src/App.js:
--------------------------------------------------------------------------------
1 | import logo from './logo.svg';
2 | import './App.css';
3 |
4 | function App() {
5 | return (
6 |
22 | );
23 | }
24 |
25 | export default App;
26 |
--------------------------------------------------------------------------------
/06-create-react-app/src/App.test.js:
--------------------------------------------------------------------------------
1 | import { render, screen } from '@testing-library/react';
2 | import App from './App';
3 |
4 | test('renders learn react link', () => {
5 | render();
6 | const linkElement = screen.getByText(/learn react/i);
7 | expect(linkElement).toBeInTheDocument();
8 | });
9 |
--------------------------------------------------------------------------------
/06-create-react-app/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 |
--------------------------------------------------------------------------------
/06-create-react-app/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 | import reportWebVitals from './reportWebVitals';
6 |
7 | const root = ReactDOM.createRoot(document.getElementById('root'));
8 | root.render(
9 |
10 |
11 |
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 |
--------------------------------------------------------------------------------
/06-create-react-app/src/reportWebVitals.js:
--------------------------------------------------------------------------------
1 | const reportWebVitals = onPerfEntry => {
2 | if (onPerfEntry && onPerfEntry instanceof Function) {
3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
4 | getCLS(onPerfEntry);
5 | getFID(onPerfEntry);
6 | getFCP(onPerfEntry);
7 | getLCP(onPerfEntry);
8 | getTTFB(onPerfEntry);
9 | });
10 | }
11 | };
12 |
13 | export default reportWebVitals;
14 |
--------------------------------------------------------------------------------
/06-create-react-app/src/setupTests.js:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/07-create-react-app-eject/.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 |
--------------------------------------------------------------------------------
/07-create-react-app-eject/config/jest/babelTransform.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const babelJest = require('babel-jest').default;
4 |
5 | const hasJsxRuntime = (() => {
6 | if (process.env.DISABLE_NEW_JSX_TRANSFORM === 'true') {
7 | return false;
8 | }
9 |
10 | try {
11 | require.resolve('react/jsx-runtime');
12 | return true;
13 | } catch (e) {
14 | return false;
15 | }
16 | })();
17 |
18 | module.exports = babelJest.createTransformer({
19 | presets: [
20 | [
21 | require.resolve('babel-preset-react-app'),
22 | {
23 | runtime: hasJsxRuntime ? 'automatic' : 'classic',
24 | },
25 | ],
26 | ],
27 | babelrc: false,
28 | configFile: false,
29 | });
30 |
--------------------------------------------------------------------------------
/07-create-react-app-eject/config/jest/cssTransform.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // This is a custom Jest transformer turning style imports into empty objects.
4 | // http://facebook.github.io/jest/docs/en/webpack.html
5 |
6 | module.exports = {
7 | process() {
8 | return 'module.exports = {};';
9 | },
10 | getCacheKey() {
11 | // The output is always the same.
12 | return 'cssTransform';
13 | },
14 | };
15 |
--------------------------------------------------------------------------------
/07-create-react-app-eject/config/jest/fileTransform.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const path = require('path');
4 | const camelcase = require('camelcase');
5 |
6 | // This is a custom Jest transformer turning file imports into filenames.
7 | // http://facebook.github.io/jest/docs/en/webpack.html
8 |
9 | module.exports = {
10 | process(src, filename) {
11 | const assetFilename = JSON.stringify(path.basename(filename));
12 |
13 | if (filename.match(/\.svg$/)) {
14 | // Based on how SVGR generates a component name:
15 | // https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6
16 | const pascalCaseFilename = camelcase(path.parse(filename).name, {
17 | pascalCase: true,
18 | });
19 | const componentName = `Svg${pascalCaseFilename}`;
20 | return `const React = require('react');
21 | module.exports = {
22 | __esModule: true,
23 | default: ${assetFilename},
24 | ReactComponent: React.forwardRef(function ${componentName}(props, ref) {
25 | return {
26 | $$typeof: Symbol.for('react.element'),
27 | type: 'svg',
28 | ref: ref,
29 | key: null,
30 | props: Object.assign({}, props, {
31 | children: ${assetFilename}
32 | })
33 | };
34 | }),
35 | };`;
36 | }
37 |
38 | return `module.exports = ${assetFilename};`;
39 | },
40 | };
41 |
--------------------------------------------------------------------------------
/07-create-react-app-eject/config/webpack/persistentCache/createEnvironmentHash.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | const { createHash } = require('crypto');
3 |
4 | module.exports = env => {
5 | const hash = createHash('md5');
6 | hash.update(JSON.stringify(env));
7 |
8 | return hash.digest('hex');
9 | };
10 |
--------------------------------------------------------------------------------
/07-create-react-app-eject/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/07-create-react-app-eject/public/favicon.ico
--------------------------------------------------------------------------------
/07-create-react-app-eject/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/07-create-react-app-eject/public/logo192.png
--------------------------------------------------------------------------------
/07-create-react-app-eject/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/07-create-react-app-eject/public/logo512.png
--------------------------------------------------------------------------------
/07-create-react-app-eject/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 |
--------------------------------------------------------------------------------
/07-create-react-app-eject/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/07-create-react-app-eject/scripts/test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // Do this as the first thing so that any code reading it knows the right env.
4 | process.env.BABEL_ENV = 'test';
5 | process.env.NODE_ENV = 'test';
6 | process.env.PUBLIC_URL = '';
7 |
8 | // Makes the script crash on unhandled rejections instead of silently
9 | // ignoring them. In the future, promise rejections that are not handled will
10 | // terminate the Node.js process with a non-zero exit code.
11 | process.on('unhandledRejection', err => {
12 | throw err;
13 | });
14 |
15 | // Ensure environment variables are read.
16 | require('../config/env');
17 |
18 | const jest = require('jest');
19 | const execSync = require('child_process').execSync;
20 | let argv = process.argv.slice(2);
21 |
22 | function isInGitRepository() {
23 | try {
24 | execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' });
25 | return true;
26 | } catch (e) {
27 | return false;
28 | }
29 | }
30 |
31 | function isInMercurialRepository() {
32 | try {
33 | execSync('hg --cwd . root', { stdio: 'ignore' });
34 | return true;
35 | } catch (e) {
36 | return false;
37 | }
38 | }
39 |
40 | // Watch unless on CI or explicitly running all tests
41 | if (
42 | !process.env.CI &&
43 | argv.indexOf('--watchAll') === -1 &&
44 | argv.indexOf('--watchAll=false') === -1
45 | ) {
46 | // https://github.com/facebook/create-react-app/issues/5210
47 | const hasSourceControl = isInGitRepository() || isInMercurialRepository();
48 | argv.push(hasSourceControl ? '--watch' : '--watchAll');
49 | }
50 |
51 |
52 | jest.run(argv);
53 |
--------------------------------------------------------------------------------
/07-create-react-app-eject/src/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 |
--------------------------------------------------------------------------------
/07-create-react-app-eject/src/App.js:
--------------------------------------------------------------------------------
1 | import logo from './logo.svg';
2 | import './App.css';
3 |
4 | function App() {
5 | return (
6 |
22 | );
23 | }
24 |
25 | export default App;
26 |
--------------------------------------------------------------------------------
/07-create-react-app-eject/src/App.test.js:
--------------------------------------------------------------------------------
1 | import { render, screen } from '@testing-library/react';
2 | import App from './App';
3 |
4 | test('renders learn react link', () => {
5 | render();
6 | const linkElement = screen.getByText(/learn react/i);
7 | expect(linkElement).toBeInTheDocument();
8 | });
9 |
--------------------------------------------------------------------------------
/07-create-react-app-eject/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 |
--------------------------------------------------------------------------------
/07-create-react-app-eject/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 | import reportWebVitals from './reportWebVitals';
6 |
7 | const root = ReactDOM.createRoot(document.getElementById('root'));
8 | root.render(
9 |
10 |
11 |
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 |
--------------------------------------------------------------------------------
/07-create-react-app-eject/src/reportWebVitals.js:
--------------------------------------------------------------------------------
1 | const reportWebVitals = onPerfEntry => {
2 | if (onPerfEntry && onPerfEntry instanceof Function) {
3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
4 | getCLS(onPerfEntry);
5 | getFID(onPerfEntry);
6 | getFCP(onPerfEntry);
7 | getLCP(onPerfEntry);
8 | getTTFB(onPerfEntry);
9 | });
10 | }
11 | };
12 |
13 | export default reportWebVitals;
14 |
--------------------------------------------------------------------------------
/07-create-react-app-eject/src/setupTests.js:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/08-reusable-components/.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 |
--------------------------------------------------------------------------------
/08-reusable-components/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "00-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.3.1",
10 | "react-dom": "^18.3.1",
11 | "react-scripts": "5.0.1",
12 | "web-vitals": "^2.1.4"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/08-reusable-components/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/08-reusable-components/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/08-reusable-components/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/08-reusable-components/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/08-reusable-components/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/08-reusable-components/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/08-reusable-components/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/08-reusable-components/public/favicon-16x16.png
--------------------------------------------------------------------------------
/08-reusable-components/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/08-reusable-components/public/favicon-32x32.png
--------------------------------------------------------------------------------
/08-reusable-components/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/08-reusable-components/public/favicon.ico
--------------------------------------------------------------------------------
/08-reusable-components/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 | React App
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/08-reusable-components/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/08-reusable-components/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
--------------------------------------------------------------------------------
/08-reusable-components/src/App.js:
--------------------------------------------------------------------------------
1 | import './App.css';
2 | import MyComponent from './components/MyComponent';
3 | import OtherComponent from './components/OtherComponent';
4 |
5 | function App() {
6 | return (
7 |
8 |
9 |
10 |
11 | );
12 | }
13 |
14 | export default App;
15 |
--------------------------------------------------------------------------------
/08-reusable-components/src/components/MyComponent.js:
--------------------------------------------------------------------------------
1 | function MyComponent() {
2 | return (
3 |
4 |
Hello from the reusable component
5 |
6 |
7 | );
8 | }
9 |
10 | export default MyComponent;
11 |
--------------------------------------------------------------------------------
/08-reusable-components/src/components/OtherComponent.js:
--------------------------------------------------------------------------------
1 | function OtherComponent() {
2 | return (
3 |
6 | );
7 | }
8 |
9 | export default OtherComponent;
10 |
--------------------------------------------------------------------------------
/08-reusable-components/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-family: 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
8 | 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
9 | }
10 |
--------------------------------------------------------------------------------
/08-reusable-components/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render();
8 |
--------------------------------------------------------------------------------
/09-props/.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 |
--------------------------------------------------------------------------------
/09-props/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "00-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.3.1",
10 | "react-dom": "^18.3.1",
11 | "react-scripts": "5.0.1",
12 | "web-vitals": "^2.1.4"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/09-props/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/09-props/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/09-props/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/09-props/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/09-props/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/09-props/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/09-props/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/09-props/public/favicon-16x16.png
--------------------------------------------------------------------------------
/09-props/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/09-props/public/favicon-32x32.png
--------------------------------------------------------------------------------
/09-props/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/09-props/public/favicon.ico
--------------------------------------------------------------------------------
/09-props/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 | React App
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/09-props/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/09-props/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
--------------------------------------------------------------------------------
/09-props/src/App.js:
--------------------------------------------------------------------------------
1 | import './App.css';
2 | import PetInfo from './components/PetInfo';
3 |
4 | function App() {
5 | return (
6 |
10 | );
11 | }
12 |
13 | export default App;
14 |
--------------------------------------------------------------------------------
/09-props/src/components/PetInfo.js:
--------------------------------------------------------------------------------
1 | function PetInfo({ animal, age }) {
2 | // const { animal, age } = props;
3 | return (
4 |
5 | My {animal} is {age} years old
6 |
7 | );
8 | }
9 |
10 | export default PetInfo;
11 |
--------------------------------------------------------------------------------
/09-props/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-family: 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
8 | 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
9 | }
10 |
--------------------------------------------------------------------------------
/09-props/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render();
8 |
--------------------------------------------------------------------------------
/10-conditional-rendering/.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 |
--------------------------------------------------------------------------------
/10-conditional-rendering/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "00-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.3.1",
10 | "react-dom": "^18.3.1",
11 | "react-scripts": "5.0.1",
12 | "web-vitals": "^2.1.4"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/10-conditional-rendering/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/10-conditional-rendering/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/10-conditional-rendering/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/10-conditional-rendering/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/10-conditional-rendering/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/10-conditional-rendering/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/10-conditional-rendering/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/10-conditional-rendering/public/favicon-16x16.png
--------------------------------------------------------------------------------
/10-conditional-rendering/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/10-conditional-rendering/public/favicon-32x32.png
--------------------------------------------------------------------------------
/10-conditional-rendering/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/10-conditional-rendering/public/favicon.ico
--------------------------------------------------------------------------------
/10-conditional-rendering/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 | React App
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/10-conditional-rendering/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/10-conditional-rendering/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
--------------------------------------------------------------------------------
/10-conditional-rendering/src/App.js:
--------------------------------------------------------------------------------
1 | import './App.css';
2 | import PetInfo from './components/PetInfo';
3 |
4 | function App() {
5 | return (
6 |
10 | );
11 | }
12 |
13 | export default App;
14 |
--------------------------------------------------------------------------------
/10-conditional-rendering/src/components/PetInfo.js:
--------------------------------------------------------------------------------
1 | function PetInfo({ animal, age, hasPet }) {
2 | // const text = hasPet
3 | // ? `My ${animal} is ${age} years old`
4 | // : "I don't have an animal";
5 | // return {text}
;
6 |
7 | return hasPet ? (
8 | {`My ${animal} is ${age} years old`}
9 | ) : (
10 | I don't have an animal
11 | );
12 | }
13 |
14 | export default PetInfo;
15 |
--------------------------------------------------------------------------------
/10-conditional-rendering/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-family: 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
8 | 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
9 | }
10 |
--------------------------------------------------------------------------------
/10-conditional-rendering/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render();
8 |
--------------------------------------------------------------------------------
/11-state/.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 |
--------------------------------------------------------------------------------
/11-state/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "00-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.3.1",
10 | "react-dom": "^18.3.1",
11 | "react-scripts": "5.0.1",
12 | "web-vitals": "^2.1.4"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/11-state/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/11-state/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/11-state/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/11-state/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/11-state/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/11-state/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/11-state/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/11-state/public/favicon-16x16.png
--------------------------------------------------------------------------------
/11-state/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/11-state/public/favicon-32x32.png
--------------------------------------------------------------------------------
/11-state/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/11-state/public/favicon.ico
--------------------------------------------------------------------------------
/11-state/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 | React App
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/11-state/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/11-state/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | h1 {
6 | font-size: 90px;
7 | margin-top: 20px;
8 | }
9 |
10 | button {
11 | padding: 15px;
12 | font-size: 30px;
13 | border-radius: 5px;
14 | border: 0;
15 | margin: 20px;
16 | cursor: pointer;
17 | }
18 |
--------------------------------------------------------------------------------
/11-state/src/App.js:
--------------------------------------------------------------------------------
1 | import './App.css';
2 | import RandomNumber from './components/RandomNumber';
3 |
4 | function App() {
5 | return (
6 |
7 |
8 |
9 | );
10 | }
11 |
12 | export default App;
13 |
--------------------------------------------------------------------------------
/11-state/src/components/RandomNumber.js:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import generateRandomNum from '../utils/generateRandomNum';
3 |
4 | function RandomNumber({ maxNum }) {
5 | const [randomNum, setRandomNum] = useState(generateRandomNum(maxNum));
6 | const changeRandomNum = () => {
7 | setRandomNum(generateRandomNum(maxNum));
8 | };
9 | return (
10 |
11 |
{randomNum}
12 |
13 |
14 | );
15 | }
16 |
17 | export default RandomNumber;
18 |
--------------------------------------------------------------------------------
/11-state/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-family: 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
8 | 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
9 |
10 | color: white;
11 | background-color: #112d49;
12 | }
13 |
--------------------------------------------------------------------------------
/11-state/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render();
8 |
--------------------------------------------------------------------------------
/11-state/src/utils/generateRandomNum.js:
--------------------------------------------------------------------------------
1 | function generateRandomNum(maxNum) {
2 | return Math.floor(Math.random() * maxNum);
3 | }
4 |
5 | export default generateRandomNum;
6 |
--------------------------------------------------------------------------------
/12-state-via-props/.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 |
--------------------------------------------------------------------------------
/12-state-via-props/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "00-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.3.1",
10 | "react-dom": "^18.3.1",
11 | "react-scripts": "5.0.1",
12 | "web-vitals": "^2.1.4"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/12-state-via-props/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/12-state-via-props/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/12-state-via-props/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/12-state-via-props/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/12-state-via-props/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/12-state-via-props/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/12-state-via-props/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/12-state-via-props/public/favicon-16x16.png
--------------------------------------------------------------------------------
/12-state-via-props/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/12-state-via-props/public/favicon-32x32.png
--------------------------------------------------------------------------------
/12-state-via-props/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/12-state-via-props/public/favicon.ico
--------------------------------------------------------------------------------
/12-state-via-props/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 | React App
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/12-state-via-props/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/12-state-via-props/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | h1 {
6 | font-size: 90px;
7 | margin-top: 20px;
8 | }
9 |
10 | button {
11 | padding: 15px;
12 | font-size: 30px;
13 | border-radius: 5px;
14 | border: 0;
15 | margin: 20px;
16 | cursor: pointer;
17 | }
18 |
--------------------------------------------------------------------------------
/12-state-via-props/src/App.js:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import './App.css';
3 | import Counter from './components/Counter';
4 | import Button from './components/Button';
5 |
6 | function App() {
7 | const [count, setCount] = useState(0);
8 | const incrementCount = () => {
9 | setCount(count + 1);
10 | };
11 | return (
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | );
20 | }
21 |
22 | export default App;
23 |
--------------------------------------------------------------------------------
/12-state-via-props/src/components/Button.js:
--------------------------------------------------------------------------------
1 | function Button({ onClick }) {
2 | return ;
3 | }
4 |
5 | export default Button;
6 |
--------------------------------------------------------------------------------
/12-state-via-props/src/components/Counter.js:
--------------------------------------------------------------------------------
1 | function Counter({ count }) {
2 | return Total clicks: {count}
;
3 | }
4 |
5 | export default Counter;
6 |
--------------------------------------------------------------------------------
/12-state-via-props/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-family: 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
8 | 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
9 |
10 | color: white;
11 | background-color: #112d49;
12 | }
13 |
--------------------------------------------------------------------------------
/12-state-via-props/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render();
8 |
--------------------------------------------------------------------------------
/13-map/.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 |
--------------------------------------------------------------------------------
/13-map/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "00-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.3.1",
10 | "react-dom": "^18.3.1",
11 | "react-scripts": "5.0.1",
12 | "web-vitals": "^2.1.4"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/13-map/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/13-map/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/13-map/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/13-map/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/13-map/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/13-map/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/13-map/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/13-map/public/favicon-16x16.png
--------------------------------------------------------------------------------
/13-map/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/13-map/public/favicon-32x32.png
--------------------------------------------------------------------------------
/13-map/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/13-map/public/favicon.ico
--------------------------------------------------------------------------------
/13-map/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 | React App
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/13-map/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/13-map/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | h1 {
6 | font-size: 90px;
7 | margin-top: 20px;
8 | }
9 |
10 | button {
11 | padding: 15px;
12 | font-size: 30px;
13 | border-radius: 5px;
14 | border: 0;
15 | margin: 20px;
16 | cursor: pointer;
17 | }
18 |
--------------------------------------------------------------------------------
/13-map/src/App.js:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import './App.css';
3 | import Counter from './components/Counter';
4 | import Button from './components/Button';
5 |
6 | function App({ text }) {
7 | const [count, setCount] = useState(0);
8 | const incrementCount = () => {
9 | setCount(count + 1);
10 | };
11 |
12 | const texts = ['Click me!', 'Click me please!', 'Hit me!', 'Press me!'];
13 |
14 | return (
15 |
16 |
17 | {texts.map(text, index => {
18 | return ;
19 | })}
20 |
21 | );
22 | }
23 |
24 | export default App;
25 |
--------------------------------------------------------------------------------
/13-map/src/components/Button.js:
--------------------------------------------------------------------------------
1 | function Button({ onClick, text }) {
2 | return ;
3 | }
4 |
5 | export default Button;
6 |
--------------------------------------------------------------------------------
/13-map/src/components/Counter.js:
--------------------------------------------------------------------------------
1 | function Counter({ count }) {
2 | return Total clicks: {count}
;
3 | }
4 |
5 | export default Counter;
6 |
--------------------------------------------------------------------------------
/13-map/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-family: 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
8 | 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
9 |
10 | color: white;
11 | background-color: #112d49;
12 | }
13 |
--------------------------------------------------------------------------------
/13-map/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render();
8 |
--------------------------------------------------------------------------------
/14-map-array-of-objects/.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 |
--------------------------------------------------------------------------------
/14-map-array-of-objects/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "00-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.3.1",
10 | "react-dom": "^18.3.1",
11 | "react-scripts": "5.0.1",
12 | "web-vitals": "^2.1.4"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/14-map-array-of-objects/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/14-map-array-of-objects/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/14-map-array-of-objects/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/14-map-array-of-objects/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/14-map-array-of-objects/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/14-map-array-of-objects/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/14-map-array-of-objects/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/14-map-array-of-objects/public/favicon-16x16.png
--------------------------------------------------------------------------------
/14-map-array-of-objects/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/14-map-array-of-objects/public/favicon-32x32.png
--------------------------------------------------------------------------------
/14-map-array-of-objects/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/14-map-array-of-objects/public/favicon.ico
--------------------------------------------------------------------------------
/14-map-array-of-objects/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 | React App
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/14-map-array-of-objects/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/14-map-array-of-objects/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .cards {
6 | display: flex;
7 | flex-wrap: wrap;
8 | flex-direction: row;
9 | justify-content: space-between;
10 | gap: 15px;
11 | }
12 |
13 | .card {
14 | width: 250px;
15 | border: 1px lightgray solid;
16 | border-radius: 10px;
17 | padding-bottom: 10px;
18 | }
19 |
20 | .card > img {
21 | width: 100%;
22 | border-radius: 10px;
23 | }
24 |
--------------------------------------------------------------------------------
/14-map-array-of-objects/src/App.js:
--------------------------------------------------------------------------------
1 | import './App.css';
2 | import Persons from './components/Persons';
3 |
4 | function App() {
5 | return (
6 |
9 | );
10 | }
11 |
12 | export default App;
13 |
--------------------------------------------------------------------------------
/14-map-array-of-objects/src/components/Person.js:
--------------------------------------------------------------------------------
1 | function Person(props) {
2 | const { firstName, lastName, email, img } = props;
3 |
4 | return (
5 |
6 |

7 |
8 | {firstName} {lastName}
9 |
10 |
{email}
11 |
12 | );
13 | }
14 |
15 | export default Person;
16 |
--------------------------------------------------------------------------------
/14-map-array-of-objects/src/components/Persons.js:
--------------------------------------------------------------------------------
1 | import persons from '../data/persons';
2 | import Person from './Person';
3 |
4 | function Persons() {
5 | return (
6 |
7 | {persons.map(person => {
8 | return
;
9 | })}
10 |
11 | );
12 | }
13 |
14 | export default Persons;
15 |
--------------------------------------------------------------------------------
/14-map-array-of-objects/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-family: 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
8 | 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
9 | }
10 |
--------------------------------------------------------------------------------
/14-map-array-of-objects/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render();
8 |
--------------------------------------------------------------------------------
/15-logical-and-operator/.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 |
--------------------------------------------------------------------------------
/15-logical-and-operator/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "00-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.3.1",
10 | "react-dom": "^18.3.1",
11 | "react-scripts": "5.0.1",
12 | "web-vitals": "^2.1.4"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/15-logical-and-operator/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/15-logical-and-operator/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/15-logical-and-operator/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/15-logical-and-operator/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/15-logical-and-operator/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/15-logical-and-operator/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/15-logical-and-operator/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/15-logical-and-operator/public/favicon-16x16.png
--------------------------------------------------------------------------------
/15-logical-and-operator/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/15-logical-and-operator/public/favicon-32x32.png
--------------------------------------------------------------------------------
/15-logical-and-operator/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/15-logical-and-operator/public/favicon.ico
--------------------------------------------------------------------------------
/15-logical-and-operator/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 | React App
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/15-logical-and-operator/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/15-logical-and-operator/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | h1 {
6 | font-size: 90px;
7 | margin-top: 20px;
8 | }
9 |
10 | button {
11 | padding: 15px;
12 | font-size: 30px;
13 | border-radius: 5px;
14 | border: 0;
15 | margin: 20px;
16 | cursor: pointer;
17 | }
18 |
--------------------------------------------------------------------------------
/15-logical-and-operator/src/App.js:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import './App.css';
3 | import Counter from './components/Counter';
4 | import Button from './components/Button';
5 | import ResetBtn from './components/ResetBtn';
6 |
7 | function App() {
8 | const [count, setCount] = useState(0);
9 | const incrementCount = () => {
10 | setCount(count + 1);
11 | };
12 |
13 | const resetCount = () => {
14 | setCount(0);
15 | };
16 |
17 | return (
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | );
27 | }
28 |
29 | export default App;
30 |
--------------------------------------------------------------------------------
/15-logical-and-operator/src/components/Button.js:
--------------------------------------------------------------------------------
1 | function Button({ onClick }) {
2 | return ;
3 | }
4 |
5 | export default Button;
6 |
--------------------------------------------------------------------------------
/15-logical-and-operator/src/components/Counter.js:
--------------------------------------------------------------------------------
1 | function Counter({ count }) {
2 | return Total clicks: {count}
;
3 | }
4 |
5 | export default Counter;
6 |
--------------------------------------------------------------------------------
/15-logical-and-operator/src/components/ResetBtn.js:
--------------------------------------------------------------------------------
1 | function ResetBtn({ count, onClick }) {
2 | return (
3 |
4 | {count > 0 && (
5 |
6 |
9 |
10 | )}
11 |
12 | );
13 | }
14 |
15 | export default ResetBtn;
16 |
--------------------------------------------------------------------------------
/15-logical-and-operator/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-family: 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
8 | 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
9 |
10 | color: white;
11 | background-color: #112d49;
12 | }
13 |
--------------------------------------------------------------------------------
/15-logical-and-operator/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render();
8 |
--------------------------------------------------------------------------------
/16-react-fragment/.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 |
--------------------------------------------------------------------------------
/16-react-fragment/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "00-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.3.1",
10 | "react-dom": "^18.3.1",
11 | "react-scripts": "5.0.1",
12 | "web-vitals": "^2.1.4"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/16-react-fragment/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/16-react-fragment/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/16-react-fragment/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/16-react-fragment/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/16-react-fragment/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/16-react-fragment/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/16-react-fragment/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/16-react-fragment/public/favicon-16x16.png
--------------------------------------------------------------------------------
/16-react-fragment/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/16-react-fragment/public/favicon-32x32.png
--------------------------------------------------------------------------------
/16-react-fragment/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/16-react-fragment/public/favicon.ico
--------------------------------------------------------------------------------
/16-react-fragment/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 | React App
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/16-react-fragment/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/16-react-fragment/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
--------------------------------------------------------------------------------
/16-react-fragment/src/App.js:
--------------------------------------------------------------------------------
1 | import './App.css';
2 | import Card from './components/Card';
3 |
4 | function App() {
5 | return (
6 |
7 |
8 |
9 | );
10 | }
11 |
12 | export default App;
13 |
--------------------------------------------------------------------------------
/16-react-fragment/src/components/Card.js:
--------------------------------------------------------------------------------
1 | const Card = () => {
2 | return (
3 | <>
4 | Viktor
5 | I am recording React course
6 |
7 | >
8 | );
9 | };
10 |
11 | export default Card;
12 |
--------------------------------------------------------------------------------
/16-react-fragment/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-family: 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
8 | 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
9 | }
10 |
--------------------------------------------------------------------------------
/16-react-fragment/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render();
8 |
--------------------------------------------------------------------------------
/17-uncontrolled-input/.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 |
--------------------------------------------------------------------------------
/17-uncontrolled-input/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "00-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.3.1",
10 | "react-dom": "^18.3.1",
11 | "react-scripts": "5.0.1",
12 | "web-vitals": "^2.1.4"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/17-uncontrolled-input/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/17-uncontrolled-input/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/17-uncontrolled-input/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/17-uncontrolled-input/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/17-uncontrolled-input/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/17-uncontrolled-input/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/17-uncontrolled-input/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/17-uncontrolled-input/public/favicon-16x16.png
--------------------------------------------------------------------------------
/17-uncontrolled-input/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/17-uncontrolled-input/public/favicon-32x32.png
--------------------------------------------------------------------------------
/17-uncontrolled-input/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/17-uncontrolled-input/public/favicon.ico
--------------------------------------------------------------------------------
/17-uncontrolled-input/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 | React App
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/17-uncontrolled-input/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/17-uncontrolled-input/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | h1 {
6 | font-size: 70px;
7 | margin-top: 20px;
8 | }
9 |
10 | button {
11 | padding: 15px;
12 | font-size: 30px;
13 | border-radius: 5px;
14 | border: 0;
15 | margin: 20px;
16 | cursor: pointer;
17 | }
18 |
19 | form {
20 | font-size: 30px;
21 | }
22 |
23 | input {
24 | margin: 15px;
25 | padding: 10px;
26 | font-size: 20px;
27 | }
28 |
29 | label {
30 | display: block;
31 | }
32 |
--------------------------------------------------------------------------------
/17-uncontrolled-input/src/App.js:
--------------------------------------------------------------------------------
1 | import './App.css';
2 | import Login from './components/Login';
3 |
4 | function App() {
5 | return (
6 |
7 |
8 |
9 | );
10 | }
11 |
12 | export default App;
13 |
--------------------------------------------------------------------------------
/17-uncontrolled-input/src/components/Login.js:
--------------------------------------------------------------------------------
1 | function Login() {
2 | function handleFormSubmit(event) {
3 | event.preventDefault();
4 |
5 | const userData = {
6 | username: event.target.username.value,
7 | password: event.target.password.value,
8 | };
9 |
10 | console.log(userData);
11 | alert(JSON.stringify(userData));
12 | }
13 | return (
14 | <>
15 | Login Form
16 |
27 | >
28 | );
29 | }
30 |
31 | export default Login;
32 |
--------------------------------------------------------------------------------
/17-uncontrolled-input/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-family: 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
8 | 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
9 |
10 | color: white;
11 | background-color: #112d49;
12 | }
13 |
--------------------------------------------------------------------------------
/17-uncontrolled-input/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render();
8 |
--------------------------------------------------------------------------------
/18-controlled-input/.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 |
--------------------------------------------------------------------------------
/18-controlled-input/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "00-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.3.1",
10 | "react-dom": "^18.3.1",
11 | "react-scripts": "5.0.1",
12 | "web-vitals": "^2.1.4"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/18-controlled-input/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/18-controlled-input/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/18-controlled-input/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/18-controlled-input/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/18-controlled-input/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/18-controlled-input/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/18-controlled-input/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/18-controlled-input/public/favicon-16x16.png
--------------------------------------------------------------------------------
/18-controlled-input/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/18-controlled-input/public/favicon-32x32.png
--------------------------------------------------------------------------------
/18-controlled-input/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/18-controlled-input/public/favicon.ico
--------------------------------------------------------------------------------
/18-controlled-input/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 | React App
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/18-controlled-input/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/18-controlled-input/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | h1 {
6 | font-size: 70px;
7 | margin-top: 20px;
8 | }
9 |
10 | button {
11 | padding: 15px;
12 | font-size: 30px;
13 | border-radius: 5px;
14 | border: 0;
15 | margin: 20px;
16 | cursor: pointer;
17 | }
18 |
19 | form {
20 | font-size: 30px;
21 | }
22 |
23 | input {
24 | margin: 15px;
25 | padding: 10px;
26 | font-size: 20px;
27 | }
28 |
29 | label {
30 | display: block;
31 | }
32 |
--------------------------------------------------------------------------------
/18-controlled-input/src/App.js:
--------------------------------------------------------------------------------
1 | import './App.css';
2 | import Login from './components/Login';
3 |
4 | function App() {
5 | return (
6 |
7 |
8 |
9 | );
10 | }
11 |
12 | export default App;
13 |
--------------------------------------------------------------------------------
/18-controlled-input/src/components/Login.js:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 |
3 | function Login() {
4 | // const [username, setUsername] = useState('');
5 | // const [password, setPassword] = useState('');
6 |
7 | const [data, setData] = useState({ username: '', password: '' });
8 |
9 | function handleFormSubmit(event) {
10 | event.preventDefault();
11 | console.log(data);
12 | alert(JSON.stringify(data));
13 | }
14 |
15 | function handleInputChange(event, name) {
16 | setData({ ...data, [name]: event.target.value });
17 | }
18 |
19 | return (
20 | <>
21 | Login Form
22 |
41 | >
42 | );
43 | }
44 |
45 | export default Login;
46 |
--------------------------------------------------------------------------------
/18-controlled-input/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-family: 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
8 | 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
9 |
10 | color: white;
11 | background-color: #112d49;
12 | }
13 |
--------------------------------------------------------------------------------
/18-controlled-input/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render();
8 |
--------------------------------------------------------------------------------
/19-children-prop/.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 |
--------------------------------------------------------------------------------
/19-children-prop/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "00-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.3.1",
10 | "react-dom": "^18.3.1",
11 | "react-scripts": "5.0.1",
12 | "web-vitals": "^2.1.4"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/19-children-prop/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/19-children-prop/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/19-children-prop/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/19-children-prop/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/19-children-prop/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/19-children-prop/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/19-children-prop/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/19-children-prop/public/favicon-16x16.png
--------------------------------------------------------------------------------
/19-children-prop/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/19-children-prop/public/favicon-32x32.png
--------------------------------------------------------------------------------
/19-children-prop/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/19-children-prop/public/favicon.ico
--------------------------------------------------------------------------------
/19-children-prop/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 | React App
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/19-children-prop/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/19-children-prop/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
--------------------------------------------------------------------------------
/19-children-prop/src/App.js:
--------------------------------------------------------------------------------
1 | import './App.css';
2 | import Wrapper from './components/Wrapper';
3 |
4 | function App() {
5 | return (
6 |
7 |
8 | Hello World
9 |
10 |
11 |
12 | Hello City
13 | Some text
14 |
15 |
16 |
17 | );
18 | }
19 |
20 | export default App;
21 |
--------------------------------------------------------------------------------
/19-children-prop/src/components/Wrapper.js:
--------------------------------------------------------------------------------
1 | function Wrapper(props) {
2 | const style = {
3 | backgroundColor: props.color,
4 | width: '250px',
5 | padding: '20px',
6 | margin: '20px auto',
7 | };
8 |
9 | return {props.children}
;
10 | }
11 |
12 | export default Wrapper;
13 |
--------------------------------------------------------------------------------
/19-children-prop/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-family: 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
8 | 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
9 | }
10 |
--------------------------------------------------------------------------------
/19-children-prop/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render();
8 |
--------------------------------------------------------------------------------
/20-useEffect/.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 |
--------------------------------------------------------------------------------
/20-useEffect/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "00-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.3.1",
10 | "react-dom": "^18.3.1",
11 | "react-scripts": "5.0.1",
12 | "web-vitals": "^2.1.4"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/20-useEffect/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/20-useEffect/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/20-useEffect/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/20-useEffect/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/20-useEffect/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/20-useEffect/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/20-useEffect/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/20-useEffect/public/favicon-16x16.png
--------------------------------------------------------------------------------
/20-useEffect/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/20-useEffect/public/favicon-32x32.png
--------------------------------------------------------------------------------
/20-useEffect/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/20-useEffect/public/favicon.ico
--------------------------------------------------------------------------------
/20-useEffect/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 | React App
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/20-useEffect/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/20-useEffect/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
--------------------------------------------------------------------------------
/20-useEffect/src/App.js:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from 'react';
2 | import './App.css';
3 |
4 | function App() {
5 | const [todo, setTodo] = useState(null);
6 |
7 | useEffect(() => {
8 | fetch('https://jsonplaceholder.typicode.com/todos/5')
9 | .then(response => response.json())
10 | .then(json => setTodo(json));
11 | }, []);
12 |
13 | return (
14 |
15 | {todo &&
{todo.title}
}
16 | {todo && {todo.id}
}
17 | {todo && {todo.userId}
}
18 |
19 | );
20 | }
21 |
22 | export default App;
23 |
--------------------------------------------------------------------------------
/20-useEffect/src/components/Post.js:
--------------------------------------------------------------------------------
1 | function Post() {
2 | return This is post
;
3 | }
4 |
5 | export default Post;
6 |
--------------------------------------------------------------------------------
/20-useEffect/src/components/Posts.js:
--------------------------------------------------------------------------------
1 | import Post from './Post';
2 |
3 | function Posts() {
4 | return (
5 |
10 | );
11 | }
12 |
13 | export default Posts;
14 |
--------------------------------------------------------------------------------
/20-useEffect/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-family: 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
8 | 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
9 | }
10 |
--------------------------------------------------------------------------------
/20-useEffect/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render();
8 |
--------------------------------------------------------------------------------
/21-jsonplaceholder-posts/.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 |
--------------------------------------------------------------------------------
/21-jsonplaceholder-posts/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "00-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.3.1",
10 | "react-dom": "^18.3.1",
11 | "react-scripts": "5.0.1",
12 | "web-vitals": "^2.1.4"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/21-jsonplaceholder-posts/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/21-jsonplaceholder-posts/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/21-jsonplaceholder-posts/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/21-jsonplaceholder-posts/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/21-jsonplaceholder-posts/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/21-jsonplaceholder-posts/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/21-jsonplaceholder-posts/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/21-jsonplaceholder-posts/public/favicon-16x16.png
--------------------------------------------------------------------------------
/21-jsonplaceholder-posts/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/21-jsonplaceholder-posts/public/favicon-32x32.png
--------------------------------------------------------------------------------
/21-jsonplaceholder-posts/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/21-jsonplaceholder-posts/public/favicon.ico
--------------------------------------------------------------------------------
/21-jsonplaceholder-posts/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 | React App
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/21-jsonplaceholder-posts/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/21-jsonplaceholder-posts/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | h1 {
6 | text-align: center;
7 | }
8 |
--------------------------------------------------------------------------------
/21-jsonplaceholder-posts/src/App.js:
--------------------------------------------------------------------------------
1 | import './App.css';
2 | import Posts from './components/Posts';
3 |
4 | function App() {
5 | return (
6 |
9 | );
10 | }
11 |
12 | export default App;
13 |
--------------------------------------------------------------------------------
/21-jsonplaceholder-posts/src/components/Post.css:
--------------------------------------------------------------------------------
1 | .post {
2 | max-width: 50%;
3 | margin: 25px auto;
4 | padding: 15px;
5 | border-radius: 15px;
6 | box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
7 | }
8 |
--------------------------------------------------------------------------------
/21-jsonplaceholder-posts/src/components/Post.js:
--------------------------------------------------------------------------------
1 | import './Post.css';
2 |
3 | function Post(props) {
4 | const { id, title, userId, body } = props;
5 | return (
6 |
7 |
{id}
8 |
{title}
9 |
{body}
10 |
User ID:{userId}
11 |
12 | );
13 | }
14 |
15 | export default Post;
16 |
--------------------------------------------------------------------------------
/21-jsonplaceholder-posts/src/components/Posts.js:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from 'react';
2 | import Post from './Post';
3 |
4 | function Posts() {
5 | const [posts, setPosts] = useState([]);
6 | const [error, setError] = useState('');
7 | const [isLoading, setIsLoading] = useState(true);
8 |
9 | useEffect(() => {
10 | fetch('https://jsonplaceholder.typicode.com/posts')
11 | .then(response => response.json())
12 | .then(posts => setPosts(posts))
13 | .catch(error => setError(error.message))
14 | .finally(() => setIsLoading(false));
15 | }, []);
16 |
17 | if (error) {
18 | return Error: {error}
;
19 | }
20 |
21 | return (
22 | <>
23 | Posts
24 |
25 | {isLoading ? (
26 | Loading...
27 | ) : (
28 | posts.map(post => )
29 | )}
30 | >
31 | );
32 | }
33 |
34 | export default Posts;
35 |
--------------------------------------------------------------------------------
/21-jsonplaceholder-posts/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-family: 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
8 | 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
9 | }
10 |
--------------------------------------------------------------------------------
/21-jsonplaceholder-posts/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render();
8 |
--------------------------------------------------------------------------------
/22-useEffect-async-await/.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 |
--------------------------------------------------------------------------------
/22-useEffect-async-await/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "00-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.3.1",
10 | "react-dom": "^18.3.1",
11 | "react-scripts": "5.0.1",
12 | "web-vitals": "^2.1.4"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/22-useEffect-async-await/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/22-useEffect-async-await/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/22-useEffect-async-await/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/22-useEffect-async-await/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/22-useEffect-async-await/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/22-useEffect-async-await/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/22-useEffect-async-await/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/22-useEffect-async-await/public/favicon-16x16.png
--------------------------------------------------------------------------------
/22-useEffect-async-await/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/22-useEffect-async-await/public/favicon-32x32.png
--------------------------------------------------------------------------------
/22-useEffect-async-await/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/22-useEffect-async-await/public/favicon.ico
--------------------------------------------------------------------------------
/22-useEffect-async-await/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 | React App
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/22-useEffect-async-await/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/22-useEffect-async-await/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | h1 {
6 | text-align: center;
7 | }
8 |
--------------------------------------------------------------------------------
/22-useEffect-async-await/src/App.js:
--------------------------------------------------------------------------------
1 | import './App.css';
2 | import Posts from './components/Posts';
3 |
4 | function App() {
5 | return (
6 |
9 | );
10 | }
11 |
12 | export default App;
13 |
--------------------------------------------------------------------------------
/22-useEffect-async-await/src/components/Post.css:
--------------------------------------------------------------------------------
1 | .post {
2 | max-width: 50%;
3 | margin: 25px auto;
4 | padding: 15px;
5 | border-radius: 15px;
6 | box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
7 | }
8 |
--------------------------------------------------------------------------------
/22-useEffect-async-await/src/components/Post.js:
--------------------------------------------------------------------------------
1 | import './Post.css';
2 |
3 | function Post(props) {
4 | const { id, title, userId, body } = props;
5 | return (
6 |
7 |
{id}
8 |
{title}
9 |
{body}
10 |
User ID:{userId}
11 |
12 | );
13 | }
14 |
15 | export default Post;
16 |
--------------------------------------------------------------------------------
/22-useEffect-async-await/src/components/Posts.js:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from 'react';
2 | import Post from './Post';
3 |
4 | const API_URL = 'https://jsonplaceholder.typicode.com/posts';
5 |
6 | function Posts() {
7 | const [posts, setPosts] = useState([]);
8 | const [error, setError] = useState('');
9 | const [isLoading, setIsLoading] = useState(true);
10 |
11 | useEffect(() => {
12 | async function fetchData() {
13 | try {
14 | const res = await fetch(API_URL);
15 | const posts = await res.json();
16 | setPosts(posts);
17 | } catch (error) {
18 | setError(error.message);
19 | }
20 | setIsLoading(false);
21 | }
22 |
23 | fetchData();
24 | }, []);
25 |
26 | // useEffect(() => {
27 | // fetch('https://jsonplaceholder.typicode.com/posts')
28 | // .then(response => response.json())
29 | // .then(posts => setPosts(posts))
30 | // .catch(error => setError(error.message))
31 | // .finally(() => setIsLoading(false));
32 | // }, []);
33 |
34 | if (error) {
35 | return Error: {error}
;
36 | }
37 |
38 | return (
39 | <>
40 | Posts
41 |
42 | {isLoading ? (
43 | Loading...
44 | ) : (
45 | posts.map(post => )
46 | )}
47 | >
48 | );
49 | }
50 |
51 | export default Posts;
52 |
--------------------------------------------------------------------------------
/22-useEffect-async-await/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-family: 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
8 | 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
9 | }
10 |
--------------------------------------------------------------------------------
/22-useEffect-async-await/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render();
8 |
--------------------------------------------------------------------------------
/23-css-modules/.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 |
--------------------------------------------------------------------------------
/23-css-modules/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "00-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.3.1",
10 | "react-dom": "^18.3.1",
11 | "react-scripts": "5.0.1",
12 | "web-vitals": "^2.1.4"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/23-css-modules/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/23-css-modules/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/23-css-modules/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/23-css-modules/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/23-css-modules/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/23-css-modules/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/23-css-modules/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/23-css-modules/public/favicon-16x16.png
--------------------------------------------------------------------------------
/23-css-modules/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/23-css-modules/public/favicon-32x32.png
--------------------------------------------------------------------------------
/23-css-modules/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/23-css-modules/public/favicon.ico
--------------------------------------------------------------------------------
/23-css-modules/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 | React App
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/23-css-modules/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/23-css-modules/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
--------------------------------------------------------------------------------
/23-css-modules/src/App.js:
--------------------------------------------------------------------------------
1 | import './App.css';
2 | import Info from './components/Info';
3 |
4 | function App() {
5 | return (
6 |
7 |
8 |
App component
9 | App component
10 |
11 |
12 | );
13 | }
14 |
15 | export default App;
16 |
--------------------------------------------------------------------------------
/23-css-modules/src/components/Info.css:
--------------------------------------------------------------------------------
1 | h1 {
2 | color: green;
3 | }
4 |
5 | .my-button {
6 | background-color: yellow;
7 | }
8 |
--------------------------------------------------------------------------------
/23-css-modules/src/components/Info.js:
--------------------------------------------------------------------------------
1 | import './Info.css';
2 | import styles from './info.module.css';
3 |
4 | function Info() {
5 | return (
6 |
7 |
Hello from the Info component!
8 | Hello from the Info component!
9 |
10 |
11 | );
12 | }
13 |
14 | export default Info;
15 |
--------------------------------------------------------------------------------
/23-css-modules/src/components/info.module.css:
--------------------------------------------------------------------------------
1 | .info {
2 | border: 2px solid grey;
3 | border-radius: 10px;
4 | padding: 20px;
5 | max-width: 40%;
6 | margin: 20px auto;
7 | }
8 |
9 | h2 {
10 | color: blue;
11 | }
12 |
--------------------------------------------------------------------------------
/23-css-modules/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-family: 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
8 | 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
9 | }
10 |
--------------------------------------------------------------------------------
/23-css-modules/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render();
8 |
--------------------------------------------------------------------------------
/24-todo-app-v1/.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 |
--------------------------------------------------------------------------------
/24-todo-app-v1/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "00-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.3.1",
10 | "react-dom": "^18.3.1",
11 | "react-icons": "^5.3.0",
12 | "react-scripts": "5.0.1",
13 | "web-vitals": "^2.1.4"
14 | },
15 | "scripts": {
16 | "start": "react-scripts start",
17 | "build": "react-scripts build",
18 | "test": "react-scripts test",
19 | "eject": "react-scripts eject"
20 | },
21 | "eslintConfig": {
22 | "extends": [
23 | "react-app",
24 | "react-app/jest"
25 | ]
26 | },
27 | "browserslist": {
28 | "production": [
29 | ">0.2%",
30 | "not dead",
31 | "not op_mini all"
32 | ],
33 | "development": [
34 | "last 1 chrome version",
35 | "last 1 firefox version",
36 | "last 1 safari version"
37 | ]
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/24-todo-app-v1/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/24-todo-app-v1/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/24-todo-app-v1/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/24-todo-app-v1/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/24-todo-app-v1/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/24-todo-app-v1/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/24-todo-app-v1/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/24-todo-app-v1/public/favicon-16x16.png
--------------------------------------------------------------------------------
/24-todo-app-v1/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/24-todo-app-v1/public/favicon-32x32.png
--------------------------------------------------------------------------------
/24-todo-app-v1/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/24-todo-app-v1/public/favicon.ico
--------------------------------------------------------------------------------
/24-todo-app-v1/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 | React App
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/24-todo-app-v1/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/24-todo-app-v1/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | max-width: 600px;
4 | margin: 0 auto;
5 | }
6 |
7 | h1 {
8 | font-size: 2.2rem;
9 | margin-bottom: 40px;
10 | margin-top: 24px;
11 | }
12 |
--------------------------------------------------------------------------------
/24-todo-app-v1/src/App.js:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import TodoForm from './components/TodoForm/TodoForm';
3 | import TodoList from './components/TodoList/TodoList';
4 | import './App.css';
5 |
6 | function App() {
7 | const [todos, setTodos] = useState([]);
8 |
9 | const addTodoHandler = text => {
10 | setTodos([...todos, text]);
11 | };
12 |
13 | const deleteTodoHandler = index => {
14 | setTodos(todos.filter((_, idx) => idx !== index));
15 | };
16 | return (
17 |
18 |
Todo App
19 |
20 |
21 |
22 | );
23 | }
24 |
25 | export default App;
26 |
--------------------------------------------------------------------------------
/24-todo-app-v1/src/components/Todo/Todo.js:
--------------------------------------------------------------------------------
1 | import { RiTodoFill } from 'react-icons/ri';
2 | import styles from './Todo.module.css';
3 |
4 | function Todo({ todo, index, deleteTodo }) {
5 | return (
6 | deleteTodo(index)}>
7 |
8 |
{todo}
9 |
10 | );
11 | }
12 |
13 | export default Todo;
14 |
--------------------------------------------------------------------------------
/24-todo-app-v1/src/components/Todo/Todo.module.css:
--------------------------------------------------------------------------------
1 | .todo {
2 | display: flex;
3 | align-items: center;
4 | padding: 10px 20px;
5 | margin: 15px 0;
6 | font-size: 1.5rem;
7 | border-radius: 5px;
8 | border: 2px solid #555;
9 | color: #112d49;
10 | background-color: #fbfef9;
11 | }
12 |
13 | .todoText {
14 | width: 100%;
15 | text-align: left;
16 | }
17 |
18 | .todoIcon {
19 | font-size: 1.8rem;
20 | margin-right: 10px;
21 | color: teal;
22 | }
23 |
--------------------------------------------------------------------------------
/24-todo-app-v1/src/components/TodoForm/TodoForm.js:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import styles from './TodoForm.module.css';
3 |
4 | function TodoForm({ addTodo }) {
5 | const [text, setText] = useState('');
6 | const onSubmitHandler = event => {
7 | event.preventDefault();
8 | addTodo(text);
9 | setText('');
10 | };
11 | return (
12 |
13 |
21 |
22 | );
23 | }
24 |
25 | export default TodoForm;
26 |
--------------------------------------------------------------------------------
/24-todo-app-v1/src/components/TodoForm/TodoForm.module.css:
--------------------------------------------------------------------------------
1 | .todoFormContainer {
2 | margin-bottom: 30px;
3 | }
4 |
5 | .todoFormContainer form {
6 | display: flex;
7 | align-items: center;
8 | justify-content: center;
9 | }
10 |
11 | .todoFormContainer input {
12 | width: 45%;
13 | height: 30px;
14 | font-size: 1.3rem;
15 | }
16 |
17 | .todoFormContainer button {
18 | margin-left: 20px;
19 | height: 50px;
20 | cursor: pointer;
21 | background-color: beige;
22 | font-size: 1.5rem;
23 | }
24 |
25 | .todoFormContainer button:hover {
26 | background-color: rgb(240, 240, 155);
27 | }
28 |
29 | .todoFormContainer input,
30 | .todoFormContainer button {
31 | padding: 10px 15px;
32 | border: none;
33 | border-radius: 5px;
34 | }
35 |
--------------------------------------------------------------------------------
/24-todo-app-v1/src/components/TodoList/TodoList.js:
--------------------------------------------------------------------------------
1 | import Todo from '../Todo/Todo';
2 | import styles from './TodoList.module.css';
3 |
4 | function TodoList({ todos, deleteTodo }) {
5 | return (
6 |
7 | {!todos.length &&
Todo list is empty
}
8 | {todos.map((todo, index) => (
9 |
10 | ))}
11 |
12 | );
13 | }
14 | export default TodoList;
15 |
--------------------------------------------------------------------------------
/24-todo-app-v1/src/components/TodoList/TodoList.module.css:
--------------------------------------------------------------------------------
1 | .todoListContainer {
2 | padding: 10px;
3 | }
4 |
--------------------------------------------------------------------------------
/24-todo-app-v1/src/components/UI/Button.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/24-todo-app-v1/src/components/UI/Button.js
--------------------------------------------------------------------------------
/24-todo-app-v1/src/components/UI/Button.module.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/24-todo-app-v1/src/components/UI/Button.module.css
--------------------------------------------------------------------------------
/24-todo-app-v1/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-family: 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
8 | 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
9 |
10 | color: white;
11 | background-color: #112d49;
12 | }
13 |
--------------------------------------------------------------------------------
/24-todo-app-v1/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render();
8 |
--------------------------------------------------------------------------------
/25-todo-app-v2/.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-todo-app-v2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "00-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.3.1",
10 | "react-dom": "^18.3.1",
11 | "react-icons": "^5.3.0",
12 | "react-scripts": "5.0.1",
13 | "uuid": "^10.0.0",
14 | "web-vitals": "^2.1.4"
15 | },
16 | "scripts": {
17 | "start": "react-scripts start",
18 | "build": "react-scripts build",
19 | "test": "react-scripts test",
20 | "eject": "react-scripts eject"
21 | },
22 | "eslintConfig": {
23 | "extends": [
24 | "react-app",
25 | "react-app/jest"
26 | ]
27 | },
28 | "browserslist": {
29 | "production": [
30 | ">0.2%",
31 | "not dead",
32 | "not op_mini all"
33 | ],
34 | "development": [
35 | "last 1 chrome version",
36 | "last 1 firefox version",
37 | "last 1 safari version"
38 | ]
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/25-todo-app-v2/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/25-todo-app-v2/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/25-todo-app-v2/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/25-todo-app-v2/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/25-todo-app-v2/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/25-todo-app-v2/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/25-todo-app-v2/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/25-todo-app-v2/public/favicon-16x16.png
--------------------------------------------------------------------------------
/25-todo-app-v2/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/25-todo-app-v2/public/favicon-32x32.png
--------------------------------------------------------------------------------
/25-todo-app-v2/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/25-todo-app-v2/public/favicon.ico
--------------------------------------------------------------------------------
/25-todo-app-v2/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 | React App
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/25-todo-app-v2/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/25-todo-app-v2/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | max-width: 600px;
4 | margin: 0 auto;
5 | }
6 |
7 | h1 {
8 | font-size: 2.2rem;
9 | margin-bottom: 40px;
10 | margin-top: 24px;
11 | }
12 |
--------------------------------------------------------------------------------
/25-todo-app-v2/src/components/Todo/Todo.js:
--------------------------------------------------------------------------------
1 | import { RiTodoFill, RiDeleteBin2Line } from 'react-icons/ri';
2 | import { FaCheck } from 'react-icons/fa';
3 | import styles from './Todo.module.css';
4 |
5 | function Todo({ todo, deleteTodo, toggleTodo }) {
6 | return (
7 |
12 |
13 |
{todo.text}
14 |
deleteTodo(todo.id)}
17 | />
18 | toggleTodo(todo.id)}
21 | />
22 |
23 | );
24 | }
25 |
26 | export default Todo;
27 |
--------------------------------------------------------------------------------
/25-todo-app-v2/src/components/Todo/Todo.module.css:
--------------------------------------------------------------------------------
1 | .todo {
2 | display: flex;
3 | align-items: center;
4 | padding: 10px 20px;
5 | margin: 15px 0;
6 | font-size: 1.5rem;
7 | border-radius: 5px;
8 | border: 2px solid #555;
9 | color: #112d49;
10 | background-color: #fbfef9;
11 | }
12 |
13 | .todoText {
14 | width: 100%;
15 | text-align: left;
16 | }
17 |
18 | .todoIcon {
19 | font-size: 1.8rem;
20 | margin-right: 10px;
21 | color: teal;
22 | }
23 |
24 | .completedTodo {
25 | background-color: unset;
26 | border-color: gray;
27 | color: gray;
28 | }
29 |
30 | .todo.completedTodo .todoIcon,
31 | .todo.completedTodo .checkIcon,
32 | .todo.completedTodo .deleteIcon {
33 | color: gray;
34 | }
35 |
36 | .checkIcon,
37 | .deleteIcon {
38 | cursor: pointer;
39 | color: lightgrey;
40 | padding: 0 7px;
41 | font-size: 1.8rem;
42 | transition: transform 0.3s;
43 | }
44 |
45 | .checkIcon:hover,
46 | .deleteIcon:hover {
47 | cursor: pointer;
48 | transform: scale(1.3);
49 | }
50 |
51 | .checkIcon:hover {
52 | color: green;
53 | }
54 |
55 | .deleteIcon:hover {
56 | color: red;
57 | }
58 |
--------------------------------------------------------------------------------
/25-todo-app-v2/src/components/TodoForm/TodoForm.js:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import styles from './TodoForm.module.css';
3 | import Button from '../UI/Button';
4 |
5 | function TodoForm({ addTodo }) {
6 | const [text, setText] = useState('');
7 | const onSubmitHandler = event => {
8 | event.preventDefault();
9 | addTodo(text);
10 | setText('');
11 | };
12 | return (
13 |
14 |
24 |
25 | );
26 | }
27 |
28 | export default TodoForm;
29 |
--------------------------------------------------------------------------------
/25-todo-app-v2/src/components/TodoForm/TodoForm.module.css:
--------------------------------------------------------------------------------
1 | .todoFormContainer {
2 | margin-bottom: 30px;
3 | }
4 |
5 | .todoFormContainer form {
6 | display: flex;
7 | align-items: center;
8 | justify-content: center;
9 | }
10 |
11 | .todoFormContainer input {
12 | width: 45%;
13 | height: 30px;
14 | font-size: 1.3rem;
15 | padding: 10px 15px;
16 | border: none;
17 | border-radius: 5px;
18 | }
19 |
--------------------------------------------------------------------------------
/25-todo-app-v2/src/components/TodoList/TodoList.js:
--------------------------------------------------------------------------------
1 | import Todo from '../Todo/Todo';
2 | import styles from './TodoList.module.css';
3 |
4 | function TodoList({ todos, deleteTodo, toggleTodo }) {
5 | return (
6 |
7 | {!todos.length &&
Todo list is empty
}
8 | {todos.map(todo => (
9 |
15 | ))}
16 |
17 | );
18 | }
19 | export default TodoList;
20 |
--------------------------------------------------------------------------------
/25-todo-app-v2/src/components/TodoList/TodoList.module.css:
--------------------------------------------------------------------------------
1 | .todoListContainer {
2 | padding: 10px;
3 | }
4 |
--------------------------------------------------------------------------------
/25-todo-app-v2/src/components/TodosActions/TodosActions.js:
--------------------------------------------------------------------------------
1 | import { RiDeleteBin2Line, RiRefreshLine } from 'react-icons/ri';
2 | import Button from '../UI/Button';
3 | import styles from './TodosActions.module.css';
4 |
5 | function TodosActions({
6 | resetTodos,
7 | deleteCompletedTodos,
8 | completedTodosExist,
9 | }) {
10 | return (
11 |
12 |
15 |
22 |
23 | );
24 | }
25 |
26 | export default TodosActions;
27 |
--------------------------------------------------------------------------------
/25-todo-app-v2/src/components/TodosActions/TodosActions.module.css:
--------------------------------------------------------------------------------
1 | .todosActionContainer {
2 | margin: 5px;
3 | }
4 |
--------------------------------------------------------------------------------
/25-todo-app-v2/src/components/UI/Button.js:
--------------------------------------------------------------------------------
1 | import styles from './Button.module.css';
2 |
3 | function Button(props) {
4 | const { onClick, children, title, disabled = false } = props;
5 | return (
6 |
15 | );
16 | }
17 |
18 | export default Button;
19 |
--------------------------------------------------------------------------------
/25-todo-app-v2/src/components/UI/Button.module.css:
--------------------------------------------------------------------------------
1 | .btn {
2 | margin-left: 20px;
3 | height: 50px;
4 | cursor: pointer;
5 | background-color: beige;
6 | font-size: 1.5rem;
7 | padding: 10px 15px;
8 | border: none;
9 | border-radius: 5px;
10 | }
11 |
12 | .btn:hover {
13 | background-color: rgb(240, 240, 155);
14 | }
15 |
--------------------------------------------------------------------------------
/25-todo-app-v2/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-family: 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
8 | 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
9 |
10 | color: white;
11 | background-color: #112d49;
12 | }
13 |
--------------------------------------------------------------------------------
/25-todo-app-v2/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render();
8 |
--------------------------------------------------------------------------------
/26-react-router/.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 |
--------------------------------------------------------------------------------
/26-react-router/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "00-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.3.1",
10 | "react-dom": "^18.3.1",
11 | "react-router-dom": "^6.26.1",
12 | "react-scripts": "5.0.1",
13 | "web-vitals": "^2.1.4"
14 | },
15 | "scripts": {
16 | "start": "react-scripts start",
17 | "build": "react-scripts build",
18 | "test": "react-scripts test",
19 | "eject": "react-scripts eject"
20 | },
21 | "eslintConfig": {
22 | "extends": [
23 | "react-app",
24 | "react-app/jest"
25 | ]
26 | },
27 | "browserslist": {
28 | "production": [
29 | ">0.2%",
30 | "not dead",
31 | "not op_mini all"
32 | ],
33 | "development": [
34 | "last 1 chrome version",
35 | "last 1 firefox version",
36 | "last 1 safari version"
37 | ]
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/26-react-router/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/26-react-router/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/26-react-router/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/26-react-router/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/26-react-router/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/26-react-router/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/26-react-router/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/26-react-router/public/favicon-16x16.png
--------------------------------------------------------------------------------
/26-react-router/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/26-react-router/public/favicon-32x32.png
--------------------------------------------------------------------------------
/26-react-router/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/26-react-router/public/favicon.ico
--------------------------------------------------------------------------------
/26-react-router/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 | React App
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/26-react-router/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/26-react-router/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .active {
6 | color: yellow;
7 | }
8 |
9 | .courseLink {
10 | font-size: 25px;
11 | }
12 |
13 | .courseLink:hover {
14 | text-decoration: underline;
15 | }
16 |
17 | a {
18 | color: wheat;
19 | font-size: 35px;
20 | text-decoration: none;
21 | }
22 |
23 | nav {
24 | background-color: darkcyan;
25 | padding: 15px;
26 | }
27 |
28 | nav a {
29 | margin: 15px;
30 | }
31 |
32 | h1 {
33 | font-size: 90px;
34 | margin-top: 20px;
35 | }
36 |
37 | button {
38 | padding: 15px;
39 | font-size: 30px;
40 | border-radius: 5px;
41 | border: 0;
42 | margin: 20px;
43 | cursor: pointer;
44 | }
45 |
--------------------------------------------------------------------------------
/26-react-router/src/App.jsx:
--------------------------------------------------------------------------------
1 | import { BrowserRouter, Route, Routes } from 'react-router-dom';
2 | import './App.css';
3 | import Home from './components/Home';
4 | import About from './components/About';
5 | import Contacts from './components/Contacts';
6 | import Courses from './components/Courses';
7 | import SingleCourse from './components/SingleCourse';
8 | import NotFound from './components/NotFound';
9 | import MainLayout from './layouts/MainLayout';
10 |
11 | function App() {
12 | return (
13 |
14 |
15 |
16 | }>
17 | } />
18 | } />
19 | } />
20 | } />
21 | } />
22 | } />
23 |
24 |
25 |
26 |
27 | );
28 | }
29 |
30 | export default App;
31 |
--------------------------------------------------------------------------------
/26-react-router/src/components/About.jsx:
--------------------------------------------------------------------------------
1 | function About() {
2 | return About
;
3 | }
4 |
5 | export default About;
6 |
--------------------------------------------------------------------------------
/26-react-router/src/components/Contacts.jsx:
--------------------------------------------------------------------------------
1 | function Contacts() {
2 | return Contacts
;
3 | }
4 |
5 | export default Contacts;
6 |
--------------------------------------------------------------------------------
/26-react-router/src/components/Courses.jsx:
--------------------------------------------------------------------------------
1 | import { Link } from 'react-router-dom';
2 | import courses from '../data/courses';
3 |
4 | function Courses() {
5 | return (
6 | <>
7 | Courses
8 | {courses.map(course => {
9 | return (
10 |
11 |
12 | {course.title}
13 |
14 |
15 | );
16 | })}
17 | >
18 | );
19 | }
20 |
21 | export default Courses;
22 |
--------------------------------------------------------------------------------
/26-react-router/src/components/Home.jsx:
--------------------------------------------------------------------------------
1 | function Home() {
2 | return Home
;
3 | }
4 |
5 | export default Home;
6 |
--------------------------------------------------------------------------------
/26-react-router/src/components/Menu.jsx:
--------------------------------------------------------------------------------
1 | import { NavLink } from 'react-router-dom';
2 |
3 | function Menu() {
4 | return (
5 |
11 | );
12 | }
13 |
14 | export default Menu;
15 |
--------------------------------------------------------------------------------
/26-react-router/src/components/NotFound.jsx:
--------------------------------------------------------------------------------
1 | function NotFound() {
2 | return Not Found
;
3 | }
4 |
5 | export default NotFound;
6 |
--------------------------------------------------------------------------------
/26-react-router/src/components/SingleCourse.jsx:
--------------------------------------------------------------------------------
1 | import { Link, useParams } from 'react-router-dom';
2 | import courses from '../data/courses';
3 | import NotFound from './NotFound';
4 | // import { useEffect } from 'react';
5 | // import { useNavigate } from 'react-router-dom';
6 |
7 | function SingleCourse() {
8 | const params = useParams();
9 | const course = courses.find(course => course.slug === params.slug);
10 | if (!course) {
11 | return ;
12 | }
13 |
14 | // const navigate = useNavigate();
15 |
16 | // useEffect(() => {
17 | // if (!course) {
18 | // navigate('..', { relative: 'path' });
19 | // }
20 | // }, [course, navigate]);
21 |
22 | // return (
23 | // <>
24 | // {course?.title}
25 | // {course?.slug}
26 | // {course?.id}
27 | //
28 | // All courses
29 | //
30 | // >
31 | // );
32 |
33 | return (
34 | <>
35 | {course.title}
36 | {course.slug}
37 | {course.id}
38 |
39 | All courses
40 |
41 | >
42 | );
43 | }
44 |
45 | export default SingleCourse;
46 |
--------------------------------------------------------------------------------
/26-react-router/src/data/courses.js:
--------------------------------------------------------------------------------
1 | const courses = [
2 | {
3 | title: 'Complete React Guide',
4 | slug: 'react',
5 | id: 257,
6 | },
7 | {
8 | title: 'Complete JavaScript Guide',
9 | slug: 'javascript',
10 | id: 345,
11 | },
12 | {
13 | title: 'Complete Python Guide',
14 | slug: 'python',
15 | id: 498,
16 | },
17 | {
18 | title: 'Complete Node.js Guide',
19 | slug: 'node-js',
20 | id: 516,
21 | },
22 | ];
23 |
24 | export default courses;
25 |
--------------------------------------------------------------------------------
/26-react-router/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-family: 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
8 | 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
9 |
10 | color: white;
11 | background-color: #112d49;
12 | }
13 |
--------------------------------------------------------------------------------
/26-react-router/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render();
8 |
--------------------------------------------------------------------------------
/26-react-router/src/layouts/MainLayout.jsx:
--------------------------------------------------------------------------------
1 | import { Outlet } from 'react-router-dom';
2 | import Menu from '../components/Menu';
3 |
4 | function MainLayout() {
5 | return (
6 | <>
7 |
8 |
9 | >
10 | );
11 | }
12 |
13 | export default MainLayout;
14 |
--------------------------------------------------------------------------------
/27-context-api/.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 |
--------------------------------------------------------------------------------
/27-context-api/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "00-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.3.1",
10 | "react-dom": "^18.3.1",
11 | "react-scripts": "5.0.1",
12 | "web-vitals": "^2.1.4"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/27-context-api/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/27-context-api/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/27-context-api/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/27-context-api/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/27-context-api/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/27-context-api/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/27-context-api/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/27-context-api/public/favicon-16x16.png
--------------------------------------------------------------------------------
/27-context-api/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/27-context-api/public/favicon-32x32.png
--------------------------------------------------------------------------------
/27-context-api/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/27-context-api/public/favicon.ico
--------------------------------------------------------------------------------
/27-context-api/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 | React App
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/27-context-api/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/27-context-api/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | h1 {
6 | font-size: 90px;
7 | margin-top: 20px;
8 | }
9 |
10 | button {
11 | padding: 15px;
12 | font-size: 30px;
13 | border-radius: 5px;
14 | border: 0;
15 | margin: 20px;
16 | cursor: pointer;
17 | }
18 |
--------------------------------------------------------------------------------
/27-context-api/src/App.js:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import './App.css';
3 | import User from './components/User';
4 | import UserContext from './context/UserContext';
5 | import ChangeUser from './components/ChangeUser';
6 |
7 | function App() {
8 | const [user, setUser] = useState('Evan');
9 |
10 | return (
11 |
12 |
13 |
14 |
15 |
16 |
17 | );
18 | }
19 |
20 | export default App;
21 |
--------------------------------------------------------------------------------
/27-context-api/src/components/ChangeUser.jsx:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react';
2 | import UserContext from '../context/UserContext';
3 |
4 | function ChangeUser() {
5 | const { user, setUser } = useContext(UserContext);
6 | return (
7 |
10 | );
11 | }
12 |
13 | export default ChangeUser;
14 |
--------------------------------------------------------------------------------
/27-context-api/src/components/User.jsx:
--------------------------------------------------------------------------------
1 | import UserInfo from './UserInfo';
2 |
3 | function User() {
4 | return ;
5 | }
6 |
7 | export default User;
8 |
--------------------------------------------------------------------------------
/27-context-api/src/components/UserInfo.jsx:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react';
2 | import UserContext from '../context/UserContext';
3 |
4 | function UserInfo() {
5 | const { user } = useContext(UserContext);
6 |
7 | return {user}
;
8 | }
9 |
10 | export default UserInfo;
11 |
--------------------------------------------------------------------------------
/27-context-api/src/context/UserContext.js:
--------------------------------------------------------------------------------
1 | import { createContext } from 'react';
2 |
3 | const UserContext = createContext({
4 | user: '',
5 | setUser: () => {},
6 | });
7 |
8 | export default UserContext;
9 |
--------------------------------------------------------------------------------
/27-context-api/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-family: 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
8 | 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
9 |
10 | color: white;
11 | background-color: #112d49;
12 | }
13 |
--------------------------------------------------------------------------------
/27-context-api/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render();
8 |
--------------------------------------------------------------------------------
/28-reducer/reducer.js:
--------------------------------------------------------------------------------
1 | const initialState = [];
2 |
3 | function reducer(state, action) {
4 | switch (action.type) {
5 | case 'ADD_NAME':
6 | return [...state, action.payload];
7 |
8 | case 'DELETE_NAME':
9 | return state.filter(personName => personName !== action.payload);
10 |
11 | case 'CLEAR_NAMES':
12 | return [];
13 |
14 | default:
15 | return state;
16 | }
17 | // if (action.type === 'ADD_NAME') {
18 | // return [...state, action.payload];
19 | // }
20 |
21 | // if (action.type === 'DELETE_NAME') {
22 | // return state.filter(personName => personName !== action.payload);
23 | // }
24 |
25 | // if (action.type === 'CLEAR_NAMES') {
26 | // return [];
27 | // }
28 |
29 | // return state;
30 | }
31 |
32 | let newState = reducer(initialState, { type: 'ADD_NAME', payload: 'Alice' });
33 | console.log(newState);
34 |
35 | newState = reducer(newState, { type: 'ADD_NAME', payload: 'Evan' });
36 | console.log(newState);
37 |
38 | newState = reducer(newState, { type: 'ADD_NAME', payload: 'Inna' });
39 | console.log(newState);
40 |
41 | newState = reducer(newState, { type: 'DELETE_NAME', payload: 'Inna' });
42 | console.log(newState);
43 |
44 | newState = reducer(newState, { type: 'CLEAR_NAMES' });
45 | console.log(newState);
46 |
47 | newState = reducer(newState, { type: 'ADD_NAME', payload: 'Evan' });
48 | console.log(newState);
49 |
50 | newState = reducer(newState, { type: 'ADD_NAME', payload: 'Alice' });
51 | console.log(newState);
52 |
53 | newState = reducer(newState, { type: 'ADD_NAME', payload: 'Inna' });
54 | console.log(newState);
55 |
--------------------------------------------------------------------------------
/29-pure-redux/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Pure Redux
7 |
8 |
9 |
10 | Pure Redux
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/29-pure-redux/index.js:
--------------------------------------------------------------------------------
1 | import store from './redux/store.js';
2 | import getCurrentTime from './utils/getCurrentTime.js';
3 |
4 | const addTimeBtn = document.getElementById('addTime');
5 | addTimeBtn.addEventListener('click', () => {
6 | store.dispatch({
7 | type: 'ADD_CURRENT_TIME',
8 | payload: getCurrentTime(),
9 | });
10 | });
11 |
12 | const clearTimeBtn = document.getElementById('clearTimes');
13 | clearTimeBtn.addEventListener('click', () => {
14 | store.dispatch({
15 | type: 'CLEAR_ALL_TIMES',
16 | });
17 | });
18 |
19 | const timesList = document.getElementById('timesList');
20 |
21 | store.subscribe(() => {
22 | timesList.innerHTML = '';
23 | const times = store.getState();
24 | times.forEach(time => {
25 | let li = document.createElement('li');
26 | li.innerText = time;
27 | timesList.appendChild(li);
28 | });
29 | });
30 |
31 | // store.subscribe(() =>
32 | // console.log(`Redux store just changed! ${store.getState()}`),
33 | // );
34 |
35 | // store.dispatch({
36 | // type: 'ADD_CURRENT_TIME',
37 | // payload: '11:30:00',
38 | // });
39 |
40 | // store.dispatch({
41 | // type: 'ADD_CURRENT_TIME',
42 | // payload: '11:32:00',
43 | // });
44 |
45 | // store.dispatch({
46 | // type: 'CLEAR_ALL_TIMES',
47 | // });
48 |
--------------------------------------------------------------------------------
/29-pure-redux/redux/reducer.js:
--------------------------------------------------------------------------------
1 | const initialState = [];
2 |
3 | function reducer(state = initialState, action) {
4 | switch (action.type) {
5 | case 'ADD_CURRENT_TIME':
6 | return [...state, action.payload];
7 |
8 | case 'CLEAR_ALL_TIMES':
9 | return [];
10 |
11 | default:
12 | return state;
13 | }
14 | }
15 |
16 | export default reducer;
17 |
--------------------------------------------------------------------------------
/29-pure-redux/redux/store.js:
--------------------------------------------------------------------------------
1 | import { configureStore } from 'https://cdn.jsdelivr.net/npm/@reduxjs/toolkit@2.2.7/+esm';
2 | import reducer from './reducer.js';
3 |
4 | export default configureStore({
5 | reducer: reducer,
6 | });
7 |
--------------------------------------------------------------------------------
/29-pure-redux/utils/getCurrentTime.js:
--------------------------------------------------------------------------------
1 | function getCurrentTime() {
2 | const now = new Date();
3 | const hours = now.getHours().toString().padStart(2, '0');
4 | const minutes = now.getMinutes().toString().padStart(2, '0');
5 | const seconds = now.getSeconds().toString().padStart(2, '0');
6 |
7 | const currentTime = `${hours}:${minutes}:${seconds}`;
8 |
9 | return currentTime;
10 | }
11 |
12 | export default getCurrentTime;
13 |
--------------------------------------------------------------------------------
/30-react-redux/api/.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 |
--------------------------------------------------------------------------------
/30-react-redux/api/README.md:
--------------------------------------------------------------------------------
1 | # Book Library App API
2 |
--------------------------------------------------------------------------------
/30-react-redux/api/index.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const cors = require('cors');
3 | const booksData = require('./data/books.json'); // Import the book data
4 |
5 | const app = express();
6 |
7 | app.use(cors());
8 |
9 | function getRandomBook() {
10 | const randomIndex = Math.floor(Math.random() * booksData.length);
11 | const randomBook = booksData[randomIndex];
12 | return randomBook;
13 | }
14 |
15 | app.get('/random-book', (req, res) => {
16 | res.json(getRandomBook()); // http://localhost:4000/random-book
17 | });
18 |
19 | app.get('/random-book-delayed', (req, res) => {
20 | setTimeout(() => {
21 | res.json(getRandomBook()); // http://localhost:4000/random-book-delayed
22 | }, 2000);
23 | });
24 |
25 | const port = process.env.PORT || 4000;
26 | app.listen(port, () => {
27 | console.log(`Server is running on port ${port}`);
28 | });
29 |
--------------------------------------------------------------------------------
/30-react-redux/api/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "api",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "node index.js",
8 | "dev": "nodemon index.js"
9 | },
10 | "keywords": [],
11 | "author": "",
12 | "license": "ISC",
13 | "dependencies": {
14 | "cors": "^2.8.5",
15 | "express": "^4.21.0",
16 | "nodemon": "^3.1.4"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/30-react-redux/api/vercel.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 2,
3 | "builds": [
4 | {
5 | "src": "*.js",
6 | "use": "@vercel/node"
7 | }
8 | ],
9 | "routes": [
10 | {
11 | "src": "/(.*)",
12 | "dest": "/"
13 | }
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/30-react-redux/frontend/.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 |
--------------------------------------------------------------------------------
/30-react-redux/frontend/README.md:
--------------------------------------------------------------------------------
1 | # Book Library App
2 |
--------------------------------------------------------------------------------
/30-react-redux/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "frontend",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@reduxjs/toolkit": "^1.9.5",
7 | "@testing-library/jest-dom": "^5.17.0",
8 | "@testing-library/react": "^13.4.0",
9 | "@testing-library/user-event": "^13.5.0",
10 | "axios": "^1.7.7",
11 | "react": "^18.3.1",
12 | "react-dom": "^18.3.1",
13 | "react-icons": "^5.3.0",
14 | "react-redux": "^8.1.2",
15 | "react-scripts": "5.0.1",
16 | "react-toastify": "^10.0.5",
17 | "uuid": "^10.0.0",
18 | "web-vitals": "^2.1.4"
19 | },
20 | "scripts": {
21 | "start": "react-scripts start",
22 | "build": "react-scripts build",
23 | "test": "react-scripts test",
24 | "eject": "react-scripts eject"
25 | },
26 | "eslintConfig": {
27 | "extends": [
28 | "react-app",
29 | "react-app/jest"
30 | ]
31 | },
32 | "browserslist": {
33 | "production": [
34 | ">0.2%",
35 | "not dead",
36 | "not op_mini all"
37 | ],
38 | "development": [
39 | "last 1 chrome version",
40 | "last 1 firefox version",
41 | "last 1 safari version"
42 | ]
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/30-react-redux/frontend/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/30-react-redux/frontend/public/favicon.ico
--------------------------------------------------------------------------------
/30-react-redux/frontend/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/30-react-redux/frontend/public/logo192.png
--------------------------------------------------------------------------------
/30-react-redux/frontend/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ViktorSvertoka/react-projects/ef2eb68efe92058abd5d5ba8b40cf5547446de46/30-react-redux/frontend/public/logo512.png
--------------------------------------------------------------------------------
/30-react-redux/frontend/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 |
--------------------------------------------------------------------------------
/30-react-redux/frontend/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/30-react-redux/frontend/src/App.css:
--------------------------------------------------------------------------------
1 | .app {
2 | display: flex;
3 | flex-direction: column;
4 | align-items: center;
5 | justify-content: center;
6 | text-align: center;
7 | }
8 |
9 | .app-header {
10 | background-color: #0a1a2d;
11 | color: #fff;
12 | width: 100%;
13 | margin-bottom: 20px;
14 | }
15 |
16 | .app-main {
17 | display: flex;
18 | justify-content: space-between;
19 | width: 80%;
20 | margin: 0 auto;
21 | }
22 |
23 | .app-left-column {
24 | flex: 1;
25 | flex-basis: 35%;
26 | display: flex;
27 | align-items: center;
28 | align-self: flex-start;
29 | }
30 |
31 | .app-right-column {
32 | flex: 1;
33 | flex-basis: 65%;
34 | display: flex;
35 | flex-direction: column;
36 | }
37 |
38 | .app-block {
39 | padding: 20px;
40 | margin: 20px;
41 | background-color: #f2f2f2;
42 | border-radius: 5px;
43 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
44 | }
45 |
46 | @media (max-width: 1024px) {
47 | .app-main {
48 | width: 100%;
49 | flex-direction: column;
50 | }
51 |
52 | .app-left-column,
53 | .app-right-column {
54 | flex-basis: 100%;
55 | align-self: unset;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/30-react-redux/frontend/src/App.js:
--------------------------------------------------------------------------------
1 | import BookList from './components/BookList/BookList';
2 | import BookForm from './components/BookForm/BookForm';
3 | import Filter from './components/Filter/Filter';
4 | import Error from './components/Error/Error';
5 | import './App.css';
6 |
7 | function App() {
8 | return (
9 |
10 |
11 | Book Library App
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | );
25 | }
26 |
27 | export default App;
28 |
--------------------------------------------------------------------------------
/30-react-redux/frontend/src/components/BookForm/BookForm.css:
--------------------------------------------------------------------------------
1 | .book-form {
2 | width: 100%;
3 | }
4 |
5 | .book-form label {
6 | display: block;
7 | width: 100%;
8 | text-align: center;
9 | margin-bottom: 10px;
10 | }
11 |
12 | .book-form input {
13 | width: 80%;
14 | padding: 8px;
15 | margin-bottom: 10px;
16 | border: 1px solid #ccc;
17 | border-radius: 3px;
18 | }
19 |
20 | .book-form button {
21 | background-color: #007bff;
22 | color: #fff;
23 | padding: 8px 12px;
24 | border: none;
25 | border-radius: 3px;
26 | cursor: pointer;
27 | margin: 10px;
28 | transition: background-color 0.3s ease;
29 | }
30 |
31 | .book-form button:hover {
32 | background-color: #0056b3;
33 | }
34 |
35 | .book-form .spinner {
36 | animation: spinner 1s infinite linear;
37 | margin-left: 10px;
38 | }
39 |
40 | @keyframes spinner {
41 | from {
42 | transform: rotate(0deg);
43 | }
44 |
45 | to {
46 | transform: rotate(360deg);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/30-react-redux/frontend/src/components/BookList/BookList.css:
--------------------------------------------------------------------------------
1 | .book-list ul {
2 | padding: 0;
3 | margin: 20px -20px;
4 | list-style: none;
5 | }
6 |
7 | .book-list li {
8 | display: flex;
9 | justify-content: space-between;
10 | align-items: center;
11 | width: auto;
12 | padding: 10px 20px;
13 | border-bottom: 1px solid #ccc;
14 | background-color: #fff;
15 | list-style-type: none;
16 | }
17 |
18 | .book-list li:nth-child(even) {
19 | background-color: #f2f2f2;
20 | }
21 |
22 | .book-list li:hover {
23 | background-color: #dbe4f8;
24 | }
25 |
26 | .book-list button {
27 | background-color: #fff;
28 | color: red;
29 | border: 1px solid red;
30 | padding: 8px 12px;
31 | border-radius: 3px;
32 | cursor: pointer;
33 | transition: background-color 0.3s ease;
34 | }
35 |
36 | .book-list button:hover {
37 | background-color: #fdd;
38 | }
39 |
40 | .book-list .highlight {
41 | background-color: #ff0;
42 | }
43 |
44 | .book-list .book-info {
45 | flex: 1;
46 | text-align: left;
47 | }
48 |
49 | .book-list .book-actions {
50 | display: flex;
51 | align-items: center;
52 | }
53 |
54 | .book-list .star-icon {
55 | width: 24px;
56 | height: 24px;
57 | margin: 0 20px;
58 | cursor: pointer;
59 | transition: color 0.3s ease;
60 | color: #fca510;
61 | }
62 |
--------------------------------------------------------------------------------
/30-react-redux/frontend/src/components/Error/Error.js:
--------------------------------------------------------------------------------
1 | import { useEffect } from 'react';
2 | import { ToastContainer, toast } from 'react-toastify';
3 | import { useSelector, useDispatch } from 'react-redux';
4 | import 'react-toastify/dist/ReactToastify.css';
5 | import { clearError, selectErrorMessage } from '../../redux/slices/errorSlice';
6 |
7 | const Error = () => {
8 | const errorMessage = useSelector(selectErrorMessage);
9 | const dispatch = useDispatch();
10 |
11 | useEffect(() => {
12 | if (errorMessage) {
13 | toast.info(errorMessage);
14 | dispatch(clearError());
15 | }
16 | }, [errorMessage, dispatch]);
17 | return ;
18 | };
19 |
20 | export default Error;
21 |
--------------------------------------------------------------------------------
/30-react-redux/frontend/src/components/Filter/Filter.css:
--------------------------------------------------------------------------------
1 | .filter-row {
2 | display: flex;
3 | justify-content: space-between;
4 | align-items: center;
5 | }
6 |
7 | .filter-group {
8 | flex: 1;
9 | text-align: center;
10 | }
11 |
12 | .filter input[type='text'] {
13 | width: 80%;
14 | padding: 8px;
15 | border: 1px solid #ccc;
16 | border-radius: 3px;
17 | }
18 |
19 | .filter button {
20 | background-color: #007bff;
21 | color: #fff;
22 | padding: 8px 12px;
23 | border: none;
24 | border-radius: 3px;
25 | cursor: pointer;
26 | margin: 10px;
27 | transition: background-color 0.3s ease;
28 | }
29 |
30 | .filter button:hover {
31 | background-color: #0056b3;
32 | }
33 |
34 | @media screen and (max-width: 1024px) {
35 | .filter-row {
36 | flex-direction: column;
37 | align-items: stretch;
38 | }
39 |
40 | .filter-group {
41 | width: 100%;
42 | margin: auto;
43 | margin-bottom: 10px;
44 | }
45 |
46 | .filter button {
47 | margin: 10px auto 0;
48 | max-width: 50%;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/30-react-redux/frontend/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto',
4 | 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans',
5 | 'Helvetica Neue', sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | background-color: #112d49;
9 | }
10 |
11 | code {
12 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
13 | monospace;
14 | }
15 |
--------------------------------------------------------------------------------
/30-react-redux/frontend/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Provider } from 'react-redux';
3 | import ReactDOM from 'react-dom/client';
4 | import store from './redux/store';
5 | import './index.css';
6 | import App from './App';
7 |
8 | const root = ReactDOM.createRoot(document.getElementById('root'));
9 | root.render(
10 |
11 |
12 | ,
13 | );
14 |
--------------------------------------------------------------------------------
/30-react-redux/frontend/src/redux/slices/errorSlice.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from '@reduxjs/toolkit';
2 |
3 | const initialState = '';
4 |
5 | const errorSlice = createSlice({
6 | name: 'error',
7 | initialState,
8 | reducers: {
9 | setError: (state, action) => {
10 | return action.payload;
11 | },
12 | clearError: () => {
13 | return initialState;
14 | },
15 | },
16 | });
17 |
18 | export const { setError, clearError } = errorSlice.actions;
19 |
20 | export const selectErrorMessage = state => state.error;
21 |
22 | export default errorSlice.reducer;
23 |
--------------------------------------------------------------------------------
/30-react-redux/frontend/src/redux/slices/filterSlice.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from '@reduxjs/toolkit';
2 |
3 | const initialState = {
4 | title: '',
5 | author: '',
6 | onlyFavorite: false,
7 | };
8 |
9 | const filterSlice = createSlice({
10 | name: 'filter',
11 | initialState,
12 | reducers: {
13 | setTitleFilter: (state, action) => {
14 | state.title = action.payload;
15 | },
16 | setAuthorFilter: (state, action) => {
17 | state.author = action.payload;
18 | },
19 | setOnlyFavoriteFilter: state => {
20 | state.onlyFavorite = !state.onlyFavorite;
21 | },
22 | resetFilters: () => {
23 | return initialState;
24 | },
25 | },
26 | });
27 |
28 | export const {
29 | setTitleFilter,
30 | setAuthorFilter,
31 | setOnlyFavoriteFilter,
32 | resetFilters,
33 | } = filterSlice.actions;
34 |
35 | export const selectTitleFilter = state => state.filter.title;
36 | export const selectAuthorFilter = state => state.filter.author;
37 | export const selectOnlyFavoriteFilter = state => state.filter.onlyFavorite;
38 |
39 | export default filterSlice.reducer;
40 |
--------------------------------------------------------------------------------
/30-react-redux/frontend/src/redux/store.js:
--------------------------------------------------------------------------------
1 | import { configureStore } from '@reduxjs/toolkit';
2 | import booksReducer from './slices/booksSlice';
3 | import filterReducer from './slices/filterSlice';
4 | import errorReducer from './slices/errorSlice';
5 |
6 | const store = configureStore({
7 | reducer: {
8 | books: booksReducer,
9 | filter: filterReducer,
10 | error: errorReducer,
11 | },
12 | });
13 |
14 | export default store;
15 |
--------------------------------------------------------------------------------
/30-react-redux/frontend/src/utils/createBookWithID.js:
--------------------------------------------------------------------------------
1 | import { v4 as uuidv4 } from 'uuid';
2 |
3 | const createBookWithID = (book, source) => {
4 | return {
5 | ...book,
6 | source,
7 | isFavorite: false,
8 | id: uuidv4(),
9 | };
10 | };
11 |
12 | export default createBookWithID;
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Udemy Course
2 |
--------------------------------------------------------------------------------