diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..53326df --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + "configurations": [ + { + "type": "java", + "name": "Spring Boot-BackendApplication", + "request": "launch", + "cwd": "${workspaceFolder}", + "mainClass": "com.uga.backend.BackendApplication", + "projectName": "backend", + "args": "", + "envFile": "${workspaceFolder}/.env" + } + ] +} diff --git a/backend/node_modules/.package-lock.json b/backend/node_modules/.package-lock.json new file mode 100644 index 0000000..ad0a0ec --- /dev/null +++ b/backend/node_modules/.package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "backend", + "lockfileVersion": 2, + "requires": true, + "packages": {} +} diff --git a/backend/package-lock.json b/backend/package-lock.json new file mode 100644 index 0000000..ad0a0ec --- /dev/null +++ b/backend/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "backend", + "lockfileVersion": 2, + "requires": true, + "packages": {} +} diff --git a/backend/package.json b/backend/package.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/backend/package.json @@ -0,0 +1 @@ +{} diff --git a/my-app/package-lock.json b/my-app/package-lock.json index 51eb551..a0f777d 100644 --- a/my-app/package-lock.json +++ b/my-app/package-lock.json @@ -21,6 +21,7 @@ "react-dom": "^18.2.0", "react-router-dom": "^6.8.1", "react-scripts": "5.0.1", + "react-toastify": "^9.1.2", "web-vitals": "^2.1.4" }, "devDependencies": { @@ -6495,6 +6496,14 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "engines": { + "node": ">=6" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -15983,6 +15992,18 @@ } } }, + "node_modules/react-toastify": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.2.tgz", + "integrity": "sha512-PBfzXO5jMGEtdYR5jxrORlNZZe/EuOkwvwKijMatsZZm8IZwLj01YvobeJYNjFcA6uy6CVrx2fzL9GWbhWPTDA==", + "dependencies": { + "clsx": "^1.1.1" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -23589,6 +23610,11 @@ "wrap-ansi": "^7.0.0" } }, + "clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==" + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -30263,6 +30289,14 @@ "workbox-webpack-plugin": "^6.4.1" } }, + "react-toastify": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.2.tgz", + "integrity": "sha512-PBfzXO5jMGEtdYR5jxrORlNZZe/EuOkwvwKijMatsZZm8IZwLj01YvobeJYNjFcA6uy6CVrx2fzL9GWbhWPTDA==", + "requires": { + "clsx": "^1.1.1" + } + }, "react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", diff --git a/my-app/package.json b/my-app/package.json index 4b1fd5e..d88d051 100644 --- a/my-app/package.json +++ b/my-app/package.json @@ -16,8 +16,8 @@ "react-dom": "^18.2.0", "react-router-dom": "^6.8.1", "react-scripts": "5.0.1", - "web-vitals": "^2.1.4", - "firebase": "^9.17.2" + "react-toastify": "^9.1.2", + "web-vitals": "^2.1.4" }, "scripts": { "start": "react-scripts start", diff --git a/my-app/src/components/ParkingPassSwap/ParkingPassMain.jsx b/my-app/src/components/ParkingPassSwap/ParkingPassMain.jsx index af9cc3b..f7d257c 100644 --- a/my-app/src/components/ParkingPassSwap/ParkingPassMain.jsx +++ b/my-app/src/components/ParkingPassSwap/ParkingPassMain.jsx @@ -1,6 +1,7 @@ import React, { useEffect, useState } from 'react'; +import { ToastContainer, toast } from 'react-toastify'; +import 'react-toastify/dist/ReactToastify.css'; import { Container, Row, Col, Button, Select, Form } from 'react-bootstrap'; - import ParkingPass from './ParkingPass'; import AddParkingPassModal from './AddParkingPassModal.jsx'; import './ParkingPassMain.css'; @@ -13,6 +14,7 @@ const ParkingPassMain = () => { maxPrice: 999, lot: 'Any', }); + const [myPromise, setPromise] = useState(); const getPasses = async () => { const response = await fetch('http://localhost:8080/api/parking/getAll'); @@ -50,114 +52,165 @@ const ParkingPassMain = () => { setFilterState(originalState); }; + // Another way to call the toast message + function notifySuccess(text) { + toast.success(text, { + position: 'top-center', + autoClose: 3000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: 'colored', + }); + } + useEffect(() => { - getPasses(); + console.log('useEffect running'); + // showToastMessage(); // reusable toast message + setPromise(getPasses()); }, []); useEffect(() => { setPassesToShow(filterPasses(filterState)); - }, [passes]); + if (passes.length == 0 && myPromise) { + // For some reason, the toast message is called twice. I found out that it's b/c of React.Strictmode for the index.js file + // Removing the wrapper component fixes the problem + toast.promise( + myPromise, + { + pending: 'Retrieving Data', + success: 'Data Successfully Displayed', + error: 'Error when fetching data. Turn on Backend', + }, + { + style: { + minWidth: '380px', + }, + success: { + duration: 5000, + }, + } + ); + } + }, [passes, myPromise]); const handleAddPass = newPass => { setPasses([...passes, newPass]); + notifySuccess('The Parking Pass was added successfully!'); }; return ( - - - - - - Lot - - - - - - - - - - Max Price ($) - - - - - - - - - - - - - - {passesToShow.map(pass => { - return ; - })} - - - - setShowAddModal(false)} - onSubmit={handleAddPass} + <> + + + + + + Lot + + + + + + + + + + Max Price ($) + + + + + + + + + + + + + + {passesToShow.map(pass => { + return ; + })} + + + + setShowAddModal(false)} + onSubmit={handleAddPass} + /> + + - + ); }; diff --git a/my-app/src/components/TicketPage/TicketPage.jsx b/my-app/src/components/TicketPage/TicketPage.jsx index 71643cb..c62fcb0 100644 --- a/my-app/src/components/TicketPage/TicketPage.jsx +++ b/my-app/src/components/TicketPage/TicketPage.jsx @@ -1,4 +1,5 @@ import React, { useEffect, useState } from 'react'; +import { ToastContainer, toast } from 'react-toastify'; import { Container, Row, Col, Button, Select, Form } from 'react-bootstrap'; import Ticket from './Ticket'; @@ -13,6 +14,7 @@ const TicketPage = () => { maxPrice: 999, team: 'Any', }); + const [myPromise, setPromise] = useState(); const handleChange = event => { const { name, value } = event.target; @@ -47,126 +49,167 @@ const TicketPage = () => { const getTickets = async () => { const response = await fetch('http://localhost:8080/api/tickets/getAll'); const json = await response.json(); + console.log(json); setTickets(json); setTicketsToShow(json); }; + function notifySuccess(text) { + toast.success(text, { + position: 'top-center', + autoClose: 3000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: 'colored', + }); + } + useEffect(() => { - getTickets(); + setPromise(getTickets()); }, []); useEffect(() => { setTicketsToShow(filterTickets(filterState)); - }, [tickets]); + if (tickets.length == 0 && myPromise) { + // For some reason, the toast message is called twice. I found out that it's b/c of React.Strictmode for the index.js file + // Removing the wrapper component fixes the problem + toast.promise( + myPromise, + { + pending: 'Retrieving Data', + success: 'Data Successfully Displayed', + error: 'Error when fetching data. Turn on Backend', + }, + { + style: { + minWidth: '380px', + }, + success: { + duration: 5000, + }, + } + ); + } + }, [tickets, myPromise]); const handleAddTicket = newTicket => { setTickets([...tickets, newTicket]); + notifySuccess('The Ticket has been added successfully!'); }; return ( - - - - - - Team - - - - - - - - - - - - - - - - - - Max Price ($) - - - - - - - - - - - - - - {ticketsToShow.map(ticket => { - return ; - })} - - - - setShowAddModal(false)} - onSubmit={handleAddTicket} + <> + + + + + + Team + + + + + + + + + + Max Price ($) + + + + + + + + + + + + + + {ticketsToShow.map(ticket => { + return ; + })} + + + + setShowAddModal(false)} + onSubmit={handleAddTicket} + /> + + - + ); }; diff --git a/my-app/src/index.js b/my-app/src/index.js index ba3d8ca..89187f4 100644 --- a/my-app/src/index.js +++ b/my-app/src/index.js @@ -7,6 +7,7 @@ import 'bootstrap/dist/css/bootstrap.css'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( + // You can disable React.StrictMode in your development environment if you do not want it to run the additional checks and render twice.