From fbaae8f461ff085356670d41506cd92180227beb Mon Sep 17 00:00:00 2001
From: omagdy7
Date: Sat, 23 Dec 2023 01:39:59 +0200
Subject: Final version
---
driver/index.html | 1 -
driver/src/pages/Home.tsx | 106 ++++++++++----
driver/src/pages/SignUp.tsx | 3 +-
driver/src/utils/fetchUserIdByPhoneNumber.ts | 24 ++++
driver/src/utils/updateStatus.ts | 24 ++++
...154605b2b23f957321f3fac0a.cache.dill.track.dill | Bin 39927112 -> 39941312 bytes
.../assets/debug/flutter_assets/kernel_blob.bin | Bin 39927112 -> 39941312 bytes
.../out/assets/flutter_assets/kernel_blob.bin.jar | Bin 13375384 -> 13385785 bytes
.../flutter/debug/flutter_assets/kernel_blob.bin | Bin 39927112 -> 39941312 bytes
.../packageDebug/tmp/debug/dex-renamer-state.txt | 2 +-
mobile/build/app/outputs/apk/debug/app-debug.apk | Bin 64140809 -> 77508504 bytes
mobile/build/app/outputs/flutter-apk/app-debug.apk | Bin 64140809 -> 77508504 bytes
.../app/outputs/flutter-apk/app-debug.apk.sha1 | 2 +-
mobile/lib/cart.dart | 46 +++++-
mobile/lib/drawer.dart | 122 ++++++++++++++++
mobile/lib/login.dart | 6 +-
mobile/lib/main.dart | 90 ++----------
mobile/lib/order_history.dart | 59 +-------
mobile/lib/payement_order.dart | 159 +++++++++++++--------
mobile/lib/ride_request.dart | 122 ++++++++++++++++
mobile/lib/routes.dart | 131 ++++++++++++++---
mobile/lib/signup.dart | 81 ++++++++++-
22 files changed, 725 insertions(+), 253 deletions(-)
create mode 100644 driver/src/utils/fetchUserIdByPhoneNumber.ts
create mode 100644 driver/src/utils/updateStatus.ts
create mode 100644 mobile/lib/drawer.dart
create mode 100644 mobile/lib/ride_request.dart
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 @@
-
Carpool
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()
const [rideRequests, setRideRequests] = useState([])
- const [currentTrip, setCurrentTrip] = useState()
+ const [currentTrip, setCurrentTrip] = useState(null)
+ const [toComplete, setToComplete] = useState(false)
const [isLoggedIn, setIsLoggedIn] = useState(true)
@@ -57,30 +61,45 @@ export default function Home() {
-
@@ -89,11 +108,38 @@ 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() {
Dropoff: {currentTrip?.dropOff}
-
- Start Trip
-
-
+ {
+ setToComplete(true);
+ }}
+ className="w-full mt-4 border-green-500 text-white" variant="outline">
Finish Trip
-
+ {
+ 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
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
index 5ccaef7..3a348bd 100644
Binary files a/mobile/build/93cae48154605b2b23f957321f3fac0a.cache.dill.track.dill and b/mobile/build/93cae48154605b2b23f957321f3fac0a.cache.dill.track.dill differ
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
index 5ccaef7..3a348bd 100644
Binary files a/mobile/build/app/intermediates/assets/debug/flutter_assets/kernel_blob.bin and b/mobile/build/app/intermediates/assets/debug/flutter_assets/kernel_blob.bin differ
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
index e01d684..102f012 100644
Binary files a/mobile/build/app/intermediates/compressed_assets/debug/out/assets/flutter_assets/kernel_blob.bin.jar and b/mobile/build/app/intermediates/compressed_assets/debug/out/assets/flutter_assets/kernel_blob.bin.jar differ
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
index 5ccaef7..3a348bd 100644
Binary files a/mobile/build/app/intermediates/flutter/debug/flutter_assets/kernel_blob.bin and b/mobile/build/app/intermediates/flutter/debug/flutter_assets/kernel_blob.bin differ
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
index 1093fcb..4d7455a 100644
Binary files a/mobile/build/app/outputs/apk/debug/app-debug.apk and b/mobile/build/app/outputs/apk/debug/app-debug.apk differ
diff --git a/mobile/build/app/outputs/flutter-apk/app-debug.apk b/mobile/build/app/outputs/flutter-apk/app-debug.apk
index 1093fcb..4d7455a 100644
Binary files a/mobile/build/app/outputs/flutter-apk/app-debug.apk and b/mobile/build/app/outputs/flutter-apk/app-debug.apk differ
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 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: [
+ 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 {
@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 {
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 {
_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: [
- 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 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 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>(
+ 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,
+ MaterialPageRoute(
+ builder: (context) =>
+ CreditCardDetailsPage(orderID: "13251231254"),
+ ),
+ );
+ },
+ child: Card(
+ elevation: 3,
+ margin: const EdgeInsets.symmetric(
+ vertical: 8,
+ horizontal: 16,
+ ),
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(12),
+ ),
+ child: ListTile(
+ subtitle: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ 'Ride: ${order.pickUp} - ${order.dropOff}',
+ style: const TextStyle(color: Colors.black),
+ ),
+ Text(
+ 'Status: ${order.status}',
+ style: const TextStyle(color: Colors.black),
+ ),
+ Text(
+ 'Amount: \$${order.amount.toStringAsFixed(2)}',
+ style: const TextStyle(color: Colors.black),
+ ),
+ ],
+ ),
+ leading: const Icon(Icons.payment),
+ ),
),
- ),
- subtitle: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text('Ride: ${order.rideName}'),
- Text('Status: ${order.status}'),
- Text('Amount: \$${order.amount.toStringAsFixed(2)}'),
- ],
- ),
- leading: Icon(Icons
- .payment), // TODO Use an appropriate icon for payment/order tracking
- ),
- ),
- );
+ );
+ },
+ );
+ }
},
),
);
}
+
+ Future> _fetchOrders() async {
+ final currentUser = _auth.currentUser;
+ if (currentUser != null) {
+ final passengerID = currentUser.uid;
+
+ QuerySnapshot rideRequests = await _firestore
+ .collection('RideRequest')
+ .where('passengerID', isEqualTo: passengerID)
+ .get();
+
+ List orders = [];
+ rideRequests.docs.forEach((doc) {
+ String pickUp = doc['pickUp'];
+ String dropOff = doc['dropOff'];
+ String status = doc['status'];
+
+ Order order = Order(
+ pickUp: pickUp,
+ dropOff: dropOff,
+ status: status,
+ amount: 50,
+ );
+ orders.add(order);
+ });
+ return orders;
+ } else {
+ return [];
+ }
+ }
}
diff --git a/mobile/lib/ride_request.dart b/mobile/lib/ride_request.dart
new file mode 100644
index 0000000..454134f
--- /dev/null
+++ b/mobile/lib/ride_request.dart
@@ -0,0 +1,122 @@
+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
+class Ride {
+ final String name;
+ final String startLocation;
+ final String endLocation;
+ 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.carBrand,
+ required this.carModel,
+ required this.carColor,
+ required this.plateNumber,
+ required this.status,
+ required this.orderTime,
+ });
+}
+
+class RequestRidePage extends StatelessWidget {
+ final Ride selectedRide;
+
+ RequestRidePage({required this.selectedRide});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: const Text('Ride Request'),
+ ),
+ body: Padding(
+ padding: const EdgeInsets.all(16.0),
+ child: Card(
+ elevation: 5,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(12),
+ ),
+ child: Padding(
+ padding: const EdgeInsets.all(16.0),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ const Text(
+ 'Selected Ride:',
+ style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
+ ),
+ const SizedBox(height: 12),
+ ListTile(
+ leading: const Icon(Icons.directions_car, color: Colors.blue),
+ title: Text(selectedRide.name),
+ subtitle: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ const SizedBox(height: 8),
+ Row(
+ children: [
+ const Icon(Icons.location_on, color: Colors.blue),
+ const SizedBox(width: 4),
+ Text(selectedRide.startLocation),
+ ],
+ ),
+ const SizedBox(height: 4),
+ Row(
+ children: [
+ const Icon(Icons.arrow_forward, color: Colors.blue),
+ const SizedBox(width: 4),
+ Text(selectedRide.endLocation),
+ ],
+ ),
+ ],
+ ),
+ ),
+ const SizedBox(height: 20),
+ ElevatedButton(
+ onPressed: () async {
+ FirebaseFirestore firestore = FirebaseFirestore.instance;
+ User? user = FirebaseAuth.instance.currentUser;
+
+ if (user != null) {
+ String userId = user.uid;
+ print("UserId: ${userId}");
+ CollectionReference collection =
+ firestore.collection('RideRequest');
+
+ Map data = {
+ 'dropOff': selectedRide.endLocation,
+ 'pickUp': selectedRide.startLocation,
+ 'status': "Pending",
+ 'passengerID': userId,
+ };
+
+ try {
+ // Add a new document with an automatically generated ID
+ 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/routes.dart b/mobile/lib/routes.dart
index 5073271..88fb9fb 100644
--- a/mobile/lib/routes.dart
+++ b/mobile/lib/routes.dart
@@ -1,6 +1,7 @@
+import 'package:carpool/drawer.dart';
+import 'package:carpool/ride_request.dart';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
-import 'cart.dart';
import 'package:intl/intl.dart';
// Accessing Firestore instance
@@ -10,11 +11,51 @@ class Route {
final String name;
final String startLocation;
final String endLocation;
+ final String carBrand;
+ final String carModel;
+ final String carColor;
+ final String plateNumber;
+ final String status;
+ final DateTime orderTime;
- Route(
- {required this.name,
- required this.startLocation,
- required this.endLocation});
+ Route({
+ required this.name,
+ required this.startLocation,
+ required this.endLocation,
+ required this.carBrand,
+ required this.carModel,
+ required this.carColor,
+ required this.plateNumber,
+ required this.status,
+ required this.orderTime,
+ });
+}
+
+Color getColorFromString(String color) {
+ switch (color.toLowerCase()) {
+ case 'red':
+ return Colors.red;
+ case 'blue':
+ return Colors.blue;
+ case 'green':
+ return Colors.green;
+ case 'yellow':
+ return Colors.yellow;
+ case 'orange':
+ return Colors.orange;
+ case 'purple':
+ return Colors.purple;
+ case 'pink':
+ return Colors.pink;
+ case 'cyan':
+ return Colors.cyan;
+ case 'silver':
+ return Colors.grey;
+ // You can add more cases for additional colors as needed
+ default:
+ // Return a default color if the input doesn't match any specified colors
+ return Colors.black;
+ }
}
Future> getDataFromFirestore() async {
@@ -24,17 +65,29 @@ Future> getDataFromFirestore() async {
QuerySnapshot querySnapshot = await firestore.collection('Rides').get();
// Loop through the documents in the collection
- querySnapshot.docs.forEach((doc) {
+ querySnapshot.docs
+ .where((element) => element['status'] == 'Unreserved')
+ .forEach((doc) {
String name = doc['driverName'];
- // String carModel = doc['carModel'];
- // String carColor = doc['carColor'];
- // String plateNumber = doc['plateNumber'];
- // String status = doc['status'];
- // DateTime orderTime = doc['orderTime'];
String fromLocation = doc['fromLocation'];
String toLocation = doc['toLocation'];
+ String carModel = doc['carModel'];
+ String carBrand = doc['carBrand'];
+ String carColor = doc['carColor'];
+ String plateNumber = doc['plateNumber'];
+ String status = doc['status'];
+ Timestamp orderTime = doc['orderTime'];
routes.add(Route(
- name: name, startLocation: fromLocation, endLocation: toLocation));
+ name: name,
+ startLocation: fromLocation,
+ endLocation: toLocation,
+ carModel: carModel,
+ carBrand: carBrand,
+ carColor: carColor,
+ plateNumber: plateNumber,
+ status: status,
+ orderTime: orderTime.toDate(),
+ ));
});
} catch (e) {
print('Error retrieving data: $e');
@@ -43,7 +96,10 @@ Future> getDataFromFirestore() async {
}
class RoutesPage extends StatefulWidget {
+ const RoutesPage({super.key});
+
@override
+ // ignore: library_private_types_in_public_api
_RoutesPageState createState() => _RoutesPageState();
}
@@ -67,6 +123,7 @@ class _RoutesPageState extends State {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Routes')),
+ drawer: const CustomDrawer(),
body: ListView.builder(
itemCount: routes.length,
itemBuilder: (BuildContext context, int index) {
@@ -74,18 +131,21 @@ class _RoutesPageState extends State {
return GestureDetector(
onTap: () {
DateTime now = DateTime.now();
- String formattedDateTime =
- DateFormat('EEEE dd/MM/yyyy hh:mm a').format(now);
Ride selectedRide = Ride(
- name: route.name,
- startLocation: route.startLocation,
- endLocation: route.endLocation,
- time: formattedDateTime,
- );
+ name: route.name,
+ startLocation: route.startLocation,
+ endLocation: route.endLocation,
+ carModel: route.carModel,
+ carBrand: route.carBrand,
+ carColor: route.carColor,
+ plateNumber: route.plateNumber,
+ status: route.status,
+ orderTime: route.orderTime);
Navigator.push(
context,
MaterialPageRoute(
- builder: (context) => CartPage(selectedRide: selectedRide),
+ builder: (context) =>
+ RequestRidePage(selectedRide: selectedRide),
),
);
},
@@ -120,6 +180,37 @@ class _RoutesPageState extends State {
Flexible(child: Text(route.endLocation)),
],
),
+ Row(
+ children: [
+ Icon(Icons.directions_car,
+ color: getColorFromString(route.carColor)),
+ const SizedBox(width: 4),
+ Text('${route.carBrand} - ${route.carModel}'),
+ ],
+ ),
+ Row(
+ children: [
+ const Icon(Icons.confirmation_number,
+ color: Colors.blue),
+ const SizedBox(width: 4),
+ Text('Plate: ${route.plateNumber}'),
+ ],
+ ),
+ Row(
+ children: [
+ const Icon(Icons.info, color: Colors.blue),
+ const SizedBox(width: 4),
+ Text('Status: ${route.status}'),
+ ],
+ ),
+ Row(
+ children: [
+ const Icon(Icons.schedule, color: Colors.blue),
+ const SizedBox(width: 4),
+ Text(DateFormat('EEEE dd/MM/yyyy hh:mm a')
+ .format(route.orderTime)),
+ ],
+ ),
],
),
leading: const Icon(Icons.directions_car),
diff --git a/mobile/lib/signup.dart b/mobile/lib/signup.dart
index 18a27ad..0650711 100644
--- a/mobile/lib/signup.dart
+++ b/mobile/lib/signup.dart
@@ -1,3 +1,5 @@
+import 'package:carpool/drawer.dart';
+import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:fluttertoast/fluttertoast.dart';
@@ -18,6 +20,8 @@ class _SignUpPageState extends State {
final FocusNode _focusNodeConfirmPassword = FocusNode();
final TextEditingController _controllerUsername = TextEditingController();
final TextEditingController _controllerPassword = TextEditingController();
+ final TextEditingController _controllerName = TextEditingController();
+ final TextEditingController _controllerPhoneNumber = TextEditingController();
final TextEditingController _corfirmPassword = TextEditingController();
bool _obscurePassword = true;
@@ -25,6 +29,8 @@ class _SignUpPageState extends State {
@override
Widget build(BuildContext context) {
return Scaffold(
+ appBar: AppBar(title: const Text('Sign Up')),
+ drawer: CustomDrawer(),
backgroundColor: Colors.grey[300],
body: Form(
key: _formKey,
@@ -35,7 +41,7 @@ class _SignUpPageState extends State {
const SizedBox(height: 20),
Image.asset(
"assets/logo.png",
- height: 190,
+ height: 140,
),
Text(
"Welcome ",
@@ -137,6 +143,47 @@ class _SignUpPageState extends State {
return null;
},
),
+ const SizedBox(height: 10),
+ TextFormField(
+ controller: _controllerName,
+ keyboardType: TextInputType.name,
+ decoration: InputDecoration(
+ labelText: "Name",
+ border: OutlineInputBorder(
+ borderRadius: BorderRadius.circular(10),
+ ),
+ enabledBorder: OutlineInputBorder(
+ borderRadius: BorderRadius.circular(10),
+ ),
+ ),
+ validator: (String? value) {
+ if (value == null || value.isEmpty) {
+ return "Please enter name.";
+ }
+ return null;
+ },
+ ),
+ const SizedBox(height: 10),
+ TextFormField(
+ controller: _controllerPhoneNumber,
+ keyboardType: TextInputType.number,
+ decoration: InputDecoration(
+ labelText: "Phone Number",
+ border: OutlineInputBorder(
+ borderRadius: BorderRadius.circular(10),
+ ),
+ enabledBorder: OutlineInputBorder(
+ borderRadius: BorderRadius.circular(10),
+ ),
+ ),
+ validator: (String? value) {
+ if (value == null || value.isEmpty) {
+ return "Please enter phone number.";
+ }
+ return null;
+ },
+ ),
+ const SizedBox(height: 60),
const SizedBox(height: 60),
Column(
children: [
@@ -146,7 +193,7 @@ class _SignUpPageState extends State {
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
- backgroundColor: Color(0xFF355291),
+ backgroundColor: const Color(0xFF355291),
),
onPressed: () async {
if (_formKey.currentState?.validate() ?? false) {
@@ -154,10 +201,30 @@ class _SignUpPageState extends State {
await FirebaseAuth.instance
.createUserWithEmailAndPassword(
email: _controllerUsername.text.trim(),
- password: _controllerPassword.text.trim())
- .then((value) =>
- Navigator.pushNamedAndRemoveUntil(
- context, "/", (route) => false));
+ password: _controllerPassword.text.trim());
+
+ FirebaseFirestore firestore =
+ FirebaseFirestore.instance;
+ User? user = FirebaseAuth.instance.currentUser;
+ CollectionReference collection =
+ firestore.collection('users');
+
+ Map data = {
+ 'name': _controllerName.text.trim(),
+ 'phoneNumber': _controllerPhoneNumber.text.trim(),
+ 'uid': user?.uid,
+ };
+
+ try {
+ // Add a new document with an automatically generated ID
+ await collection.add(data);
+ print('Document added successfully!');
+ } catch (e) {
+ print('Error adding document: $e');
+ }
+
+ Navigator.pushNamedAndRemoveUntil(
+ context, "/login", (route) => false);
} on FirebaseAuthException catch (e) {
Fluttertoast.showToast(
msg: e.message.toString(),
@@ -195,6 +262,8 @@ class _SignUpPageState extends State {
_controllerUsername.dispose();
_controllerPassword.dispose();
_corfirmPassword.dispose();
+ _controllerName.dispose();
+ _controllerPhoneNumber.dispose();
super.dispose();
}
}
--
cgit v1.2.3