diff --git a/README.md b/README.md index ee78fa0..e957e6c 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Originally created by Julia Ying, Grace Kim, Ritika Bhatnagar, Aasha Jain - To run the application, make two terminals: - Make sure you are in `backend` and run `python app.py`. - Make sure you are in `frontend` and run `npm run dev`. -- Navigate to http://localhost:5173/ to view application. (Backend runs on http://localhost:5000/). +- Navigate to http://localhost:5173/ to view application. (Backend runs on http://localhost:5005/). ### Deploying diff --git a/backend/app.py b/backend/app.py index d2bb7a0..1b0f2ee 100644 --- a/backend/app.py +++ b/backend/app.py @@ -228,6 +228,8 @@ def addride(): origin: a dictionary containing the origin location dest: a dictionary containing the destination location arrival_time: a datetime object with the arrival date & time + leave_by_time (optional): time to leave origin + phone_number (optional): contact phone number note (optional): note with the rideshare Returns: @@ -242,6 +244,8 @@ def addride(): dest_obj = data.get("destination") note = data.get("note") + leave_by_time = data.get("leave_by_time") + phone_number = data.get("phone_number") origin_addr = origin_obj["formatted_address"] origin_name = origin_obj["name"] @@ -270,6 +274,8 @@ def addride(): dest_json, arrival_time, note, + leave_by_time, + phone_number, ) return jsonify({"success": True, "message": "Rideshare successfully created!"}) except: @@ -742,4 +748,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=5005, debug=debug) diff --git a/backend/database.py b/backend/database.py index 1311095..4ad059f 100644 --- a/backend/database.py +++ b/backend/database.py @@ -27,6 +27,8 @@ def database_setup(): creation_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, current_riders TEXT[][], + leave_by_time TIME, + phone_number VARCHAR(20), note VARCHAR(250) ); @@ -90,6 +92,8 @@ def create_ride( destination, arrival_time, note="", + leave_by_time=None, + phone_number=None, ): """ Adds a ride to the Rides database @@ -99,8 +103,8 @@ def create_ride( sql_command = f""" INSERT INTO Rides (admin_netid, admin_name, admin_email, max_capacity, current_riders, - origin_dict, destination_dict, arrival_time, note, updated_at) VALUES (%s, %s, %s, %s, - %s, %s, %s, %s, %s, CURRENT_TIMESTAMP); + origin_dict, destination_dict, arrival_time, leave_by_time, phone_number, note, updated_at) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, CURRENT_TIMESTAMP); """ values = ( @@ -112,6 +116,8 @@ def create_ride( origin, destination, arrival_time, + leave_by_time, + phone_number, note, ) diff --git a/frontend/src/components/WarningModal.jsx b/frontend/src/components/WarningModal.jsx index 08a37c7..3fa7680 100644 --- a/frontend/src/components/WarningModal.jsx +++ b/frontend/src/components/WarningModal.jsx @@ -3,11 +3,9 @@ export default function WarningModal({ isOpen, title, children }) { return (
-
-
-

{title}

-
-
{children}
+
+

{title}

+ {children}
); diff --git a/frontend/src/pages/AllRides.jsx b/frontend/src/pages/AllRides.jsx index 64037e2..8a94dd0 100644 --- a/frontend/src/pages/AllRides.jsx +++ b/frontend/src/pages/AllRides.jsx @@ -2,6 +2,7 @@ import { useRef, useState, useEffect } from "react"; import { Link } from "react-router-dom"; import DateTimePicker from "../components/DateTimePicker.jsx"; +import { TimePicker } from "antd"; import RideCard from "../components/RideCard.jsx"; import Button from "../components/Button.jsx"; import Modal from "../components/Modal.jsx"; @@ -59,6 +60,8 @@ export default function AllRides() { const [dest, setDest] = useState(null); const [date, setDate] = useState(""); const [time, setTime] = useState(""); + const [leaveByTime, setLeaveByTime] = useState(""); + const [phoneNumber, setPhoneNumber] = useState(""); const [rideNote, setRideNote] = useState(""); const [isCreatingRide, setIsCreatingRide] = useState(false); @@ -188,6 +191,7 @@ export default function AllRides() { } if (arrival_time_iso && now.getTime() >= arrival_time_iso.getTime()) { + document.activeElement?.blur(); // Remove focus from any active input setValidationModalTitle("Invalid Input"); setValidationModalMessage("Cannot enter a date in the past."); setShowValidationModal(true); // Show the validation modal @@ -195,19 +199,17 @@ export default function AllRides() { } // Check if any required fields are missing + // ! TODO: temporarily removed origin and dest if ( !capacity || - !origin || - !dest || !date || !time || capacity === "" || - origin === "" || - dest === "" || date === "" || !parsedDate.isValid() || !parsedTime.isValid() ) { + document.activeElement?.blur(); // Remove focus from any active input setValidationModalTitle("Missing fields"); setValidationModalMessage( "You must provide all fields to create a ride." @@ -226,6 +228,10 @@ export default function AllRides() { "HH:mm:ss" )}`; const arrival_time_iso = new Date(arrival_time_string).toISOString(); + + // Format leave by time if provided + const leave_by_time_formatted = leaveByTime ? leaveByTime.format("HH:mm:ss") : null; + try { const response = await fetch("/api/addride", { method: "POST", @@ -234,9 +240,11 @@ export default function AllRides() { }, body: JSON.stringify({ capacity: capacity["label"], - origin: origin, - destination: dest, + origin: { name: "Default Origin", formatted_address: "Default Origin", place_id: "temp_origin" }, // ! TODO: temporarily changed origin and dest + destination: { name: "Default Destination", formatted_address: "Default Destination", place_id: "temp_dest" }, arrival_time: arrival_time_iso, + leave_by_time: leave_by_time_formatted, + phone_number: phoneNumber || null, note: rideNote, }), }); @@ -275,6 +283,8 @@ export default function AllRides() { setDest(""); setDate(""); setTime(""); + setLeaveByTime(""); + setPhoneNumber(""); setRideNote(""); originRef.current = null; destinationRef.current = null; @@ -671,17 +681,40 @@ export default function AllRides() { />
+
+
+

Arrival Time (in ET)

+ +
+
+

Leave By:

+ +
+
-

Arrival Time (in ET)

- Phone Number (Optional)

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

Optional Note to Riders

+

Note to Riders (Optional)

{ <>
{renderToAndFrom(ride)} -

+

+ {ride.leave_by_time && ( + + Leave by: {ride.leave_by_time} + + )} Arrives by {getFormattedDate(new Date(ride.arrival_time))} -

+

@@ -96,6 +101,11 @@ export const renderRideCardInfo = (ride) => { className="inline-flex text-theme_medium_2 hover:text-theme_dark_2 ml-1 mb-0.5 align-middle" />

+ {ride.phone_number && ( +

+ Phone: {ride.phone_number} +

+ )}

Seats Taken:{" "} {ride.current_riders.length}/{ride.max_capacity} diff --git a/frontend/vite.config.js b/frontend/vite.config.js index 91fd2f7..7cc708b 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -7,7 +7,7 @@ export default defineConfig(({ command }) => ({ server: { proxy: { "/api": { - target: "http://localhost:5000", + target: "http://localhost:5005", }, }, },