diff options
22 files changed, 725 insertions, 253 deletions
diff --git a/driver/index.html b/driver/index.html index 5fc871e..8025373 100644 --- a/driver/index.html +++ b/driver/index.html @@ -2,7 +2,6 @@ <html lang="en"> <head> <meta charset="UTF-8" /> - <link rel="icon" type="image/svg+xml" href="/vite.svg" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Carpool</title> </head> diff --git a/driver/src/pages/Home.tsx b/driver/src/pages/Home.tsx index bd003b6..e2fb141 100644 --- a/driver/src/pages/Home.tsx +++ b/driver/src/pages/Home.tsx @@ -10,6 +10,9 @@ import { useEffect, useState } from "react" import { Navigate } from "react-router-dom" import { fetchRideRequests } from "@/utils/fetchRideRequests" import { collection, onSnapshot } from "firebase/firestore" +import { toast } from "@/components/ui/use-toast" +import { updateStatus } from "@/utils/updateStatus" +import { fetchUserIdByPhoneNumber } from "@/utils/fetchUserIdByPhoneNumber" interface IDriver { uid: string, @@ -33,7 +36,8 @@ interface IPassengerRequest { export default function Home() { const [driverData, setDriverData] = useState<IDriver | null | undefined>() const [rideRequests, setRideRequests] = useState<IPassengerRequest[]>([]) - const [currentTrip, setCurrentTrip] = useState<IPassengerRequest>() + const [currentTrip, setCurrentTrip] = useState<IPassengerRequest | null>(null) + const [toComplete, setToComplete] = useState(false) const [isLoggedIn, setIsLoggedIn] = useState(true) @@ -57,30 +61,45 @@ export default function Home() { </p> <div className="flex justify-between mt-2"> <Button onClick={ - () => { - const newRideReqs = rideRequests.map((request) => { - if (request.phoneNumber === phoneNumber) { - return { ...request, status: 'Accepted' }; + async () => { + if (currentTrip) { + toast({ + description: "You already have a trip consider canceling the trip to accept a new one" + }) + } else { + const newRideReqs = rideRequests.map((request) => { + if (request.phoneNumber === phoneNumber) { + return { ...request, status: 'Accepted' }; + } + return request; + }) + const curTrip: any = newRideReqs.find((req) => req.phoneNumber == phoneNumber) + const userId = await fetchUserIdByPhoneNumber(phoneNumber) + if (userId) { + await updateStatus(userId, "Accepted") } - return request; - }) - const curTrip = newRideReqs.find((req) => req.phoneNumber == phoneNumber) - setCurrentTrip(curTrip) - setRideRequests(newRideReqs) + setCurrentTrip(curTrip) + setRideRequests((_) => [...newRideReqs]) + } } } className="text-green-500 border-green-500" variant="outline"> Accept </Button> - <Button onClick={() => { - const newRideReqs = rideRequests.map((request) => { - if (request.phoneNumber === phoneNumber) { - return { ...request, status: 'Cancelled' }; + <Button onClick={ + async () => { + const newRideReqs = rideRequests.map((request) => { + if (request.phoneNumber === phoneNumber) { + return { ...request, status: 'Cancelled' }; + } + return request; + }) + const userId = await fetchUserIdByPhoneNumber(phoneNumber) + if (userId) { + await updateStatus(userId, "Rejected") } - return request; - }) - setRideRequests(newRideReqs) - }} className="border-red-500 text-red-500" variant="outline"> + setRideRequests(() => newRideReqs) + }} className="border-red-500 text-red-500" variant="outline"> Reject </Button> </div> @@ -90,10 +109,37 @@ export default function Home() { } useEffect(() => { + const doWork = async () => { + if (toComplete) { + let phoneNumber = '' + const newRideReqs = rideRequests.map((request) => { + if (request.status === "Accepted") { + phoneNumber = request.phoneNumber; + return { ...request, status: 'Completed' }; + } + return request; + }) + const userId = await fetchUserIdByPhoneNumber(phoneNumber) + if (userId) { + await updateStatus(userId, "Completed") + } + setRideRequests(newRideReqs) + setCurrentTrip(null) + } + } + doWork() + + return () => { + doWork() + } + + }, [toComplete]) + + useEffect(() => { const user = auth.currentUser; async function fetchData() { const data: IDriver | null | undefined = await fetchUserDetails(user?.uid); - const rideReqs = await fetchRideRequests() + const rideReqs: any = await fetchRideRequests() setDriverData(data) setRideRequests(rideReqs) } @@ -173,13 +219,25 @@ export default function Home() { <p> <strong>Dropoff:</strong> {currentTrip?.dropOff} </p> - <Button className="w-full mt-4 border-blue-500 text-white" variant="outline"> - Start Trip - </Button> - <Button className="w-full mt-4 border-green-500 text-white" variant="outline"> + <Button + onClick={() => { + setToComplete(true); + }} + className="w-full mt-4 border-green-500 text-white" variant="outline"> Finish Trip </Button> - <Button className="w-full mt-4 border-red-500 text-white" variant="outline"> + <Button + onClick={() => { + const newRideReqs = rideRequests.map((request) => { + if (request.status === "Accepted") { + return { ...request, status: 'Pending' }; + } + return request; + }) + setRideRequests(newRideReqs) + setCurrentTrip(null) + }} + className="w-full mt-4 border-red-500 text-white" variant="outline"> Cancel Trip </Button> </CardContent> diff --git a/driver/src/pages/SignUp.tsx b/driver/src/pages/SignUp.tsx index b73d810..dbe5e9c 100644 --- a/driver/src/pages/SignUp.tsx +++ b/driver/src/pages/SignUp.tsx @@ -4,7 +4,7 @@ import { Button } from "@/components/ui/button" import { useState, useEffect } from 'react'; import { auth, db } from '../firebase/firebase_config'; import { createUserWithEmailAndPassword } from 'firebase/auth'; -import { Navigate, redirect } from "react-router-dom"; +import { Navigate } from "react-router-dom"; import { addDoc, collection } from "firebase/firestore"; const SignUp = () => { @@ -43,7 +43,6 @@ const SignUp = () => { const userCredential = await createUserWithEmailAndPassword(auth, email, password); const usersCollection = collection(db, 'users'); const userUid = userCredential.user.uid; // Get the user's UID - console.log(userUid, name, phoneNumber, carBrand, carModel, carColor, plateNumber) addDoc(usersCollection, { uid: userUid, name: name, diff --git a/driver/src/utils/fetchUserIdByPhoneNumber.ts b/driver/src/utils/fetchUserIdByPhoneNumber.ts new file mode 100644 index 0000000..843ac67 --- /dev/null +++ b/driver/src/utils/fetchUserIdByPhoneNumber.ts @@ -0,0 +1,24 @@ +import { auth, db } from "@/firebase/firebase_config"; +import { DocumentData, collection, getDocs, query, where } from "firebase/firestore"; + + +export const fetchUserIdByPhoneNumber = async (phoneNumber: any) => { + try { + const user = auth.currentUser; + let data = null + if (user) { + const usersRef = collection(db, "users") + const q = query(usersRef, where("phoneNumber", "==", phoneNumber)) + const querySnapshot = await getDocs(q); + querySnapshot.forEach((doc: DocumentData) => { + data = doc.data() + }); + return data.uid; + } else { + console.log("There is no user"); + return null; + } + } catch (error) { + console.error('Error fetching user details:', error); + } +}; diff --git a/driver/src/utils/updateStatus.ts b/driver/src/utils/updateStatus.ts new file mode 100644 index 0000000..a717905 --- /dev/null +++ b/driver/src/utils/updateStatus.ts @@ -0,0 +1,24 @@ +import { db } from "@/firebase/firebase_config"; +import { collection, doc, getDocs, query, updateDoc, where } from "firebase/firestore"; + +export const updateStatus = async (userId, newStatus) => { + console.log("userID: ", userId) + try { + const q = query(collection(db, 'RideRequest'), where('passengerID', '==', userId)); + const querySnapshot = await getDocs(q); + + querySnapshot.forEach(async (doc_data) => { + try { + const passengerRequestRef = doc(db, 'RideRequest', doc_data.id); + await updateDoc(passengerRequestRef, { + status: newStatus, + }); + console.log(`Status updated successfully for document ID: ${doc_data.id}`); + } catch (error) { + console.error('Error updating status:', error); + } + }); + } catch (error) { + console.error('Error fetching documents:', error); + } +}; diff --git a/mobile/build/93cae48154605b2b23f957321f3fac0a.cache.dill.track.dill b/mobile/build/93cae48154605b2b23f957321f3fac0a.cache.dill.track.dill Binary files differindex 5ccaef7..3a348bd 100644 --- a/mobile/build/93cae48154605b2b23f957321f3fac0a.cache.dill.track.dill +++ b/mobile/build/93cae48154605b2b23f957321f3fac0a.cache.dill.track.dill diff --git a/mobile/build/app/intermediates/assets/debug/flutter_assets/kernel_blob.bin b/mobile/build/app/intermediates/assets/debug/flutter_assets/kernel_blob.bin Binary files differindex 5ccaef7..3a348bd 100644 --- a/mobile/build/app/intermediates/assets/debug/flutter_assets/kernel_blob.bin +++ b/mobile/build/app/intermediates/assets/debug/flutter_assets/kernel_blob.bin diff --git a/mobile/build/app/intermediates/compressed_assets/debug/out/assets/flutter_assets/kernel_blob.bin.jar b/mobile/build/app/intermediates/compressed_assets/debug/out/assets/flutter_assets/kernel_blob.bin.jar Binary files differindex e01d684..102f012 100644 --- a/mobile/build/app/intermediates/compressed_assets/debug/out/assets/flutter_assets/kernel_blob.bin.jar +++ b/mobile/build/app/intermediates/compressed_assets/debug/out/assets/flutter_assets/kernel_blob.bin.jar diff --git a/mobile/build/app/intermediates/flutter/debug/flutter_assets/kernel_blob.bin b/mobile/build/app/intermediates/flutter/debug/flutter_assets/kernel_blob.bin Binary files differindex 5ccaef7..3a348bd 100644 --- a/mobile/build/app/intermediates/flutter/debug/flutter_assets/kernel_blob.bin +++ b/mobile/build/app/intermediates/flutter/debug/flutter_assets/kernel_blob.bin diff --git a/mobile/build/app/intermediates/incremental/packageDebug/tmp/debug/dex-renamer-state.txt b/mobile/build/app/intermediates/incremental/packageDebug/tmp/debug/dex-renamer-state.txt index 0505f4a..89eb96c 100644 --- a/mobile/build/app/intermediates/incremental/packageDebug/tmp/debug/dex-renamer-state.txt +++ b/mobile/build/app/intermediates/incremental/packageDebug/tmp/debug/dex-renamer-state.txt @@ -1,4 +1,4 @@ -#Thu Dec 21 00:19:52 EET 2023 +#Fri Dec 22 23:31:13 EET 2023 base.0=/home/omar/programming/flutter/carpool/mobile/build/app/intermediates/dex/debug/mergeExtDexDebug/classes.dex base.1=/home/omar/programming/flutter/carpool/mobile/build/app/intermediates/dex/debug/mergeLibDexDebug/0/classes.dex base.2=/home/omar/programming/flutter/carpool/mobile/build/app/intermediates/dex/debug/mergeProjectDexDebug/0/classes.dex diff --git a/mobile/build/app/outputs/apk/debug/app-debug.apk b/mobile/build/app/outputs/apk/debug/app-debug.apk Binary files differindex 1093fcb..4d7455a 100644 --- a/mobile/build/app/outputs/apk/debug/app-debug.apk +++ b/mobile/build/app/outputs/apk/debug/app-debug.apk diff --git a/mobile/build/app/outputs/flutter-apk/app-debug.apk b/mobile/build/app/outputs/flutter-apk/app-debug.apk Binary files differindex 1093fcb..4d7455a 100644 --- a/mobile/build/app/outputs/flutter-apk/app-debug.apk +++ b/mobile/build/app/outputs/flutter-apk/app-debug.apk diff --git a/mobile/build/app/outputs/flutter-apk/app-debug.apk.sha1 b/mobile/build/app/outputs/flutter-apk/app-debug.apk.sha1 index d6d28fd..0b04769 100644 --- a/mobile/build/app/outputs/flutter-apk/app-debug.apk.sha1 +++ b/mobile/build/app/outputs/flutter-apk/app-debug.apk.sha1 @@ -1 +1 @@ -05d1e60c34d7362541e2cd0aa3fa1c4167fee399
\ No newline at end of file +75a7deb87c6a470acc2433e8469eb99674effc04
\ No newline at end of file diff --git a/mobile/lib/cart.dart b/mobile/lib/cart.dart index 109e407..7464bb4 100644 --- a/mobile/lib/cart.dart +++ b/mobile/lib/cart.dart @@ -1,3 +1,5 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; // Define a Ride class to represent the selected ride @@ -5,13 +7,23 @@ class Ride { final String name; final String startLocation; final String endLocation; - final String time; + final String carBrand; + final String carModel; + final String carColor; + final String plateNumber; + final String status; + final DateTime orderTime; Ride({ required this.name, required this.startLocation, required this.endLocation, - required this.time, + required this.carBrand, + required this.carModel, + required this.carColor, + required this.plateNumber, + required this.status, + required this.orderTime, }); } @@ -70,7 +82,7 @@ class CartPage extends StatelessWidget { children: [ const Icon(Icons.access_time, color: Colors.blue), const SizedBox(width: 4), - Text(selectedRide.time), + // Text(selectedRide.orderTime.toString()), ], ), ], @@ -78,9 +90,31 @@ class CartPage extends StatelessWidget { ), const SizedBox(height: 20), ElevatedButton( - onPressed: () { - // Implement payment or confirmation logic here - // For now, just print a message + onPressed: () async { + FirebaseFirestore firestore = FirebaseFirestore.instance; + User? user = FirebaseAuth.instance.currentUser; + + if (user != null) { + String userId = user.uid; + CollectionReference collection = + firestore.collection('RideRequest'); + + Map<String, dynamic> data = { + 'dropOff': selectedRide.endLocation, + 'pickUp': selectedRide.startLocation, + 'status': "Pending", + 'cost': "50", + 'passengerID': userId, + }; + + try { + await collection.add(data); + print('Document added successfully!'); + } catch (e) { + print('Error adding document: $e'); + } + } + print('Processing Requesting Ride'); }, child: const Text('Request Ride'), diff --git a/mobile/lib/drawer.dart b/mobile/lib/drawer.dart new file mode 100644 index 0000000..34022f6 --- /dev/null +++ b/mobile/lib/drawer.dart @@ -0,0 +1,122 @@ +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/material.dart'; + +class CustomDrawer extends StatelessWidget { + const CustomDrawer({Key? key}) : super(key: key); + + Widget _buildDrawerItem({ + required IconData icon, + required String text, + required VoidCallback onTap, + }) { + return ListTile( + leading: Icon(icon), + title: Text(text), + onTap: onTap, + ); + } + + @override + Widget build(BuildContext context) { + return Drawer( + child: ListView( + padding: EdgeInsets.zero, + children: <Widget>[ + const DrawerHeader( + decoration: BoxDecoration( + color: Colors.blue, + ), + child: Text( + 'Menu', + style: TextStyle( + color: Colors.white, + fontSize: 24, + ), + ), + ), + _buildDrawerItem( + icon: Icons.app_registration_rounded, + text: 'Signup', + onTap: () { + Navigator.pop(context); + Navigator.pushNamed(context, '/signup'); + }, + ), + _buildDrawerItem( + icon: Icons.login, + text: 'Login', + onTap: () { + Navigator.pop(context); + Navigator.pushNamed(context, '/login'); + }, + ), + _buildDrawerItem( + icon: Icons.map, + text: 'Routes', + onTap: () { + User? user = FirebaseAuth.instance.currentUser; + if (user != null) { + Navigator.pop(context); + Navigator.pushNamed(context, '/routes'); + } else { + Navigator.pop(context); + Navigator.pushNamed(context, '/login'); + } + }, + ), + _buildDrawerItem( + icon: Icons.shopping_cart, + text: 'Cart', + onTap: () { + User? user = FirebaseAuth.instance.currentUser; + if (user != null) { + Navigator.pop(context); + Navigator.pushNamed(context, '/cart'); + } else { + Navigator.pop(context); + Navigator.pushNamed(context, '/login'); + } + }, + ), + _buildDrawerItem( + icon: Icons.history, + text: 'Order History', + onTap: () { + User? user = FirebaseAuth.instance.currentUser; + if (user != null) { + Navigator.pop(context); + Navigator.pushNamed(context, '/order_history'); + } else { + Navigator.pop(context); + Navigator.pushNamed(context, '/login'); + } + }, + ), + _buildDrawerItem( + icon: Icons.payment, + text: 'Payment & Order Tracking', + onTap: () { + User? user = FirebaseAuth.instance.currentUser; + if (user != null) { + Navigator.pop(context); + Navigator.pushNamed(context, '/payment'); + } else { + Navigator.pop(context); + Navigator.pushNamed(context, '/login'); + } + }, + ), + _buildDrawerItem( + icon: Icons.logout, + text: 'Logout', + onTap: () { + FirebaseAuth.instance.signOut(); + Navigator.pop(context); + Navigator.pushNamed(context, '/login'); + }, + ), + ], + ), + ); + } +} diff --git a/mobile/lib/login.dart b/mobile/lib/login.dart index b210650..7eadcf4 100644 --- a/mobile/lib/login.dart +++ b/mobile/lib/login.dart @@ -1,3 +1,4 @@ +import 'package:carpool/drawer.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:firebase_auth/firebase_auth.dart'; @@ -23,6 +24,8 @@ class _LoginPageState extends State<LoginPage> { @override Widget build(BuildContext context) { return Scaffold( + appBar: AppBar(title: const Text('Login')), + drawer: CustomDrawer(), backgroundColor: Colors.grey[300], body: Form( key: _formKey, @@ -118,7 +121,7 @@ class _LoginPageState extends State<LoginPage> { password: _controllerPassword.text.trim()) .then((value) => Navigator.pushNamedAndRemoveUntil( - context, '/', (route) => false)); + context, '/routes', (route) => false)); } on FirebaseAuthException catch (e) { Fluttertoast.showToast( msg: e.message.toString(), @@ -156,6 +159,7 @@ class _LoginPageState extends State<LoginPage> { _focusNodePassword.dispose(); _controllerUsername.dispose(); _controllerPassword.dispose(); + _controllerPassword.dispose(); super.dispose(); } } diff --git a/mobile/lib/main.dart b/mobile/lib/main.dart index 5fd2374..f40a6ca 100644 --- a/mobile/lib/main.dart +++ b/mobile/lib/main.dart @@ -1,9 +1,11 @@ +import 'package:carpool/drawer.dart'; +import 'package:carpool/ride_request.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; import 'firebase_options.dart'; import 'routes.dart'; import 'login.dart'; -import 'cart.dart'; +// import 'cart.dart'; import 'payement_order.dart'; import 'signup.dart'; import 'order_history.dart'; @@ -30,13 +32,17 @@ class MyApp extends StatelessWidget { '/routes': (context) => RoutesPage(), '/order_history': (context) => OrderHistoryPage(), '/payment': (context) => PaymentOrderTrackingPage(), - '/cart': (context) => CartPage( - selectedRide: Ride( - name: 'Sample Ride', - startLocation: 'Sample Start', - endLocation: 'Sample End', - time: 'Sample Time', - )), + '/request_ride': (context) => RequestRidePage( + selectedRide: Ride( + name: "", + startLocation: "", + endLocation: "", + carModel: "", + carBrand: "", + carColor: "", + plateNumber: "", + status: "", + orderTime: DateTime.now())), }, ); } @@ -49,73 +55,7 @@ class HomePage extends StatelessWidget { appBar: AppBar( title: const Text('Home'), ), - drawer: Drawer( - child: ListView( - padding: EdgeInsets.zero, - children: <Widget>[ - const DrawerHeader( - decoration: BoxDecoration( - color: Colors.blue, - ), - child: Text( - 'Menu', - style: TextStyle( - color: Colors.white, - fontSize: 24, - ), - ), - ), - _buildDrawerItem( - icon: Icons.app_registration_rounded, - text: 'Signup', - onTap: () { - Navigator.pop(context); - Navigator.pushNamed(context, '/signup'); - }, - ), - _buildDrawerItem( - icon: Icons.login, - text: 'Login', - onTap: () { - Navigator.pop(context); - Navigator.pushNamed(context, '/login'); - }, - ), - _buildDrawerItem( - icon: Icons.map, - text: 'Routes', - onTap: () { - Navigator.pop(context); - Navigator.pushNamed(context, '/routes'); - }, - ), - _buildDrawerItem( - icon: Icons.shopping_cart, - text: 'Cart', - onTap: () { - Navigator.pop(context); - Navigator.pushNamed(context, '/cart'); - }, - ), - _buildDrawerItem( - icon: Icons.history, - text: 'Order History', - onTap: () { - Navigator.pop(context); - Navigator.pushNamed(context, '/order_history'); - }, - ), - _buildDrawerItem( - icon: Icons.payment, - text: 'Payment & Order Tracking', - onTap: () { - Navigator.pop(context); - Navigator.pushNamed(context, '/payment'); - }, - ), - ], - ), - ), + drawer: CustomDrawer(), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.start, diff --git a/mobile/lib/order_history.dart b/mobile/lib/order_history.dart index 543a5ec..ef9b1d5 100644 --- a/mobile/lib/order_history.dart +++ b/mobile/lib/order_history.dart @@ -25,66 +25,12 @@ class OrderHistoryPage extends StatelessWidget { final List<RideOrder> orders = [ RideOrder( orderID: '001', - driverName: 'John Doe', + driverName: 'Omar Magdy', carModel: 'Toyota Corolla', carColor: Colors.black, plateNumber: 'ABC-123', status: 'Completed', - orderTime: DateTime.now().subtract(const Duration(days: 5)), - ), - RideOrder( - orderID: '002', - driverName: 'Alice Smith', - carModel: 'Honda Civic', - carColor: Colors.blue, - plateNumber: 'XYZ-789', - status: 'Cancelled', - orderTime: DateTime.now().subtract(const Duration(days: 2)), - ), - RideOrder( - orderID: '004', - driverName: 'Emily Johnson', - carModel: 'Chevrolet Malibu', - carColor: Colors.green, - plateNumber: 'GHI-789', - status: 'Completed', - orderTime: DateTime.now().subtract(const Duration(days: 7)), - ), - RideOrder( - orderID: '005', - driverName: 'David Wilson', - carModel: 'Tesla Model 3', - carColor: Colors.grey, - plateNumber: 'JKL-012', - status: 'Pending', - orderTime: DateTime.now().subtract(const Duration(days: 2)), - ), - RideOrder( - orderID: '006', - driverName: 'Sophia Brown', - carModel: 'BMW X5', - carColor: Colors.black, - plateNumber: 'MNO-345', - status: 'Cancelled', - orderTime: DateTime.now().subtract(const Duration(days: 4)), - ), - RideOrder( - orderID: '007', - driverName: 'James Davis', - carModel: 'Audi A4', - carColor: Colors.blueGrey, - plateNumber: 'PQR-678', - status: 'pending', - orderTime: DateTime.now().subtract(const Duration(days: 6)), - ), - RideOrder( - orderID: '008', - driverName: 'Olivia Martinez', - carModel: 'Hyundai Elantra', - carColor: Colors.orange, - plateNumber: 'STU-901', - status: 'Completed', - orderTime: DateTime.now().subtract(const Duration(days: 9)), + orderTime: DateTime.now(), ), ]; @@ -96,7 +42,6 @@ class OrderHistoryPage extends StatelessWidget { return Colors.orange; case 'cancelled': return Colors.red; - // Add more cases for other statuses default: return Colors.grey; } diff --git a/mobile/lib/payement_order.dart b/mobile/lib/payement_order.dart index eac05ec..19fa357 100644 --- a/mobile/lib/payement_order.dart +++ b/mobile/lib/payement_order.dart @@ -1,81 +1,122 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/material.dart'; +import 'package:firebase_auth/firebase_auth.dart'; import 'credit_card_payment.dart'; class Order { - final String orderID; - final String rideName; + final String pickUp; + final String dropOff; final String status; final double amount; - Order( - {required this.orderID, - required this.rideName, - required this.status, - required this.amount}); + Order({ + required this.pickUp, + required this.dropOff, + required this.status, + required this.amount, + }); } class PaymentOrderTrackingPage extends StatelessWidget { - final List<Order> orders = [ - Order( - orderID: '001', - rideName: 'Morning Ride - Gate 3 to Abdu-Basha', - status: 'Completed', - amount: 15.0), - Order( - orderID: '002', - rideName: 'Afternoon Ride - Abdu-Basha to Gate 3', - status: 'Pending', - amount: 12.5), - ]; + final FirebaseFirestore _firestore = FirebaseFirestore.instance; + final FirebaseAuth _auth = FirebaseAuth.instance; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text('Payment & Order Tracking'), + title: const Text('Payment & Order Tracking'), ), - body: ListView.builder( - itemCount: orders.length, - itemBuilder: (BuildContext context, int index) { - final Order order = orders[index]; - return GestureDetector( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - CreditCardDetailsPage(orderID: order.orderID), - ), - ); - }, - child: Card( - elevation: 3, - margin: EdgeInsets.symmetric(vertical: 8, horizontal: 16), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - child: ListTile( - title: Text( - 'Order ID: ${order.orderID}', - style: TextStyle( - fontWeight: FontWeight.bold, + body: FutureBuilder<List<Order>>( + future: _fetchOrders(), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return Center(child: CircularProgressIndicator()); + } else if (snapshot.hasError) { + return Center(child: Text('Error: ${snapshot.error}')); + } else if (!snapshot.hasData || snapshot.data!.isEmpty) { + return Center(child: Text('No orders found.')); + } else { + return ListView.builder( + itemCount: snapshot.data!.length, + itemBuilder: (BuildContext context, int index) { + final Order order = snapshot.data![index]; + return GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPage |
