From 0a6033d4e4fe8048b9a0ae1370a7d54a1a09e0a0 Mon Sep 17 00:00:00 2001 From: ferzik85 Date: Mon, 6 Nov 2023 16:00:35 +0100 Subject: [PATCH 01/22] change app structure --- .eslintrc.json | 3 +-- package.json | 4 +++- src/App.jsx | 7 ++++-- src/App.module.css | 5 ++++ src/common/Button/Button.jsx | 0 src/common/Input/Input.jsx | 0 src/components/CourseInfo/CourseInfo.jsx | 0 .../CourseInfo/CourseInfo.module.css | 0 src/components/Courses/Courses.jsx | 0 src/components/Courses/Courses.module.css | 0 .../components/CourseCard/CourseCard.jsx | 0 .../CourseCard/CourseCard.module.css | 0 .../components/SearchBar/SearchBar.jsx | 0 .../components/SearchBar/SearchBar.module.css | 0 src/components/Header/Header.jsx | 14 +++++++++++ src/components/Header/Header.module.css | 23 +++++++++++++++++++ src/components/Header/components/Logo.jsx | 0 .../Header/components/Logo.module.css | 0 src/{index.js => index.jsx} | 6 ++--- 19 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 src/App.module.css create mode 100644 src/common/Button/Button.jsx create mode 100644 src/common/Input/Input.jsx create mode 100644 src/components/CourseInfo/CourseInfo.jsx create mode 100644 src/components/CourseInfo/CourseInfo.module.css create mode 100644 src/components/Courses/Courses.jsx create mode 100644 src/components/Courses/Courses.module.css create mode 100644 src/components/Courses/components/CourseCard/CourseCard.jsx create mode 100644 src/components/Courses/components/CourseCard/CourseCard.module.css create mode 100644 src/components/Courses/components/SearchBar/SearchBar.jsx create mode 100644 src/components/Courses/components/SearchBar/SearchBar.module.css create mode 100644 src/components/Header/Header.jsx create mode 100644 src/components/Header/Header.module.css create mode 100644 src/components/Header/components/Logo.jsx create mode 100644 src/components/Header/components/Logo.module.css rename src/{index.js => index.jsx} (78%) diff --git a/.eslintrc.json b/.eslintrc.json index 3901202..94e801f 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -4,7 +4,7 @@ "browser": true, "es2021": true }, - "extends": ["airbnb", "react", "prettier"], + "extends": ["airbnb", "prettier"], "parserOptions": { "ecmaFeatures": { "jsx": true @@ -13,7 +13,6 @@ "sourceType": "module" }, "plugins": [ - "react", "prettier" ], "rules": { diff --git a/package.json b/package.json index 7dc5f43..efcd2d8 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,9 @@ "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", - "eject": "react-scripts eject" + "eject": "react-scripts eject", + "eslint": "eslint --ext .js --ext .jsx src", + "eslint:fix": "eslint --fix --ext .js --ext .jsx src" }, "eslintConfig": { "extends": [ diff --git a/src/App.jsx b/src/App.jsx index b0a1632..5614fbe 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,5 +1,8 @@ +import React from 'react'; +import classes from './App.module.css'; + function App() { - return
React
; + return
; } -export default App; \ No newline at end of file +export default App; diff --git a/src/App.module.css b/src/App.module.css new file mode 100644 index 0000000..c293b74 --- /dev/null +++ b/src/App.module.css @@ -0,0 +1,5 @@ +.main { + margin: 3rem auto; + width: 100%; + max-width: 40rem; + } \ No newline at end of file diff --git a/src/common/Button/Button.jsx b/src/common/Button/Button.jsx new file mode 100644 index 0000000..e69de29 diff --git a/src/common/Input/Input.jsx b/src/common/Input/Input.jsx new file mode 100644 index 0000000..e69de29 diff --git a/src/components/CourseInfo/CourseInfo.jsx b/src/components/CourseInfo/CourseInfo.jsx new file mode 100644 index 0000000..e69de29 diff --git a/src/components/CourseInfo/CourseInfo.module.css b/src/components/CourseInfo/CourseInfo.module.css new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Courses/Courses.jsx b/src/components/Courses/Courses.jsx new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Courses/Courses.module.css b/src/components/Courses/Courses.module.css new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Courses/components/CourseCard/CourseCard.jsx b/src/components/Courses/components/CourseCard/CourseCard.jsx new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Courses/components/CourseCard/CourseCard.module.css b/src/components/Courses/components/CourseCard/CourseCard.module.css new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Courses/components/SearchBar/SearchBar.jsx b/src/components/Courses/components/SearchBar/SearchBar.jsx new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Courses/components/SearchBar/SearchBar.module.css b/src/components/Courses/components/SearchBar/SearchBar.module.css new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Header/Header.jsx b/src/components/Header/Header.jsx new file mode 100644 index 0000000..beb1a5f --- /dev/null +++ b/src/components/Header/Header.jsx @@ -0,0 +1,14 @@ +import classes from './Header.module.css'; + +function Header() { + return ( +
+
+ Logo + Courses +
+
+ ); +} + +export default Header; diff --git a/src/components/Header/Header.module.css b/src/components/Header/Header.module.css new file mode 100644 index 0000000..72f50d6 --- /dev/null +++ b/src/components/Header/Header.module.css @@ -0,0 +1,23 @@ +.header { + width: 100%; + height: 5rem; + display: flex; + align-items: center; + justify-content: space-between; + background-color: #77002e; + padding: 0 10%; + } + + .logo { + font-size: 2rem; + color: white; + font-weight: bold; + } + + .badge { + background-color: #cc2062; + color: white; + border-radius: 12px; + padding: 0 1rem; + margin-left: 0.5rem; + } \ No newline at end of file diff --git a/src/components/Header/components/Logo.jsx b/src/components/Header/components/Logo.jsx new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Header/components/Logo.module.css b/src/components/Header/components/Logo.module.css new file mode 100644 index 0000000..e69de29 diff --git a/src/index.js b/src/index.jsx similarity index 78% rename from src/index.js rename to src/index.jsx index a024d30..78decd1 100644 --- a/src/index.js +++ b/src/index.jsx @@ -5,7 +5,7 @@ import App from './App'; const container = document.getElementById('root'); const root = ReactDOM.createRoot(container); root.render( - - - + + + ); From f98c7756e78d4f9de2829822c3be71c180516291 Mon Sep 17 00:00:00 2001 From: ferzik85 Date: Mon, 6 Nov 2023 16:00:35 +0100 Subject: [PATCH 02/22] change app structure --- .eslintrc.json | 3 +-- package.json | 4 +++- src/App.jsx | 7 ++++-- src/App.module.css | 5 ++++ src/common/Button/Button.jsx | 0 src/common/Input/Input.jsx | 0 src/components/CourseInfo/CourseInfo.jsx | 0 .../CourseInfo/CourseInfo.module.css | 0 src/components/Courses/Courses.jsx | 0 src/components/Courses/Courses.module.css | 0 .../components/CourseCard/CourseCard.jsx | 0 .../CourseCard/CourseCard.module.css | 0 .../components/SearchBar/SearchBar.jsx | 0 .../components/SearchBar/SearchBar.module.css | 0 src/components/Header/Header.jsx | 14 +++++++++++ src/components/Header/Header.module.css | 23 +++++++++++++++++++ src/components/Header/components/Logo.jsx | 0 .../Header/components/Logo.module.css | 0 src/{index.js => index.jsx} | 6 ++--- 19 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 src/App.module.css create mode 100644 src/common/Button/Button.jsx create mode 100644 src/common/Input/Input.jsx create mode 100644 src/components/CourseInfo/CourseInfo.jsx create mode 100644 src/components/CourseInfo/CourseInfo.module.css create mode 100644 src/components/Courses/Courses.jsx create mode 100644 src/components/Courses/Courses.module.css create mode 100644 src/components/Courses/components/CourseCard/CourseCard.jsx create mode 100644 src/components/Courses/components/CourseCard/CourseCard.module.css create mode 100644 src/components/Courses/components/SearchBar/SearchBar.jsx create mode 100644 src/components/Courses/components/SearchBar/SearchBar.module.css create mode 100644 src/components/Header/Header.jsx create mode 100644 src/components/Header/Header.module.css create mode 100644 src/components/Header/components/Logo.jsx create mode 100644 src/components/Header/components/Logo.module.css rename src/{index.js => index.jsx} (78%) diff --git a/.eslintrc.json b/.eslintrc.json index 3901202..94e801f 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -4,7 +4,7 @@ "browser": true, "es2021": true }, - "extends": ["airbnb", "react", "prettier"], + "extends": ["airbnb", "prettier"], "parserOptions": { "ecmaFeatures": { "jsx": true @@ -13,7 +13,6 @@ "sourceType": "module" }, "plugins": [ - "react", "prettier" ], "rules": { diff --git a/package.json b/package.json index 7dc5f43..efcd2d8 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,9 @@ "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", - "eject": "react-scripts eject" + "eject": "react-scripts eject", + "eslint": "eslint --ext .js --ext .jsx src", + "eslint:fix": "eslint --fix --ext .js --ext .jsx src" }, "eslintConfig": { "extends": [ diff --git a/src/App.jsx b/src/App.jsx index b0a1632..950a34e 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,5 +1,8 @@ +import React from 'react'; +import classes from './App.module.css'; + function App() { - return
React
; + return
React
; } -export default App; \ No newline at end of file +export default App; diff --git a/src/App.module.css b/src/App.module.css new file mode 100644 index 0000000..c293b74 --- /dev/null +++ b/src/App.module.css @@ -0,0 +1,5 @@ +.main { + margin: 3rem auto; + width: 100%; + max-width: 40rem; + } \ No newline at end of file diff --git a/src/common/Button/Button.jsx b/src/common/Button/Button.jsx new file mode 100644 index 0000000..e69de29 diff --git a/src/common/Input/Input.jsx b/src/common/Input/Input.jsx new file mode 100644 index 0000000..e69de29 diff --git a/src/components/CourseInfo/CourseInfo.jsx b/src/components/CourseInfo/CourseInfo.jsx new file mode 100644 index 0000000..e69de29 diff --git a/src/components/CourseInfo/CourseInfo.module.css b/src/components/CourseInfo/CourseInfo.module.css new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Courses/Courses.jsx b/src/components/Courses/Courses.jsx new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Courses/Courses.module.css b/src/components/Courses/Courses.module.css new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Courses/components/CourseCard/CourseCard.jsx b/src/components/Courses/components/CourseCard/CourseCard.jsx new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Courses/components/CourseCard/CourseCard.module.css b/src/components/Courses/components/CourseCard/CourseCard.module.css new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Courses/components/SearchBar/SearchBar.jsx b/src/components/Courses/components/SearchBar/SearchBar.jsx new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Courses/components/SearchBar/SearchBar.module.css b/src/components/Courses/components/SearchBar/SearchBar.module.css new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Header/Header.jsx b/src/components/Header/Header.jsx new file mode 100644 index 0000000..beb1a5f --- /dev/null +++ b/src/components/Header/Header.jsx @@ -0,0 +1,14 @@ +import classes from './Header.module.css'; + +function Header() { + return ( +
+
+ Logo + Courses +
+
+ ); +} + +export default Header; diff --git a/src/components/Header/Header.module.css b/src/components/Header/Header.module.css new file mode 100644 index 0000000..72f50d6 --- /dev/null +++ b/src/components/Header/Header.module.css @@ -0,0 +1,23 @@ +.header { + width: 100%; + height: 5rem; + display: flex; + align-items: center; + justify-content: space-between; + background-color: #77002e; + padding: 0 10%; + } + + .logo { + font-size: 2rem; + color: white; + font-weight: bold; + } + + .badge { + background-color: #cc2062; + color: white; + border-radius: 12px; + padding: 0 1rem; + margin-left: 0.5rem; + } \ No newline at end of file diff --git a/src/components/Header/components/Logo.jsx b/src/components/Header/components/Logo.jsx new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Header/components/Logo.module.css b/src/components/Header/components/Logo.module.css new file mode 100644 index 0000000..e69de29 diff --git a/src/index.js b/src/index.jsx similarity index 78% rename from src/index.js rename to src/index.jsx index a024d30..78decd1 100644 --- a/src/index.js +++ b/src/index.jsx @@ -5,7 +5,7 @@ import App from './App'; const container = document.getElementById('root'); const root = ReactDOM.createRoot(container); root.render( - - - + + + ); From d2e90cfbf65540d52f105e70a9e5cd6d853ff706 Mon Sep 17 00:00:00 2001 From: ferzik85 Date: Tue, 7 Nov 2023 12:05:52 +0100 Subject: [PATCH 03/22] save backbone for components without styling --- .eslintrc.json | 6 ++- .husky/pre-commit | 4 ++ package-lock.json | 23 +++++++++ package.json | 6 ++- src/App.jsx | 9 +++- src/App.module.css | 10 +++- src/assets/epam-logo.svg | 25 ++++++++++ src/common/Button/Button.jsx | 12 +++++ src/common/Button/Button.module.css | 10 ++++ src/common/Input/Input.jsx | 11 ++++ src/common/Input/Input.module.css | 10 ++++ src/components/Body/Body.jsx | 24 +++++++++ src/components/Body/Body.module.css | 3 ++ src/components/CourseInfo/CourseInfo.jsx | 41 +++++++++++++++ src/components/Courses/Courses.jsx | 28 +++++++++++ .../components/CourseCard/CourseCard.jsx | 36 +++++++++++++ .../components/SearchBar/SearchBar.jsx | 16 ++++++ .../EmptyCourseList/EmptyCourseList.jsx | 16 ++++++ .../EmptyCourseList.module.css | 0 src/components/Header/Header.jsx | 15 +++--- src/components/Header/Header.module.css | 50 ++++++++++++------- src/components/Header/components/Logo.jsx | 9 ++++ .../Header/components/Logo.module.css | 4 ++ src/data/AuthorsList.js | 20 ++++++++ src/data/CoursesList.js | 25 ++++++++++ src/utils/FormatAuthors.js | 5 ++ src/utils/FormatDate.js | 5 ++ src/utils/FormatDuration.js | 20 ++++++++ 28 files changed, 412 insertions(+), 31 deletions(-) create mode 100644 .husky/pre-commit create mode 100644 src/assets/epam-logo.svg create mode 100644 src/common/Button/Button.module.css create mode 100644 src/common/Input/Input.module.css create mode 100644 src/components/Body/Body.jsx create mode 100644 src/components/Body/Body.module.css create mode 100644 src/components/EmptyCourseList/EmptyCourseList.jsx create mode 100644 src/components/EmptyCourseList/EmptyCourseList.module.css create mode 100644 src/data/AuthorsList.js create mode 100644 src/data/CoursesList.js create mode 100644 src/utils/FormatAuthors.js create mode 100644 src/utils/FormatDate.js create mode 100644 src/utils/FormatDuration.js diff --git a/.eslintrc.json b/.eslintrc.json index 94e801f..980b11b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -16,9 +16,11 @@ "prettier" ], "rules": { + "react/prop-types": 0, + "import/prefer-default-export": "off", "prettier/prettier": [ "error", { - "printWidth": 80, + "printWidth": 160, "trailingComma": "es5", "semi": true, "jsxSingleQuote": true, @@ -37,6 +39,6 @@ "importOrderSortSpecifiers": true } ], - "no-duplicate-imports": "error" + "no-duplicate-imports": "error" } } \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..749cf1e --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npm run prepublish diff --git a/package-lock.json b/package-lock.json index 59d2ca7..4d4ae4e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "prop-types": "^15.8.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "5.0.1", @@ -27,6 +28,7 @@ "eslint-plugin-prettier": "^5.0.1", "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", + "husky": "^8.0.3", "prettier": "^3.0.3" } }, @@ -9574,6 +9576,21 @@ "node": ">=10.17.0" } }, + "node_modules/husky": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "dev": true, + "bin": { + "husky": "lib/bin.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -25176,6 +25193,12 @@ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" }, + "husky": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "dev": true + }, "iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", diff --git a/package.json b/package.json index efcd2d8..3261a02 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,10 @@ "test": "react-scripts test", "eject": "react-scripts eject", "eslint": "eslint --ext .js --ext .jsx src", - "eslint:fix": "eslint --fix --ext .js --ext .jsx src" + "eslint:fix": "eslint --fix --ext .js --ext .jsx src", + "test:nowatch": "react-scripts test --watchAll=false", + "prepare": "husky install", + "prepublish": "npm run eslint:fix" }, "eslintConfig": { "extends": [ @@ -48,6 +51,7 @@ "eslint-plugin-prettier": "^5.0.1", "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", + "husky": "^8.0.3", "prettier": "^3.0.3" } } diff --git a/src/App.jsx b/src/App.jsx index 950a34e..9ac831f 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,8 +1,15 @@ import React from 'react'; +import Header from './components/Header/Header'; +import Body from './components/Body/Body'; import classes from './App.module.css'; function App() { - return
React
; + return ( +
+
+ +
+ ); } export default App; diff --git a/src/App.module.css b/src/App.module.css index c293b74..35fd0b4 100644 --- a/src/App.module.css +++ b/src/App.module.css @@ -1,5 +1,11 @@ .main { - margin: 3rem auto; + margin: auto; + margin-top: 5px; width: 100%; - max-width: 40rem; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; } \ No newline at end of file diff --git a/src/assets/epam-logo.svg b/src/assets/epam-logo.svg new file mode 100644 index 0000000..5e4e20f --- /dev/null +++ b/src/assets/epam-logo.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + diff --git a/src/common/Button/Button.jsx b/src/common/Button/Button.jsx index e69de29..3e10a07 100644 --- a/src/common/Button/Button.jsx +++ b/src/common/Button/Button.jsx @@ -0,0 +1,12 @@ +import React from 'react'; +import classes from './Button.module.css'; + +function Button({ label }) { + return ( + + ); +} + +export default Button; diff --git a/src/common/Button/Button.module.css b/src/common/Button/Button.module.css new file mode 100644 index 0000000..69a402c --- /dev/null +++ b/src/common/Button/Button.module.css @@ -0,0 +1,10 @@ +.button { + background-color: #4CAF50; /* Green */ + border: none; + color: white; + padding: 6px 32px; + text-align: center; + text-decoration: none; + display: inline-block; + font-size: 10px; + } \ No newline at end of file diff --git a/src/common/Input/Input.jsx b/src/common/Input/Input.jsx index e69de29..d3691f2 100644 --- a/src/common/Input/Input.jsx +++ b/src/common/Input/Input.jsx @@ -0,0 +1,11 @@ +import React from 'react'; + +function Input() { + return ( +
+ +
+ ); +} + +export default Input; diff --git a/src/common/Input/Input.module.css b/src/common/Input/Input.module.css new file mode 100644 index 0000000..0567361 --- /dev/null +++ b/src/common/Input/Input.module.css @@ -0,0 +1,10 @@ +.input { + background-color: #4CAF50; /* Green */ + border: none; + color: white; + padding: 15px 32px; + text-align: center; + text-decoration: none; + display: inline-block; + font-size: 16px; + } \ No newline at end of file diff --git a/src/components/Body/Body.jsx b/src/components/Body/Body.jsx new file mode 100644 index 0000000..65a2614 --- /dev/null +++ b/src/components/Body/Body.jsx @@ -0,0 +1,24 @@ +import React from 'react'; +import Courses from '../Courses/Courses'; +import mockedCoursesList from '../../data/CoursesList'; +import mockedAuthorsList from '../../data/AuthorsList'; +import EmptyCourseList from '../EmptyCourseList/EmptyCourseList'; +import CourseInfo from '../CourseInfo/CourseInfo'; +import bodyClasses from './Body.module.css'; + +function Body() { + const courses = mockedCoursesList.map((course) => ({ + ...course, + authors: course.authors.map((authorId) => mockedAuthorsList.find((author) => author.id === authorId)?.name ?? 'Unknown author'), + })); + + return ( +
+ + + +
+ ); +} + +export default Body; diff --git a/src/components/Body/Body.module.css b/src/components/Body/Body.module.css new file mode 100644 index 0000000..b9b57cc --- /dev/null +++ b/src/components/Body/Body.module.css @@ -0,0 +1,3 @@ +.body { + background-color: grey; +} \ No newline at end of file diff --git a/src/components/CourseInfo/CourseInfo.jsx b/src/components/CourseInfo/CourseInfo.jsx index e69de29..afb7e2b 100644 --- a/src/components/CourseInfo/CourseInfo.jsx +++ b/src/components/CourseInfo/CourseInfo.jsx @@ -0,0 +1,41 @@ +import React from 'react'; +import Button from '../../common/Button/Button'; +import formatDate from '../../utils/FormatDate'; +import formatDuration from '../../utils/FormatDuration'; +import formatAuthors from '../../utils/FormatAuthors'; + +function CourseInfo({ course }) { + return ( +
+

{course.title}

+
+

Description

+

{course.description}

+
+
+

+ ID: + {course.id} +

+

+ Duration: + {formatDuration(course.duration)} +

+

+ Created: + {formatDate(course.creationDate)} +

+

+ Authors: + {formatAuthors(course.authors)} +

+

+

+
+
+ ); +} + +export default CourseInfo; diff --git a/src/components/Courses/Courses.jsx b/src/components/Courses/Courses.jsx index e69de29..3518357 100644 --- a/src/components/Courses/Courses.jsx +++ b/src/components/Courses/Courses.jsx @@ -0,0 +1,28 @@ +import React from 'react'; +import CourseCard from './components/CourseCard/CourseCard'; +import Button from '../../common/Button/Button'; +import SearchBar from './components/SearchBar/SearchBar'; + +function Courses({ courses }) { + return ( +
+ +

+

+ ); +} + +export default Courses; diff --git a/src/components/Courses/components/CourseCard/CourseCard.jsx b/src/components/Courses/components/CourseCard/CourseCard.jsx index e69de29..708d505 100644 --- a/src/components/Courses/components/CourseCard/CourseCard.jsx +++ b/src/components/Courses/components/CourseCard/CourseCard.jsx @@ -0,0 +1,36 @@ +import React from 'react'; +import Button from '../../../../common/Button/Button'; +import formatDate from '../../../../utils/FormatDate'; +import formatDuration from '../../../../utils/FormatDuration'; +import formatAuthors from '../../../../utils/FormatAuthors'; + +function CourseCard({ title, description, creationDate, duration, authors }) { + return ( +
+
+

{title}

+

{description}

+
+
+

+ Authors: + {formatAuthors(authors)} +

+

+ Duration: + {formatDuration(duration)} +

+

+ Created: + {formatDate(creationDate)} +

+

+

+
+
+ ); +} + +export default CourseCard; diff --git a/src/components/Courses/components/SearchBar/SearchBar.jsx b/src/components/Courses/components/SearchBar/SearchBar.jsx index e69de29..c4f09b5 100644 --- a/src/components/Courses/components/SearchBar/SearchBar.jsx +++ b/src/components/Courses/components/SearchBar/SearchBar.jsx @@ -0,0 +1,16 @@ +import React from 'react'; +import Button from '../../../../common/Button/Button'; +import Input from '../../../../common/Input/Input'; + +function SearchBar() { + return ( +
+

+ +

+ ); +} + +export default SearchBar; diff --git a/src/components/EmptyCourseList/EmptyCourseList.jsx b/src/components/EmptyCourseList/EmptyCourseList.jsx new file mode 100644 index 0000000..c70ba4b --- /dev/null +++ b/src/components/EmptyCourseList/EmptyCourseList.jsx @@ -0,0 +1,16 @@ +import React from 'react'; +import Button from '../../common/Button/Button'; + +function EmptyCourseList() { + return ( +
+

Course List is Empty

+

Please use "Add New Course" button to add your first course

+

+

+ ); +} + +export default EmptyCourseList; diff --git a/src/components/EmptyCourseList/EmptyCourseList.module.css b/src/components/EmptyCourseList/EmptyCourseList.module.css new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Header/Header.jsx b/src/components/Header/Header.jsx index beb1a5f..7d5cebc 100644 --- a/src/components/Header/Header.jsx +++ b/src/components/Header/Header.jsx @@ -1,13 +1,16 @@ +import React from 'react'; +import Button from '../../common/Button/Button'; import classes from './Header.module.css'; function Header() { return ( -
-
- Logo - Courses -
-
+
+

Courses

+ Sergey + +
); } diff --git a/src/components/Header/Header.module.css b/src/components/Header/Header.module.css index 72f50d6..2c9893d 100644 --- a/src/components/Header/Header.module.css +++ b/src/components/Header/Header.module.css @@ -1,23 +1,35 @@ -.header { - width: 100%; - height: 5rem; - display: flex; - align-items: center; - justify-content: space-between; - background-color: #77002e; - padding: 0 10%; + .header { + width: 70%; + height: 40px; + background-color: white; } - - .logo { - font-size: 2rem; + + .title { + vertical-align: middle; + text-align: right; + background-color: rgba(0, 0, 0, 0.432); color: white; - font-weight: bold; + padding-left: 100px; + padding-right: 10px; + padding-top: 10px; + padding-bottom: 10px; + margin-left: 30px; + margin-top: 10px; + font-size: 10px; + width: 80%; + border: 1px solid red; } - - .badge { - background-color: #cc2062; + + .headerbutton { + margin-top: 10px; + float: right; + background-color: rgba(0, 0, 0, 0.432); color: white; - border-radius: 12px; - padding: 0 1rem; - margin-left: 0.5rem; - } \ No newline at end of file + border: 1px solid red; + } + + .headerlogo { + width: 20%; + height: 100%; + float: left; + } diff --git a/src/components/Header/components/Logo.jsx b/src/components/Header/components/Logo.jsx index e69de29..7a8b463 100644 --- a/src/components/Header/components/Logo.jsx +++ b/src/components/Header/components/Logo.jsx @@ -0,0 +1,9 @@ +import React from 'react'; +import classes from './Logo.module.css'; +import logo from '../../../assets/epam-logo.svg'; + +function Logo() { + return epam-logo; +} + +export default Logo; diff --git a/src/components/Header/components/Logo.module.css b/src/components/Header/components/Logo.module.css index e69de29..5f0cb5f 100644 --- a/src/components/Header/components/Logo.module.css +++ b/src/components/Header/components/Logo.module.css @@ -0,0 +1,4 @@ +.logo { + height: 20px; + pointer-events: none; + } \ No newline at end of file diff --git a/src/data/AuthorsList.js b/src/data/AuthorsList.js new file mode 100644 index 0000000..dc6a4a5 --- /dev/null +++ b/src/data/AuthorsList.js @@ -0,0 +1,20 @@ +const mockedAuthorsList = [ + { + id: '27cc3006-e93a-4748-8ca8-73d06aa93b6d', + name: 'Vasiliy Dobkin', + }, + { + id: 'f762978b-61eb-4096-812b-ebde22838167', + name: 'Nicolas Kim', + }, + { + id: 'df32994e-b23d-497c-9e4d-84e4dc02882f', + name: 'Anna Sidorenko', + }, + { + id: '095a1817-d45b-4ed7-9cf7-b2417bcbf748', + name: 'Valentina Larina', + }, +]; + +export default mockedAuthorsList; diff --git a/src/data/CoursesList.js b/src/data/CoursesList.js new file mode 100644 index 0000000..b60b4af --- /dev/null +++ b/src/data/CoursesList.js @@ -0,0 +1,25 @@ +const mockedCoursesList = [ + { + id: 'de5aaa59-90f5-4dbc-b8a9-aaf205c551ba', + title: 'JavaScript', + description: `Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum + has been the industry's standard dummy text ever since the 1500s, when an unknown + printer took a galley of type and scrambled it to make a type specimen book. It has survived + not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.`, + creationDate: '08/03/2021', + duration: 160, + authors: ['27cc3006-e93a-4748-8ca8-73d06aa93b6d', 'f762978b-61eb-4096-812b-ebde22838167'], + }, + { + id: 'b5630fdd-7bf7-4d39-b75a-2b5906fd0916', + title: 'Angular', + description: `Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum + has been the industry's standard dummy text ever since the 1500s, when an unknown + printer took a galley of type and scrambled it to make a type specimen book.`, + creationDate: '10/11/2020', + duration: 210, + authors: ['df32994e-b23d-497c-9e4d-84e4dc02882f', '095a1817-d45b-4ed7-9cf7-b2417bcbf748'], + }, +]; + +export default mockedCoursesList; diff --git a/src/utils/FormatAuthors.js b/src/utils/FormatAuthors.js new file mode 100644 index 0000000..13a776a --- /dev/null +++ b/src/utils/FormatAuthors.js @@ -0,0 +1,5 @@ +function formatAuthors(authors) { + return authors?.join(', ') ?? ''; +} + +export default formatAuthors; diff --git a/src/utils/FormatDate.js b/src/utils/FormatDate.js new file mode 100644 index 0000000..5266336 --- /dev/null +++ b/src/utils/FormatDate.js @@ -0,0 +1,5 @@ +function formatDate(date) { + return date?.replaceAll('/', '.') ?? ''; +} + +export default formatDate; diff --git a/src/utils/FormatDuration.js b/src/utils/FormatDuration.js new file mode 100644 index 0000000..9f0dbc3 --- /dev/null +++ b/src/utils/FormatDuration.js @@ -0,0 +1,20 @@ +function formatDuration(duration) { + let hh = Math.floor(duration / 60); + let mm = Math.floor(duration % 60); + let hours = 'hours'; + if (hh === 1) { + hours = 'hour'; + } + + if (hh < 10) { + hh = `0${hh}`; + } + + if (mm < 10) { + mm = `0${mm}`; + } + + return `${hh}:${mm} ${hours}`; +} + +export default formatDuration; From d9139db6e4c57abffd179f7ed85015a8c62ca99e Mon Sep 17 00:00:00 2001 From: ferzik85 Date: Tue, 7 Nov 2023 13:25:40 +0100 Subject: [PATCH 04/22] save styles --- .eslintrc.json | 1 + src/common/Button/Button.module.css | 6 ++-- src/components/Body/Body.jsx | 5 +-- src/components/Body/Body.module.css | 5 ++- src/components/Header/Header.jsx | 14 +++++--- src/components/Header/Header.module.css | 45 +++++++++++++++---------- 6 files changed, 50 insertions(+), 26 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 980b11b..e884cd9 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -16,6 +16,7 @@ "prettier" ], "rules": { + "no-unused-vars": "off", "react/prop-types": 0, "import/prefer-default-export": "off", "prettier/prettier": [ diff --git a/src/common/Button/Button.module.css b/src/common/Button/Button.module.css index 69a402c..b4b2c90 100644 --- a/src/common/Button/Button.module.css +++ b/src/common/Button/Button.module.css @@ -1,10 +1,12 @@ .button { - background-color: #4CAF50; /* Green */ + background-color: rgb(0, 113, 155); + border-radius: 3px; border: none; color: white; padding: 6px 32px; text-align: center; text-decoration: none; display: inline-block; - font-size: 10px; + font-size: 14px; + font-weight: bold; } \ No newline at end of file diff --git a/src/components/Body/Body.jsx b/src/components/Body/Body.jsx index 65a2614..8309a6d 100644 --- a/src/components/Body/Body.jsx +++ b/src/components/Body/Body.jsx @@ -14,9 +14,10 @@ function Body() { return (
- + {/* - + */} + asdddddd
); } diff --git a/src/components/Body/Body.module.css b/src/components/Body/Body.module.css index b9b57cc..ad6d5fc 100644 --- a/src/components/Body/Body.module.css +++ b/src/components/Body/Body.module.css @@ -1,3 +1,6 @@ .body { - background-color: grey; + background-color: #E8E8E8; + min-height: 100px; + width: 100%; + border: 1px solid green; } \ No newline at end of file diff --git a/src/components/Header/Header.jsx b/src/components/Header/Header.jsx index 7d5cebc..5b39529 100644 --- a/src/components/Header/Header.jsx +++ b/src/components/Header/Header.jsx @@ -1,15 +1,21 @@ import React from 'react'; import Button from '../../common/Button/Button'; import classes from './Header.module.css'; +import Logo from './components/Logo'; function Header() { return (
-

Courses

- Sergey - +
+ + + + COURSES +
+
+ Sergey
); } diff --git a/src/components/Header/Header.module.css b/src/components/Header/Header.module.css index 2c9893d..098e7f6 100644 --- a/src/components/Header/Header.module.css +++ b/src/components/Header/Header.module.css @@ -1,35 +1,46 @@ .header { - width: 70%; - height: 40px; + display: flex; + flex-wrap: nowrap; + align-items: center; + width: 100%; + height: 80px; background-color: white; + border: 1px solid red; } - .title { + .header-title { + display: flex; + flex-wrap: nowrap; + align-items: center; vertical-align: middle; text-align: right; background-color: rgba(0, 0, 0, 0.432); color: white; - padding-left: 100px; - padding-right: 10px; - padding-top: 10px; - padding-bottom: 10px; + padding-left: 30px; + padding-right: 20px; + padding-top: 5px; + padding-bottom: 5px; margin-left: 30px; - margin-top: 10px; - font-size: 10px; - width: 80%; + font-size: 14px; border: 1px solid red; + font-weight: bold; } - .headerbutton { + .header-button { + margin-left: auto; margin-top: 10px; - float: right; - background-color: rgba(0, 0, 0, 0.432); color: white; border: 1px solid red; } - .headerlogo { - width: 20%; - height: 100%; - float: left; + .header-button span { + color: black; + margin-right: 20px; + margin-left: 10px; + font-size: 14px; + font-weight: bold; + } + + .header-logo { + margin-right: 10px; } From b494de5f8c5e6a941f2f174988cf7b658fbd2268 Mon Sep 17 00:00:00 2001 From: ferzik85 Date: Tue, 7 Nov 2023 15:36:08 +0100 Subject: [PATCH 05/22] save styles --- src/components/Body/Body.jsx | 5 +-- src/components/Courses/Courses.jsx | 7 +-- src/components/Courses/Courses.module.css | 7 +++ .../components/CourseCard/CourseCard.jsx | 13 +++--- .../CourseCard/CourseCard.module.css | 43 +++++++++++++++++++ src/components/Header/Header.module.css | 1 + 6 files changed, 64 insertions(+), 12 deletions(-) diff --git a/src/components/Body/Body.jsx b/src/components/Body/Body.jsx index 8309a6d..c0c0690 100644 --- a/src/components/Body/Body.jsx +++ b/src/components/Body/Body.jsx @@ -14,10 +14,9 @@ function Body() { return (
- {/* - + + {/* */} - asdddddd
); } diff --git a/src/components/Courses/Courses.jsx b/src/components/Courses/Courses.jsx index 3518357..21666d4 100644 --- a/src/components/Courses/Courses.jsx +++ b/src/components/Courses/Courses.jsx @@ -2,14 +2,15 @@ import React from 'react'; import CourseCard from './components/CourseCard/CourseCard'; import Button from '../../common/Button/Button'; import SearchBar from './components/SearchBar/SearchBar'; +import classes from './Courses.module.css'; function Courses({ courses }) { return ( -
- +
+ {/*

diff --git a/src/components/Courses/components/CourseCard/CourseCard.module.css b/src/components/Courses/components/CourseCard/CourseCard.module.css index e69de29..5af3c63 100644 --- a/src/components/Courses/components/CourseCard/CourseCard.module.css +++ b/src/components/Courses/components/CourseCard/CourseCard.module.css @@ -0,0 +1,43 @@ +.course-card { + width: 700px; + display: flex; + flex-wrap: nowrap; + border-left: 5px solid; + background-color: white; + border-radius: 4px; + margin: auto; + margin-top: 10px; + margin-bottom: 10px; +} + +.course-card-left { + width: 70%; + margin-right: 30px; +} + +.course-card-title { + font-weight: bold; + margin: 10px; +} + +.course-card-description { + margin: 10px; + text-align: justify; +} + +.course-card-right { + margin-top: 40px; + margin-right: 50px; + display: flex; + flex-wrap: nowrap; + flex-direction: column; + } + +.course-card-right p span { + font-weight: bold; +} + +.course-card-right-p-button { + margin-top: auto; + margin-bottom: 10px; +} \ No newline at end of file diff --git a/src/components/Header/Header.module.css b/src/components/Header/Header.module.css index 098e7f6..ed0b0f1 100644 --- a/src/components/Header/Header.module.css +++ b/src/components/Header/Header.module.css @@ -42,5 +42,6 @@ } .header-logo { + display: flex; margin-right: 10px; } From 231b24b951bb2f1d848ac5f56344e9946ab7d931 Mon Sep 17 00:00:00 2001 From: ferzik85 Date: Tue, 7 Nov 2023 16:46:38 +0100 Subject: [PATCH 06/22] save --- src/common/Input/Input.jsx | 5 +++-- src/common/Input/Input.module.css | 10 ++-------- src/components/Courses/Courses.jsx | 8 ++++---- src/components/Courses/Courses.module.css | 13 +++++++++++++ .../components/CourseCard/CourseCard.module.css | 7 +++++++ .../Courses/components/SearchBar/SearchBar.jsx | 9 ++++----- .../components/SearchBar/SearchBar.module.css | 4 ++++ 7 files changed, 37 insertions(+), 19 deletions(-) diff --git a/src/common/Input/Input.jsx b/src/common/Input/Input.jsx index d3691f2..a16d0bc 100644 --- a/src/common/Input/Input.jsx +++ b/src/common/Input/Input.jsx @@ -1,9 +1,10 @@ import React from 'react'; +import classes from './Input.module.css'; function Input() { return ( -
- +
+
); } diff --git a/src/common/Input/Input.module.css b/src/common/Input/Input.module.css index 0567361..670f48b 100644 --- a/src/common/Input/Input.module.css +++ b/src/common/Input/Input.module.css @@ -1,10 +1,4 @@ .input { - background-color: #4CAF50; /* Green */ - border: none; - color: white; - padding: 15px 32px; - text-align: center; - text-decoration: none; - display: inline-block; - font-size: 16px; + display: flex; + margin-right: 10px; } \ No newline at end of file diff --git a/src/components/Courses/Courses.jsx b/src/components/Courses/Courses.jsx index 21666d4..35f8464 100644 --- a/src/components/Courses/Courses.jsx +++ b/src/components/Courses/Courses.jsx @@ -7,10 +7,10 @@ import classes from './Courses.module.css'; function Courses({ courses }) { return (
- {/* -

+

+
{courses.map((course) => ( ))}
diff --git a/src/components/Courses/Courses.module.css b/src/components/Courses/Courses.module.css index 39ae62c..b82c303 100644 --- a/src/components/Courses/Courses.module.css +++ b/src/components/Courses/Courses.module.css @@ -4,4 +4,17 @@ flex-direction: column; width: 80%; margin: auto; +} + +.courses-header { + width: 700px; + display: flex; + flex-wrap: nowrap; + margin: auto; + margin-top: 20px; + margin-bottom: 20px; +} + +.courses-header button { + margin-left: auto; } \ No newline at end of file diff --git a/src/components/Courses/components/CourseCard/CourseCard.module.css b/src/components/Courses/components/CourseCard/CourseCard.module.css index 5af3c63..d27e53b 100644 --- a/src/components/Courses/components/CourseCard/CourseCard.module.css +++ b/src/components/Courses/components/CourseCard/CourseCard.module.css @@ -40,4 +40,11 @@ .course-card-right-p-button { margin-top: auto; margin-bottom: 10px; +} + +.course-card-right p { + width: 250px; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; } \ No newline at end of file diff --git a/src/components/Courses/components/SearchBar/SearchBar.jsx b/src/components/Courses/components/SearchBar/SearchBar.jsx index c4f09b5..8a36b64 100644 --- a/src/components/Courses/components/SearchBar/SearchBar.jsx +++ b/src/components/Courses/components/SearchBar/SearchBar.jsx @@ -1,14 +1,13 @@ import React from 'react'; import Button from '../../../../common/Button/Button'; import Input from '../../../../common/Input/Input'; +import classes from './SearchBar.module.css'; function SearchBar() { return ( -
-

- -

); } diff --git a/src/components/Courses/components/SearchBar/SearchBar.module.css b/src/components/Courses/components/SearchBar/SearchBar.module.css index e69de29..27da857 100644 --- a/src/components/Courses/components/SearchBar/SearchBar.module.css +++ b/src/components/Courses/components/SearchBar/SearchBar.module.css @@ -0,0 +1,4 @@ +.search-bar { + display: flex; + flex-wrap: nowrap; +} From c6d9c898d2a632a57653017eec110401977f574c Mon Sep 17 00:00:00 2001 From: ferzik85 Date: Tue, 7 Nov 2023 16:57:22 +0100 Subject: [PATCH 07/22] save header fix --- src/components/Header/Header.jsx | 8 +++----- src/components/Header/Header.module.css | 18 +++--------------- .../Header/components/Logo.module.css | 3 ++- 3 files changed, 8 insertions(+), 21 deletions(-) diff --git a/src/components/Header/Header.jsx b/src/components/Header/Header.jsx index 5b39529..dca7e23 100644 --- a/src/components/Header/Header.jsx +++ b/src/components/Header/Header.jsx @@ -6,12 +6,10 @@ import Logo from './components/Logo'; function Header() { return (
-
- - - - COURSES +
+
+
COURSES
Sergey
); } diff --git a/src/components/EmptyCourseList/EmptyCourseList.module.css b/src/components/EmptyCourseList/EmptyCourseList.module.css index e69de29..d788d81 100644 --- a/src/components/EmptyCourseList/EmptyCourseList.module.css +++ b/src/components/EmptyCourseList/EmptyCourseList.module.css @@ -0,0 +1,20 @@ +.empty-course-list { + display: flex; + flex-wrap: nowrap; + flex-direction: column; + width: 80%; + margin: auto; + align-items: center; + justify-content: center; +} + +.empty-course-list div { + margin: auto; + margin-top: 20px; +} + +.empty-course-list > div:first-of-type { + font-weight: bold; + margin-top: 300px; + } + \ No newline at end of file From 036ba46c9915add0178bbce9c057e6bc3d7b788b Mon Sep 17 00:00:00 2001 From: ferzik85 Date: Tue, 7 Nov 2023 17:59:00 +0100 Subject: [PATCH 10/22] style course info component --- src/components/Body/Body.jsx | 6 +-- src/components/CourseInfo/CourseInfo.jsx | 52 +++++++++--------- .../CourseInfo/CourseInfo.module.css | 54 +++++++++++++++++++ 3 files changed, 84 insertions(+), 28 deletions(-) diff --git a/src/components/Body/Body.jsx b/src/components/Body/Body.jsx index 1b08b67..9dfc814 100644 --- a/src/components/Body/Body.jsx +++ b/src/components/Body/Body.jsx @@ -14,9 +14,9 @@ function Body() { return (
- {/* */} - - {/* */} + {/* + */} +
); } diff --git a/src/components/CourseInfo/CourseInfo.jsx b/src/components/CourseInfo/CourseInfo.jsx index afb7e2b..93c5e0a 100644 --- a/src/components/CourseInfo/CourseInfo.jsx +++ b/src/components/CourseInfo/CourseInfo.jsx @@ -3,37 +3,39 @@ import Button from '../../common/Button/Button'; import formatDate from '../../utils/FormatDate'; import formatDuration from '../../utils/FormatDuration'; import formatAuthors from '../../utils/FormatAuthors'; +import classes from './CourseInfo.module.css'; function CourseInfo({ course }) { return ( -
-

{course.title}

-
-

Description

-

{course.description}

+
+
{course.title}
+
+
Description:
+
+
{course.description}
+
+

+ ID: + {course.id} +

+

+ Duration: + {formatDuration(course.duration)} +

+

+ Created: + {formatDate(course.creationDate)} +

+

+ Authors: + {formatAuthors(course.authors)} +

+
+
-

- ID: - {course.id} -

-

- Duration: - {formatDuration(course.duration)} -

-

- Created: - {formatDate(course.creationDate)} -

-

- Authors: - {formatAuthors(course.authors)} -

-

-

-
); } diff --git a/src/components/CourseInfo/CourseInfo.module.css b/src/components/CourseInfo/CourseInfo.module.css index e69de29..4e9b2f4 100644 --- a/src/components/CourseInfo/CourseInfo.module.css +++ b/src/components/CourseInfo/CourseInfo.module.css @@ -0,0 +1,54 @@ +.course-info { + display: flex; + flex-wrap: nowrap; + flex-direction: column; + width: 80%; + margin: auto; + align-items: center; + justify-content: center; +} +.course-info > div:last-of-type { + width: 100%; + text-align: right; + margin-top: 20px; +} + +.course-info-title { + font-weight: bold; + font-size: 24px; + width: 100%; + text-align: left; + margin-bottom: 20px; + margin-top: 30px; +} + +.course-description { + background-color: white; + padding: 20px; +} + +.course-description > div:first-of-type { + margin-bottom: 10px; + font-weight: bold; +} + +.course-description-layout { + display: flex; + flex-wrap: nowrap; + margin: auto; +} + +.course-description-text { + text-align: justify; + border-right: 1px solid #E8E8E8;; + padding-right: 20px; + width: 60%; +} + +p { + margin: 10px; +} + +p span { + font-weight: bold; +} \ No newline at end of file From 78fdb4ac14d7c141469fac91e363d32ddfdcce5b Mon Sep 17 00:00:00 2001 From: ferzik85 Date: Wed, 8 Nov 2023 10:16:53 +0100 Subject: [PATCH 11/22] implement show course info and return to course list --- src/common/Button/Button.jsx | 4 +-- src/components/Body/Body.jsx | 29 ++++++++++++++++--- src/components/CourseInfo/CourseInfo.jsx | 4 +-- src/components/Courses/Courses.jsx | 3 +- .../components/CourseCard/CourseCard.jsx | 4 +-- 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/common/Button/Button.jsx b/src/common/Button/Button.jsx index 3e10a07..1e81425 100644 --- a/src/common/Button/Button.jsx +++ b/src/common/Button/Button.jsx @@ -1,9 +1,9 @@ import React from 'react'; import classes from './Button.module.css'; -function Button({ label }) { +function Button({ label, onClick }) { return ( - ); diff --git a/src/components/Body/Body.jsx b/src/components/Body/Body.jsx index 9dfc814..5fb2a6a 100644 --- a/src/components/Body/Body.jsx +++ b/src/components/Body/Body.jsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState, useCallback } from 'react'; import Courses from '../Courses/Courses'; import mockedCoursesList from '../../data/CoursesList'; import mockedAuthorsList from '../../data/AuthorsList'; @@ -12,11 +12,32 @@ function Body() { authors: course.authors.map((authorId) => mockedAuthorsList.find((author) => author.id === authorId)?.name ?? 'Unknown author'), })); + const [courseId, setCourseId] = useState(null); + + const selectCourseId = useCallback( + (id) => { + setCourseId(id); + }, + [setCourseId] + ); + + const resetCourseId = useCallback(() => { + setCourseId(null); + }, [setCourseId]); + + const isCourseSelected = () => courseId !== null; + + const courseExists = () => courses.some((course) => course.id === courseId); + + const findCourse = () => courses.find((course) => course.id === courseId); + + const courseListIsEmpty = () => courses.length === 0; + + const renderCourses = () => (courseListIsEmpty() ? : ); + return (
- {/* - */} - + {isCourseSelected() && courseExists() ? : renderCourses()}
); } diff --git a/src/components/CourseInfo/CourseInfo.jsx b/src/components/CourseInfo/CourseInfo.jsx index 93c5e0a..2a4d631 100644 --- a/src/components/CourseInfo/CourseInfo.jsx +++ b/src/components/CourseInfo/CourseInfo.jsx @@ -5,7 +5,7 @@ import formatDuration from '../../utils/FormatDuration'; import formatAuthors from '../../utils/FormatAuthors'; import classes from './CourseInfo.module.css'; -function CourseInfo({ course }) { +function CourseInfo({ course, resetCourseId }) { return (
{course.title}
@@ -34,7 +34,7 @@ function CourseInfo({ course }) {
-
); diff --git a/src/components/Courses/Courses.jsx b/src/components/Courses/Courses.jsx index 35f8464..02d3d8d 100644 --- a/src/components/Courses/Courses.jsx +++ b/src/components/Courses/Courses.jsx @@ -4,7 +4,7 @@ import Button from '../../common/Button/Button'; import SearchBar from './components/SearchBar/SearchBar'; import classes from './Courses.module.css'; -function Courses({ courses }) { +function Courses({ courses, selectCourseId }) { return (
@@ -20,6 +20,7 @@ function Courses({ courses }) { creationDate={course.creationDate} duration={course.duration} authors={course.authors} + selectCourseId={selectCourseId} /> ))}
diff --git a/src/components/Courses/components/CourseCard/CourseCard.jsx b/src/components/Courses/components/CourseCard/CourseCard.jsx index 75e0f16..799593a 100644 --- a/src/components/Courses/components/CourseCard/CourseCard.jsx +++ b/src/components/Courses/components/CourseCard/CourseCard.jsx @@ -5,7 +5,7 @@ import formatDuration from '../../../../utils/FormatDuration'; import formatAuthors from '../../../../utils/FormatAuthors'; import classes from './CourseCard.module.css'; -function CourseCard({ title, description, creationDate, duration, authors }) { +function CourseCard({ id, title, description, creationDate, duration, authors, selectCourseId }) { return (
@@ -26,7 +26,7 @@ function CourseCard({ title, description, creationDate, duration, authors }) { {formatDate(creationDate)}

-

From 1f01ff8969d34852f951be2e44a6e6532f2ab1b3 Mon Sep 17 00:00:00 2001 From: ferzik85 Date: Wed, 8 Nov 2023 11:10:33 +0100 Subject: [PATCH 12/22] add course search functionality --- src/common/Button/Button.module.css | 1 + src/common/Input/Input.jsx | 4 ++-- .../CourseInfo/CourseInfo.module.css | 2 +- src/components/Courses/Courses.jsx | 16 +++++++++++++--- .../Courses/components/SearchBar/SearchBar.jsx | 18 ++++++++++++++---- src/components/Header/Header.module.css | 3 ++- src/utils/SearchCourses.js | 7 +++++++ 7 files changed, 40 insertions(+), 11 deletions(-) create mode 100644 src/utils/SearchCourses.js diff --git a/src/common/Button/Button.module.css b/src/common/Button/Button.module.css index b4b2c90..f5a44dd 100644 --- a/src/common/Button/Button.module.css +++ b/src/common/Button/Button.module.css @@ -9,4 +9,5 @@ display: inline-block; font-size: 14px; font-weight: bold; + cursor: pointer; } \ No newline at end of file diff --git a/src/common/Input/Input.jsx b/src/common/Input/Input.jsx index a16d0bc..94df6fd 100644 --- a/src/common/Input/Input.jsx +++ b/src/common/Input/Input.jsx @@ -1,10 +1,10 @@ import React from 'react'; import classes from './Input.module.css'; -function Input() { +function Input({ onChange }) { return (
- + onChange(e.target.value)} />
); } diff --git a/src/components/CourseInfo/CourseInfo.module.css b/src/components/CourseInfo/CourseInfo.module.css index 4e9b2f4..43e2d6d 100644 --- a/src/components/CourseInfo/CourseInfo.module.css +++ b/src/components/CourseInfo/CourseInfo.module.css @@ -2,7 +2,7 @@ display: flex; flex-wrap: nowrap; flex-direction: column; - width: 80%; + width: 700px; margin: auto; align-items: center; justify-content: center; diff --git a/src/components/Courses/Courses.jsx b/src/components/Courses/Courses.jsx index 02d3d8d..13d188f 100644 --- a/src/components/Courses/Courses.jsx +++ b/src/components/Courses/Courses.jsx @@ -1,17 +1,27 @@ -import React from 'react'; +import React, { useState, useCallback } from 'react'; import CourseCard from './components/CourseCard/CourseCard'; import Button from '../../common/Button/Button'; import SearchBar from './components/SearchBar/SearchBar'; +import searchCourses from '../../utils/SearchCourses'; import classes from './Courses.module.css'; function Courses({ courses, selectCourseId }) { + const [courseList, setCourses] = useState(courses); + + const submitSearchString = useCallback( + (searchString) => { + setCourses(searchCourses(searchString, courseList)); + }, + [setCourses] + ); + return (
- +
- {courses.map((course) => ( + {courseList.map((course) => ( { + setSearchValue(value); + if (!value) submitSearchString(null); + }, + [setSearchValue] + ); + return (
- -
); } diff --git a/src/components/Header/Header.module.css b/src/components/Header/Header.module.css index 0e78197..965d5b8 100644 --- a/src/components/Header/Header.module.css +++ b/src/components/Header/Header.module.css @@ -9,7 +9,8 @@ .header-title { color: black; - margin-left: 30px; + margin-bottom: 10px; + margin-left: 10px; font-size: 24px; font-weight: bold; } diff --git a/src/utils/SearchCourses.js b/src/utils/SearchCourses.js new file mode 100644 index 0000000..a788fc0 --- /dev/null +++ b/src/utils/SearchCourses.js @@ -0,0 +1,7 @@ +function searchCourses(value, courses) { + if (value === null) return courses; + const valueToSearch = value.toLowerCase(); + return courses.filter((course) => course.title.toLowerCase().indexOf(valueToSearch) !== -1 || course.id.toLowerCase().indexOf(valueToSearch) !== -1); +} + +export default searchCourses; From fd745574a0901edd1125dd11d5716b2bae65d273 Mon Sep 17 00:00:00 2001 From: ferzik85 Date: Wed, 8 Nov 2023 20:11:16 +0100 Subject: [PATCH 13/22] fix styles 1 --- src/App.module.css | 16 ++--- src/components/Header/Header.module.css | 64 +++++++++---------- .../Header/components/Logo.module.css | 1 - 3 files changed, 38 insertions(+), 43 deletions(-) diff --git a/src/App.module.css b/src/App.module.css index 35fd0b4..2d46541 100644 --- a/src/App.module.css +++ b/src/App.module.css @@ -1,11 +1,7 @@ .main { - margin: auto; - margin-top: 5px; - width: 100%; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - } \ No newline at end of file + margin: auto; + width: 100%; + font-family: "Segoe UI", sans-serif; + display: flex; + flex-direction: column; +} diff --git a/src/components/Header/Header.module.css b/src/components/Header/Header.module.css index 965d5b8..5118264 100644 --- a/src/components/Header/Header.module.css +++ b/src/components/Header/Header.module.css @@ -1,36 +1,36 @@ - .header { - display: flex; - flex-wrap: nowrap; - align-items: center; - width: 100%; - height: 80px; - background-color: white; - } +.header { + display: flex; + flex-wrap: nowrap; + align-items: center; + width: 100%; + height: 80px; + background-color: white; +} - .header-title { - color: black; - margin-bottom: 10px; - margin-left: 10px; - font-size: 24px; - font-weight: bold; - } +.header-title { + color: black; + margin-bottom: 10px; + margin-left: 10px; + font-size: 24px; + font-weight: bold; +} - .header-button { - margin-left: auto; - margin-top: 10px; - color: white; - margin-right: 10px; - } +.header-button { + margin-left: auto; + margin-top: 10px; + color: white; + margin-right: 10px; +} - .header-button span { - color: black; - margin-right: 20px; - margin-left: 10px; - font-size: 14px; - font-weight: bold; - } +.header-button span { + color: black; + margin-right: 20px; + font-size: 14px; + font-weight: bold; +} - .header-logo { - display: flex; - margin-right: 10px; - } +.header-logo { + display: flex; + margin-right: 10px; + margin-left: 10px; +} diff --git a/src/components/Header/components/Logo.module.css b/src/components/Header/components/Logo.module.css index da66552..0a84818 100644 --- a/src/components/Header/components/Logo.module.css +++ b/src/components/Header/components/Logo.module.css @@ -1,5 +1,4 @@ .logo { pointer-events: none; - margin-left: 20px; height: 40px; } \ No newline at end of file From e976d7670c15931522927764fe66d8841410f81e Mon Sep 17 00:00:00 2001 From: ferzik85 Date: Wed, 8 Nov 2023 20:23:19 +0100 Subject: [PATCH 14/22] save changes --- src/common/Button/Button.module.css | 21 ++++++++--------- src/common/Input/Input.jsx | 2 +- src/common/Input/Input.module.css | 6 ++--- src/components/Body/Body.module.css | 8 +++---- .../EmptyCourseList.module.css | 23 ++++++++----------- 5 files changed, 27 insertions(+), 33 deletions(-) diff --git a/src/common/Button/Button.module.css b/src/common/Button/Button.module.css index f5a44dd..0f9835d 100644 --- a/src/common/Button/Button.module.css +++ b/src/common/Button/Button.module.css @@ -1,13 +1,10 @@ .button { - background-color: rgb(0, 113, 155); - border-radius: 3px; - border: none; - color: white; - padding: 6px 32px; - text-align: center; - text-decoration: none; - display: inline-block; - font-size: 14px; - font-weight: bold; - cursor: pointer; - } \ No newline at end of file + background-color: rgb(0, 113, 155); + border-radius: 3px; + border: none; + color: white; + padding: 6px 32px; + font-size: 14px; + font-weight: bold; + cursor: pointer; +} diff --git a/src/common/Input/Input.jsx b/src/common/Input/Input.jsx index 94df6fd..078cc7d 100644 --- a/src/common/Input/Input.jsx +++ b/src/common/Input/Input.jsx @@ -4,7 +4,7 @@ import classes from './Input.module.css'; function Input({ onChange }) { return (
- onChange(e.target.value)} /> + onChange(e.target.value)} />
); } diff --git a/src/common/Input/Input.module.css b/src/common/Input/Input.module.css index 670f48b..3f6629b 100644 --- a/src/common/Input/Input.module.css +++ b/src/common/Input/Input.module.css @@ -1,4 +1,4 @@ .input { - display: flex; - margin-right: 10px; - } \ No newline at end of file + display: flex; + margin-right: 10px; +} diff --git a/src/components/Body/Body.module.css b/src/components/Body/Body.module.css index 28b9078..e099e88 100644 --- a/src/components/Body/Body.module.css +++ b/src/components/Body/Body.module.css @@ -1,5 +1,5 @@ .body { - background-color: #E8E8E8; - width: 100%; - height: 100vh; -} \ No newline at end of file + background-color: #e8e8e8; + width: 100%; + height: 100vh; +} diff --git a/src/components/EmptyCourseList/EmptyCourseList.module.css b/src/components/EmptyCourseList/EmptyCourseList.module.css index d788d81..0969b5d 100644 --- a/src/components/EmptyCourseList/EmptyCourseList.module.css +++ b/src/components/EmptyCourseList/EmptyCourseList.module.css @@ -1,20 +1,17 @@ .empty-course-list { - display: flex; - flex-wrap: nowrap; - flex-direction: column; - width: 80%; - margin: auto; - align-items: center; - justify-content: center; + display: flex; + flex-wrap: nowrap; + flex-direction: column; + width: 80%; + margin: auto; } .empty-course-list div { - margin: auto; - margin-top: 20px; + margin: auto; + margin-top: 20px; } .empty-course-list > div:first-of-type { - font-weight: bold; - margin-top: 300px; - } - \ No newline at end of file + font-weight: bold; + margin-top: 300px; +} From 8fe27d35318f4f3252bba559996e0f6b858dff93 Mon Sep 17 00:00:00 2001 From: ferzik85 Date: Wed, 8 Nov 2023 20:30:29 +0100 Subject: [PATCH 15/22] fix styles 2 --- .../CourseInfo/CourseInfo.module.css | 54 +++++++++--------- src/components/Courses/Courses.module.css | 26 ++++----- .../CourseCard/CourseCard.module.css | 57 +++++++++---------- .../components/SearchBar/SearchBar.module.css | 4 +- 4 files changed, 69 insertions(+), 72 deletions(-) diff --git a/src/components/CourseInfo/CourseInfo.module.css b/src/components/CourseInfo/CourseInfo.module.css index 43e2d6d..e67dbed 100644 --- a/src/components/CourseInfo/CourseInfo.module.css +++ b/src/components/CourseInfo/CourseInfo.module.css @@ -1,25 +1,23 @@ .course-info { - display: flex; - flex-wrap: nowrap; - flex-direction: column; - width: 700px; - margin: auto; - align-items: center; - justify-content: center; + display: flex; + flex-wrap: nowrap; + flex-direction: column; + width: 700px; + margin: auto; } .course-info > div:last-of-type { - width: 100%; - text-align: right; - margin-top: 20px; + width: 100%; + text-align: right; + margin-top: 20px; } .course-info-title { - font-weight: bold; - font-size: 24px; - width: 100%; - text-align: left; - margin-bottom: 20px; - margin-top: 30px; + font-weight: bold; + font-size: 24px; + width: 100%; + text-align: left; + margin-bottom: 20px; + margin-top: 30px; } .course-description { @@ -28,27 +26,27 @@ } .course-description > div:first-of-type { - margin-bottom: 10px; - font-weight: bold; + margin-bottom: 10px; + font-weight: bold; } .course-description-layout { - display: flex; - flex-wrap: nowrap; - margin: auto; + display: flex; + flex-wrap: nowrap; + margin: auto; } .course-description-text { - text-align: justify; - border-right: 1px solid #E8E8E8;; - padding-right: 20px; - width: 60%; + text-align: justify; + border-right: 1px solid #e8e8e8; + padding-right: 20px; + width: 60%; } p { - margin: 10px; + margin: 10px; } p span { - font-weight: bold; -} \ No newline at end of file + font-weight: bold; +} diff --git a/src/components/Courses/Courses.module.css b/src/components/Courses/Courses.module.css index b82c303..a4cdce0 100644 --- a/src/components/Courses/Courses.module.css +++ b/src/components/Courses/Courses.module.css @@ -1,20 +1,20 @@ .courses { - display: flex; - flex-wrap: nowrap; - flex-direction: column; - width: 80%; - margin: auto; + display: flex; + flex-wrap: nowrap; + flex-direction: column; + width: 80%; + margin: auto; } .courses-header { - width: 700px; - display: flex; - flex-wrap: nowrap; - margin: auto; - margin-top: 20px; - margin-bottom: 20px; + width: 700px; + display: flex; + flex-wrap: nowrap; + margin: auto; + margin-top: 20px; + margin-bottom: 20px; } .courses-header button { - margin-left: auto; -} \ No newline at end of file + margin-left: auto; +} diff --git a/src/components/Courses/components/CourseCard/CourseCard.module.css b/src/components/Courses/components/CourseCard/CourseCard.module.css index d27e53b..5bcb719 100644 --- a/src/components/Courses/components/CourseCard/CourseCard.module.css +++ b/src/components/Courses/components/CourseCard/CourseCard.module.css @@ -1,50 +1,49 @@ .course-card { - width: 700px; - display: flex; - flex-wrap: nowrap; - border-left: 5px solid; - background-color: white; - border-radius: 4px; - margin: auto; - margin-top: 10px; - margin-bottom: 10px; + width: 700px; + display: flex; + flex-wrap: nowrap; + border-left: 5px solid; + background-color: white; + border-radius: 4px; + margin: auto; + margin-top: 10px; + margin-bottom: 10px; } .course-card-left { - width: 70%; - margin-right: 30px; + width: 70%; + margin-right: 30px; } .course-card-title { - font-weight: bold; - margin: 10px; + font-weight: bold; + margin: 10px; } .course-card-description { - margin: 10px; - text-align: justify; + margin: 10px; + text-align: justify; } .course-card-right { - margin-top: 40px; - margin-right: 50px; - display: flex; - flex-wrap: nowrap; - flex-direction: column; - } + margin-top: 40px; + display: flex; + flex-wrap: nowrap; + flex-direction: column; +} .course-card-right p span { - font-weight: bold; + font-weight: bold; } .course-card-right-p-button { - margin-top: auto; - margin-bottom: 10px; + margin-top: auto; + margin-bottom: 10px; } .course-card-right p { - width: 250px; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; -} \ No newline at end of file + width: 250px; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; +} diff --git a/src/components/Courses/components/SearchBar/SearchBar.module.css b/src/components/Courses/components/SearchBar/SearchBar.module.css index 27da857..628ae79 100644 --- a/src/components/Courses/components/SearchBar/SearchBar.module.css +++ b/src/components/Courses/components/SearchBar/SearchBar.module.css @@ -1,4 +1,4 @@ .search-bar { - display: flex; - flex-wrap: nowrap; + display: flex; + flex-wrap: nowrap; } From 77ed1f08f64370b053aff1673b9cc04077b233ce Mon Sep 17 00:00:00 2001 From: ferzik85 Date: Wed, 8 Nov 2023 21:03:25 +0100 Subject: [PATCH 16/22] fix course info component --- src/components/CourseInfo/CourseInfo.jsx | 47 ++++++++++++------- .../CourseInfo/CourseInfo.module.css | 22 ++++++--- 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/src/components/CourseInfo/CourseInfo.jsx b/src/components/CourseInfo/CourseInfo.jsx index 2a4d631..80148a8 100644 --- a/src/components/CourseInfo/CourseInfo.jsx +++ b/src/components/CourseInfo/CourseInfo.jsx @@ -6,6 +6,17 @@ import formatAuthors from '../../utils/FormatAuthors'; import classes from './CourseInfo.module.css'; function CourseInfo({ course, resetCourseId }) { + const formatDurationInHours = (duration) => { + const formattedDuration = formatDuration(duration)?.split(' '); + const formattedTime = formattedDuration[0]; + const formattedText = formattedDuration[1]; + return ( + <> + {formattedTime} {formattedText} + + ); + }; + return (
{course.title}
@@ -13,23 +24,25 @@ function CourseInfo({ course, resetCourseId }) {
Description:
{course.description}
-
-

- ID: - {course.id} -

-

- Duration: - {formatDuration(course.duration)} -

-

- Created: - {formatDate(course.creationDate)} -

-

- Authors: - {formatAuthors(course.authors)} -

+
+ + + + + + + + + + + + + + + + + +
ID:{course.id}
Duration:{formatDurationInHours(course.duration)}
Created:{formatDate(course.creationDate)}
Authors:{formatAuthors(course.authors)}
diff --git a/src/components/CourseInfo/CourseInfo.module.css b/src/components/CourseInfo/CourseInfo.module.css index e67dbed..2335a2b 100644 --- a/src/components/CourseInfo/CourseInfo.module.css +++ b/src/components/CourseInfo/CourseInfo.module.css @@ -2,7 +2,7 @@ display: flex; flex-wrap: nowrap; flex-direction: column; - width: 700px; + width: 80%; margin: auto; } .course-info > div:last-of-type { @@ -30,6 +30,11 @@ font-weight: bold; } +tr > td:first-of-type { + margin-bottom: 10px; + font-weight: bold; +} + .course-description-layout { display: flex; flex-wrap: nowrap; @@ -40,13 +45,18 @@ text-align: justify; border-right: 1px solid #e8e8e8; padding-right: 20px; - width: 60%; + width: 50%; } -p { - margin: 10px; +.course-description-metadata { + padding-left: 20px; } -p span { - font-weight: bold; +tr td { + padding-top: 6px; + padding-bottom: 6px; +} + +tr td:last-of-type { + padding-left: 20px; } From 7bf70f27a5c088a4e97723fa5e2111f6c68b7397 Mon Sep 17 00:00:00 2001 From: ferzik85 Date: Thu, 9 Nov 2023 09:22:41 +0100 Subject: [PATCH 17/22] self review --- src/components/Courses/Courses.jsx | 7 +------ src/components/Header/components/Logo.jsx | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/components/Courses/Courses.jsx b/src/components/Courses/Courses.jsx index 13d188f..d853a62 100644 --- a/src/components/Courses/Courses.jsx +++ b/src/components/Courses/Courses.jsx @@ -8,12 +8,7 @@ import classes from './Courses.module.css'; function Courses({ courses, selectCourseId }) { const [courseList, setCourses] = useState(courses); - const submitSearchString = useCallback( - (searchString) => { - setCourses(searchCourses(searchString, courseList)); - }, - [setCourses] - ); + const submitSearchString = useCallback((searchString) => setCourses(searchCourses(searchString, courseList)), [setCourses]); return (
diff --git a/src/components/Header/components/Logo.jsx b/src/components/Header/components/Logo.jsx index 7a8b463..2aaef48 100644 --- a/src/components/Header/components/Logo.jsx +++ b/src/components/Header/components/Logo.jsx @@ -3,7 +3,7 @@ import classes from './Logo.module.css'; import logo from '../../../assets/epam-logo.svg'; function Logo() { - return epam-logo; + return epam logo; } export default Logo; From 1d5dbea2ec8cbb2e584258f18cbf308ca0e39d39 Mon Sep 17 00:00:00 2001 From: ferzik85 Date: Thu, 9 Nov 2023 09:42:16 +0100 Subject: [PATCH 18/22] self review 2 --- .eslintrc.json | 1 - src/components/Body/Body.jsx | 11 ++--------- src/components/CourseInfo/CourseInfo.jsx | 2 +- src/components/Header/components/Logo.module.css | 6 +++--- 4 files changed, 6 insertions(+), 14 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index e884cd9..980b11b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -16,7 +16,6 @@ "prettier" ], "rules": { - "no-unused-vars": "off", "react/prop-types": 0, "import/prefer-default-export": "off", "prettier/prettier": [ diff --git a/src/components/Body/Body.jsx b/src/components/Body/Body.jsx index 5fb2a6a..0feefe6 100644 --- a/src/components/Body/Body.jsx +++ b/src/components/Body/Body.jsx @@ -14,16 +14,9 @@ function Body() { const [courseId, setCourseId] = useState(null); - const selectCourseId = useCallback( - (id) => { - setCourseId(id); - }, - [setCourseId] - ); + const selectCourseId = useCallback((id) => setCourseId(id), [setCourseId]); - const resetCourseId = useCallback(() => { - setCourseId(null); - }, [setCourseId]); + const resetCourseId = useCallback(() => setCourseId(null), [setCourseId]); const isCourseSelected = () => courseId !== null; diff --git a/src/components/CourseInfo/CourseInfo.jsx b/src/components/CourseInfo/CourseInfo.jsx index 80148a8..7de7dc1 100644 --- a/src/components/CourseInfo/CourseInfo.jsx +++ b/src/components/CourseInfo/CourseInfo.jsx @@ -7,7 +7,7 @@ import classes from './CourseInfo.module.css'; function CourseInfo({ course, resetCourseId }) { const formatDurationInHours = (duration) => { - const formattedDuration = formatDuration(duration)?.split(' '); + const formattedDuration = formatDuration(duration).split(' '); const formattedTime = formattedDuration[0]; const formattedText = formattedDuration[1]; return ( diff --git a/src/components/Header/components/Logo.module.css b/src/components/Header/components/Logo.module.css index 0a84818..f62b01a 100644 --- a/src/components/Header/components/Logo.module.css +++ b/src/components/Header/components/Logo.module.css @@ -1,4 +1,4 @@ .logo { - pointer-events: none; - height: 40px; - } \ No newline at end of file + pointer-events: none; + height: 40px; +} From 74b071122a9b6f2f37d2635b149a6b46b0858470 Mon Sep 17 00:00:00 2001 From: ferzik85 Date: Mon, 13 Nov 2023 12:10:02 +0100 Subject: [PATCH 19/22] Pr feedback 1 --- src/App.module.css => public/index.css | 9 +++- public/index.html | 1 + src/App.jsx | 5 +- src/common/Button/Button.jsx | 4 +- src/common/Input/Input.jsx | 4 +- src/common/Input/Input.module.css | 5 +- src/components/Body/Body.jsx | 12 ++--- src/components/Body/Body.module.css | 3 +- src/components/CourseInfo/CourseInfo.jsx | 52 ++++++++++--------- src/components/Courses/Courses.jsx | 14 ++--- src/components/Courses/Courses.module.css | 4 +- .../components/CourseCard/CourseCard.jsx | 18 +++---- .../CourseCard/CourseCard.module.css | 18 +++---- .../components/SearchBar/SearchBar.jsx | 14 ++--- .../EmptyCourseList/EmptyCourseList.jsx | 4 +- .../EmptyCourseList.module.css | 1 - src/components/Header/Header.jsx | 10 ++-- src/components/Header/Header.module.css | 9 ++-- src/components/Header/components/Logo.jsx | 4 +- .../Header/components/Logo.module.css | 1 - src/utils/SearchCourses.js | 2 +- 21 files changed, 100 insertions(+), 94 deletions(-) rename src/App.module.css => public/index.css (61%) diff --git a/src/App.module.css b/public/index.css similarity index 61% rename from src/App.module.css rename to public/index.css index 2d46541..60ff69d 100644 --- a/src/App.module.css +++ b/public/index.css @@ -1,5 +1,12 @@ -.main { +html, +body { + height: 100%; + width: 100%; +} + +#root { margin: auto; + height: 100%; width: 100%; font-family: "Segoe UI", sans-serif; display: flex; diff --git a/public/index.html b/public/index.html index 366a547..3bec97d 100644 --- a/public/index.html +++ b/public/index.html @@ -8,6 +8,7 @@ name="description" content="Web site created using create-react-app" /> + Courses App diff --git a/src/App.jsx b/src/App.jsx index 9ac831f..ca23a6f 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,14 +1,13 @@ import React from 'react'; import Header from './components/Header/Header'; import Body from './components/Body/Body'; -import classes from './App.module.css'; function App() { return ( -
+ <>
-
+ ); } diff --git a/src/common/Button/Button.jsx b/src/common/Button/Button.jsx index 1e81425..108de03 100644 --- a/src/common/Button/Button.jsx +++ b/src/common/Button/Button.jsx @@ -1,9 +1,9 @@ import React from 'react'; -import classes from './Button.module.css'; +import styles from './Button.module.css'; function Button({ label, onClick }) { return ( - ); diff --git a/src/common/Input/Input.jsx b/src/common/Input/Input.jsx index 078cc7d..c985d29 100644 --- a/src/common/Input/Input.jsx +++ b/src/common/Input/Input.jsx @@ -1,9 +1,9 @@ import React from 'react'; -import classes from './Input.module.css'; +import styles from './Input.module.css'; function Input({ onChange }) { return ( -
+
onChange(e.target.value)} />
); diff --git a/src/common/Input/Input.module.css b/src/common/Input/Input.module.css index 3f6629b..082a3ba 100644 --- a/src/common/Input/Input.module.css +++ b/src/common/Input/Input.module.css @@ -1,4 +1,7 @@ .input { - display: flex; margin-right: 10px; } + +div input{ + height: 22px; +} diff --git a/src/components/Body/Body.jsx b/src/components/Body/Body.jsx index 0feefe6..f27c462 100644 --- a/src/components/Body/Body.jsx +++ b/src/components/Body/Body.jsx @@ -4,7 +4,7 @@ import mockedCoursesList from '../../data/CoursesList'; import mockedAuthorsList from '../../data/AuthorsList'; import EmptyCourseList from '../EmptyCourseList/EmptyCourseList'; import CourseInfo from '../CourseInfo/CourseInfo'; -import bodyClasses from './Body.module.css'; +import styles from './Body.module.css'; function Body() { const courses = mockedCoursesList.map((course) => ({ @@ -14,9 +14,9 @@ function Body() { const [courseId, setCourseId] = useState(null); - const selectCourseId = useCallback((id) => setCourseId(id), [setCourseId]); + const handleShowCourse = useCallback((id) => setCourseId(id), [setCourseId]); - const resetCourseId = useCallback(() => setCourseId(null), [setCourseId]); + const handleShowCourses = useCallback(() => setCourseId(null), [setCourseId]); const isCourseSelected = () => courseId !== null; @@ -26,11 +26,11 @@ function Body() { const courseListIsEmpty = () => courses.length === 0; - const renderCourses = () => (courseListIsEmpty() ? : ); + const renderCourses = () => (courseListIsEmpty() ? : ); return ( -
- {isCourseSelected() && courseExists() ? : renderCourses()} +
+ {isCourseSelected() && courseExists() ? : renderCourses()}
); } diff --git a/src/components/Body/Body.module.css b/src/components/Body/Body.module.css index e099e88..98bfbf1 100644 --- a/src/components/Body/Body.module.css +++ b/src/components/Body/Body.module.css @@ -1,5 +1,4 @@ .body { background-color: #e8e8e8; - width: 100%; - height: 100vh; + flex-grow: 1; } diff --git a/src/components/CourseInfo/CourseInfo.jsx b/src/components/CourseInfo/CourseInfo.jsx index 7de7dc1..cfff81c 100644 --- a/src/components/CourseInfo/CourseInfo.jsx +++ b/src/components/CourseInfo/CourseInfo.jsx @@ -3,9 +3,9 @@ import Button from '../../common/Button/Button'; import formatDate from '../../utils/FormatDate'; import formatDuration from '../../utils/FormatDuration'; import formatAuthors from '../../utils/FormatAuthors'; -import classes from './CourseInfo.module.css'; +import styles from './CourseInfo.module.css'; -function CourseInfo({ course, resetCourseId }) { +function CourseInfo({ course, onBackClick }) { const formatDurationInHours = (duration) => { const formattedDuration = formatDuration(duration).split(' '); const formattedTime = formattedDuration[0]; @@ -18,36 +18,38 @@ function CourseInfo({ course, resetCourseId }) { }; return ( -
-
{course.title}
-
+
+
{course.title}
+
Description:
-
-
{course.description}
-
+
+
{course.description}
+
- - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + +
ID:{course.id}
Duration:{formatDurationInHours(course.duration)}
Created:{formatDate(course.creationDate)}
Authors:{formatAuthors(course.authors)}
ID:{course.id}
Duration:{formatDurationInHours(course.duration)}
Created:{formatDate(course.creationDate)}
Authors:{formatAuthors(course.authors)}
-
); diff --git a/src/components/Courses/Courses.jsx b/src/components/Courses/Courses.jsx index d853a62..660836e 100644 --- a/src/components/Courses/Courses.jsx +++ b/src/components/Courses/Courses.jsx @@ -3,17 +3,17 @@ import CourseCard from './components/CourseCard/CourseCard'; import Button from '../../common/Button/Button'; import SearchBar from './components/SearchBar/SearchBar'; import searchCourses from '../../utils/SearchCourses'; -import classes from './Courses.module.css'; +import styles from './Courses.module.css'; -function Courses({ courses, selectCourseId }) { +function Courses({ courses, onShowCourseClick }) { const [courseList, setCourses] = useState(courses); - const submitSearchString = useCallback((searchString) => setCourses(searchCourses(searchString, courseList)), [setCourses]); + const handleSearchClick = useCallback((searchString) => setCourses(searchCourses(searchString, courseList)), [setCourses]); return ( -
-
- +
+
+
{courseList.map((course) => ( @@ -25,7 +25,7 @@ function Courses({ courses, selectCourseId }) { creationDate={course.creationDate} duration={course.duration} authors={course.authors} - selectCourseId={selectCourseId} + onShowCourseClick={onShowCourseClick} /> ))}
diff --git a/src/components/Courses/Courses.module.css b/src/components/Courses/Courses.module.css index a4cdce0..042e6d6 100644 --- a/src/components/Courses/Courses.module.css +++ b/src/components/Courses/Courses.module.css @@ -6,7 +6,7 @@ margin: auto; } -.courses-header { +.header { width: 700px; display: flex; flex-wrap: nowrap; @@ -15,6 +15,6 @@ margin-bottom: 20px; } -.courses-header button { +.header button { margin-left: auto; } diff --git a/src/components/Courses/components/CourseCard/CourseCard.jsx b/src/components/Courses/components/CourseCard/CourseCard.jsx index 799593a..4af6faa 100644 --- a/src/components/Courses/components/CourseCard/CourseCard.jsx +++ b/src/components/Courses/components/CourseCard/CourseCard.jsx @@ -3,16 +3,16 @@ import Button from '../../../../common/Button/Button'; import formatDate from '../../../../utils/FormatDate'; import formatDuration from '../../../../utils/FormatDuration'; import formatAuthors from '../../../../utils/FormatAuthors'; -import classes from './CourseCard.module.css'; +import styles from './CourseCard.module.css'; -function CourseCard({ id, title, description, creationDate, duration, authors, selectCourseId }) { +function CourseCard({ id, title, description, creationDate, duration, authors, onShowCourseClick }) { return ( -
-
-

{title}

-

{description}

+
+
+

{title}

+

{description}

-
+

Authors: {formatAuthors(authors)} @@ -25,8 +25,8 @@ function CourseCard({ id, title, description, creationDate, duration, authors, s Created: {formatDate(creationDate)}

-

-

diff --git a/src/components/Courses/components/CourseCard/CourseCard.module.css b/src/components/Courses/components/CourseCard/CourseCard.module.css index 5bcb719..e30724c 100644 --- a/src/components/Courses/components/CourseCard/CourseCard.module.css +++ b/src/components/Courses/components/CourseCard/CourseCard.module.css @@ -1,7 +1,6 @@ -.course-card { +.card { width: 700px; display: flex; - flex-wrap: nowrap; border-left: 5px solid; background-color: white; border-radius: 4px; @@ -10,38 +9,37 @@ margin-bottom: 10px; } -.course-card-left { +.left { width: 70%; margin-right: 30px; } -.course-card-title { +.title { font-weight: bold; margin: 10px; } -.course-card-description { +.description { margin: 10px; text-align: justify; } -.course-card-right { +.right { margin-top: 40px; display: flex; - flex-wrap: nowrap; flex-direction: column; } -.course-card-right p span { +.right p span { font-weight: bold; } -.course-card-right-p-button { +.card-button { margin-top: auto; margin-bottom: 10px; } -.course-card-right p { +.right p { width: 250px; white-space: nowrap; text-overflow: ellipsis; diff --git a/src/components/Courses/components/SearchBar/SearchBar.jsx b/src/components/Courses/components/SearchBar/SearchBar.jsx index 436a44e..4cb4800 100644 --- a/src/components/Courses/components/SearchBar/SearchBar.jsx +++ b/src/components/Courses/components/SearchBar/SearchBar.jsx @@ -1,23 +1,23 @@ import React, { useState, useCallback } from 'react'; import Button from '../../../../common/Button/Button'; import Input from '../../../../common/Input/Input'; -import classes from './SearchBar.module.css'; +import styles from './SearchBar.module.css'; -function SearchBar({ submitSearchString }) { +function SearchBar({ onSearchClick }) { const [searchValue, setSearchValue] = useState(null); - const handleSearchValueChange = useCallback( + const handleChange = useCallback( (value) => { setSearchValue(value); - if (!value) submitSearchString(null); + if (!value) onSearchClick(null); }, [setSearchValue] ); return ( -
- -
); } diff --git a/src/components/EmptyCourseList/EmptyCourseList.jsx b/src/components/EmptyCourseList/EmptyCourseList.jsx index 7f0d882..12e33e7 100644 --- a/src/components/EmptyCourseList/EmptyCourseList.jsx +++ b/src/components/EmptyCourseList/EmptyCourseList.jsx @@ -1,10 +1,10 @@ import React from 'react'; import Button from '../../common/Button/Button'; -import classes from './EmptyCourseList.module.css'; +import styles from './EmptyCourseList.module.css'; function EmptyCourseList() { return ( -
+
Course List is Empty
Please use "Add New Course" button to add your first course
diff --git a/src/components/EmptyCourseList/EmptyCourseList.module.css b/src/components/EmptyCourseList/EmptyCourseList.module.css index 0969b5d..5cf5774 100644 --- a/src/components/EmptyCourseList/EmptyCourseList.module.css +++ b/src/components/EmptyCourseList/EmptyCourseList.module.css @@ -1,6 +1,5 @@ .empty-course-list { display: flex; - flex-wrap: nowrap; flex-direction: column; width: 80%; margin: auto; diff --git a/src/components/Header/Header.jsx b/src/components/Header/Header.jsx index dca7e23..f1b235d 100644 --- a/src/components/Header/Header.jsx +++ b/src/components/Header/Header.jsx @@ -1,16 +1,16 @@ import React from 'react'; import Button from '../../common/Button/Button'; -import classes from './Header.module.css'; +import styles from './Header.module.css'; import Logo from './components/Logo'; function Header() { return ( -
-
+
+
-
COURSES
-
+
COURSES
+
Sergey
diff --git a/src/components/Header/Header.module.css b/src/components/Header/Header.module.css index 5118264..5f81d38 100644 --- a/src/components/Header/Header.module.css +++ b/src/components/Header/Header.module.css @@ -1,13 +1,12 @@ .header { display: flex; - flex-wrap: nowrap; align-items: center; width: 100%; height: 80px; background-color: white; } -.header-title { +.title { color: black; margin-bottom: 10px; margin-left: 10px; @@ -15,21 +14,21 @@ font-weight: bold; } -.header-button { +.button { margin-left: auto; margin-top: 10px; color: white; margin-right: 10px; } -.header-button span { +.button span { color: black; margin-right: 20px; font-size: 14px; font-weight: bold; } -.header-logo { +.logo { display: flex; margin-right: 10px; margin-left: 10px; diff --git a/src/components/Header/components/Logo.jsx b/src/components/Header/components/Logo.jsx index 2aaef48..25f5929 100644 --- a/src/components/Header/components/Logo.jsx +++ b/src/components/Header/components/Logo.jsx @@ -1,9 +1,9 @@ import React from 'react'; -import classes from './Logo.module.css'; +import styles from './Logo.module.css'; import logo from '../../../assets/epam-logo.svg'; function Logo() { - return epam logo; + return epam logo; } export default Logo; diff --git a/src/components/Header/components/Logo.module.css b/src/components/Header/components/Logo.module.css index f62b01a..ed74c80 100644 --- a/src/components/Header/components/Logo.module.css +++ b/src/components/Header/components/Logo.module.css @@ -1,4 +1,3 @@ .logo { - pointer-events: none; height: 40px; } diff --git a/src/utils/SearchCourses.js b/src/utils/SearchCourses.js index a788fc0..61fe2af 100644 --- a/src/utils/SearchCourses.js +++ b/src/utils/SearchCourses.js @@ -1,7 +1,7 @@ function searchCourses(value, courses) { if (value === null) return courses; const valueToSearch = value.toLowerCase(); - return courses.filter((course) => course.title.toLowerCase().indexOf(valueToSearch) !== -1 || course.id.toLowerCase().indexOf(valueToSearch) !== -1); + return courses.filter((course) => course.title.toLowerCase().includes(valueToSearch) || course.id.toLowerCase().includes(valueToSearch)); } export default searchCourses; From a65d30daf4fe26efbde926904ad2f4df1695244e Mon Sep 17 00:00:00 2001 From: ferzik85 Date: Mon, 13 Nov 2023 12:22:40 +0100 Subject: [PATCH 20/22] fix input css --- src/common/Input/Input.jsx | 6 +----- src/common/Input/Input.module.css | 4 ---- src/components/Courses/components/SearchBar/SearchBar.jsx | 4 +++- .../Courses/components/SearchBar/SearchBar.module.css | 5 ++++- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/common/Input/Input.jsx b/src/common/Input/Input.jsx index c985d29..81aff73 100644 --- a/src/common/Input/Input.jsx +++ b/src/common/Input/Input.jsx @@ -2,11 +2,7 @@ import React from 'react'; import styles from './Input.module.css'; function Input({ onChange }) { - return ( -
- onChange(e.target.value)} /> -
- ); + return onChange(e.target.value)} />; } export default Input; diff --git a/src/common/Input/Input.module.css b/src/common/Input/Input.module.css index 082a3ba..97d331c 100644 --- a/src/common/Input/Input.module.css +++ b/src/common/Input/Input.module.css @@ -1,7 +1,3 @@ .input { - margin-right: 10px; -} - -div input{ height: 22px; } diff --git a/src/components/Courses/components/SearchBar/SearchBar.jsx b/src/components/Courses/components/SearchBar/SearchBar.jsx index 4cb4800..9ad92c1 100644 --- a/src/components/Courses/components/SearchBar/SearchBar.jsx +++ b/src/components/Courses/components/SearchBar/SearchBar.jsx @@ -16,7 +16,9 @@ function SearchBar({ onSearchClick }) { return (
- +
+ +
); diff --git a/src/components/Courses/components/SearchBar/SearchBar.module.css b/src/components/Courses/components/SearchBar/SearchBar.module.css index 628ae79..dfc0142 100644 --- a/src/components/Courses/components/SearchBar/SearchBar.module.css +++ b/src/components/Courses/components/SearchBar/SearchBar.module.css @@ -1,4 +1,7 @@ .search-bar { display: flex; - flex-wrap: nowrap; } + +.input { + margin-right: 10px; +} \ No newline at end of file From 0fff6a463b7a715ef51f39accfa70b545f3ba43a Mon Sep 17 00:00:00 2001 From: ferzik85 Date: Mon, 13 Nov 2023 12:48:30 +0100 Subject: [PATCH 21/22] PR feedback 2 --- src/components/CourseInfo/CourseInfo.jsx | 12 ++++---- .../CourseInfo/CourseInfo.module.css | 18 +++++------ .../components/CourseCard/CourseCard.jsx | 6 ++-- .../CourseCard/CourseCard.module.css | 30 +++++++++---------- .../components/SearchBar/SearchBar.jsx | 4 +-- .../components/SearchBar/SearchBar.module.css | 4 +-- .../EmptyCourseList/EmptyCourseList.jsx | 2 +- .../EmptyCourseList.module.css | 6 ++-- 8 files changed, 40 insertions(+), 42 deletions(-) diff --git a/src/components/CourseInfo/CourseInfo.jsx b/src/components/CourseInfo/CourseInfo.jsx index cfff81c..d08ef95 100644 --- a/src/components/CourseInfo/CourseInfo.jsx +++ b/src/components/CourseInfo/CourseInfo.jsx @@ -18,13 +18,13 @@ function CourseInfo({ course, onBackClick }) { }; return ( -
-
{course.title}
-
+
+
{course.title}
+
Description:
-
-
{course.description}
-
+
+
{course.description}
+
diff --git a/src/components/CourseInfo/CourseInfo.module.css b/src/components/CourseInfo/CourseInfo.module.css index 2335a2b..8686deb 100644 --- a/src/components/CourseInfo/CourseInfo.module.css +++ b/src/components/CourseInfo/CourseInfo.module.css @@ -1,17 +1,16 @@ -.course-info { +.courseInfo { display: flex; - flex-wrap: nowrap; flex-direction: column; width: 80%; margin: auto; } -.course-info > div:last-of-type { +.courseInfo > div:last-of-type { width: 100%; text-align: right; margin-top: 20px; } -.course-info-title { +.courseInfoTitle { font-weight: bold; font-size: 24px; width: 100%; @@ -20,12 +19,12 @@ margin-top: 30px; } -.course-description { +.courseDescription { background-color: white; padding: 20px; } -.course-description > div:first-of-type { +.courseDescription > div:first-of-type { margin-bottom: 10px; font-weight: bold; } @@ -35,20 +34,19 @@ tr > td:first-of-type { font-weight: bold; } -.course-description-layout { +.courseDescriptionLayout { display: flex; - flex-wrap: nowrap; margin: auto; } -.course-description-text { +.courseDescriptionText { text-align: justify; border-right: 1px solid #e8e8e8; padding-right: 20px; width: 50%; } -.course-description-metadata { +.courseDescriptionMetadata { padding-left: 20px; } diff --git a/src/components/Courses/components/CourseCard/CourseCard.jsx b/src/components/Courses/components/CourseCard/CourseCard.jsx index 4af6faa..2a93adb 100644 --- a/src/components/Courses/components/CourseCard/CourseCard.jsx +++ b/src/components/Courses/components/CourseCard/CourseCard.jsx @@ -8,11 +8,11 @@ import styles from './CourseCard.module.css'; function CourseCard({ id, title, description, creationDate, duration, authors, onShowCourseClick }) { return (
-
+

{title}

{description}

-
+

Authors: {formatAuthors(authors)} @@ -25,7 +25,7 @@ function CourseCard({ id, title, description, creationDate, duration, authors, o Created: {formatDate(creationDate)}

-

+

diff --git a/src/components/Courses/components/CourseCard/CourseCard.module.css b/src/components/Courses/components/CourseCard/CourseCard.module.css index e30724c..ed6ad53 100644 --- a/src/components/Courses/components/CourseCard/CourseCard.module.css +++ b/src/components/Courses/components/CourseCard/CourseCard.module.css @@ -9,11 +9,6 @@ margin-bottom: 10px; } -.left { - width: 70%; - margin-right: 30px; -} - .title { font-weight: bold; margin: 10px; @@ -24,24 +19,29 @@ text-align: justify; } -.right { +.cardLeft { + width: 70%; + margin-right: 30px; +} + +.cardRight { margin-top: 40px; display: flex; flex-direction: column; } -.right p span { +.cardRight p { + width: 250px; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; +} + +.cardRight p span { font-weight: bold; } -.card-button { +.cardButton { margin-top: auto; margin-bottom: 10px; } - -.right p { - width: 250px; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; -} diff --git a/src/components/Courses/components/SearchBar/SearchBar.jsx b/src/components/Courses/components/SearchBar/SearchBar.jsx index 9ad92c1..000fcf8 100644 --- a/src/components/Courses/components/SearchBar/SearchBar.jsx +++ b/src/components/Courses/components/SearchBar/SearchBar.jsx @@ -15,8 +15,8 @@ function SearchBar({ onSearchClick }) { ); return ( -
-
+
+