├── public ├── robots.txt ├── favicon.ico ├── logo192.png ├── logo512.png ├── manifest.json └── index.html ├── .babelrc ├── src ├── App.css ├── App.js ├── externalFunction.js ├── redux │ ├── configureStore.js │ ├── imf │ │ ├── __mocks__ │ │ │ └── imf.js │ │ └── imf.js │ └── individual │ │ ├── __mocks__ │ │ └── individual.js │ │ └── individual.js ├── index.js ├── components │ ├── Header.js │ ├── Router.js │ ├── DetailsPage.js │ ├── CallAPI.js │ ├── HomePage.js │ └── style.css └── tests │ ├── imf.test.js │ └── individual.test.js ├── .gitignore ├── .stylelintrc.json ├── .eslintrc.json ├── netlify.toml ├── MIT.md ├── package.json ├── README.md └── .github └── workflows └── linters.yml /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pratap-panabaka/metrics-webapp-mutual-funds/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pratap-panabaka/metrics-webapp-mutual-funds/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pratap-panabaka/metrics-webapp-mutual-funds/HEAD/public/logo512.png -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-react" 4 | ], 5 | "plugins": ["@babel/plugin-syntax-jsx"] 6 | } -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | @import url('https://use.typekit.net/gmu8egi.css'); 2 | 3 | html, 4 | body { 5 | font-family: 'Lato', sans-serif; 6 | } 7 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import Router from './components/Router'; 2 | import './App.css'; 3 | 4 | function App() { 5 | return ( 6 | <> 7 | 8 | 9 | ); 10 | } 11 | 12 | export default App; 13 | -------------------------------------------------------------------------------- /src/externalFunction.js: -------------------------------------------------------------------------------- 1 | const getMultipleRandom = (arr, num) => { 2 | const shuffled = [...arr].sort(() => 0.5 - Math.random()); 3 | 4 | return shuffled.slice(0, num); 5 | }; 6 | 7 | export default getMultipleRandom; 8 | -------------------------------------------------------------------------------- /src/redux/configureStore.js: -------------------------------------------------------------------------------- 1 | import { configureStore, combineReducers } from '@reduxjs/toolkit'; 2 | import imfReducer from './imf/imf'; 3 | import getIndividualDataReducer from './individual/individual'; 4 | 5 | const reducer = combineReducers({ imfReducer, getIndividualDataReducer }); 6 | 7 | const store = configureStore({ reducer }); 8 | 9 | export default store; 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | # Local Netlify folder 26 | .netlify 27 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import { BrowserRouter } from 'react-router-dom'; 4 | import { Provider } from 'react-redux'; 5 | import App from './App'; 6 | import store from './redux/configureStore'; 7 | 8 | const root = ReactDOM.createRoot(document.getElementById('root')); 9 | root.render( 10 | 11 | 12 | 13 | 14 | , 15 | ); 16 | -------------------------------------------------------------------------------- /src/redux/imf/__mocks__/imf.js: -------------------------------------------------------------------------------- 1 | const fetchedObj = [{ schemeCode: 100027, schemeName: 'Grindlays Super Saver Income Fund-GSSIF-Half Yearly Dividend' }, 2 | { schemeCode: 100028, schemeName: 'Grindlays Super Saver Income Fund-GSSIF-Quaterly Dividend' }, 3 | { schemeCode: 100029, schemeName: 'Grindlays Super Saver Income Fund-GSSIF-Growth' }, 4 | { schemeCode: 100030, schemeName: 'Grindlays Super Saver Income Fund-GSSIF-Annual Dividend' }]; 5 | 6 | const getDataAction = () => () => fetchedObj; 7 | 8 | export default getDataAction; 9 | -------------------------------------------------------------------------------- /src/components/Header.js: -------------------------------------------------------------------------------- 1 | import { FaMicrophone } from 'react-icons/fa'; 2 | import { FiSettings } from 'react-icons/fi'; 3 | import './style.css'; 4 | 5 | const Header = () => ( 6 | <> 7 |
8 |
9 |

10 | Indian Mutual Funds 11 |

12 |
13 | 14 | 15 |
16 |
17 |
18 | 19 | ); 20 | 21 | export default Header; 22 | -------------------------------------------------------------------------------- /src/redux/individual/__mocks__/individual.js: -------------------------------------------------------------------------------- 1 | const fetchedObj = { 2 | meta: 3 | { 4 | fund_house: 'DSP Mutual Fund', 5 | scheme_type: 'Open Ended Schemes', 6 | scheme_category: 'Debt Scheme - Gilt Fund', 7 | scheme_code: 100086, 8 | scheme_name: 'DSP Government Securities Fund - Regular Plan - IDCW - Monthly', 9 | }, 10 | data: [{ date: '03-10-2022', nav: '10.70250' }, { date: '30-09-2022', nav: '10.71460' }], 11 | status: 'SUCCESS', 12 | }; 13 | 14 | const getIndividualDataAction = () => () => fetchedObj; 15 | 16 | export default getIndividualDataAction; 17 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/redux/imf/imf.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const GET_DATA = 'GET_DATA'; 4 | const API = 'https://api.mfapi.in/mf'; 5 | 6 | const initialState = []; 7 | 8 | const imfReducer = (state = initialState, action) => { 9 | switch (action.type) { 10 | case GET_DATA: 11 | return action.payload; 12 | default: 13 | return state; 14 | } 15 | }; 16 | 17 | export const getDataAction = () => (dispatch) => { 18 | axios.get(API).then((response) => { 19 | const { data } = response; 20 | dispatch({ type: GET_DATA, payload: data }); 21 | }); 22 | }; 23 | 24 | export default imfReducer; 25 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.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", "plugin:react-hooks/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 | -------------------------------------------------------------------------------- /src/components/Router.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { Routes, Route } from 'react-router-dom'; 3 | import HomePage from './HomePage'; 4 | import CallAPI from './CallAPI'; 5 | import DetailsPage from './DetailsPage'; 6 | 7 | const Router = () => { 8 | const [id, setId] = useState(''); 9 | 10 | const handleId = (e) => { 11 | setId(e.target.parentElement.id); 12 | }; 13 | 14 | return ( 15 | <> 16 | 17 | } /> 18 | } /> 19 | } /> 20 | 21 | 22 | ); 23 | }; 24 | 25 | export default Router; 26 | -------------------------------------------------------------------------------- /src/redux/individual/individual.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const GET_INDIVIDUAL_DATA = 'GET_INDIVIDUAL_DATA'; 4 | const API = 'https://api.mfapi.in/mf'; 5 | 6 | const initialState = { 7 | meta: {}, 8 | data: [], 9 | status: '', 10 | }; 11 | 12 | const getIndividualDataReducer = (state = initialState, action) => { 13 | switch (action.type) { 14 | case GET_INDIVIDUAL_DATA: 15 | return action.payload; 16 | default: 17 | return state; 18 | } 19 | }; 20 | 21 | export const getIndividualDataAction = (id) => (dispatch) => { 22 | axios.get(`${API}/${id}`).then((response) => { 23 | const { data } = response; 24 | dispatch({ type: GET_INDIVIDUAL_DATA, payload: data }); 25 | }); 26 | }; 27 | 28 | export default getIndividualDataReducer; 29 | -------------------------------------------------------------------------------- /src/tests/imf.test.js: -------------------------------------------------------------------------------- 1 | import imfReducer, { getDataAction } from '../redux/imf/imf'; 2 | 3 | jest.mock('../redux/imf/imf'); 4 | 5 | const toCompare = [{ schemeCode: 100027, schemeName: 'Grindlays Super Saver Income Fund-GSSIF-Half Yearly Dividend' }, 6 | { schemeCode: 100028, schemeName: 'Grindlays Super Saver Income Fund-GSSIF-Quaterly Dividend' }, 7 | { schemeCode: 100029, schemeName: 'Grindlays Super Saver Income Fund-GSSIF-Growth' }, 8 | { schemeCode: 100030, schemeName: 'Grindlays Super Saver Income Fund-GSSIF-Annual Dividend' }]; 9 | 10 | describe('Test Store', () => { 11 | test('test imfReducer', () => { 12 | const initialState = []; 13 | const fetchedState = imfReducer(initialState, getDataAction); 14 | expect(fetchedState()).toStrictEqual(toCompare); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | # example netlify.toml 2 | [build] 3 | command = "react-scripts build" 4 | functions = "netlify/functions" 5 | publish = "build" 6 | 7 | ## Uncomment to use this redirect for Single Page Applications like create-react-app. 8 | ## Not needed for static site generators. 9 | #[[redirects]] 10 | # from = "/*" 11 | # to = "/index.html" 12 | # status = 200 13 | 14 | ## (optional) Settings for Netlify Dev 15 | ## https://github.com/netlify/cli/blob/main/docs/netlify-dev.md#project-detection 16 | #[dev] 17 | # command = "yarn start" # Command to start your dev server 18 | # port = 3000 # Port that the dev server will be listening on 19 | # publish = "dist" # Folder with the static content for _redirect file 20 | 21 | ## more info on configuring this file: https://docs.netlify.com/configure-builds/file-based-configuration/ 22 | -------------------------------------------------------------------------------- /src/tests/individual.test.js: -------------------------------------------------------------------------------- 1 | import getIndividualDataReducer, { getIndividualDataAction } from '../redux/individual/individual'; 2 | 3 | jest.mock('../redux/individual/individual'); 4 | 5 | const toCompare = { 6 | meta: 7 | { 8 | fund_house: 'DSP Mutual Fund', 9 | scheme_type: 'Open Ended Schemes', 10 | scheme_category: 'Debt Scheme - Gilt Fund', 11 | scheme_code: 100086, 12 | scheme_name: 'DSP Government Securities Fund - Regular Plan - IDCW - Monthly', 13 | }, 14 | data: [{ date: '03-10-2022', nav: '10.70250' }, { date: '30-09-2022', nav: '10.71460' }], 15 | status: 'SUCCESS', 16 | }; 17 | 18 | describe('Test Store', () => { 19 | test('test getIndividualDataReducer', () => { 20 | const initialState = []; 21 | const fetchedState = getIndividualDataReducer(initialState, getIndividualDataAction); 22 | expect(fetchedState()).toStrictEqual(toCompare); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /MIT.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 PRATAP 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. -------------------------------------------------------------------------------- /src/components/DetailsPage.js: -------------------------------------------------------------------------------- 1 | import { NavLink } from 'react-router-dom'; 2 | import { FcPrevious } from 'react-icons/fc'; 3 | import { useSelector } from 'react-redux'; 4 | import { FaPiggyBank } from 'react-icons/fa'; 5 | import Header from './Header'; 6 | 7 | const DetailsPage = () => { 8 | const individualData = useSelector((state) => state.getIndividualDataReducer); 9 | 10 | return ( 11 | <> 12 |
13 | 14 |
15 |
16 |
17 |
18 | 19 |
20 |
21 | Showing Statistics: 22 |
23 | {individualData.data.length} 24 |
25 |
26 | 27 | 28 | 29 | 30 | 31 | { 32 | individualData.data.map((item) => ( 33 | 34 | 35 | 36 | 37 | )) 38 | } 39 |
DateNet Asset Value
{item.date}{item.nav}
40 | 41 | ); 42 | }; 43 | 44 | export default DetailsPage; 45 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mutual-funds", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@reduxjs/toolkit": "^1.8.5", 7 | "@testing-library/jest-dom": "^5.16.5", 8 | "@testing-library/react": "^13.4.0", 9 | "@testing-library/user-event": "^13.5.0", 10 | "axios": "^0.27.2", 11 | "npm": "^8.19.2", 12 | "prop-types": "^15.8.1", 13 | "react": "^18.2.0", 14 | "react-dom": "^18.2.0", 15 | "react-icons": "^4.4.0", 16 | "react-redux": "^8.0.4", 17 | "react-router-dom": "^6.4.1", 18 | "react-scripts": "5.0.1", 19 | "web-vitals": "^2.1.4" 20 | }, 21 | "scripts": { 22 | "start": "react-scripts start", 23 | "build": "react-scripts build", 24 | "test": "react-scripts test", 25 | "eject": "react-scripts eject" 26 | }, 27 | "eslintConfig": { 28 | "extends": [ 29 | "react-app", 30 | "react-app/jest" 31 | ] 32 | }, 33 | "browserslist": { 34 | "production": [ 35 | ">0.2%", 36 | "not dead", 37 | "not op_mini all" 38 | ], 39 | "development": [ 40 | "last 1 chrome version", 41 | "last 1 firefox version", 42 | "last 1 safari version" 43 | ] 44 | }, 45 | "devDependencies": { 46 | "@babel/core": "^7.19.3", 47 | "@babel/eslint-parser": "^7.19.1", 48 | "@babel/plugin-syntax-jsx": "^7.18.6", 49 | "@babel/preset-env": "^7.19.3", 50 | "@babel/preset-react": "^7.18.6", 51 | "eslint": "^7.32.0", 52 | "eslint-config-airbnb": "^18.2.1", 53 | "eslint-plugin-import": "^2.26.0", 54 | "eslint-plugin-jsx-a11y": "^6.6.1", 55 | "eslint-plugin-react": "^7.31.8", 56 | "eslint-plugin-react-hooks": "^4.6.0", 57 | "netlify-cli": "^12.0.4", 58 | "stylelint": "^13.13.1", 59 | "stylelint-config-standard": "^21.0.0", 60 | "stylelint-csstree-validator": "^1.9.0", 61 | "stylelint-scss": "^3.21.0" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](https://img.shields.io/badge/Microverse-blueviolet) 2 | 3 | # Metrics Webapp - Mututal Funds 4 | 5 | This React Capstone Project is about building a Mobile Web Application to check a list of metrics (numeric values) that are built with React and Redux. 6 | 7 | Select an API that provides numeric data about a topic and then build the webapp around it. 8 | 9 | ## Link to Live Demo 10 | 11 | [Loom Link](https://www.loom.com/share/3ae06abf18ee4831acdcc5610741caeb) 12 | 13 | ## Built With 14 | 15 | - React & Redux 16 | 17 | ## Netlify Link 18 | 19 | - [Netlify Link](https://metrics-app-mutual-funds-panabaka.netlify.app/) 20 | 21 | ## Preview of the Mutual Funds App 22 | ![Metrics-App-Pic-1](https://user-images.githubusercontent.com/40719899/193776623-1a123f7c-95e8-4fd6-a762-f22b36b04835.png) 23 | ![Metrics-App-Pic-2](https://user-images.githubusercontent.com/40719899/193776631-c84ec4df-fea0-4d68-ab37-86748c261081.png) 24 | ![Metrics-App-Pic-3](https://user-images.githubusercontent.com/40719899/193776635-33e63ca3-4146-453e-a1be-7679b34e7f09.png) 25 | 26 | 27 | 28 | ## Getting Started 29 | 30 | To get a local copy up and running follow these simple example steps. 31 | 32 | ```` 33 | git clone https://github.com/PRATAP-KUMAR/metrics-webapp-mutual-funds 34 | cd metrics-webapp-mutual-funds 35 | npm start 36 | ```` 37 | 38 | ## Author 39 | 40 | 👤 **PRATAP PANABAKA** 41 | 42 | - GitHub: [@PRATAP-KUMAR](https://github.com/PRATAP-KUMAR) 43 | - Twitter: [@PRATAP_TWT](https://twitter.com/PRATAP_TWT) 44 | - Linkedin: [@LinkedIn](https://www.linkedin.com/in/pratap-kumar-panabaka-755489236/) 45 | 46 | 47 | ## 🤝 Contributing 48 | 49 | Contributions, issues, and feature requests are welcome! 50 | 51 | Feel free to check the [issues page](../../issues/). 52 | 53 | ## Show your support 54 | 55 | Give a ⭐️ if you like this project! 56 | 57 | ## Acknowledgments 58 | 59 | - Original Design is by the Author [Nelson Sakwa on Behance](https://www.behance.net/sakwadesignstudio) 60 | 61 | ## 📝 License 62 | 63 | This project is [MIT](./MIT.md) licensed. 64 | -------------------------------------------------------------------------------- /.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-22.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-22.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-22.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 | -------------------------------------------------------------------------------- /src/components/CallAPI.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import { useDispatch, useSelector } from 'react-redux'; 3 | import { NavLink } from 'react-router-dom'; 4 | import PropTypes from 'prop-types'; 5 | import { FcPrevious, FcNext } from 'react-icons/fc'; 6 | import { FaPiggyBank } from 'react-icons/fa'; 7 | import { getIndividualDataAction } from '../redux/individual/individual'; 8 | import Header from './Header'; 9 | import './style.css'; 10 | 11 | const CallAPI = ({ id }) => { 12 | const individualData = useSelector((state) => state.getIndividualDataReducer); 13 | const dispatch = useDispatch(); 14 | 15 | useEffect(() => { 16 | dispatch(getIndividualDataAction(id)); 17 | }, [dispatch, id]); 18 | 19 | return ( 20 | <> 21 |
22 |
23 | 24 |
25 | 26 |
27 |
28 |
29 | 30 |
31 |
32 | Available Data: 33 |
34 | {individualData.data.length} 35 |
36 |
37 |
38 | SCHEME CODE -  39 | {individualData.meta.scheme_code} 40 |  DETAILS 41 |
42 |
43 |
44 | Fund House:  45 | {individualData.meta.fund_house} 46 |
47 |
48 |
49 |
50 | Scheme Name:  51 | {individualData.meta.scheme_name} 52 |
53 |
54 |
55 |
56 | Scheme Type:  57 | {individualData.meta.scheme_type} 58 |
59 |
60 |
61 |
62 | Scheme Category:  63 | {individualData.meta.scheme_category} 64 |
65 |
66 |
67 | 68 | ); 69 | }; 70 | 71 | CallAPI.propTypes = { id: PropTypes.string.isRequired }; 72 | 73 | export default CallAPI; 74 | -------------------------------------------------------------------------------- /src/components/HomePage.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | import { useDispatch, useSelector } from 'react-redux'; 3 | import { NavLink } from 'react-router-dom'; 4 | import PropTypes from 'prop-types'; 5 | import { RiFundsBoxFill } from 'react-icons/ri'; 6 | import { FcNext } from 'react-icons/fc'; 7 | import { getDataAction } from '../redux/imf/imf'; 8 | import getExternalFunction from '../externalFunction'; 9 | import Header from './Header'; 10 | 11 | const HomePage = ({ handleId }) => { 12 | const imfData = useSelector((state) => state.imfReducer); 13 | const dispatch = useDispatch(); 14 | 15 | const [value, setValue] = useState(''); 16 | const handleInputChange = (e) => setValue(e.target.value); 17 | 18 | useEffect(() => { 19 | if (imfData.length === 0) { 20 | dispatch(getDataAction()); 21 | } 22 | }, [dispatch, imfData.length]); 23 | 24 | if (imfData.length === 0) { 25 | return ( 26 |

27 | INDIAN MUTUAL FUNDS 28 |
29 | PAGE IS LOADING... 30 |
31 | PLEASE WAIT 32 |

33 | ); 34 | } 35 | 36 | return ( 37 |
38 |
39 |
40 |
41 | 42 |
43 |
44 | FUNDING GROUPS: 45 |
46 | {imfData.length} 47 |
48 |
49 |
50 | 58 |
59 |
60 | TOTAL STATS 61 |
62 |
63 | { 64 | getExternalFunction(imfData, 500) 65 | .filter((item) => item.schemeName.toLowerCase().includes(value.toLowerCase())) 66 | .map((item) => ( 67 | 72 |
73 |
74 | 75 |
76 |
77 |
78 | {item.schemeName} 79 |
80 |
81 | {item.schemeCode} 82 |
83 |
84 |
85 |
86 | )) 87 | } 88 |
89 |
90 | ); 91 | }; 92 | 93 | HomePage.propTypes = { 94 | handleId: PropTypes.func.isRequired, 95 | }; 96 | 97 | export default HomePage; 98 | -------------------------------------------------------------------------------- /src/components/style.css: -------------------------------------------------------------------------------- 1 | @media only screen and (max-width: 2000px) { 2 | .loading { 3 | background-color: #43aadd; 4 | display: flex; 5 | justify-content: center; 6 | width: 100%; 7 | height: 100%; 8 | } 9 | 10 | .header { 11 | display: flex; 12 | gap: 5rem; 13 | height: 4rem; 14 | background: #054ea1; 15 | text-align: center; 16 | font-weight: bold; 17 | font-size: 1rem; 18 | justify-content: space-around; 19 | align-items: center; 20 | color: #fff; 21 | padding-left: 1rem; 22 | } 23 | 24 | .icons { 25 | display: flex; 26 | gap: 2rem; 27 | font-size: 1.5rem; 28 | justify-content: flex-end; 29 | padding-right: 1rem; 30 | } 31 | 32 | .banner { 33 | background-color: #43aadd; 34 | display: flex; 35 | justify-content: center; 36 | height: 20rem; 37 | align-items: center; 38 | padding: 0 2rem; 39 | } 40 | 41 | .logo, 42 | .text-banner { 43 | display: flex; 44 | justify-content: center; 45 | flex: 0.5; 46 | } 47 | 48 | .search-bar { 49 | display: flex; 50 | border: 2px solid #122471; 51 | } 52 | 53 | .search-box { 54 | width: 100%; 55 | text-align: center; 56 | font-size: 1rem; 57 | margin: 0 auto; 58 | height: 2rem; 59 | background-color: #054ea1; 60 | color: #fff; 61 | border: none; 62 | } 63 | 64 | .search-bar > ::placeholder { 65 | color: #c2bbbb; 66 | } 67 | 68 | .stats { 69 | background-color: #122471; 70 | font-weight: bold; 71 | color: #fff; 72 | padding-left: 1rem; 73 | line-height: 2rem; 74 | } 75 | 76 | .banner-mp { 77 | flex: 0.5; 78 | text-align: right; 79 | display: flex; 80 | background-color: #43aadd; 81 | justify-content: space-between; 82 | height: 20rem; 83 | align-items: center; 84 | padding: 0 2rem; 85 | } 86 | 87 | .text-banner { 88 | flex: 0.5; 89 | font-size: 1.5rem; 90 | font-weight: bold; 91 | color: #fff; 92 | text-align: left; 93 | } 94 | 95 | .container { 96 | display: grid; 97 | grid-template-columns: 1fr 1fr; 98 | align-items: center; 99 | background-color: #e1e1e1; 100 | } 101 | 102 | .card { 103 | display: flex; 104 | flex-direction: column; 105 | justify-content: space-around; 106 | padding: 0 2rem; 107 | background-color: #054ea1; 108 | height: 15rem; 109 | border: 0.2px solid #43aadd; 110 | } 111 | 112 | .next-arrow { 113 | text-align: right; 114 | } 115 | 116 | .text { 117 | font-size: 1.2rem; 118 | font-weight: bold; 119 | color: #fff; 120 | text-align: right; 121 | } 122 | 123 | .subtext { 124 | font-size: 0.8rem; 125 | color: #fff; 126 | text-align: right; 127 | } 128 | 129 | .card:nth-child(2), 130 | .card:nth-child(3n) { 131 | background-color: #122471; 132 | } 133 | 134 | .card-mp { 135 | display: flex; 136 | padding: 2rem; 137 | background-color: #054ea1; 138 | height: 2.5rem; 139 | border: 0.2px solid #43aadd; 140 | justify-content: flex-start; 141 | } 142 | 143 | .card-mp .text { 144 | text-align: left; 145 | } 146 | 147 | .card-mp:nth-child(odd) { 148 | background-color: #122471; 149 | } 150 | 151 | .card-dp { 152 | display: flex; 153 | padding: 2rem; 154 | background-color: #054ea1; 155 | height: 2.5rem; 156 | border: 0.2px solid #43aadd; 157 | justify-content: flex-start; 158 | } 159 | 160 | .details-page { 161 | text-align: center; 162 | } 163 | 164 | .table { 165 | width: 100%; 166 | color: #fff; 167 | } 168 | 169 | .table, 170 | th, 171 | td { 172 | border: 2px solid #43aadd; 173 | border-collapse: collapse; 174 | } 175 | 176 | th { 177 | background-color: #054ea1; 178 | } 179 | 180 | tr { 181 | background-color: #054ea1; 182 | text-align: center; 183 | } 184 | 185 | tr:nth-child(even) { 186 | background-color: #122471; 187 | } 188 | 189 | .z-index { 190 | z-index: 9; 191 | } 192 | } 193 | --------------------------------------------------------------------------------