summaryrefslogtreecommitdiff
path: root/mobile/lib
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/lib')
-rw-r--r--mobile/lib/cart.dart95
-rw-r--r--mobile/lib/credit_card_payment.dart68
-rw-r--r--mobile/lib/login.dart161
-rw-r--r--mobile/lib/main.dart200
-rw-r--r--mobile/lib/order_history.dart181
-rw-r--r--mobile/lib/payement_order.dart81
-rw-r--r--mobile/lib/routes.dart99
-rw-r--r--mobile/lib/signup.dart200
8 files changed, 1085 insertions, 0 deletions
diff --git a/mobile/lib/cart.dart b/mobile/lib/cart.dart
new file mode 100644
index 0000000..b3d5b0b
--- /dev/null
+++ b/mobile/lib/cart.dart
@@ -0,0 +1,95 @@
+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 time;
+
+ Ride({
+ required this.name,
+ required this.startLocation,
+ required this.endLocation,
+ required this.time,
+ });
+}
+
+class CartPage extends StatelessWidget {
+ final Ride selectedRide;
+
+ CartPage({required this.selectedRide});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: const Text('Cart'),
+ ),
+ 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: <Widget>[
+ 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: 4),
+ Row(
+ children: [
+ const Icon(Icons.access_time, color: Colors.blue),
+ const SizedBox(width: 4),
+ Text(selectedRide.time),
+ ],
+ ),
+ ],
+ ),
+ ),
+ const SizedBox(height: 20),
+ ElevatedButton(
+ onPressed: () {
+ // Implement payment or confirmation logic here
+ // For now, just print a message
+ print('Processing payment/confirmation...');
+ },
+ child: const Text('Proceed to Payment/Confirm'),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/mobile/lib/credit_card_payment.dart b/mobile/lib/credit_card_payment.dart
new file mode 100644
index 0000000..ef1d737
--- /dev/null
+++ b/mobile/lib/credit_card_payment.dart
@@ -0,0 +1,68 @@
+import 'package:flutter/material.dart';
+
+class CreditCardDetailsPage extends StatelessWidget {
+ final String orderID;
+
+ CreditCardDetailsPage({required this.orderID});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: const Text('Credit Card Details'),
+ ),
+ body: Padding(
+ padding: const EdgeInsets.all(16.0),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ const Icon(
+ Icons.credit_card,
+ size: 100,
+ color: Colors.blue,
+ ),
+ const SizedBox(height: 24.0),
+ TextFormField(
+ decoration: const InputDecoration(
+ labelText: 'Card Number',
+ hintText: 'Enter your card number',
+ prefixIcon: Icon(Icons.payment),
+ ),
+ keyboardType: TextInputType.number,
+ ),
+ const SizedBox(height: 16.0),
+ TextFormField(
+ decoration: const InputDecoration(
+ labelText: 'Expiration Date',
+ hintText: 'MM/YYYY',
+ prefixIcon: Icon(Icons.date_range),
+ ),
+ keyboardType: TextInputType.datetime,
+ ),
+ const SizedBox(height: 16.0),
+ TextFormField(
+ decoration: const InputDecoration(
+ labelText: 'CVV',
+ hintText: 'Enter CVV',
+ prefixIcon: Icon(Icons.lock),
+ ),
+ keyboardType: TextInputType.number,
+ obscureText: true,
+ ),
+ const SizedBox(height: 24.0),
+ ElevatedButton(
+ onPressed: () {
+ // TODO:
+ // Implement payment processing logic here
+ print('Payment processed for Order ID: $orderID');
+ Navigator.pop(
+ context); // Return to previous screen after payment
+ },
+ child: const Text('Submit Payment'),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/mobile/lib/login.dart b/mobile/lib/login.dart
new file mode 100644
index 0000000..b210650
--- /dev/null
+++ b/mobile/lib/login.dart
@@ -0,0 +1,161 @@
+import 'package:flutter/material.dart';
+import 'package:fluttertoast/fluttertoast.dart';
+import 'package:firebase_auth/firebase_auth.dart';
+
+class LoginPage extends StatefulWidget {
+ const LoginPage({
+ Key? key,
+ }) : super(key: key);
+
+ @override
+ State<LoginPage> createState() => _LoginPageState();
+}
+
+class _LoginPageState extends State<LoginPage> {
+ final GlobalKey<FormState> _formKey = GlobalKey();
+
+ final FocusNode _focusNodePassword = FocusNode();
+ final TextEditingController _controllerUsername = TextEditingController();
+ final TextEditingController _controllerPassword = TextEditingController();
+
+ bool _obscurePassword = true;
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ backgroundColor: Colors.grey[300],
+ body: Form(
+ key: _formKey,
+ child: SingleChildScrollView(
+ padding: const EdgeInsets.all(30.0),
+ child: Column(
+ children: [
+ Image.asset(
+ "assets/logo.png",
+ height: 190,
+ ),
+ Text(
+ "Welcome back",
+ style: Theme.of(context).textTheme.headlineMedium,
+ ),
+ Text(
+ "Login to your account",
+ style: Theme.of(context).textTheme.bodySmall,
+ ),
+ const SizedBox(height: 40),
+ TextFormField(
+ controller: _controllerUsername,
+ keyboardType: TextInputType.name,
+ decoration: InputDecoration(
+ labelText: "Email",
+ prefixIcon: const Icon(Icons.email_outlined),
+ border: OutlineInputBorder(
+ borderRadius: BorderRadius.circular(10),
+ ),
+ enabledBorder: OutlineInputBorder(
+ borderRadius: BorderRadius.circular(10),
+ ),
+ ),
+ onEditingComplete: () => _focusNodePassword.requestFocus(),
+ validator: (String? value) {
+ if (value == null || value.isEmpty) {
+ return "Please enter username.";
+ }
+
+ return null;
+ },
+ ),
+ const SizedBox(height: 10),
+ TextFormField(
+ controller: _controllerPassword,
+ focusNode: _focusNodePassword,
+ obscureText: _obscurePassword,
+ keyboardType: TextInputType.visiblePassword,
+ decoration: InputDecoration(
+ labelText: "Password",
+ prefixIcon: const Icon(Icons.password_outlined),
+ suffixIcon: IconButton(
+ onPressed: () {
+ setState(() {
+ _obscurePassword = !_obscurePassword;
+ });
+ },
+ icon: _obscurePassword
+ ? const Icon(Icons.visibility_outlined)
+ : const Icon(Icons.visibility_off_outlined)),
+ border: OutlineInputBorder(
+ borderRadius: BorderRadius.circular(10),
+ ),
+ enabledBorder: OutlineInputBorder(
+ borderRadius: BorderRadius.circular(10),
+ ),
+ ),
+ validator: (String? value) {
+ if (value == null || value.isEmpty) {
+ return "Please enter password.";
+ }
+
+ return null;
+ },
+ ),
+ const SizedBox(height: 60),
+ Column(
+ children: [
+ ElevatedButton(
+ style: ElevatedButton.styleFrom(
+ minimumSize: const Size.fromHeight(50),
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(20),
+ ),
+ backgroundColor: Color(0xFF355291),
+ ),
+ onPressed: () async {
+ if (_formKey.currentState?.validate() ?? false) {
+ try {
+ await FirebaseAuth.instance
+ .signInWithEmailAndPassword(
+ email: _controllerUsername.text.trim(),
+ password: _controllerPassword.text.trim())
+ .then((value) =>
+ Navigator.pushNamedAndRemoveUntil(
+ context, '/', (route) => false));
+ } on FirebaseAuthException catch (e) {
+ Fluttertoast.showToast(
+ msg: e.message.toString(),
+ gravity: ToastGravity.SNACKBAR);
+ }
+ }
+ },
+ child: const Text("Login"),
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ const Text("Don't have an account?"),
+ TextButton(
+ onPressed: () {
+ _formKey.currentState?.reset();
+ Navigator.pushNamedAndRemoveUntil(
+ context, "/signup", (route) => false);
+ },
+ child: const Text("Signup"),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ),
+ );
+ }
+
+ @override
+ void dispose() {
+ _focusNodePassword.dispose();
+ _controllerUsername.dispose();
+ _controllerPassword.dispose();
+ super.dispose();
+ }
+}
diff --git a/mobile/lib/main.dart b/mobile/lib/main.dart
new file mode 100644
index 0000000..5fd2374
--- /dev/null
+++ b/mobile/lib/main.dart
@@ -0,0 +1,200 @@
+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 'payement_order.dart';
+import 'signup.dart';
+import 'order_history.dart';
+
+void main() async {
+ WidgetsFlutterBinding.ensureInitialized();
+ await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
+ runApp(MyApp());
+}
+
+class MyApp extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ title: 'Carpool App',
+ theme: ThemeData(
+ primarySwatch: Colors.blue,
+ visualDensity: VisualDensity.adaptivePlatformDensity,
+ ),
+ home: HomePage(),
+ routes: {
+ '/signup': (context) => const SignUpPage(),
+ '/login': (context) => const LoginPage(),
+ '/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',
+ )),
+ },
+ );
+ }
+}
+
+class HomePage extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ 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');
+ },
+ ),
+ ],
+ ),
+ ),
+ body: Center(
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ const SizedBox(height: 20),
+ const Text(
+ 'Hello there',
+ style: TextStyle(
+ fontSize: 48,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ const SizedBox(height: 20),
+ const Text(
+ 'Welcome to Carpool',
+ style: TextStyle(
+ fontSize: 18,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ const SizedBox(height: 20),
+ Image.asset(
+ 'assets/logo.png',
+ width: 200,
+ height: 200,
+ ),
+ const SizedBox(height: 40),
+ ElevatedButton(
+ onPressed: () {
+ Navigator.pushNamed(context, '/login');
+ },
+ style: ElevatedButton.styleFrom(
+ primary: Colors.blue,
+ ),
+ child: const Padding(
+ padding: EdgeInsets.symmetric(horizontal: 40, vertical: 16),
+ child: Text(
+ 'Login',
+ style: TextStyle(
+ fontSize: 18,
+ color: Colors.white,
+ ),
+ ),
+ ),
+ ),
+ const SizedBox(height: 20),
+ ElevatedButton(
+ onPressed: () {
+ Navigator.pushNamed(context, '/signup');
+ },
+ style: ElevatedButton.styleFrom(
+ primary: Colors.green,
+ ),
+ child: const Padding(
+ padding: EdgeInsets.symmetric(horizontal: 40, vertical: 16),
+ child: Text(
+ 'Signup',
+ style: TextStyle(
+ fontSize: 18,
+ color: Colors.white,
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+
+ Widget _buildDrawerItem({
+ required IconData icon,
+ required String text,
+ required VoidCallback onTap,
+ }) {
+ return ListTile(
+ leading: Icon(icon),
+ title: Text(text),
+ onTap: onTap,
+ );
+ }
+}
diff --git a/mobile/lib/order_history.dart b/mobile/lib/order_history.dart
new file mode 100644
index 0000000..543a5ec
--- /dev/null
+++ b/mobile/lib/order_history.dart
@@ -0,0 +1,181 @@
+import 'package:flutter/material.dart';
+import 'package:intl/intl.dart';
+
+class RideOrder {
+ final String orderID;
+ final String driverName;
+ final String carModel;
+ final Color? carColor;
+ final String plateNumber;
+ final String status;
+ final DateTime orderTime;
+
+ RideOrder({
+ required this.orderID,
+ required this.driverName,
+ required this.carModel,
+ required this.carColor,
+ required this.plateNumber,
+ required this.status,
+ required this.orderTime,
+ });
+}
+
+class OrderHistoryPage extends StatelessWidget {
+ final List<RideOrder> orders = [
+ RideOrder(
+ orderID: '001',
+ driverName: 'John Doe',
+ 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)),
+ ),
+ ];
+
+ Color _getStatusColor(String status) {
+ switch (status.toLowerCase()) {
+ case 'completed':
+ return Colors.green;
+ case 'pending':
+ return Colors.orange;
+ case 'cancelled':
+ return Colors.red;
+ // Add more cases for other statuses
+ default:
+ return Colors.grey;
+ }
+ }
+
+ String _formatDateTime(DateTime dateTime) {
+ return DateFormat('EEEE dd/MM/yyyy hh:mm a').format(dateTime);
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: const Text('Order History'),
+ ),
+ body: ListView.builder(
+ itemCount: orders.length,
+ itemBuilder: (BuildContext context, int index) {
+ final RideOrder order = orders[index];
+ return Card(
+ elevation: 3,
+ margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(12),
+ ),
+ child: ListTile(
+ title: Row(
+ children: [
+ Expanded(
+ child: Text(
+ '${order.driverName} - ${order.carModel}',
+ style: const TextStyle(
+ fontWeight: FontWeight.bold,
+ ),
+ overflow: TextOverflow.ellipsis,
+ ),
+ ),
+ ],
+ ),
+ subtitle: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ _formatDateTime(order.orderTime),
+ style: const TextStyle(
+ fontSize: 12,
+ color: Colors.grey,
+ ),
+ ),
+ Text(
+ order.status,
+ style: TextStyle(
+ color: _getStatusColor(order.status),
+ ),
+ ),
+ ],
+ ),
+ Row(
+ children: [
+ Icon(Icons.time_to_leave, color: order.carColor), //
+ const SizedBox(width: 4),
+ Text(order.plateNumber),
+ ],
+ ),
+ ],
+ ),
+ leading: const Icon(Icons
+ .assignment), // Use an appropriate icon for order history
+ onTap: () {
+ // Handle tapping on a specific order (if needed)
+ print('Selected Order ID: ${order.orderID}');
+ },
+ ),
+ );
+ },
+ ),
+ );
+ }
+}
diff --git a/mobile/lib/payement_order.dart b/mobile/lib/payement_order.dart
new file mode 100644
index 0000000..eac05ec
--- /dev/null
+++ b/mobile/lib/payement_order.dart
@@ -0,0 +1,81 @@
+import 'package:flutter/material.dart';
+import 'credit_card_payment.dart';
+
+class Order {
+ final String orderID;
+ final String rideName;
+ final String status;
+ final double amount;
+
+ Order(
+ {required this.orderID,
+ required this.rideName,
+ 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),
+ ];
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: 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,
+ ),
+ ),
+ 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
+ ),
+ ),
+ );
+ },
+ ),
+ );
+ }
+}
diff --git a/mobile/lib/routes.dart b/mobile/lib/routes.dart
new file mode 100644
index 0000000..de5864c
--- /dev/null
+++ b/mobile/lib/routes.dart
@@ -0,0 +1,99 @@
+import 'package:flutter/material.dart';
+import 'cart.dart';
+import 'package:intl/intl.dart';
+
+class Route {
+ final String name;
+ final String startLocation;
+ final String endLocation;
+
+ Route(
+ {required this.name,
+ required this.startLocation,
+ required this.endLocation});
+}
+
+class RoutesPage extends StatelessWidget {
+ final List<Route> dummyRoutes = [
+ Route(
+ name: 'Morning Ride - Gate 3 to Abdu-Basha',
+ startLocation: 'Abassyia',
+ endLocation: 'Abdu-Basha Gate-3'),
+ Route(
+ name: 'Morning Ride - Abdu-Basha to 5th Settlement',
+ startLocation: 'Abdu-Basha',
+ endLocation: '5th Settlement'),
+ Route(
+ name: 'Afternoon Ride - Abdu-Basha to Gate 3',
+ startLocation: 'Hadayek Elkoba',
+ endLocation: 'Abdu-Basha Gate-6'),
+ ];
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(title: const Text('Routes')),
+ body: ListView.builder(
+ itemCount: dummyRoutes.length,
+ itemBuilder: (BuildContext context, int index) {
+ final Route route = dummyRoutes[index];
+ 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,
+ );
+ Navigator.push(
+ context,
+ MaterialPageRoute(
+ builder: (context) => CartPage(selectedRide: selectedRide),
+ ),
+ );
+ },
+ child: Card(
+ elevation: 3,
+ margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(12),
+ ),
+ child: ListTile(
+ title: Text(
+ route.name,
+ style: const TextStyle(
+ fontWeight: FontWeight.bold,
+ fontSize: 16,
+ ),
+ ),
+ subtitle: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ children: [
+ const Icon(Icons.location_on, color: Colors.blue),
+ const SizedBox(width: 4),
+ Flexible(child: Text(route.startLocation)),
+ ],
+ ),
+ Row(
+ children: [
+ const Icon(Icons.arrow_forward, color: Colors.blue),
+ const SizedBox(width: 4),
+ Flexible(child: Text(route.endLocation)),
+ ],
+ ),
+ ],
+ ),
+ leading: const Icon(Icons.directions_car),
+ ),
+ ),
+ );
+ },
+ ),
+ );
+ }
+}
diff --git a/mobile/lib/signup.dart b/mobile/lib/signup.dart
new file mode 100644
index 0000000..18a27ad
--- /dev/null
+++ b/mobile/lib/signup.dart
@@ -0,0 +1,200 @@
+import 'package:flutter/material.dart';
+import 'package:firebase_auth/firebase_auth.dart';
+import 'package:fluttertoast/fluttertoast.dart';
+
+class SignUpPage extends StatefulWidget {
+ const SignUpPage({
+ Key? key,
+ }) : super(key: key);
+
+ @override
+ State<SignUpPage> createState() => _SignUpPageState();
+}
+
+class _SignUpPageState extends State<SignUpPage> {
+ final GlobalKey<FormState> _formKey = GlobalKey();
+
+ final FocusNode _focusNodePassword = FocusNode();
+ final FocusNode _focusNodeConfirmPassword = FocusNode();
+ final TextEditingController _controllerUsername = TextEditingController();
+ final TextEditingController _controllerPassword = TextEditingController();
+ final TextEditingController _corfirmPassword = TextEditingController();
+
+ bool _obscurePassword = true;
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ backgroundColor: Colors.grey[300],
+ body: Form(
+ key: _formKey,
+ child: SingleChildScrollView(
+ padding: const EdgeInsets.all(30.0),
+ child: Column(
+ children: [
+ const SizedBox(height: 20),
+ Image.asset(
+ "assets/logo.png",
+ height: 190,
+ ),
+ Text(
+ "Welcome ",
+ style: Theme.of(context).textTheme.headlineMedium,
+ ),
+ Text(
+ "Create your account",
+ style: Theme.of(context).textTheme.bodySmall,
+ ),
+ const SizedBox(height: 40),
+ TextFormField(
+ controller: _controllerUsername,
+ keyboardType: TextInputType.name,
+ decoration: InputDecoration(
+ labelText: "Email",
+ prefixIcon: const Icon(Icons.email_outlined),
+ border: OutlineInputBorder(
+ borderRadius: BorderRadius.circular(10),
+ ),
+ enabledBorder: OutlineInputBorder(
+ borderRadius: BorderRadius.circular(10),
+ ),
+ ),
+ onEditingComplete: () => _focusNodePassword.requestFocus(),
+ validator: (String? value) {
+ if (value == null || value.isEmpty) {
+ return "Please enter username.";
+ }
+
+ return null;
+ },
+ ),
+ const SizedBox(height: 10),
+ TextFormField(
+ controller: _controllerPassword,
+ focusNode: _focusNodePassword,
+ obscureText: _obscurePassword,
+ keyboardType: TextInputType.visiblePassword,
+ decoration: InputDecoration(
+ labelText: "Password",
+ prefixIcon: const Icon(Icons.password_outlined),
+ suffixIcon: IconButton(
+ onPressed: () {
+ setState(() {
+ _obscurePassword = !_obscurePassword;
+ });
+ },
+ icon: _obscurePassword
+ ? const Icon(Icons.visibility_outlined)
+ : const Icon(Icons.visibility_off_outlined)),
+ border: OutlineInputBorder(
+ borderRadius: BorderRadius.circular(10),
+ ),
+ enabledBorder: OutlineInputBorder(
+ borderRadius: BorderRadius.circular(10),
+ ),
+ ),
+ validator: (String? value) {
+ if (value == null || value.isEmpty) {
+ return "Please enter password.";
+ }
+
+ return null;
+ },
+ ),
+ const SizedBox(height: 10),
+ TextFormField(
+ controller: _corfirmPassword,
+ focusNode: _focusNodeConfirmPassword,
+ obscureText: _obscurePassword,
+ keyboardType: TextInputType.visiblePassword,
+ decoration: InputDecoration(
+ labelText: "Confirm Password",
+ prefixIcon: const Icon(Icons.password_outlined),
+ suffixIcon: IconButton(
+ onPressed: () {
+ setState(() {
+ _obscurePassword = !_obscu