diff --git a/.gitignore b/.gitignore index a98ad9c..e872ed6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,12 @@ .env __pycache__/ .DS_Store -.venv/ \ No newline at end of file + +# Python virtual environments +.venv/ +venv/ +env/ +ENV/ + +# Node modules +node_modules/ \ No newline at end of file diff --git a/backend/app.py b/backend/app.py index d2bb7a0..f6650e4 100644 --- a/backend/app.py +++ b/backend/app.py @@ -742,4 +742,4 @@ def send_email_notification(netid, mail, subject, message): debug = FLASK_ENV == "development" if not app._got_first_request: database.database_setup() - app.run(host="0.0.0.0", port=5000, debug=debug) + app.run(host="0.0.0.0", port=5000, debug=debug) diff --git a/backend/requirements.txt b/backend/requirements.txt index ba09790..65ec7f8 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -6,7 +6,7 @@ itsdangerous==2.2.0 Jinja2==3.1.6 MarkupSafe==3.0.2 packaging==24.2 -psycopg2==2.9.10 +psycopg2-binary==2.9.10 python-dotenv==1.0.1 SQLAlchemy==2.0.38 typing_extensions==4.12.2 diff --git a/frontend/src/pages/AllRides.jsx b/frontend/src/pages/AllRides.jsx index 64037e2..6b02f96 100644 --- a/frontend/src/pages/AllRides.jsx +++ b/frontend/src/pages/AllRides.jsx @@ -48,6 +48,11 @@ export default function AllRides() { const [validationModalMessage, setValidationModalMessage] = useState(""); // message inside validation modal const [validationModalTitle, setValidationModalTitle] = useState(""); // title of validation modal + const [showJoinModal, setShowJoinModal] = useState(false); // controls join request modal visibility + const [selectedRide, setSelectedRide] = useState(null); // stores the ride being requested + const [phoneNumber, setPhoneNumber] = useState(""); // stores user's phone number input + const [joinComments, setJoinComments] = useState(""); // stores optional comments from user + // Refs for handling input elements const originRef = useRef(null); // stores origin const destinationRef = useRef(null); // stores destination @@ -296,12 +301,19 @@ export default function AllRides() { setLoading(false); }; + const handleOpenJoinModal = (ride) => { + setSelectedRide(ride); + setShowJoinModal(true); + }; + // Handles ride requests made by user const handleRideRequest = async ( rideid, origin, destination, - arrival_time + arrival_time, + phoneNumber, + comments ) => { setPendingRideId((prev) => [...prev, rideid]); // track pending request by ID try { @@ -319,8 +331,23 @@ export default function AllRides() { origin_name: origin["name"], destination_name: destination["name"], formatted_arrival_time: formattedArrivalTime, + phone_number: phoneNumber, + comments: comments, }), }); + + handleShowPopupMessage( + setPopupMessageInfo, + true, + "Request sent! An email has been sent to the ride creator." + ); + + // Close modal and reset fields + setShowJoinModal(false); + setPhoneNumber(""); + setJoinComments(""); + setSelectedRide(null); + await fetchDashboardData(); // refresh dashboardData after requesting ride if (!response.ok) { console.error("Request failed:", response.status); @@ -579,13 +606,7 @@ export default function AllRides() { ride.admin_netid === dashboardData.user_info.netid || ride.current_riders.length === ride.max_capacity ? () => {} - : () => - handleRideRequest( - ride.id, - ride.origin, - ride.destination, - ride.arrival_time - ) + : () => handleOpenJoinModal(ride) // open modal instead of direct request } buttonClassName={`${ ride.admin_netid === dashboardData.user_info.netid @@ -721,6 +742,77 @@ export default function AllRides() { )} + + {showJoinModal && selectedRide && ( + { + setShowJoinModal(false); + setPhoneNumber(""); + setJoinComments(""); + setSelectedRide(null); + }} + title="Request to Join Ride" + > +
+
+

+ ✉️ An email will be sent to the ride creator with your contact information and request. +

+
+ +
+

Phone Number

+ setPhoneNumber(e.target.value)} + placeholder="Enter your phone number" + className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-theme_medium_1" + /> +
+ +
+

Optional Comments

+ +
+ +
+ + +
+
+
+ )} ); }