Skip to content

Commit

Permalink
Merge pull request #23 from CSSE6400/postgis
Browse files Browse the repository at this point in the history
Fixed issues with nearby algorithm
  • Loading branch information
Mohamad11Dab authored May 27, 2024
2 parents c8dc727 + 677bfa0 commit a405387
Show file tree
Hide file tree
Showing 31 changed files with 1,630 additions and 104 deletions.
50 changes: 50 additions & 0 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
@@ -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
4 changes: 4 additions & 0 deletions application/app/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
18 changes: 18 additions & 0 deletions application/app/frontend/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -42,11 +45,26 @@ const App = () => {
<TripDetail />
</PrivateRoute>
} />
<Route path="/trips/:tripId" element={
<PrivateRoute userType="driver">
<TripInformation />
</PrivateRoute>
} />
<Route path="/ride-request" element={
<PrivateRoute userType="passenger">
<RideRequest />
</PrivateRoute>
} />
<Route path="/rides/:tripId" element={
<PrivateRoute userType="driver">
<RideRequests />
</PrivateRoute>
} />
<Route path="/trips" element={
<PrivateRoute userType="driver">
<TripsPage />
</PrivateRoute>
} />
</Routes>
</Router>
</UserProvider>
Expand Down
66 changes: 66 additions & 0 deletions application/app/frontend/src/api/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
};
17 changes: 17 additions & 0 deletions application/app/frontend/src/components/ApprovedTripCard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react';
import '../styles/TripCard.css';

const ApprovedTripCard = ({ riderName, startingPoint, destination, onClickCard }) => {
return (
<div className="trip-card" onClick={onClickCard}>
<div className="trip-info">
<p>{riderName}</p>
<h3>{startingPoint}</h3>
<h3>{destination}</h3>
</div>
</div>

);
};

export default ApprovedTripCard;
14 changes: 7 additions & 7 deletions application/app/frontend/src/components/RideRequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,29 +97,29 @@ function RideRequest() {

return (
<div>
<h1>Create Ride Request</h1>
<form onSubmit={handleSubmit} className={styles.formContainer}>
<h1>Create Ride Request</h1>
<div className={styles.gridContainer}>
<label className={styles.fullWidth}>
Pickup Window Start:
<div className={styles.formText}>Pickup Window Start:</div>
<input type="datetime-local" name="pickup_window_start" value={tripWindows.pickup_window_start.replace(':00', '')} onChange={handleTimeChange} className={errors.pickup_window_start ? styles.errorInput : styles.inputField} />
</label>
<label className={styles.fullWidth}>
Pickup Window End:
<div className={styles.formText}>Pickup Window End:</div>
<input type="datetime-local" name="pickup_window_end" value={tripWindows.pickup_window_end.replace(':00', '')} onChange={handleTimeChange} className={errors.pickup_window_end ? styles.errorInput : styles.inputField} />
</label>
<label className={styles.fullWidth}>
Pickup Address:
<div className={styles.formText}>Pickup Address:</div>
<input type="text" value={pickupAddress} onChange={(e) => handleAddressChange(e, "pickup")} className={errors.pickup ? styles.errorInput : styles.inputField} />
</label>
<label className={styles.fullWidth}>
Dropoff Address:
<div className={styles.formText}>Dropoff Address:</div>
<input type="text" value={dropoffAddress} onChange={(e) => handleAddressChange(e, "dropoff")} className={errors.dropoff ? styles.errorInput : styles.inputField} />
</label>
</div>
<button type="submit" className={styles.button}>Create Trip Request</button>
<center><button type="submit" className={styles.button}>Create Trip Request</button></center>
</form>
<button onClick={handleLogout} className={styles.blueButton}>Logout</button>
<center><button onClick={handleLogout} className={styles.blueButton}>Logout</button></center>
</div>
);
}
Expand Down
74 changes: 74 additions & 0 deletions application/app/frontend/src/components/RideRequests.js
Original file line number Diff line number Diff line change
@@ -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 (
<div>
<center><h1>Available Ride Requests</h1></center>
{errorMessage && <Alert severity="info">{errorMessage}</Alert>}
{successMessage && <Alert severity="success">{successMessage}</Alert>}
<center>
<div>
{tripRequests.length > 0 ? (
tripRequests.map(tripRequest => (
<RiderCard
key={tripRequest.id}
riderName={tripRequest.passenger_name}
startingPoint={tripRequest.start_address}
destination={tripRequest.end_address}
onApprove={() => handleApprove(tripRequest.id)}
/>
))
) : (
<p>No ride requests available.</p>
)}
</div>
</center>
</div>
);
};

export default RideRequests;
16 changes: 13 additions & 3 deletions application/app/frontend/src/components/RiderCard.js
Original file line number Diff line number Diff line change
@@ -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 (
<div className="rider-card">
<h3 style={{marginBottom:40}}>{riderName}</h3>
<div className="rider-cards">
<div className="rider-info">
<h3>{riderName}</h3>
<p>{startingPoint}</p>
<p>{destination}</p>
</div>
<div className="actions">
<center>
<button className="approve" onClick={onApprove}>
<CheckCircleIcon style={{ color: 'green' }} />
</button>
</center>
</div>
</div>
</div>
);
};

export default RiderCard;
export default RiderCard;
20 changes: 15 additions & 5 deletions application/app/frontend/src/components/Routing.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand All @@ -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;
}
});

Expand All @@ -38,4 +48,4 @@ const createRoutineMachineLayer = ({waypoints}) => {

const RoutingMachine = createControlComponent(createRoutineMachineLayer);

export default RoutingMachine;
export default RoutingMachine;
2 changes: 1 addition & 1 deletion application/app/frontend/src/components/TripCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ const TripCard = ({ trip }) => {
);
};

export default TripCard;
export default TripCard;
Loading

0 comments on commit a405387

Please sign in to comment.