├── ios
├── Flutter
│ ├── Debug.xcconfig
│ ├── Release.xcconfig
│ └── AppFrameworkInfo.plist
├── Runner
│ ├── Runner-Bridging-Header.h
│ ├── Assets.xcassets
│ │ ├── LaunchImage.imageset
│ │ │ ├── LaunchImage.png
│ │ │ ├── LaunchImage@2x.png
│ │ │ ├── LaunchImage@3x.png
│ │ │ ├── README.md
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ ├── Icon-App-20x20@1x.png
│ │ │ ├── Icon-App-20x20@2x.png
│ │ │ ├── Icon-App-20x20@3x.png
│ │ │ ├── Icon-App-29x29@1x.png
│ │ │ ├── Icon-App-29x29@2x.png
│ │ │ ├── Icon-App-29x29@3x.png
│ │ │ ├── Icon-App-40x40@1x.png
│ │ │ ├── Icon-App-40x40@2x.png
│ │ │ ├── Icon-App-40x40@3x.png
│ │ │ ├── Icon-App-50x50@1x.png
│ │ │ ├── Icon-App-50x50@2x.png
│ │ │ ├── Icon-App-57x57@1x.png
│ │ │ ├── Icon-App-57x57@2x.png
│ │ │ ├── Icon-App-60x60@2x.png
│ │ │ ├── Icon-App-60x60@3x.png
│ │ │ ├── Icon-App-72x72@1x.png
│ │ │ ├── Icon-App-72x72@2x.png
│ │ │ ├── Icon-App-76x76@1x.png
│ │ │ ├── Icon-App-76x76@2x.png
│ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ ├── Icon-App-83.5x83.5@2x.png
│ │ │ └── Contents.json
│ ├── AppDelegate.swift
│ ├── Base.lproj
│ │ ├── Main.storyboard
│ │ └── LaunchScreen.storyboard
│ └── Info.plist
├── Runner.xcworkspace
│ └── contents.xcworkspacedata
├── Runner.xcodeproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ ├── xcshareddata
│ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ └── project.pbxproj
└── .gitignore
├── assets
├── Oswald-Light.ttf
├── Oswald-Regular.ttf
├── Pacifico-Regular.ttf
├── images
│ ├── check_img.png
│ └── login_icon.png
├── images_readme
│ ├── 1.png
│ ├── 10.png
│ ├── 11.png
│ ├── 12.png
│ ├── 2.png
│ ├── 3.png
│ ├── 4.png
│ ├── 5.png
│ ├── 6.png
│ ├── 7.png
│ ├── 8.png
│ └── 9.png
├── SpecialElite-Regular.ttf
├── FiraSansExtraCondensed-Light.ttf
├── FiraSansExtraCondensed-Regular.ttf
├── FiraSansExtraCondensed-SemiBold.ttf
└── map_style.txt
├── android
├── app
│ ├── .settings
│ │ └── org.eclipse.buildship.core.prefs
│ ├── src
│ │ ├── main
│ │ │ ├── res
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── values
│ │ │ │ │ └── styles.xml
│ │ │ │ └── drawable
│ │ │ │ │ └── launch_background.xml
│ │ │ ├── kotlin
│ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── flutter_app
│ │ │ │ │ └── MainActivity.kt
│ │ │ └── AndroidManifest.xml
│ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ └── profile
│ │ │ └── AndroidManifest.xml
│ ├── .classpath
│ ├── .project
│ ├── google-services.json
│ └── build.gradle
├── gradle.properties
├── .gitignore
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── .settings
│ └── org.eclipse.buildship.core.prefs
├── .project
├── settings.gradle
└── build.gradle
├── .metadata
├── .vscode
└── launch.json
├── lib
├── main.dart
├── widgets
│ ├── ReviewCard.dart
│ └── RideResultCard.dart
├── services
│ ├── Authenticator.dart
│ ├── fakeDB.dart
│ └── DataBase.dart
├── screens
│ ├── AuthScreen.dart
│ ├── ConfirmScreen.dart
│ ├── MyApp.dart
│ ├── HomeScreen.dart
│ ├── LoginScreen.dart
│ ├── ReviewsScreen.dart
│ ├── ProfileScreen.dart
│ └── ProfileEditScreen.dart
└── models
│ ├── ReviewModel.dart
│ ├── SearchModel.dart
│ ├── UserModel.dart
│ ├── RidesModel.dart
│ └── UserRide.dart
├── .gitignore
├── test
└── widget_test.dart
├── pubspec.yaml
├── README.md
├── LICENSE
└── pubspec.lock
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
--------------------------------------------------------------------------------
/assets/Oswald-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/assets/Oswald-Light.ttf
--------------------------------------------------------------------------------
/assets/Oswald-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/assets/Oswald-Regular.ttf
--------------------------------------------------------------------------------
/assets/Pacifico-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/assets/Pacifico-Regular.ttf
--------------------------------------------------------------------------------
/assets/images/check_img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/assets/images/check_img.png
--------------------------------------------------------------------------------
/assets/images_readme/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/assets/images_readme/1.png
--------------------------------------------------------------------------------
/assets/images_readme/10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/assets/images_readme/10.png
--------------------------------------------------------------------------------
/assets/images_readme/11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/assets/images_readme/11.png
--------------------------------------------------------------------------------
/assets/images_readme/12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/assets/images_readme/12.png
--------------------------------------------------------------------------------
/assets/images_readme/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/assets/images_readme/2.png
--------------------------------------------------------------------------------
/assets/images_readme/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/assets/images_readme/3.png
--------------------------------------------------------------------------------
/assets/images_readme/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/assets/images_readme/4.png
--------------------------------------------------------------------------------
/assets/images_readme/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/assets/images_readme/5.png
--------------------------------------------------------------------------------
/assets/images_readme/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/assets/images_readme/6.png
--------------------------------------------------------------------------------
/assets/images_readme/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/assets/images_readme/7.png
--------------------------------------------------------------------------------
/assets/images_readme/8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/assets/images_readme/8.png
--------------------------------------------------------------------------------
/assets/images_readme/9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/assets/images_readme/9.png
--------------------------------------------------------------------------------
/android/app/.settings/org.eclipse.buildship.core.prefs:
--------------------------------------------------------------------------------
1 | connection.project.dir=..
2 | eclipse.preferences.version=1
3 |
--------------------------------------------------------------------------------
/assets/images/login_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/assets/images/login_icon.png
--------------------------------------------------------------------------------
/assets/SpecialElite-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/assets/SpecialElite-Regular.ttf
--------------------------------------------------------------------------------
/assets/FiraSansExtraCondensed-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/assets/FiraSansExtraCondensed-Light.ttf
--------------------------------------------------------------------------------
/assets/FiraSansExtraCondensed-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/assets/FiraSansExtraCondensed-Regular.ttf
--------------------------------------------------------------------------------
/assets/FiraSansExtraCondensed-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/assets/FiraSansExtraCondensed-SemiBold.ttf
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.enableR8=true
3 | android.useAndroidX=true
4 | android.enableJetifier=true
5 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickosmark/ShareMyRide/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
7 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: 0b8abb4724aa590dd0f429683339b1e045a1594d
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/android/app/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "Flutter",
9 | "request": "launch",
10 | "type": "dart"
11 | }
12 | ]
13 | }
--------------------------------------------------------------------------------
/android/.settings/org.eclipse.buildship.core.prefs:
--------------------------------------------------------------------------------
1 | arguments=
2 | auto.sync=false
3 | build.scans.enabled=false
4 | connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(6.3))
5 | connection.project.dir=
6 | eclipse.preferences.version=1
7 | gradle.user.home=
8 | java.home=C\:/Program Files/Java/jdk-13.0.2
9 | jvm.arguments=
10 | offline.mode=false
11 | override.workspace.settings=true
12 | show.console.view=true
13 | show.executions.view=true
14 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/android/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | android
4 | Project android created by Buildship.
5 |
6 |
7 |
8 |
9 | org.eclipse.buildship.core.gradleprojectbuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.buildship.core.gradleprojectnature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/example/flutter_app/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.flutter_app
2 |
3 | import androidx.annotation.NonNull;
4 | import io.flutter.embedding.android.FlutterActivity
5 | import io.flutter.embedding.engine.FlutterEngine
6 | import io.flutter.plugins.GeneratedPluginRegistrant
7 |
8 | class MainActivity: FlutterActivity() {
9 | override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
10 | GeneratedPluginRegistrant.registerWith(flutterEngine);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
4 |
5 | def plugins = new Properties()
6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
7 | if (pluginsFile.exists()) {
8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
9 | }
10 |
11 | plugins.each { name, path ->
12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
13 | include ":$name"
14 | project(":$name").projectDir = pluginDirectory
15 | }
16 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_app/models/UserModel.dart';
3 | import 'package:flutter_app/screens/AuthScreen.dart';
4 | import 'package:flutter_app/screens/HomeScreen.dart';
5 | import 'screens/ProfileScreen.dart';
6 | import 'screens/RidesScreen.dart';
7 | import 'services/fakeDB.dart';
8 | import 'package:flutter_app/screens/MyApp.dart';
9 |
10 | void main() => runApp(Welcome());
11 |
12 |
13 | class Welcome extends StatelessWidget {
14 | @override
15 | Widget build(BuildContext context) {
16 | return MaterialApp(
17 | home: AuthScreen(),
18 | );
19 | }
20 | }
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.mode2v3
3 | *.moved-aside
4 | *.pbxuser
5 | *.perspectivev3
6 | **/*sync/
7 | .sconsign.dblite
8 | .tags*
9 | **/.vagrant/
10 | **/DerivedData/
11 | Icon?
12 | **/Pods/
13 | **/.symlinks/
14 | profile
15 | xcuserdata
16 | **/.generated/
17 | Flutter/App.framework
18 | Flutter/Flutter.framework
19 | Flutter/Flutter.podspec
20 | Flutter/Generated.xcconfig
21 | Flutter/app.flx
22 | Flutter/app.zip
23 | Flutter/flutter_assets/
24 | Flutter/flutter_export_environment.sh
25 | ServiceDefinitions.json
26 | Runner/GeneratedPluginRegistrant.*
27 |
28 | # Exceptions to above rules.
29 | !default.mode1v3
30 | !default.mode2v3
31 | !default.pbxuser
32 | !default.perspectivev3
33 |
--------------------------------------------------------------------------------
/android/app/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | app
4 | Project app created by Buildship.
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.buildship.core.gradleprojectbuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.jdt.core.javanature
21 | org.eclipse.buildship.core.gradleprojectnature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | .dart_tool/
26 | .flutter-plugins
27 | .flutter-plugins-dependencies
28 | .packages
29 | .pub-cache/
30 | .pub/
31 | /build/
32 |
33 | # Web related
34 | lib/generated_plugin_registrant.dart
35 |
36 | # Exceptions to above rules.
37 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
38 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.3.50'
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.5.0'
10 | classpath 'com.google.gms:google-services:4.3.3'
11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | google()
18 | jcenter()
19 | }
20 | }
21 |
22 | rootProject.buildDir = '../build'
23 | subprojects {
24 | project.buildDir = "${rootProject.buildDir}/${project.name}"
25 | }
26 | subprojects {
27 | project.evaluationDependsOn(':app')
28 | }
29 |
30 | task clean(type: Delete) {
31 | delete rootProject.buildDir
32 | }
33 |
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 8.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/lib/widgets/ReviewCard.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_app/models/ReviewModel.dart';
3 |
4 | class ReviewCard extends StatelessWidget {
5 |
6 | final ReviewModel reviewModel;
7 |
8 | const ReviewCard({
9 | @required this.reviewModel,
10 | });
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | return Card(
15 | margin: EdgeInsets.symmetric(vertical: 5.0, horizontal: 15.0),
16 | child: ListTile(
17 | leading: CircleAvatar(
18 | backgroundImage: new NetworkImage(
19 | reviewModel.imageUrl)),
20 | title: Text(reviewModel.name),
21 | subtitle: Text(reviewModel.reviewText),
22 | trailing: Row(
23 | mainAxisSize: MainAxisSize.min,
24 | children: [
25 | Text(reviewModel.rating.toString()),
26 | Icon(
27 | Icons.star,
28 | size: 15.0,
29 | ),
30 | ],
31 | ),
32 | ),
33 | );
34 | }
35 | }
--------------------------------------------------------------------------------
/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | // This is a basic Flutter widget test.
2 | //
3 | // To perform an interaction with a widget in your test, use the WidgetTester
4 | // utility that Flutter provides. For example, you can send tap and scroll
5 | // gestures. You can also use WidgetTester to find child widgets in the widget
6 | // tree, read text, and verify that the values of widget properties are correct.
7 |
8 | import 'package:flutter/material.dart';
9 | import 'package:flutter_app/screens/MyApp.dart';
10 | import 'package:flutter_test/flutter_test.dart';
11 |
12 | import 'package:flutter_app/main.dart';
13 |
14 | void main() {
15 | testWidgets('Counter increments smoke test', (WidgetTester tester) async {
16 | // Build our app and trigger a frame.
17 | await tester.pumpWidget(MyApp());
18 |
19 | // Verify that our counter starts at 0.
20 | expect(find.text('0'), findsOneWidget);
21 | expect(find.text('1'), findsNothing);
22 |
23 | // Tap the '+' icon and trigger a frame.
24 | await tester.tap(find.byIcon(Icons.add));
25 | await tester.pump();
26 |
27 | // Verify that our counter has incremented.
28 | expect(find.text('0'), findsNothing);
29 | expect(find.text('1'), findsOneWidget);
30 | });
31 | }
32 |
--------------------------------------------------------------------------------
/android/app/google-services.json:
--------------------------------------------------------------------------------
1 | {
2 | "project_info": {
3 | "project_number": "89872132049",
4 | "firebase_url": "https://sharemyride-1f480.firebaseio.com",
5 | "project_id": "sharemyride-1f480",
6 | "storage_bucket": "sharemyride-1f480.appspot.com"
7 | },
8 | "client": [
9 | {
10 | "client_info": {
11 | "mobilesdk_app_id": "1:89872132049:android:4f63b2d0e598d8e8fa22f0",
12 | "android_client_info": {
13 | "package_name": "gr.sharemyride.flutter_app"
14 | }
15 | },
16 | "oauth_client": [
17 | {
18 | "client_id": "89872132049-1igj3goqs58euvlv9hsvmo2o8i0sml4f.apps.googleusercontent.com",
19 | "client_type": 3
20 | }
21 | ],
22 | "api_key": [
23 | {
24 | "current_key": "AIzaSyBr82Dlp0YDhiFSYhX7jG8MhtJj80XAMiw"
25 | }
26 | ],
27 | "services": {
28 | "appinvite_service": {
29 | "other_platform_oauth_client": [
30 | {
31 | "client_id": "89872132049-1igj3goqs58euvlv9hsvmo2o8i0sml4f.apps.googleusercontent.com",
32 | "client_type": 3
33 | }
34 | ]
35 | }
36 | }
37 | }
38 | ],
39 | "configuration_version": "1"
40 | }
--------------------------------------------------------------------------------
/lib/services/Authenticator.dart:
--------------------------------------------------------------------------------
1 | import 'package:firebase_auth/firebase_auth.dart';
2 |
3 | class Authenticator {
4 | final _auth = FirebaseAuth.instance;
5 |
6 |
7 | //can be print in console i guess
8 | Future getAnonUserSingInResult() async {
9 | AuthResult result;
10 | try{
11 | result = await _auth.signInAnonymously();
12 | //AuthResult.user type=FireBaseUser
13 | }catch(e){
14 | result = null;
15 | }
16 | return result;
17 | }
18 |
19 |
20 | // Future getPhoneVerificationResult() async{
21 | // AuthResult result;
22 | // try{
23 | // result = await _auth.ph
24 | // }catch(e){
25 | // print(e);
26 | // result = null;
27 | // }
28 | //
29 | // return result;
30 | // }
31 |
32 | FirebaseUser getAnonUserData(AuthResult result) {
33 | FirebaseUser user;
34 | try{
35 | user = result.user;
36 | }catch(e){
37 | user = null;
38 | }
39 |
40 | return user;
41 | }
42 |
43 | Future getCurrentFireBaseUser()async{
44 | var user = await _auth.currentUser();
45 | return user;
46 | }
47 |
48 | Future getCurrentFireBaseUserID() async {
49 | var currentUser = await _auth.currentUser();
50 | String currentUserId = currentUser.uid;
51 | if(currentUserId == null){
52 | return 'NoUserYet';
53 | }else{
54 | return currentUser.uid;
55 | }
56 | }
57 |
58 | Future isUserAuthenticated() async{
59 | var currentUser = await _auth.currentUser();
60 | if(currentUser == null){
61 | return false;
62 | }else{
63 | return true;
64 | }
65 | }
66 |
67 |
68 |
69 |
70 | }
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | Share My Ride
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: flutter_app
2 | description: A carppoling app where you can find and search for rides
3 |
4 | version: 0.5.0
5 |
6 | environment:
7 | sdk: ">=2.3.0 <3.0.0"
8 |
9 | dependencies:
10 |
11 | datetime_picker_formfield: ^1.0.0
12 | google_maps_flutter: ^0.5.26+4
13 | geolocator: ^5.0.0
14 | search_map_place: ^0.3.0
15 | flutter_polyline_points: ^0.1.0
16 | google_fonts: ^1.0.0
17 | firebase_core: ^0.4.4+3
18 | firebase_auth: ^0.16.0
19 | cloud_firestore: ^0.13.5
20 | flutter_spinkit: ^4.1.2+1
21 | geoflutterfire: ^2.1.0
22 | geocoder: ^0.2.1
23 | fluttertoast: ^4.0.0
24 |
25 | flutter_rating_bar: ^3.0.1+1
26 | flutter:
27 | sdk: flutter
28 |
29 |
30 | cupertino_icons: ^0.1.2
31 |
32 | dev_dependencies:
33 | flutter_test:
34 | sdk: flutter
35 |
36 | flutter_launcher_icons: "^0.7.3"
37 |
38 | flutter_icons:
39 | android: true
40 | ios: true
41 | image_path: "assets/images/login_icon.png"
42 |
43 |
44 | flutter:
45 |
46 |
47 | uses-material-design: true
48 |
49 |
50 | assets:
51 | - assets/images/login_icon.png
52 | - assets/map_style.txt
53 | - assets/images/check_img.png
54 |
55 |
56 | fonts:
57 | - family: special
58 | fonts:
59 | - asset: assets/SpecialElite-Regular.ttf
60 |
61 | - family: oswald
62 | fonts:
63 | - asset: assets/Oswald-Regular.ttf
64 |
65 | - family: pacifico
66 | fonts:
67 | - asset: assets/Pacifico-Regular.ttf
68 |
69 | - family: fira
70 | fonts:
71 | - asset: assets/FiraSansExtraCondensed-Regular.ttf
72 | - asset: assets/FiraSansExtraCondensed-Light.ttf
73 | weight: 200
74 | - asset: assets/FiraSansExtraCondensed-SemiBold.ttf
75 | weight: 600
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
8 |
12 |
14 |
21 |
22 |
23 |
24 |
25 |
26 |
28 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Share My Ride :blue_car:
2 |
3 | Share My Ride is a carpooling app that helps drivers and passengers create or request rides and reduce their traveling costs!
4 | The app is entirely built with dart and the flutter framework.
5 |
6 | # Features
7 |
8 | - Create new rides
9 | - Search existing rides in 3km radius from your destination!
10 |
11 |
12 |
13 |
14 | - Create/Search Rendezvous Points where you can pick up passengers
15 |
16 |
17 |
18 | - Accept/Decline/Cornfirm/Cancel incoming rides
19 |
20 |
21 |
22 | - Write reviews for other users, passengers or drivers
23 |
24 |
25 |
26 | - View and edit your profile
27 |
28 |
29 |
--------------------------------------------------------------------------------
/lib/screens/AuthScreen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_app/screens/LoginScreen.dart';
3 | import 'package:flutter_app/screens/MyApp.dart';
4 | import 'package:flutter_app/services/Authenticator.dart';
5 | import 'package:flutter_app/services/DataBase.dart';
6 | import 'package:flutter_spinkit/flutter_spinkit.dart';
7 |
8 | class AuthScreen extends StatefulWidget {
9 | @override
10 | _AuthScreenState createState() => _AuthScreenState();
11 | }
12 |
13 | class _AuthScreenState extends State {
14 |
15 | static final _auth = Authenticator();
16 | final db = DataBase(auth: _auth);
17 | bool isAuthenticated;
18 |
19 |
20 |
21 | void printCurrentUserData() async{
22 | var currentUser = await _auth.getCurrentFireBaseUserID();
23 | print('user is $currentUser');
24 | }
25 |
26 | void navigateToCorrectPage() async {
27 | isAuthenticated = await _auth.isUserAuthenticated();
28 | if(isAuthenticated){
29 | print('navigating to APP!!!');
30 | var currentUser = await _auth.getCurrentFireBaseUser();
31 | //var currentDB = DataBase(auth: _auth);
32 | await Future.delayed(const Duration(seconds: 1), () {
33 | Navigator.push(
34 | context,
35 | MaterialPageRoute(
36 | builder: (context) => MyApp(db: db, selectedIndex: 0,),
37 | ),
38 | );
39 | });
40 | }else{
41 | print("navigating to Login");
42 | await Future.delayed(const Duration(seconds: 1), () {
43 | Navigator.push(
44 | context,
45 | MaterialPageRoute(
46 | builder: (context) => LoginScreen(db: db,),
47 | ),
48 | );
49 | });
50 | }
51 |
52 |
53 | }
54 |
55 |
56 | @override
57 | void initState() {
58 | super.initState();
59 | print('inside init state...');
60 | //printCurrentUserData();
61 | navigateToCorrectPage();
62 |
63 | }
64 |
65 |
66 | @override
67 | Widget build(BuildContext context) {
68 | return Scaffold(
69 | body: Center(
70 | child: SpinKitPumpingHeart(
71 | color: Colors.redAccent,
72 | size: 100.0,
73 | ),
74 | ),
75 | );
76 | }
77 | }
--------------------------------------------------------------------------------
/lib/models/ReviewModel.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | //This Model get created when a new review is created
4 | class ReviewModel {
5 | String phone;
6 | String imageUrl;
7 | String name;
8 | String reviewText;
9 | double rating;
10 |
11 |
12 | ReviewModel({
13 | this.phone,
14 | this.imageUrl,
15 | this.name,
16 | this.reviewText,
17 | this.rating,
18 | });
19 |
20 |
21 | ReviewModel copyWith({
22 | String phone,
23 | String imageUrl,
24 | String name,
25 | String reviewText,
26 | double rating,
27 | }) {
28 | return ReviewModel(
29 | phone: phone ?? this.phone,
30 | imageUrl: imageUrl ?? this.imageUrl,
31 | name: name ?? this.name,
32 | reviewText: reviewText ?? this.reviewText,
33 | rating: rating ?? this.rating,
34 | );
35 | }
36 |
37 | Map toMap() {
38 | return {
39 | 'phone' : phone,
40 | 'imageUrl': imageUrl,
41 | 'name': name,
42 | 'reviewText': reviewText,
43 | 'rating': rating,
44 | };
45 | }
46 |
47 | static ReviewModel fromMap(Map map) {
48 | if (map == null) return null;
49 |
50 | double rating = map['rating'].toDouble();
51 |
52 | return ReviewModel(
53 | phone: map['phone'],
54 | imageUrl: map['imageUrl'],
55 | name: map['name'],
56 | reviewText: map['reviewText'],
57 | rating: rating,
58 | );
59 | }
60 |
61 | String toJson() => json.encode(toMap());
62 |
63 | static ReviewModel fromJson(String source) => fromMap(json.decode(source));
64 |
65 | @override
66 | String toString() {
67 | return 'ReviewModel(phone: $phone, imageurl: $imageUrl, name: $name, reviewText: $reviewText, rating: $rating)';
68 | }
69 |
70 | @override
71 | bool operator ==(Object o) {
72 | if (identical(this, o)) return true;
73 |
74 | return o is ReviewModel &&
75 | o.phone == phone &&
76 | o.imageUrl == imageUrl &&
77 | o.name == name &&
78 | o.reviewText == reviewText &&
79 | o.rating == rating;
80 | }
81 |
82 | @override
83 | int get hashCode {
84 | return imageUrl.hashCode ^
85 | name.hashCode ^
86 | reviewText.hashCode ^
87 | rating.hashCode;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = '1'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.0'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply plugin: 'kotlin-android'
26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 |
28 | android {
29 | compileSdkVersion 28
30 |
31 | sourceSets {
32 | main.java.srcDirs += 'src/main/kotlin'
33 | }
34 |
35 | lintOptions {
36 | disable 'InvalidPackage'
37 | }
38 |
39 | defaultConfig {
40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
41 | applicationId "gr.sharemyride.flutter_app"
42 | minSdkVersion 16
43 | targetSdkVersion 28
44 | multiDexEnabled true
45 | versionCode flutterVersionCode.toInteger()
46 | versionName flutterVersionName
47 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
48 | }
49 |
50 | buildTypes {
51 | release {
52 | // TODO: Add your own signing config for the release build.
53 | // Signing with the debug keys for now, so `flutter run --release` works.
54 | signingConfig signingConfigs.debug
55 | }
56 | }
57 | }
58 |
59 | flutter {
60 | source '../..'
61 | }
62 |
63 | dependencies {
64 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
65 | testImplementation 'junit:junit:4.12'
66 | androidTestImplementation 'androidx.test:runner:1.1.1'
67 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
68 | }
69 |
70 | apply plugin: 'com.android.application'
71 | apply plugin: 'com.google.gms.google-services'
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/lib/widgets/RideResultCard.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_app/models/UserModel.dart';
3 | import 'package:flutter_app/models/RidesModel.dart';
4 |
5 | class RideResultCard extends StatelessWidget {
6 |
7 | final RidesModel ridesModel;
8 | final Function(RidesModel) onPressed;
9 | final Color darkBlueColor = Color.fromRGBO(26, 26, 48, 1.0);
10 |
11 | RideResultCard({
12 | this.ridesModel,
13 | this.onPressed
14 | });
15 |
16 | @override
17 | Widget build(BuildContext context) {
18 | UserModel userModel = ridesModel.driver;
19 | String from, to;
20 | double rating = double.parse((userModel.rating).toStringAsFixed(1));
21 | if(ridesModel.fromText.length > 400)
22 | from = ridesModel.fromText.substring(0, 37) + "...";
23 | else
24 | from = ridesModel.fromText;
25 |
26 | if(ridesModel.toText.length > 400)
27 | to = ridesModel.toText.substring(0, 37) + "...";
28 | else
29 | to = ridesModel.toText;
30 |
31 | return Card(
32 | color: Colors.yellow[50],
33 | child: ListTile(
34 | leading: CircleAvatar(
35 | backgroundImage: new NetworkImage(userModel.getUrlFromNameHash(genderInput: userModel.gender)),
36 | radius: 28.0,
37 | ),
38 | title: Padding(
39 | padding: const EdgeInsets.only(top: 10.0),
40 | child: Text(userModel.name),
41 | ),
42 | subtitle: Column(
43 | children: [
44 | SizedBox(
45 | height: 7.0,
46 | ),
47 | SizedBox(child: Text(from), height: 35),
48 | Icon(
49 | Icons.arrow_downward
50 | ),
51 | SizedBox(child: Text(to), height: 35),
52 | SizedBox(
53 | height: 3.0,
54 | ),
55 | RaisedButton(
56 | color: darkBlueColor,
57 | textColor: Colors.white,
58 | child: Text('Show Details'),
59 | onPressed: () {
60 | onPressed(ridesModel);
61 | },
62 | shape: RoundedRectangleBorder(
63 | borderRadius: BorderRadius.circular(30.0)),
64 | ),
65 | ],
66 | ),
67 | trailing: Row(
68 | mainAxisSize: MainAxisSize.min,
69 | children: [
70 | Text(rating.toString()),
71 | Icon(
72 | Icons.star,
73 | size: 15.0,
74 | ),
75 | ],
76 | ),
77 | ),
78 | );
79 | }
80 | }
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/lib/screens/ConfirmScreen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:google_fonts/google_fonts.dart';
3 |
4 | class ConfirmScreen extends StatelessWidget {
5 | var darkBlueColor = Color.fromRGBO(26, 26, 48, 1.0);
6 | var lightBlueColor = Colors.blue;
7 | var lightGreyBackground = Color.fromRGBO(229, 229, 229, 1.0);
8 | @override
9 | Widget build(BuildContext context) {
10 | return MaterialApp(
11 | title: 'ShareMyRide',
12 | theme: ThemeData(
13 | scaffoldBackgroundColor: Colors.white,
14 | primaryColor: darkBlueColor,
15 | accentColor: lightBlueColor,
16 | //cardColor: lightGreyBackground,
17 | textTheme: TextTheme(
18 | body1: TextStyle(color: Color.fromRGBO(26, 26, 48, 1.0)),
19 | ),
20 | ),
21 | home: Scaffold(
22 | body: SafeArea(
23 | child: SafeArea(
24 | child: SingleChildScrollView(
25 | child: Column(
26 | crossAxisAlignment: CrossAxisAlignment.stretch,
27 | children: [
28 | Container(
29 | margin: EdgeInsets.symmetric(
30 | vertical: 25.0, horizontal: 10.0),
31 | child: Text(
32 | "Share My Ride",
33 | style: GoogleFonts.pacifico(
34 | textStyle: TextStyle(fontSize: 50.0)),
35 | textAlign: TextAlign.center,
36 | ),
37 | ),
38 | Container(
39 | padding: EdgeInsets.only(left: 30.0, top: 50.0),
40 | child: Text(
41 | "Confirm",
42 | ),
43 | ),
44 | Container(
45 | padding:
46 | EdgeInsets.only(left: 20.0, right: 20.0, top: 10.0),
47 | child: TextField(
48 | obscureText: false,
49 | decoration: InputDecoration(
50 | border: OutlineInputBorder(),
51 | labelText: "Enter your confirmation code"),
52 | ),
53 | ),
54 | Row(
55 | mainAxisAlignment: MainAxisAlignment.center,
56 | children: [
57 | Container(
58 | padding: EdgeInsets.only(top: 50.0, bottom: 80.0),
59 | child: RaisedButton(
60 | onPressed: () {},
61 | child: Text(
62 | "Confirm",
63 | style: TextStyle(color: Colors.white),
64 | ),
65 | shape: RoundedRectangleBorder(
66 | borderRadius: BorderRadius.circular(30.0)),
67 | color: darkBlueColor,
68 | ),
69 | )
70 | ],
71 | ),
72 | Column(
73 |
74 | children: [
75 | Container(
76 | height: 130.0,
77 | child: Image.asset('assets/images/login_icon.png', color: darkBlueColor,),
78 | )
79 | ],
80 | )
81 | ],
82 | ),
83 | ),
84 | ),
85 | ),
86 | ));
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/lib/models/SearchModel.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:cloud_firestore/cloud_firestore.dart';
4 | import 'package:google_maps_flutter/google_maps_flutter.dart';
5 |
6 | import 'package:flutter_app/models/UserModel.dart';
7 | import 'package:geoflutterfire/geoflutterfire.dart';
8 |
9 | class SearchModel {
10 | String fromText;
11 | String toText;
12 | LatLng fromCords;
13 | LatLng toCords;
14 | DateTime searchDate;
15 | UserModel searcher;
16 |
17 | final Geoflutterfire geo = Geoflutterfire();
18 |
19 | SearchModel({
20 | this.fromText,
21 | this.toText,
22 | this.fromCords,
23 | this.toCords,
24 | this.searchDate,
25 | this.searcher,
26 | });
27 |
28 |
29 |
30 | SearchModel copyWith({
31 | String fromText,
32 | String toText,
33 | LatLng fromCords,
34 | LatLng toCords,
35 | DateTime searchDate,
36 | UserModel searcher,
37 | }) {
38 | return SearchModel(
39 | fromText: fromText ?? this.fromText,
40 | toText: toText ?? this.toText,
41 | fromCords: fromCords ?? this.fromCords,
42 | toCords: toCords ?? this.toCords,
43 | searchDate: searchDate ?? this.searchDate,
44 | searcher: searcher ?? this.searcher,
45 | );
46 | }
47 |
48 | Map fromLatLngtoGeoFirePoint(LatLng latLng){
49 | return geo.point(latitude: latLng.latitude, longitude: latLng.longitude).data;
50 | }
51 |
52 | LatLng fromGeoPointToLatLng(GeoFirePoint point){
53 | return LatLng(point.latitude, point.longitude);
54 | }
55 |
56 |
57 |
58 | Map toMap() {
59 | return {
60 | 'fromText': fromText,
61 | 'toText': toText,
62 | 'fromCords': fromLatLngtoGeoFirePoint(fromCords),
63 | 'toCords': fromLatLngtoGeoFirePoint(toCords),
64 | 'searchDate': searchDate?.millisecondsSinceEpoch,
65 | 'searcher': searcher?.toMap(),
66 | };
67 | }
68 |
69 | static SearchModel fromMap(Map map) {
70 | if (map == null) return null;
71 |
72 | LatLng fromGeoPointToLatLng(Map map){
73 | GeoPoint point = map['geopoint'];
74 | Map result = {
75 | 'geopoint': map['geopoint'],
76 | 'geohash': map['geohash'],
77 | };
78 | return LatLng(point.latitude, point.longitude);
79 | }
80 |
81 | return SearchModel(
82 | fromText: map['fromText'],
83 | toText: map['toText'],
84 | fromCords: fromGeoPointToLatLng(map['fromCords']),
85 | toCords: fromGeoPointToLatLng(map['toCords']),
86 | searchDate: DateTime.fromMillisecondsSinceEpoch(map['searchDate']),
87 | searcher: UserModel.fromMap(map['searcher']),
88 | );
89 | }
90 |
91 | String toJson() => json.encode(toMap());
92 |
93 | static SearchModel fromJson(String source) => fromMap(json.decode(source));
94 |
95 | @override
96 | String toString() {
97 | return 'SearchModel(fromText: $fromText, toText: $toText, fromCords: $fromCords, toCords: $toCords, searchDate: $searchDate, searcher: $searcher)';
98 | }
99 |
100 | @override
101 | bool operator ==(Object o) {
102 | if (identical(this, o)) return true;
103 |
104 | return o is SearchModel &&
105 | o.fromText == fromText &&
106 | o.toText == toText &&
107 | o.fromCords == fromCords &&
108 | o.toCords == toCords &&
109 | o.searchDate == searchDate &&
110 | o.searcher == searcher;
111 | }
112 |
113 | @override
114 | int get hashCode {
115 | return fromText.hashCode ^
116 | toText.hashCode ^
117 | fromCords.hashCode ^
118 | toCords.hashCode ^
119 | searchDate.hashCode ^
120 | searcher.hashCode;
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/lib/screens/MyApp.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 | import 'package:flutter_app/models/UserModel.dart';
4 | import 'package:flutter_app/screens/HomeScreen.dart';
5 | import 'package:flutter_app/screens/ProfileScreen.dart';
6 | import 'package:flutter_app/screens/RidesScreen.dart';
7 | import 'package:flutter_app/services/DataBase.dart';
8 | import 'package:flutter_app/services/fakeDB.dart';
9 |
10 | import 'package:flutter_app/screens/chrisHomeScreen.dart';
11 |
12 |
13 | class MyApp extends StatefulWidget {
14 | final DataBase db;
15 | final int selectedIndex;
16 |
17 | // MyApp contsructor takes a selectedIndex;
18 | // 0 for HomeScreen
19 | // 1 for Rides
20 | // 2 for Profile
21 | MyApp({this.db,this.selectedIndex});
22 |
23 | @override
24 | _MyAppState createState() => _MyAppState();
25 | }
26 |
27 | class _MyAppState extends State {
28 |
29 | void printCurrentUserFromFireStore() async {
30 | UserModel currentUser = await db.getCurrentUserModel();
31 | print(currentUser.toString());
32 | }
33 |
34 | DataBase db;
35 |
36 | //Selected Icon in the bottomNavBar
37 | int _selectedIndex = 0;
38 |
39 | //The screen showing first
40 | Widget _selectedScreen ;
41 |
42 | @override
43 | void initState() {
44 | super.initState();
45 | db = widget.db;
46 | printCurrentUserFromFireStore();
47 | //_selectedScreen = widget.selectedScreen;
48 | _selectedIndex = widget.selectedIndex;
49 | switch (_selectedIndex) {
50 | case 0:
51 | _selectedScreen = ChrisHomeScreen(db: db,);
52 | break;
53 | case 1:
54 | _selectedScreen = RidesScreen(db: db,);
55 | break;
56 | case 2:
57 | _selectedScreen = ProfileScreen(db: db,);
58 | break;
59 | }
60 |
61 | }
62 |
63 |
64 | @override
65 | Widget build(BuildContext context) {
66 | return WillPopScope(
67 | onWillPop: (){
68 | return SystemNavigator.pop();
69 | },
70 | child: MaterialApp(
71 | theme: ThemeData(
72 | fontFamily: 'fira',
73 | textTheme: TextTheme(
74 | body1: TextStyle(
75 | fontFamily: 'fira',
76 | ),
77 | ),
78 | ),
79 | home: Scaffold(
80 | bottomNavigationBar: BottomNavigationBar(
81 | items: const [
82 | BottomNavigationBarItem(
83 | icon: Icon(Icons.home),
84 | title: Text('HOME'),
85 | ),
86 | BottomNavigationBarItem(
87 | icon: Icon(Icons.drive_eta),
88 | title: Text('RIDES'),
89 | ),
90 | BottomNavigationBarItem(
91 | icon: Icon(Icons.account_circle),
92 | title: Text('PROFILE'),
93 | ),
94 | ],
95 | currentIndex: _selectedIndex,
96 | selectedItemColor: Colors.blue,
97 | onTap: (index) {
98 | setState(() {
99 | _selectedIndex = index;
100 | switch (_selectedIndex) {
101 | case 0:
102 | _selectedScreen = ChrisHomeScreen(db: db,);
103 | break;
104 | case 1:
105 | _selectedScreen = RidesScreen(db: db);
106 | break;
107 | case 2:
108 | _selectedScreen = ProfileScreen(db: db,);
109 | break;
110 | }
111 | });
112 | },
113 | ),
114 | body: _selectedScreen,
115 | ),
116 | ),
117 | );
118 | }
119 | }
--------------------------------------------------------------------------------
/assets/map_style.txt:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "elementType": "geometry",
4 | "stylers": [
5 | {
6 | "color": "#212121"
7 | }
8 | ]
9 | },
10 | {
11 | "elementType": "labels.icon",
12 | "stylers": [
13 | {
14 | "visibility": "off"
15 | }
16 | ]
17 | },
18 | {
19 | "elementType": "labels.text.fill",
20 | "stylers": [
21 | {
22 | "color": "#757575"
23 | }
24 | ]
25 | },
26 | {
27 | "elementType": "labels.text.stroke",
28 | "stylers": [
29 | {
30 | "color": "#212121"
31 | }
32 | ]
33 | },
34 | {
35 | "featureType": "administrative",
36 | "elementType": "geometry",
37 | "stylers": [
38 | {
39 | "color": "#757575"
40 | }
41 | ]
42 | },
43 | {
44 | "featureType": "administrative.country",
45 | "elementType": "labels.text.fill",
46 | "stylers": [
47 | {
48 | "color": "#9e9e9e"
49 | }
50 | ]
51 | },
52 | {
53 | "featureType": "administrative.land_parcel",
54 | "stylers": [
55 | {
56 | "visibility": "off"
57 | }
58 | ]
59 | },
60 | {
61 | "featureType": "administrative.locality",
62 | "elementType": "labels.text.fill",
63 | "stylers": [
64 | {
65 | "color": "#bdbdbd"
66 | }
67 | ]
68 | },
69 | {
70 | "featureType": "poi",
71 | "elementType": "labels.text.fill",
72 | "stylers": [
73 | {
74 | "color": "#757575"
75 | }
76 | ]
77 | },
78 | {
79 | "featureType": "poi.park",
80 | "elementType": "geometry",
81 | "stylers": [
82 | {
83 | "color": "#181818"
84 | }
85 | ]
86 | },
87 | {
88 | "featureType": "poi.park",
89 | "elementType": "labels.text.fill",
90 | "stylers": [
91 | {
92 | "color": "#616161"
93 | }
94 | ]
95 | },
96 | {
97 | "featureType": "poi.park",
98 | "elementType": "labels.text.stroke",
99 | "stylers": [
100 | {
101 | "color": "#1b1b1b"
102 | }
103 | ]
104 | },
105 | {
106 | "featureType": "road",
107 | "elementType": "geometry.fill",
108 | "stylers": [
109 | {
110 | "color": "#2c2c2c"
111 | }
112 | ]
113 | },
114 | {
115 | "featureType": "road",
116 | "elementType": "labels.text.fill",
117 | "stylers": [
118 | {
119 | "color": "#8a8a8a"
120 | }
121 | ]
122 | },
123 | {
124 | "featureType": "road.arterial",
125 | "elementType": "geometry",
126 | "stylers": [
127 | {
128 | "color": "#373737"
129 | }
130 | ]
131 | },
132 | {
133 | "featureType": "road.highway",
134 | "elementType": "geometry",
135 | "stylers": [
136 | {
137 | "color": "#3c3c3c"
138 | }
139 | ]
140 | },
141 | {
142 | "featureType": "road.highway.controlled_access",
143 | "elementType": "geometry",
144 | "stylers": [
145 | {
146 | "color": "#4e4e4e"
147 | }
148 | ]
149 | },
150 | {
151 | "featureType": "road.local",
152 | "elementType": "labels.text.fill",
153 | "stylers": [
154 | {
155 | "color": "#616161"
156 | }
157 | ]
158 | },
159 | {
160 | "featureType": "transit",
161 | "elementType": "labels.text.fill",
162 | "stylers": [
163 | {
164 | "color": "#757575"
165 | }
166 | ]
167 | },
168 | {
169 | "featureType": "water",
170 | "elementType": "geometry",
171 | "stylers": [
172 | {
173 | "color": "#000000"
174 | }
175 | ]
176 | },
177 | {
178 | "featureType": "water",
179 | "elementType": "labels.text.fill",
180 | "stylers": [
181 | {
182 | "color": "#3d3d3d"
183 | }
184 | ]
185 | }
186 | ]
--------------------------------------------------------------------------------
/lib/models/UserModel.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:flutter/foundation.dart';
4 |
5 | import 'package:flutter_app/models/ReviewModel.dart';
6 | import 'package:flutter_app/models/RidesModel.dart';
7 | import 'package:flutter_app/models/UserRide.dart';
8 |
9 | enum Gender {
10 | male,
11 | female,
12 | nonBinary,
13 | }
14 |
15 |
16 |
17 | class UserModel {
18 |
19 | String name;
20 | Gender gender;
21 | String phone;
22 | String email;
23 | String carInfo;
24 | double rating;
25 | //
26 | //Constructor
27 | UserModel({
28 | this.name,
29 | this.gender,
30 | this.phone,
31 | this.email,
32 | this.carInfo,
33 | this.rating,
34 | });
35 |
36 | String getUrlFromNameHash({Gender genderInput}){
37 | int id = this.name.hashCode % 100;
38 | switch (genderInput) {
39 | case Gender.male:
40 | return 'https://randomuser.me/api/portraits/men/$id.jpg';
41 | break;
42 | case Gender.female:
43 | return 'https://randomuser.me/api/portraits/women/$id.jpg';
44 | break;
45 | case Gender.nonBinary:
46 | return 'https://img.documentonews.gr/unsafe/1000x600/smart/http://img.dash.documentonews.gr/documento/imagegrid/2018/10/31/5bd98303cd3a18740d2cf935.jpg';
47 | break;
48 | default:
49 | return 'https://upload.wikimedia.org/wikipedia/en/0/00/The_Child_aka_Baby_Yoda_%28Star_Wars%29.jpg';
50 | }
51 |
52 | }
53 |
54 |
55 |
56 | @override
57 | String toString() {
58 | return 'UserModel(name: $name, gender: $gender, phone: $phone, email: $email, carInfo: $carInfo, rating: $rating,)';
59 | }
60 |
61 |
62 |
63 | UserModel copyWith({
64 | String name,
65 | Gender gender,
66 | String phone,
67 | String email,
68 | String carInfo,
69 | double rating,
70 | }) {
71 | return UserModel(
72 | name: name ?? this.name,
73 | gender: gender ?? this.gender,
74 | phone: phone ?? this.phone,
75 | email: email ?? this.email,
76 | carInfo: carInfo ?? this.carInfo,
77 | rating: rating ?? this.rating,
78 | );
79 | }
80 |
81 | Map toMap() {
82 | return {
83 | 'name': name,
84 | 'gender': gender?.toString(),
85 | 'phone': phone,
86 | 'email': email,
87 | 'carInfo': carInfo,
88 | 'rating': rating,
89 | };
90 | }
91 |
92 | static UserModel fromMap(Map map) {
93 | if (map == null) return null;
94 |
95 | Gender gender;
96 | if(map['gender'] == 'Gender.male'){
97 | gender = Gender.male;
98 | }else if(map['gender'] == 'Gender.female'){
99 | gender = Gender.female;
100 | }else if(map['gender'] == 'Gender.nonBinary'){
101 | gender = Gender.nonBinary;
102 | }else{
103 | gender = null;
104 | }
105 |
106 |
107 | return UserModel(
108 | name: map['name'],
109 | gender: gender,
110 | phone: map['phone'],
111 | email: map['email'],
112 | carInfo: map['carInfo'],
113 | rating: map['rating'],
114 | );
115 | }
116 |
117 | String toJson() => json.encode(toMap());
118 |
119 | static UserModel fromJson(String source) => fromMap(json.decode(source));
120 |
121 | @override
122 | bool operator ==(Object o) {
123 | if (identical(this, o)) return true;
124 |
125 | return o is UserModel &&
126 | o.name == name &&
127 | o.gender == gender &&
128 | o.phone == phone &&
129 | o.email == email &&
130 | o.carInfo == carInfo &&
131 | o.rating == rating;
132 |
133 | }
134 |
135 | @override
136 | int get hashCode {
137 | return
138 | name.hashCode ^
139 | gender.hashCode ^
140 | phone.hashCode ^
141 | email.hashCode ^
142 | carInfo.hashCode ^
143 | rating.hashCode;
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/lib/services/fakeDB.dart:
--------------------------------------------------------------------------------
1 | //Random User to display on Screen.
2 | import 'package:flutter_app/models/ReviewModel.dart';
3 | import 'package:flutter_app/models/RidesModel.dart';
4 | import 'package:flutter_app/models/UserModel.dart';
5 | import 'package:flutter_app/models/UserRide.dart';
6 | import 'package:google_maps_flutter/google_maps_flutter.dart';
7 |
8 | class FakeDB {
9 |
10 | static RidesModel fakeRide = new RidesModel(fromText: 'from', toText: 'to', randPoints: [new LatLng(38.236785, 23.94523)], toLatLng: new LatLng(37.236785, 23.44523), dateTime: new DateTime(2020), driver: fakeUser);
11 | static UserModel fakeUser = new UserModel(name: 'name', gender: Gender.male, phone: '699999999', email: 'covid19@gmail.com', carInfo: 'mercedes bench', rating: 1.1);
12 | static ReviewModel reviewModel = new ReviewModel(imageUrl: 'https://randomuser.me/api/portraits/men/52.jpg',
13 | name: 'John Ioannides',
14 | phone: '6999999999',
15 | reviewText: 'God bless Trump!! America is the best country in the world but this driver is shit.',
16 | rating: 5.0,);
17 | // static final UserModel randomDriver39 = UserModel(
18 | // name: 'Odhgouliss',
19 | // gender: Gender.female,
20 | // phone: '+30 699999999',
21 | // email: 'info@covid19.who',
22 | // carInfo: 'Mercedez Benz ;) ',
23 | // reviewsList: [
24 | // //user 52
25 | // ReviewModel(
26 | // imageUrl: 'https://randomuser.me/api/portraits/men/52.jpg',
27 | // name: 'Alexis Tsipras',
28 | // reviewText:
29 | // 'polu kalos DRIVER',
30 | // rating: 5.0,
31 | // ),
32 | // //
33 | // //User 17
34 | // ReviewModel(
35 | // imageUrl: 'https://randomuser.me/api/portraits/men/17.jpg',
36 | // name: 'Rey Mysterio',
37 | // reviewText: 'This driver is the SHIT',
38 | // rating: 5.0,
39 | // ),
40 | // //User 6
41 | // ReviewModel(
42 | // imageUrl: 'https://randomuser.me/api/portraits/men/6.jpg',
43 | // name: 'Donald Trump',
44 | // reviewText: 'covfefe DRIVER',
45 | // rating: 2.0,
46 | // ),
47 | // ],
48 | // ridesList: [],
49 | // );
50 | //
51 | // static final RidesModel ride55 = RidesModel(
52 | // randPoints: [new LatLng(38.236785, 23.94523), new LatLng(38.324466, 23.844654), new LatLng(38.787454, 23.563211), new LatLng(37.67887, 23.454545), new LatLng(37.67887, 22.45)],
53 | // toLatLng: new LatLng(38.67887, 23.45),
54 | // dateTime: new DateTime(2020),
55 | // driver: randomDriver39,
56 | // );
57 | //
58 | // static final UserModel randomPassenger12 = UserModel(
59 | // name: 'Tsampatsidis',
60 | // gender: Gender.female,
61 | // phone: '+30 699999999',
62 | // email: 'info@covid19.who',
63 | // carInfo: 'Mercedez Benz ;) ',
64 | // reviewsList: [
65 | // //user 52
66 | // ReviewModel(
67 | // imageUrl: 'https://randomuser.me/api/portraits/men/52.jpg',
68 | // name: 'John Ioannides',
69 | // reviewText:
70 | // 'God bless Trump!! America is the best country in the world but this driver is shit.',
71 | // rating: 5.0,
72 | // ),
73 | // //
74 | // //User 17
75 | // ReviewModel(
76 | // imageUrl: 'https://randomuser.me/api/portraits/men/17.jpg',
77 | // name: 'Kuriakos Mitsotakis',
78 | // reviewText: 'Menoume Spiti gia na exoume tin ugeia mas',
79 | // rating: 5.0,
80 | // ),
81 | // //User 6
82 | // ReviewModel(
83 | // imageUrl: 'https://randomuser.me/api/portraits/men/6.jpg',
84 | // name: 'Donald Trump',
85 | // reviewText: 'covfefe',
86 | // rating: 2.0,
87 | // ),
88 | // ],
89 | // ridesList: [
90 | // UserRide(
91 | // status: Status.pending,
92 | // isDriver: false,
93 | // ride: ride55,
94 | // fellowTraveler: randomDriver39,
95 | // ),
96 | // ],
97 | // );
98 | //
99 |
100 | }
101 |
102 |
--------------------------------------------------------------------------------
/lib/models/RidesModel.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:cloud_firestore/cloud_firestore.dart';
4 | import 'package:flutter/foundation.dart';
5 | import 'package:flutter/material.dart';
6 | import 'package:google_maps_flutter/google_maps_flutter.dart';
7 |
8 | import 'package:flutter_app/models/UserModel.dart';
9 | import 'package:geoflutterfire/geoflutterfire.dart';
10 |
11 | //These class represents public rides. rides that you can find searching...
12 | //Should be used when someone click CREATE
13 | class RidesModel {
14 |
15 | String fromText;
16 | String toText;
17 | List randPoints;
18 | LatLng toLatLng;
19 | DateTime dateTime;
20 | UserModel driver;
21 |
22 | final Geoflutterfire geo = Geoflutterfire();
23 |
24 | RidesModel({
25 | this.fromText,
26 | this.toText,
27 | this.randPoints,
28 | this.toLatLng,
29 | this.dateTime,
30 | this.driver
31 | });
32 |
33 |
34 | RidesModel copyWith({
35 | String fromText,
36 | String toText,
37 | List randPoints,
38 | LatLng toLatLng,
39 | DateTime dateTime,
40 | UserModel driver,
41 | }) {
42 | return RidesModel(
43 | fromText: fromText ?? this.fromText,
44 | toText: toText ?? this.toText,
45 | randPoints: randPoints ?? this.randPoints,
46 | toLatLng: toLatLng ?? this.toLatLng,
47 | dateTime: dateTime ?? this.dateTime,
48 | driver: driver ?? this.driver,
49 | );
50 | }
51 |
52 | Map fromLatLngtoGeoFirePoint(LatLng latLng){
53 | return geo.point(latitude: latLng.latitude, longitude: latLng.longitude).data;
54 | }
55 |
56 | LatLng fromGeoPointToLatLng(GeoFirePoint point){
57 | return LatLng(point.latitude, point.longitude);
58 | }
59 |
60 | Map toMap(){
61 | return {
62 | 'fromText': fromText,
63 | 'toText': toText,
64 | 'randPoints': randPoints?.map((x) => fromLatLngtoGeoFirePoint(x))?.toList(),
65 | 'toLatLng': fromLatLngtoGeoFirePoint(toLatLng),
66 | 'dateTime': dateTime?.millisecondsSinceEpoch,
67 | 'driver': driver?.toMap()
68 | };
69 | }
70 |
71 |
72 | static RidesModel fromMap(Map map) {
73 | if (map == null) return null;
74 |
75 | LatLng fromGeoPointToLatLng(Map map){
76 | GeoPoint point = map['geopoint'];
77 | Map result = {
78 | 'geopoint': map['geopoint'],
79 | 'geohash': map['geohash'],
80 | };
81 | return LatLng(point.latitude, point.longitude);
82 | }
83 |
84 |
85 | return RidesModel(
86 | fromText: map['fromText'],
87 | toText: map['toText'],
88 | randPoints: List.from(map['randPoints']?.map((x) => fromGeoPointToLatLng(x))),
89 | toLatLng: fromGeoPointToLatLng(map['toLatLng']),
90 | dateTime: DateTime.fromMillisecondsSinceEpoch(map['dateTime']),
91 | driver: UserModel.fromMap(map['driver']),
92 | );
93 | }
94 |
95 |
96 |
97 | //String toJson() => json.encode(toMap());
98 |
99 | //static RidesModel fromJson(String source) => fromMap(json.decode(source));
100 |
101 | @override
102 | String toString() {
103 | return 'RidesModel(fromText: $fromText, toText: $toText, randPoints: $randPoints, toLatLng: $toLatLng, dateTime: $dateTime, driver: $driver)';
104 | }
105 |
106 | @override
107 | bool operator ==(Object o) {
108 | if (identical(this, o)) return true;
109 |
110 | return o is RidesModel &&
111 | o.fromText == fromText &&
112 | o.toText == toText &&
113 | listEquals(o.randPoints, randPoints) &&
114 | o.toLatLng == toLatLng &&
115 | o.dateTime == dateTime &&
116 | o.driver == driver;
117 | }
118 |
119 | @override
120 | int get hashCode {
121 | return fromText.hashCode ^
122 | toText.hashCode ^
123 | randPoints.hashCode ^
124 | toLatLng.hashCode ^
125 | dateTime.hashCode ^
126 | driver.hashCode;
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/lib/models/UserRide.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:cloud_firestore/cloud_firestore.dart';
4 | import 'package:flutter_app/models/RidesModel.dart';
5 | import 'package:flutter_app/models/UserModel.dart';
6 | import 'package:google_maps_flutter/google_maps_flutter.dart';
7 | import 'package:geoflutterfire/geoflutterfire.dart';
8 |
9 | enum Status{
10 | pending,
11 | confirmed,
12 | completed,
13 | myRides,
14 | }
15 |
16 | class UserRide {
17 | String phone;
18 | Status status;
19 | bool isDriver;
20 | bool isFinished;
21 | RidesModel ride;
22 | UserModel fellowTraveler;
23 | LatLng randPoint;
24 |
25 | final Geoflutterfire geo = Geoflutterfire();
26 |
27 | UserRide({
28 | this.phone,
29 | this.status,
30 | this.isDriver,
31 | this.isFinished,
32 | this.ride,
33 | this.fellowTraveler,
34 | this.randPoint,
35 | });
36 |
37 | UserRide copyWith({
38 | String phone,
39 | Status status,
40 | bool isDriver,
41 | bool isFinished,
42 | RidesModel ride,
43 | UserModel fellowTraveler,
44 | LatLng randPoint
45 | }) {
46 | return UserRide(
47 | phone: phone ?? this.phone,
48 | status: status ?? this.status,
49 | isDriver: isDriver ?? this.isDriver,
50 | isFinished: isFinished ?? this.isFinished,
51 | ride: ride ?? this.ride,
52 | fellowTraveler: fellowTraveler ?? this.fellowTraveler,
53 | randPoint: randPoint ?? this.randPoint,
54 | );
55 | }
56 |
57 |
58 | Map fromLatLngtoGeoFirePoint(LatLng latLng){
59 | return geo.point(latitude: latLng.latitude, longitude: latLng.longitude).data;
60 | }
61 |
62 | LatLng fromGeoPointToLatLng(GeoFirePoint point){
63 | return LatLng(point.latitude, point.longitude);
64 | }
65 |
66 | Map toMap() {
67 | return {
68 | 'phone' : phone,
69 | 'status': status?.toString(),
70 | 'isDriver': isDriver,
71 | 'isFinished' : isFinished,
72 | 'ride': ride?.toMap(),
73 | 'fellowTraveler': fellowTraveler?.toMap(),
74 | 'randPoint' : fromLatLngtoGeoFirePoint(randPoint),
75 | };
76 | }
77 |
78 | static UserRide fromMap(Map map) {
79 | if (map == null) return null;
80 |
81 | LatLng fromGeoPointToLatLng(Map map){
82 | GeoPoint point = map['geopoint'];
83 | Map result = {
84 | 'geopoint': map['geopoint'],
85 | 'geohash': map['geohash'],
86 | };
87 | return LatLng(point.latitude, point.longitude);
88 | }
89 |
90 | Status status;
91 | if(map['status'] == 'Status.pending'){
92 | status = Status.pending;
93 | }else if(map['status'] == 'Status.confirmed'){
94 | status = Status.confirmed;
95 | }else if(map['status'] == 'Status.completed'){
96 | status = Status.completed;
97 | }else if(map['status'] == 'Status.myRides'){
98 | status = Status.myRides;
99 | }else{
100 | status = null;
101 | }
102 |
103 | return UserRide(
104 | phone: map['phone'],
105 | status: status,
106 | isDriver: map['isDriver'],
107 | isFinished: map['isFinished'],
108 | ride: RidesModel.fromMap(map['ride']),
109 | fellowTraveler: UserModel.fromMap(map['fellowTraveler']),
110 | randPoint: fromGeoPointToLatLng(map['randPoint']),
111 | );
112 | }
113 |
114 | String toJson() => json.encode(toMap());
115 |
116 | static UserRide fromJson(String source) => fromMap(json.decode(source));
117 |
118 | @override
119 | String toString() {
120 | return 'UserRide(userPhone: $phone, status: $status, isDriver: $isDriver, ride: $ride, fellowTraveler: $fellowTraveler)';
121 | }
122 |
123 | @override
124 | bool operator ==(Object o) {
125 | if (identical(this, o)) return true;
126 |
127 | return o is UserRide &&
128 | o.phone == phone &&
129 | o.status == status &&
130 | o.isDriver == isDriver &&
131 | o.ride == ride &&
132 | o.fellowTraveler == fellowTraveler;
133 | }
134 |
135 | @override
136 | int get hashCode {
137 | return status.hashCode ^
138 | isDriver.hashCode ^
139 | ride.hashCode ^
140 | fellowTraveler.hashCode;
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/lib/screens/HomeScreen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'dart:async';
3 | import 'package:flutter/material.dart';
4 | import 'package:google_maps_flutter/google_maps_flutter.dart';
5 |
6 | class HomeScreen extends StatefulWidget {
7 | @override
8 | _HomeScreenState createState() => _HomeScreenState();
9 | }
10 |
11 | class _HomeScreenState extends State {
12 | Completer _controler = Completer();
13 |
14 | @override
15 | void initState(){
16 | super.initState();
17 | }
18 | double zoomVal = 0.5;
19 |
20 | @override
21 | Widget build(BuildContext context) {
22 | return Scaffold(
23 | body: Stack(
24 | children: [
25 | _googlemap(context),
26 | // _zoomminusfunction(),
27 | // _zoomplusfunction(),
28 | _buildContainer()
29 | ],
30 | ),
31 |
32 | );
33 | }
34 |
35 | Widget _buildContainer(){
36 | return Align(
37 | alignment: Alignment.bottomLeft,
38 | child: Container(
39 | margin: EdgeInsets.symmetric(vertical: 20.0),
40 | height: 150.0,
41 | child: ListView(
42 | scrollDirection: Axis.horizontal,
43 | children: [
44 | SizedBox(width: 10.0,),
45 | Padding(
46 | padding: const EdgeInsets.all(8.0),
47 | child: _boxes(),
48 | ),
49 | SizedBox(width: 10.0,),
50 | Padding(
51 | padding: const EdgeInsets.all(8.0),
52 | child: _boxes(),
53 | ),
54 | SizedBox(width: 10.0,),
55 | Padding(
56 | padding: const EdgeInsets.all(8.0),
57 | child: _boxes(),
58 | ),
59 | ],
60 | ),
61 | ),
62 | );
63 | }
64 |
65 | Widget _googlemap(BuildContext context){
66 | return Container(
67 | height: MediaQuery.of(context).size.height,
68 | width: MediaQuery.of(context).size.width,
69 | child: GoogleMap(
70 | mapType: MapType.normal,
71 | initialCameraPosition: CameraPosition(target: LatLng(37.9838, 23.7275), zoom: 12),
72 | onMapCreated: (GoogleMapController controler){
73 | _controler.complete(controler);
74 | },
75 | markers:{
76 | firstmarker, secondmarker
77 | },
78 | ),
79 | );
80 | }
81 |
82 | Future _gotoLocation(double lat, double long) async{
83 | final GoogleMapController controller = await _controler.future;
84 | controller.animateCamera(CameraUpdate.newCameraPosition(CameraPosition(target: LatLng(lat,long), zoom: 15, tilt: 50.0, bearing: 45.0)));
85 | }
86 | }
87 | Marker firstmarker = Marker(
88 | markerId: MarkerId("mark1"),
89 | position: LatLng(37.9833, 23.7272),
90 | infoWindow: InfoWindow(title: "arxhPeous"),
91 | icon: BitmapDescriptor.defaultMarkerWithHue(
92 | BitmapDescriptor.hueBlue,
93 | )
94 | );
95 |
96 | Marker secondmarker = Marker(
97 | markerId: MarkerId("mark2"),
98 | position: LatLng(37.9839, 23.7277),
99 | infoWindow: InfoWindow(title: "telosPeous"),
100 | icon: BitmapDescriptor.defaultMarkerWithHue(
101 | BitmapDescriptor.hueRed,
102 | )
103 | );
104 |
105 | Widget _boxes(){
106 | return GestureDetector(
107 | onTap: (){
108 | _gotoLocation(37.4324, 36.3432);
109 |
110 | },
111 | child: Container(
112 | child: new FittedBox(
113 | child: Material(
114 | color: Colors.white,
115 | elevation: 14.0,
116 | borderRadius: BorderRadius.circular(24.0),
117 | shadowColor: Color(0x802196F3),
118 | child: Row(
119 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
120 | children: [
121 | Container(
122 | width: 180,
123 | height: 200,
124 | child: Text(
125 | "sex",
126 | style: TextStyle(fontSize: 16.0),
127 | ),
128 | )
129 | ],
130 | ),
131 | ),
132 | ),
133 | ),
134 | );
135 | }
136 |
137 | void _gotoLocation(double d, double e) {
138 | }
--------------------------------------------------------------------------------
/lib/screens/LoginScreen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_app/screens/MyApp.dart';
3 | import 'package:flutter_app/screens/ProfileEditScreen.dart';
4 | import 'package:flutter_app/services/DataBase.dart';
5 | import 'package:google_fonts/google_fonts.dart';
6 |
7 | class LoginScreen extends StatelessWidget {
8 |
9 | final DataBase db;
10 |
11 | LoginScreen({@required this.db});
12 | String phoneInput;
13 | var darkBlueColor = Color.fromRGBO(26, 26, 48, 1.0);
14 | var lightBlueColor = Colors.blue;
15 | var lightGreyBackground = Color.fromRGBO(229, 229, 229, 1.0);
16 | @override
17 | Widget build(BuildContext context) {
18 | return MaterialApp(
19 | title: 'ShareMyRide',
20 | theme: ThemeData(
21 | scaffoldBackgroundColor: Colors.white,
22 | primaryColor: darkBlueColor,
23 | accentColor: lightBlueColor,
24 | //cardColor: lightGreyBackground,
25 | textTheme: TextTheme(
26 | body1: TextStyle(color: Color.fromRGBO(26, 26, 48, 1.0)),
27 | ),
28 | ),
29 | home: Scaffold(
30 | body: SafeArea(
31 | child: SafeArea(
32 | child: SingleChildScrollView(
33 | child: Column(
34 | crossAxisAlignment: CrossAxisAlignment.stretch,
35 | children: [
36 | Container(
37 | margin: EdgeInsets.symmetric(
38 | vertical: 25.0, horizontal: 10.0),
39 | child: Text(
40 | "Share My Ride",
41 | style: GoogleFonts.pacifico(
42 | textStyle: TextStyle(fontSize: 50.0)),
43 | textAlign: TextAlign.center,
44 | ),
45 | ),
46 | Container(
47 | padding: EdgeInsets.only(left: 30.0, top: 50.0),
48 | child: Text(
49 | "Phone",
50 | ),
51 | ),
52 | Container(
53 | padding:
54 | EdgeInsets.only(left: 20.0, right: 20.0, top: 10.0),
55 | child: TextField(
56 | obscureText: false,
57 | decoration: InputDecoration(
58 | border: OutlineInputBorder(),
59 | labelText: "Enter your phone number",
60 | ),
61 | onChanged: (value){
62 | print(' typing : $value');
63 | phoneInput = value;
64 | },
65 | ),
66 | ),
67 | Row(
68 | mainAxisAlignment: MainAxisAlignment.center,
69 | children: [
70 | Container(
71 | padding: EdgeInsets.only(top: 50.0, bottom: 80.0),
72 | child: RaisedButton(
73 | onPressed: () {
74 | },
75 | child: Text(
76 | "Next",
77 | style: TextStyle(color: Colors.white),
78 | ),
79 | shape: RoundedRectangleBorder(
80 | borderRadius: BorderRadius.circular(30.0)),
81 | color: darkBlueColor,
82 | ),
83 | )
84 | ],
85 | ),
86 | Column(
87 |
88 | children: [
89 | Container(
90 | height: 130.0,
91 | child: Image.asset('assets/images/login_icon.png', color: darkBlueColor,),
92 | )
93 | ],
94 | ),
95 | Row(
96 | mainAxisAlignment: MainAxisAlignment.end,
97 | children: [
98 | Padding(
99 | padding: const EdgeInsets.fromLTRB(0.0, 25.0, 8.0, 0.0),
100 | child: InkWell(
101 | onTap: () async{
102 | var result = await db.auth.getAnonUserSingInResult();
103 | if(result == null){
104 | print('problem with registationn :(((((((((((');
105 | }else{
106 | //If no problems with sing in go to profileScreen to enter data
107 | Navigator.push(
108 | context,
109 | MaterialPageRoute(
110 | builder: (context) => ProfileEditScreen(db: db, isNewUser: true),
111 | ),
112 | );
113 | }
114 | },
115 | child: Text(
116 | 'Sign in anonymously',
117 | style: TextStyle(
118 | color: darkBlueColor,
119 | fontSize: 15.0,
120 | ),
121 | ),
122 | ),
123 | ),
124 | ],
125 | ),
126 | ],
127 | ),
128 | ),
129 | ),
130 | ),
131 | ));
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/lib/screens/ReviewsScreen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_app/models/ReviewModel.dart';
3 | import 'package:flutter_app/models/UserModel.dart';
4 | import 'package:flutter_app/models/UserRide.dart';
5 | import 'package:flutter_app/screens/MyApp.dart';
6 | import 'package:flutter_app/services/DataBase.dart';
7 | import 'package:google_fonts/google_fonts.dart';
8 | import 'package:flutter_rating_bar/flutter_rating_bar.dart';
9 | import 'package:fluttertoast/fluttertoast.dart';
10 |
11 | class ReviewsScreen extends StatelessWidget {
12 | final DataBase db;
13 | final UserRide ride;
14 | final UserModel myUser;
15 | final UserModel reviewee;
16 |
17 | ReviewsScreen({this.db, this.ride, this.reviewee, this.myUser});
18 |
19 | final Color darkBlueColor = Color.fromRGBO(26, 26, 48, 1.0);
20 | final Color lightBlueColor = Colors.blue;
21 | final Color lightGreyBackground = Color.fromRGBO(229, 229, 229, 1.0);
22 | //
23 | //
24 | double revRating;
25 | String reviewText;
26 |
27 |
28 | // i need url,name, AND PHONE from card(reviewee)
29 | //and
30 | //myUserModel to create ReviewModel
31 |
32 |
33 | @override
34 | Widget build(BuildContext context) {
35 | return MaterialApp(
36 | title: 'ShareMyRide',
37 | theme: ThemeData(
38 | scaffoldBackgroundColor: Colors.white,
39 | primaryColor: darkBlueColor,
40 | accentColor: lightBlueColor,
41 | //cardColor: lightGreyBackground,
42 | textTheme: TextTheme(
43 | body1: TextStyle(
44 | color: darkBlueColor,
45 | fontFamily: 'fira',
46 | fontSize: 12.0,
47 | ),
48 | subhead: TextStyle(
49 | color: darkBlueColor,
50 | fontFamily: 'fira',
51 | fontSize: 16.0,
52 | ),
53 | ),
54 | ),
55 | home: Scaffold(
56 | body: SafeArea(
57 | child: SingleChildScrollView(
58 | child: Column(
59 | children: [
60 | Align(
61 | alignment: Alignment.topLeft,
62 | child: IconButton(
63 | icon: Icon(Icons.clear),
64 | onPressed: () {
65 | Navigator.push(
66 | context,
67 | MaterialPageRoute(
68 | builder: (context) => MyApp(db: db, selectedIndex: 1,)),
69 | );
70 | },
71 | ),
72 | ),
73 | Container(
74 | padding: EdgeInsets.only(top: 20.0),
75 | child: CircleAvatar(
76 | radius: 60.0,
77 | backgroundImage:
78 | new NetworkImage(reviewee.getUrlFromNameHash(genderInput: reviewee.gender))),
79 | ),
80 | Container(
81 | padding: EdgeInsets.only(top: 10.0),
82 | child: Text(
83 | reviewee.name,
84 | style: TextStyle(
85 | fontSize: 32.0,
86 | fontWeight: FontWeight.w600,
87 | ),
88 | ),
89 | ),
90 | RatingBar(
91 | initialRating: 3,
92 | minRating: 1,
93 | direction: Axis.horizontal,
94 | allowHalfRating: true,
95 | itemCount: 5,
96 | itemPadding:
97 | EdgeInsets.symmetric(horizontal: 4.0, vertical: 10.0),
98 | itemBuilder: (context, _) => Icon(
99 | Icons.star,
100 | color: Colors.amber,
101 | ),
102 | onRatingUpdate: (rating) {
103 | revRating = rating;
104 | print(rating);
105 | },
106 | ),
107 | Container(
108 | padding: EdgeInsets.only(left: 20.0, right: 20.0, top: 20.0),
109 | child: TextField(
110 | onChanged: (value) => reviewText = value,
111 | obscureText: false,
112 | //expands: true,
113 | maxLines: 5,
114 | decoration: InputDecoration(
115 | border: OutlineInputBorder(
116 | borderRadius: BorderRadius.circular(10.0)),
117 | labelText: "Enter your review here"),
118 | textAlignVertical: TextAlignVertical.top,
119 | ),
120 | ),
121 | Container(
122 | padding: EdgeInsets.only(top: 50.0, bottom: 100.0),
123 | child: RaisedButton(
124 | onPressed: () async{
125 |
126 | if(revRating == null && reviewText == null){
127 | Fluttertoast.showToast(
128 | msg: 'Please re-enter a valid rating and/or text',
129 | timeInSecForIosWeb: 1,
130 | );
131 | }else{
132 | var review = ReviewModel(
133 | phone: reviewee.phone,
134 | name: myUser.name,
135 | imageUrl: myUser.getUrlFromNameHash(genderInput: myUser.gender),
136 | reviewText: this.reviewText,
137 | rating: this.revRating,
138 | );
139 | db.createReviewModel(review);
140 | await db.updateRideToFinished(ride,reviewee);
141 | //TODO delete the Ride from the public list . It's over..
142 | //db.deleteRideModel(ride);
143 | //navigate to ridescreen
144 | Navigator.push(
145 | context,
146 | MaterialPageRoute(
147 | builder: (context) => MyApp(db: db,selectedIndex: 1),
148 | ),
149 | );
150 | }
151 |
152 |
153 | }, //onPressed
154 | child: Text(
155 | "SUBMIT",
156 | style: TextStyle(color: Colors.white),
157 | ),
158 | shape: RoundedRectangleBorder(
159 | borderRadius: BorderRadius.circular(30.0)),
160 | color: darkBlueColor,
161 | ),
162 | ),
163 | ],
164 | ),
165 | ),
166 | ),
167 | ),
168 | );
169 | }
170 | }
171 |
172 |
173 | /*
174 | showDialog(
175 | context: context,
176 | barrierDismissible: false, // user must tap button!
177 | builder: (BuildContext context) {
178 | return AlertDialog(
179 | title: Text('This is the title.'),
180 | content: SingleChildScrollView(
181 | child: ListBody(
182 | children: [
183 | Text('This is a test alert dialog box.'),
184 | ],
185 | ),
186 | ),
187 | actions: [
188 | FlatButton(
189 | child: Text('I get it.'),
190 | onPressed: () {
191 | Navigator.of(context).pop();
192 | },
193 | ),
194 | FlatButton(
195 | child: Text('Or not.'),
196 | onPressed: () {
197 | Navigator.of(context).pop();
198 | },
199 | ),
200 | ],
201 | );
202 | },
203 | );
204 | */
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | archive:
5 | dependency: transitive
6 | description:
7 | name: archive
8 | url: "https://pub.dartlang.org"
9 | source: hosted
10 | version: "2.0.11"
11 | args:
12 | dependency: transitive
13 | description:
14 | name: args
15 | url: "https://pub.dartlang.org"
16 | source: hosted
17 | version: "1.5.2"
18 | async:
19 | dependency: transitive
20 | description:
21 | name: async
22 | url: "https://pub.dartlang.org"
23 | source: hosted
24 | version: "2.4.0"
25 | boolean_selector:
26 | dependency: transitive
27 | description:
28 | name: boolean_selector
29 | url: "https://pub.dartlang.org"
30 | source: hosted
31 | version: "1.0.5"
32 | charcode:
33 | dependency: transitive
34 | description:
35 | name: charcode
36 | url: "https://pub.dartlang.org"
37 | source: hosted
38 | version: "1.1.2"
39 | cloud_firestore:
40 | dependency: "direct main"
41 | description:
42 | name: cloud_firestore
43 | url: "https://pub.dartlang.org"
44 | source: hosted
45 | version: "0.13.5"
46 | cloud_firestore_platform_interface:
47 | dependency: transitive
48 | description:
49 | name: cloud_firestore_platform_interface
50 | url: "https://pub.dartlang.org"
51 | source: hosted
52 | version: "1.1.0"
53 | cloud_firestore_web:
54 | dependency: transitive
55 | description:
56 | name: cloud_firestore_web
57 | url: "https://pub.dartlang.org"
58 | source: hosted
59 | version: "0.1.1+2"
60 | collection:
61 | dependency: transitive
62 | description:
63 | name: collection
64 | url: "https://pub.dartlang.org"
65 | source: hosted
66 | version: "1.14.11"
67 | convert:
68 | dependency: transitive
69 | description:
70 | name: convert
71 | url: "https://pub.dartlang.org"
72 | source: hosted
73 | version: "2.1.1"
74 | crypto:
75 | dependency: transitive
76 | description:
77 | name: crypto
78 | url: "https://pub.dartlang.org"
79 | source: hosted
80 | version: "2.1.3"
81 | cupertino_icons:
82 | dependency: "direct main"
83 | description:
84 | name: cupertino_icons
85 | url: "https://pub.dartlang.org"
86 | source: hosted
87 | version: "0.1.3"
88 | datetime_picker_formfield:
89 | dependency: "direct main"
90 | description:
91 | name: datetime_picker_formfield
92 | url: "https://pub.dartlang.org"
93 | source: hosted
94 | version: "1.0.0"
95 | equatable:
96 | dependency: transitive
97 | description:
98 | name: equatable
99 | url: "https://pub.dartlang.org"
100 | source: hosted
101 | version: "1.1.1"
102 | firebase:
103 | dependency: transitive
104 | description:
105 | name: firebase
106 | url: "https://pub.dartlang.org"
107 | source: hosted
108 | version: "7.3.0"
109 | firebase_auth:
110 | dependency: "direct main"
111 | description:
112 | name: firebase_auth
113 | url: "https://pub.dartlang.org"
114 | source: hosted
115 | version: "0.16.0"
116 | firebase_auth_platform_interface:
117 | dependency: transitive
118 | description:
119 | name: firebase_auth_platform_interface
120 | url: "https://pub.dartlang.org"
121 | source: hosted
122 | version: "1.1.7"
123 | firebase_auth_web:
124 | dependency: transitive
125 | description:
126 | name: firebase_auth_web
127 | url: "https://pub.dartlang.org"
128 | source: hosted
129 | version: "0.1.2"
130 | firebase_core:
131 | dependency: "direct main"
132 | description:
133 | name: firebase_core
134 | url: "https://pub.dartlang.org"
135 | source: hosted
136 | version: "0.4.4+3"
137 | firebase_core_platform_interface:
138 | dependency: transitive
139 | description:
140 | name: firebase_core_platform_interface
141 | url: "https://pub.dartlang.org"
142 | source: hosted
143 | version: "1.0.4"
144 | firebase_core_web:
145 | dependency: transitive
146 | description:
147 | name: firebase_core_web
148 | url: "https://pub.dartlang.org"
149 | source: hosted
150 | version: "0.1.1+2"
151 | flutter:
152 | dependency: "direct main"
153 | description: flutter
154 | source: sdk
155 | version: "0.0.0"
156 | flutter_launcher_icons:
157 | dependency: "direct dev"
158 | description:
159 | name: flutter_launcher_icons
160 | url: "https://pub.dartlang.org"
161 | source: hosted
162 | version: "0.7.5"
163 | flutter_plugin_android_lifecycle:
164 | dependency: transitive
165 | description:
166 | name: flutter_plugin_android_lifecycle
167 | url: "https://pub.dartlang.org"
168 | source: hosted
169 | version: "1.0.7"
170 | flutter_polyline_points:
171 | dependency: "direct main"
172 | description:
173 | name: flutter_polyline_points
174 | url: "https://pub.dartlang.org"
175 | source: hosted
176 | version: "0.1.0"
177 | flutter_rating_bar:
178 | dependency: "direct main"
179 | description:
180 | name: flutter_rating_bar
181 | url: "https://pub.dartlang.org"
182 | source: hosted
183 | version: "3.0.1+1"
184 | flutter_spinkit:
185 | dependency: "direct main"
186 | description:
187 | name: flutter_spinkit
188 | url: "https://pub.dartlang.org"
189 | source: hosted
190 | version: "4.1.2+1"
191 | flutter_test:
192 | dependency: "direct dev"
193 | description: flutter
194 | source: sdk
195 | version: "0.0.0"
196 | flutter_web_plugins:
197 | dependency: transitive
198 | description: flutter
199 | source: sdk
200 | version: "0.0.0"
201 | fluttertoast:
202 | dependency: "direct main"
203 | description:
204 | name: fluttertoast
205 | url: "https://pub.dartlang.org"
206 | source: hosted
207 | version: "4.0.1"
208 | geocoder:
209 | dependency: "direct main"
210 | description:
211 | name: geocoder
212 | url: "https://pub.dartlang.org"
213 | source: hosted
214 | version: "0.2.1"
215 | geoflutterfire:
216 | dependency: "direct main"
217 | description:
218 | name: geoflutterfire
219 | url: "https://pub.dartlang.org"
220 | source: hosted
221 | version: "2.1.0"
222 | geolocator:
223 | dependency: "direct main"
224 | description:
225 | name: geolocator
226 | url: "https://pub.dartlang.org"
227 | source: hosted
228 | version: "5.3.1"
229 | google_api_availability:
230 | dependency: transitive
231 | description:
232 | name: google_api_availability
233 | url: "https://pub.dartlang.org"
234 | source: hosted
235 | version: "2.0.4"
236 | google_fonts:
237 | dependency: "direct main"
238 | description:
239 | name: google_fonts
240 | url: "https://pub.dartlang.org"
241 | source: hosted
242 | version: "1.0.0"
243 | google_maps_flutter:
244 | dependency: "direct main"
245 | description:
246 | name: google_maps_flutter
247 | url: "https://pub.dartlang.org"
248 | source: hosted
249 | version: "0.5.26+4"
250 | http:
251 | dependency: transitive
252 | description:
253 | name: http
254 | url: "https://pub.dartlang.org"
255 | source: hosted
256 | version: "0.12.1"
257 | http_parser:
258 | dependency: transitive
259 | description:
260 | name: http_parser
261 | url: "https://pub.dartlang.org"
262 | source: hosted
263 | version: "3.1.4"
264 | image:
265 | dependency: transitive
266 | description:
267 | name: image
268 | url: "https://pub.dartlang.org"
269 | source: hosted
270 | version: "2.1.4"
271 | intl:
272 | dependency: transitive
273 | description:
274 | name: intl
275 | url: "https://pub.dartlang.org"
276 | source: hosted
277 | version: "0.16.1"
278 | js:
279 | dependency: transitive
280 | description:
281 | name: js
282 | url: "https://pub.dartlang.org"
283 | source: hosted
284 | version: "0.6.1+1"
285 | location_permissions:
286 | dependency: transitive
287 | description:
288 | name: location_permissions
289 | url: "https://pub.dartlang.org"
290 | source: hosted
291 | version: "2.0.5"
292 | matcher:
293 | dependency: transitive
294 | description:
295 | name: matcher
296 | url: "https://pub.dartlang.org"
297 | source: hosted
298 | version: "0.12.6"
299 | meta:
300 | dependency: transitive
301 | description:
302 | name: meta
303 | url: "https://pub.dartlang.org"
304 | source: hosted
305 | version: "1.1.8"
306 | path:
307 | dependency: transitive
308 | description:
309 | name: path
310 | url: "https://pub.dartlang.org"
311 | source: hosted
312 | version: "1.6.4"
313 | path_provider:
314 | dependency: transitive
315 | description:
316 | name: path_provider
317 | url: "https://pub.dartlang.org"
318 | source: hosted
319 | version: "1.6.7"
320 | path_provider_macos:
321 | dependency: transitive
322 | description:
323 | name: path_provider_macos
324 | url: "https://pub.dartlang.org"
325 | source: hosted
326 | version: "0.0.4+1"
327 | path_provider_platform_interface:
328 | dependency: transitive
329 | description:
330 | name: path_provider_platform_interface
331 | url: "https://pub.dartlang.org"
332 | source: hosted
333 | version: "1.0.1"
334 | pedantic:
335 | dependency: transitive
336 | description:
337 | name: pedantic
338 | url: "https://pub.dartlang.org"
339 | source: hosted
340 | version: "1.8.0+1"
341 | petitparser:
342 | dependency: transitive
343 | description:
344 | name: petitparser
345 | url: "https://pub.dartlang.org"
346 | source: hosted
347 | version: "2.4.0"
348 | platform:
349 | dependency: transitive
350 | description:
351 | name: platform
352 | url: "https://pub.dartlang.org"
353 | source: hosted
354 | version: "2.2.1"
355 | plugin_platform_interface:
356 | dependency: transitive
357 | description:
358 | name: plugin_platform_interface
359 | url: "https://pub.dartlang.org"
360 | source: hosted
361 | version: "1.0.2"
362 | quiver:
363 | dependency: transitive
364 | description:
365 | name: quiver
366 | url: "https://pub.dartlang.org"
367 | source: hosted
368 | version: "2.0.5"
369 | rxdart:
370 | dependency: transitive
371 | description:
372 | name: rxdart
373 | url: "https://pub.dartlang.org"
374 | source: hosted
375 | version: "0.23.1"
376 | search_map_place:
377 | dependency: "direct main"
378 | description:
379 | name: search_map_place
380 | url: "https://pub.dartlang.org"
381 | source: hosted
382 | version: "0.3.0"
383 | sky_engine:
384 | dependency: transitive
385 | description: flutter
386 | source: sdk
387 | version: "0.0.99"
388 | source_span:
389 | dependency: transitive
390 | description:
391 | name: source_span
392 | url: "https://pub.dartlang.org"
393 | source: hosted
394 | version: "1.5.5"
395 | stack_trace:
396 | dependency: transitive
397 | description:
398 | name: stack_trace
399 | url: "https://pub.dartlang.org"
400 | source: hosted
401 | version: "1.9.3"
402 | stream_channel:
403 | dependency: transitive
404 | description:
405 | name: stream_channel
406 | url: "https://pub.dartlang.org"
407 | source: hosted
408 | version: "2.0.0"
409 | string_scanner:
410 | dependency: transitive
411 | description:
412 | name: string_scanner
413 | url: "https://pub.dartlang.org"
414 | source: hosted
415 | version: "1.0.5"
416 | term_glyph:
417 | dependency: transitive
418 | description:
419 | name: term_glyph
420 | url: "https://pub.dartlang.org"
421 | source: hosted
422 | version: "1.1.0"
423 | test_api:
424 | dependency: transitive
425 | description:
426 | name: test_api
427 | url: "https://pub.dartlang.org"
428 | source: hosted
429 | version: "0.2.11"
430 | typed_data:
431 | dependency: transitive
432 | description:
433 | name: typed_data
434 | url: "https://pub.dartlang.org"
435 | source: hosted
436 | version: "1.1.6"
437 | vector_math:
438 | dependency: transitive
439 | description:
440 | name: vector_math
441 | url: "https://pub.dartlang.org"
442 | source: hosted
443 | version: "2.0.8"
444 | xml:
445 | dependency: transitive
446 | description:
447 | name: xml
448 | url: "https://pub.dartlang.org"
449 | source: hosted
450 | version: "3.5.0"
451 | yaml:
452 | dependency: transitive
453 | description:
454 | name: yaml
455 | url: "https://pub.dartlang.org"
456 | source: hosted
457 | version: "2.2.1"
458 | sdks:
459 | dart: ">=2.7.0 <3.0.0"
460 | flutter: ">=1.12.13+hotfix.6 <2.0.0"
461 |
--------------------------------------------------------------------------------
/lib/screens/ProfileScreen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_app/services/DataBase.dart';
3 | import 'package:google_fonts/google_fonts.dart';
4 | import 'package:flutter_app/models/ReviewModel.dart';
5 | import 'package:flutter_app/models/UserModel.dart';
6 | import 'package:flutter_app/screens/ProfileEditScreen.dart';
7 | import 'package:flutter_app/widgets/ReviewCard.dart';
8 |
9 | class ProfileScreen extends StatelessWidget {
10 |
11 |
12 | final DataBase db;
13 |
14 | ProfileScreen({
15 | @required this.db,
16 | });
17 |
18 | Future futureUser ;
19 | Future> futureReviews ;
20 | //List reviewWidgetList = [];
21 |
22 | var darkBlueColor = Color.fromRGBO(26, 26, 48, 1.0);
23 | var lightBlueColor = Colors.blue;
24 | var lightGreyBackground = Color.fromRGBO(229, 229, 229, 1.0);
25 |
26 | List reviewCardsWidgetsFromList(List reviews){
27 | List reviewWidgetList = [];
28 | if (reviews.isEmpty || reviews == null) {
29 | reviewWidgetList.add(
30 | Text('You have no reviews yet'),
31 | );
32 | } else {
33 | for (var item in reviews) {
34 | reviewWidgetList.add(ReviewCard(reviewModel: item));
35 | }
36 | }
37 | return reviewWidgetList;
38 | }
39 |
40 |
41 |
42 | double getRatingAverage(List reviewsList){
43 |
44 | if(reviewsList.isEmpty){
45 | return 0.0;
46 | }else{
47 | double sum = 0;
48 | for (var item in reviewsList) {
49 | var currentRating = item.rating;
50 | sum = sum + currentRating;
51 | }
52 | return sum/reviewsList.length;
53 | }
54 | }
55 |
56 | void getDataFromDb(){
57 | futureUser = db.getCurrentUserModel();
58 | futureReviews = db.getCurrentUserReviews();
59 | }
60 |
61 | void printReviewList() async{
62 | List reviews = await db.getCurrentUserReviews();
63 | print('!!!!REVIEWS IN DB: $reviews');
64 | }
65 | @override
66 | Widget build(BuildContext context) {
67 | printReviewList();
68 | getDataFromDb();
69 | UserModel initialUser = UserModel(
70 | name:'waiting...',
71 | gender: null,
72 | phone: 'waiting...',
73 | email: 'waiting...',
74 | rating: 0.0,
75 | carInfo: 'waiting...',
76 | );
77 | UserModel errorUser = UserModel(
78 | name:'ERROR',
79 | gender: Gender.nonBinary,
80 | phone: 'ERROR',
81 | email: 'ERROR',
82 | rating: 0.0,
83 | carInfo: 'ERROR',
84 | );
85 |
86 | Widget userScreen(UserModel userModel, Future> futureReviews){
87 | //addReviewCards(reviews);
88 | return MaterialApp(
89 | title: 'ShareMyRide',
90 | theme: ThemeData(
91 | scaffoldBackgroundColor: Colors.white,
92 | primaryColor: darkBlueColor,
93 | accentColor: lightBlueColor,
94 | //cardColor: lightGreyBackground,
95 | textTheme: TextTheme(
96 | body1: TextStyle(
97 | color: darkBlueColor,
98 | fontFamily: 'fira',
99 | fontSize: 14.0,
100 | ),
101 | subhead: TextStyle(
102 | color: darkBlueColor,
103 | fontFamily: 'fira',
104 | fontSize: 16.0,
105 | ),
106 | ),
107 | ),
108 | home: Scaffold(
109 | body: SafeArea(
110 | child: SingleChildScrollView(
111 | child: Column(
112 | children: [
113 | Container(
114 | margin:
115 | EdgeInsets.symmetric(vertical: 25.0, horizontal: 10.0),
116 | child: Row(
117 | mainAxisAlignment: MainAxisAlignment.end,
118 | children: [
119 | IconButton(
120 | icon: Icon(Icons.edit),
121 | onPressed: () {
122 | Navigator.push(
123 | context,
124 | MaterialPageRoute(
125 | builder: (context) => ProfileEditScreen(db: this.db, isNewUser: false,)),
126 | );
127 | }),
128 | ],
129 | ),
130 | ),
131 | CircleAvatar(
132 | radius: 60.0,
133 | backgroundImage: new NetworkImage(
134 | userModel.getUrlFromNameHash(genderInput: userModel.gender),
135 | ),
136 | ),
137 | Padding(
138 | padding: const EdgeInsets.symmetric(vertical: 10.0,horizontal: 0.0),
139 | child: Text(
140 | userModel.name,
141 | style: TextStyle(
142 | fontSize: 32.0,
143 | fontWeight: FontWeight.w600,
144 | ),
145 | ),
146 | ),
147 | Row(
148 | mainAxisAlignment: MainAxisAlignment.center,
149 | children: [
150 | Container(
151 | padding: EdgeInsets.only(right: 5.0),
152 | child: Text(
153 | 'My Rating:',
154 | style: GoogleFonts.oswald(
155 | textStyle: TextStyle(
156 | fontSize: 15.0,
157 | )),
158 | ),
159 | ),
160 | Container(
161 | padding: EdgeInsets.only(left: 5.0),
162 | child: Row(
163 | mainAxisSize: MainAxisSize.min,
164 | children: [
165 | FutureBuilder>(
166 | future: futureReviews,
167 | initialData: [],
168 | builder:(BuildContext context, AsyncSnapshot> snapshot) {
169 | if(snapshot.hasData){
170 | print('We have rating!!!');
171 | return Text(
172 | getRatingAverage(snapshot.data).toString().substring(0,3),
173 | style: GoogleFonts.oswald(
174 | textStyle: TextStyle(
175 | fontSize: 15.0,
176 | )),
177 | );
178 | }else if(snapshot.hasError){
179 | print('error');
180 | return Text(
181 | 'error',
182 | style: GoogleFonts.oswald(
183 | textStyle: TextStyle(
184 | fontSize: 15.0,
185 | )),
186 | );
187 | }else{
188 | //waiting...
189 | print('waiting for rating');
190 | return Column(
191 | children: [
192 | Center(
193 | child: SizedBox(
194 | child: CircularProgressIndicator(),
195 | width: 50,
196 | height: 50,
197 | ),
198 | ),
199 | ],
200 | );
201 | }
202 |
203 | }
204 | ),
205 | Icon(
206 | Icons.star,
207 | size: 15.0,
208 | ),
209 | ],
210 | ),
211 | ),
212 | ],
213 | ),
214 | Row(
215 | children: [
216 | Container(
217 | padding: EdgeInsets.fromLTRB(15.0, 15.0, 0.0, 0.0),
218 | child: Text(
219 | 'Personal Info',
220 | style:TextStyle(
221 | fontSize: 22.0,
222 | fontWeight: FontWeight.w600,
223 | ),
224 | ),
225 | ),
226 | ],
227 | ),
228 | Card(
229 | margin: EdgeInsets.symmetric(vertical: 5.0, horizontal: 15.0),
230 | child: ListTile(
231 | leading: Icon(Icons.phone),
232 | title: Text(userModel.phone.substring(0,10)),
233 | ),
234 | ),
235 | Card(
236 | margin: EdgeInsets.symmetric(vertical: 5.0, horizontal: 15.0),
237 | child: ListTile(
238 | leading: Icon(Icons.email),
239 | title: Text(userModel.email),
240 | ),
241 | ),
242 | Row(
243 | children: [
244 | Container(
245 | padding: EdgeInsets.fromLTRB(15.0, 25.0, 0.0, 0.0),
246 | child: Text(
247 | 'Car Info',
248 | style:TextStyle(
249 | fontSize: 22.0,
250 | fontWeight: FontWeight.w600,
251 | ),
252 | ),
253 | ),
254 | ],
255 | ),
256 | Card(
257 | margin: EdgeInsets.symmetric(vertical: 5.0, horizontal: 15.0),
258 | child: ListTile(
259 | leading: Icon(Icons.directions_car),
260 | title: Text(userModel.carInfo),
261 | ),
262 | ),
263 | Row(
264 | children: [
265 | Container(
266 | padding: EdgeInsets.fromLTRB(15.0, 25.0, 0.0, 0.0),
267 | child: Text(
268 | 'Reviews',
269 | style:TextStyle(
270 | fontSize: 22.0,
271 | fontWeight: FontWeight.w600,
272 | ),
273 | ),
274 | ),
275 | ],
276 | ),
277 | FutureBuilder>(
278 | future: futureReviews,
279 | builder: (BuildContext context, AsyncSnapshot> snapshot){
280 | if(snapshot.hasData){
281 | print('We have reviews!!!');
282 | return Column(
283 | children: reviewCardsWidgetsFromList(snapshot.data),
284 | );
285 | }else if(snapshot.hasError){
286 | print('error in review list');
287 | print('error data: ${snapshot.data}');
288 | return Column(
289 | children: reviewCardsWidgetsFromList([]),
290 | );
291 | }else{
292 | //waiting...
293 | print('waiting reviews');
294 | return Column(
295 | children: [
296 | Center(
297 | child: SizedBox(
298 | child: CircularProgressIndicator(),
299 | width: 50,
300 | height: 50,
301 | ),
302 | ),
303 | ],
304 | );
305 | }
306 | },
307 | ),
308 | ],
309 | ),
310 | ),
311 | ),
312 | ),
313 | );
314 | }
315 |
316 |
317 | return FutureBuilder(
318 | //TODO add second future with wait
319 | //futureReviews
320 | future: futureUser,
321 | initialData: initialUser,
322 | builder: (BuildContext context, AsyncSnapshot snapshot){
323 | if(snapshot.hasData){
324 | print('we have profile data!!!');
325 | return userScreen(snapshot.data, this.futureReviews);
326 | }else if(snapshot.hasError){
327 | print('error');
328 | return userScreen(errorUser,this.futureReviews);
329 | }else{
330 | //waiting...
331 | print('waiting');
332 | return Center(
333 | child: SizedBox(
334 | child: CircularProgressIndicator(),
335 | width: 100,
336 | height: 100,
337 | ),
338 | );
339 | }
340 |
341 | }
342 | );
343 |
344 | }
345 | }
346 |
--------------------------------------------------------------------------------
/lib/screens/ProfileEditScreen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_app/models/RidesModel.dart';
3 | import 'package:flutter_app/models/UserModel.dart';
4 | import 'package:flutter_app/models/UserRide.dart';
5 | import 'package:flutter_app/screens/AuthScreen.dart';
6 | import 'package:flutter_app/screens/MyApp.dart';
7 | import 'package:flutter_app/screens/ProfileScreen.dart';
8 | import 'package:flutter_app/services/DataBase.dart';
9 | import 'package:fluttertoast/fluttertoast.dart';
10 | import 'package:google_fonts/google_fonts.dart';
11 | import 'package:flutter_app/services/fakeDB.dart';
12 | import 'package:google_maps_flutter/google_maps_flutter.dart';
13 |
14 |
15 | class ProfileEditScreen extends StatefulWidget {
16 | //Checks if the User is a new User so that close and check buttons have different behaviour
17 | final bool isNewUser;
18 | final DataBase db;
19 | ProfileEditScreen({this.db, this.isNewUser});
20 |
21 | @override
22 | _ProfileEditScreenState createState() => _ProfileEditScreenState();
23 | }
24 |
25 | class _ProfileEditScreenState extends State {
26 | Gender gender = Gender.male;
27 |
28 | String name;
29 |
30 | String phone;
31 |
32 | String email;
33 |
34 | String carInfo;
35 |
36 | bool hasGenderChanged = false;
37 |
38 | var darkBlueColor = Color.fromRGBO(26, 26, 48, 1.0);
39 |
40 | var lightBlueColor = Colors.blue;
41 |
42 | var lightGreyBackground = Color.fromRGBO(229, 229, 229, 1.0);
43 |
44 |
45 | void deleteAccount() async {
46 | var user = await widget.db.auth.getCurrentFireBaseUser();
47 | print("deleting user...");
48 | await user.delete();
49 | Navigator.push(
50 | context,
51 | MaterialPageRoute(
52 | builder: (context) => AuthScreen(),
53 | ),
54 | );
55 | }
56 |
57 |
58 |
59 | void iconsClickEventHandler(BuildContext context, String iconName) async {
60 | if (iconName == 'check') {
61 | //If the user is new navigate to Home Screen.If she
62 | //just edits her profile navigate to profile screen
63 | if (widget.isNewUser) {
64 | // check if phone, name,etc are null-> show a toast
65 | if(this.name==null || this.email==null || this.carInfo==null){
66 | Fluttertoast.showToast(
67 | msg: "Εrror, please fill all the fields",
68 | timeInSecForIosWeb: 1,
69 | );
70 | }else{
71 | //This is where a new UserModel get created
72 | //Identifier should be phone so i pass UUID to phone number
73 | UserModel user = UserModel(
74 | name: this.name,
75 | gender: this.gender,
76 | phone: await widget.db.auth.getCurrentFireBaseUserID(),
77 | email: this.email,
78 | carInfo: this.carInfo,
79 | rating: 0.0,
80 | );
81 | var result = widget.db.createUserModel(user);
82 | if(result == null){
83 | print('Problem with creation.');
84 | }else{
85 | //if no problem proceed to MyApp->HomeScreen
86 | Navigator.push(
87 | context,
88 | MaterialPageRoute(
89 | builder: (context) => MyApp(db: widget.db,selectedIndex: 0),
90 | ),
91 | );
92 | }
93 |
94 | }
95 |
96 | } else {
97 | //existing user. Update data
98 | //check if a specific field is updated in order to
99 | // correctly update the database
100 | Map updatedFields = new Map();
101 | if(this.hasGenderChanged){
102 | updatedFields['gender'] = this.gender.toString();
103 | print("DEBUG the gender has changed");
104 | }
105 | if (this.name != null){
106 | updatedFields['name'] = this.name;
107 | print("DEBUG name changed");
108 | }
109 | if(this.email != null){
110 | updatedFields['email'] = this.email;
111 | print("DEBUG phone changed");
112 | }
113 | if(this.carInfo != null){
114 | updatedFields['carInfo'] = this.carInfo;
115 | print("DEBUG carinfo changed");
116 | }
117 |
118 | //print(updatedFields);
119 | await widget.db.updateCurrentUserModel(updatedFields);
120 |
121 | Navigator.push(
122 | context,
123 | MaterialPageRoute(
124 | builder: (context) => MyApp(db: widget.db,selectedIndex: 2),
125 | ),
126 | );
127 | }
128 | }
129 | //
130 | //
131 | if (iconName == 'close') {
132 | if (widget.isNewUser) {
133 | //DELETE user if he hasn't entered anything and
134 | deleteAccount();
135 | Navigator.push(
136 | context,
137 | MaterialPageRoute(
138 | builder: (context) => AuthScreen(),
139 | ),
140 | );
141 | } else {
142 | Navigator.push(
143 | context,
144 | MaterialPageRoute(
145 | builder: (context) => MyApp(db: widget.db,selectedIndex: 2),
146 | ),
147 | );
148 | }
149 | }
150 | }
151 |
152 | @override
153 | Widget build(BuildContext context) {
154 | return MaterialApp(
155 | title: 'ShareMyRide',
156 | theme: ThemeData(
157 | scaffoldBackgroundColor: Colors.white,
158 | primaryColor: darkBlueColor,
159 | accentColor: lightBlueColor,
160 | //cardColor: lightGreyBackground,
161 | textTheme: TextTheme(
162 | body1: TextStyle(color: Color.fromRGBO(26, 26, 48, 1.0)),
163 | ),
164 | ),
165 | home: Scaffold(
166 | body: SafeArea(
167 | child: SingleChildScrollView(
168 | child: Column(
169 | children: [
170 | Container(
171 | margin:
172 | EdgeInsets.symmetric(vertical: 25.0, horizontal: 10.0),
173 | child: Row(
174 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
175 | children: [
176 | IconButton(
177 | icon: Icon(Icons.close),
178 | onPressed: () =>
179 | iconsClickEventHandler(context, 'close')),
180 | IconButton(
181 | icon: Icon(Icons.check),
182 | onPressed: () =>
183 | iconsClickEventHandler(context, 'check'))
184 | ],
185 | ),
186 | ),
187 | CircleAvatar(
188 | radius: 60.0,
189 | backgroundImage:
190 | new NetworkImage('https://via.placeholder.com/150')),
191 | Container(
192 | padding: EdgeInsets.all(10.0),
193 | child: TextField(
194 | onChanged: (value) => name = value,
195 | obscureText: false,
196 | decoration: InputDecoration(
197 | border: OutlineInputBorder(), labelText: "Enter name"),
198 | ),
199 | ),
200 | Row(
201 | mainAxisAlignment: MainAxisAlignment.center,
202 | children: [],
203 | ),
204 | Row(
205 | children: [
206 | Container(
207 | padding: EdgeInsets.fromLTRB(15.0, 25.0, 0.0, 0.0),
208 | child: Text(
209 | 'Personal Info',
210 | style: GoogleFonts.oswald(
211 | textStyle: TextStyle(
212 | fontSize: 20.0,
213 | )),
214 | ),
215 | ),
216 | ],
217 | ),
218 | Card(
219 | margin: EdgeInsets.symmetric(vertical: 5.0, horizontal: 15.0),
220 | child: TextField(
221 | onChanged: (value) => phone = value,
222 | obscureText: false,
223 | decoration: InputDecoration(
224 | border: OutlineInputBorder(),
225 | icon: Icon(Icons.phone),
226 | labelText: "Enter phone number"),
227 | ),
228 | ),
229 | Card(
230 | margin: EdgeInsets.symmetric(vertical: 5.0, horizontal: 15.0),
231 | child: TextField(
232 | onChanged: (value) => email = value,
233 | obscureText: false,
234 | decoration: InputDecoration(
235 | border: OutlineInputBorder(),
236 | icon: Icon(Icons.email),
237 | labelText: "Enter email"),
238 | ),
239 | ),
240 | Card(
241 | margin:
242 | EdgeInsets.symmetric(vertical: 5.0, horizontal: 15.0),
243 | child: Row(
244 | children: [
245 | Expanded(
246 | flex:1,
247 | child: Icon(
248 | Icons.wc,
249 | color: Colors.black54,
250 | ),
251 | ),
252 | Expanded(
253 | flex: 4,
254 | child: Align(
255 | alignment: Alignment.center,
256 | child: Text(
257 | 'Enter your gender',
258 | style: TextStyle(
259 | color: Colors.black54,
260 | fontSize: 16.0,
261 | ),
262 | ),
263 | ),
264 | ),
265 | Expanded(
266 | flex: 5,
267 | child: DropdownButton(
268 | isExpanded: true,
269 | value: gender,
270 | icon: Icon(Icons.arrow_downward),
271 | iconSize: 24,
272 | elevation: 16,
273 | style: TextStyle(color: Colors.deepPurple),
274 | onChanged: (Gender newValue) {
275 | this.hasGenderChanged = true;
276 | setState(() {
277 | gender = newValue;
278 | });
279 | },
280 | items: [Gender.male, Gender.female, Gender.nonBinary]
281 | .map>((Gender value) {
282 | return DropdownMenuItem(
283 | value: value,
284 | child: Text(value.toString().substring(7)),
285 | );
286 | }).toList(),
287 | ),
288 | ),
289 | ],
290 | )),
291 | Row(
292 | children: [
293 | Container(
294 | padding: EdgeInsets.fromLTRB(15.0, 25.0, 0.0, 0.0),
295 | child: Text(
296 | 'Car Info',
297 | style: GoogleFonts.oswald(
298 | textStyle: TextStyle(
299 | fontSize: 20.0,
300 | )),
301 | ),
302 | ),
303 | ],
304 | ),
305 | Card(
306 | margin: EdgeInsets.symmetric(vertical: 5.0, horizontal: 15.0),
307 | child: TextField(
308 | onChanged: (value) => carInfo = value,
309 | obscureText: false,
310 | decoration: InputDecoration(
311 | border: OutlineInputBorder(),
312 | icon: Icon(Icons.directions_car),
313 | labelText: "Enter car information"),
314 | ),
315 | ),
316 | Container(
317 | child: RaisedButton(
318 | onPressed: () async{
319 | //delete user
320 | print("deleting user...");
321 | await deleteAccount();
322 | Navigator.push(
323 | context,
324 | MaterialPageRoute(
325 | builder: (context) => AuthScreen(),
326 | ),
327 | );
328 | },
329 | child: Text(
330 | "DELETE USER",
331 | style: TextStyle(
332 | color: Colors.white,
333 | fontSize: 15.0,
334 | ),
335 | ),
336 | shape: RoundedRectangleBorder(
337 | borderRadius: BorderRadius.circular(30.0)),
338 | color: Colors.red[700],
339 | ),
340 | ),
341 | ],
342 | ),
343 | ),
344 | ),
345 | ),
346 | );
347 | }
348 | }
349 |
--------------------------------------------------------------------------------
/lib/services/DataBase.dart:
--------------------------------------------------------------------------------
1 | //import 'dart:html';
2 |
3 | import 'package:cloud_firestore/cloud_firestore.dart';
4 | import 'package:flutter_app/models/ReviewModel.dart';
5 | import 'package:flutter_app/models/RidesModel.dart';
6 | import 'package:flutter_app/models/SearchModel.dart';
7 | import 'package:flutter_app/models/UserModel.dart';
8 | import 'package:flutter_app/models/UserRide.dart';
9 | import 'package:flutter_app/services/Authenticator.dart';
10 | import 'package:geoflutterfire/geoflutterfire.dart';
11 | import 'package:google_maps_flutter/google_maps_flutter.dart';
12 |
13 |
14 | class Paths{
15 | static String UserModel = 'UserModel';
16 | static String ReviewModel = 'ReviewModel';
17 | static String UserRide = 'UserRide';
18 | static String RidesModel = 'RidesModel';
19 | }
20 |
21 | class DataBase {
22 | final Authenticator auth;
23 | final db = Firestore.instance;
24 | final Geoflutterfire geo = Geoflutterfire();
25 | DataBase({this.auth});
26 |
27 |
28 | Future getCurrAnonUserPhone() async {
29 | String currentUserId = await auth.getCurrentFireBaseUserID();
30 |
31 | }
32 |
33 | Future getCurrentUserModel() async{
34 | UserModel generatedUserModel;
35 | var userCollection = db.collection(Paths.UserModel);
36 | String currentUser = await auth.getCurrentFireBaseUserID();
37 | var query = userCollection.where('phone',isEqualTo: currentUser);
38 | var remoteDoc = await query.getDocuments();
39 | List results = [];
40 | for(var i in remoteDoc.documents){
41 | //Map result = i.data;
42 | results.add(i.data);
43 | }
44 | generatedUserModel = UserModel.fromMap(results[0]);
45 | if(currentUser == 'NoUserYet'){
46 | generatedUserModel = UserModel(
47 | name: 'No User Yet :(',
48 | gender: Gender.nonBinary,
49 | phone: '0000000',
50 | email: 'error no email',
51 | carInfo: 'no car mate :/',
52 | rating: 0.0,
53 | );
54 | }
55 | return generatedUserModel;
56 | }
57 |
58 | Future>getCurrentUserReviews() async{
59 | List generetedList = [];
60 | String currentUser = await auth.getCurrentFireBaseUserID();
61 | var reviewCollection = db.collection(Paths.ReviewModel);
62 | var query = reviewCollection.where('phone',isEqualTo: currentUser);
63 | var remoteDoc = await query.getDocuments();
64 | List results = [];
65 | for(var i in remoteDoc.documents){
66 | //Map result = i.data;
67 | ReviewModel review = ReviewModel.fromMap(i.data);
68 | generetedList.add(review);
69 | }
70 | return generetedList;
71 | }
72 |
73 | Future> getCurrentUserRides() async {
74 | List generatedList = [];
75 | String currentUser = await auth.getCurrentFireBaseUserID();
76 | var userRideCollection = db.collection(Paths.UserRide);
77 | var query = userRideCollection.where('phone', isEqualTo: currentUser);
78 | var remoteDoc = await query.getDocuments();
79 | for(var i in remoteDoc.documents){
80 | UserRide userRide = UserRide.fromMap(i.data);
81 | generatedList.add(userRide);
82 | }
83 | return generatedList;
84 | }
85 |
86 |
87 | Future> getRidesModelsFromSearch(SearchModel searchModel) async{
88 | String currentUser = await auth.getCurrentFireBaseUserID();
89 |
90 | //Destination set when searching for ride
91 | GeoFirePoint toGeoFirePoint = GeoFirePoint(searchModel.toCords.latitude, searchModel.toCords.longitude);
92 | List generatedList = [];
93 | var ridesModelCollection = db.collection(Paths.RidesModel);
94 | //var query = ridesModelCollection.where('dateTime', isGreaterThanOrEqualTo: searchModel.searchDate.millisecondsSinceEpoch);
95 | var geoRef = geo.collection(collectionRef: ridesModelCollection)
96 | .within(center: toGeoFirePoint, radius: 3, field: 'toLatLng', strictMode: true);
97 |
98 | var listFromStream = await geoRef.first;
99 | for(var i in listFromStream){
100 |
101 | //exclude rides created by current user
102 | //exclude past rides
103 | if(i.data['driver']['phone'] != currentUser && i.data['dateTime'] >= searchModel.searchDate.millisecondsSinceEpoch){
104 | RidesModel ride = RidesModel.fromMap(i.data);
105 | generatedList.add(ride);
106 | }
107 |
108 | }
109 |
110 | return generatedList;
111 | }
112 |
113 |
114 | Future> getUserReviewsFromPhone(String phone) async{
115 | List generetedList = [];
116 | var reviewCollection = db.collection(Paths.ReviewModel);
117 | var query = reviewCollection.where('phone',isEqualTo: phone);
118 | var remoteDoc = await query.getDocuments();
119 | List results = [];
120 | for(var i in remoteDoc.documents){
121 | //Map result = i.data;
122 | ReviewModel review = ReviewModel.fromMap(i.data);
123 | generetedList.add(review);
124 | }
125 | return generetedList;
126 | }
127 |
128 |
129 | //should return DocRef??
130 | Future createUserModel(UserModel user) async{
131 | DocumentReference docRef;
132 | var userCollection = db.collection(Paths.UserModel);
133 | try {
134 | docRef = await userCollection.add(user.toMap());
135 | }catch (e) {
136 | docRef = null;
137 | }
138 | return docRef;
139 | }
140 |
141 |
142 | Future createUserRide(UserRide userRide) async {
143 | DocumentReference docRef;
144 | var userRideCollection = db.collection(Paths.UserRide);
145 | try{
146 | docRef = await userRideCollection.add(userRide.toMap());
147 | }catch (e){
148 | docRef = null;
149 | }
150 | return docRef;
151 | }
152 |
153 |
154 | Future createReviewModel(ReviewModel review) async{
155 | DocumentReference docRef;
156 | var reviewModelCollection = db.collection(Paths.ReviewModel);
157 | try{
158 | docRef = await reviewModelCollection.add(review.toMap());
159 | }catch (e){
160 | docRef = null;
161 | }
162 | return docRef;
163 | }
164 |
165 | Future createRidesModel(RidesModel ride) async{
166 | DocumentReference docRef;
167 | var reviewModelCollection = db.collection(Paths.RidesModel);
168 | try{
169 | docRef = await reviewModelCollection.add(ride.toMap());
170 | }catch (e){
171 | docRef = null;
172 | }
173 | return docRef;
174 | }
175 |
176 | Future updateRideToConfirmed(UserRide ride) async{
177 | String phone = ride.phone;
178 | String fellowTravellerPhone = ride.fellowTraveler.phone;
179 |
180 | //search for this user
181 | //update status of this user
182 | var userRideCollection = db.collection(Paths.UserRide);
183 | var query = userRideCollection
184 | .where('phone',isEqualTo: ride.phone)
185 | .where('status', isEqualTo: "Status.pending")
186 | .where('ride.fromText',isEqualTo: ride.ride.fromText)
187 | .where('ride.toText',isEqualTo: ride.ride.toText);
188 | var remoteDoc = await query.getDocuments();
189 | for(var i in remoteDoc.documents){
190 | try {
191 | i.reference.updateData({'status' : 'Status.confirmed'});
192 | } on Exception catch (e) {
193 | print('couldnt change from pending to confirmed');
194 | }
195 | }
196 |
197 | //search for fellowTraveller
198 | //update status of fellowTraveller
199 | var query2 = userRideCollection
200 | .where('phone',isEqualTo: fellowTravellerPhone)
201 | .where('status', isEqualTo: "Status.pending")
202 | .where('ride.fromText',isEqualTo: ride.ride.fromText)
203 | .where('ride.toText',isEqualTo: ride.ride.toText);
204 | var remoteDoc2 = await query2.getDocuments();
205 | for(var i in remoteDoc2.documents){
206 | try {
207 | i.reference.updateData({'status' : 'Status.confirmed'});
208 | } on Exception catch (e) {
209 | print('couldnt change from pending to confirmed');
210 | }
211 |
212 | }
213 | }
214 |
215 | Future updateRideToCompleted(UserRide ride) async{
216 | String phone = ride.phone;
217 | String fellowTravellerPhone = ride.fellowTraveler.phone;
218 |
219 | //search for this user
220 | //update status of this user
221 | var userRideCollection = db.collection(Paths.UserRide);
222 | var query = userRideCollection
223 | .where('phone',isEqualTo: ride.phone)
224 | .where('status', isEqualTo: "Status.confirmed")
225 | .where('ride.fromText',isEqualTo: ride.ride.fromText)
226 | .where('ride.toText',isEqualTo: ride.ride.toText);
227 | var remoteDoc = await query.getDocuments();
228 | for(var i in remoteDoc.documents){
229 | try {
230 | i.reference.updateData({'status' : 'Status.completed'});
231 | } on Exception catch (e) {
232 | print('couldnt change from confirmed to completed');
233 | }
234 | }
235 |
236 | //search for fellowTraveller
237 | //update status of fellowTraveller
238 | var query2 = userRideCollection
239 | .where('phone',isEqualTo: fellowTravellerPhone)
240 | .where('status', isEqualTo: "Status.confirmed")
241 | .where('ride.fromText',isEqualTo: ride.ride.fromText)
242 | .where('ride.toText',isEqualTo: ride.ride.toText);
243 | var remoteDoc2 = await query2.getDocuments();
244 | for(var i in remoteDoc2.documents){
245 | try {
246 | i.reference.updateData({'status' : 'Status.completed'});
247 | } on Exception catch (e) {
248 | print('couldnt change from confirmed to completed');
249 | }
250 | }
251 | }
252 |
253 | Future updateRideToFinished(UserRide ride, UserModel reviewee) async{
254 | //search for this user
255 | //update status of this user
256 | var userRideCollection = db.collection(Paths.UserRide);
257 | var query = userRideCollection
258 | .where('phone',isEqualTo: ride.phone)
259 | .where('status', isEqualTo: "Status.completed")
260 | .where('ride.fromText',isEqualTo: ride.ride.fromText)
261 | .where('ride.toText',isEqualTo: ride.ride.toText);
262 | var remoteDoc = await query.getDocuments();
263 | for(var i in remoteDoc.documents){
264 | try {
265 | i.reference.updateData({'isFinished' : true});
266 | } on Exception catch (e) {
267 | print('couldnt change from completed to finished ');
268 | }
269 | }
270 | }
271 |
272 | Future declineRide(UserRide ride) async{
273 | String phone = ride.phone;
274 | String fellowTravellerPhone = ride.fellowTraveler.phone;
275 |
276 |
277 | //decline for this user
278 | var userRideCollection = db.collection(Paths.UserRide);
279 | var query = userRideCollection
280 | .where('phone',isEqualTo: ride.phone)
281 | .where('status', isEqualTo: "Status.pending")
282 | .where('ride.fromText',isEqualTo: ride.ride.fromText)
283 | .where('ride.toText',isEqualTo: ride.ride.toText);
284 | var remoteDoc = await query.getDocuments();
285 | for(var i in remoteDoc.documents){
286 | try {
287 | i.reference.delete();
288 | } on Exception catch (e) {
289 | print('couldnt decline');
290 | }
291 | }
292 |
293 |
294 | //decline for fellowtraveler
295 | var query2 = userRideCollection
296 | .where('phone',isEqualTo: fellowTravellerPhone)
297 | .where('status', isEqualTo: "Status.pending")
298 | .where('ride.fromText',isEqualTo: ride.ride.fromText)
299 | .where('ride.toText',isEqualTo: ride.ride.toText);
300 | var remoteDoc2 = await query2.getDocuments();
301 | for(var i in remoteDoc2.documents){
302 | try {
303 | i.reference.delete();
304 | } on Exception catch (e) {
305 | print('couldnt decline');
306 | }
307 | }
308 | }
309 |
310 | Future cancelRide(UserRide ride) async{
311 | String phone = ride.phone;
312 | String fellowTravellerPhone = ride.fellowTraveler.phone;
313 |
314 |
315 | //cancel for this user
316 | var userRideCollection = db.collection(Paths.UserRide);
317 | var query = userRideCollection
318 | .where('phone',isEqualTo: ride.phone)
319 | .where('status', isEqualTo: "Status.confirmed")
320 | .where('ride.fromText',isEqualTo: ride.ride.fromText)
321 | .where('ride.toText',isEqualTo: ride.ride.toText);
322 | var remoteDoc = await query.getDocuments();
323 | for(var i in remoteDoc.documents){
324 | try {
325 | i.reference.delete();
326 | } on Exception catch (e) {
327 | print('couldnt cancel');
328 | }
329 | }
330 |
331 |
332 | //cancel for fellowtraveler
333 | var query2 = userRideCollection
334 | .where('phone',isEqualTo: fellowTravellerPhone)
335 | .where('status', isEqualTo: "Status.confirmed")
336 | .where('ride.fromText',isEqualTo: ride.ride.fromText)
337 | .where('ride.toText',isEqualTo: ride.ride.toText);
338 | var remoteDoc2 = await query2.getDocuments();
339 | for(var i in remoteDoc2.documents){
340 | try {
341 | i.reference.delete();
342 | } on Exception catch (e) {
343 | print('couldnt cancel');
344 | }
345 | }
346 | }
347 |
348 |
349 | Future updateCurrentUserModel(Map userData) async{
350 | var userCollection = db.collection(Paths.UserModel);
351 | String currentUser = await auth.getCurrentFireBaseUserID();
352 | var query = userCollection.where('phone',isEqualTo: currentUser);
353 | var remoteDoc = await query.getDocuments();
354 | for(var i in remoteDoc.documents){
355 | //Map result = i.data;
356 | try {
357 | i.reference.updateData(userData);
358 | } on Exception catch (e) {
359 | print('couldnt change from completed to finished ');
360 | }
361 | }
362 | }
363 |
364 | void updateCurrentUserRating(List reviewsList) async{
365 |
366 | double getRatingAverage(List reviewsList){
367 |
368 | if(reviewsList.isEmpty){
369 | return 0.0;
370 | }else{
371 | double sum = 0;
372 | for (var item in reviewsList) {
373 | var currentRating = item.rating;
374 | sum = sum + currentRating;
375 | }
376 | return sum/reviewsList.length;
377 | }
378 | }
379 | var averageRating=getRatingAverage(reviewsList);
380 | var userCollection = db.collection(Paths.UserModel);
381 | String currentUser = await auth.getCurrentFireBaseUserID();
382 | var query = userCollection.where('phone',isEqualTo: currentUser);
383 | var remoteDoc = await query.getDocuments();
384 | List results = [];
385 | for(var i in remoteDoc.documents){
386 | //Map result = i.data;
387 | //results.add(i.data);
388 | try{
389 | i.reference.updateData({'rating' : averageRating});
390 | } on Exception catch (e) {
391 | print('couldnt update rating on DB : $e');
392 | }
393 |
394 | }
395 | }
396 |
397 |
398 |
399 |
400 | Future deleteRideModelFromUserRide(UserRide userRide) async{
401 | var ridesCollection = db.collection(Paths.RidesModel);
402 | var query = ridesCollection
403 | .where('driver.phone',isEqualTo: userRide.phone)
404 | .where('fromText',isEqualTo: userRide.ride.fromText)
405 | .where('toText',isEqualTo: userRide.ride.toText);
406 | var remoteDoc = await query.getDocuments();
407 | for(var i in remoteDoc.documents){
408 | i.reference.delete();
409 | }
410 | }
411 |
412 | Future deleteUserRide(UserRide userRide) async{
413 | var userRidesCollection = db.collection(Paths.UserRide);
414 | var query = userRidesCollection
415 | .where('phone',isEqualTo: userRide.phone)
416 | .where('status', isEqualTo: "Status.myRides")
417 | .where('ride.fromText',isEqualTo: userRide.ride.fromText)
418 | .where('ride.toText',isEqualTo: userRide.ride.toText);
419 | var remoteDoc = await query.getDocuments();
420 | for(var i in remoteDoc.documents){
421 | i.reference.delete();
422 | }
423 |
424 | }
425 |
426 |
427 | Future> getAllUserModelsFromDb() async{
428 | var remoteDocuments = await db.collection('UserModel').getDocuments();
429 | List