├── .babelrc
├── .eslintrc.json
├── .github
└── workflows
│ └── linters.yml
├── .gitignore
├── .stylelintrc.json
├── LICENSE
├── README.md
├── package-lock.json
├── package.json
├── public
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
└── robots.txt
└── src
├── App.js
├── __tests__
├── Calculator.test.js
├── Home.test.js
├── Items.test.js
├── Navbar.test.js
├── Quotes.spec.js
└── __snapshots__
│ ├── Calculator.test.js.snap
│ ├── Home.test.js.snap
│ ├── Items.test.js.snap
│ ├── Navbar.test.js.snap
│ └── Quotes.spec.js.snap
├── components
├── Calculator.css
├── Calculator.js
├── Home.js
├── Items.js
├── Navbar.css
├── Navbar.js
├── Quotes.js
└── logic
│ ├── calculate.js
│ ├── calculate.test.js
│ ├── operate.js
│ └── operate.test.js
├── index.css
└── index.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/preset-react"
4 | ],
5 | "plugins": ["@babel/plugin-syntax-jsx"]
6 | }
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "es6": true,
5 | "jest": true
6 | },
7 | "parser": "@babel/eslint-parser",
8 | "parserOptions": {
9 | "ecmaFeatures": {
10 | "jsx": true
11 | },
12 | "ecmaVersion": 2018,
13 | "sourceType": "module"
14 | },
15 | "extends": ["airbnb", "plugin:react/recommended"],
16 | "plugins": ["react"],
17 | "rules": {
18 | "react/jsx-filename-extension": ["warn", { "extensions": [".js", ".jsx"] }],
19 | "react/react-in-jsx-scope": "off",
20 | "import/no-unresolved": "off",
21 | "no-shadow": "off"
22 | },
23 | "ignorePatterns": [
24 | "dist/",
25 | "build/"
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/.github/workflows/linters.yml:
--------------------------------------------------------------------------------
1 | name: Linters
2 |
3 | on: pull_request
4 |
5 | env:
6 | FORCE_COLOR: 1
7 |
8 | jobs:
9 | eslint:
10 | name: ESLint
11 | runs-on: ubuntu-18.04
12 | steps:
13 | - uses: actions/checkout@v2
14 | - uses: actions/setup-node@v1
15 | with:
16 | node-version: "12.x"
17 | - name: Setup ESLint
18 | run: |
19 | npm install --save-dev eslint@7.x eslint-config-airbnb@18.x eslint-plugin-import@2.x eslint-plugin-jsx-a11y@6.x eslint-plugin-react@7.x eslint-plugin-react-hooks@4.x @babel/eslint-parser@7.x @babel/core@7.x @babel/plugin-syntax-jsx@7.x @babel/preset-env@7.x @babel/preset-react@7.x
20 | [ -f .eslintrc.json ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/react-redux/.eslintrc.json
21 | [ -f .babelrc ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/react-redux/.babelrc
22 | - name: ESLint Report
23 | run: npx eslint .
24 | stylelint:
25 | name: Stylelint
26 | runs-on: ubuntu-18.04
27 | steps:
28 | - uses: actions/checkout@v2
29 | - uses: actions/setup-node@v1
30 | with:
31 | node-version: "12.x"
32 | - name: Setup Stylelint
33 | run: |
34 | npm install --save-dev stylelint@13.x stylelint-scss@3.x stylelint-config-standard@21.x stylelint-csstree-validator@1.x
35 | [ -f .stylelintrc.json ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/react-redux/.stylelintrc.json
36 | - name: Stylelint Report
37 | run: npx stylelint "**/*.{css,scss}"
38 | nodechecker:
39 | name: node_modules checker
40 | runs-on: ubuntu-18.04
41 | steps:
42 | - uses: actions/checkout@v2
43 | - name: Check node_modules existence
44 | run: |
45 | if [ -d "node_modules/" ]; then echo -e "\e[1;31mThe node_modules/ folder was pushed to the repo. Please remove it from the GitHub repository and try again."; echo -e "\e[1;32mYou can set up a .gitignore file with this folder included on it to prevent this from happening in the future." && exit 1; fi
46 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.stylelintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["stylelint-config-standard"],
3 | "plugins": ["stylelint-scss", "stylelint-csstree-validator"],
4 | "rules": {
5 | "at-rule-no-unknown": [
6 | true,
7 | {
8 | "ignoreAtRules": ["tailwind", "apply", "variants", "responsive", "screen"]
9 | }
10 | ],
11 | "scss/at-rule-no-unknown": [
12 | true,
13 | {
14 | "ignoreAtRules": ["tailwind", "apply", "variants", "responsive", "screen"]
15 | }
16 | ],
17 | "csstree/validator": true
18 | },
19 | "ignoreFiles": ["build/**", "dist/**", "**/reset*.css", "**/bootstrap*.css", "**/*.js", "**/*.jsx"]
20 | }
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Fayob
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Math Magician React Project
2 |
3 | ## Description
4 |
5 | "Math magicians" is a website for all fans of mathematics. It is a Single Page App (SPA) that allows users to:
6 | - Make simple calculations.
7 | - Read a random math-related quote.
8 |
9 | This project was based on learning React.
10 |
11 | ## Live Demo
12 |
13 | [Checkout the deployed app here](https://math-magician-app-by-fayob.netlify.app/)
14 |
15 | # Getting Started with Create React App
16 |
17 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
18 |
19 | ### Directory
20 |
21 | - This directory can be clone using `git clone git@github.com:Fayob/maths-magician-app.git`
22 |
23 | ## Available Scripts
24 |
25 | In the project directory, you can run:
26 |
27 | - `npm install` to install all dependencies
28 |
29 | - `npm start` to spin up the app in your web browser.
30 |
31 | ## Learn More
32 |
33 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
34 |
35 | To learn React, check out the [React documentation](https://reactjs.org/).
36 |
37 | ## Author
38 |
39 | 👨 Abimbola Favour Adedeji
40 |
41 | GitHub: [@fayob](https://github.com/fayob)
42 |
43 | Twitter: [@fabimworld2536](https://twitter.com/Fabimworld2536)
44 |
45 | LinkedIn: [@abimbola-ade](https://www.linkedin.com/in/abimbola-ade)
46 |
47 | ## Contributing
48 |
49 | Contributions, issues, and feature requests are welcome! Feel free to check the [issues page](#).
50 |
51 | ## Show your support
52 |
53 | Give a ⭐️ if you like this project!
54 |
55 | ## License
56 |
57 | This project is [MIT](./LICENSE) licensed.
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "math-app",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.16.5",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "big-js": "^3.1.3",
10 | "prop-types": "^15.8.1",
11 | "react": "^18.2.0",
12 | "react-dom": "^18.2.0",
13 | "react-router-dom": "^6.4.2",
14 | "react-scripts": "5.0.1",
15 | "web-vitals": "^2.1.4"
16 | },
17 | "scripts": {
18 | "start": "react-scripts start",
19 | "build": "react-scripts build",
20 | "test": "react-scripts test",
21 | "eject": "react-scripts eject"
22 | },
23 | "eslintConfig": {
24 | "extends": [
25 | "react-app",
26 | "react-app/jest"
27 | ]
28 | },
29 | "browserslist": {
30 | "production": [
31 | ">0.2%",
32 | "not dead",
33 | "not op_mini all"
34 | ],
35 | "development": [
36 | "last 1 chrome version",
37 | "last 1 firefox version",
38 | "last 1 safari version"
39 | ]
40 | },
41 | "devDependencies": {
42 | "@babel/core": "^7.19.6",
43 | "@babel/eslint-parser": "^7.19.1",
44 | "@babel/plugin-syntax-jsx": "^7.18.6",
45 | "@babel/preset-react": "^7.18.6",
46 | "eslint": "^7.32.0",
47 | "eslint-config-airbnb": "^18.2.1",
48 | "eslint-plugin-import": "^2.26.0",
49 | "eslint-plugin-jsx-a11y": "^6.6.1",
50 | "eslint-plugin-react": "^7.31.10",
51 | "eslint-plugin-react-hooks": "^4.6.0",
52 | "jest-watch-typeahead": "^0.6.5",
53 | "stylelint": "^13.13.1",
54 | "stylelint-config-standard": "^21.0.0",
55 | "stylelint-csstree-validator": "^1.9.0",
56 | "stylelint-scss": "^3.21.0"
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MohamedHNoor/maths-magician-app/ea7618fc49c8e419640fbf43cf274f97526b5225/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | Math Magicians App
28 |
29 |
30 | You need to enable JavaScript to run this app.
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MohamedHNoor/maths-magician-app/ea7618fc49c8e419640fbf43cf274f97526b5225/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MohamedHNoor/maths-magician-app/ea7618fc49c8e419640fbf43cf274f97526b5225/public/logo512.png
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
3 | import Navbar from './components/Navbar';
4 | import Calculator from './components/Calculator';
5 | import Home from './components/Home';
6 | import Quotes from './components/Quotes';
7 |
8 | const App = () => (
9 | <>
10 |
11 |
12 |
13 | } />
14 | } />
15 | } />
16 |
17 |
18 | >
19 |
20 | );
21 |
22 | export default App;
23 |
--------------------------------------------------------------------------------
/src/__tests__/Calculator.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render, screen } from '@testing-library/react';
3 | import '@testing-library/jest-dom';
4 |
5 | import Calculator from '../components/Calculator';
6 |
7 | describe('test for Calculator Component', () => {
8 | it('should render Calculator Component', () => {
9 | expect(render( )).toMatchSnapshot();
10 | });
11 |
12 | it('should render Calculator Component', () => {
13 | render( );
14 | expect(screen.getByText('Let`s do some math!')).not.toBeNull();
15 | expect(screen.queryByText('8')).toBeInTheDocument();
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/src/__tests__/Home.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render, screen } from '@testing-library/react';
3 |
4 | import Home from '../components/Home';
5 |
6 | describe('test for Home Component', () => {
7 | it('should render Home Component', () => {
8 | expect(render( )).toMatchSnapshot();
9 | });
10 |
11 | it('should query text content', () => {
12 | render( );
13 | screen.debug();
14 |
15 | expect(screen.queryByText(/Welcome to our page!/)).not.toBeNull();
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/src/__tests__/Items.test.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-vars */
2 | import React from 'react';
3 | import { render, screen, fireEvent } from '@testing-library/react';
4 |
5 | import Item from '../components/Items';
6 |
7 | const onClickHandler = jest.fn();
8 |
9 | describe('test for Item Component', () => {
10 | it('should render Item component', () => {
11 | expect(render( )).toMatchSnapshot();
12 | });
13 |
14 | it('should test for click event', () => {
15 | render(
16 | ,
17 | );
18 |
19 | fireEvent.click(screen.getByText('AC'));
20 | fireEvent.click(screen.getByText('AC'));
21 | fireEvent.click(screen.getByText('AC'));
22 | fireEvent.click(screen.getByText('AC'));
23 |
24 | expect(onClickHandler).toHaveBeenCalledTimes(4);
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/src/__tests__/Navbar.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from '@testing-library/react';
3 | import { BrowserRouter } from 'react-router-dom';
4 |
5 | import Navbar from '../components/Navbar';
6 |
7 | describe('test for Navbar Component', () => {
8 | it('should render Navbar Component', () => {
9 | expect(render( , { wrapper: BrowserRouter })).toMatchSnapshot();
10 | });
11 | });
12 |
--------------------------------------------------------------------------------
/src/__tests__/Quotes.spec.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import Quotes from '../components/Quotes';
5 |
6 | describe('test for Quotes Component', () => {
7 | it('should render Quotes Component', () => {
8 | expect(render( )).toMatchSnapshot();
9 | });
10 | });
11 |
--------------------------------------------------------------------------------
/src/__tests__/__snapshots__/Calculator.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`test for Calculator Component should render Calculator Component 1`] = `
4 | Object {
5 | "asFragment": [Function],
6 | "baseElement":
7 |
8 |
11 |
12 | Let\`s do some math!
13 |
14 |
17 |
22 |
25 | AC
26 |
27 |
30 | +/-
31 |
32 |
35 | %
36 |
37 |
40 | ÷
41 |
42 |
45 | x
46 |
47 |
50 | -
51 |
52 |
55 | +
56 |
57 |
60 | =
61 |
62 |
65 | 1
66 |
67 |
70 | 2
71 |
72 |
75 | 3
76 |
77 |
80 | 4
81 |
82 |
85 | 5
86 |
87 |
90 | 6
91 |
92 |
95 | 7
96 |
97 |
100 | 8
101 |
102 |
105 | 9
106 |
107 |
110 | 0
111 |
112 |
115 | .
116 |
117 |
118 |
119 |
120 | ,
121 | "container":
122 |
125 |
126 | Let\`s do some math!
127 |
128 |
131 |
136 |
139 | AC
140 |
141 |
144 | +/-
145 |
146 |
149 | %
150 |
151 |
154 | ÷
155 |
156 |
159 | x
160 |
161 |
164 | -
165 |
166 |
169 | +
170 |
171 |
174 | =
175 |
176 |
179 | 1
180 |
181 |
184 | 2
185 |
186 |
189 | 3
190 |
191 |
194 | 4
195 |
196 |
199 | 5
200 |
201 |
204 | 6
205 |
206 |
209 | 7
210 |
211 |
214 | 8
215 |
216 |
219 | 9
220 |
221 |
224 | 0
225 |
226 |
229 | .
230 |
231 |
232 |
233 |
,
234 | "debug": [Function],
235 | "findAllByAltText": [Function],
236 | "findAllByDisplayValue": [Function],
237 | "findAllByLabelText": [Function],
238 | "findAllByPlaceholderText": [Function],
239 | "findAllByRole": [Function],
240 | "findAllByTestId": [Function],
241 | "findAllByText": [Function],
242 | "findAllByTitle": [Function],
243 | "findByAltText": [Function],
244 | "findByDisplayValue": [Function],
245 | "findByLabelText": [Function],
246 | "findByPlaceholderText": [Function],
247 | "findByRole": [Function],
248 | "findByTestId": [Function],
249 | "findByText": [Function],
250 | "findByTitle": [Function],
251 | "getAllByAltText": [Function],
252 | "getAllByDisplayValue": [Function],
253 | "getAllByLabelText": [Function],
254 | "getAllByPlaceholderText": [Function],
255 | "getAllByRole": [Function],
256 | "getAllByTestId": [Function],
257 | "getAllByText": [Function],
258 | "getAllByTitle": [Function],
259 | "getByAltText": [Function],
260 | "getByDisplayValue": [Function],
261 | "getByLabelText": [Function],
262 | "getByPlaceholderText": [Function],
263 | "getByRole": [Function],
264 | "getByTestId": [Function],
265 | "getByText": [Function],
266 | "getByTitle": [Function],
267 | "queryAllByAltText": [Function],
268 | "queryAllByDisplayValue": [Function],
269 | "queryAllByLabelText": [Function],
270 | "queryAllByPlaceholderText": [Function],
271 | "queryAllByRole": [Function],
272 | "queryAllByTestId": [Function],
273 | "queryAllByText": [Function],
274 | "queryAllByTitle": [Function],
275 | "queryByAltText": [Function],
276 | "queryByDisplayValue": [Function],
277 | "queryByLabelText": [Function],
278 | "queryByPlaceholderText": [Function],
279 | "queryByRole": [Function],
280 | "queryByTestId": [Function],
281 | "queryByText": [Function],
282 | "queryByTitle": [Function],
283 | "rerender": [Function],
284 | "unmount": [Function],
285 | }
286 | `;
287 |
--------------------------------------------------------------------------------
/src/__tests__/__snapshots__/Home.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`test for Home Component should render Home Component 1`] = `
4 | Object {
5 | "asFragment": [Function],
6 | "baseElement":
7 |
8 |
11 |
12 | Welcome to our page!
13 |
14 |
15 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
16 |
17 |
18 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
19 |
20 |
21 |
22 | ,
23 | "container":
24 |
27 |
28 | Welcome to our page!
29 |
30 |
31 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
32 |
33 |
34 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
35 |
36 |
37 |
,
38 | "debug": [Function],
39 | "findAllByAltText": [Function],
40 | "findAllByDisplayValue": [Function],
41 | "findAllByLabelText": [Function],
42 | "findAllByPlaceholderText": [Function],
43 | "findAllByRole": [Function],
44 | "findAllByTestId": [Function],
45 | "findAllByText": [Function],
46 | "findAllByTitle": [Function],
47 | "findByAltText": [Function],
48 | "findByDisplayValue": [Function],
49 | "findByLabelText": [Function],
50 | "findByPlaceholderText": [Function],
51 | "findByRole": [Function],
52 | "findByTestId": [Function],
53 | "findByText": [Function],
54 | "findByTitle": [Function],
55 | "getAllByAltText": [Function],
56 | "getAllByDisplayValue": [Function],
57 | "getAllByLabelText": [Function],
58 | "getAllByPlaceholderText": [Function],
59 | "getAllByRole": [Function],
60 | "getAllByTestId": [Function],
61 | "getAllByText": [Function],
62 | "getAllByTitle": [Function],
63 | "getByAltText": [Function],
64 | "getByDisplayValue": [Function],
65 | "getByLabelText": [Function],
66 | "getByPlaceholderText": [Function],
67 | "getByRole": [Function],
68 | "getByTestId": [Function],
69 | "getByText": [Function],
70 | "getByTitle": [Function],
71 | "queryAllByAltText": [Function],
72 | "queryAllByDisplayValue": [Function],
73 | "queryAllByLabelText": [Function],
74 | "queryAllByPlaceholderText": [Function],
75 | "queryAllByRole": [Function],
76 | "queryAllByTestId": [Function],
77 | "queryAllByText": [Function],
78 | "queryAllByTitle": [Function],
79 | "queryByAltText": [Function],
80 | "queryByDisplayValue": [Function],
81 | "queryByLabelText": [Function],
82 | "queryByPlaceholderText": [Function],
83 | "queryByRole": [Function],
84 | "queryByTestId": [Function],
85 | "queryByText": [Function],
86 | "queryByTitle": [Function],
87 | "rerender": [Function],
88 | "unmount": [Function],
89 | }
90 | `;
91 |
--------------------------------------------------------------------------------
/src/__tests__/__snapshots__/Items.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`test for Item Component should render Item component 1`] = `
4 | Object {
5 | "asFragment": [Function],
6 | "baseElement":
7 |
14 | ,
15 | "container": ,
22 | "debug": [Function],
23 | "findAllByAltText": [Function],
24 | "findAllByDisplayValue": [Function],
25 | "findAllByLabelText": [Function],
26 | "findAllByPlaceholderText": [Function],
27 | "findAllByRole": [Function],
28 | "findAllByTestId": [Function],
29 | "findAllByText": [Function],
30 | "findAllByTitle": [Function],
31 | "findByAltText": [Function],
32 | "findByDisplayValue": [Function],
33 | "findByLabelText": [Function],
34 | "findByPlaceholderText": [Function],
35 | "findByRole": [Function],
36 | "findByTestId": [Function],
37 | "findByText": [Function],
38 | "findByTitle": [Function],
39 | "getAllByAltText": [Function],
40 | "getAllByDisplayValue": [Function],
41 | "getAllByLabelText": [Function],
42 | "getAllByPlaceholderText": [Function],
43 | "getAllByRole": [Function],
44 | "getAllByTestId": [Function],
45 | "getAllByText": [Function],
46 | "getAllByTitle": [Function],
47 | "getByAltText": [Function],
48 | "getByDisplayValue": [Function],
49 | "getByLabelText": [Function],
50 | "getByPlaceholderText": [Function],
51 | "getByRole": [Function],
52 | "getByTestId": [Function],
53 | "getByText": [Function],
54 | "getByTitle": [Function],
55 | "queryAllByAltText": [Function],
56 | "queryAllByDisplayValue": [Function],
57 | "queryAllByLabelText": [Function],
58 | "queryAllByPlaceholderText": [Function],
59 | "queryAllByRole": [Function],
60 | "queryAllByTestId": [Function],
61 | "queryAllByText": [Function],
62 | "queryAllByTitle": [Function],
63 | "queryByAltText": [Function],
64 | "queryByDisplayValue": [Function],
65 | "queryByLabelText": [Function],
66 | "queryByPlaceholderText": [Function],
67 | "queryByRole": [Function],
68 | "queryByTestId": [Function],
69 | "queryByText": [Function],
70 | "queryByTitle": [Function],
71 | "rerender": [Function],
72 | "unmount": [Function],
73 | }
74 | `;
75 |
--------------------------------------------------------------------------------
/src/__tests__/__snapshots__/Navbar.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`test for Navbar Component should render Navbar Component 1`] = `
4 | Object {
5 | "asFragment": [Function],
6 | "baseElement":
7 |
8 |
11 |
12 | Math Magicians
13 |
14 |
48 |
49 |
50 | ,
51 | "container":
52 |
55 |
56 | Math Magicians
57 |
58 |
92 |
93 |
,
94 | "debug": [Function],
95 | "findAllByAltText": [Function],
96 | "findAllByDisplayValue": [Function],
97 | "findAllByLabelText": [Function],
98 | "findAllByPlaceholderText": [Function],
99 | "findAllByRole": [Function],
100 | "findAllByTestId": [Function],
101 | "findAllByText": [Function],
102 | "findAllByTitle": [Function],
103 | "findByAltText": [Function],
104 | "findByDisplayValue": [Function],
105 | "findByLabelText": [Function],
106 | "findByPlaceholderText": [Function],
107 | "findByRole": [Function],
108 | "findByTestId": [Function],
109 | "findByText": [Function],
110 | "findByTitle": [Function],
111 | "getAllByAltText": [Function],
112 | "getAllByDisplayValue": [Function],
113 | "getAllByLabelText": [Function],
114 | "getAllByPlaceholderText": [Function],
115 | "getAllByRole": [Function],
116 | "getAllByTestId": [Function],
117 | "getAllByText": [Function],
118 | "getAllByTitle": [Function],
119 | "getByAltText": [Function],
120 | "getByDisplayValue": [Function],
121 | "getByLabelText": [Function],
122 | "getByPlaceholderText": [Function],
123 | "getByRole": [Function],
124 | "getByTestId": [Function],
125 | "getByText": [Function],
126 | "getByTitle": [Function],
127 | "queryAllByAltText": [Function],
128 | "queryAllByDisplayValue": [Function],
129 | "queryAllByLabelText": [Function],
130 | "queryAllByPlaceholderText": [Function],
131 | "queryAllByRole": [Function],
132 | "queryAllByTestId": [Function],
133 | "queryAllByText": [Function],
134 | "queryAllByTitle": [Function],
135 | "queryByAltText": [Function],
136 | "queryByDisplayValue": [Function],
137 | "queryByLabelText": [Function],
138 | "queryByPlaceholderText": [Function],
139 | "queryByRole": [Function],
140 | "queryByTestId": [Function],
141 | "queryByText": [Function],
142 | "queryByTitle": [Function],
143 | "rerender": [Function],
144 | "unmount": [Function],
145 | }
146 | `;
147 |
--------------------------------------------------------------------------------
/src/__tests__/__snapshots__/Quotes.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`test for Quotes Component should render Quotes Component 1`] = `
4 | Object {
5 | "asFragment": [Function],
6 | "baseElement":
7 |
8 |
11 |
12 | Mathematics is not about numbers, equations, computations, or algorithms: it is about understanding. -William Paul Thurston
13 |
14 |
15 |
16 | ,
17 | "container":
18 |
21 |
22 | Mathematics is not about numbers, equations, computations, or algorithms: it is about understanding. -William Paul Thurston
23 |
24 |
25 |
,
26 | "debug": [Function],
27 | "findAllByAltText": [Function],
28 | "findAllByDisplayValue": [Function],
29 | "findAllByLabelText": [Function],
30 | "findAllByPlaceholderText": [Function],
31 | "findAllByRole": [Function],
32 | "findAllByTestId": [Function],
33 | "findAllByText": [Function],
34 | "findAllByTitle": [Function],
35 | "findByAltText": [Function],
36 | "findByDisplayValue": [Function],
37 | "findByLabelText": [Function],
38 | "findByPlaceholderText": [Function],
39 | "findByRole": [Function],
40 | "findByTestId": [Function],
41 | "findByText": [Function],
42 | "findByTitle": [Function],
43 | "getAllByAltText": [Function],
44 | "getAllByDisplayValue": [Function],
45 | "getAllByLabelText": [Function],
46 | "getAllByPlaceholderText": [Function],
47 | "getAllByRole": [Function],
48 | "getAllByTestId": [Function],
49 | "getAllByText": [Function],
50 | "getAllByTitle": [Function],
51 | "getByAltText": [Function],
52 | "getByDisplayValue": [Function],
53 | "getByLabelText": [Function],
54 | "getByPlaceholderText": [Function],
55 | "getByRole": [Function],
56 | "getByTestId": [Function],
57 | "getByText": [Function],
58 | "getByTitle": [Function],
59 | "queryAllByAltText": [Function],
60 | "queryAllByDisplayValue": [Function],
61 | "queryAllByLabelText": [Function],
62 | "queryAllByPlaceholderText": [Function],
63 | "queryAllByRole": [Function],
64 | "queryAllByTestId": [Function],
65 | "queryAllByText": [Function],
66 | "queryAllByTitle": [Function],
67 | "queryByAltText": [Function],
68 | "queryByDisplayValue": [Function],
69 | "queryByLabelText": [Function],
70 | "queryByPlaceholderText": [Function],
71 | "queryByRole": [Function],
72 | "queryByTestId": [Function],
73 | "queryByText": [Function],
74 | "queryByTitle": [Function],
75 | "rerender": [Function],
76 | "unmount": [Function],
77 | }
78 | `;
79 |
--------------------------------------------------------------------------------
/src/components/Calculator.css:
--------------------------------------------------------------------------------
1 | .calculator {
2 | display: flex;
3 | justify-content: center;
4 | gap: 2rem;
5 | }
6 |
7 | .calculator > h4 {
8 | font-size: 1rem;
9 | font-weight: 500;
10 | }
11 |
12 | .header {
13 | grid-area: header;
14 | color: white;
15 | padding-right: 0.5rem;
16 | font-size: 25px;
17 | height: 20px;
18 | justify-self: flex-end;
19 | align-self: center;
20 | }
21 |
22 | .AC {
23 | grid-area: AC;
24 | background: lightgray;
25 | }
26 |
27 | .addSub {
28 | grid-area: addSub;
29 | background: lightgray;
30 | }
31 |
32 | .percent {
33 | grid-area: percent;
34 | background: lightgray;
35 | }
36 |
37 | .divide {
38 | grid-area: divide;
39 | background: #ff9411;
40 | }
41 |
42 | .seven {
43 | grid-area: seven;
44 | background: lightgray;
45 | }
46 |
47 | .eight {
48 | grid-area: eight;
49 | background: lightgray;
50 | }
51 |
52 | .nine {
53 | grid-area: nine;
54 | background: lightgray;
55 | }
56 |
57 | .multiply {
58 | grid-area: multiply;
59 | background: #ff9411;
60 | }
61 |
62 | .four {
63 | grid-area: four;
64 | background: lightgray;
65 | }
66 |
67 | .five {
68 | grid-area: five;
69 | background: lightgray;
70 | }
71 |
72 | .six {
73 | grid-area: six;
74 | background: lightgray;
75 | }
76 |
77 | .minus {
78 | grid-area: minus;
79 | background: #ff9411;
80 | }
81 |
82 | .one {
83 | grid-area: one;
84 | background: lightgray;
85 | }
86 |
87 | .two {
88 | grid-area: two;
89 | background: lightgray;
90 | }
91 |
92 | .three {
93 | grid-area: three;
94 | background: lightgray;
95 | }
96 |
97 | .plus {
98 | grid-area: plus;
99 | background: #ff9411;
100 | }
101 |
102 | .zero {
103 | grid-area: zero;
104 | background: lightgray;
105 | }
106 |
107 | .dot {
108 | grid-area: dot;
109 | background: lightgray;
110 | }
111 |
112 | .equal {
113 | grid-area: equal;
114 | background: #ff9411;
115 | }
116 |
117 | .container {
118 | width: 400px;
119 | height: 400px;
120 | display: grid;
121 | text-align: center;
122 | grid-template-areas:
123 | "header header header header"
124 | "AC addSub percent divide"
125 | "seven eight nine multiply"
126 | "four five six minus"
127 | "one two three plus"
128 | "zero zero dot equal";
129 | grid-gap: 0.15rem;
130 | background: darkgray;
131 | position: relative;
132 | }
133 |
134 | .container > div {
135 | display: flex;
136 | justify-content: center;
137 | align-items: center;
138 | }
139 |
--------------------------------------------------------------------------------
/src/components/Calculator.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import Item from './Items';
3 | import calculate from './logic/calculate';
4 |
5 | import './Calculator.css';
6 |
7 | const Calculator = () => {
8 | const [state, setState] = useState({
9 | total: '0',
10 | next: null,
11 | operation: null,
12 | });
13 |
14 | const clickHandler = (event) => {
15 | const text = event.target.textContent;
16 | const newState = calculate(state, text);
17 | setState({ ...newState });
18 | };
19 |
20 | const { total, next } = state;
21 |
22 | return (
23 |
24 |
Let`s do some math!
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | );
49 | };
50 |
51 | export default Calculator;
52 |
--------------------------------------------------------------------------------
/src/components/Home.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable max-len */
2 | import React from 'react';
3 |
4 | const Home = () => (
5 |
6 |
Welcome to our page!
7 |
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
8 |
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
9 |
10 | );
11 |
12 | export default Home;
13 |
--------------------------------------------------------------------------------
/src/components/Items.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 |
4 | const Item = ({ value, className, onClickHandler }) => (
5 |
6 | { value }
7 |
8 | );
9 |
10 | Item.propTypes = {
11 | value: PropTypes.string.isRequired,
12 | className: PropTypes.string.isRequired,
13 | onClickHandler: PropTypes.func.isRequired,
14 | };
15 |
16 | export default Item;
17 |
--------------------------------------------------------------------------------
/src/components/Navbar.css:
--------------------------------------------------------------------------------
1 | .navbar {
2 | display: flex;
3 | justify-content: space-between;
4 | align-items: center;
5 | margin-bottom: 3rem;
6 | }
7 |
8 | .nav_lists {
9 | display: flex;
10 | text-decoration: underline;
11 | list-style-type: none;
12 | gap: 0.5rem;
13 | }
14 |
15 | .nav_list {
16 | height: 70%;
17 | padding-right: 0.5rem;
18 | border-right: 2px solid black;
19 | }
20 |
21 | .link {
22 | color: blue;
23 | text-decoration: none;
24 | }
25 |
26 | .hidden {
27 | border-right: none;
28 | }
29 |
--------------------------------------------------------------------------------
/src/components/Navbar.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Link } from 'react-router-dom';
3 | import './Navbar.css';
4 |
5 | const Navbar = () => (
6 |
7 | Math Magicians
8 |
9 |
10 | Home
11 |
12 |
13 | Calculator
14 |
15 |
16 | Quote
17 |
18 |
19 |
20 | );
21 |
22 | export default Navbar;
23 |
--------------------------------------------------------------------------------
/src/components/Quotes.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable max-len */
2 | import React from 'react';
3 |
4 | const Quotes = () => (
5 |
6 |
Mathematics is not about numbers, equations, computations, or algorithms: it is about understanding. -William Paul Thurston
7 |
8 | );
9 |
10 | export default Quotes;
11 |
--------------------------------------------------------------------------------
/src/components/logic/calculate.js:
--------------------------------------------------------------------------------
1 | import operate from './operate';
2 |
3 | function isNumber(item) {
4 | return !!item.match(/[0-9]+/);
5 | }
6 |
7 | /**
8 | * Given a button name and a calculator data object, return an updated
9 | * calculator data object.
10 | *
11 | * Calculator data object contains:
12 | * total:s the running total
13 | * next:String the next number to be operated on with the total
14 | * operation:String +, -, etc.
15 | */
16 | export default function calculate(obj, buttonName) {
17 | if (buttonName === 'AC') {
18 | return {
19 | total: '0',
20 | next: null,
21 | operation: null,
22 | };
23 | }
24 |
25 | if (isNumber(buttonName)) {
26 | if (buttonName === '0' && obj.next === '0') {
27 | return {};
28 | }
29 | // If there is an operation, update next
30 | if (obj.operation) {
31 | if (obj.next && obj.next !== '0') {
32 | return { ...obj, next: obj.next + buttonName };
33 | }
34 | return { ...obj, next: buttonName };
35 | }
36 | // If there is no operation, update next and clear the value
37 | if (obj.next && obj.next !== '0') {
38 | return {
39 | next: obj.next + buttonName,
40 | total: null,
41 | };
42 | }
43 | return {
44 | next: buttonName,
45 | total: null,
46 | };
47 | }
48 |
49 | if (buttonName === '.') {
50 | if (obj.next) {
51 | if (obj.next.includes('.')) {
52 | return { ...obj };
53 | }
54 | return { ...obj, next: `${obj.next}.` };
55 | }
56 | if (obj.operation) {
57 | return { ...obj, next: '0.' };
58 | }
59 | if (obj.total) {
60 | if (obj.total.includes('.')) {
61 | return {};
62 | }
63 | return { ...obj, next: `${obj.total}.` };
64 | }
65 | return { ...obj, next: '0.' };
66 | }
67 |
68 | if (buttonName === '=') {
69 | if (obj.next && obj.operation) {
70 | return {
71 | total: operate(obj.total, obj.next, obj.operation),
72 | next: null,
73 | operation: null,
74 | };
75 | }
76 | // '=' with no operation, nothing to do
77 | return {};
78 | }
79 |
80 | if (buttonName === '+/-') {
81 | if (obj.next) {
82 | return { ...obj, next: (-1 * parseFloat(obj.next)).toString() };
83 | }
84 | if (obj.total) {
85 | return { ...obj, total: (-1 * parseFloat(obj.total)).toString() };
86 | }
87 | return {};
88 | }
89 |
90 | // Button must be an operation
91 |
92 | // When the user presses an operation button without having entered
93 | // a number first, do nothing.
94 | // if (!obj.next && !obj.total) {
95 | // return {};
96 | // }
97 |
98 | // User pressed an operation after pressing '='
99 | if (!obj.next && obj.total && !obj.operation) {
100 | return { ...obj, operation: buttonName };
101 | }
102 |
103 | // User pressed an operation button and there is an existing operation
104 | if (obj.operation) {
105 | if (obj.total && !obj.next) {
106 | return { ...obj, operation: buttonName };
107 | }
108 |
109 | if (!obj.total) {
110 | return { total: 0, operation: buttonName };
111 | }
112 |
113 | return {
114 | total: operate(obj.total, obj.next, obj.operation),
115 | next: null,
116 | operation: buttonName,
117 | };
118 | }
119 |
120 | // no operation yet, but the user typed one
121 |
122 | // The user hasn't typed a number yet, just save the operation
123 | if (!obj.next) {
124 | return { operation: buttonName };
125 | }
126 |
127 | // save the operation and shift 'next' into 'total'
128 | return {
129 | total: obj.next,
130 | next: null,
131 | operation: buttonName,
132 | };
133 | }
134 |
--------------------------------------------------------------------------------
/src/components/logic/calculate.test.js:
--------------------------------------------------------------------------------
1 | import calculate from './calculate';
2 |
3 | describe('testing calculate function', () => {
4 | test('should return an object with total', () => {
5 | expect(calculate({ total: '10', next: '5', operation: '+' }, '=')).toEqual({ total: '15', next: null, operation: null });
6 | expect(calculate({ total: '10', next: '5', operation: '-' }, '=')).toEqual({ total: '5', next: null, operation: null });
7 | expect(calculate({ total: '10', next: '5', operation: 'x' }, '=')).toEqual({ total: '50', next: null, operation: null });
8 | expect(calculate({ total: '10', next: '5', operation: '÷' }, '=')).toEqual({ total: '2', next: null, operation: null });
9 | });
10 |
11 | test('should return an empty object', () => {
12 | expect(calculate({ total: '0', next: '5', operation: null }, '=')).toEqual({});
13 | });
14 |
15 | test('for the +/- buttonName', () => {
16 | expect(calculate({ total: '10', next: '5', operation: null }, '+/-')).toEqual({ total: '10', next: '-5', operation: null });
17 | expect(calculate({ total: '10', next: null, operation: null }, '+/-')).toEqual({ total: '-10', next: null, operation: null });
18 | });
19 |
20 | test('should update next value property', () => {
21 | expect(calculate({ total: '10', next: '5', operation: '+' }, '8')).toEqual({ total: '10', next: '58', operation: '+' });
22 | });
23 |
24 | test('should reset all values to default', () => {
25 | expect(calculate({ total: '10', next: '5', operation: '+' }, 'AC')).toEqual({ total: '0', next: null, operation: null });
26 | });
27 | });
28 |
--------------------------------------------------------------------------------
/src/components/logic/operate.js:
--------------------------------------------------------------------------------
1 | import Big from 'big-js';
2 |
3 | export default function operate(numberOne, numberTwo, operation) {
4 | const one = Big(numberOne);
5 | const two = Big(numberTwo);
6 | if (operation === '+') {
7 | return one.plus(two).toString();
8 | }
9 | if (operation === '-') {
10 | return one.minus(two).toString();
11 | }
12 | if (operation === 'x') {
13 | return one.times(two).toString();
14 | }
15 | if (operation === '÷') {
16 | try {
17 | return one.div(two).toString();
18 | } catch (err) {
19 | return "Can't divide by 0.";
20 | }
21 | }
22 | if (operation === '%') {
23 | try {
24 | return one.mod(two).toString();
25 | } catch (err) {
26 | return "Can't find modulo as can't divide by 0.";
27 | }
28 | }
29 | throw Error(`Unknown operation '${operation}'`);
30 | }
31 |
--------------------------------------------------------------------------------
/src/components/logic/operate.test.js:
--------------------------------------------------------------------------------
1 | import operate from './operate';
2 |
3 | describe('test for operate function', () => {
4 | it('should add numbers together', () => {
5 | expect(operate(1, 1, '+')).toBe('2');
6 | });
7 |
8 | it('should subtract numbers', () => {
9 | expect(operate('10', '7', '-')).toBe('3');
10 | });
11 |
12 | it('should multiply numbers', () => {
13 | expect(operate(10, 10, 'x')).toBe('100');
14 | });
15 |
16 | it('should divide numbers', () => {
17 | expect(operate('10', '2', '÷')).toBe('5');
18 | expect(operate(3, 0, '÷')).toBe('Can\'t divide by 0.');
19 | });
20 |
21 | it('should find the modulus of numbers', () => {
22 | expect(operate(9, 2, '%')).toBe('1');
23 | });
24 |
25 | it('should throw an error', () => {
26 | expect(() => {
27 | operate(9, 2, '#');
28 | }).toThrowError();
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | margin: 1rem;
9 | padding: 1rem;
10 | font-family:
11 | -apple-system,
12 | BlinkMacSystemFont,
13 | 'Segoe UI',
14 | 'Roboto',
15 | 'Oxygen',
16 | 'Ubuntu',
17 | 'Cantarell',
18 | 'Fira Sans',
19 | 'Droid Sans',
20 | 'Helvetica Neue',
21 | sans-serif;
22 | -webkit-font-smoothing: antialiased;
23 | -moz-osx-font-smoothing: grayscale;
24 | }
25 |
26 | .home_component p {
27 | margin-top: 1rem;
28 | }
29 |
30 | .quotes {
31 | max-width: 968px;
32 | height: 60vh;
33 | line-height: 1.5rem;
34 | display: flex;
35 | align-items: center;
36 | justify-content: center;
37 | margin: 0 auto;
38 | }
39 |
--------------------------------------------------------------------------------
/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 |
9 |
10 | ,
11 | );
12 |
13 | // If you want to start measuring performance in your app, pass a function
14 | // to log results (for example: reportWebVitals(console.log))
15 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
16 |
--------------------------------------------------------------------------------