├── 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-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.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 │ └── xcshareddata │ │ ├── WorkspaceSettings.xcsettings │ │ └── IDEWorkspaceChecks.plist ├── Runner.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ └── IDEWorkspaceChecks.plist │ ├── xcshareddata │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ └── project.pbxproj └── .gitignore ├── lib ├── models │ └── user.dart ├── shared │ ├── constants.dart │ └── loading.dart ├── pages │ ├── tourist_authenticate_page.dart │ ├── success_guide_signup_page.dart │ ├── selectusertype_page.dart │ ├── change_name_page.dart │ ├── booknow_page.dart │ ├── change_password_page.dart │ ├── settings_page.dart │ ├── tourist_signin_page.dart │ ├── tourist_home_page.dart │ ├── tourist_signup_page.dart │ ├── guide_signup_page.dart │ └── guide_details_page.dart ├── main.dart ├── helper │ └── helper_functions.dart └── services │ ├── database_service.dart │ └── auth_service.dart ├── snapshots ├── snapshot1.jpeg ├── snapshot2.jpeg ├── snapshot3.jpeg ├── snapshot4.jpeg └── snapshot5.png ├── android ├── gradle.properties ├── .gitignore ├── app │ ├── 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 │ │ │ │ ├── drawable │ │ │ │ │ └── launch_background.xml │ │ │ │ └── values │ │ │ │ │ └── styles.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── TouristAssist │ │ │ │ │ └── MainActivity.kt │ │ │ └── AndroidManifest.xml │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ └── profile │ │ │ └── AndroidManifest.xml │ └── build.gradle ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── build.gradle └── settings.gradle ├── .metadata ├── .gitignore ├── README.md ├── LICENSE ├── test └── widget_test.dart ├── pubspec.yaml └── 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" 2 | -------------------------------------------------------------------------------- /lib/models/user.dart: -------------------------------------------------------------------------------- 1 | class User { 2 | final String uid; 3 | 4 | User({this.uid}); 5 | } -------------------------------------------------------------------------------- /snapshots/snapshot1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedgulabkhan/TouristAssist/HEAD/snapshots/snapshot1.jpeg -------------------------------------------------------------------------------- /snapshots/snapshot2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedgulabkhan/TouristAssist/HEAD/snapshots/snapshot2.jpeg -------------------------------------------------------------------------------- /snapshots/snapshot3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedgulabkhan/TouristAssist/HEAD/snapshots/snapshot3.jpeg -------------------------------------------------------------------------------- /snapshots/snapshot4.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedgulabkhan/TouristAssist/HEAD/snapshots/snapshot4.jpeg -------------------------------------------------------------------------------- /snapshots/snapshot5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedgulabkhan/TouristAssist/HEAD/snapshots/snapshot5.png -------------------------------------------------------------------------------- /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/ahmedgulabkhan/TouristAssist/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/ahmedgulabkhan/TouristAssist/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/ahmedgulabkhan/TouristAssist/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/ahmedgulabkhan/TouristAssist/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/ahmedgulabkhan/TouristAssist/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedgulabkhan/TouristAssist/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedgulabkhan/TouristAssist/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/ahmedgulabkhan/TouristAssist/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/ahmedgulabkhan/TouristAssist/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/ahmedgulabkhan/TouristAssist/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/ahmedgulabkhan/TouristAssist/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/ahmedgulabkhan/TouristAssist/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/ahmedgulabkhan/TouristAssist/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/ahmedgulabkhan/TouristAssist/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/ahmedgulabkhan/TouristAssist/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedgulabkhan/TouristAssist/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/ahmedgulabkhan/TouristAssist/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedgulabkhan/TouristAssist/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/ahmedgulabkhan/TouristAssist/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/ahmedgulabkhan/TouristAssist/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedgulabkhan/TouristAssist/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/ahmedgulabkhan/TouristAssist/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/ahmedgulabkhan/TouristAssist/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/example/TouristAssist/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.TouristAssist 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.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: 1ad9baa8b99a2897c20f9e6e54d3b9b359ade314 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /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. -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /lib/shared/constants.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | const textInputDecoration = InputDecoration( 4 | enabledBorder: OutlineInputBorder( 5 | borderSide: BorderSide(color: Colors.white, width: 2.0) 6 | ), 7 | focusedBorder: OutlineInputBorder( 8 | borderSide: BorderSide(color: Colors.lightBlueAccent, width: 2.0) 9 | ), 10 | errorBorder: OutlineInputBorder( 11 | borderSide: BorderSide(color: Colors.red, width: 2.0) 12 | ), 13 | focusedErrorBorder: OutlineInputBorder( 14 | borderSide: BorderSide(color: Colors.red, width: 2.0) 15 | ), 16 | ); -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /lib/shared/loading.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | 4 | class Loading extends StatelessWidget { 5 | @override 6 | Widget build(BuildContext context) { 7 | return Container( 8 | color: Colors.black87, 9 | child: Center( 10 | child: SpinKitRing( 11 | color: Theme.of(context).primaryColor, 12 | size: 50.0, 13 | ) 14 | ), 15 | ); 16 | } 17 | } 18 | 19 | class LoadingAlt extends StatelessWidget { 20 | @override 21 | Widget build(BuildContext context) { 22 | return Container( 23 | color: Colors.white, 24 | child: Center( 25 | child: SpinKitRing( 26 | color: Theme.of(context).primaryColor, 27 | size: 50.0, 28 | ) 29 | ), 30 | ); 31 | } 32 | } -------------------------------------------------------------------------------- /lib/pages/tourist_authenticate_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:TouristAssist/pages/tourist_signin_page.dart'; 2 | import 'package:TouristAssist/pages/tourist_signup_page.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class TouristAuthenticatePage extends StatefulWidget { 6 | 7 | @override 8 | _TouristAuthenticatePageState createState() => _TouristAuthenticatePageState(); 9 | } 10 | 11 | class _TouristAuthenticatePageState extends State { 12 | 13 | bool showSignIn = false; 14 | void toggleView() { 15 | setState(() { 16 | showSignIn = !showSignIn; 17 | }); 18 | } 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | if(showSignIn) { 23 | return TouristSignInPage(toggleView: toggleView); 24 | } 25 | else { 26 | return TouristSignUpPage(toggleView: toggleView); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | android/app/google-services.json 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Exceptions to above rules. 44 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 45 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TouristAssist 2 | ## About 3 | TouristAssist is an app made using Flutter and Firebase which provides a better tourism experience. Tourists can sign up and book local guides based on the current city they are present in. It shows a map of their current location and all the guides present in that area. 4 | 5 | ## Snapshots of the application 6 | 7 | ![Screenshots](/snapshots/snapshot5.png) 8 | 9 | ## Configuration Steps 10 | 1. Cloning the repository: 11 | 12 | ``` 13 | $ git clone https://github.com/ahmedgulabkhan/TouristAssist.git 14 | ``` 15 | 16 | 2. Open the project and install dependencies (using terminal): 17 | 18 | ``` 19 | $ cd TouristAssist 20 | $ flutter pub get 21 | ``` 22 | This installs all the required dependencies like cloud_firestore, firebase_auth, shared_preferences, flutter_map, geolocator, etc... 23 | 24 | 3. Make an android project on your firebase account, follow the mentioned steps and you're good to go. 25 | 26 | 4. Now run the app on your connected device (using terminal): 27 | 28 | `$ flutter run` 29 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Ahmed Gulab Khan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /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_test/flutter_test.dart'; 10 | 11 | import 'package:TouristAssist/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Flutter Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | include ':app' 6 | 7 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 8 | def properties = new Properties() 9 | 10 | assert localPropertiesFile.exists() 11 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 12 | 13 | def flutterSdkPath = properties.getProperty("flutter.sdk") 14 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 15 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 16 | 17 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 18 | 19 | def plugins = new Properties() 20 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 21 | if (pluginsFile.exists()) { 22 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 23 | } 24 | 25 | plugins.each { name, path -> 26 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 27 | include ":$name" 28 | project(":$name").projectDir = pluginDirectory 29 | } -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:TouristAssist/helper/helper_functions.dart'; 2 | import 'package:TouristAssist/pages/selectusertype_page.dart'; 3 | import 'package:TouristAssist/pages/tourist_home_page.dart'; 4 | import 'package:flutter/material.dart'; 5 | 6 | void main() { 7 | runApp(MyApp()); 8 | } 9 | 10 | class MyApp extends StatefulWidget { 11 | @override 12 | _MyAppState createState() => _MyAppState(); 13 | } 14 | 15 | class _MyAppState extends State { 16 | 17 | bool _isLoggedIn = false; 18 | bool _isLoading = true; 19 | 20 | @override 21 | void initState() { 22 | super.initState(); 23 | _getIsLoggedIn(); 24 | } 25 | 26 | _getIsLoggedIn() async { 27 | await HelperFunctions.getUserLoggedInSharedPreference().then((result) { 28 | if(result != null) { 29 | setState(() { 30 | _isLoggedIn = result; 31 | }); 32 | } 33 | }); 34 | 35 | setState(() { 36 | _isLoading = false; 37 | }); 38 | } 39 | 40 | 41 | @override 42 | Widget build(BuildContext context) { 43 | return _isLoading ? Container(color: Colors.black87) : MaterialApp( 44 | title: 'TouristAssist', 45 | debugShowCheckedModeBanner: false, 46 | theme: ThemeData( 47 | primaryColor: Colors.blue, 48 | backgroundColor: Colors.black87, 49 | ), 50 | // home: SelectUserTypePage() 51 | home: _isLoggedIn ? TouristHomePage() : SelectUserTypePage() 52 | ); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lib/pages/success_guide_signup_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class SuccessGuideSignUpPage extends StatelessWidget { 4 | 5 | @override 6 | Widget build(BuildContext context) { 7 | return Scaffold( 8 | extendBodyBehindAppBar: true, 9 | appBar: AppBar( 10 | backgroundColor: Colors.transparent, 11 | elevation: 0.0, 12 | iconTheme: IconThemeData( 13 | color: Colors.white 14 | ), 15 | // leading: , 16 | ), 17 | body: Container( 18 | width: MediaQuery.of(context).size.width, 19 | color: Theme.of(context).backgroundColor, 20 | padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 30.0), 21 | child: Column( 22 | mainAxisAlignment: MainAxisAlignment.center, 23 | crossAxisAlignment: CrossAxisAlignment.center, 24 | children: [ 25 | CircleAvatar( 26 | radius: 65.0, 27 | backgroundColor: Colors.green, 28 | child: Icon(Icons.done, color: Colors.white, size: 80.0), 29 | ), 30 | // Icon(Icons.done_outline, color: Colors.green, size: 100.0), 31 | SizedBox(height: 30.0), 32 | Text('You have successfully been registered as a guide. You will now recieve calls when a tourist wants to hire you', style: TextStyle(fontSize: 18.0, color: Colors.white)) 33 | ] 34 | ), 35 | ), 36 | ); 37 | } 38 | } -------------------------------------------------------------------------------- /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 | TouristAssist 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 | -------------------------------------------------------------------------------- /lib/pages/selectusertype_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:TouristAssist/pages/guide_signup_page.dart'; 2 | import 'package:TouristAssist/pages/tourist_authenticate_page.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class SelectUserTypePage extends StatelessWidget { 6 | @override 7 | Widget build(BuildContext context) { 8 | return Scaffold( 9 | body: Container( 10 | width: MediaQuery.of(context).size.width, 11 | height: MediaQuery.of(context).size.height, 12 | color: Theme.of(context).backgroundColor, 13 | child: Column( 14 | mainAxisAlignment: MainAxisAlignment.center, 15 | children: [ 16 | Text('TouristAssist 🚀', style: TextStyle(color: Colors.white, fontSize: 40.0, fontWeight: FontWeight.bold)), 17 | 18 | SizedBox(height: 50.0), 19 | 20 | FlatButton( 21 | onPressed: () { 22 | Navigator.of(context).push(MaterialPageRoute(builder: (context) => TouristAuthenticatePage())); 23 | }, 24 | child: Text('Get started as a Tourist', style: TextStyle(color: Colors.white, fontSize: 18.0)), 25 | color: Colors.lightBlueAccent, 26 | padding: EdgeInsets.symmetric(horizontal: 30.0, vertical: 20.0), 27 | ), 28 | 29 | SizedBox(height: 20.0), 30 | 31 | FlatButton( 32 | onPressed: () { 33 | Navigator.of(context).push(MaterialPageRoute(builder: (context) => GuideSignUpPage())); 34 | }, 35 | child: Text('Get started as a Guide', style: TextStyle(color: Colors.white, fontSize: 18.0)), 36 | color: Colors.lightBlueAccent, 37 | padding: EdgeInsets.symmetric(horizontal: 30.0, vertical: 20.0), 38 | ), 39 | ], 40 | ), 41 | ), 42 | ); 43 | } 44 | } -------------------------------------------------------------------------------- /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: 'com.google.gms.google-services' 26 | apply plugin: 'kotlin-android' 27 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 28 | 29 | android { 30 | compileSdkVersion 28 31 | 32 | sourceSets { 33 | main.java.srcDirs += 'src/main/kotlin' 34 | } 35 | 36 | lintOptions { 37 | disable 'InvalidPackage' 38 | } 39 | 40 | defaultConfig { 41 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 42 | applicationId "com.example.TouristAssist" 43 | minSdkVersion 21 44 | targetSdkVersion 28 45 | versionCode flutterVersionCode.toInteger() 46 | versionName flutterVersionName 47 | } 48 | 49 | buildTypes { 50 | release { 51 | // TODO: Add your own signing config for the release build. 52 | // Signing with the debug keys for now, so `flutter run --release` works. 53 | signingConfig signingConfigs.debug 54 | } 55 | } 56 | } 57 | 58 | flutter { 59 | source '../..' 60 | } 61 | 62 | dependencies { 63 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 64 | } 65 | -------------------------------------------------------------------------------- /lib/helper/helper_functions.dart: -------------------------------------------------------------------------------- 1 | import 'package:shared_preferences/shared_preferences.dart'; 2 | 3 | class HelperFunctions{ 4 | 5 | static String sharedPreferenceUserLoggedInKey = "ISLOGGEDIN"; 6 | static String sharedPreferenceUserNameKey = "USERNAMEKEY"; 7 | static String sharedPreferenceUserEmailKey = "USEREMAILKEY"; 8 | static String sharedPreferenceUserPasswordKey = "USERPASSWORDKEY"; 9 | 10 | // saving data to sharedpreferences 11 | static Future saveUserLoggedInSharedPreference(bool isUserLoggedIn) async{ 12 | 13 | SharedPreferences preferences = await SharedPreferences.getInstance(); 14 | return await preferences.setBool(sharedPreferenceUserLoggedInKey, isUserLoggedIn); 15 | } 16 | 17 | static Future saveUserNameSharedPreference(String userName) async{ 18 | SharedPreferences preferences = await SharedPreferences.getInstance(); 19 | return await preferences.setString(sharedPreferenceUserNameKey, userName); 20 | } 21 | 22 | static Future saveUserEmailSharedPreference(String userEmail) async{ 23 | SharedPreferences preferences = await SharedPreferences.getInstance(); 24 | return await preferences.setString(sharedPreferenceUserEmailKey, userEmail); 25 | } 26 | 27 | static Future saveUserPasswordSharedPreference(String userPassword) async{ 28 | SharedPreferences preferences = await SharedPreferences.getInstance(); 29 | return await preferences.setString(sharedPreferenceUserPasswordKey, userPassword); 30 | } 31 | 32 | 33 | 34 | // fetching data from sharedpreferences 35 | static Future getUserLoggedInSharedPreference() async{ 36 | SharedPreferences preferences = await SharedPreferences.getInstance(); 37 | return preferences.getBool(sharedPreferenceUserLoggedInKey); 38 | } 39 | 40 | static Future getUserNameSharedPreference() async{ 41 | SharedPreferences preferences = await SharedPreferences.getInstance(); 42 | return preferences.getString(sharedPreferenceUserNameKey); 43 | } 44 | 45 | static Future getUserEmailSharedPreference() async{ 46 | SharedPreferences preferences = await SharedPreferences.getInstance(); 47 | return preferences.getString(sharedPreferenceUserEmailKey); 48 | } 49 | 50 | static Future getUserPasswordSharedPreference() async{ 51 | SharedPreferences preferences = await SharedPreferences.getInstance(); 52 | return preferences.getString(sharedPreferenceUserPasswordKey); 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /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/pages/change_name_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:TouristAssist/helper/helper_functions.dart'; 2 | import 'package:TouristAssist/pages/tourist_home_page.dart'; 3 | import 'package:TouristAssist/services/database_service.dart'; 4 | import 'package:TouristAssist/shared/constants.dart'; 5 | import 'package:TouristAssist/shared/loading.dart'; 6 | import 'package:flutter/material.dart'; 7 | 8 | class ChangeNamePage extends StatefulWidget { 9 | 10 | final String userUid; 11 | ChangeNamePage({ 12 | this.userUid 13 | }); 14 | 15 | @override 16 | _ChangeNamePageState createState() => _ChangeNamePageState(); 17 | } 18 | 19 | class _ChangeNamePageState extends State { 20 | 21 | bool _isLoading = false; 22 | final _formKey = GlobalKey(); 23 | TextEditingController _nameEditingController = new TextEditingController(); 24 | 25 | void _changeName(BuildContext context, String newName) async { 26 | if (_formKey.currentState.validate()) { 27 | setState(() { 28 | _isLoading = true; 29 | }); 30 | await DatabaseService(uid: widget.userUid).changeName(newName); 31 | await HelperFunctions.saveUserNameSharedPreference(newName); 32 | Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) => TouristHomePage()), (Route route) => false); 33 | } 34 | } 35 | 36 | @override 37 | Widget build(BuildContext context) { 38 | return _isLoading ? LoadingAlt() : Scaffold( 39 | appBar: AppBar( 40 | title: Text('Change name', style: TextStyle(color: Colors.white)), 41 | elevation: 0.0, 42 | ), 43 | body: Form( 44 | key: _formKey, 45 | child: Container( 46 | padding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 20.0), 47 | child: Column( 48 | children: [ 49 | TextFormField( 50 | style: TextStyle(color: Colors.black), 51 | controller: _nameEditingController, 52 | decoration: textInputDecoration.copyWith( 53 | hintText: 'Enter new name', 54 | hintStyle: TextStyle(color: Colors.grey), 55 | prefixIcon: Icon(Icons.person, color: Colors.black), 56 | ), 57 | validator: (val) => val.isEmpty ? 'This field cannot be blank' : null 58 | ), 59 | SizedBox(height: 10.0), 60 | FlatButton( 61 | color: Colors.green, 62 | onPressed: () { 63 | _changeName(context, _nameEditingController.text); 64 | }, 65 | child: Text('Change name', style: TextStyle(color: Colors.white)) 66 | ) 67 | ], 68 | ), 69 | ), 70 | ), 71 | ); 72 | } 73 | } -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 8 | 9 | 10 | 11 | 12 | 16 | 23 | 27 | 31 | 36 | 40 | 41 | 42 | 43 | 44 | 45 | 47 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /lib/pages/booknow_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:TouristAssist/pages/guide_details_page.dart'; 2 | import 'package:TouristAssist/shared/loading.dart'; 3 | import 'package:cloud_firestore/cloud_firestore.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:url_launcher/url_launcher.dart'; 6 | 7 | class BookNowPage extends StatelessWidget { 8 | 9 | final String currentUserCity; 10 | BookNowPage({ 11 | this.currentUserCity 12 | }); 13 | 14 | Future _getGuidesInfo() async { 15 | QuerySnapshot snapshot = await Firestore.instance.collection('guides').where('city', isEqualTo: currentUserCity).getDocuments(); 16 | 17 | return snapshot.documents; 18 | } 19 | 20 | Future _makePhoneCall(String url) async { 21 | if (await canLaunch(url)) { 22 | await launch(url); 23 | } else { 24 | throw 'Could not launch $url'; 25 | } 26 | } 27 | 28 | @override 29 | Widget build(BuildContext context) { 30 | return Scaffold( 31 | appBar: AppBar( 32 | backgroundColor: Theme.of(context).primaryColor, 33 | title: Text('Guides near you', style: TextStyle(color: Colors.white)), 34 | elevation: 0.0, 35 | iconTheme: IconThemeData( 36 | color: Colors.white, 37 | ) 38 | ), 39 | body: FutureBuilder( 40 | future: _getGuidesInfo(), 41 | builder: (BuildContext context, AsyncSnapshot snapshot) { 42 | if(snapshot.data == null) { 43 | return LoadingAlt(); 44 | } 45 | else { 46 | return ListView.builder( 47 | itemCount: snapshot.data.length, 48 | itemBuilder: (BuildContext context, int index) { 49 | return ListTile( 50 | leading: CircleAvatar( 51 | radius: 30.0, 52 | backgroundColor: Colors.blue, 53 | child: Text(snapshot.data[index]['fullName'].substring(0,1).toUpperCase(), style: TextStyle(color: Colors.white)), 54 | ), 55 | title: Text(snapshot.data[index]['fullName'], style: TextStyle(fontSize: 18.0, fontWeight: FontWeight.bold)), 56 | subtitle: Text('${snapshot.data[index]['rating']}⭐ (${snapshot.data[index]['votes'].length}) • Rs. ${snapshot.data[index]['costPerHour']}/hr'), 57 | trailing: FlatButton( 58 | color: Colors.blue, 59 | onPressed: () { 60 | _makePhoneCall('tel:${snapshot.data[index]['phoneNumber']}'); 61 | }, 62 | child: Text('Call now', style: TextStyle(color: Colors.white)) 63 | ), 64 | contentPadding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0), 65 | onTap: () { 66 | Navigator.of(context).push(MaterialPageRoute(builder: (context) => GuideDetailsPage(guideUid: snapshot.data[index]['uid']))); 67 | }, 68 | ); 69 | } 70 | ); 71 | } 72 | } 73 | ) 74 | ); 75 | } 76 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /lib/pages/change_password_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:TouristAssist/helper/helper_functions.dart'; 2 | import 'package:TouristAssist/pages/tourist_home_page.dart'; 3 | import 'package:TouristAssist/services/database_service.dart'; 4 | import 'package:TouristAssist/shared/constants.dart'; 5 | import 'package:TouristAssist/shared/loading.dart'; 6 | import 'package:firebase_auth/firebase_auth.dart'; 7 | import 'package:flutter/material.dart'; 8 | 9 | class ChangePasswordPage extends StatefulWidget { 10 | 11 | final String userUid; 12 | ChangePasswordPage({ 13 | this.userUid 14 | }); 15 | 16 | @override 17 | _ChangePasswordPageState createState() => _ChangePasswordPageState(); 18 | } 19 | 20 | class _ChangePasswordPageState extends State { 21 | 22 | bool _isLoading = false; 23 | final _formKey = GlobalKey(); 24 | TextEditingController _passwordEditingController = new TextEditingController(); 25 | 26 | void _changePassword(BuildContext context, String newPassword) async{ 27 | if (_formKey.currentState.validate()) { 28 | setState(() { 29 | _isLoading = true; 30 | }); 31 | FirebaseUser user = await FirebaseAuth.instance.currentUser(); 32 | 33 | user.updatePassword(newPassword).then((_){ 34 | print("Succesfull changed password"); 35 | }).catchError((error){ 36 | print("Password can't be changed" + error.toString()); 37 | }); 38 | 39 | await DatabaseService(uid: widget.userUid).changePassword(newPassword); 40 | await HelperFunctions.saveUserPasswordSharedPreference(newPassword); 41 | Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) => TouristHomePage()), (Route route) => false); 42 | } 43 | } 44 | 45 | @override 46 | Widget build(BuildContext context) { 47 | return _isLoading ? LoadingAlt() : Scaffold( 48 | appBar: AppBar( 49 | title: Text('Change password'), 50 | elevation: 0.0, 51 | ), 52 | body: Form( 53 | key: _formKey, 54 | child: Container( 55 | padding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 20.0), 56 | child: Column( 57 | children: [ 58 | TextFormField( 59 | style: TextStyle(color: Colors.black), 60 | controller: _passwordEditingController, 61 | decoration: textInputDecoration.copyWith( 62 | hintText: 'Enter new password', 63 | hintStyle: TextStyle(color: Colors.grey), 64 | prefixIcon: Icon(Icons.lock, color: Colors.black) 65 | ), 66 | validator: (val) => val.length < 6 ? 'Password not strong enough' : null, 67 | obscureText: true, 68 | ), 69 | SizedBox(height: 10.0), 70 | FlatButton( 71 | color: Colors.green, 72 | onPressed: () { 73 | _changePassword(context, _passwordEditingController.text); 74 | }, 75 | child: Text('Change password', style: TextStyle(color: Colors.white)) 76 | ) 77 | ], 78 | ), 79 | ), 80 | ), 81 | ); 82 | } 83 | } -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: TouristAssist 2 | description: A new Flutter project. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `pub publish`. This is preferred for private packages. 6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 7 | 8 | # The following defines the version and build number for your application. 9 | # A version number is three numbers separated by dots, like 1.2.43 10 | # followed by an optional build number separated by a +. 11 | # Both the version and the builder number may be overridden in flutter 12 | # build by specifying --build-name and --build-number, respectively. 13 | # In Android, build-name is used as versionName while build-number used as versionCode. 14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 16 | # Read more about iOS versioning at 17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 18 | version: 1.0.0+1 19 | 20 | environment: 21 | sdk: ">=2.7.0 <3.0.0" 22 | 23 | dependencies: 24 | flutter: 25 | sdk: flutter 26 | 27 | 28 | # The following adds the Cupertino Icons font to your application. 29 | # Use with the CupertinoIcons class for iOS style icons. 30 | cupertino_icons: ^0.1.3 31 | shared_preferences: ^0.5.7+2 32 | firebase_auth: ^0.16.1 33 | cloud_firestore: ^0.13.6 34 | flutter_spinkit: ^4.1.2+1 35 | flutter_map: ^0.9.0 36 | url_launcher: ^5.4.10 37 | geolocator: ^5.3.2+2 38 | 39 | dev_dependencies: 40 | flutter_test: 41 | sdk: flutter 42 | 43 | # For information on the generic Dart part of this file, see the 44 | # following page: https://dart.dev/tools/pub/pubspec 45 | 46 | # The following section is specific to Flutter. 47 | flutter: 48 | 49 | # The following line ensures that the Material Icons font is 50 | # included with your application, so that you can use the icons in 51 | # the material Icons class. 52 | uses-material-design: true 53 | 54 | # To add assets to your application, add an assets section, like this: 55 | # assets: 56 | # - images/a_dot_burr.jpeg 57 | # - images/a_dot_ham.jpeg 58 | 59 | # An image asset can refer to one or more resolution-specific "variants", see 60 | # https://flutter.dev/assets-and-images/#resolution-aware. 61 | 62 | # For details regarding adding assets from package dependencies, see 63 | # https://flutter.dev/assets-and-images/#from-packages 64 | 65 | # To add custom fonts to your application, add a fonts section here, 66 | # in this "flutter" section. Each entry in this list should have a 67 | # "family" key with the font family name, and a "fonts" key with a 68 | # list giving the asset and other descriptors for the font. For 69 | # example: 70 | # fonts: 71 | # - family: Schyler 72 | # fonts: 73 | # - asset: fonts/Schyler-Regular.ttf 74 | # - asset: fonts/Schyler-Italic.ttf 75 | # style: italic 76 | # - family: Trajan Pro 77 | # fonts: 78 | # - asset: fonts/TrajanPro.ttf 79 | # - asset: fonts/TrajanPro_Bold.ttf 80 | # weight: 700 81 | # 82 | # For details regarding fonts from package dependencies, 83 | # see https://flutter.dev/custom-fonts/#from-packages 84 | -------------------------------------------------------------------------------- /lib/services/database_service.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | 3 | class DatabaseService { 4 | 5 | final String uid; 6 | DatabaseService({ 7 | this.uid 8 | }); 9 | 10 | // Collection reference 11 | final CollectionReference touristCollection = Firestore.instance.collection('tourists'); 12 | final CollectionReference guideCollection = Firestore.instance.collection('guides'); 13 | 14 | // update tourist data 15 | Future updateTouristData(String fullName, String email, String password) async { 16 | return await touristCollection.document(uid).setData({ 17 | 'fullName': fullName, 18 | 'email': email, 19 | 'password': password, 20 | }); 21 | } 22 | 23 | // update guide data 24 | Future updateGuideData(String fullName, String email, String phoneNumber, String city, String costPerHour, String password, double latitude, double longitude) async { 25 | return await guideCollection.document(uid).setData({ 26 | 'uid': uid, 27 | 'fullName': fullName, 28 | 'email': email, 29 | 'phoneNumber': phoneNumber, 30 | 'password': password, 31 | 'city': city, 32 | 'costPerHour': costPerHour, 33 | 'rating': 0, 34 | 'votes': [], 35 | 'latitude': latitude, 36 | 'longitude': longitude 37 | }); 38 | } 39 | 40 | // get user data 41 | Future getTouristData(String email) async { 42 | QuerySnapshot snapshot = await touristCollection.where('email', isEqualTo: email).getDocuments(); 43 | // print(snapshot.documents[0].data); 44 | return snapshot; 45 | } 46 | 47 | // get guide data 48 | Future getGuideData(String uid) async { 49 | QuerySnapshot snapshot = await guideCollection.where('uid', isEqualTo: uid).getDocuments(); 50 | return snapshot.documents[0].data; 51 | } 52 | 53 | // is guide attempting to sign in as a tourist 54 | Future isGuideSigningIn(String email) async { 55 | QuerySnapshot snapshot = await guideCollection.where('email', isEqualTo: email).getDocuments(); 56 | if(snapshot.documents.length == 0) { 57 | return false; 58 | } 59 | else return true; 60 | } 61 | 62 | // is tourist attempting to sign in as a guide 63 | Future isTouristSigningIn(String email) async { 64 | QuerySnapshot snapshot = await touristCollection.where('email', isEqualTo: email).getDocuments(); 65 | if(snapshot.documents.length == 0) { 66 | return false; 67 | } 68 | else return true; 69 | } 70 | 71 | // submit rating 72 | submitRating(int starNum, String userUid) async { 73 | DocumentSnapshot guideDocSnapshot = await guideCollection.document(uid).get(); 74 | await guideCollection.document(uid).updateData({ 75 | 'rating': ((guideDocSnapshot.data['rating'] * guideDocSnapshot.data['votes'].length) + starNum) / (guideDocSnapshot.data['votes'].length + 1), 76 | 'votes': FieldValue.arrayUnion([userUid]) 77 | }); 78 | } 79 | 80 | // update name 81 | changeName(String newName) async { 82 | return await touristCollection.document(uid).updateData({ 83 | 'fullName': newName 84 | }); 85 | } 86 | 87 | // update name 88 | changePassword(String newPassword) async { 89 | return await touristCollection.document(uid).updateData({ 90 | 'password': newPassword 91 | }); 92 | } 93 | 94 | // delete user account 95 | deleteUser() async { 96 | return await touristCollection.document(uid).delete(); 97 | } 98 | } -------------------------------------------------------------------------------- /lib/services/auth_service.dart: -------------------------------------------------------------------------------- 1 | import 'package:TouristAssist/helper/helper_functions.dart'; 2 | import 'package:TouristAssist/models/user.dart'; 3 | import 'package:firebase_auth/firebase_auth.dart'; 4 | import 'database_service.dart'; 5 | 6 | class AuthService { 7 | final FirebaseAuth _auth = FirebaseAuth.instance; 8 | 9 | 10 | // create user object based on FirebaseUser 11 | User _userFromFirebaseUser(FirebaseUser user) { 12 | return (user != null) ? User(uid: user.uid) : null; 13 | } 14 | 15 | 16 | // sign in tourist with email and password 17 | Future signInTouristWithEmailAndPassword(String email, String password) async { 18 | bool isWrongLogin = await DatabaseService().isGuideSigningIn(email); 19 | if(isWrongLogin) { 20 | return null; 21 | } 22 | else { 23 | try { 24 | AuthResult result = await _auth.signInWithEmailAndPassword(email: email, password: password); 25 | FirebaseUser user = result.user; 26 | return _userFromFirebaseUser(user); 27 | } catch(e) { 28 | print(e.toString()); 29 | return null; 30 | } 31 | } 32 | } 33 | 34 | 35 | // register tourist with email and password 36 | Future registerTouristWithEmailAndPassword(String fullName, String email, String password) async { 37 | try { 38 | AuthResult result = await _auth.createUserWithEmailAndPassword(email: email, password: password); 39 | FirebaseUser user = result.user; 40 | 41 | // Create a new document for the user with uid 42 | await DatabaseService(uid: user.uid).updateTouristData(fullName, email, password); 43 | return _userFromFirebaseUser(user); 44 | } catch(e) { 45 | print(e.toString()); 46 | return null; 47 | } 48 | } 49 | 50 | 51 | // sign in guide with email and password 52 | Future signInGuideWithEmailAndPassword(String email, String password) async { 53 | bool isWrongLogin = await DatabaseService().isTouristSigningIn(email); 54 | if(isWrongLogin) { 55 | return null; 56 | } 57 | else { 58 | try { 59 | AuthResult result = await _auth.signInWithEmailAndPassword(email: email, password: password); 60 | FirebaseUser user = result.user; 61 | return _userFromFirebaseUser(user); 62 | } catch(e) { 63 | print(e.toString()); 64 | return null; 65 | } 66 | } 67 | } 68 | 69 | 70 | // register guide with email and password 71 | Future registerGuideWithEmailAndPassword(String fullName, String email, String phoneNumber, String city, String costPerHour, String password, double latitude, double longitude) async { 72 | try { 73 | AuthResult result = await _auth.createUserWithEmailAndPassword(email: email, password: password); 74 | FirebaseUser user = result.user; 75 | 76 | // Create a new document for the user with uid 77 | await DatabaseService(uid: user.uid).updateGuideData(fullName, email, phoneNumber, city, costPerHour, password, latitude, longitude); 78 | return _userFromFirebaseUser(user); 79 | } catch(e) { 80 | print(e.toString()); 81 | return null; 82 | } 83 | } 84 | 85 | 86 | //sign out 87 | Future signOut() async { 88 | try { 89 | await HelperFunctions.saveUserLoggedInSharedPreference(false); 90 | await HelperFunctions.saveUserEmailSharedPreference(''); 91 | await HelperFunctions.saveUserNameSharedPreference(''); 92 | 93 | return await _auth.signOut(); 94 | } catch(e) { 95 | print(e.toString()); 96 | return null; 97 | } 98 | } 99 | } -------------------------------------------------------------------------------- /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/pages/settings_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:TouristAssist/helper/helper_functions.dart'; 2 | import 'package:TouristAssist/pages/change_name_page.dart'; 3 | import 'package:TouristAssist/pages/change_password_page.dart'; 4 | import 'package:TouristAssist/pages/selectusertype_page.dart'; 5 | import 'package:TouristAssist/services/database_service.dart'; 6 | import 'package:TouristAssist/shared/loading.dart'; 7 | import 'package:firebase_auth/firebase_auth.dart'; 8 | import 'package:flutter/material.dart'; 9 | 10 | class SettingsPage extends StatefulWidget { 11 | 12 | @override 13 | _SettingsPageState createState() => _SettingsPageState(); 14 | } 15 | 16 | class _SettingsPageState extends State { 17 | 18 | FirebaseUser user; 19 | String userName = ''; 20 | String userEmail = ''; 21 | String userPassword = ''; 22 | bool _isLoading = true; 23 | 24 | @override 25 | void initState() { 26 | super.initState(); 27 | _getUserDetails(); 28 | } 29 | 30 | _getUserDetails() async { 31 | user = await FirebaseAuth.instance.currentUser(); 32 | await HelperFunctions.getUserNameSharedPreference().then((value) { 33 | setState(() { 34 | userName = value; 35 | }); 36 | }); 37 | await HelperFunctions.getUserEmailSharedPreference().then((value) { 38 | setState(() { 39 | userEmail = value; 40 | }); 41 | }); 42 | await HelperFunctions.getUserPasswordSharedPreference().then((value) { 43 | setState(() { 44 | userPassword = value; 45 | }); 46 | }); 47 | 48 | setState(() { 49 | _isLoading = false; 50 | }); 51 | } 52 | 53 | _deleteAccount() async { 54 | setState(() { 55 | _isLoading = true; 56 | }); 57 | 58 | await DatabaseService(uid: user.uid).deleteUser(); 59 | user.delete(); 60 | 61 | await HelperFunctions.saveUserLoggedInSharedPreference(false); 62 | await HelperFunctions.saveUserEmailSharedPreference(''); 63 | await HelperFunctions.saveUserNameSharedPreference(''); 64 | await HelperFunctions.saveUserPasswordSharedPreference(''); 65 | 66 | Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) => SelectUserTypePage()), (Route route) => false); 67 | } 68 | 69 | @override 70 | Widget build(BuildContext context) { 71 | return _isLoading ? LoadingAlt() : Scaffold( 72 | appBar: AppBar( 73 | elevation: 0.0, 74 | backgroundColor: Theme.of(context).primaryColor, 75 | title: Text('Settings', style: TextStyle(color: Colors.white)), 76 | iconTheme: IconThemeData( 77 | color: Colors.white 78 | ) 79 | ), 80 | body: ListView( 81 | children: [ 82 | ListTile( 83 | onTap: () { 84 | Navigator.of(context).push(MaterialPageRoute(builder: (context) => ChangeNamePage(userUid: user.uid))); 85 | }, 86 | title: Text('Name'), 87 | subtitle: Text(userName), 88 | trailing: Text('Change Name'), 89 | ), 90 | Divider(), 91 | ListTile( 92 | onTap: () { 93 | 94 | }, 95 | title: Text('Email'), 96 | subtitle: Text(userEmail), 97 | ), 98 | Divider(), 99 | ListTile( 100 | onTap: () { 101 | Navigator.of(context).push(MaterialPageRoute(builder: (context) => ChangePasswordPage(userUid: user.uid))); 102 | }, 103 | title: Text('Password'), 104 | trailing: Text('Change Password'), 105 | ), 106 | Divider(), 107 | ListTile( 108 | onTap: () { 109 | _deleteAccount(); 110 | }, 111 | title: Text('Delete account', style: TextStyle(color: Colors.red)), 112 | ) 113 | ], 114 | ) 115 | ); 116 | } 117 | } -------------------------------------------------------------------------------- /lib/pages/tourist_signin_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:TouristAssist/helper/helper_functions.dart'; 2 | import 'package:TouristAssist/pages/tourist_home_page.dart'; 3 | import 'package:TouristAssist/services/auth_service.dart'; 4 | import 'package:TouristAssist/services/database_service.dart'; 5 | import 'package:TouristAssist/shared/constants.dart'; 6 | import 'package:TouristAssist/shared/loading.dart'; 7 | import 'package:cloud_firestore/cloud_firestore.dart'; 8 | import 'package:flutter/gestures.dart'; 9 | import 'package:flutter/material.dart'; 10 | 11 | class TouristSignInPage extends StatefulWidget { 12 | 13 | final Function toggleView; 14 | TouristSignInPage({this.toggleView}); 15 | 16 | @override 17 | _TouristSignInPageState createState() => _TouristSignInPageState(); 18 | } 19 | 20 | class _TouristSignInPageState extends State { 21 | 22 | TextEditingController _emailEditingController = new TextEditingController(); 23 | TextEditingController _passwordEditingController = new TextEditingController(); 24 | 25 | final AuthService _authService = new AuthService(); 26 | 27 | final _formKey = GlobalKey(); 28 | bool _isLoading = false; 29 | String _error = ''; 30 | 31 | _onSignIn() async { 32 | if (_formKey.currentState.validate()) { 33 | setState(() { 34 | _isLoading = true; 35 | }); 36 | 37 | await _authService.signInTouristWithEmailAndPassword(_emailEditingController.text, _passwordEditingController.text).then((result) async { 38 | if (result != null) { 39 | QuerySnapshot userInfoSnapshot = await DatabaseService().getTouristData(_emailEditingController.text); 40 | 41 | await HelperFunctions.saveUserLoggedInSharedPreference(true); 42 | await HelperFunctions.saveUserEmailSharedPreference(_emailEditingController.text); 43 | await HelperFunctions.saveUserNameSharedPreference( 44 | userInfoSnapshot.documents[0].data['fullName'] 45 | ); 46 | 47 | Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) => TouristHomePage()), (Route route) => false); 48 | // Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context) => TouristHomePage())); 49 | } 50 | else { 51 | setState(() { 52 | _error = 'Error signing in!'; 53 | _isLoading = false; 54 | }); 55 | } 56 | }); 57 | } 58 | } 59 | 60 | @override 61 | Widget build(BuildContext context) { 62 | return _isLoading ? Loading() : Scaffold( 63 | body: Form( 64 | key: _formKey, 65 | child: Container( 66 | color: Theme.of(context).backgroundColor, 67 | child: ListView( 68 | padding: EdgeInsets.symmetric(horizontal: 30.0, vertical: 80.0), 69 | children: [ 70 | Column( 71 | mainAxisAlignment: MainAxisAlignment.center, 72 | crossAxisAlignment: CrossAxisAlignment.center, 73 | children: [ 74 | Text("Welcome back!", style: TextStyle(color: Colors.white, fontSize: 40.0, fontWeight: FontWeight.bold)), 75 | 76 | SizedBox(height: 30.0), 77 | 78 | Text("Sign In", style: TextStyle(color: Colors.white, fontSize: 25.0)), 79 | 80 | SizedBox(height: 20.0), 81 | 82 | TextFormField( 83 | style: TextStyle(color: Colors.white), 84 | controller: _emailEditingController, 85 | decoration: textInputDecoration.copyWith( 86 | hintText: 'Email', 87 | hintStyle: TextStyle(color: Colors.grey), 88 | prefixIcon: Icon(Icons.alternate_email, color: Colors.white), 89 | ), 90 | validator: (val) { 91 | return RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+").hasMatch(val) ? null : "Please enter a valid email"; 92 | }, 93 | ), 94 | 95 | SizedBox(height: 15.0), 96 | 97 | TextFormField( 98 | style: TextStyle(color: Colors.white), 99 | controller: _passwordEditingController, 100 | decoration: textInputDecoration.copyWith( 101 | hintText: 'Password', 102 | hintStyle: TextStyle(color: Colors.grey), 103 | prefixIcon: Icon(Icons.lock, color: Colors.white), 104 | ), 105 | validator: (val) => val.length < 6 ? 'Password not strong enough' : null, 106 | obscureText: true, 107 | ), 108 | 109 | SizedBox(height: 20.0), 110 | 111 | SizedBox( 112 | width: double.infinity, 113 | height: 50.0, 114 | child: RaisedButton( 115 | elevation: 0.0, 116 | color: Colors.lightBlueAccent, 117 | shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30.0)), 118 | child: Text('Sign In', style: TextStyle(color: Colors.white, fontSize: 16.0)), 119 | onPressed: () { 120 | _onSignIn(); 121 | } 122 | ), 123 | ), 124 | 125 | SizedBox(height: 20.0), 126 | 127 | Text.rich( 128 | TextSpan( 129 | text: "Don't have an account? ", 130 | style: TextStyle(color: Colors.white, fontSize: 14.0), 131 | children: [ 132 | TextSpan( 133 | text: 'Register here', 134 | style: TextStyle( 135 | color: Colors.lightBlueAccent, 136 | ), 137 | recognizer: TapGestureRecognizer()..onTap = () { 138 | widget.toggleView(); 139 | }, 140 | ), 141 | ], 142 | ), 143 | ), 144 | 145 | SizedBox(height: 10.0), 146 | 147 | Text(_error, style: TextStyle(color: Colors.red, fontSize: 14.0)), 148 | ], 149 | ), 150 | ], 151 | ), 152 | ), 153 | ) 154 | ); 155 | } 156 | } -------------------------------------------------------------------------------- /lib/pages/tourist_home_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:TouristAssist/helper/helper_functions.dart'; 2 | import 'package:TouristAssist/pages/booknow_page.dart'; 3 | import 'package:TouristAssist/pages/guide_details_page.dart'; 4 | import 'package:TouristAssist/pages/selectusertype_page.dart'; 5 | import 'package:TouristAssist/pages/settings_page.dart'; 6 | import 'package:TouristAssist/services/auth_service.dart'; 7 | import 'package:TouristAssist/shared/loading.dart'; 8 | import 'package:cloud_firestore/cloud_firestore.dart'; 9 | import 'package:flutter/material.dart'; 10 | import 'package:flutter_map/flutter_map.dart'; 11 | import 'package:geolocator/geolocator.dart'; 12 | import 'package:latlong/latlong.dart'; 13 | 14 | class TouristHomePage extends StatefulWidget { 15 | 16 | @override 17 | _TouristHomePageState createState() => _TouristHomePageState(); 18 | } 19 | 20 | class _TouristHomePageState extends State { 21 | 22 | bool _isLoading = true; 23 | dynamic _touristLocation; 24 | dynamic _currentUserCity; 25 | String _userName = ''; 26 | List _guides; 27 | final AuthService _authService = AuthService(); 28 | final GlobalKey _scaffoldKey = new GlobalKey(); 29 | 30 | @override 31 | void initState() { 32 | super.initState(); 33 | _getUserAndLocationDetails(); 34 | } 35 | 36 | _getUserAndLocationDetails() async { 37 | await HelperFunctions.getUserNameSharedPreference().then((value) { 38 | setState(() { 39 | _userName = value; 40 | }); 41 | }); 42 | final location = await Geolocator().getCurrentPosition(desiredAccuracy: LocationAccuracy.best); 43 | List p = await Geolocator().placemarkFromCoordinates(location.latitude, location.longitude); 44 | Placemark place = p[0]; 45 | 46 | setState(() { 47 | _touristLocation = location; 48 | _currentUserCity = place.locality.toLowerCase(); 49 | _isLoading = false; 50 | }); 51 | 52 | QuerySnapshot snapshot = await Firestore.instance.collection('guides').where('city', isEqualTo: _currentUserCity).getDocuments(); 53 | _guides = snapshot.documents; 54 | } 55 | 56 | List _getGuideMarkers() { 57 | List _markers = [ 58 | Marker( 59 | height: 45.0, 60 | width: 45.0, 61 | point: LatLng(_touristLocation.latitude, _touristLocation.longitude), 62 | builder: (context) => Container( 63 | child: IconButton( 64 | icon: Icon(Icons.location_on), 65 | color: Colors.red, 66 | iconSize: 45.0, 67 | onPressed: () {} 68 | ), 69 | ) 70 | ), 71 | ]; 72 | 73 | if(_guides != null) { 74 | for(dynamic item in _guides ) { 75 | _markers.add( 76 | Marker( 77 | height: 30.0, 78 | width: 30.0, 79 | point: LatLng(item['latitude'], item['longitude']), 80 | builder: (context) => Container( 81 | child: GestureDetector( 82 | onTap: () { 83 | Navigator.of(context).push(MaterialPageRoute(builder: (context) => GuideDetailsPage(guideUid: item['uid']))); 84 | }, 85 | child: Text('📍', style: TextStyle(fontSize: 30.0)) 86 | ), 87 | ) 88 | ) 89 | ); 90 | } 91 | } 92 | 93 | return _markers; 94 | } 95 | 96 | @override 97 | Widget build(BuildContext context) { 98 | return _isLoading ? Loading() : Scaffold( 99 | key: _scaffoldKey, 100 | extendBodyBehindAppBar: true, 101 | appBar: AppBar( 102 | backgroundColor: Colors.transparent, 103 | elevation: 0.0, 104 | leading: IconButton( 105 | iconSize: 35.0, 106 | icon: Icon(Icons.menu, color: Colors.black), 107 | onPressed: (){ 108 | _scaffoldKey.currentState.openDrawer(); 109 | }, 110 | ), 111 | ), 112 | drawer: Drawer( 113 | child: Container( 114 | child: ListView( 115 | children: [ 116 | Container( 117 | height: 150.0, 118 | padding: EdgeInsets.symmetric(horizontal: 20.0), 119 | color: Theme.of(context).backgroundColor, 120 | child: Row( 121 | crossAxisAlignment: CrossAxisAlignment.center, 122 | children: [ 123 | Icon(Icons.account_circle, color: Colors.white, size: 60.0), 124 | SizedBox(width: 10.0), 125 | Text(_userName, style: TextStyle(color: Colors.white, fontSize: 18.0)) 126 | ], 127 | ), 128 | ), 129 | ListTile( 130 | onTap: () { 131 | Navigator.of(context).pop(); 132 | }, 133 | contentPadding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 5.0), 134 | leading: Icon(Icons.home), 135 | title: Text('Home', style: TextStyle(fontSize: 16.0)), 136 | ), 137 | ListTile( 138 | onTap: () { 139 | Navigator.of(context).push(MaterialPageRoute(builder: (context) => SettingsPage())); 140 | }, 141 | contentPadding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 5.0), 142 | leading: Icon(Icons.settings), 143 | title: Text('Settings', style: TextStyle(fontSize: 16.0)), 144 | ), 145 | ListTile( 146 | onTap: () async { 147 | await _authService.signOut(); 148 | Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) => SelectUserTypePage()), (Route route) => false); 149 | }, 150 | contentPadding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 5.0), 151 | leading: Icon(Icons.exit_to_app, color: Colors.red), 152 | title: Text('Sign Out', style: TextStyle(fontSize: 16.0, color: Colors.red)), 153 | ), 154 | ], 155 | ), 156 | ), 157 | ), 158 | body: FlutterMap( 159 | options: MapOptions( 160 | center: LatLng(_touristLocation.latitude, _touristLocation.longitude), 161 | minZoom: 5.0 162 | ), 163 | layers: [ 164 | TileLayerOptions( 165 | urlTemplate: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", 166 | subdomains: ['a', 'b', 'c'] 167 | ), 168 | MarkerLayerOptions( 169 | markers: _getGuideMarkers() 170 | ) 171 | ], 172 | ), 173 | bottomSheet: GestureDetector( 174 | onTap: () { 175 | Navigator.of(context).push(MaterialPageRoute(builder: (context) => BookNowPage(currentUserCity: _currentUserCity))); 176 | }, 177 | child: Container( 178 | width: MediaQuery.of(context).size.width, 179 | height: 65.0, 180 | color: Theme.of(context).primaryColor, 181 | child: Center( 182 | child: Text('Book a Guide Now', style: TextStyle(color: Colors.white, fontSize: 20.0)) 183 | ) 184 | ), 185 | ), 186 | ); 187 | } 188 | } -------------------------------------------------------------------------------- /lib/pages/tourist_signup_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:TouristAssist/helper/helper_functions.dart'; 2 | import 'package:TouristAssist/pages/tourist_home_page.dart'; 3 | import 'package:TouristAssist/services/auth_service.dart'; 4 | import 'package:TouristAssist/shared/constants.dart'; 5 | import 'package:TouristAssist/shared/loading.dart'; 6 | import 'package:flutter/gestures.dart'; 7 | import 'package:flutter/material.dart'; 8 | 9 | class TouristSignUpPage extends StatefulWidget { 10 | 11 | final Function toggleView; 12 | TouristSignUpPage({this.toggleView}); 13 | 14 | @override 15 | _TouristSignUpPageState createState() => _TouristSignUpPageState(); 16 | } 17 | 18 | class _TouristSignUpPageState extends State { 19 | 20 | TextEditingController _fullNameEditingController = new TextEditingController(); 21 | TextEditingController _emailEditingController = new TextEditingController(); 22 | TextEditingController _passwordEditingController = new TextEditingController(); 23 | TextEditingController _confirmPasswordEditingController = new TextEditingController(); 24 | 25 | final AuthService _authService = new AuthService(); 26 | 27 | final _formKey = GlobalKey(); 28 | bool _isLoading = false; 29 | String _error = ''; 30 | 31 | _onRegister() async { 32 | if (_formKey.currentState.validate()) { 33 | setState(() { 34 | _isLoading = true; 35 | }); 36 | 37 | await _authService.registerTouristWithEmailAndPassword(_fullNameEditingController.text, _emailEditingController.text, _passwordEditingController.text).then((result) async { 38 | if (result != null) { 39 | await HelperFunctions.saveUserLoggedInSharedPreference(true); 40 | await HelperFunctions.saveUserEmailSharedPreference(_emailEditingController.text); 41 | await HelperFunctions.saveUserNameSharedPreference(_fullNameEditingController.text); 42 | 43 | Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) => TouristHomePage()), (Route route) => false); 44 | // Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context) => TouristHomePage())); 45 | } 46 | else { 47 | setState(() { 48 | _error = 'Error while registering the user!'; 49 | _isLoading = false; 50 | }); 51 | } 52 | }); 53 | } 54 | } 55 | 56 | @override 57 | Widget build(BuildContext context) { 58 | return _isLoading ? Loading() : Scaffold( 59 | body: Form( 60 | key: _formKey, 61 | child: Container( 62 | color: Theme.of(context).backgroundColor, 63 | child: ListView( 64 | padding: EdgeInsets.symmetric(horizontal: 30.0, vertical: 80.0), 65 | children: [ 66 | Column( 67 | mainAxisAlignment: MainAxisAlignment.center, 68 | crossAxisAlignment: CrossAxisAlignment.center, 69 | children: [ 70 | Text("Get started as a Tourist", style: TextStyle(color: Colors.white, fontSize: 40.0, fontWeight: FontWeight.bold)), 71 | 72 | SizedBox(height: 30.0), 73 | 74 | Text("Sign Up", style: TextStyle(color: Colors.white, fontSize: 25.0)), 75 | 76 | SizedBox(height: 20.0), 77 | 78 | TextFormField( 79 | style: TextStyle(color: Colors.white), 80 | controller: _fullNameEditingController, 81 | decoration: textInputDecoration.copyWith( 82 | hintText: 'Full Name', 83 | hintStyle: TextStyle(color: Colors.grey), 84 | prefixIcon: Icon(Icons.person, color: Colors.white) 85 | ), 86 | validator: (val) => val.isEmpty ? 'This field cannot be blank' : null 87 | ), 88 | 89 | SizedBox(height: 15.0), 90 | 91 | TextFormField( 92 | style: TextStyle(color: Colors.white), 93 | controller: _emailEditingController, 94 | decoration: textInputDecoration.copyWith( 95 | hintText: 'Email', 96 | hintStyle: TextStyle(color: Colors.grey), 97 | prefixIcon: Icon(Icons.alternate_email, color: Colors.white) 98 | ), 99 | validator: (val) { 100 | return RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+").hasMatch(val) ? null : "Please enter a valid email"; 101 | }, 102 | ), 103 | 104 | SizedBox(height: 15.0), 105 | 106 | TextFormField( 107 | style: TextStyle(color: Colors.white), 108 | controller: _passwordEditingController, 109 | decoration: textInputDecoration.copyWith( 110 | hintText: 'Password', 111 | hintStyle: TextStyle(color: Colors.grey), 112 | prefixIcon: Icon(Icons.lock, color: Colors.white) 113 | ), 114 | validator: (val) => val.length < 6 ? 'Password not strong enough' : null, 115 | obscureText: true, 116 | ), 117 | 118 | SizedBox(height: 15.0), 119 | 120 | TextFormField( 121 | style: TextStyle(color: Colors.white), 122 | controller: _confirmPasswordEditingController, 123 | decoration: textInputDecoration.copyWith( 124 | hintText: 'Confirm password', 125 | hintStyle: TextStyle(color: Colors.grey), 126 | prefixIcon: Icon(Icons.lock, color: Colors.white), 127 | ), 128 | validator: (val) => val == _passwordEditingController.text ? null : 'Does not macth the password', 129 | obscureText: true, 130 | ), 131 | 132 | SizedBox(height: 20.0), 133 | 134 | SizedBox( 135 | width: double.infinity, 136 | height: 50.0, 137 | child: RaisedButton( 138 | elevation: 0.0, 139 | color: Colors.lightBlueAccent, 140 | shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30.0)), 141 | child: Text('Sign Up', style: TextStyle(color: Colors.white, fontSize: 16.0)), 142 | onPressed: () { 143 | _onRegister(); 144 | } 145 | ), 146 | ), 147 | 148 | SizedBox(height: 20.0), 149 | 150 | Text.rich( 151 | TextSpan( 152 | text: "Already have an account? ", 153 | style: TextStyle(color: Colors.white, fontSize: 14.0), 154 | children: [ 155 | TextSpan( 156 | text: 'Sign In', 157 | style: TextStyle(color: Colors.lightBlueAccent), 158 | recognizer: TapGestureRecognizer()..onTap = () { 159 | widget.toggleView(); 160 | }, 161 | ), 162 | ], 163 | ), 164 | ), 165 | 166 | SizedBox(height: 10.0), 167 | 168 | Text(_error, style: TextStyle(color: Colors.red, fontSize: 14.0)), 169 | ], 170 | ), 171 | ], 172 | ), 173 | ) 174 | ), 175 | ); 176 | } 177 | } -------------------------------------------------------------------------------- /lib/pages/guide_signup_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:TouristAssist/pages/success_guide_signup_page.dart'; 2 | import 'package:TouristAssist/services/auth_service.dart'; 3 | import 'package:TouristAssist/shared/constants.dart'; 4 | import 'package:TouristAssist/shared/loading.dart'; 5 | import 'package:flutter/material.dart'; 6 | import 'package:geolocator/geolocator.dart'; 7 | 8 | class GuideSignUpPage extends StatefulWidget { 9 | 10 | @override 11 | _GuideSignUpPageState createState() => _GuideSignUpPageState(); 12 | } 13 | 14 | class _GuideSignUpPageState extends State { 15 | 16 | TextEditingController _fullNameEditingController = new TextEditingController(); 17 | TextEditingController _emailEditingController = new TextEditingController(); 18 | TextEditingController _phoneNumberEditingController = new TextEditingController(); 19 | TextEditingController _cityEditingController = new TextEditingController(); 20 | TextEditingController _costPerHourEditingController = new TextEditingController(); 21 | TextEditingController _passwordEditingController = new TextEditingController(); 22 | TextEditingController _confirmPasswordEditingController = new TextEditingController(); 23 | 24 | final AuthService _authService = new AuthService(); 25 | 26 | final _formKey = GlobalKey(); 27 | dynamic _guideLocation = ''; 28 | bool _isLoading = false; 29 | String _error = ''; 30 | 31 | @override 32 | void initState() { 33 | super.initState(); 34 | _getLocation(); 35 | } 36 | 37 | _getLocation() async { 38 | final location = await Geolocator().getCurrentPosition(desiredAccuracy: LocationAccuracy.best); 39 | setState(() { 40 | _guideLocation = location; 41 | }); 42 | } 43 | 44 | _onRegister() async { 45 | if (_formKey.currentState.validate()) { 46 | setState(() { 47 | _isLoading = true; 48 | }); 49 | 50 | await _authService.registerGuideWithEmailAndPassword(_fullNameEditingController.text, _emailEditingController.text, _phoneNumberEditingController.text, _cityEditingController.text.toLowerCase(), _costPerHourEditingController.text, _passwordEditingController.text, _guideLocation.latitude, _guideLocation.longitude).then((result) async { 51 | if (result != null) { 52 | // Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) => SuccessGuideSignUpPage()), (Route route) => false); 53 | Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context) => SuccessGuideSignUpPage())); 54 | } 55 | else { 56 | setState(() { 57 | _error = 'Error while registering the user!'; 58 | _isLoading = false; 59 | }); 60 | } 61 | }); 62 | } 63 | } 64 | 65 | @override 66 | Widget build(BuildContext context) { 67 | return _isLoading ? Loading() : Scaffold( 68 | body: Form( 69 | key: _formKey, 70 | child: Container( 71 | color: Theme.of(context).backgroundColor, 72 | child: ListView( 73 | padding: EdgeInsets.symmetric(horizontal: 30.0, vertical: 80.0), 74 | children: [ 75 | Column( 76 | mainAxisAlignment: MainAxisAlignment.center, 77 | crossAxisAlignment: CrossAxisAlignment.center, 78 | children: [ 79 | Text("Get started as a Guide", style: TextStyle(color: Colors.white, fontSize: 40.0, fontWeight: FontWeight.bold)), 80 | 81 | SizedBox(height: 30.0), 82 | 83 | Text("Sign Up", style: TextStyle(color: Colors.white, fontSize: 25.0)), 84 | 85 | SizedBox(height: 20.0), 86 | 87 | TextFormField( 88 | style: TextStyle(color: Colors.white), 89 | controller: _fullNameEditingController, 90 | decoration: textInputDecoration.copyWith( 91 | hintText: 'Full Name', 92 | hintStyle: TextStyle(color: Colors.grey), 93 | prefixIcon: Icon(Icons.person, color: Colors.white) 94 | ), 95 | validator: (val) => val.isEmpty ? 'This field cannot be blank' : null 96 | ), 97 | 98 | SizedBox(height: 15.0), 99 | 100 | TextFormField( 101 | style: TextStyle(color: Colors.white), 102 | controller: _emailEditingController, 103 | decoration: textInputDecoration.copyWith( 104 | hintText: 'Email', 105 | hintStyle: TextStyle(color: Colors.grey), 106 | prefixIcon: Icon(Icons.alternate_email, color: Colors.white) 107 | ), 108 | validator: (val) { 109 | return RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+").hasMatch(val) ? null : "Please enter a valid email"; 110 | }, 111 | ), 112 | 113 | SizedBox(height: 15.0), 114 | 115 | TextFormField( 116 | style: TextStyle(color: Colors.white), 117 | controller: _phoneNumberEditingController, 118 | decoration: textInputDecoration.copyWith( 119 | hintText: 'Phone Number', 120 | hintStyle: TextStyle(color: Colors.grey), 121 | prefixIcon: Icon(Icons.phone, color: Colors.white) 122 | ), 123 | validator: (val) => val.isEmpty ? 'This field cannot be blank' : null 124 | ), 125 | 126 | SizedBox(height: 15.0), 127 | 128 | TextFormField( 129 | style: TextStyle(color: Colors.white), 130 | controller: _cityEditingController, 131 | decoration: textInputDecoration.copyWith( 132 | hintText: 'Current City', 133 | hintStyle: TextStyle(color: Colors.grey), 134 | prefixIcon: Icon(Icons.location_on, color: Colors.white) 135 | ), 136 | validator: (val) => val.isEmpty ? 'This field cannot be blank' : null 137 | ), 138 | 139 | SizedBox(height: 15.0), 140 | 141 | TextFormField( 142 | style: TextStyle(color: Colors.white), 143 | controller: _costPerHourEditingController, 144 | decoration: textInputDecoration.copyWith( 145 | hintText: 'Cost per hour (Rs.)', 146 | hintStyle: TextStyle(color: Colors.grey), 147 | prefixIcon: Icon(Icons.attach_money, color: Colors.white) 148 | ), 149 | validator: (val) => val.isEmpty ? 'This field cannot be blank' : null 150 | ), 151 | 152 | SizedBox(height: 15.0), 153 | 154 | TextFormField( 155 | style: TextStyle(color: Colors.white), 156 | controller: _passwordEditingController, 157 | decoration: textInputDecoration.copyWith( 158 | hintText: 'Password', 159 | hintStyle: TextStyle(color: Colors.grey), 160 | prefixIcon: Icon(Icons.lock, color: Colors.white) 161 | ), 162 | validator: (val) => val.length < 6 ? 'Password not strong enough' : null, 163 | obscureText: true, 164 | ), 165 | 166 | SizedBox(height: 15.0), 167 | 168 | TextFormField( 169 | style: TextStyle(color: Colors.white), 170 | controller: _confirmPasswordEditingController, 171 | decoration: textInputDecoration.copyWith( 172 | hintText: 'Confirm password', 173 | hintStyle: TextStyle(color: Colors.grey), 174 | prefixIcon: Icon(Icons.lock, color: Colors.white), 175 | ), 176 | validator: (val) => val == _passwordEditingController.text ? null : 'Does not macth the password', 177 | obscureText: true, 178 | ), 179 | 180 | SizedBox(height: 10.0), 181 | 182 | Text('Your current location will be used for signing up', style: TextStyle(color: Colors.white)), 183 | 184 | _guideLocation == '' ? Text('') : 185 | Text('Lat: ${_guideLocation.latitude.toStringAsFixed(3)}, Long: ${_guideLocation.longitude.toStringAsFixed(3)}', style: TextStyle(color: Colors.white)), 186 | 187 | SizedBox(height: 20.0), 188 | 189 | SizedBox( 190 | width: double.infinity, 191 | height: 50.0, 192 | child: RaisedButton( 193 | elevation: 0.0, 194 | color: Colors.lightBlueAccent, 195 | shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30.0)), 196 | child: Text('Sign Up', style: TextStyle(color: Colors.white, fontSize: 16.0)), 197 | onPressed: () { 198 | _onRegister(); 199 | } 200 | ), 201 | ), 202 | 203 | SizedBox(height: 10.0), 204 | 205 | Text(_error, style: TextStyle(color: Colors.red, fontSize: 14.0)), 206 | ], 207 | ), 208 | ], 209 | ), 210 | ) 211 | ), 212 | ); 213 | } 214 | } -------------------------------------------------------------------------------- /lib/pages/guide_details_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:TouristAssist/services/database_service.dart'; 2 | import 'package:TouristAssist/shared/loading.dart'; 3 | import 'package:firebase_auth/firebase_auth.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:url_launcher/url_launcher.dart'; 6 | 7 | class GuideDetailsPage extends StatefulWidget { 8 | 9 | final String guideUid; 10 | GuideDetailsPage({ 11 | this.guideUid 12 | }); 13 | 14 | @override 15 | _GuideDetailsPageState createState() => _GuideDetailsPageState(); 16 | } 17 | 18 | class _GuideDetailsPageState extends State { 19 | 20 | dynamic _guideData; 21 | int starNum = 0; 22 | String error = ''; 23 | FirebaseUser _user; 24 | bool _didUserRate = false; 25 | bool _isLoading = true; 26 | 27 | @override 28 | void initState() { 29 | super.initState(); 30 | _getCurrentUserAndGuideDetails(); 31 | } 32 | 33 | _getCurrentUserAndGuideDetails() async { 34 | _user = await FirebaseAuth.instance.currentUser(); 35 | _guideData = await DatabaseService().getGuideData(widget.guideUid); 36 | if(_guideData['votes'].contains(_user.uid)) { 37 | _didUserRate = true; 38 | } 39 | 40 | setState(() { 41 | _isLoading = false; 42 | }); 43 | } 44 | 45 | Future _makePhoneCall(String url) async { 46 | if (await canLaunch(url)) { 47 | await launch(url); 48 | } else { 49 | throw 'Could not launch $url'; 50 | } 51 | } 52 | 53 | String capitalize(String s) => s[0].toUpperCase() + s.substring(1); 54 | 55 | Widget _starBuilder() { 56 | if(starNum == 0) { 57 | return Row( 58 | mainAxisAlignment: MainAxisAlignment.center, 59 | children: [ 60 | GestureDetector( 61 | onTap: () { 62 | setState(() { 63 | starNum = 1; 64 | }); 65 | }, 66 | child: Icon(Icons.star_border) 67 | ), 68 | GestureDetector( 69 | onTap: () { 70 | setState(() { 71 | starNum = 2; 72 | }); 73 | }, 74 | child: Icon(Icons.star_border) 75 | ), 76 | GestureDetector( 77 | onTap: () { 78 | setState(() { 79 | starNum = 3; 80 | }); 81 | }, 82 | child: Icon(Icons.star_border) 83 | ), 84 | GestureDetector( 85 | onTap: () { 86 | setState(() { 87 | starNum = 4; 88 | }); 89 | }, 90 | child: Icon(Icons.star_border) 91 | ), 92 | GestureDetector( 93 | onTap: () { 94 | setState(() { 95 | starNum = 5; 96 | }); 97 | }, 98 | child: Icon(Icons.star_border) 99 | ), 100 | ], 101 | ); 102 | } 103 | else if(starNum == 1) { 104 | return Row( 105 | mainAxisAlignment: MainAxisAlignment.center, 106 | children: [ 107 | GestureDetector( 108 | onTap: () { 109 | setState(() { 110 | starNum = 1; 111 | }); 112 | }, 113 | child: Icon(Icons.star, color: Colors.yellow) 114 | ), 115 | GestureDetector( 116 | onTap: () { 117 | setState(() { 118 | starNum = 2; 119 | }); 120 | }, 121 | child: Icon(Icons.star_border) 122 | ), 123 | GestureDetector( 124 | onTap: () { 125 | setState(() { 126 | starNum = 3; 127 | }); 128 | }, 129 | child: Icon(Icons.star_border) 130 | ), 131 | GestureDetector( 132 | onTap: () { 133 | setState(() { 134 | starNum = 4; 135 | }); 136 | }, 137 | child: Icon(Icons.star_border) 138 | ), 139 | GestureDetector( 140 | onTap: () { 141 | setState(() { 142 | starNum = 5; 143 | }); 144 | }, 145 | child: Icon(Icons.star_border) 146 | ), 147 | ], 148 | ); 149 | } 150 | else if(starNum == 2) { 151 | return Row( 152 | mainAxisAlignment: MainAxisAlignment.center, 153 | children: [ 154 | GestureDetector( 155 | onTap: () { 156 | setState(() { 157 | starNum = 1; 158 | }); 159 | }, 160 | child: Icon(Icons.star, color: Colors.yellow) 161 | ), 162 | GestureDetector( 163 | onTap: () { 164 | setState(() { 165 | starNum = 2; 166 | }); 167 | }, 168 | child: Icon(Icons.star, color: Colors.yellow) 169 | ), 170 | GestureDetector( 171 | onTap: () { 172 | setState(() { 173 | starNum = 3; 174 | }); 175 | }, 176 | child: Icon(Icons.star_border) 177 | ), 178 | GestureDetector( 179 | onTap: () { 180 | setState(() { 181 | starNum = 4; 182 | }); 183 | }, 184 | child: Icon(Icons.star_border) 185 | ), 186 | GestureDetector( 187 | onTap: () { 188 | setState(() { 189 | starNum = 5; 190 | }); 191 | }, 192 | child: Icon(Icons.star_border) 193 | ), 194 | ], 195 | ); 196 | } 197 | else if(starNum == 3) { 198 | return Row( 199 | mainAxisAlignment: MainAxisAlignment.center, 200 | children: [ 201 | GestureDetector( 202 | onTap: () { 203 | setState(() { 204 | starNum = 1; 205 | }); 206 | }, 207 | child: Icon(Icons.star, color: Colors.yellow) 208 | ), 209 | GestureDetector( 210 | onTap: () { 211 | setState(() { 212 | starNum = 2; 213 | }); 214 | }, 215 | child: Icon(Icons.star, color: Colors.yellow) 216 | ), 217 | GestureDetector( 218 | onTap: () { 219 | setState(() { 220 | starNum = 3; 221 | }); 222 | }, 223 | child: Icon(Icons.star, color: Colors.yellow) 224 | ), 225 | GestureDetector( 226 | onTap: () { 227 | setState(() { 228 | starNum = 4; 229 | }); 230 | }, 231 | child: Icon(Icons.star_border) 232 | ), 233 | GestureDetector( 234 | onTap: () { 235 | setState(() { 236 | starNum = 5; 237 | }); 238 | }, 239 | child: Icon(Icons.star_border) 240 | ), 241 | ], 242 | ); 243 | } 244 | else if(starNum == 4) { 245 | return Row( 246 | mainAxisAlignment: MainAxisAlignment.center, 247 | children: [ 248 | GestureDetector( 249 | onTap: () { 250 | setState(() { 251 | starNum = 1; 252 | }); 253 | }, 254 | child: Icon(Icons.star, color: Colors.yellow) 255 | ), 256 | GestureDetector( 257 | onTap: () { 258 | setState(() { 259 | starNum = 2; 260 | }); 261 | }, 262 | child: Icon(Icons.star, color: Colors.yellow) 263 | ), 264 | GestureDetector( 265 | onTap: () { 266 | setState(() { 267 | starNum = 3; 268 | }); 269 | }, 270 | child: Icon(Icons.star, color: Colors.yellow) 271 | ), 272 | GestureDetector( 273 | onTap: () { 274 | setState(() { 275 | starNum = 4; 276 | }); 277 | }, 278 | child: Icon(Icons.star, color: Colors.yellow) 279 | ), 280 | GestureDetector( 281 | onTap: () { 282 | setState(() { 283 | starNum = 5; 284 | }); 285 | }, 286 | child: Icon(Icons.star_border) 287 | ), 288 | ], 289 | ); 290 | } 291 | else { 292 | return Row( 293 | mainAxisAlignment: MainAxisAlignment.center, 294 | children: [ 295 | GestureDetector( 296 | onTap: () { 297 | setState(() { 298 | starNum = 1; 299 | }); 300 | }, 301 | child: Icon(Icons.star, color: Colors.yellow) 302 | ), 303 | GestureDetector( 304 | onTap: () { 305 | setState(() { 306 | starNum = 2; 307 | }); 308 | }, 309 | child: Icon(Icons.star, color: Colors.yellow) 310 | ), 311 | GestureDetector( 312 | onTap: () { 313 | setState(() { 314 | starNum = 3; 315 | }); 316 | }, 317 | child: Icon(Icons.star, color: Colors.yellow) 318 | ), 319 | GestureDetector( 320 | onTap: () { 321 | setState(() { 322 | starNum = 4; 323 | }); 324 | }, 325 | child: Icon(Icons.star, color: Colors.yellow) 326 | ), 327 | GestureDetector( 328 | onTap: () { 329 | setState(() { 330 | starNum = 5; 331 | }); 332 | }, 333 | child: Icon(Icons.star, color: Colors.yellow) 334 | ), 335 | ], 336 | ); 337 | } 338 | } 339 | 340 | _submitRating(String guideUid) async { 341 | // setState(() { 342 | // _didUserRate = true; 343 | // }); 344 | await DatabaseService(uid: guideUid).submitRating(starNum, _user.uid); 345 | Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context) => GuideDetailsPage(guideUid: guideUid,))); 346 | } 347 | 348 | @override 349 | Widget build(BuildContext context) { 350 | return _isLoading ? LoadingAlt() : Scaffold( 351 | extendBodyBehindAppBar: true, 352 | appBar: AppBar( 353 | backgroundColor: Colors.transparent, 354 | elevation: 0.0, 355 | iconTheme: IconThemeData( 356 | color: Colors.white, 357 | ) 358 | ), 359 | body: Column( 360 | crossAxisAlignment: CrossAxisAlignment.start, 361 | children: [ 362 | Container( 363 | width: MediaQuery.of(context).size.width, 364 | height: MediaQuery.of(context).size.height/2 - 100, 365 | child: Icon(Icons.person, color: Colors.white, size: MediaQuery.of(context).size.height/2 - 100), 366 | color: Colors.black87, 367 | ), 368 | Container( 369 | padding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 30.0), 370 | child: Column( 371 | crossAxisAlignment: CrossAxisAlignment.start, 372 | children: [ 373 | Text.rich( 374 | TextSpan( 375 | text: "Name: ", 376 | style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold), 377 | children: [ 378 | TextSpan(text: '${_guideData['fullName']}', style: TextStyle(fontWeight: FontWeight.normal)), 379 | ], 380 | ), 381 | ), 382 | 383 | Divider(height: 30.0), 384 | 385 | Text.rich( 386 | TextSpan( 387 | text: "City: ", 388 | style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold), 389 | children: [ 390 | TextSpan(text: '${capitalize(_guideData['city'].toString())}', style: TextStyle(fontWeight: FontWeight.normal)), 391 | ], 392 | ), 393 | ), 394 | 395 | Divider(height: 30.0), 396 | 397 | Text.rich( 398 | TextSpan( 399 | text: "Rating: ", 400 | style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold), 401 | children: [ 402 | TextSpan(text: '${_guideData['rating']}⭐ (${_guideData['votes'].length} votes)', style: TextStyle(fontWeight: FontWeight.normal)), 403 | ], 404 | ), 405 | ), 406 | 407 | Divider(height: 30.0), 408 | 409 | Text.rich( 410 | TextSpan( 411 | text: "Cost: ", 412 | style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold), 413 | children: [ 414 | TextSpan(text: 'Rs. ${_guideData['costPerHour']}/hr', style: TextStyle(fontWeight: FontWeight.normal)), 415 | ], 416 | ), 417 | ), 418 | ], 419 | ) 420 | ), 421 | 422 | _starBuilder(), 423 | 424 | SizedBox(height: 5.0), 425 | 426 | _didUserRate ? 427 | Container( 428 | width: MediaQuery.of(context).size.width, 429 | child: Center( 430 | child: FlatButton( 431 | color: Colors.grey, 432 | onPressed: () {}, 433 | child: Text('Already rated this guide', style: TextStyle(color: Colors.black)) 434 | ), 435 | ), 436 | ) 437 | : 438 | Container( 439 | width: MediaQuery.of(context).size.width, 440 | child: Center( 441 | child: FlatButton( 442 | color: Colors.green, 443 | onPressed: () async { 444 | if(starNum != 0) { 445 | setState(() { 446 | error = ''; 447 | }); 448 | await _submitRating(widget.guideUid); 449 | } 450 | else { 451 | setState(() { 452 | error = 'Rating cannot be 0'; 453 | }); 454 | } 455 | }, 456 | child: Text('Give Rating', style: TextStyle(color: Colors.white)) 457 | ), 458 | ), 459 | ), 460 | 461 | SizedBox(height: 10.0), 462 | 463 | Center( 464 | child: Text(error, style: TextStyle(color: Colors.red, fontSize: 14.0)) 465 | ) 466 | ], 467 | ), 468 | bottomSheet: Row( 469 | children: [ 470 | GestureDetector( 471 | onTap: () { 472 | _makePhoneCall('tel:${_guideData['phoneNumber']}'); 473 | }, 474 | child: Container( 475 | width: MediaQuery.of(context).size.width, 476 | height: 65.0, 477 | color: Theme.of(context).primaryColor, 478 | child: Center( 479 | child: Text('Call now', style: TextStyle(color: Colors.white, fontSize: 18.0)) 480 | ) 481 | ), 482 | ), 483 | ], 484 | ), 485 | ); 486 | } 487 | } -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | ansicolor: 5 | dependency: transitive 6 | description: 7 | name: ansicolor 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "1.0.2" 11 | archive: 12 | dependency: transitive 13 | description: 14 | name: archive 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.0.13" 18 | args: 19 | dependency: transitive 20 | description: 21 | name: args 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "1.6.0" 25 | async: 26 | dependency: transitive 27 | description: 28 | name: async 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "2.4.1" 32 | boolean_selector: 33 | dependency: transitive 34 | description: 35 | name: boolean_selector 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "2.0.0" 39 | cached_network_image: 40 | dependency: transitive 41 | description: 42 | name: cached_network_image 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "2.2.0+1" 46 | charcode: 47 | dependency: transitive 48 | description: 49 | name: charcode 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.1.3" 53 | clock: 54 | dependency: transitive 55 | description: 56 | name: clock 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "1.0.1" 60 | cloud_firestore: 61 | dependency: "direct main" 62 | description: 63 | name: cloud_firestore 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "0.13.7" 67 | cloud_firestore_platform_interface: 68 | dependency: transitive 69 | description: 70 | name: cloud_firestore_platform_interface 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "1.1.2" 74 | cloud_firestore_web: 75 | dependency: transitive 76 | description: 77 | name: cloud_firestore_web 78 | url: "https://pub.dartlang.org" 79 | source: hosted 80 | version: "0.1.1+2" 81 | collection: 82 | dependency: transitive 83 | description: 84 | name: collection 85 | url: "https://pub.dartlang.org" 86 | source: hosted 87 | version: "1.14.12" 88 | console_log_handler: 89 | dependency: transitive 90 | description: 91 | name: console_log_handler 92 | url: "https://pub.dartlang.org" 93 | source: hosted 94 | version: "1.1.6" 95 | convert: 96 | dependency: transitive 97 | description: 98 | name: convert 99 | url: "https://pub.dartlang.org" 100 | source: hosted 101 | version: "2.1.1" 102 | crypto: 103 | dependency: transitive 104 | description: 105 | name: crypto 106 | url: "https://pub.dartlang.org" 107 | source: hosted 108 | version: "2.1.4" 109 | cupertino_icons: 110 | dependency: "direct main" 111 | description: 112 | name: cupertino_icons 113 | url: "https://pub.dartlang.org" 114 | source: hosted 115 | version: "0.1.3" 116 | equatable: 117 | dependency: transitive 118 | description: 119 | name: equatable 120 | url: "https://pub.dartlang.org" 121 | source: hosted 122 | version: "1.2.0" 123 | file: 124 | dependency: transitive 125 | description: 126 | name: file 127 | url: "https://pub.dartlang.org" 128 | source: hosted 129 | version: "5.2.1" 130 | firebase: 131 | dependency: transitive 132 | description: 133 | name: firebase 134 | url: "https://pub.dartlang.org" 135 | source: hosted 136 | version: "7.3.0" 137 | firebase_auth: 138 | dependency: "direct main" 139 | description: 140 | name: firebase_auth 141 | url: "https://pub.dartlang.org" 142 | source: hosted 143 | version: "0.16.1" 144 | firebase_auth_platform_interface: 145 | dependency: transitive 146 | description: 147 | name: firebase_auth_platform_interface 148 | url: "https://pub.dartlang.org" 149 | source: hosted 150 | version: "1.1.8" 151 | firebase_auth_web: 152 | dependency: transitive 153 | description: 154 | name: firebase_auth_web 155 | url: "https://pub.dartlang.org" 156 | source: hosted 157 | version: "0.1.3+1" 158 | firebase_core: 159 | dependency: transitive 160 | description: 161 | name: firebase_core 162 | url: "https://pub.dartlang.org" 163 | source: hosted 164 | version: "0.4.5" 165 | firebase_core_platform_interface: 166 | dependency: transitive 167 | description: 168 | name: firebase_core_platform_interface 169 | url: "https://pub.dartlang.org" 170 | source: hosted 171 | version: "1.0.4" 172 | firebase_core_web: 173 | dependency: transitive 174 | description: 175 | name: firebase_core_web 176 | url: "https://pub.dartlang.org" 177 | source: hosted 178 | version: "0.1.1+2" 179 | flutter: 180 | dependency: "direct main" 181 | description: flutter 182 | source: sdk 183 | version: "0.0.0" 184 | flutter_cache_manager: 185 | dependency: transitive 186 | description: 187 | name: flutter_cache_manager 188 | url: "https://pub.dartlang.org" 189 | source: hosted 190 | version: "1.4.1" 191 | flutter_image: 192 | dependency: transitive 193 | description: 194 | name: flutter_image 195 | url: "https://pub.dartlang.org" 196 | source: hosted 197 | version: "3.0.0" 198 | flutter_map: 199 | dependency: "direct main" 200 | description: 201 | name: flutter_map 202 | url: "https://pub.dartlang.org" 203 | source: hosted 204 | version: "0.9.0" 205 | flutter_spinkit: 206 | dependency: "direct main" 207 | description: 208 | name: flutter_spinkit 209 | url: "https://pub.dartlang.org" 210 | source: hosted 211 | version: "4.1.2+1" 212 | flutter_test: 213 | dependency: "direct dev" 214 | description: flutter 215 | source: sdk 216 | version: "0.0.0" 217 | flutter_web_plugins: 218 | dependency: transitive 219 | description: flutter 220 | source: sdk 221 | version: "0.0.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.2+2" 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 | http: 237 | dependency: transitive 238 | description: 239 | name: http 240 | url: "https://pub.dartlang.org" 241 | source: hosted 242 | version: "0.12.1" 243 | http_parser: 244 | dependency: transitive 245 | description: 246 | name: http_parser 247 | url: "https://pub.dartlang.org" 248 | source: hosted 249 | version: "3.1.4" 250 | image: 251 | dependency: transitive 252 | description: 253 | name: image 254 | url: "https://pub.dartlang.org" 255 | source: hosted 256 | version: "2.1.12" 257 | intl: 258 | dependency: transitive 259 | description: 260 | name: intl 261 | url: "https://pub.dartlang.org" 262 | source: hosted 263 | version: "0.16.1" 264 | js: 265 | dependency: transitive 266 | description: 267 | name: js 268 | url: "https://pub.dartlang.org" 269 | source: hosted 270 | version: "0.6.2" 271 | latlong: 272 | dependency: transitive 273 | description: 274 | name: latlong 275 | url: "https://pub.dartlang.org" 276 | source: hosted 277 | version: "0.6.1" 278 | lists: 279 | dependency: transitive 280 | description: 281 | name: lists 282 | url: "https://pub.dartlang.org" 283 | source: hosted 284 | version: "0.1.6" 285 | location_permissions: 286 | dependency: transitive 287 | description: 288 | name: location_permissions 289 | url: "https://pub.dartlang.org" 290 | source: hosted 291 | version: "3.0.0+1" 292 | logging: 293 | dependency: transitive 294 | description: 295 | name: logging 296 | url: "https://pub.dartlang.org" 297 | source: hosted 298 | version: "0.11.4" 299 | matcher: 300 | dependency: transitive 301 | description: 302 | name: matcher 303 | url: "https://pub.dartlang.org" 304 | source: hosted 305 | version: "0.12.6" 306 | meta: 307 | dependency: transitive 308 | description: 309 | name: meta 310 | url: "https://pub.dartlang.org" 311 | source: hosted 312 | version: "1.1.8" 313 | mgrs_dart: 314 | dependency: transitive 315 | description: 316 | name: mgrs_dart 317 | url: "https://pub.dartlang.org" 318 | source: hosted 319 | version: "1.0.1" 320 | path: 321 | dependency: transitive 322 | description: 323 | name: path 324 | url: "https://pub.dartlang.org" 325 | source: hosted 326 | version: "1.6.4" 327 | path_provider: 328 | dependency: transitive 329 | description: 330 | name: path_provider 331 | url: "https://pub.dartlang.org" 332 | source: hosted 333 | version: "1.6.11" 334 | path_provider_linux: 335 | dependency: transitive 336 | description: 337 | name: path_provider_linux 338 | url: "https://pub.dartlang.org" 339 | source: hosted 340 | version: "0.0.1+2" 341 | path_provider_macos: 342 | dependency: transitive 343 | description: 344 | name: path_provider_macos 345 | url: "https://pub.dartlang.org" 346 | source: hosted 347 | version: "0.0.4+3" 348 | path_provider_platform_interface: 349 | dependency: transitive 350 | description: 351 | name: path_provider_platform_interface 352 | url: "https://pub.dartlang.org" 353 | source: hosted 354 | version: "1.0.2" 355 | pedantic: 356 | dependency: transitive 357 | description: 358 | name: pedantic 359 | url: "https://pub.dartlang.org" 360 | source: hosted 361 | version: "1.9.0" 362 | petitparser: 363 | dependency: transitive 364 | description: 365 | name: petitparser 366 | url: "https://pub.dartlang.org" 367 | source: hosted 368 | version: "2.4.0" 369 | platform: 370 | dependency: transitive 371 | description: 372 | name: platform 373 | url: "https://pub.dartlang.org" 374 | source: hosted 375 | version: "2.2.1" 376 | platform_detect: 377 | dependency: transitive 378 | description: 379 | name: platform_detect 380 | url: "https://pub.dartlang.org" 381 | source: hosted 382 | version: "1.4.0" 383 | plugin_platform_interface: 384 | dependency: transitive 385 | description: 386 | name: plugin_platform_interface 387 | url: "https://pub.dartlang.org" 388 | source: hosted 389 | version: "1.0.2" 390 | positioned_tap_detector: 391 | dependency: transitive 392 | description: 393 | name: positioned_tap_detector 394 | url: "https://pub.dartlang.org" 395 | source: hosted 396 | version: "1.0.3" 397 | process: 398 | dependency: transitive 399 | description: 400 | name: process 401 | url: "https://pub.dartlang.org" 402 | source: hosted 403 | version: "3.0.13" 404 | proj4dart: 405 | dependency: transitive 406 | description: 407 | name: proj4dart 408 | url: "https://pub.dartlang.org" 409 | source: hosted 410 | version: "1.0.5" 411 | pub_semver: 412 | dependency: transitive 413 | description: 414 | name: pub_semver 415 | url: "https://pub.dartlang.org" 416 | source: hosted 417 | version: "1.4.4" 418 | quiver: 419 | dependency: transitive 420 | description: 421 | name: quiver 422 | url: "https://pub.dartlang.org" 423 | source: hosted 424 | version: "2.1.3" 425 | rxdart: 426 | dependency: transitive 427 | description: 428 | name: rxdart 429 | url: "https://pub.dartlang.org" 430 | source: hosted 431 | version: "0.24.1" 432 | shared_preferences: 433 | dependency: "direct main" 434 | description: 435 | name: shared_preferences 436 | url: "https://pub.dartlang.org" 437 | source: hosted 438 | version: "0.5.7+3" 439 | shared_preferences_macos: 440 | dependency: transitive 441 | description: 442 | name: shared_preferences_macos 443 | url: "https://pub.dartlang.org" 444 | source: hosted 445 | version: "0.0.1+10" 446 | shared_preferences_platform_interface: 447 | dependency: transitive 448 | description: 449 | name: shared_preferences_platform_interface 450 | url: "https://pub.dartlang.org" 451 | source: hosted 452 | version: "1.0.4" 453 | shared_preferences_web: 454 | dependency: transitive 455 | description: 456 | name: shared_preferences_web 457 | url: "https://pub.dartlang.org" 458 | source: hosted 459 | version: "0.1.2+7" 460 | sky_engine: 461 | dependency: transitive 462 | description: flutter 463 | source: sdk 464 | version: "0.0.99" 465 | source_span: 466 | dependency: transitive 467 | description: 468 | name: source_span 469 | url: "https://pub.dartlang.org" 470 | source: hosted 471 | version: "1.7.0" 472 | sqflite: 473 | dependency: transitive 474 | description: 475 | name: sqflite 476 | url: "https://pub.dartlang.org" 477 | source: hosted 478 | version: "1.3.1" 479 | sqflite_common: 480 | dependency: transitive 481 | description: 482 | name: sqflite_common 483 | url: "https://pub.dartlang.org" 484 | source: hosted 485 | version: "1.0.2+1" 486 | stack_trace: 487 | dependency: transitive 488 | description: 489 | name: stack_trace 490 | url: "https://pub.dartlang.org" 491 | source: hosted 492 | version: "1.9.3" 493 | stream_channel: 494 | dependency: transitive 495 | description: 496 | name: stream_channel 497 | url: "https://pub.dartlang.org" 498 | source: hosted 499 | version: "2.0.0" 500 | string_scanner: 501 | dependency: transitive 502 | description: 503 | name: string_scanner 504 | url: "https://pub.dartlang.org" 505 | source: hosted 506 | version: "1.0.5" 507 | synchronized: 508 | dependency: transitive 509 | description: 510 | name: synchronized 511 | url: "https://pub.dartlang.org" 512 | source: hosted 513 | version: "2.2.0+1" 514 | term_glyph: 515 | dependency: transitive 516 | description: 517 | name: term_glyph 518 | url: "https://pub.dartlang.org" 519 | source: hosted 520 | version: "1.1.0" 521 | test_api: 522 | dependency: transitive 523 | description: 524 | name: test_api 525 | url: "https://pub.dartlang.org" 526 | source: hosted 527 | version: "0.2.15" 528 | transparent_image: 529 | dependency: transitive 530 | description: 531 | name: transparent_image 532 | url: "https://pub.dartlang.org" 533 | source: hosted 534 | version: "1.0.0" 535 | tuple: 536 | dependency: transitive 537 | description: 538 | name: tuple 539 | url: "https://pub.dartlang.org" 540 | source: hosted 541 | version: "1.0.3" 542 | typed_data: 543 | dependency: transitive 544 | description: 545 | name: typed_data 546 | url: "https://pub.dartlang.org" 547 | source: hosted 548 | version: "1.1.6" 549 | unicode: 550 | dependency: transitive 551 | description: 552 | name: unicode 553 | url: "https://pub.dartlang.org" 554 | source: hosted 555 | version: "0.2.4" 556 | url_launcher: 557 | dependency: "direct main" 558 | description: 559 | name: url_launcher 560 | url: "https://pub.dartlang.org" 561 | source: hosted 562 | version: "5.4.11" 563 | url_launcher_macos: 564 | dependency: transitive 565 | description: 566 | name: url_launcher_macos 567 | url: "https://pub.dartlang.org" 568 | source: hosted 569 | version: "0.0.1+7" 570 | url_launcher_platform_interface: 571 | dependency: transitive 572 | description: 573 | name: url_launcher_platform_interface 574 | url: "https://pub.dartlang.org" 575 | source: hosted 576 | version: "1.0.7" 577 | url_launcher_web: 578 | dependency: transitive 579 | description: 580 | name: url_launcher_web 581 | url: "https://pub.dartlang.org" 582 | source: hosted 583 | version: "0.1.2" 584 | uuid: 585 | dependency: transitive 586 | description: 587 | name: uuid 588 | url: "https://pub.dartlang.org" 589 | source: hosted 590 | version: "2.2.0" 591 | validate: 592 | dependency: transitive 593 | description: 594 | name: validate 595 | url: "https://pub.dartlang.org" 596 | source: hosted 597 | version: "1.7.0" 598 | vector_math: 599 | dependency: transitive 600 | description: 601 | name: vector_math 602 | url: "https://pub.dartlang.org" 603 | source: hosted 604 | version: "2.0.8" 605 | wkt_parser: 606 | dependency: transitive 607 | description: 608 | name: wkt_parser 609 | url: "https://pub.dartlang.org" 610 | source: hosted 611 | version: "1.0.7" 612 | xdg_directories: 613 | dependency: transitive 614 | description: 615 | name: xdg_directories 616 | url: "https://pub.dartlang.org" 617 | source: hosted 618 | version: "0.1.0" 619 | xml: 620 | dependency: transitive 621 | description: 622 | name: xml 623 | url: "https://pub.dartlang.org" 624 | source: hosted 625 | version: "3.6.1" 626 | sdks: 627 | dart: ">=2.8.0 <3.0.0" 628 | flutter: ">=1.12.13+hotfix.6 <2.0.0" 629 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 13 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 14 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 15 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXCopyFilesBuildPhase section */ 19 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 20 | isa = PBXCopyFilesBuildPhase; 21 | buildActionMask = 2147483647; 22 | dstPath = ""; 23 | dstSubfolderSpec = 10; 24 | files = ( 25 | ); 26 | name = "Embed Frameworks"; 27 | runOnlyForDeploymentPostprocessing = 0; 28 | }; 29 | /* End PBXCopyFilesBuildPhase section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 33 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 34 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 35 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 36 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 37 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 38 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 39 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 40 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 42 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 43 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 44 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 45 | /* End PBXFileReference section */ 46 | 47 | /* Begin PBXFrameworksBuildPhase section */ 48 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 49 | isa = PBXFrameworksBuildPhase; 50 | buildActionMask = 2147483647; 51 | files = ( 52 | ); 53 | runOnlyForDeploymentPostprocessing = 0; 54 | }; 55 | /* End PBXFrameworksBuildPhase section */ 56 | 57 | /* Begin PBXGroup section */ 58 | 9740EEB11CF90186004384FC /* Flutter */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 62 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 63 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 64 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 65 | ); 66 | name = Flutter; 67 | sourceTree = ""; 68 | }; 69 | 97C146E51CF9000F007C117D = { 70 | isa = PBXGroup; 71 | children = ( 72 | 9740EEB11CF90186004384FC /* Flutter */, 73 | 97C146F01CF9000F007C117D /* Runner */, 74 | 97C146EF1CF9000F007C117D /* Products */, 75 | ); 76 | sourceTree = ""; 77 | }; 78 | 97C146EF1CF9000F007C117D /* Products */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 97C146EE1CF9000F007C117D /* Runner.app */, 82 | ); 83 | name = Products; 84 | sourceTree = ""; 85 | }; 86 | 97C146F01CF9000F007C117D /* Runner */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 90 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 91 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 92 | 97C147021CF9000F007C117D /* Info.plist */, 93 | 97C146F11CF9000F007C117D /* Supporting Files */, 94 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 95 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 96 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 97 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 98 | ); 99 | path = Runner; 100 | sourceTree = ""; 101 | }; 102 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | ); 106 | name = "Supporting Files"; 107 | sourceTree = ""; 108 | }; 109 | /* End PBXGroup section */ 110 | 111 | /* Begin PBXNativeTarget section */ 112 | 97C146ED1CF9000F007C117D /* Runner */ = { 113 | isa = PBXNativeTarget; 114 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 115 | buildPhases = ( 116 | 9740EEB61CF901F6004384FC /* Run Script */, 117 | 97C146EA1CF9000F007C117D /* Sources */, 118 | 97C146EB1CF9000F007C117D /* Frameworks */, 119 | 97C146EC1CF9000F007C117D /* Resources */, 120 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 121 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 122 | ); 123 | buildRules = ( 124 | ); 125 | dependencies = ( 126 | ); 127 | name = Runner; 128 | productName = Runner; 129 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 130 | productType = "com.apple.product-type.application"; 131 | }; 132 | /* End PBXNativeTarget section */ 133 | 134 | /* Begin PBXProject section */ 135 | 97C146E61CF9000F007C117D /* Project object */ = { 136 | isa = PBXProject; 137 | attributes = { 138 | LastUpgradeCheck = 1020; 139 | ORGANIZATIONNAME = ""; 140 | TargetAttributes = { 141 | 97C146ED1CF9000F007C117D = { 142 | CreatedOnToolsVersion = 7.3.1; 143 | LastSwiftMigration = 1100; 144 | }; 145 | }; 146 | }; 147 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 148 | compatibilityVersion = "Xcode 9.3"; 149 | developmentRegion = en; 150 | hasScannedForEncodings = 0; 151 | knownRegions = ( 152 | en, 153 | Base, 154 | ); 155 | mainGroup = 97C146E51CF9000F007C117D; 156 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 157 | projectDirPath = ""; 158 | projectRoot = ""; 159 | targets = ( 160 | 97C146ED1CF9000F007C117D /* Runner */, 161 | ); 162 | }; 163 | /* End PBXProject section */ 164 | 165 | /* Begin PBXResourcesBuildPhase section */ 166 | 97C146EC1CF9000F007C117D /* Resources */ = { 167 | isa = PBXResourcesBuildPhase; 168 | buildActionMask = 2147483647; 169 | files = ( 170 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 171 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 172 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 173 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 174 | ); 175 | runOnlyForDeploymentPostprocessing = 0; 176 | }; 177 | /* End PBXResourcesBuildPhase section */ 178 | 179 | /* Begin PBXShellScriptBuildPhase section */ 180 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 181 | isa = PBXShellScriptBuildPhase; 182 | buildActionMask = 2147483647; 183 | files = ( 184 | ); 185 | inputPaths = ( 186 | ); 187 | name = "Thin Binary"; 188 | outputPaths = ( 189 | ); 190 | runOnlyForDeploymentPostprocessing = 0; 191 | shellPath = /bin/sh; 192 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 193 | }; 194 | 9740EEB61CF901F6004384FC /* Run Script */ = { 195 | isa = PBXShellScriptBuildPhase; 196 | buildActionMask = 2147483647; 197 | files = ( 198 | ); 199 | inputPaths = ( 200 | ); 201 | name = "Run Script"; 202 | outputPaths = ( 203 | ); 204 | runOnlyForDeploymentPostprocessing = 0; 205 | shellPath = /bin/sh; 206 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 207 | }; 208 | /* End PBXShellScriptBuildPhase section */ 209 | 210 | /* Begin PBXSourcesBuildPhase section */ 211 | 97C146EA1CF9000F007C117D /* Sources */ = { 212 | isa = PBXSourcesBuildPhase; 213 | buildActionMask = 2147483647; 214 | files = ( 215 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 216 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | }; 220 | /* End PBXSourcesBuildPhase section */ 221 | 222 | /* Begin PBXVariantGroup section */ 223 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 224 | isa = PBXVariantGroup; 225 | children = ( 226 | 97C146FB1CF9000F007C117D /* Base */, 227 | ); 228 | name = Main.storyboard; 229 | sourceTree = ""; 230 | }; 231 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 232 | isa = PBXVariantGroup; 233 | children = ( 234 | 97C147001CF9000F007C117D /* Base */, 235 | ); 236 | name = LaunchScreen.storyboard; 237 | sourceTree = ""; 238 | }; 239 | /* End PBXVariantGroup section */ 240 | 241 | /* Begin XCBuildConfiguration section */ 242 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 243 | isa = XCBuildConfiguration; 244 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 245 | buildSettings = { 246 | ALWAYS_SEARCH_USER_PATHS = NO; 247 | CLANG_ANALYZER_NONNULL = YES; 248 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 249 | CLANG_CXX_LIBRARY = "libc++"; 250 | CLANG_ENABLE_MODULES = YES; 251 | CLANG_ENABLE_OBJC_ARC = YES; 252 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 253 | CLANG_WARN_BOOL_CONVERSION = YES; 254 | CLANG_WARN_COMMA = YES; 255 | CLANG_WARN_CONSTANT_CONVERSION = YES; 256 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 257 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 258 | CLANG_WARN_EMPTY_BODY = YES; 259 | CLANG_WARN_ENUM_CONVERSION = YES; 260 | CLANG_WARN_INFINITE_RECURSION = YES; 261 | CLANG_WARN_INT_CONVERSION = YES; 262 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 263 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 264 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 265 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 266 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 267 | CLANG_WARN_STRICT_PROTOTYPES = YES; 268 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 269 | CLANG_WARN_UNREACHABLE_CODE = YES; 270 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 271 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 272 | COPY_PHASE_STRIP = NO; 273 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 274 | ENABLE_NS_ASSERTIONS = NO; 275 | ENABLE_STRICT_OBJC_MSGSEND = YES; 276 | GCC_C_LANGUAGE_STANDARD = gnu99; 277 | GCC_NO_COMMON_BLOCKS = YES; 278 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 279 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 280 | GCC_WARN_UNDECLARED_SELECTOR = YES; 281 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 282 | GCC_WARN_UNUSED_FUNCTION = YES; 283 | GCC_WARN_UNUSED_VARIABLE = YES; 284 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 285 | MTL_ENABLE_DEBUG_INFO = NO; 286 | SDKROOT = iphoneos; 287 | SUPPORTED_PLATFORMS = iphoneos; 288 | TARGETED_DEVICE_FAMILY = "1,2"; 289 | VALIDATE_PRODUCT = YES; 290 | }; 291 | name = Profile; 292 | }; 293 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 294 | isa = XCBuildConfiguration; 295 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 296 | buildSettings = { 297 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 298 | CLANG_ENABLE_MODULES = YES; 299 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 300 | ENABLE_BITCODE = NO; 301 | FRAMEWORK_SEARCH_PATHS = ( 302 | "$(inherited)", 303 | "$(PROJECT_DIR)/Flutter", 304 | ); 305 | INFOPLIST_FILE = Runner/Info.plist; 306 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 307 | LIBRARY_SEARCH_PATHS = ( 308 | "$(inherited)", 309 | "$(PROJECT_DIR)/Flutter", 310 | ); 311 | PRODUCT_BUNDLE_IDENTIFIER = com.example.TouristAssist; 312 | PRODUCT_NAME = "$(TARGET_NAME)"; 313 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 314 | SWIFT_VERSION = 5.0; 315 | VERSIONING_SYSTEM = "apple-generic"; 316 | }; 317 | name = Profile; 318 | }; 319 | 97C147031CF9000F007C117D /* Debug */ = { 320 | isa = XCBuildConfiguration; 321 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 322 | buildSettings = { 323 | ALWAYS_SEARCH_USER_PATHS = NO; 324 | CLANG_ANALYZER_NONNULL = YES; 325 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 326 | CLANG_CXX_LIBRARY = "libc++"; 327 | CLANG_ENABLE_MODULES = YES; 328 | CLANG_ENABLE_OBJC_ARC = YES; 329 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 330 | CLANG_WARN_BOOL_CONVERSION = YES; 331 | CLANG_WARN_COMMA = YES; 332 | CLANG_WARN_CONSTANT_CONVERSION = YES; 333 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 334 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 335 | CLANG_WARN_EMPTY_BODY = YES; 336 | CLANG_WARN_ENUM_CONVERSION = YES; 337 | CLANG_WARN_INFINITE_RECURSION = YES; 338 | CLANG_WARN_INT_CONVERSION = YES; 339 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 340 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 341 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 342 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 343 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 344 | CLANG_WARN_STRICT_PROTOTYPES = YES; 345 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 346 | CLANG_WARN_UNREACHABLE_CODE = YES; 347 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 348 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 349 | COPY_PHASE_STRIP = NO; 350 | DEBUG_INFORMATION_FORMAT = dwarf; 351 | ENABLE_STRICT_OBJC_MSGSEND = YES; 352 | ENABLE_TESTABILITY = YES; 353 | GCC_C_LANGUAGE_STANDARD = gnu99; 354 | GCC_DYNAMIC_NO_PIC = NO; 355 | GCC_NO_COMMON_BLOCKS = YES; 356 | GCC_OPTIMIZATION_LEVEL = 0; 357 | GCC_PREPROCESSOR_DEFINITIONS = ( 358 | "DEBUG=1", 359 | "$(inherited)", 360 | ); 361 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 362 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 363 | GCC_WARN_UNDECLARED_SELECTOR = YES; 364 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 365 | GCC_WARN_UNUSED_FUNCTION = YES; 366 | GCC_WARN_UNUSED_VARIABLE = YES; 367 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 368 | MTL_ENABLE_DEBUG_INFO = YES; 369 | ONLY_ACTIVE_ARCH = YES; 370 | SDKROOT = iphoneos; 371 | TARGETED_DEVICE_FAMILY = "1,2"; 372 | }; 373 | name = Debug; 374 | }; 375 | 97C147041CF9000F007C117D /* Release */ = { 376 | isa = XCBuildConfiguration; 377 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 378 | buildSettings = { 379 | ALWAYS_SEARCH_USER_PATHS = NO; 380 | CLANG_ANALYZER_NONNULL = YES; 381 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 382 | CLANG_CXX_LIBRARY = "libc++"; 383 | CLANG_ENABLE_MODULES = YES; 384 | CLANG_ENABLE_OBJC_ARC = YES; 385 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 386 | CLANG_WARN_BOOL_CONVERSION = YES; 387 | CLANG_WARN_COMMA = YES; 388 | CLANG_WARN_CONSTANT_CONVERSION = YES; 389 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 390 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 391 | CLANG_WARN_EMPTY_BODY = YES; 392 | CLANG_WARN_ENUM_CONVERSION = YES; 393 | CLANG_WARN_INFINITE_RECURSION = YES; 394 | CLANG_WARN_INT_CONVERSION = YES; 395 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 396 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 397 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 398 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 399 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 400 | CLANG_WARN_STRICT_PROTOTYPES = YES; 401 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 402 | CLANG_WARN_UNREACHABLE_CODE = YES; 403 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 404 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 405 | COPY_PHASE_STRIP = NO; 406 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 407 | ENABLE_NS_ASSERTIONS = NO; 408 | ENABLE_STRICT_OBJC_MSGSEND = YES; 409 | GCC_C_LANGUAGE_STANDARD = gnu99; 410 | GCC_NO_COMMON_BLOCKS = YES; 411 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 412 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 413 | GCC_WARN_UNDECLARED_SELECTOR = YES; 414 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 415 | GCC_WARN_UNUSED_FUNCTION = YES; 416 | GCC_WARN_UNUSED_VARIABLE = YES; 417 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 418 | MTL_ENABLE_DEBUG_INFO = NO; 419 | SDKROOT = iphoneos; 420 | SUPPORTED_PLATFORMS = iphoneos; 421 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 422 | TARGETED_DEVICE_FAMILY = "1,2"; 423 | VALIDATE_PRODUCT = YES; 424 | }; 425 | name = Release; 426 | }; 427 | 97C147061CF9000F007C117D /* Debug */ = { 428 | isa = XCBuildConfiguration; 429 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 430 | buildSettings = { 431 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 432 | CLANG_ENABLE_MODULES = YES; 433 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 434 | ENABLE_BITCODE = NO; 435 | FRAMEWORK_SEARCH_PATHS = ( 436 | "$(inherited)", 437 | "$(PROJECT_DIR)/Flutter", 438 | ); 439 | INFOPLIST_FILE = Runner/Info.plist; 440 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 441 | LIBRARY_SEARCH_PATHS = ( 442 | "$(inherited)", 443 | "$(PROJECT_DIR)/Flutter", 444 | ); 445 | PRODUCT_BUNDLE_IDENTIFIER = com.example.TouristAssist; 446 | PRODUCT_NAME = "$(TARGET_NAME)"; 447 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 448 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 449 | SWIFT_VERSION = 5.0; 450 | VERSIONING_SYSTEM = "apple-generic"; 451 | }; 452 | name = Debug; 453 | }; 454 | 97C147071CF9000F007C117D /* Release */ = { 455 | isa = XCBuildConfiguration; 456 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 457 | buildSettings = { 458 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 459 | CLANG_ENABLE_MODULES = YES; 460 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 461 | ENABLE_BITCODE = NO; 462 | FRAMEWORK_SEARCH_PATHS = ( 463 | "$(inherited)", 464 | "$(PROJECT_DIR)/Flutter", 465 | ); 466 | INFOPLIST_FILE = Runner/Info.plist; 467 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 468 | LIBRARY_SEARCH_PATHS = ( 469 | "$(inherited)", 470 | "$(PROJECT_DIR)/Flutter", 471 | ); 472 | PRODUCT_BUNDLE_IDENTIFIER = com.example.TouristAssist; 473 | PRODUCT_NAME = "$(TARGET_NAME)"; 474 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 475 | SWIFT_VERSION = 5.0; 476 | VERSIONING_SYSTEM = "apple-generic"; 477 | }; 478 | name = Release; 479 | }; 480 | /* End XCBuildConfiguration section */ 481 | 482 | /* Begin XCConfigurationList section */ 483 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 484 | isa = XCConfigurationList; 485 | buildConfigurations = ( 486 | 97C147031CF9000F007C117D /* Debug */, 487 | 97C147041CF9000F007C117D /* Release */, 488 | 249021D3217E4FDB00AE95B9 /* Profile */, 489 | ); 490 | defaultConfigurationIsVisible = 0; 491 | defaultConfigurationName = Release; 492 | }; 493 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 494 | isa = XCConfigurationList; 495 | buildConfigurations = ( 496 | 97C147061CF9000F007C117D /* Debug */, 497 | 97C147071CF9000F007C117D /* Release */, 498 | 249021D4217E4FDB00AE95B9 /* Profile */, 499 | ); 500 | defaultConfigurationIsVisible = 0; 501 | defaultConfigurationName = Release; 502 | }; 503 | /* End XCConfigurationList section */ 504 | }; 505 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 506 | } 507 | --------------------------------------------------------------------------------