diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml new file mode 100644 index 00000000..1450ef5e --- /dev/null +++ b/.github/workflows/workflow.yml @@ -0,0 +1,50 @@ +name: CI + +on: + push: + branches: + - '*' + pull_request: + branches: + - '*' + +jobs: + build: + runs-on: ubuntu-latest + + services: + postgres: + image: postgis/postgis + env: + POSTGRES_DB: ride + POSTGRES_USER: administrator + POSTGRES_PASSWORD: verySecretPassword + ports: + - 5432:5432 + # Options to keep the container running until the end of the job + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + steps: + - uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.10' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r application/requirements.txt + + - name: Run tests + run: | + export SQLALCHEMY_DATABASE_URI=postgresql+psycopg://administrator:verySecretPassword@localhost:5432/ride + cd application/app/tests + python -m unittest discover + + diff --git a/application/app/frontend/package.json b/application/app/frontend/package.json index 47378c18..9f2486ff 100644 --- a/application/app/frontend/package.json +++ b/application/app/frontend/package.json @@ -4,6 +4,10 @@ "private": true, "proxy": "http://localhost:8080", "dependencies": { + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.5", + "@mui/icons-material": "^5.15.17", + "@mui/material": "^5.15.17", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", diff --git a/application/app/frontend/src/App.js b/application/app/frontend/src/App.js index defa32e3..9e7bd2c6 100644 --- a/application/app/frontend/src/App.js +++ b/application/app/frontend/src/App.js @@ -4,11 +4,14 @@ import TripRequest from './components/TripRequest'; import LoginEmail from './components/loginEmail'; import { UserProvider, UserContext } from './components/UserContext'; import './App.css'; +import RideRequests from './components/RideRequests'; import { useContext } from 'react'; import TripDetail from './components/TripDetail' import TripList from './components/TripList' import SimpleMap from './components/Map'; import RideRequest from './components/RideRequest'; +import TripsPage from './pages/TripsPage'; +import TripInformation from './pages/TripInformationPage'; /** * App component - the main component of the application. @@ -42,11 +45,26 @@ const App = () => { } /> + + + + } /> } /> + + + + } /> + + + + } /> diff --git a/application/app/frontend/src/api/api.js b/application/app/frontend/src/api/api.js index e16b1d7a..dfe7e810 100644 --- a/application/app/frontend/src/api/api.js +++ b/application/app/frontend/src/api/api.js @@ -51,4 +51,70 @@ export const fetchCoordinates = async (address) => { } else { throw new Error("Failed to fetch coordinates."); } +}; + + +export const getPendingTripRequests = async (username) => { + const url = "/trip_requests/get/pending"; + try { + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, + body: JSON.stringify({username}) + }); + if (response.ok) { + return response.json(); + } else { + throw new Error('Failed to fetch pending trip requests'); + } + } catch (error) { + throw error; + } +}; + +export const getNearbyTripRequests = async (tripId, username) => { + const url = "/trip/get/pending_nearby"; + try { + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, + body: JSON.stringify({ trip_id: tripId, username }) + }); + if (response.ok) { + return response.json(); + } else { + throw new Error('Failed to fetch nearby trip requests'); + } + } catch (error) { + throw error; + } + }; + + export const approveRequest = async (username, tripRequestId, tripId) => { + const url = "/trip/post/approved"; + try { + const response = await fetch(url, { + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ username, trip_request_id: tripRequestId, trip_id: tripId }), + }); + if (response.ok) { + return await response.json(); + } else { + const errorResponse = await response.json(); + throw new Error(errorResponse.message); + } + } catch (error) { + console.error('Error approving trip request:', error); + throw error; + } }; \ No newline at end of file diff --git a/application/app/frontend/src/components/ApprovedTripCard.js b/application/app/frontend/src/components/ApprovedTripCard.js new file mode 100644 index 00000000..d6b5fdb2 --- /dev/null +++ b/application/app/frontend/src/components/ApprovedTripCard.js @@ -0,0 +1,17 @@ +import React from 'react'; +import '../styles/TripCard.css'; + +const ApprovedTripCard = ({ riderName, startingPoint, destination, onClickCard }) => { + return ( +
+
+

{riderName}

+

{startingPoint}

+

{destination}

+
+
+ + ); +}; + +export default ApprovedTripCard; \ No newline at end of file diff --git a/application/app/frontend/src/components/RideRequest.js b/application/app/frontend/src/components/RideRequest.js index 5bf49476..a36c067d 100644 --- a/application/app/frontend/src/components/RideRequest.js +++ b/application/app/frontend/src/components/RideRequest.js @@ -97,29 +97,29 @@ function RideRequest() { return (
-

Create Ride Request

+

Create Ride Request

- +
- +
); } diff --git a/application/app/frontend/src/components/RideRequests.js b/application/app/frontend/src/components/RideRequests.js new file mode 100644 index 00000000..3070e1e7 --- /dev/null +++ b/application/app/frontend/src/components/RideRequests.js @@ -0,0 +1,74 @@ +import React, { useState, useEffect, useContext } from 'react'; +import RiderCard from './RiderCard'; +import { getNearbyTripRequests, approveRequest } from '../api/api'; +import { UserContext } from './UserContext'; +import { useParams } from 'react-router-dom'; +import Alert from '@mui/material/Alert'; + +function RideRequests() { + const { user } = useContext(UserContext); + const username = user.username; + const { tripId } = useParams(); + const [tripRequests, setTripRequests] = useState([]); + const [errorMessage, setErrorMessage] = useState(''); + const [successMessage, setSuccessMessage] = useState(''); + + useEffect(() => { + const fetchTripRequests = async () => { + try { + const response = await getNearbyTripRequests(tripId, username); + + if (response && Array.isArray(response)) { + setTripRequests(response); + } else { + setErrorMessage('Data received is not valid'); + console.error('Data received is not an array:', response); + } + } catch (error) { + setErrorMessage('Failed to fetch trip requests.'); + console.error('Failed to fetch trip requests:', error); + } + }; + fetchTripRequests(); + }, [tripId, username]); + + const handleApprove = async (tripRequestId) => { + try { + setErrorMessage(''); + setSuccessMessage(''); + const response = await approveRequest(username, tripRequestId, tripId); + setSuccessMessage(response.message); + setTripRequests(tripRequests.filter(request => request.id !== tripRequestId)); + } catch (error) { + console.error('Failed to approve ride request:', error); + setErrorMessage(error.message); + } + }; + + return ( +
+

Available Ride Requests

+ {errorMessage && {errorMessage}} + {successMessage && {successMessage}} +
+
+ {tripRequests.length > 0 ? ( + tripRequests.map(tripRequest => ( + handleApprove(tripRequest.id)} + /> + )) + ) : ( +

No ride requests available.

+ )} +
+
+
+ ); +}; + +export default RideRequests; diff --git a/application/app/frontend/src/components/RiderCard.js b/application/app/frontend/src/components/RiderCard.js index 88f91102..b5959902 100644 --- a/application/app/frontend/src/components/RiderCard.js +++ b/application/app/frontend/src/components/RiderCard.js @@ -1,16 +1,26 @@ import React from 'react'; +import CheckCircleIcon from '@mui/icons-material/CheckCircle'; import '../styles/RiderCard.css'; -const RiderCard = ({ riderName, startingPoint, destination }) => { +const RiderCard = ({ riderName, startingPoint, destination, onApprove }) => { return (
+

{riderName}

+
-

{riderName}

{startingPoint}

{destination}

+
+
+ +
+
+
); }; -export default RiderCard; \ No newline at end of file +export default RiderCard; diff --git a/application/app/frontend/src/components/Routing.js b/application/app/frontend/src/components/Routing.js index c0503cff..cc6ddf1c 100644 --- a/application/app/frontend/src/components/Routing.js +++ b/application/app/frontend/src/components/Routing.js @@ -2,14 +2,15 @@ import L from "leaflet"; import { createControlComponent } from "@react-leaflet/core"; import "leaflet-routing-machine"; import markerIconPng from "leaflet/dist/images/marker-icon.png" + const customIcon = new L.Icon({ iconUrl: markerIconPng, iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], - }); +}); -const createRoutineMachineLayer = ({waypoints}) => { +const createRoutineMachineLayer = ({ waypoints }) => { const instance = L.Routing.control({ waypoints: waypoints.map(wp => L.latLng(wp.lat, wp.lng)), lineOptions: { @@ -26,10 +27,19 @@ const createRoutineMachineLayer = ({waypoints}) => { fitSelectedRoutes: false, showAlternatives: false, show: false, - createMarker: function(i, wp) { - return L.marker(wp.latLng, { + createMarker: function(i, wp, n) { + const marker = L.marker(wp.latLng, { icon: customIcon }); + // Adding a popup to display the name + // if (waypoints[i].name) { + // marker.bindPopup(waypoints[i].name); + // } + // Alternatively, you can use a tooltip + if (waypoints[i].name) { + marker.bindTooltip(waypoints[i].name, {permanent: true}); + } + return marker; } }); @@ -38,4 +48,4 @@ const createRoutineMachineLayer = ({waypoints}) => { const RoutingMachine = createControlComponent(createRoutineMachineLayer); -export default RoutingMachine; \ No newline at end of file +export default RoutingMachine; diff --git a/application/app/frontend/src/components/TripCard.js b/application/app/frontend/src/components/TripCard.js index d8173de3..324f667a 100644 --- a/application/app/frontend/src/components/TripCard.js +++ b/application/app/frontend/src/components/TripCard.js @@ -29,4 +29,4 @@ const TripCard = ({ trip }) => { ); }; - export default TripCard; \ No newline at end of file + export default TripCard; diff --git a/application/app/frontend/src/components/TripRequest.js b/application/app/frontend/src/components/TripRequest.js index 5955d903..4cb5f48d 100644 --- a/application/app/frontend/src/components/TripRequest.js +++ b/application/app/frontend/src/components/TripRequest.js @@ -107,36 +107,40 @@ function TripRequest() { }; return ( -
-

Create Trip

+
+
+

Create Trip

-
- +
+
+ +
); } diff --git a/application/app/frontend/src/components/loginEmail.js b/application/app/frontend/src/components/loginEmail.js index 457ff235..4c00f81c 100644 --- a/application/app/frontend/src/components/loginEmail.js +++ b/application/app/frontend/src/components/loginEmail.js @@ -51,9 +51,9 @@ function LoginEmail() { return (
-

Login

-
+

Login

+
-
-
+
+
-
-
+
+
-
+
diff --git a/application/app/frontend/src/pages/TripInformationPage.js b/application/app/frontend/src/pages/TripInformationPage.js new file mode 100644 index 00000000..bde386ec --- /dev/null +++ b/application/app/frontend/src/pages/TripInformationPage.js @@ -0,0 +1,40 @@ +import React from 'react'; +import DriverInformationCard from '../components/DriverInformationCard'; +import '../styles/TripInformationPage.css' +import { useParams } from 'react-router-dom'; + +const driver = { + name: "Tom Jerry", + carRepoNo: "AAA111", + estimatedPickupTime: "09:30 AM" +} + +const TripInformation = () => { + const { tripId } = useParams(); + + return ( +
+
+

Trip Information

+
+
+
+ +
+
+

{tripId}

+

pickup point

+

{"pickup"}

+

destination

+

{"destination"}

+
+
+
+ ) +} + +export default TripInformation; \ No newline at end of file diff --git a/application/app/frontend/src/pages/TripsPage.js b/application/app/frontend/src/pages/TripsPage.js new file mode 100644 index 00000000..3823b154 --- /dev/null +++ b/application/app/frontend/src/pages/TripsPage.js @@ -0,0 +1,73 @@ +import React, { useState, useEffect, useContext } from 'react'; +import { useNavigate } from "react-router-dom"; +import { UserContext } from '../components/UserContext'; +import '../styles/TripCard.css'; +import ApprovedTripCard from '../components/ApprovedTripCard'; + +const TripsPage = () => { + const [trips, setTrips] = useState(''); + const [loading, setLoading] = useState(true); + const { user } = useContext(UserContext); + + const navigate = useNavigate() + const tripInfo = (passengerId) => { + navigate(`/trips/${passengerId}`); + } + + useEffect(() => { + const fetchTrips = async () => { + try { + const response = await fetch('/trip/get/approved', { // Use your actual base URL here + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, + body: JSON.stringify({ + trip_id: "d0c0db22-b4ce-4578-8be5-14f5cc2b30fb", + username: user.username + }), + }); + + if (response.ok) { + const data = await response.json(); + setTrips(data.accepted_trips); + } else { + console.error('Failed to fetch trips'); + } + } catch (error) { + console.error('Error:', error); + } finally { + setLoading(false); + console.log(trips); + } + }; + + fetchTrips(); + }, [trips, user.username]); + + if (loading) { + return
Loading approved trips...
; + } + + if (!trips.length) { + return
Driver hasn't approve any trips
; + } + + return ( +
+

Trips

+
+ {trips.map((trip) => ( + tripInfo(trip)} + /> + ))} +
+
+ ); +}; +export default TripsPage; \ No newline at end of file diff --git a/application/app/frontend/src/styles/DriverInformationCard.css b/application/app/frontend/src/styles/DriverInformationCard.css index 5aba1c48..8106a76e 100644 --- a/application/app/frontend/src/styles/DriverInformationCard.css +++ b/application/app/frontend/src/styles/DriverInformationCard.css @@ -1,9 +1,11 @@ .card { border: 1px solid #ccc; border-radius: 8px; - padding: 16px; + padding: 25px; margin: 10px; width: 300px; display: inline-block; vertical-align: top; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + background-color: #fff; } \ No newline at end of file diff --git a/application/app/frontend/src/styles/LoginEmail.css b/application/app/frontend/src/styles/LoginEmail.css index 8840a33c..fe26e1dd 100644 --- a/application/app/frontend/src/styles/LoginEmail.css +++ b/application/app/frontend/src/styles/LoginEmail.css @@ -1,16 +1,18 @@ /* LoginEmail.css */ .login-container { - width: 100%; + width: 20vw; border-radius: 8px; background-color: #ffffff; - padding: 20px; + padding: 40px 50px; + margin: 0 auto; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); } .login-container h2 { text-align: center; color: #333; - margin-bottom: 20px; + margin-bottom: 40px; } .login-container form { @@ -19,7 +21,7 @@ } .login-container label { - margin-bottom: 5px; + margin-bottom: 15px; color: #666; } @@ -46,7 +48,7 @@ } .login-container button { - padding: 10px; + padding: 15px; color: #fff; background-color: #007BFF; border: none; @@ -55,6 +57,7 @@ transition: background-color 0.3s; width: 100%; box-sizing: border-box; + margin-top: 15px; } @@ -66,4 +69,4 @@ padding: 10px; background-color: #fff; color: #333; -} +} \ No newline at end of file diff --git a/application/app/frontend/src/styles/RiderCard.css b/application/app/frontend/src/styles/RiderCard.css index e36050c7..1ff073d3 100644 --- a/application/app/frontend/src/styles/RiderCard.css +++ b/application/app/frontend/src/styles/RiderCard.css @@ -1,15 +1,41 @@ .rider-card { border: 1px solid #ccc; + background-color: #ffffff; border-radius: 8px; - padding: 16px; + padding: 10px; margin: 10px; - width: 300px; + width: 25vh; + height: 25vh; display: inline-block; vertical-align: top; -} - -.rider-card img { + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1), 0 6px 20px rgba(0, 0, 0, 0.1); + } + + .rider-card img { width: 100%; height: auto; margin-top: 8px; -} \ No newline at end of file + } + + .actions { + margin-top: 30px; + } + + .approve, .decline { + border: none; + background-color: transparent; + cursor: pointer; + display: flex; + align-items: center; + padding: 5px 10px; + font-size: 16px; + } + + .approve svg, .decline svg { + margin-right: 5px; + } + + .rider-cards { + margin-left: 15px; + margin-right: 15px; + } \ No newline at end of file diff --git a/application/app/frontend/src/styles/TripCard.css b/application/app/frontend/src/styles/TripCard.css index 077f6e63..0ed86329 100644 --- a/application/app/frontend/src/styles/TripCard.css +++ b/application/app/frontend/src/styles/TripCard.css @@ -1,17 +1,16 @@ .trip-card { border: 1px solid #ccc; border-radius: 8px; - padding: 16px; + padding: 25px; margin: 16px; cursor: pointer; transition: box-shadow 0.3s; - } - - .trip-card:hover { - box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + background-color: #fff; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); } .trip-card h3 { - margin-top: 0; + margin-bottom: 40px; + text-align: center; + color: #333; } - \ No newline at end of file diff --git a/application/app/frontend/src/styles/TripRequest.module.css b/application/app/frontend/src/styles/TripRequest.module.css index 62433518..57884aa3 100644 --- a/application/app/frontend/src/styles/TripRequest.module.css +++ b/application/app/frontend/src/styles/TripRequest.module.css @@ -4,9 +4,9 @@ flex-direction: column; align-items: center; gap: 20px; - margin: 0 auto; - padding: 30px; - width: 80%; + margin: 10px; + padding: 50px; + width: 50vw; max-width: 350px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); border-radius: 8px; @@ -24,9 +24,9 @@ } .inputField, .errorInput { - width: 100%; + width: 15vw; padding: 8px; - margin-top: 4px; + margin-bottom: 10px; border: 1px solid #ccc; border-radius: 4px; font-size: 14px; @@ -37,7 +37,7 @@ } .button { - width: 100%; + width: 25vh; padding: 10px; font-size: 16px; margin-top: 20px; @@ -53,7 +53,7 @@ background-color: #0056b3; } -h1 { +.tripRequest h1 { text-align: center; margin: 10; } @@ -62,13 +62,19 @@ h1 { background-color: #007BFF; color: white; border: none; - padding: 10px 20px; + padding: 8px 16px; border-radius: 4px; cursor: pointer; transition: background-color 0.3s ease; margin-top: 20px; + margin-left: 2px; + margin-right: 2px; } .blueButton:hover { - background-color: #0056b3; + background-color: #0056b3; } + +.formText { + margin-bottom: 10px; +} \ No newline at end of file diff --git a/application/app/frontend/yarn.lock b/application/app/frontend/yarn.lock index a65c646f..6273d3b4 100644 --- a/application/app/frontend/yarn.lock +++ b/application/app/frontend/yarn.lock @@ -169,7 +169,7 @@ dependencies: "@babel/types" "^7.24.5" -"@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.22.15", "@babel/helper-module-imports@^7.24.1", "@babel/helper-module-imports@^7.24.3": +"@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.22.15", "@babel/helper-module-imports@^7.24.1", "@babel/helper-module-imports@^7.24.3": version "7.24.3" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz#6ac476e6d168c7c23ff3ba3cf4f7841d46ac8128" integrity sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg== @@ -1116,7 +1116,7 @@ resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== -"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.23.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.18.3", "@babel/runtime@^7.23.2", "@babel/runtime@^7.23.9", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.24.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.5.tgz#230946857c053a36ccc66e1dd03b17dd0c4ed02c" integrity sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g== @@ -1273,6 +1273,113 @@ resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz#2cbcf822bf3764c9658c4d2e568bd0c0cb748016" integrity sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw== +"@emotion/babel-plugin@^11.11.0": + version "11.11.0" + resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz#c2d872b6a7767a9d176d007f5b31f7d504bb5d6c" + integrity sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ== + dependencies: + "@babel/helper-module-imports" "^7.16.7" + "@babel/runtime" "^7.18.3" + "@emotion/hash" "^0.9.1" + "@emotion/memoize" "^0.8.1" + "@emotion/serialize" "^1.1.2" + babel-plugin-macros "^3.1.0" + convert-source-map "^1.5.0" + escape-string-regexp "^4.0.0" + find-root "^1.1.0" + source-map "^0.5.7" + stylis "4.2.0" + +"@emotion/cache@^11.11.0": + version "11.11.0" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.11.0.tgz#809b33ee6b1cb1a625fef7a45bc568ccd9b8f3ff" + integrity sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ== + dependencies: + "@emotion/memoize" "^0.8.1" + "@emotion/sheet" "^1.2.2" + "@emotion/utils" "^1.2.1" + "@emotion/weak-memoize" "^0.3.1" + stylis "4.2.0" + +"@emotion/hash@^0.9.1": + version "0.9.1" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.1.tgz#4ffb0055f7ef676ebc3a5a91fb621393294e2f43" + integrity sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ== + +"@emotion/is-prop-valid@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz#d4175076679c6a26faa92b03bb786f9e52612337" + integrity sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw== + dependencies: + "@emotion/memoize" "^0.8.1" + +"@emotion/memoize@^0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17" + integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA== + +"@emotion/react@^11.11.4": + version "11.11.4" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.11.4.tgz#3a829cac25c1f00e126408fab7f891f00ecc3c1d" + integrity sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw== + dependencies: + "@babel/runtime" "^7.18.3" + "@emotion/babel-plugin" "^11.11.0" + "@emotion/cache" "^11.11.0" + "@emotion/serialize" "^1.1.3" + "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1" + "@emotion/utils" "^1.2.1" + "@emotion/weak-memoize" "^0.3.1" + hoist-non-react-statics "^3.3.1" + +"@emotion/serialize@^1.1.2", "@emotion/serialize@^1.1.3", "@emotion/serialize@^1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.4.tgz#fc8f6d80c492cfa08801d544a05331d1cc7cd451" + integrity sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ== + dependencies: + "@emotion/hash" "^0.9.1" + "@emotion/memoize" "^0.8.1" + "@emotion/unitless" "^0.8.1" + "@emotion/utils" "^1.2.1" + csstype "^3.0.2" + +"@emotion/sheet@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.2.tgz#d58e788ee27267a14342303e1abb3d508b6d0fec" + integrity sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA== + +"@emotion/styled@^11.11.5": + version "11.11.5" + resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.11.5.tgz#0c5c8febef9d86e8a926e663b2e5488705545dfb" + integrity sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ== + dependencies: + "@babel/runtime" "^7.18.3" + "@emotion/babel-plugin" "^11.11.0" + "@emotion/is-prop-valid" "^1.2.2" + "@emotion/serialize" "^1.1.4" + "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1" + "@emotion/utils" "^1.2.1" + +"@emotion/unitless@^0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.1.tgz#182b5a4704ef8ad91bde93f7a860a88fd92c79a3" + integrity sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ== + +"@emotion/use-insertion-effect-with-fallbacks@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz#08de79f54eb3406f9daaf77c76e35313da963963" + integrity sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw== + +"@emotion/utils@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.1.tgz#bbab58465738d31ae4cb3dbb6fc00a5991f755e4" + integrity sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg== + +"@emotion/weak-memoize@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6" + integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww== + "@eslint-community/eslint-utils@^4.2.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -1305,6 +1412,33 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== +"@floating-ui/core@^1.0.0": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.1.tgz#a4e6fef1b069cda533cbc7a4998c083a37f37573" + integrity sha512-42UH54oPZHPdRHdw6BgoBD6cg/eVTmVrFcgeRDM3jbO7uxSoipVcmcIGFcA5jmOHO5apcyvBhkSKES3fQJnu7A== + dependencies: + "@floating-ui/utils" "^0.2.0" + +"@floating-ui/dom@^1.0.0": + version "1.6.5" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.5.tgz#323f065c003f1d3ecf0ff16d2c2c4d38979f4cb9" + integrity sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw== + dependencies: + "@floating-ui/core" "^1.0.0" + "@floating-ui/utils" "^0.2.0" + +"@floating-ui/react-dom@^2.0.8": + version "2.0.9" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.0.9.tgz#264ba8b061000baa132b5910f0427a6acf7ad7ce" + integrity sha512-q0umO0+LQK4+p6aGyvzASqKbKOJcAHJ7ycE9CuUvfx3s9zTHWmGJTPOIlM/hmSBfUfg/XfY5YhLBLR/LHwShQQ== + dependencies: + "@floating-ui/dom" "^1.0.0" + +"@floating-ui/utils@^0.2.0": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.2.tgz#d8bae93ac8b815b2bd7a98078cf91e2724ef11e5" + integrity sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw== + "@humanwhocodes/config-array@^0.11.14": version "0.11.14" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" @@ -1643,6 +1777,97 @@ resolved "https://registry.yarnpkg.com/@mapbox/polyline/-/polyline-0.2.0.tgz#6e25980744aa22331f94b645a542c02d3fcfee97" integrity sha512-GCddO0iw6AzOQqZgBmjEQI9Pgo40/yRgkTkikGctE01kNBN0ThWYuAnTD+hRWrAWMV6QJ0rNm4m8DAsaAXE7Pg== +"@mui/base@5.0.0-beta.40": + version "5.0.0-beta.40" + resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-beta.40.tgz#1f8a782f1fbf3f84a961e954c8176b187de3dae2" + integrity sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ== + dependencies: + "@babel/runtime" "^7.23.9" + "@floating-ui/react-dom" "^2.0.8" + "@mui/types" "^7.2.14" + "@mui/utils" "^5.15.14" + "@popperjs/core" "^2.11.8" + clsx "^2.1.0" + prop-types "^15.8.1" + +"@mui/core-downloads-tracker@^5.15.17": + version "5.15.17" + resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.17.tgz#ce8f3dff6ec11c8294d346997f6065eb23fa99be" + integrity sha512-DVAejDQkjNnIac7MfP8sLzuo7fyrBPxNdXe+6bYqOqg1z2OPTlfFAejSNzWe7UenRMuFu9/AyFXj/X2vN2w6dA== + +"@mui/icons-material@^5.15.17": + version "5.15.17" + resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.15.17.tgz#518c02354036f7df28c8f9890b1db6a3269fcc2f" + integrity sha512-xVzl2De7IY36s/keHX45YMiCpsIx3mNv2xwDgtBkRSnZQtVk+Gqufwj1ktUxEyjzEhBl0+PiNJqYC31C+n1n6A== + dependencies: + "@babel/runtime" "^7.23.9" + +"@mui/material@^5.15.17": + version "5.15.17" + resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.15.17.tgz#1e30bacc940573813cc418aebd4484708a407ba6" + integrity sha512-ru/MLvTkCh0AZXmqwIpqGTOoVBS/sX48zArXq/DvktxXZx4fskiRA2PEc7Rk5ZlFiZhKh4moL4an+l8zZwq49Q== + dependencies: + "@babel/runtime" "^7.23.9" + "@mui/base" "5.0.0-beta.40" + "@mui/core-downloads-tracker" "^5.15.17" + "@mui/system" "^5.15.15" + "@mui/types" "^7.2.14" + "@mui/utils" "^5.15.14" + "@types/react-transition-group" "^4.4.10" + clsx "^2.1.0" + csstype "^3.1.3" + prop-types "^15.8.1" + react-is "^18.2.0" + react-transition-group "^4.4.5" + +"@mui/private-theming@^5.15.14": + version "5.15.14" + resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.15.14.tgz#edd9a82948ed01586a01c842eb89f0e3f68970ee" + integrity sha512-UH0EiZckOWcxiXLX3Jbb0K7rC8mxTr9L9l6QhOZxYc4r8FHUkefltV9VDGLrzCaWh30SQiJvAEd7djX3XXY6Xw== + dependencies: + "@babel/runtime" "^7.23.9" + "@mui/utils" "^5.15.14" + prop-types "^15.8.1" + +"@mui/styled-engine@^5.15.14": + version "5.15.14" + resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.15.14.tgz#168b154c4327fa4ccc1933a498331d53f61c0de2" + integrity sha512-RILkuVD8gY6PvjZjqnWhz8fu68dVkqhM5+jYWfB5yhlSQKg+2rHkmEwm75XIeAqI3qwOndK6zELK5H6Zxn4NHw== + dependencies: + "@babel/runtime" "^7.23.9" + "@emotion/cache" "^11.11.0" + csstype "^3.1.3" + prop-types "^15.8.1" + +"@mui/system@^5.15.15": + version "5.15.15" + resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.15.15.tgz#658771b200ce3c4a0f28e58169f02e5e718d1c53" + integrity sha512-aulox6N1dnu5PABsfxVGOZffDVmlxPOVgj56HrUnJE8MCSh8lOvvkd47cebIVQQYAjpwieXQXiDPj5pwM40jTQ== + dependencies: + "@babel/runtime" "^7.23.9" + "@mui/private-theming" "^5.15.14" + "@mui/styled-engine" "^5.15.14" + "@mui/types" "^7.2.14" + "@mui/utils" "^5.15.14" + clsx "^2.1.0" + csstype "^3.1.3" + prop-types "^15.8.1" + +"@mui/types@^7.2.14": + version "7.2.14" + resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.14.tgz#8a02ac129b70f3d82f2f9b76ded2c8d48e3fc8c9" + integrity sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ== + +"@mui/utils@^5.15.14": + version "5.15.14" + resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.15.14.tgz#e414d7efd5db00bfdc875273a40c0a89112ade3a" + integrity sha512-0lF/7Hh/ezDv5X7Pry6enMsbYyGKjADzvHyo3Qrc/SSlTsQ1VkbDMbH0m2t3OR5iIVLwMoxwM7yGd+6FCMtTFA== + dependencies: + "@babel/runtime" "^7.23.9" + "@types/prop-types" "^15.7.11" + prop-types "^15.8.1" + react-is "^18.2.0" + "@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": version "5.1.1-v1" resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129" @@ -1689,6 +1914,11 @@ schema-utils "^3.0.0" source-map "^0.7.3" +"@popperjs/core@^2.11.8": + version "2.11.8" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" + integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== + "@react-leaflet/core@^2.1.0": version "2.1.0" resolved "https://registry.yarnpkg.com/@react-leaflet/core/-/core-2.1.0.tgz#383acd31259d7c9ae8fb1b02d5e18fe613c2a13d" @@ -2137,7 +2367,7 @@ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f" integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA== -"@types/prop-types@*": +"@types/prop-types@*", "@types/prop-types@^15.7.11": version "15.7.12" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6" integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q== @@ -2164,6 +2394,13 @@ dependencies: "@types/react" "*" +"@types/react-transition-group@^4.4.10": + version "4.4.10" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.10.tgz#6ee71127bdab1f18f11ad8fb3322c6da27c327ac" + integrity sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q== + dependencies: + "@types/react" "*" + "@types/react@*": version "18.3.1" resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.1.tgz#fed43985caa834a2084d002e4771e15dfcbdbe8e" @@ -3275,6 +3512,11 @@ cliui@^7.0.2: strip-ansi "^6.0.0" wrap-ansi "^7.0.0" +clsx@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" + integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -3412,7 +3654,7 @@ content-type@~1.0.4, content-type@~1.0.5: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== -convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: +convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.9.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== @@ -3680,7 +3922,7 @@ cssstyle@^2.3.0: dependencies: cssom "~0.3.6" -csstype@^3.0.2: +csstype@^3.0.2, csstype@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== @@ -3924,6 +4166,14 @@ dom-converter@^0.2.0: dependencies: utila "~0.4" +dom-helpers@^5.0.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" + integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== + dependencies: + "@babel/runtime" "^7.8.7" + csstype "^3.0.2" + dom-serializer@0: version "0.2.2" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" @@ -4735,6 +4985,11 @@ find-cache-dir@^3.3.1: make-dir "^3.0.2" pkg-dir "^4.1.0" +find-root@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" + integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== + find-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" @@ -5109,6 +5364,13 @@ he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +hoist-non-react-statics@^3.3.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + hoopy@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" @@ -7828,7 +8090,7 @@ prompts@^2.0.1, prompts@^2.4.2: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.8.1: +prop-types@^15.6.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -7961,7 +8223,7 @@ react-error-overlay@^6.0.11: resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb" integrity sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg== -react-is@^16.13.1: +react-is@^16.13.1, react-is@^16.7.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -7971,7 +8233,7 @@ react-is@^17.0.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== -react-is@^18.0.0: +react-is@^18.0.0, react-is@^18.2.0: version "18.3.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== @@ -8058,6 +8320,16 @@ react-scripts@^5.0.1: optionalDependencies: fsevents "^2.3.2" +react-transition-group@^4.4.5: + version "4.4.5" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1" + integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g== + dependencies: + "@babel/runtime" "^7.5.5" + dom-helpers "^5.0.1" + loose-envify "^1.4.0" + prop-types "^15.6.2" + react@^18.3.1: version "18.3.1" resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" @@ -8624,6 +8896,11 @@ source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, sourc resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +source-map@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + source-map@^0.7.3: version "0.7.4" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" @@ -8877,6 +9154,11 @@ stylehacks@^5.1.1: browserslist "^4.21.4" postcss-selector-parser "^6.0.4" +stylis@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51" + integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw== + sucrase@^3.32.0: version "3.35.0" resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263" diff --git a/application/app/tests/base.py b/application/app/tests/base.py new file mode 100644 index 00000000..cf4a86fe --- /dev/null +++ b/application/app/tests/base.py @@ -0,0 +1,18 @@ +import sys +sys.path.append("..") + +from app import create_app +import unittest + +class RideTest(unittest.TestCase): + def setUp(self): + self.app = create_app(config_overrides={ + 'SQLALCHEMY_DATABASE_URI': 'postgresql+psycopg://administrator:verySecretPassword@localhost:5432/ride', + 'TESTING': True + }) + self.client = self.app.test_client() + + + def assertDictSubset(self, expected_subset: dict, whole: dict): + for key, value in expected_subset.items(): + self.assertEqual(whole[key], value) diff --git a/application/app/tests/test_health.py b/application/app/tests/test_health.py new file mode 100644 index 00000000..49ffe0ba --- /dev/null +++ b/application/app/tests/test_health.py @@ -0,0 +1,12 @@ +from base import RideTest +import unittest + +class TestHealth(RideTest): + def test_health(self): + response = self.client.get('/health') + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {'status': 'ok'}) + + +if __name__ == '__main__': + unittest.main() diff --git a/application/app/tests/test_shareride.py b/application/app/tests/test_shareride.py new file mode 100644 index 00000000..0ee753fa --- /dev/null +++ b/application/app/tests/test_shareride.py @@ -0,0 +1,134 @@ +from base import RideTest +import unittest +import json + +PASSENGER_1 = { + "username": "jDoe12", + "password": "53%32", + "name": "John Doe", + "phone_number": "1234567890", + "email": "john.doe1@example.com" + } + +PASSENGER_2 = { + "username": "kWhite34", + "password": "53%34", + "name": "Kylie White", + "phone_number": "1234567890", + "email": "KyWhite@example.com" + } + +DRIVER_1 = { + "username": "Moedab11", + "password": "53%31", + "name": "Mohamad Dabboussi", + "phone_number": "1234567890", + "email": "mohamaddabboussi@example.com", + "max_available_seats": 3, + "licence_plate": "319IRG" + } + +DRIVER_2 = { + "username": "lSmith88", + "password": "53%30", + "name": "Leo Smith", + "phone_number": "1234567890", + "email": "Leosmith@example.com", + "max_available_seats": 3, + "licence_plate": "319IRF" + } + +TRIP_REQUEST_1 = { + "username": "Moedab11", + "start_time": "2024-05-10T10:00:00Z", + "end_time": "2024-05-10T10:30:00Z", + "start_location": {"latitude": 37.7749, "longitude": -122.4194, "address": "123 street road, Brisbane, QLD"}, + "end_location": {"latitude": 37.7750, "longitude": -122.4195, "address": "125 street road, Brisbane, QLD"}, + "seats_remaining": 3, + "distance_addition": 200 + } + +RIDE_REQUEST_2 = { + "username": "jDoe12", + "pickup_location": {"latitude": 37.7751, "longitude": -122.4153, "address": "123 street road, Brisbane, QLD"}, + "dropoff_location": {"latitude": 37.7749, "longitude": -122.4194, "address": "125 street road, Brisbane, QLD"}, + "pickup_window_start": "2024-05-10T10:30:00", + "pickup_window_end": "2024-05-10T11:30:00Z" + } + +INVALID_TRIP_REQUEST = { + "username": "lSmith88", + "start_time": "2024-05-10T07:00:00Z", + "end_time": "2024-05-10T07:30:00Z", + "start_location": {"latitude": -27.4705, "longitude": 153.0260, "address": "Queen Street Mall, Brisbane, QLD"}, + "end_location": {"latitude": -27.4828, "longitude": 153.0283, "address": "Roma Street Parkland, Brisbane, QLD"}, + "seats_remaining": 2, + "distance_addition": 40 + } + +RIDE_REQUEST_1 = { + "username": "kWhite34", + "pickup_location": {"latitude": -27.4711, "longitude": 153.0235, "address": "Post Office Square, Brisbane, QLD"}, + "dropoff_location": {"latitude": -27.4817, "longitude": 153.0292, "address": "The Brisbane Showgrounds, QLD"}, + "pickup_window_start": "2024-05-10T07:00:00", + "pickup_window_end": "2024-05-10T07:30:00Z" + } + + +class TestCreatePassenger(RideTest): + def test_1_create_passenger(self): + + response = self.client.post('/passenger/create', json=PASSENGER_1) + self.assertEqual(response.status_code, 201, "Expected status code to be 201 Created") + self.assertEqual(response.json['name'], PASSENGER_1['name'], "Passenger name should match the request data") + self.assertEqual(response.json['phone_number'], PASSENGER_1['phone_number'], "Passenger phone number should match the request data") + self.assertEqual(response.json['email'], PASSENGER_1['email'], "Passenger email should match the request data") + + def test_2_passenger_already_exists(self): + + response = self.client.post('/passenger/create', json=PASSENGER_1) + self.assertEqual(response.status_code, 202, "Expected status code to be 202 Created") + self.assertEqual(response.json['message'], "User account is already a passenger", + "Response message should indicate that the user is already a passenger") + + def test_3_add_trip_request(self): + + response = self.client.post('/trip_request/create', json=RIDE_REQUEST_2) + self.assertEqual(response.status_code, 201, "Expected status code to be 201 Created") + + def test_4_get_trip_requests(self): + response = self.client.post('/trip_requests/get/all', json={"username": "jDoe12"}) + self.assertEqual(response.status_code, 200, "Expected status code to be 200 OK") + self.assertEqual(len(response.json), 1) + self.assertEqual(response.json['trip_requests'][0]['start_address'], RIDE_REQUEST_2['pickup_location']['address']) + +class TestCreateDriver(RideTest): + def test_create_driver(self): + + response = self.client.post('/driver/create', json=DRIVER_1) + self.assertEqual(response.status_code, 201, "Expected status code to be 201 Created") + self.assertEqual(response.json['name'], DRIVER_1['name'], "Driver name should match the request data") + self.assertEqual(response.json['phone_number'], DRIVER_1['phone_number'], "Driver phone number should match the request data") + self.assertEqual(response.json['email'], DRIVER_1['email'], "Driver email should match the request data") + + def test_create_trip(self): + + response = self.client.post('/trip/create', json=TRIP_REQUEST_1) + self.assertEqual(response.status_code, 201, "Expected status code to be 201 Created") + + def test_nondrivers_cannot_create_trip(self): + + response = self.client.post('/trip/create', json=INVALID_TRIP_REQUEST) + self.assertEqual(response.status_code, 404, "Expected status code to be 404 Created") + self.assertEqual(response.json['message'],"Invalid Driver! Please ensure the username is linked to a driver account.", + "Response message should indicate that the user is already a passenger") + def test_get_all_trips_for_user(self): + response = self.client.post('/trips/get/all', json={"username": "Moedab11"}) + self.assertEqual(response.status_code, 200, "Expected status code to be 200 OK") + self.assertEqual(len(response.json), 1) + self.assertEqual(response.json['trips'][0]['start_address'], TRIP_REQUEST_1['start_location']['address']) + + +# Main block to run tests +if __name__ == '__main__': + unittest.main() diff --git a/application/app/views/helpers/helpers.py b/application/app/views/helpers/helpers.py index 16bb90bf..3d159305 100644 --- a/application/app/views/helpers/helpers.py +++ b/application/app/views/helpers/helpers.py @@ -87,18 +87,29 @@ def haversine(lon1, lat1, lon2, lat2): distance = radius_earth_km * c return distance -def distance_query(set_long, set_lat, distance, offers): +def distance_query(start_long, start_lat, end_long, end_lat, distance, offers, start_time): nearby_requests = [] - ## Only search for PENDING to reduce search space - trip_requests = db.session.execute(db.select(TripRequest).filter_by(status='PENDING').order_by(TripRequest.requested_time)).scalars().all() + + trip_requests = db.session.execute( + db.select(TripRequest) + .filter( + TripRequest.status == 'PENDING', + TripRequest.window_start_time <= start_time, + TripRequest.window_end_time >= start_time + ) + .order_by(TripRequest.requested_time) + ).scalars().all() + for request in trip_requests: start_point = to_shape(request.pickup_location) + end_point = to_shape(request.dropoff_location) # Calculate distance between set point and pickup location of the request - dist = haversine(start_point.x, start_point.y, set_long, set_lat) - - if abs(dist) <= distance: + start_dist = haversine(start_point.x, start_point.y, start_long, start_lat) + end_dist = haversine(end_point.x, end_point.y, end_long, end_lat) + + if abs(start_dist) <= distance and abs(end_dist) <= distance: nearby_requests.append(request) if len(nearby_requests) == offers: diff --git a/application/app/views/routes.py b/application/app/views/routes.py index 6f283e0a..b0eac6b7 100644 --- a/application/app/views/routes.py +++ b/application/app/views/routes.py @@ -135,7 +135,7 @@ def post(self): return make_response(user.to_dict(), 201) elif user.passenger != None: - return make_response("User account is already a passenger", 202) + return make_response({"message":"User account is already a passenger"}, 202) class GetUser(Resource): @@ -167,7 +167,7 @@ def post(self): contents = create_trip_parser.parse_args() driver_id = get_driver_id_from_username(contents.get("username")) if not driver_id: - return make_response("Invalid Driver! Please ensure the username is linked to a driver account.", 404) + return make_response({"message":"Invalid Driver! Please ensure the username is linked to a driver account."}, 404) driver = get_driver_from_driver_id(driver_id) if not driver: @@ -317,6 +317,7 @@ def post(self): if trip is None: return make_response("There is no trip under this ID.", 400) start_point = to_shape(trip.start_location) + end_point = to_shape(trip.end_location) willing_distance_to_travel = trip.seats_remaining seats_remaining = trip.seats_remaining @@ -327,8 +328,9 @@ def post(self): else: willing_distance_to_travel = trip.distance_addition / trip.driver.car.max_available_seats + start_time = trip.start_time if (seats_remaining): - choices = distance_query(start_point.x, start_point.y, willing_distance_to_travel, (2 * seats_remaining)) + choices = distance_query(start_point.x, start_point.y, end_point.x, end_point.y, willing_distance_to_travel / 2, (2 * seats_remaining), start_time,) else: choices = [] return make_response(choices, 200) @@ -342,7 +344,7 @@ def post(self): trip_query = db.session.execute(db.select(Trip).filter_by(id=contents.get("trip_id"))).scalars().first() if trip_query: ans = [trip.id for trip in trip_query.trip_requests] - return make_response({"accepted trips": ans}, 200) + return make_response({"accepted_trips": ans}, 200) else: return make_response(f"This is not a valid trip id.", 400) else: @@ -373,15 +375,15 @@ def post(self): trip_query.status = TripState.MATCHED db.session.commit() - return make_response(f"Trip {contents.get('trip_request_id')} has successfully been added to the trip.", 200) + return make_response(jsonify({"message": f"Trip {contents.get('trip_request_id')} has successfully been added to the trip."}), 200) else: - return make_response("Your current trip is full.", 400) + return make_response(jsonify({"message": "Your current trip is full."}), 400) else: - return make_response("This is no longer a trip request or trip.", 400) + return make_response(jsonify({"message": "This is no longer a trip request or trip."}), 400) else: - return make_response(f"There is no driver under the username: {username}", 400) + return make_response(jsonify({"message": f"There is no driver under the username: {username}"}), 400) class Test(Resource): def get(self): diff --git a/application/docker-compose.yml b/application/docker-compose.yml index 7d42e532..30452766 100644 --- a/application/docker-compose.yml +++ b/application/docker-compose.yml @@ -9,6 +9,8 @@ services: POSTGRES_DB: ride volumes: - ./data/db:/var/lib/postgresql/data + ports: + - "5432:5432" api: build: . diff --git a/endpoint.http b/endpoint.http index cc8c1762..e8846704 100644 --- a/endpoint.http +++ b/endpoint.http @@ -5,7 +5,7 @@ POST {{baseUrl}}/driver/create Content-Type: application/json { - "username": "jDoe11", + "username": "jDoe12", "password": "53%32", "name": "John Doe", "phone_number": "1234567890", @@ -54,9 +54,9 @@ POST {{baseUrl}}/trip/create Content-Type: application/json { - "username": "jDoe12", + "username": "jDoe13", "start_time": "2024-05-10T10:00:00Z", - "end_time": "2024-05-10T10:00:00Z", + "end_time": "2024-05-10T11:00:00Z", "start_location": {"latitude": 37.7749, "longitude": -122.4194, "address": "123 street road, brisbane, qld"}, "end_location": {"latitude": 37.7749, "longitude": -122.4194, "address": "125 street road, brisbane, qld"}, "seats_remaining": 3, @@ -82,7 +82,7 @@ POST {{baseUrl}}/trips/get/all Content-Type: application/json { - "username": "jDoe12" + "username": "jDoe13" } ### Get all PENDING trips for a user @@ -98,12 +98,12 @@ POST {{baseUrl}}/trip_request/create Content-Type: application/json { - "username": "jDoe12", + "username": "Bailey45", "requested_time": "2024-05-10T11:00:00Z", "pickup_location": {"latitude": 37.7749, "longitude": -122.4194, "address": "123 street road, brisbane, qld"}, "dropoff_location": {"latitude": 37.7749, "longitude": -122.4194, "address": "125 street road, brisbane, qld"}, - "pickup_window_start": "2024-05-10T07:30:00", - "pickup_window_end": "2024-05-10T12:00:00Z" + "pickup_window_start": "2024-05-10T09:30:00", + "pickup_window_end": "2024-05-10T10:30:00" } ### Add trip request @@ -111,12 +111,12 @@ POST {{baseUrl}}/trip_request/create Content-Type: application/json { - "username": "jDoe12", - "requested_time": "2024-05-10T08:00:00", - "pickup_location": {"latitude": 37.7749, "longitude": -123.4194, "address": "123 street road, brisbane, qld"}, - "dropoff_location": {"latitude": 37.7749, "longitude": -123.4194, "address": "125 street road, brisbane, qld"}, - "pickup_window_start": "2024-05-10T07:30:00", - "pickup_window_end": "2024-05-10T08:00:00" + "username": "Bailey45", + "requested_time": "2024-05-10T11:00:00Z", + "pickup_location": {"latitude": 37.7749, "longitude": -122.4194, "address": "123 street road, brisbane, qld"}, + "dropoff_location": {"latitude": 37.7749, "longitude": -122.4194, "address": "125 street road, brisbane, qld"}, + "pickup_window_start": "2024-06-10T09:30:00", + "pickup_window_end": "2024-06-10T10:30:00" } ### Add trip request @@ -124,20 +124,20 @@ POST {{baseUrl}}/trip_request/create Content-Type: application/json { - "username": "Bailey45", - "requested_time": "2024-05-10T08:01:00", - "pickup_location": {"latitude": 37.7749, "longitude": -123.4193, "address": "123 street road, brisbane, qld"}, - "dropoff_location": {"latitude": 37.7749, "longitude": -123.4193, "address": "125 street road, brisbane, qld"}, - "pickup_window_start": "2024-05-10T07:31:00", - "pickup_window_end": "2024-05-10T08:00:00" + "username": "jDoe12", + "pickup_location": {"latitude": 37.7749, "longitude": -123.4194, "address": "123 street road, brisbane, qld"}, + "dropoff_location": {"latitude": 37.7749, "longitude": -123.4194, "address": "125 street road, brisbane, qld"}, + "pickup_window_start": "2024-05-11T07:30:00", + "pickup_window_end": "2024-05-11T08:00:00" } + ### Get all trip requests for a user POST {{baseUrl}}/trip_requests/get/all Content-Type: application/json { - "username": "jDoe12" + "username": "Bailey45" } ### Get all trip requests for a user @@ -171,7 +171,7 @@ POST {{baseUrl}}/trip/get/pending_nearby Content-Type: application/json { - "trip_id": "c84fbfc3-3d2f-4f3f-a3ff-15286d31c51c", + "trip_id": "40a7b51b-ec8b-4c09-86ac-2d0a2157bae3", "username": "jDoe12" } diff --git a/package.json b/package.json new file mode 100644 index 00000000..540c11b6 --- /dev/null +++ b/package.json @@ -0,0 +1,8 @@ +{ + "dependencies": { + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.5", + "@mui/icons-material": "^5.15.17", + "@mui/material": "^5.15.17" + } +} diff --git a/sqlmap.sh b/sqlmap.sh new file mode 100755 index 00000000..88cdc62f --- /dev/null +++ b/sqlmap.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +# Check if the host argument is provided +if [ -z "$1" ]; then + echo "Usage: $0 " + exit 1 +fi + +# The host URL passed as the first argument +HOST=$1 + +# Directory where you want to clone and run sqlmap +WORKDIR="/tmp/sqlmap-test" + +# Create working directory +mkdir -p $WORKDIR +cd $WORKDIR + +# Clone the sqlmap repository +git clone --depth 1 https://github.com/sqlmapproject/sqlmap.git +cd sqlmap + +# Create the request.txt file using the provided HOST +cat <request.txt +POST /profile HTTP/1.1 +Host: $HOST +Content-Type: application/json + +{"username": "test", "password": "test", "user_type": "driver"} +EOF + +# Run sqlmap specifically targeting PostgreSQL +python sqlmap.py -r request.txt --dbms=PostgreSQL --level=5 --risk=3 --batch + +# Cleanup: delete the sqlmap directory +cd .. +rm -rf sqlmap + +# Optional: remove the work directory +# rm -rf $WORKDIR diff --git a/unittest.sh b/unittest.sh new file mode 100755 index 00000000..94be1cdc --- /dev/null +++ b/unittest.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Navigate to the application directory where docker-compose.yml is located +cd application + +# Start only the database service +docker-compose up -d database + +# Wait for 10 seconds to allow the database to initialize +echo "Waiting for the database service to initialize... Sleeping for 20 seconds" +sleep 20 + +# Navigate to the tests directory and run unittests +echo "Running tests..." +cd app/tests +python -W ignore -m unittest discover + +# Navigate back to the application directory +echo "Shutting down services..." +cd ../../.. + +# Shut down all services +./cleanup.sh +./purge_db.sh +echo "Testing and cleanup completed." diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 00000000..d952be0a --- /dev/null +++ b/yarn.lock @@ -0,0 +1,590 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@^7.0.0": + version "7.24.2" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae" + integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ== + dependencies: + "@babel/highlight" "^7.24.2" + picocolors "^1.0.0" + +"@babel/helper-module-imports@^7.16.7": + version "7.24.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz#6ac476e6d168c7c23ff3ba3cf4f7841d46ac8128" + integrity sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg== + dependencies: + "@babel/types" "^7.24.0" + +"@babel/helper-string-parser@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz#f99c36d3593db9540705d0739a1f10b5e20c696e" + integrity sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ== + +"@babel/helper-validator-identifier@^7.24.5": + version "7.24.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz#918b1a7fa23056603506370089bd990d8720db62" + integrity sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA== + +"@babel/highlight@^7.24.2": + version "7.24.5" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.5.tgz#bc0613f98e1dd0720e99b2a9ee3760194a704b6e" + integrity sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw== + dependencies: + "@babel/helper-validator-identifier" "^7.24.5" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.23.9", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7": + version "7.24.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.5.tgz#230946857c053a36ccc66e1dd03b17dd0c4ed02c" + integrity sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g== + dependencies: + regenerator-runtime "^0.14.0" + +"@babel/types@^7.24.0": + version "7.24.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.5.tgz#7661930afc638a5383eb0c4aee59b74f38db84d7" + integrity sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ== + dependencies: + "@babel/helper-string-parser" "^7.24.1" + "@babel/helper-validator-identifier" "^7.24.5" + to-fast-properties "^2.0.0" + +"@emotion/babel-plugin@^11.11.0": + version "11.11.0" + resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz#c2d872b6a7767a9d176d007f5b31f7d504bb5d6c" + integrity sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ== + dependencies: + "@babel/helper-module-imports" "^7.16.7" + "@babel/runtime" "^7.18.3" + "@emotion/hash" "^0.9.1" + "@emotion/memoize" "^0.8.1" + "@emotion/serialize" "^1.1.2" + babel-plugin-macros "^3.1.0" + convert-source-map "^1.5.0" + escape-string-regexp "^4.0.0" + find-root "^1.1.0" + source-map "^0.5.7" + stylis "4.2.0" + +"@emotion/cache@^11.11.0": + version "11.11.0" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.11.0.tgz#809b33ee6b1cb1a625fef7a45bc568ccd9b8f3ff" + integrity sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ== + dependencies: + "@emotion/memoize" "^0.8.1" + "@emotion/sheet" "^1.2.2" + "@emotion/utils" "^1.2.1" + "@emotion/weak-memoize" "^0.3.1" + stylis "4.2.0" + +"@emotion/hash@^0.9.1": + version "0.9.1" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.1.tgz#4ffb0055f7ef676ebc3a5a91fb621393294e2f43" + integrity sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ== + +"@emotion/is-prop-valid@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz#d4175076679c6a26faa92b03bb786f9e52612337" + integrity sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw== + dependencies: + "@emotion/memoize" "^0.8.1" + +"@emotion/memoize@^0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17" + integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA== + +"@emotion/react@^11.11.4": + version "11.11.4" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.11.4.tgz#3a829cac25c1f00e126408fab7f891f00ecc3c1d" + integrity sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw== + dependencies: + "@babel/runtime" "^7.18.3" + "@emotion/babel-plugin" "^11.11.0" + "@emotion/cache" "^11.11.0" + "@emotion/serialize" "^1.1.3" + "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1" + "@emotion/utils" "^1.2.1" + "@emotion/weak-memoize" "^0.3.1" + hoist-non-react-statics "^3.3.1" + +"@emotion/serialize@^1.1.2", "@emotion/serialize@^1.1.3", "@emotion/serialize@^1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.4.tgz#fc8f6d80c492cfa08801d544a05331d1cc7cd451" + integrity sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ== + dependencies: + "@emotion/hash" "^0.9.1" + "@emotion/memoize" "^0.8.1" + "@emotion/unitless" "^0.8.1" + "@emotion/utils" "^1.2.1" + csstype "^3.0.2" + +"@emotion/sheet@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.2.tgz#d58e788ee27267a14342303e1abb3d508b6d0fec" + integrity sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA== + +"@emotion/styled@^11.11.5": + version "11.11.5" + resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.11.5.tgz#0c5c8febef9d86e8a926e663b2e5488705545dfb" + integrity sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ== + dependencies: + "@babel/runtime" "^7.18.3" + "@emotion/babel-plugin" "^11.11.0" + "@emotion/is-prop-valid" "^1.2.2" + "@emotion/serialize" "^1.1.4" + "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1" + "@emotion/utils" "^1.2.1" + +"@emotion/unitless@^0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.1.tgz#182b5a4704ef8ad91bde93f7a860a88fd92c79a3" + integrity sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ== + +"@emotion/use-insertion-effect-with-fallbacks@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz#08de79f54eb3406f9daaf77c76e35313da963963" + integrity sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw== + +"@emotion/utils@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.1.tgz#bbab58465738d31ae4cb3dbb6fc00a5991f755e4" + integrity sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg== + +"@emotion/weak-memoize@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6" + integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww== + +"@floating-ui/core@^1.0.0": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.1.tgz#a4e6fef1b069cda533cbc7a4998c083a37f37573" + integrity sha512-42UH54oPZHPdRHdw6BgoBD6cg/eVTmVrFcgeRDM3jbO7uxSoipVcmcIGFcA5jmOHO5apcyvBhkSKES3fQJnu7A== + dependencies: + "@floating-ui/utils" "^0.2.0" + +"@floating-ui/dom@^1.0.0": + version "1.6.5" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.5.tgz#323f065c003f1d3ecf0ff16d2c2c4d38979f4cb9" + integrity sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw== + dependencies: + "@floating-ui/core" "^1.0.0" + "@floating-ui/utils" "^0.2.0" + +"@floating-ui/react-dom@^2.0.8": + version "2.0.9" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.0.9.tgz#264ba8b061000baa132b5910f0427a6acf7ad7ce" + integrity sha512-q0umO0+LQK4+p6aGyvzASqKbKOJcAHJ7ycE9CuUvfx3s9zTHWmGJTPOIlM/hmSBfUfg/XfY5YhLBLR/LHwShQQ== + dependencies: + "@floating-ui/dom" "^1.0.0" + +"@floating-ui/utils@^0.2.0": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.2.tgz#d8bae93ac8b815b2bd7a98078cf91e2724ef11e5" + integrity sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw== + +"@mui/base@5.0.0-beta.40": + version "5.0.0-beta.40" + resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-beta.40.tgz#1f8a782f1fbf3f84a961e954c8176b187de3dae2" + integrity sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ== + dependencies: + "@babel/runtime" "^7.23.9" + "@floating-ui/react-dom" "^2.0.8" + "@mui/types" "^7.2.14" + "@mui/utils" "^5.15.14" + "@popperjs/core" "^2.11.8" + clsx "^2.1.0" + prop-types "^15.8.1" + +"@mui/core-downloads-tracker@^5.15.17": + version "5.15.17" + resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.17.tgz#ce8f3dff6ec11c8294d346997f6065eb23fa99be" + integrity sha512-DVAejDQkjNnIac7MfP8sLzuo7fyrBPxNdXe+6bYqOqg1z2OPTlfFAejSNzWe7UenRMuFu9/AyFXj/X2vN2w6dA== + +"@mui/icons-material@^5.15.17": + version "5.15.17" + resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.15.17.tgz#518c02354036f7df28c8f9890b1db6a3269fcc2f" + integrity sha512-xVzl2De7IY36s/keHX45YMiCpsIx3mNv2xwDgtBkRSnZQtVk+Gqufwj1ktUxEyjzEhBl0+PiNJqYC31C+n1n6A== + dependencies: + "@babel/runtime" "^7.23.9" + +"@mui/material@^5.15.17": + version "5.15.17" + resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.15.17.tgz#1e30bacc940573813cc418aebd4484708a407ba6" + integrity sha512-ru/MLvTkCh0AZXmqwIpqGTOoVBS/sX48zArXq/DvktxXZx4fskiRA2PEc7Rk5ZlFiZhKh4moL4an+l8zZwq49Q== + dependencies: + "@babel/runtime" "^7.23.9" + "@mui/base" "5.0.0-beta.40" + "@mui/core-downloads-tracker" "^5.15.17" + "@mui/system" "^5.15.15" + "@mui/types" "^7.2.14" + "@mui/utils" "^5.15.14" + "@types/react-transition-group" "^4.4.10" + clsx "^2.1.0" + csstype "^3.1.3" + prop-types "^15.8.1" + react-is "^18.2.0" + react-transition-group "^4.4.5" + +"@mui/private-theming@^5.15.14": + version "5.15.14" + resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.15.14.tgz#edd9a82948ed01586a01c842eb89f0e3f68970ee" + integrity sha512-UH0EiZckOWcxiXLX3Jbb0K7rC8mxTr9L9l6QhOZxYc4r8FHUkefltV9VDGLrzCaWh30SQiJvAEd7djX3XXY6Xw== + dependencies: + "@babel/runtime" "^7.23.9" + "@mui/utils" "^5.15.14" + prop-types "^15.8.1" + +"@mui/styled-engine@^5.15.14": + version "5.15.14" + resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.15.14.tgz#168b154c4327fa4ccc1933a498331d53f61c0de2" + integrity sha512-RILkuVD8gY6PvjZjqnWhz8fu68dVkqhM5+jYWfB5yhlSQKg+2rHkmEwm75XIeAqI3qwOndK6zELK5H6Zxn4NHw== + dependencies: + "@babel/runtime" "^7.23.9" + "@emotion/cache" "^11.11.0" + csstype "^3.1.3" + prop-types "^15.8.1" + +"@mui/system@^5.15.15": + version "5.15.15" + resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.15.15.tgz#658771b200ce3c4a0f28e58169f02e5e718d1c53" + integrity sha512-aulox6N1dnu5PABsfxVGOZffDVmlxPOVgj56HrUnJE8MCSh8lOvvkd47cebIVQQYAjpwieXQXiDPj5pwM40jTQ== + dependencies: + "@babel/runtime" "^7.23.9" + "@mui/private-theming" "^5.15.14" + "@mui/styled-engine" "^5.15.14" + "@mui/types" "^7.2.14" + "@mui/utils" "^5.15.14" + clsx "^2.1.0" + csstype "^3.1.3" + prop-types "^15.8.1" + +"@mui/types@^7.2.14": + version "7.2.14" + resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.14.tgz#8a02ac129b70f3d82f2f9b76ded2c8d48e3fc8c9" + integrity sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ== + +"@mui/utils@^5.15.14": + version "5.15.14" + resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.15.14.tgz#e414d7efd5db00bfdc875273a40c0a89112ade3a" + integrity sha512-0lF/7Hh/ezDv5X7Pry6enMsbYyGKjADzvHyo3Qrc/SSlTsQ1VkbDMbH0m2t3OR5iIVLwMoxwM7yGd+6FCMtTFA== + dependencies: + "@babel/runtime" "^7.23.9" + "@types/prop-types" "^15.7.11" + prop-types "^15.8.1" + react-is "^18.2.0" + +"@popperjs/core@^2.11.8": + version "2.11.8" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" + integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== + +"@types/parse-json@^4.0.0": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.2.tgz#5950e50960793055845e956c427fc2b0d70c5239" + integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw== + +"@types/prop-types@*", "@types/prop-types@^15.7.11": + version "15.7.12" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6" + integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q== + +"@types/react-transition-group@^4.4.10": + version "4.4.10" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.10.tgz#6ee71127bdab1f18f11ad8fb3322c6da27c327ac" + integrity sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q== + dependencies: + "@types/react" "*" + +"@types/react@*": + version "18.3.1" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.1.tgz#fed43985caa834a2084d002e4771e15dfcbdbe8e" + integrity sha512-V0kuGBX3+prX+DQ/7r2qsv1NsdfnCLnTgnRJ1pYnxykBhGMz+qj+box5lq7XsO5mtZsBqpjwwTu/7wszPfMBcw== + dependencies: + "@types/prop-types" "*" + csstype "^3.0.2" + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +babel-plugin-macros@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" + integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg== + dependencies: + "@babel/runtime" "^7.12.5" + cosmiconfig "^7.0.0" + resolve "^1.19.0" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +clsx@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" + integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +convert-source-map@^1.5.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + +cosmiconfig@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" + integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.2.1" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.10.0" + +csstype@^3.0.2, csstype@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" + integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== + +dom-helpers@^5.0.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" + integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== + dependencies: + "@babel/runtime" "^7.8.7" + csstype "^3.0.2" + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +find-root@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" + integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +hasown@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +hoist-non-react-statics@^3.3.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + +import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-core-module@^2.13.0: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + dependencies: + hasown "^2.0.0" + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +prop-types@^15.6.2, prop-types@^15.8.1: + version "15.8.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + +react-is@^16.13.1, react-is@^16.7.0: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +react-is@^18.2.0: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" + integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== + +react-transition-group@^4.4.5: + version "4.4.5" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1" + integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g== + dependencies: + "@babel/runtime" "^7.5.5" + dom-helpers "^5.0.1" + loose-envify "^1.4.0" + prop-types "^15.6.2" + +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve@^1.19.0: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +source-map@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + +stylis@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51" + integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + +yaml@^1.10.0: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==