├── 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 ├── Runner.xcodeproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ ├── xcshareddata │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ └── project.pbxproj └── .gitignore ├── images ├── logo.png └── table.png ├── android ├── key.properties ├── 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 │ │ │ │ ├── values │ │ │ │ │ └── styles.xml │ │ │ │ └── drawable │ │ │ │ │ └── launch_background.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── dezeleven │ │ │ │ │ └── food_course │ │ │ │ │ └── MainActivity.kt │ │ │ └── AndroidManifest.xml │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── google-services.json │ └── build.gradle ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── settings.gradle └── build.gradle ├── lib ├── scr │ ├── screens │ │ ├── search.dart │ │ ├── splash.dart │ │ ├── order.dart │ │ ├── product_search.dart │ │ ├── restaurants_search.dart │ │ ├── category.dart │ │ ├── details.dart │ │ ├── login.dart │ │ ├── registration.dart │ │ ├── restaurant.dart │ │ ├── home.dart │ │ └── cart.dart │ ├── helpers │ │ ├── style.dart │ │ ├── screen_navigation.dart │ │ ├── category.dart │ │ ├── user.dart │ │ ├── order.dart │ │ ├── restaurant.dart │ │ └── product.dart │ ├── widgets │ │ ├── small_floating_button.dart │ │ ├── loading.dart │ │ ├── custom_text.dart │ │ ├── bottom_navigation_icons.dart │ │ ├── likeWidget.dart │ │ ├── categories.dart │ │ ├── restaurant.dart │ │ ├── product.dart │ │ └── featured_products.dart │ ├── providers │ │ ├── category.dart │ │ ├── restaurant.dart │ │ ├── app.dart │ │ ├── product.dart │ │ └── user.dart │ └── models │ │ ├── category.dart │ │ ├── restaurant.dart │ │ ├── order.dart │ │ ├── cart_item.dart │ │ ├── user.dart │ │ └── products.dart └── main.dart ├── .metadata ├── README.md ├── .gitignore ├── 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" -------------------------------------------------------------------------------- /images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Santos-Enoque/food_app_course/HEAD/images/logo.png -------------------------------------------------------------------------------- /images/table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Santos-Enoque/food_app_course/HEAD/images/table.png -------------------------------------------------------------------------------- /android/key.properties: -------------------------------------------------------------------------------- 1 | storePassword=android 2 | keyPassword=android 3 | keyAlias=key 4 | storeFile=c:/Users/Santos/key.jks 5 | -------------------------------------------------------------------------------- /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/Santos-Enoque/food_app_course/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/Santos-Enoque/food_app_course/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/Santos-Enoque/food_app_course/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/Santos-Enoque/food_app_course/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/Santos-Enoque/food_app_course/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Santos-Enoque/food_app_course/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Santos-Enoque/food_app_course/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Santos-Enoque/food_app_course/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Santos-Enoque/food_app_course/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/Santos-Enoque/food_app_course/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/Santos-Enoque/food_app_course/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/Santos-Enoque/food_app_course/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/Santos-Enoque/food_app_course/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/Santos-Enoque/food_app_course/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/Santos-Enoque/food_app_course/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/Santos-Enoque/food_app_course/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/Santos-Enoque/food_app_course/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/Santos-Enoque/food_app_course/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/Santos-Enoque/food_app_course/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/Santos-Enoque/food_app_course/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/Santos-Enoque/food_app_course/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Santos-Enoque/food_app_course/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/Santos-Enoque/food_app_course/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /lib/scr/screens/search.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class SearchScreen extends StatelessWidget { 4 | @override 5 | Widget build(BuildContext context) { 6 | return Scaffold( 7 | 8 | ); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /lib/scr/helpers/style.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | const Color primary = Colors.deepOrange; 4 | const red = Colors.red; 5 | const Color white = Colors.white; 6 | const Color black = Colors.black; 7 | const Color grey = Colors.grey; 8 | const Color green = Colors.green; 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.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: 27321ebbad34b0a3fafe99fac037102196d655ff 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. -------------------------------------------------------------------------------- /lib/scr/helpers/screen_navigation.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | void changeScreen(BuildContext context, Widget widget) { 4 | Navigator.push(context, MaterialPageRoute(builder: (context) => widget)); 5 | } 6 | 7 | // request here 8 | void changeScreenReplacement(BuildContext context, Widget widget) { 9 | Navigator.push(context, MaterialPageRoute(builder: (context) => widget)); 10 | } 11 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /lib/scr/widgets/small_floating_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../helpers/style.dart'; 4 | 5 | 6 | class SmallButton extends StatelessWidget { 7 | final IconData icon; 8 | 9 | SmallButton(this.icon); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return Padding( 14 | padding: const EdgeInsets.all(8.0), 15 | child: Container( 16 | ), 17 | ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lib/scr/widgets/loading.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_spinkit/flutter_spinkit.dart'; 3 | import 'package:food_course/scr/helpers/style.dart'; 4 | 5 | class Loading extends StatelessWidget { 6 | @override 7 | Widget build(BuildContext context) { 8 | return Container( 9 | color: white, 10 | child: SpinKitFadingCircle( 11 | color: black, 12 | size: 30, 13 | ) 14 | ); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /lib/scr/providers/category.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../helpers/category.dart'; 3 | import '../models/category.dart'; 4 | 5 | class CategoryProvider with ChangeNotifier{ 6 | CategoryServices _categoryServices = CategoryServices(); 7 | List categories = []; 8 | 9 | CategoryProvider.initialize(){ 10 | loadCategories(); 11 | } 12 | 13 | loadCategories()async{ 14 | categories = await _categoryServices.getCategories(); 15 | notifyListeners(); 16 | } 17 | } -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/dezeleven/food_course/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.dezeleven.food_course 2 | 3 | import androidx.annotation.NonNull; 4 | import io.flutter.embedding.android.FlutterActivity 5 | import io.flutter.embedding.engine.FlutterEngine 6 | import io.flutter.plugins.GeneratedPluginRegistrant 7 | 8 | class MainActivity: FlutterActivity() { 9 | override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { 10 | GeneratedPluginRegistrant.registerWith(flutterEngine); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /lib/scr/models/category.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | 3 | class CategoryModel { 4 | static const ID = "id"; 5 | static const NAME = "name"; 6 | static const IMAGE = "image"; 7 | 8 | int _id; 9 | String _name; 10 | String _image; 11 | 12 | // getters 13 | int get id => _id; 14 | 15 | String get name => _name; 16 | 17 | String get image => _image; 18 | 19 | CategoryModel.fromSnapshot(DocumentSnapshot snapshot){ 20 | _id = snapshot.data[ID]; 21 | _name = snapshot.data[NAME]; 22 | _image = snapshot.data[IMAGE]; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # food_course 2 | 3 | A new Flutter application. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /lib/scr/helpers/category.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import '../models/category.dart'; 3 | 4 | class CategoryServices { 5 | String collection = "categories"; 6 | Firestore _firestore = Firestore.instance; 7 | 8 | Future> getCategories() async => 9 | _firestore.collection(collection).getDocuments().then((result) { 10 | List categories = []; 11 | for(DocumentSnapshot category in result.documents){ 12 | categories.add(CategoryModel.fromSnapshot(category)); 13 | } 14 | return categories; 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 | -------------------------------------------------------------------------------- /lib/scr/widgets/custom_text.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../helpers/style.dart'; 3 | 4 | class CustomText extends StatelessWidget { 5 | final String text; 6 | final double size; 7 | final Color color; 8 | final FontWeight weight; 9 | 10 | // name constructor that has a positional parameters with the text required 11 | // and the other parameters optional 12 | CustomText({@required this.text, this.size,this.color,this.weight}); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return Text( 17 | text,style: TextStyle(fontSize: size ?? 16, color: color ?? black, fontWeight: weight ?? FontWeight.normal), 18 | ); 19 | } 20 | } -------------------------------------------------------------------------------- /lib/scr/screens/splash.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:food_course/scr/helpers/style.dart'; 3 | import 'package:food_course/scr/widgets/custom_text.dart'; 4 | import 'package:food_course/scr/widgets/loading.dart'; 5 | 6 | class Splash extends StatefulWidget { 7 | @override 8 | _SplashState createState() => _SplashState(); 9 | } 10 | 11 | class _SplashState extends State { 12 | @override 13 | Widget build(BuildContext context) { 14 | return Scaffold( 15 | backgroundColor: white, 16 | body:Column( 17 | mainAxisAlignment: MainAxisAlignment.center, 18 | children: [ 19 | CustomText(text: "Loading"), 20 | Loading(), 21 | ], 22 | ) 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | /build/ 32 | 33 | # Web related 34 | lib/generated_plugin_registrant.dart 35 | 36 | # Exceptions to above rules. 37 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 38 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.50' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:3.5.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | classpath 'com.google.gms:google-services:4.3.3' 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/scr/widgets/bottom_navigation_icons.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:food_course/scr/widgets/custom_text.dart'; 3 | 4 | class BottomNavIcon extends StatelessWidget { 5 | final String image; 6 | final String name; 7 | final Function onTap; 8 | 9 | const BottomNavIcon({Key key, this.image, this.name, this.onTap}) : super(key: key); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return Padding( 14 | padding: const EdgeInsets.all(8.0), 15 | child: GestureDetector( 16 | onTap: onTap ?? null, 17 | child: Column( 18 | children: [ 19 | Image.asset("images/$image",width: 20,height: 20,), 20 | SizedBox(height: 2,), 21 | CustomText(text: name,) 22 | ], 23 | ), 24 | ), 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /lib/scr/widgets/likeWidget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:food_course/scr/helpers/style.dart'; 3 | 4 | class LikeWidget extends StatelessWidget { 5 | @override 6 | Widget build(BuildContext context) { 7 | return Padding( 8 | padding: EdgeInsets.all(8), 9 | child: Container( 10 | decoration: BoxDecoration( 11 | borderRadius: 12 | BorderRadius.circular(20), 13 | color: white, 14 | boxShadow: [ 15 | BoxShadow( 16 | color: Colors.grey[300], 17 | offset: Offset(1, 1), 18 | blurRadius: 4), 19 | ]), 20 | child: Padding( 21 | padding: const EdgeInsets.all(4.0), 22 | child: Icon( 23 | Icons.favorite_border, 24 | color: red, 25 | size: 18, 26 | ), 27 | ), 28 | ), 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/scr/providers/restaurant.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../helpers/restaurant.dart'; 3 | import '../models/restaurant.dart'; 4 | 5 | class RestaurantProvider with ChangeNotifier{ 6 | RestaurantServices _restaurantServices = RestaurantServices(); 7 | List restaurants = []; 8 | List searchedRestaurants = []; 9 | 10 | RestaurantModel restaurant; 11 | 12 | RestaurantProvider.initialize(){ 13 | loadRestaurants(); 14 | } 15 | 16 | loadRestaurants()async{ 17 | restaurants = await _restaurantServices.getRestaurants(); 18 | notifyListeners(); 19 | } 20 | 21 | loadSingleRestaurant({String retaurantId}) async{ 22 | restaurant = await _restaurantServices.getRestaurantById(id: retaurantId); 23 | notifyListeners(); 24 | } 25 | 26 | Future search({String name})async{ 27 | searchedRestaurants = await _restaurantServices.searchRestaurant(restaurantName: name); 28 | print("RESTOS ARE: ${searchedRestaurants.length}"); 29 | notifyListeners(); 30 | } 31 | } -------------------------------------------------------------------------------- /android/app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "752818674694", 4 | "firebase_url": "https://foodapp-ee4f1.firebaseio.com", 5 | "project_id": "foodapp-ee4f1", 6 | "storage_bucket": "foodapp-ee4f1.appspot.com" 7 | }, 8 | "client": [ 9 | { 10 | "client_info": { 11 | "mobilesdk_app_id": "1:752818674694:android:112f5ce725096ae00bf787", 12 | "android_client_info": { 13 | "package_name": "com.dezeleven.food_course" 14 | } 15 | }, 16 | "oauth_client": [ 17 | { 18 | "client_id": "752818674694-bhfd4m2ck3vfabqj08r0uholac3bpspj.apps.googleusercontent.com", 19 | "client_type": 3 20 | } 21 | ], 22 | "api_key": [ 23 | { 24 | "current_key": "AIzaSyAm1hjOoZc8dJc8lIhXLzZalQLx4IWJJTw" 25 | } 26 | ], 27 | "services": { 28 | "appinvite_service": { 29 | "other_platform_oauth_client": [ 30 | { 31 | "client_id": "752818674694-bhfd4m2ck3vfabqj08r0uholac3bpspj.apps.googleusercontent.com", 32 | "client_type": 3 33 | } 34 | ] 35 | } 36 | } 37 | } 38 | ], 39 | "configuration_version": "1" 40 | } -------------------------------------------------------------------------------- /lib/scr/models/restaurant.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | 3 | class RestaurantModel { 4 | static const ID = "id"; 5 | static const NAME = "name"; 6 | static const AVG_PRICE = "avgPrice"; 7 | static const RATING = "rating"; 8 | static const RATES = "rates"; 9 | static const IMAGE = "image"; 10 | static const POPULAR = "popular"; 11 | static const USER_LIKES = "userLikes"; 12 | 13 | 14 | 15 | String _id; 16 | String _name; 17 | String _image; 18 | List _userLikes; 19 | double _rating; 20 | double _avgPrice; 21 | bool _popular; 22 | int _rates; 23 | 24 | // getters 25 | String get id => _id; 26 | 27 | String get name => _name; 28 | 29 | String get image => _image; 30 | 31 | List get userLikes => _userLikes; 32 | 33 | double get avgPrice => _avgPrice; 34 | 35 | double get rating => _rating; 36 | 37 | bool get popular => _popular; 38 | 39 | int get rates => _rates; 40 | 41 | // public variable 42 | bool liked = false; 43 | 44 | 45 | RestaurantModel.fromSnapshot(DocumentSnapshot snapshot) { 46 | _id = snapshot.data[ID]; 47 | _name = snapshot.data[NAME]; 48 | _image = snapshot.data[IMAGE]; 49 | _avgPrice = snapshot.data[AVG_PRICE]; 50 | _rating = snapshot.data[RATING]; 51 | _popular = snapshot.data[POPULAR]; 52 | _rates = snapshot.data[RATES]; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lib/scr/models/order.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | 3 | class OrderModel{ 4 | static const ID = "id"; 5 | static const DESCRIPTION = "description"; 6 | static const CART = "cart"; 7 | static const USER_ID = "userId"; 8 | static const TOTAL = "total"; 9 | static const STATUS = "status"; 10 | static const CREATED_AT = "createdAt"; 11 | static const RESTAURANT_ID = "restaurantId"; 12 | 13 | 14 | String _id; 15 | String _restaurantId; 16 | String _description; 17 | String _userId; 18 | String _status; 19 | int _createdAt; 20 | int _total; 21 | 22 | // getters 23 | String get id => _id; 24 | String get restaurantId => _restaurantId; 25 | String get description => _description; 26 | String get userId => _userId; 27 | String get status => _status; 28 | int get total => _total; 29 | int get createdAt => _createdAt; 30 | 31 | // public variable 32 | List cart; 33 | 34 | 35 | OrderModel.fromSnapshot(DocumentSnapshot snapshot){ 36 | _id = snapshot.data[ID]; 37 | _description = snapshot.data[DESCRIPTION]; 38 | _total = snapshot.data[TOTAL]; 39 | _status = snapshot.data[STATUS]; 40 | _userId = snapshot.data[USER_ID]; 41 | _createdAt = snapshot.data[CREATED_AT]; 42 | _restaurantId = snapshot.data[RESTAURANT_ID]; 43 | cart = snapshot.data[CART]; 44 | } 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | } -------------------------------------------------------------------------------- /lib/scr/helpers/user.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import 'package:food_course/scr/models/cart_item.dart'; 3 | import 'package:food_course/scr/models/user.dart'; 4 | 5 | class UserServices{ 6 | String collection = "users"; 7 | Firestore _firestore = Firestore.instance; 8 | 9 | void createUser(Map values) { 10 | String id = values["id"]; 11 | _firestore.collection(collection).document(id).setData(values); 12 | } 13 | 14 | void updateUserData(Map values){ 15 | _firestore.collection(collection).document(values['id']).updateData(values); 16 | } 17 | 18 | 19 | void addToCart({String userId, CartItemModel cartItem}){ 20 | print("THE USER ID IS: $userId"); 21 | print("cart items are: ${cartItem.toString()}"); 22 | _firestore.collection(collection).document(userId).updateData({ 23 | "cart": FieldValue.arrayUnion([cartItem.toMap()]) 24 | }); 25 | } 26 | 27 | void removeFromCart({String userId, CartItemModel cartItem}){ 28 | print("THE USER ID IS: $userId"); 29 | print("cart items are: ${cartItem.toString()}"); 30 | _firestore.collection(collection).document(userId).updateData({ 31 | "cart": FieldValue.arrayRemove([cartItem.toMap()]) 32 | }); 33 | } 34 | 35 | 36 | Future getUserById(String id) => _firestore.collection(collection).document(id).get().then((doc){ 37 | return UserModel.fromSnapshot(doc); 38 | }); 39 | } -------------------------------------------------------------------------------- /lib/scr/helpers/order.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import 'package:food_course/scr/models/cart_item.dart'; 3 | import 'package:food_course/scr/models/order.dart'; 4 | 5 | class OrderServices{ 6 | String collection = "orders"; 7 | Firestore _firestore = Firestore.instance; 8 | 9 | void createOrder({String userId ,String id,String description,String status ,List cart, int totalPrice}) { 10 | List convertedCart = []; 11 | List restaurantIds = []; 12 | 13 | for(CartItemModel item in cart){ 14 | convertedCart.add(item.toMap()); 15 | restaurantIds.add(item.restaurantId); 16 | } 17 | 18 | 19 | _firestore.collection(collection).document(id).setData({ 20 | "userId": userId, 21 | "id": id, 22 | "restaurantIds": restaurantIds, 23 | "cart": convertedCart, 24 | "total": totalPrice, 25 | "createdAt": DateTime.now().millisecondsSinceEpoch, 26 | "description": description, 27 | "status": status 28 | }); 29 | } 30 | 31 | Future> getUserOrders({String userId}) async => 32 | _firestore 33 | .collection(collection) 34 | .where("userId", isEqualTo: userId) 35 | .getDocuments() 36 | .then((result) { 37 | List orders = []; 38 | for (DocumentSnapshot order in result.documents) { 39 | orders.add(OrderModel.fromSnapshot(order)); 40 | } 41 | return orders; 42 | }); 43 | 44 | } -------------------------------------------------------------------------------- /lib/scr/helpers/restaurant.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import '../models/restaurant.dart'; 3 | 4 | class RestaurantServices { 5 | String collection = "restaurants"; 6 | Firestore _firestore = Firestore.instance; 7 | 8 | Future> getRestaurants() async => 9 | _firestore.collection(collection).getDocuments().then((result) { 10 | List restaurants = []; 11 | for(DocumentSnapshot restaurant in result.documents){ 12 | restaurants.add(RestaurantModel.fromSnapshot(restaurant)); 13 | } 14 | return restaurants; 15 | }); 16 | 17 | Future getRestaurantById({String id}) => _firestore.collection(collection).document(id.toString()).get().then((doc){ 18 | return RestaurantModel.fromSnapshot(doc); 19 | }); 20 | 21 | Future> searchRestaurant({String restaurantName}) { 22 | // code to convert the first character to uppercase 23 | String searchKey = restaurantName[0].toUpperCase() + restaurantName.substring(1); 24 | return _firestore 25 | .collection(collection) 26 | .orderBy("name") 27 | .startAt([searchKey]) 28 | .endAt([searchKey + '\uf8ff']) 29 | .getDocuments() 30 | .then((result) { 31 | List restaurants = []; 32 | for (DocumentSnapshot product in result.documents) { 33 | restaurants.add(RestaurantModel.fromSnapshot(product)); 34 | } 35 | return restaurants; 36 | }); 37 | } 38 | } -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 8 | 12 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /lib/scr/models/cart_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | 3 | class CartItemModel { 4 | static const ID = "id"; 5 | static const NAME = "name"; 6 | static const IMAGE = "image"; 7 | static const PRODUCT_ID = "productId"; 8 | static const QUANTITY = "quantity"; 9 | static const PRICE = "price"; 10 | static const RESTAURANT_ID = "restaurantId"; 11 | static const TOTAL_RESTAURANT_SALES = "totalRestaurantSale"; 12 | 13 | 14 | 15 | String _id; 16 | String _name; 17 | String _image; 18 | String _productId; 19 | String _restaurantId; 20 | int _totalRestaurantSale; 21 | int _quantity; 22 | int _price; 23 | 24 | 25 | 26 | // getters 27 | String get id => _id; 28 | 29 | String get name => _name; 30 | 31 | String get image => _image; 32 | 33 | String get productId => _productId; 34 | 35 | String get restaurantId => _restaurantId; 36 | 37 | int get price => _price; 38 | 39 | int get totalRestaurantSale => _totalRestaurantSale; 40 | 41 | int get quantity => _quantity; 42 | 43 | 44 | CartItemModel.fromMap(Map data){ 45 | _id = data[ID]; 46 | _name = data[NAME]; 47 | _image = data[IMAGE]; 48 | _productId = data[PRODUCT_ID]; 49 | _price = data[PRICE]; 50 | _quantity = data[QUANTITY]; 51 | _totalRestaurantSale = data[TOTAL_RESTAURANT_SALES]; 52 | _restaurantId = data[RESTAURANT_ID]; 53 | } 54 | 55 | Map toMap() => { 56 | ID: _id, 57 | IMAGE: _image, 58 | NAME: _name, 59 | PRODUCT_ID: _productId, 60 | QUANTITY: _quantity, 61 | PRICE: _price, 62 | RESTAURANT_ID: _restaurantId, 63 | TOTAL_RESTAURANT_SALES: _totalRestaurantSale 64 | }; 65 | } 66 | -------------------------------------------------------------------------------- /lib/scr/screens/order.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:food_course/scr/helpers/style.dart'; 3 | import 'package:food_course/scr/models/order.dart'; 4 | import 'package:food_course/scr/providers/app.dart'; 5 | import 'package:food_course/scr/providers/user.dart'; 6 | import 'package:food_course/scr/widgets/custom_text.dart'; 7 | import 'package:provider/provider.dart'; 8 | 9 | class OrdersScreen extends StatelessWidget { 10 | @override 11 | Widget build(BuildContext context) { 12 | final user = Provider.of(context); 13 | final app = Provider.of(context); 14 | return Scaffold( 15 | appBar: AppBar( 16 | iconTheme: IconThemeData(color: black), 17 | backgroundColor: white, 18 | elevation: 0.0, 19 | title: CustomText(text: "Orders"), 20 | leading: IconButton( 21 | icon: Icon(Icons.close), 22 | onPressed: () { 23 | Navigator.pop(context); 24 | }), 25 | ), 26 | backgroundColor: white, 27 | body: ListView.builder( 28 | itemCount: user.orders.length, 29 | itemBuilder: (_, index){ 30 | OrderModel _order = user.orders[index]; 31 | return ListTile( 32 | leading: CustomText( 33 | text: "\$${_order.total / 100}", 34 | weight: FontWeight.bold, 35 | ), 36 | title: Text(_order.description), 37 | subtitle: Text(DateTime.fromMillisecondsSinceEpoch(_order.createdAt).toString()), 38 | trailing: CustomText(text: _order.status, color: green,), 39 | ); 40 | }), 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /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 | food_course 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/scr/providers/app.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | enum SearchBy{PRODUCTS, RESTAURANTS} 4 | 5 | class AppProvider with ChangeNotifier{ 6 | bool isLoading = false; 7 | SearchBy search = SearchBy.PRODUCTS; 8 | String filterBy = "Products"; 9 | int totalPrice = 0; 10 | int priceSum = 0; 11 | int quantitySum = 0; 12 | 13 | void changeLoading(){ 14 | isLoading = !isLoading; 15 | notifyListeners(); 16 | } 17 | 18 | void changeSearchBy({SearchBy newSearchBy}){ 19 | search = newSearchBy; 20 | if(newSearchBy == SearchBy.PRODUCTS){ 21 | filterBy = "Products"; 22 | }else{ 23 | filterBy = "Restaurants"; 24 | } 25 | notifyListeners(); 26 | } 27 | 28 | addPrice({int newPrice}){ 29 | priceSum += newPrice; 30 | notifyListeners(); 31 | } 32 | 33 | addQuantity({int newQuantity}){ 34 | quantitySum += newQuantity; 35 | notifyListeners(); 36 | } 37 | 38 | getTotalPrice(){ 39 | print("THE TOTAL SUM IS: $priceSum"); 40 | print("THE TOTAL SUM IS: $priceSum"); 41 | print("THE TOTAL SUM IS: $priceSum"); 42 | print("THE TOTAL SUM IS: $priceSum"); 43 | print("THE QUANTITY SUM IS: $quantitySum"); 44 | print("THE QUANTITY SUM IS: $quantitySum"); 45 | print("THE QUANTITY SUM IS: $quantitySum"); 46 | print("THE QUANTITY SUM IS: $quantitySum"); 47 | 48 | 49 | totalPrice = priceSum * quantitySum; 50 | print("THE TOTAL AMOUNT IS: $totalPrice"); 51 | print("THE TOTAL AMOUNT IS: $totalPrice"); 52 | print("THE TOTAL AMOUNT IS: $totalPrice"); 53 | print("THE TOTAL AMOUNT IS: $totalPrice"); 54 | print("THE TOTAL AMOUNT IS: $totalPrice"); 55 | 56 | 57 | 58 | notifyListeners(); 59 | } 60 | 61 | } -------------------------------------------------------------------------------- /lib/scr/models/user.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import 'package:food_course/scr/models/cart_item.dart'; 3 | 4 | class UserModel{ 5 | static const ID = "id"; 6 | static const NAME = "name"; 7 | static const EMAIL = "email"; 8 | static const STRIPE_ID = "stripeId"; 9 | static const CART = "cart"; 10 | 11 | 12 | 13 | String _name; 14 | String _email; 15 | String _id; 16 | String _stripeId; 17 | int _priceSum = 0; 18 | int _quantitySum = 0; 19 | 20 | 21 | // getters 22 | String get name => _name; 23 | String get email => _email; 24 | String get id => _id; 25 | String get stripeId => _stripeId; 26 | 27 | // public variable 28 | List cart; 29 | int totalCartPrice; 30 | 31 | UserModel.fromSnapshot(DocumentSnapshot snapshot){ 32 | _name = snapshot.data[NAME]; 33 | _email = snapshot.data[EMAIL]; 34 | _id = snapshot.data[ID]; 35 | _stripeId = snapshot.data[STRIPE_ID]; 36 | cart = _convertCartItems(snapshot.data[CART]) ?? []; 37 | totalCartPrice = snapshot.data[CART] == null ? 0 :getTotalPrice(cart: snapshot.data[CART]); 38 | } 39 | 40 | int getTotalPrice({List cart}){ 41 | if(cart == null){ 42 | return 0; 43 | } 44 | for(Map cartItem in cart){ 45 | _priceSum += cartItem["price"] * cartItem["quantity"]; 46 | } 47 | 48 | int total = _priceSum; 49 | 50 | print("THE TOTAL IS $total"); 51 | print("THE TOTAL IS $total"); 52 | print("THE TOTAL IS $total"); 53 | print("THE TOTAL IS $total"); 54 | print("THE TOTAL IS $total"); 55 | 56 | return total; 57 | } 58 | 59 | List _convertCartItems(List cart){ 60 | List convertedCart = []; 61 | for(Map cartItem in cart){ 62 | convertedCart.add(CartItemModel.fromMap(cartItem)); 63 | } 64 | return convertedCart; 65 | } 66 | } -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:food_course/scr/providers/app.dart'; 3 | import 'package:food_course/scr/providers/category.dart'; 4 | import 'package:food_course/scr/providers/product.dart'; 5 | import 'package:food_course/scr/providers/restaurant.dart'; 6 | import 'package:food_course/scr/providers/user.dart'; 7 | import 'package:food_course/scr/screens/home.dart'; 8 | import 'package:food_course/scr/screens/login.dart'; 9 | import 'package:food_course/scr/screens/splash.dart'; 10 | import 'package:food_course/scr/widgets/loading.dart'; 11 | import 'package:provider/provider.dart'; 12 | 13 | void main() { 14 | WidgetsFlutterBinding.ensureInitialized(); 15 | runApp(MultiProvider( 16 | providers: [ 17 | ChangeNotifierProvider.value(value: AppProvider()), 18 | ChangeNotifierProvider.value(value: UserProvider.initialize()), 19 | ChangeNotifierProvider.value(value: CategoryProvider.initialize()), 20 | ChangeNotifierProvider.value(value: RestaurantProvider.initialize()), 21 | ChangeNotifierProvider.value(value: ProductProvider.initialize()), 22 | ], 23 | child: MaterialApp( 24 | debugShowCheckedModeBanner: false, 25 | title: 'Food App', 26 | theme: ThemeData( 27 | primarySwatch: Colors.red, 28 | ), 29 | home: ScreensController()))); 30 | } 31 | 32 | class ScreensController extends StatelessWidget { 33 | @override 34 | Widget build(BuildContext context) { 35 | final auth = Provider.of(context); 36 | switch (auth.status) { 37 | case Status.Uninitialized: 38 | return Splash(); 39 | case Status.Unauthenticated: 40 | case Status.Authenticating: 41 | return LoginScreen(); 42 | case Status.Authenticated: 43 | return Home(); 44 | default: 45 | return LoginScreen(); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/scr/models/products.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | 3 | class ProductModel { 4 | static const ID = "id"; 5 | static const NAME = "name"; 6 | static const RATING = "rating"; 7 | static const IMAGE = "image"; 8 | static const PRICE = "price"; 9 | static const RESTAURANT_ID = "restaurantId"; 10 | static const RESTAURANT = "restaurant"; 11 | static const DESCRIPTION = "description"; 12 | static const CATEGORY = "category"; 13 | static const FEATURED = "featured"; 14 | static const RATES = "rates"; 15 | static const USER_LIKES = "userLikes"; 16 | 17 | 18 | String _id; 19 | String _name; 20 | String _restaurantId; 21 | String _restaurant; 22 | String _category; 23 | String _image; 24 | String _description; 25 | 26 | double _rating; 27 | int _price; 28 | int _rates; 29 | 30 | bool _featured; 31 | 32 | String get id => _id; 33 | 34 | String get name => _name; 35 | 36 | String get restaurant => _restaurant; 37 | 38 | String get restaurantId => _restaurantId; 39 | 40 | String get category => _category; 41 | 42 | String get description => _description; 43 | 44 | String get image => _image; 45 | 46 | 47 | 48 | double get rating => _rating; 49 | 50 | int get price => _price; 51 | 52 | bool get featured => _featured; 53 | 54 | int get rates => _rates; 55 | 56 | // public variable 57 | bool liked = false; 58 | 59 | ProductModel.fromSnapshot(DocumentSnapshot snapshot) { 60 | _id = snapshot.data[ID]; 61 | _image = snapshot.data[IMAGE]; 62 | _restaurant = snapshot.data[RESTAURANT]; 63 | _restaurantId = snapshot.data[RESTAURANT_ID].toString(); 64 | _description = snapshot.data[DESCRIPTION]; 65 | _id = snapshot.data[ID]; 66 | _featured = snapshot.data[FEATURED]; 67 | _price = snapshot.data[PRICE].floor(); 68 | _category = snapshot.data[CATEGORY]; 69 | _rating = snapshot.data[RATING]; 70 | _rates = snapshot.data[RATES]; 71 | _name = snapshot.data[NAME]; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /lib/scr/providers/product.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../helpers/product.dart'; 3 | import '../models/products.dart'; 4 | 5 | class ProductProvider with ChangeNotifier{ 6 | ProductServices _productServices = ProductServices(); 7 | List products = []; 8 | List productsByCategory = []; 9 | List productsByRestaurant = []; 10 | List productsSearched = []; 11 | 12 | 13 | 14 | ProductProvider.initialize(){ 15 | loadProducts(); 16 | } 17 | 18 | loadProducts()async{ 19 | products = await _productServices.getProducts(); 20 | notifyListeners(); 21 | } 22 | 23 | Future loadProductsByCategory({String categoryName})async{ 24 | productsByCategory = await _productServices.getProductsOfCategory(category: categoryName); 25 | notifyListeners(); 26 | } 27 | 28 | Future loadProductsByRestaurant({String restaurantId})async{ 29 | productsByRestaurant = await _productServices.getProductsByRestaurant(id: restaurantId); 30 | notifyListeners(); 31 | } 32 | 33 | // likeDislikeProduct({String userId, ProductModel product, bool liked})async{ 34 | // if(liked){ 35 | // if(product.userLikes.remove(userId)){ 36 | // _productServices.likeOrDislikeProduct(id: product.id, userLikes: product.userLikes); 37 | // }else{ 38 | // print("THE USER WA NOT REMOVED"); 39 | // } 40 | // }else{ 41 | // 42 | // product.userLikes.add(userId); 43 | // _productServices.likeOrDislikeProduct(id: product.id, userLikes: product.userLikes); 44 | // 45 | // 46 | // } 47 | // } 48 | 49 | Future search({String productName})async{ 50 | productsSearched = await _productServices.searchProducts(productName: productName); 51 | print("THE NUMBER OF PRODUCTS DETECTED IS: ${productsSearched.length}"); 52 | print("THE NUMBER OF PRODUCTS DETECTED IS: ${productsSearched.length}"); 53 | print("THE NUMBER OF PRODUCTS DETECTED IS: ${productsSearched.length}"); 54 | 55 | notifyListeners(); 56 | } 57 | 58 | 59 | } -------------------------------------------------------------------------------- /lib/scr/screens/product_search.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:food_course/scr/helpers/screen_navigation.dart'; 3 | import 'package:food_course/scr/helpers/style.dart'; 4 | import 'package:food_course/scr/providers/product.dart'; 5 | import 'package:food_course/scr/screens/details.dart'; 6 | import 'package:food_course/scr/widgets/custom_text.dart'; 7 | import 'package:food_course/scr/widgets/product.dart'; 8 | import 'package:provider/provider.dart'; 9 | 10 | class ProductSearchScreen extends StatelessWidget { 11 | @override 12 | Widget build(BuildContext context) { 13 | final productProvider = Provider.of(context); 14 | 15 | return Scaffold( 16 | appBar: AppBar( 17 | iconTheme: IconThemeData(color: black), 18 | backgroundColor: white, 19 | leading: IconButton(icon: Icon(Icons.close), onPressed: (){ 20 | Navigator.pop(context); 21 | }), 22 | title: CustomText(text: "Products", size: 20,), 23 | elevation: 0.0, 24 | centerTitle: true, 25 | actions: [ 26 | IconButton(icon: Icon(Icons.shopping_cart), onPressed: (){}) 27 | ], 28 | ), 29 | body: productProvider.productsSearched.length < 1? Column( 30 | mainAxisAlignment: MainAxisAlignment.center, 31 | children: [ 32 | Row( 33 | mainAxisAlignment: MainAxisAlignment.center, 34 | children: [ 35 | Icon(Icons.search, color: grey, size: 30,), 36 | ], 37 | ), 38 | SizedBox( 39 | height: 15, 40 | ), 41 | Row( 42 | mainAxisAlignment: MainAxisAlignment.center, 43 | children: [ 44 | CustomText(text: "No products Found", color: grey, weight: FontWeight.w300, size: 22,), 45 | ], 46 | ) 47 | ], 48 | ) : ListView.builder( 49 | itemCount: productProvider.productsSearched.length, 50 | itemBuilder: (context, index){ 51 | return GestureDetector( 52 | onTap: ()async{ 53 | changeScreen(context, Details(product: productProvider.productsSearched[index])); 54 | }, 55 | child: ProductWidget(product: productProvider.productsSearched[index])); 56 | }), 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /lib/scr/helpers/product.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import '../models/products.dart'; 3 | 4 | class ProductServices { 5 | String collection = "products"; 6 | Firestore _firestore = Firestore.instance; 7 | 8 | Future> getProducts() async => 9 | _firestore.collection(collection).getDocuments().then((result) { 10 | List products = []; 11 | for (DocumentSnapshot product in result.documents) { 12 | products.add(ProductModel.fromSnapshot(product)); 13 | } 14 | return products; 15 | }); 16 | 17 | void likeOrDislikeProduct({String id, List userLikes}){ 18 | _firestore.collection(collection).document(id).updateData({ 19 | "userLikes": userLikes 20 | }); 21 | } 22 | 23 | Future> getProductsByRestaurant({String id}) async => 24 | _firestore 25 | .collection(collection) 26 | .where("restaurantId", isEqualTo: id) 27 | .getDocuments() 28 | .then((result) { 29 | List products = []; 30 | for (DocumentSnapshot product in result.documents) { 31 | products.add(ProductModel.fromSnapshot(product)); 32 | } 33 | return products; 34 | }); 35 | 36 | Future> getProductsOfCategory({String category}) async => 37 | _firestore 38 | .collection(collection) 39 | .where("category", isEqualTo: category) 40 | .getDocuments() 41 | .then((result) { 42 | List products = []; 43 | for (DocumentSnapshot product in result.documents) { 44 | products.add(ProductModel.fromSnapshot(product)); 45 | } 46 | return products; 47 | }); 48 | 49 | Future> searchProducts({String productName}) { 50 | // code to convert the first character to uppercase 51 | String searchKey = productName[0].toUpperCase() + productName.substring(1); 52 | return _firestore 53 | .collection(collection) 54 | .orderBy("name") 55 | .startAt([searchKey]) 56 | .endAt([searchKey + '\uf8ff']) 57 | .getDocuments() 58 | .then((result) { 59 | List products = []; 60 | for (DocumentSnapshot product in result.documents) { 61 | products.add(ProductModel.fromSnapshot(product)); 62 | } 63 | return products; 64 | }); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /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/scr/widgets/categories.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:food_course/scr/models/category.dart'; 3 | import 'package:food_course/scr/widgets/loading.dart'; 4 | import 'package:transparent_image/transparent_image.dart'; 5 | 6 | import '../helpers/style.dart'; 7 | import 'custom_text.dart'; 8 | 9 | class CategoryWidget extends StatelessWidget { 10 | final CategoryModel category; 11 | 12 | const CategoryWidget({Key key, this.category}) : super(key: key); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return Padding( 17 | padding: const EdgeInsets.all(6), 18 | child: Stack( 19 | children: [ 20 | Container( 21 | width: 140, 22 | height: 160, 23 | child: ClipRRect( 24 | borderRadius: BorderRadius.circular(30), 25 | child: Stack( 26 | children: [ 27 | Positioned.fill(child: Align( 28 | alignment: Alignment.center, 29 | child: Loading(), 30 | )), 31 | Center( 32 | child: FadeInImage.memoryNetwork(placeholder: kTransparentImage, image: category.image), 33 | ) 34 | ], 35 | )), 36 | ), 37 | 38 | Container( 39 | width: 140, 40 | height: 160, 41 | decoration: BoxDecoration( 42 | borderRadius: BorderRadius.only( 43 | bottomLeft: Radius.circular(30), 44 | bottomRight: Radius.circular(30), 45 | ), 46 | gradient: LinearGradient( 47 | begin: Alignment.bottomCenter, 48 | end: Alignment.topCenter, 49 | colors: [ 50 | Colors.black.withOpacity(0.6), 51 | Colors.black.withOpacity(0.6), 52 | Colors.black.withOpacity(0.6), 53 | Colors.black.withOpacity(0.4), 54 | Colors.black.withOpacity(0.1), 55 | Colors.black.withOpacity(0.05), 56 | Colors.black.withOpacity(0.025), 57 | ], 58 | )), 59 | ), 60 | 61 | Positioned.fill( 62 | child: Align( 63 | alignment: Alignment.center, 64 | child: CustomText(text: category.name, color: white, size: 26, weight: FontWeight.w300,))) 65 | ], 66 | ), 67 | ); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | apply plugin: 'com.google.gms.google-services' 28 | 29 | def keystoreProperties = new Properties() 30 | def keystorePropertiesFile = rootProject.file('key.properties') 31 | if (keystorePropertiesFile.exists()) { 32 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) 33 | } 34 | 35 | android { 36 | compileSdkVersion 28 37 | 38 | sourceSets { 39 | main.java.srcDirs += 'src/main/kotlin' 40 | } 41 | 42 | lintOptions { 43 | disable 'InvalidPackage' 44 | } 45 | 46 | defaultConfig { 47 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 48 | applicationId "com.dezeleven.food_course" 49 | minSdkVersion 19 50 | targetSdkVersion 28 51 | versionCode flutterVersionCode.toInteger() 52 | versionName flutterVersionName 53 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 54 | multiDexEnabled true 55 | } 56 | 57 | signingConfigs { 58 | release { 59 | keyAlias keystoreProperties['keyAlias'] 60 | keyPassword keystoreProperties['keyPassword'] 61 | storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null 62 | storePassword keystoreProperties['storePassword'] 63 | } 64 | } 65 | buildTypes { 66 | release { 67 | signingConfig signingConfigs.release 68 | } 69 | } 70 | } 71 | 72 | flutter { 73 | source '../..' 74 | } 75 | 76 | dependencies { 77 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 78 | testImplementation 'junit:junit:4.12' 79 | androidTestImplementation 'androidx.test:runner:1.1.1' 80 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' 81 | implementation 'com.google.firebase:firebase-analytics:17.2.0' 82 | implementation 'androidx.multidex:multidex:2.0.1' 83 | } 84 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: food_course 2 | description: A new Flutter application. 3 | 4 | # The following defines the version and build number for your application. 5 | # A version number is three numbers separated by dots, like 1.2.43 6 | # followed by an optional build number separated by a +. 7 | # Both the version and the builder number may be overridden in flutter 8 | # build by specifying --build-name and --build-number, respectively. 9 | # In Android, build-name is used as versionName while build-number used as versionCode. 10 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 11 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 12 | # Read more about iOS versioning at 13 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 14 | version: 1.0.0+1 15 | 16 | environment: 17 | sdk: ">=2.1.0 <3.0.0" 18 | 19 | dependencies: 20 | flutter: 21 | sdk: flutter 22 | carousel_pro: ^1.0.0 23 | cloud_firestore: ^0.13.0+1 24 | firebase_auth: ^0.15.3+1 25 | provider: ^4.0.1 26 | transparent_image: ^0.1.0 27 | flutter_spinkit: ^4.1.2 28 | flutter_typeahead: ^1.8.1 29 | uuid: ^2.0.4 30 | stripe_payment: ^1.0.7 31 | 32 | # The following adds the Cupertino Icons font to your application. 33 | # Use with the CupertinoIcons class for iOS style icons. 34 | cupertino_icons: ^0.1.2 35 | 36 | dev_dependencies: 37 | flutter_test: 38 | sdk: flutter 39 | 40 | 41 | # For information on the generic Dart part of this file, see the 42 | # following page: https://dart.dev/tools/pub/pubspec 43 | 44 | # The following section is specific to Flutter. 45 | flutter: 46 | 47 | # The following line ensures that the Material Icons font is 48 | # included with your application, so that you can use the icons in 49 | # the material Icons class. 50 | uses-material-design: true 51 | 52 | # To add assets to your application, add an assets section, like this: 53 | # assets: 54 | # - images/a_dot_burr.jpeg 55 | # - images/a_dot_ham.jpeg 56 | assets: 57 | - images/logo.png 58 | - images/table.png 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 | -------------------------------------------------------------------------------- /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/scr/screens/restaurants_search.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:food_course/scr/helpers/screen_navigation.dart'; 3 | import 'package:food_course/scr/helpers/style.dart'; 4 | import 'package:food_course/scr/providers/app.dart'; 5 | import 'package:food_course/scr/providers/product.dart'; 6 | import 'package:food_course/scr/providers/restaurant.dart'; 7 | import 'package:food_course/scr/screens/restaurant.dart'; 8 | import 'package:food_course/scr/widgets/custom_text.dart'; 9 | import 'package:food_course/scr/widgets/loading.dart'; 10 | import 'package:food_course/scr/widgets/product.dart'; 11 | import 'package:food_course/scr/widgets/restaurant.dart'; 12 | import 'package:provider/provider.dart'; 13 | 14 | class RestaurantsSearchScreen extends StatelessWidget { 15 | @override 16 | Widget build(BuildContext context) { 17 | final restaurantProvider = Provider.of(context); 18 | final productProvider = Provider.of(context); 19 | final app = Provider.of(context); 20 | 21 | return Scaffold( 22 | appBar: AppBar( 23 | iconTheme: IconThemeData(color: black), 24 | backgroundColor: white, 25 | leading: IconButton( 26 | icon: Icon(Icons.close), 27 | onPressed: () { 28 | Navigator.pop(context); 29 | }), 30 | title: CustomText( 31 | text: "Restaurants", 32 | size: 20, 33 | ), 34 | elevation: 0.0, 35 | centerTitle: true, 36 | actions: [ 37 | IconButton(icon: Icon(Icons.shopping_cart), onPressed: () {}) 38 | ], 39 | ), 40 | body: app.isLoading 41 | ? Container( 42 | child: Column( 43 | mainAxisAlignment: MainAxisAlignment.center, 44 | children: [Loading()], 45 | ), 46 | ) 47 | : restaurantProvider.searchedRestaurants.length < 1 48 | ? Column( 49 | mainAxisAlignment: MainAxisAlignment.center, 50 | children: [ 51 | Row( 52 | mainAxisAlignment: MainAxisAlignment.center, 53 | children: [ 54 | Icon( 55 | Icons.search, 56 | color: grey, 57 | size: 30, 58 | ), 59 | ], 60 | ), 61 | SizedBox( 62 | height: 15, 63 | ), 64 | Row( 65 | mainAxisAlignment: MainAxisAlignment.center, 66 | children: [ 67 | CustomText( 68 | text: "No Restaurants Found", 69 | color: grey, 70 | weight: FontWeight.w300, 71 | size: 22, 72 | ), 73 | ], 74 | ) 75 | ], 76 | ) 77 | : ListView.builder( 78 | itemCount: restaurantProvider.searchedRestaurants.length, 79 | itemBuilder: (context, index) { 80 | return GestureDetector( 81 | onTap: () async { 82 | app.changeLoading(); 83 | await productProvider.loadProductsByRestaurant( 84 | restaurantId: restaurantProvider 85 | .searchedRestaurants[index].id); 86 | app.changeLoading(); 87 | 88 | changeScreen( 89 | context, 90 | RestaurantScreen( 91 | restaurantModel: restaurantProvider 92 | .searchedRestaurants[index], 93 | )); 94 | }, 95 | child: RestaurantWidget( 96 | restaurant: 97 | restaurantProvider.searchedRestaurants[index])); 98 | }), 99 | ); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /lib/scr/screens/category.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:food_course/scr/helpers/screen_navigation.dart'; 3 | import 'package:food_course/scr/helpers/style.dart'; 4 | import 'package:food_course/scr/models/category.dart'; 5 | import 'package:food_course/scr/providers/product.dart'; 6 | import 'package:food_course/scr/widgets/custom_text.dart'; 7 | import 'package:food_course/scr/widgets/loading.dart'; 8 | import 'package:food_course/scr/widgets/product.dart'; 9 | import 'package:provider/provider.dart'; 10 | import 'package:transparent_image/transparent_image.dart'; 11 | 12 | import 'details.dart'; 13 | 14 | class CategoryScreen extends StatelessWidget { 15 | final CategoryModel categoryModel; 16 | 17 | const CategoryScreen({Key key, this.categoryModel}) : super(key: key); 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | final productProvider = Provider.of(context); 22 | 23 | return Scaffold( 24 | body: SafeArea( 25 | child: ListView( 26 | children: [ 27 | Stack( 28 | children: [ 29 | Positioned.fill( 30 | child: Align( 31 | alignment: Alignment.center, 32 | child: Loading(), 33 | )), 34 | ClipRRect( 35 | 36 | // borderRadius: BorderRadius.only( 37 | // bottomLeft: Radius.circular(30), 38 | // bottomRight: Radius.circular(30), 39 | // ), 40 | child: FadeInImage.memoryNetwork( 41 | placeholder: kTransparentImage, 42 | image: categoryModel.image, 43 | height: 160, 44 | fit: BoxFit.fill, 45 | width: double.infinity, 46 | ), 47 | ), 48 | Container( 49 | height: 160, 50 | decoration: BoxDecoration( 51 | // borderRadius: BorderRadius.only( 52 | // bottomLeft: Radius.circular(30), 53 | // bottomRight: Radius.circular(30), 54 | // ), 55 | gradient: LinearGradient( 56 | begin: Alignment.bottomCenter, 57 | end: Alignment.topCenter, 58 | colors: [ 59 | Colors.black.withOpacity(0.6), 60 | Colors.black.withOpacity(0.6), 61 | Colors.black.withOpacity(0.6), 62 | Colors.black.withOpacity(0.4), 63 | Colors.black.withOpacity(0.1), 64 | Colors.black.withOpacity(0.05), 65 | Colors.black.withOpacity(0.025), 66 | ], 67 | )), 68 | ), 69 | Positioned.fill( 70 | bottom: 40, 71 | child: Align( 72 | alignment: Alignment.bottomCenter, 73 | child: CustomText(text: categoryModel.name, color: white, size: 26, weight: FontWeight.w300,))), 74 | Positioned.fill( 75 | top: 5, 76 | child: Align( 77 | alignment: Alignment.topLeft, 78 | child: Padding( 79 | padding: const EdgeInsets.all(4), 80 | child: GestureDetector( 81 | onTap: (){ 82 | Navigator.pop(context); 83 | }, 84 | child: Container( 85 | decoration: BoxDecoration( 86 | borderRadius: BorderRadius.circular(20), 87 | color: black.withOpacity(0.2) 88 | ), 89 | child: Icon(Icons.close, color: white,)), 90 | ), 91 | ),)), 92 | 93 | ], 94 | ), 95 | SizedBox( 96 | height: 10, 97 | ), 98 | Column( 99 | children: productProvider.productsByCategory 100 | .map((item) => GestureDetector( 101 | onTap: () { 102 | changeScreen(context, Details(product: item,)); 103 | }, 104 | child: ProductWidget( 105 | product: item, 106 | ), 107 | )) 108 | .toList(), 109 | ) 110 | 111 | ], 112 | 113 | )), 114 | ); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /lib/scr/screens/details.dart: -------------------------------------------------------------------------------- 1 | import 'package:carousel_pro/carousel_pro.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:food_course/scr/helpers/screen_navigation.dart'; 4 | import 'package:food_course/scr/models/products.dart'; 5 | import 'package:food_course/scr/providers/app.dart'; 6 | import 'package:food_course/scr/providers/user.dart'; 7 | import 'package:food_course/scr/screens/cart.dart'; 8 | import 'package:food_course/scr/widgets/custom_text.dart'; 9 | import 'package:food_course/scr/widgets/loading.dart'; 10 | import 'package:provider/provider.dart'; 11 | import 'package:transparent_image/transparent_image.dart'; 12 | 13 | 14 | import '../helpers/style.dart'; 15 | 16 | class Details extends StatefulWidget { 17 | final ProductModel product; 18 | 19 | const Details({@required this.product}); 20 | 21 | 22 | @override 23 | _DetailsState createState() => _DetailsState(); 24 | } 25 | 26 | class _DetailsState extends State
{ 27 | int quantity = 1; 28 | final _key = GlobalKey(); 29 | 30 | @override 31 | Widget build(BuildContext context) { 32 | final user = Provider.of(context); 33 | final app = Provider.of(context); 34 | 35 | return Scaffold( 36 | key: _key, 37 | appBar: AppBar( 38 | iconTheme: IconThemeData(color: black), 39 | backgroundColor: white, 40 | elevation: 0.0, 41 | actions: [ 42 | IconButton( 43 | icon: Icon(Icons.shopping_cart), 44 | onPressed: () { 45 | changeScreen(context, CartScreen()); 46 | }, 47 | ), 48 | 49 | ], 50 | leading: IconButton(icon: Icon(Icons.close), onPressed: (){Navigator.pop(context);}), 51 | ), 52 | backgroundColor: white, 53 | body: SafeArea( 54 | child: app.isLoading ? Loading() : Column( 55 | mainAxisAlignment: MainAxisAlignment.center, 56 | children: [ 57 | CircleAvatar( 58 | radius: 120, 59 | backgroundImage: NetworkImage(widget.product.image), 60 | ), 61 | SizedBox(height: 15,), 62 | 63 | CustomText(text: widget.product.name,size: 26,weight: FontWeight.bold), 64 | CustomText(text: "\$${widget.product.price / 100}",size: 20,weight: FontWeight.w400), 65 | SizedBox(height: 10,), 66 | 67 | CustomText(text: "Description",size: 18,weight: FontWeight.w400), 68 | 69 | Padding( 70 | padding: const EdgeInsets.all(8.0), 71 | child: Text(widget.product.description , textAlign: TextAlign.center, style: TextStyle(color: grey, fontWeight: FontWeight.w300),), 72 | ), 73 | SizedBox(height: 15,), 74 | Row( 75 | mainAxisAlignment: MainAxisAlignment.center, 76 | children: [ 77 | Padding( 78 | padding: const EdgeInsets.all(8.0), 79 | child: IconButton(icon: Icon(Icons.remove,size: 36,), onPressed: (){ 80 | if(quantity != 1){ 81 | setState(() { 82 | quantity -= 1; 83 | }); 84 | } 85 | }), 86 | ), 87 | 88 | GestureDetector( 89 | onTap: ()async{ 90 | app.changeLoading(); 91 | print("All set loading"); 92 | 93 | bool value = await user.addToCard(product: widget.product, quantity: quantity); 94 | if(value){ 95 | print("Item added to cart"); 96 | _key.currentState.showSnackBar( 97 | SnackBar(content: Text("Added ro Cart!")) 98 | ); 99 | user.reloadUserModel(); 100 | app.changeLoading(); 101 | return; 102 | } else{ 103 | print("Item NOT added to cart"); 104 | 105 | } 106 | print("lOADING SET TO FALSE"); 107 | 108 | }, 109 | child: Container( 110 | decoration: BoxDecoration( 111 | color: primary, 112 | borderRadius: BorderRadius.circular(20) 113 | ), 114 | child: app.isLoading ? Loading() : Padding( 115 | padding: const EdgeInsets.fromLTRB(28,12,28,12), 116 | child: CustomText(text: "Add $quantity To Cart",color: white,size: 22,weight: FontWeight.w300,), 117 | ), 118 | 119 | ), 120 | ), 121 | Padding( 122 | padding: const EdgeInsets.all(8.0), 123 | child: IconButton(icon: Icon(Icons.add,size: 36,color: red,), onPressed: (){ 124 | setState(() { 125 | quantity += 1; 126 | }); 127 | }), 128 | ), 129 | ], 130 | ), 131 | 132 | ], 133 | ), 134 | ), 135 | ); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /lib/scr/providers/user.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:cloud_firestore/cloud_firestore.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/widgets.dart'; 5 | import 'package:firebase_auth/firebase_auth.dart'; 6 | import 'package:food_course/scr/helpers/order.dart'; 7 | import 'package:food_course/scr/helpers/user.dart'; 8 | import 'package:food_course/scr/models/cart_item.dart'; 9 | import 'package:food_course/scr/models/order.dart'; 10 | import 'package:food_course/scr/models/products.dart'; 11 | import 'package:food_course/scr/models/user.dart'; 12 | import 'package:uuid/uuid.dart'; 13 | 14 | 15 | enum Status{Uninitialized, Authenticated, Authenticating, Unauthenticated} 16 | 17 | class UserProvider with ChangeNotifier{ 18 | FirebaseAuth _auth; 19 | FirebaseUser _user; 20 | Status _status = Status.Uninitialized; 21 | Firestore _firestore = Firestore.instance; 22 | UserServices _userServicse = UserServices(); 23 | OrderServices _orderServices = OrderServices(); 24 | UserModel _userModel; 25 | 26 | // getter 27 | UserModel get userModel => _userModel; 28 | Status get status => _status; 29 | FirebaseUser get user => _user; 30 | 31 | // public variables 32 | List orders = []; 33 | 34 | final formkey = GlobalKey(); 35 | 36 | TextEditingController email = TextEditingController(); 37 | TextEditingController password = TextEditingController(); 38 | TextEditingController name = TextEditingController(); 39 | 40 | 41 | UserProvider.initialize(): _auth = FirebaseAuth.instance{ 42 | _auth.onAuthStateChanged.listen(_onStateChanged); 43 | } 44 | 45 | Future signIn()async{ 46 | try{ 47 | _status = Status.Authenticating; 48 | notifyListeners(); 49 | await _auth.signInWithEmailAndPassword(email: email.text.trim(), password: password.text.trim()); 50 | return true; 51 | }catch(e){ 52 | _status = Status.Unauthenticated; 53 | notifyListeners(); 54 | print(e.toString()); 55 | return false; 56 | } 57 | } 58 | 59 | 60 | Future signUp()async{ 61 | try{ 62 | _status = Status.Authenticating; 63 | notifyListeners(); 64 | await _auth.createUserWithEmailAndPassword(email: email.text.trim(), password: password.text.trim()).then((result){ 65 | _firestore.collection('users').document(result.user.uid).setData({ 66 | 'name':name.text, 67 | 'email':email.text, 68 | 'uid':result.user.uid, 69 | "likedFood": [], 70 | "likedRestaurants": [] 71 | }); 72 | }); 73 | return true; 74 | }catch(e){ 75 | _status = Status.Unauthenticated; 76 | notifyListeners(); 77 | print(e.toString()); 78 | return false; 79 | } 80 | } 81 | 82 | Future signOut()async{ 83 | _auth.signOut(); 84 | _status = Status.Unauthenticated; 85 | notifyListeners(); 86 | return Future.delayed(Duration.zero); 87 | } 88 | 89 | void clearController(){ 90 | name.text = ""; 91 | password.text = ""; 92 | email.text = ""; 93 | } 94 | 95 | Future reloadUserModel()async{ 96 | _userModel = await _userServicse.getUserById(user.uid); 97 | notifyListeners(); 98 | } 99 | 100 | 101 | Future _onStateChanged(FirebaseUser firebaseUser) async{ 102 | if(firebaseUser == null){ 103 | _status = Status.Unauthenticated; 104 | }else{ 105 | _user = firebaseUser; 106 | _status = Status.Authenticated; 107 | _userModel = await _userServicse.getUserById(user.uid); 108 | } 109 | notifyListeners(); 110 | } 111 | 112 | Future addToCard({ProductModel product, int quantity})async{ 113 | print("THE PRODUC IS: ${product.toString()}"); 114 | print("THE qty IS: ${quantity.toString()}"); 115 | 116 | try{ 117 | var uuid = Uuid(); 118 | String cartItemId = uuid.v4(); 119 | List cart = _userModel.cart; 120 | // bool itemExists = false; 121 | Map cartItem ={ 122 | "id": cartItemId, 123 | "name": product.name, 124 | "image": product.image, 125 | "restaurantId": product.restaurantId, 126 | "totalRestaurantSale": product.price * quantity, 127 | "productId": product.id, 128 | "price": product.price, 129 | "quantity": quantity 130 | }; 131 | 132 | CartItemModel item = CartItemModel.fromMap(cartItem); 133 | // if(!itemExists){ 134 | print("CART ITEMS ARE: ${cart.toString()}"); 135 | _userServicse.addToCart(userId: _user.uid, cartItem: item); 136 | // } 137 | 138 | 139 | 140 | return true; 141 | }catch(e){ 142 | print("THE ERROR ${e.toString()}"); 143 | return false; 144 | } 145 | 146 | } 147 | 148 | getOrders()async{ 149 | orders = await _orderServices.getUserOrders(userId: _user.uid); 150 | notifyListeners(); 151 | } 152 | 153 | Future removeFromCart({CartItemModel cartItem})async{ 154 | print("THE PRODUC IS: ${cartItem.toString()}"); 155 | 156 | try{ 157 | _userServicse.removeFromCart(userId: _user.uid, cartItem: cartItem); 158 | return true; 159 | }catch(e){ 160 | print("THE ERROR ${e.toString()}"); 161 | return false; 162 | } 163 | 164 | } 165 | } -------------------------------------------------------------------------------- /lib/scr/screens/login.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:food_course/scr/helpers/screen_navigation.dart'; 3 | import 'package:food_course/scr/helpers/style.dart'; 4 | import 'package:food_course/scr/providers/category.dart'; 5 | import 'package:food_course/scr/providers/product.dart'; 6 | import 'package:food_course/scr/providers/restaurant.dart'; 7 | import 'package:food_course/scr/providers/user.dart'; 8 | import 'package:food_course/scr/screens/home.dart'; 9 | import 'package:food_course/scr/screens/registration.dart'; 10 | import 'package:food_course/scr/widgets/custom_text.dart'; 11 | import 'package:food_course/scr/widgets/loading.dart'; 12 | import 'package:provider/provider.dart'; 13 | 14 | class LoginScreen extends StatefulWidget { 15 | @override 16 | _LoginScreenState createState() => _LoginScreenState(); 17 | } 18 | 19 | class _LoginScreenState extends State { 20 | final _key = GlobalKey(); 21 | 22 | @override 23 | Widget build(BuildContext context) { 24 | final authProvider = Provider.of(context); 25 | final categoryProvider = Provider.of(context); 26 | final restaurantProvider = Provider.of(context); 27 | final productProvider = Provider.of(context); 28 | 29 | return Scaffold( 30 | key: _key, 31 | backgroundColor: white, 32 | body: authProvider.status == Status.Authenticating? Loading() : SingleChildScrollView( 33 | child: Column( 34 | children: [ 35 | SizedBox( 36 | height: 100, 37 | ), 38 | 39 | Row( 40 | mainAxisAlignment: MainAxisAlignment.center, 41 | children: [ 42 | Image.asset("images/logo.png", width: 120, height: 120,), 43 | ], 44 | ), 45 | 46 | SizedBox( 47 | height: 40, 48 | ), 49 | Padding( 50 | padding: const EdgeInsets.all(12), 51 | child: Container( 52 | decoration: BoxDecoration( 53 | border: Border.all(color: grey), 54 | borderRadius: BorderRadius.circular(15) 55 | ), 56 | child: Padding(padding: EdgeInsets.only(left: 10), 57 | child: TextFormField( 58 | controller: authProvider.email, 59 | decoration: InputDecoration( 60 | border: InputBorder.none, 61 | hintText: "Email", 62 | icon: Icon(Icons.email) 63 | ), 64 | ),), 65 | ), 66 | ), 67 | 68 | Padding( 69 | padding: const EdgeInsets.all(12), 70 | child: Container( 71 | decoration: BoxDecoration( 72 | border: Border.all(color: grey), 73 | borderRadius: BorderRadius.circular(15) 74 | ), 75 | child: Padding(padding: EdgeInsets.only(left: 10), 76 | child: TextFormField( 77 | controller: authProvider.password, 78 | decoration: InputDecoration( 79 | border: InputBorder.none, 80 | hintText: "Password", 81 | icon: Icon(Icons.lock) 82 | ), 83 | ),), 84 | ), 85 | ), 86 | Padding( 87 | padding: const EdgeInsets.all(10), 88 | child: GestureDetector( 89 | onTap: ()async{ 90 | if(!await authProvider.signIn()){ 91 | _key.currentState.showSnackBar( 92 | SnackBar(content: Text("Login failed!")) 93 | ); 94 | return; 95 | } 96 | categoryProvider.loadCategories(); 97 | restaurantProvider.loadSingleRestaurant(); 98 | productProvider.loadProducts(); 99 | authProvider.clearController(); 100 | changeScreenReplacement(context, Home()); 101 | }, 102 | child: Container( 103 | decoration: BoxDecoration( 104 | color: red, 105 | border: Border.all(color: grey), 106 | borderRadius: BorderRadius.circular(15) 107 | ), 108 | child: Padding(padding: EdgeInsets.only(top: 10, bottom: 10), 109 | child: Row( 110 | mainAxisAlignment: MainAxisAlignment.center, 111 | children: [ 112 | CustomText(text: "Login", color: white, size: 22,) 113 | ], 114 | ),), 115 | ), 116 | ), 117 | ), 118 | 119 | GestureDetector( 120 | onTap: (){ 121 | changeScreen(context, RegistrationScreen()); 122 | }, 123 | child: Row( 124 | mainAxisAlignment: MainAxisAlignment.center, 125 | children: [ 126 | CustomText(text: "Register here", size: 20,), 127 | ], 128 | ), 129 | ), 130 | ], 131 | ), 132 | ), 133 | ); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /lib/scr/widgets/restaurant.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:food_course/scr/helpers/style.dart'; 3 | import 'package:food_course/scr/models/restaurant.dart'; 4 | import 'package:food_course/scr/widgets/custom_text.dart'; 5 | import 'package:food_course/scr/widgets/small_floating_button.dart'; 6 | import 'package:transparent_image/transparent_image.dart'; 7 | 8 | import 'loading.dart'; 9 | 10 | class RestaurantWidget extends StatelessWidget { 11 | final RestaurantModel restaurant; 12 | 13 | const RestaurantWidget({Key key, this.restaurant}) : super(key: key); 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return Padding( 18 | padding: const EdgeInsets.only(top:2, left:2, right: 2, bottom: 4), 19 | child: Stack( 20 | children: [ 21 | _backgroundImage(restaurant.image), 22 | Padding( 23 | padding: const EdgeInsets.all(8.0), 24 | child: Row( 25 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 26 | children: [ 27 | SmallButton(Icons.favorite), 28 | Padding( 29 | padding: const EdgeInsets.all(8.0), 30 | child: Container( 31 | width: 50, 32 | decoration: BoxDecoration( 33 | color: white, 34 | borderRadius: BorderRadius.circular(5), 35 | ), 36 | child: Row( 37 | children: [ 38 | Padding( 39 | padding: const EdgeInsets.all(2.0), 40 | child: Icon( 41 | Icons.star, 42 | color: Colors.yellow[900], 43 | size: 20, 44 | ), 45 | ), 46 | Text(restaurant.rating.toString()), 47 | ], 48 | ), 49 | ), 50 | ), 51 | ], 52 | ), 53 | ), 54 | Positioned.fill( 55 | child: Align( 56 | alignment: Alignment.bottomCenter, 57 | child: Container( 58 | height: 100, 59 | decoration: BoxDecoration( 60 | borderRadius: BorderRadius.only( 61 | bottomLeft: Radius.circular(20), 62 | bottomRight: Radius.circular(20), 63 | ), 64 | gradient: LinearGradient( 65 | begin: Alignment.bottomCenter, 66 | end: Alignment.topCenter, 67 | colors: [ 68 | Colors.black.withOpacity(0.8), 69 | Colors.black.withOpacity(0.7), 70 | Colors.black.withOpacity(0.6), 71 | Colors.black.withOpacity(0.4), 72 | Colors.black.withOpacity(0.1), 73 | Colors.black.withOpacity(0.05), 74 | Colors.black.withOpacity(0.025), 75 | ], 76 | )), 77 | ), 78 | )), 79 | Positioned.fill( 80 | child: Align( 81 | alignment: Alignment.bottomCenter, 82 | child: Row( 83 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 84 | children: [ 85 | Padding( 86 | padding: const EdgeInsets.fromLTRB(12, 8, 8, 8), 87 | child: RichText( 88 | text: TextSpan(children: [ 89 | TextSpan( 90 | text: "${restaurant.name} \n", 91 | style: TextStyle( 92 | fontSize: 20, 93 | fontWeight: FontWeight.bold)), 94 | TextSpan( 95 | text: "avg meal price: ", 96 | style: TextStyle( 97 | fontSize: 16, 98 | fontWeight: FontWeight.w300)), 99 | TextSpan( 100 | text: "\$${restaurant.avgPrice} \n", 101 | style: TextStyle(fontSize: 16)), 102 | ], style: TextStyle(color: white)), 103 | ), 104 | ), 105 | ], 106 | ), 107 | )) 108 | ], 109 | ), 110 | ); 111 | } 112 | 113 | Widget _backgroundImage(String image){ 114 | if(image.isEmpty || image == null){ 115 | return Container( 116 | height: 210, 117 | decoration: BoxDecoration( 118 | color: grey.withOpacity(0.8), 119 | borderRadius: BorderRadius.circular(20.0), 120 | ), 121 | child: Center( 122 | child: Image.asset("images/table.png", width: 120,), 123 | ) 124 | ); 125 | }else{ 126 | return Padding( 127 | padding: const EdgeInsets.all(0), 128 | child: ClipRRect( 129 | borderRadius: BorderRadius.circular(20.0), 130 | child: Stack( 131 | children: [ 132 | Positioned.fill(child: Align( 133 | alignment: Alignment.center, 134 | child: Container( 135 | height: 120, 136 | child: Loading()), 137 | )), 138 | Center( 139 | child: FadeInImage.memoryNetwork(placeholder: kTransparentImage, image: restaurant.image), 140 | ) 141 | ], 142 | )), 143 | ); 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /lib/scr/screens/registration.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:food_course/scr/helpers/screen_navigation.dart'; 3 | import 'package:food_course/scr/helpers/style.dart'; 4 | import 'package:food_course/scr/providers/category.dart'; 5 | import 'package:food_course/scr/providers/product.dart'; 6 | import 'package:food_course/scr/providers/restaurant.dart'; 7 | import 'package:food_course/scr/providers/user.dart'; 8 | import 'package:food_course/scr/screens/login.dart'; 9 | import 'package:food_course/scr/widgets/custom_text.dart'; 10 | import 'package:food_course/scr/widgets/loading.dart'; 11 | import 'package:provider/provider.dart'; 12 | 13 | import 'home.dart'; 14 | 15 | class RegistrationScreen extends StatefulWidget { 16 | @override 17 | _RegistrationScreenState createState() => _RegistrationScreenState(); 18 | } 19 | 20 | class _RegistrationScreenState extends State { 21 | final _key = GlobalKey(); 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | final authProvider = Provider.of(context); 26 | final categoryProvider = Provider.of(context); 27 | final restaurantProvider = Provider.of(context); 28 | final productProvider = Provider.of(context); 29 | 30 | return Scaffold( 31 | key: _key, 32 | backgroundColor: white, 33 | body: authProvider.status == Status.Authenticating? Loading() : SingleChildScrollView( 34 | child: Column( 35 | children: [ 36 | SizedBox( 37 | height: 100, 38 | ), 39 | 40 | Row( 41 | mainAxisAlignment: MainAxisAlignment.center, 42 | children: [ 43 | Image.asset("images/logo.png", width: 100, height: 100,), 44 | ], 45 | ), 46 | 47 | SizedBox( 48 | height: 40, 49 | ), 50 | 51 | Padding( 52 | padding: const EdgeInsets.all(12), 53 | child: Container( 54 | decoration: BoxDecoration( 55 | border: Border.all(color: grey), 56 | borderRadius: BorderRadius.circular(15) 57 | ), 58 | child: Padding(padding: EdgeInsets.only(left: 10), 59 | child: TextFormField( 60 | controller: authProvider.name, 61 | decoration: InputDecoration( 62 | border: InputBorder.none, 63 | hintText: "Username", 64 | icon: Icon(Icons.person) 65 | ), 66 | ),), 67 | ), 68 | ), 69 | 70 | 71 | Padding( 72 | padding: const EdgeInsets.all(12), 73 | child: Container( 74 | decoration: BoxDecoration( 75 | border: Border.all(color: grey), 76 | borderRadius: BorderRadius.circular(15) 77 | ), 78 | child: Padding(padding: EdgeInsets.only(left: 10), 79 | child: TextFormField( 80 | controller: authProvider.email, 81 | decoration: InputDecoration( 82 | border: InputBorder.none, 83 | hintText: "Emails", 84 | icon: Icon(Icons.email) 85 | ), 86 | ),), 87 | ), 88 | ), 89 | 90 | Padding( 91 | padding: const EdgeInsets.all(12), 92 | child: Container( 93 | decoration: BoxDecoration( 94 | border: Border.all(color: grey), 95 | borderRadius: BorderRadius.circular(15) 96 | ), 97 | child: Padding(padding: EdgeInsets.only(left: 10), 98 | child: TextFormField( 99 | controller: authProvider.password, 100 | decoration: InputDecoration( 101 | border: InputBorder.none, 102 | hintText: "Password", 103 | icon: Icon(Icons.lock) 104 | ), 105 | ),), 106 | ), 107 | ), 108 | 109 | Padding( 110 | padding: const EdgeInsets.all(10), 111 | child: GestureDetector( 112 | onTap: ()async{ 113 | print("BTN CLICKED!!!!"); 114 | print("BTN CLICKED!!!!"); 115 | print("BTN CLICKED!!!!"); 116 | print("BTN CLICKED!!!!"); 117 | print("BTN CLICKED!!!!"); 118 | print("BTN CLICKED!!!!"); 119 | 120 | if(!await authProvider.signUp()){ 121 | _key.currentState.showSnackBar( 122 | SnackBar(content: Text("Resgistration failed!")) 123 | ); 124 | return; 125 | } 126 | categoryProvider.loadCategories(); 127 | restaurantProvider.loadSingleRestaurant(); 128 | productProvider.loadProducts(); 129 | authProvider.clearController(); 130 | changeScreenReplacement(context, Home()); 131 | }, 132 | child: Container( 133 | decoration: BoxDecoration( 134 | color: red, 135 | border: Border.all(color: grey), 136 | borderRadius: BorderRadius.circular(15) 137 | ), 138 | child: Padding(padding: EdgeInsets.only(top: 10, bottom: 10), 139 | child: Row( 140 | mainAxisAlignment: MainAxisAlignment.center, 141 | children: [ 142 | CustomText(text: "Resgister", color: white, size: 22,) 143 | ], 144 | ),), 145 | ), 146 | ), 147 | ), 148 | 149 | GestureDetector( 150 | onTap: (){ 151 | changeScreen(context, LoginScreen()); 152 | }, 153 | child: Row( 154 | mainAxisAlignment: MainAxisAlignment.center, 155 | children: [ 156 | CustomText(text: "login here here", size: 20,), 157 | ], 158 | ), 159 | ), 160 | 161 | 162 | 163 | 164 | ], 165 | ), 166 | ), 167 | ); 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /lib/scr/widgets/product.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:food_course/scr/helpers/screen_navigation.dart'; 3 | import 'package:food_course/scr/helpers/style.dart'; 4 | import 'package:food_course/scr/models/products.dart'; 5 | import 'package:food_course/scr/providers/product.dart'; 6 | import 'package:food_course/scr/providers/restaurant.dart'; 7 | import 'package:food_course/scr/screens/restaurant.dart'; 8 | import 'package:provider/provider.dart'; 9 | 10 | import 'custom_text.dart'; 11 | 12 | class ProductWidget extends StatelessWidget { 13 | final ProductModel product; 14 | 15 | const ProductWidget({Key key, this.product}) : super(key: key); 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | final restaurantProvider = Provider.of(context); 20 | final productProvider = Provider.of(context); 21 | 22 | 23 | return Padding( 24 | padding: const EdgeInsets.only(left: 4, right: 4, top: 4, bottom: 10), 25 | child: Container( 26 | height: 110, 27 | decoration: BoxDecoration( 28 | color: white, 29 | borderRadius: BorderRadius.circular(20), 30 | boxShadow: [ 31 | BoxShadow( 32 | color: Colors.grey[300], 33 | offset: Offset(-2, -1), 34 | blurRadius: 5), 35 | ] 36 | ), 37 | // height: 160, 38 | child: Row( 39 | children: [ 40 | Container( 41 | width: 140, 42 | height: 120, 43 | child: ClipRRect( 44 | borderRadius: BorderRadius.only( 45 | bottomLeft: Radius.circular(20), 46 | topLeft: Radius.circular(20), 47 | ), 48 | child: Image.network(product.image, fit: BoxFit.fill,), 49 | ), 50 | ), 51 | Expanded( 52 | child: Column( 53 | children: [ 54 | Row( 55 | mainAxisAlignment: 56 | MainAxisAlignment.spaceBetween, 57 | children: [ 58 | Padding( 59 | padding: const EdgeInsets.all(8.0), 60 | child: CustomText( 61 | text: product.name, 62 | ), 63 | ), 64 | Padding( 65 | padding: EdgeInsets.all(8), 66 | child: Container( 67 | decoration: BoxDecoration( 68 | borderRadius: 69 | BorderRadius.circular(20), 70 | color: white, 71 | boxShadow: [ 72 | BoxShadow( 73 | color: Colors.grey[300], 74 | offset: Offset(1, 1), 75 | blurRadius: 4), 76 | ]), 77 | child: Padding( 78 | padding: const EdgeInsets.all(4.0), 79 | child: Icon( 80 | Icons.favorite_border, 81 | color: red, 82 | size: 18, 83 | ), 84 | ), 85 | ), 86 | ) 87 | ], 88 | ), 89 | 90 | SizedBox( 91 | height: 25, 92 | ), 93 | 94 | Padding( 95 | padding: const EdgeInsets.only(left: 4), 96 | child: Row( 97 | children: [ 98 | CustomText(text: "from: ", color: grey, weight: FontWeight.w300, size: 14,), 99 | SizedBox(width: 10,), 100 | GestureDetector( 101 | onTap: ()async{ 102 | await productProvider.loadProductsByRestaurant( 103 | restaurantId: product.restaurantId.toString()); 104 | await restaurantProvider.loadSingleRestaurant(retaurantId: product.restaurantId.toString()); 105 | changeScreen(context, RestaurantScreen(restaurantModel: restaurantProvider.restaurant,)); 106 | }, 107 | child: CustomText(text: product.restaurant, color: primary, weight: FontWeight.w300, size: 14,)), 108 | 109 | ], 110 | ), 111 | ), 112 | Row( 113 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 114 | children: [ 115 | Row( 116 | children: [ 117 | Padding( 118 | padding: const EdgeInsets.only(left: 8.0), 119 | child: CustomText( 120 | text: product.rating.toString(), 121 | color: grey, 122 | size: 14.0, 123 | ), 124 | ), 125 | SizedBox( 126 | width: 2, 127 | ), 128 | Icon( 129 | Icons.star, 130 | color: red, 131 | size: 16, 132 | ), 133 | Icon( 134 | Icons.star, 135 | color: red, 136 | size: 16, 137 | ), 138 | Icon( 139 | Icons.star, 140 | color: red, 141 | size: 16, 142 | ), 143 | Icon( 144 | Icons.star, 145 | color: grey, 146 | size: 16, 147 | ), 148 | ], 149 | ), 150 | Padding( 151 | padding: const EdgeInsets.only(right:8.0), 152 | child: CustomText(text: "\$${ product.price / 100}",weight: FontWeight.bold,), 153 | ), 154 | ], 155 | ), 156 | 157 | 158 | ], 159 | ), 160 | ) 161 | ], 162 | ), 163 | ), 164 | ); 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /lib/scr/widgets/featured_products.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:food_course/scr/helpers/screen_navigation.dart'; 4 | import 'package:food_course/scr/models/products.dart'; 5 | import 'package:food_course/scr/providers/product.dart'; 6 | import 'package:food_course/scr/providers/user.dart'; 7 | import 'package:food_course/scr/screens/details.dart'; 8 | import 'package:provider/provider.dart'; 9 | import 'package:transparent_image/transparent_image.dart'; 10 | 11 | import '../helpers/style.dart'; 12 | import 'custom_text.dart'; 13 | import 'loading.dart'; 14 | 15 | class Featured extends StatefulWidget { 16 | @override 17 | _FeaturedState createState() => _FeaturedState(); 18 | } 19 | 20 | class _FeaturedState extends State { 21 | @override 22 | Widget build(BuildContext context) { 23 | final productProvider = Provider.of(context); 24 | final user = Provider.of(context); 25 | 26 | 27 | return Container( 28 | height: 220, 29 | child: ListView.builder( 30 | scrollDirection: Axis.horizontal, 31 | itemCount: productProvider.products.length, 32 | itemBuilder: (_, index) { 33 | return Padding( 34 | padding: EdgeInsets.fromLTRB(12, 14, 16, 12), 35 | child: GestureDetector( 36 | onTap: () { 37 | changeScreen( 38 | _, 39 | Details( 40 | product: productProvider.products[index], 41 | )); 42 | }, 43 | child: Container( 44 | height: 220, 45 | width: 200, 46 | decoration: BoxDecoration( 47 | color: white, 48 | borderRadius: BorderRadius.circular(20), 49 | boxShadow: [ 50 | BoxShadow( 51 | color: Colors.grey[300], 52 | offset: Offset(-2, -1), 53 | blurRadius: 5), 54 | ]), 55 | child: Column( 56 | children: [ 57 | ClipRRect( 58 | borderRadius: BorderRadius.only( 59 | topLeft: Radius.circular(20), 60 | topRight: Radius.circular(20)), 61 | child: Stack( 62 | children: [ 63 | Positioned.fill( 64 | child: Align( 65 | alignment: Alignment.center, 66 | child: Loading(), 67 | )), 68 | Center( 69 | child: FadeInImage.memoryNetwork( 70 | placeholder: kTransparentImage, 71 | image: productProvider.products[index].image, 72 | height: 126, 73 | ), 74 | ) 75 | ], 76 | ), 77 | ), 78 | Row( 79 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 80 | children: [ 81 | Padding( 82 | padding: const EdgeInsets.all(8.0), 83 | child: CustomText( 84 | text: productProvider.products[index].name ?? 85 | "id null", 86 | ), 87 | ), 88 | Padding( 89 | padding: EdgeInsets.all(8), 90 | child: GestureDetector( 91 | onTap: (){ 92 | // setState(() { 93 | // productProvider.products[index].liked = !productProvider.products[index].liked; 94 | // }); 95 | // productProvider.likeDislikeProduct(userId: user.userModel.id, product: productProvider.products[index], liked: productProvider.products[index].liked); 96 | }, 97 | child: Container(), 98 | ), 99 | ) 100 | ], 101 | ), 102 | Row( 103 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 104 | children: [ 105 | Row( 106 | children: [ 107 | Padding( 108 | padding: const EdgeInsets.only(left: 8.0), 109 | child: CustomText( 110 | text: productProvider.products[index].rating 111 | .toString(), 112 | color: grey, 113 | size: 14.0, 114 | ), 115 | ), 116 | SizedBox( 117 | width: 2, 118 | ), 119 | Icon( 120 | Icons.star, 121 | color: red, 122 | size: 16, 123 | ), 124 | Icon( 125 | Icons.star, 126 | color: red, 127 | size: 16, 128 | ), 129 | Icon( 130 | Icons.star, 131 | color: red, 132 | size: 16, 133 | ), 134 | Icon( 135 | Icons.star, 136 | color: grey, 137 | size: 16, 138 | ), 139 | ], 140 | ), 141 | Padding( 142 | padding: const EdgeInsets.only(right: 8.0), 143 | child: CustomText( 144 | text: 145 | "\$${productProvider.products[index].price / 100}", 146 | weight: FontWeight.bold, 147 | ), 148 | ), 149 | ], 150 | ), 151 | ], 152 | ), 153 | ), 154 | )); 155 | }), 156 | ); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /lib/scr/screens/restaurant.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:food_course/scr/helpers/screen_navigation.dart'; 3 | import 'package:food_course/scr/helpers/style.dart'; 4 | import 'package:food_course/scr/models/category.dart'; 5 | import 'package:food_course/scr/models/restaurant.dart'; 6 | import 'package:food_course/scr/providers/product.dart'; 7 | import 'package:food_course/scr/widgets/custom_text.dart'; 8 | import 'package:food_course/scr/widgets/loading.dart'; 9 | import 'package:food_course/scr/widgets/product.dart'; 10 | import 'package:food_course/scr/widgets/small_floating_button.dart'; 11 | import 'package:provider/provider.dart'; 12 | import 'package:transparent_image/transparent_image.dart'; 13 | 14 | import 'details.dart'; 15 | 16 | class RestaurantScreen extends StatelessWidget { 17 | final RestaurantModel restaurantModel; 18 | 19 | const RestaurantScreen({Key key, this.restaurantModel}) : super(key: key); 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | final productProvider = Provider.of(context); 24 | 25 | return Scaffold( 26 | body: SafeArea( 27 | child: ListView( 28 | children: [ 29 | 30 | Stack( 31 | children: [ 32 | Positioned.fill( 33 | child: Align( 34 | alignment: Alignment.center, 35 | child: Loading(), 36 | )), 37 | 38 | // restaurant image 39 | ClipRRect( 40 | 41 | borderRadius: BorderRadius.only( 42 | bottomLeft: Radius.circular(20), 43 | bottomRight: Radius.circular(20), 44 | ), 45 | child: FadeInImage.memoryNetwork( 46 | placeholder: kTransparentImage, 47 | image: restaurantModel.image, 48 | height: 160, 49 | fit: BoxFit.fill, 50 | width: double.infinity, 51 | ), 52 | ), 53 | 54 | // fading black 55 | Container( 56 | height: 160, 57 | decoration: BoxDecoration( 58 | borderRadius: BorderRadius.only( 59 | bottomLeft: Radius.circular(20), 60 | bottomRight: Radius.circular(20), 61 | ), 62 | gradient: LinearGradient( 63 | begin: Alignment.bottomCenter, 64 | end: Alignment.topCenter, 65 | colors: [ 66 | Colors.black.withOpacity(0.6), 67 | Colors.black.withOpacity(0.6), 68 | Colors.black.withOpacity(0.6), 69 | Colors.black.withOpacity(0.4), 70 | Colors.black.withOpacity(0.1), 71 | Colors.black.withOpacity(0.05), 72 | Colors.black.withOpacity(0.025), 73 | ], 74 | )), 75 | ), 76 | 77 | //restaurant name 78 | Positioned.fill( 79 | bottom: 60, 80 | child: Align( 81 | alignment: Alignment.bottomCenter, 82 | child: CustomText(text: restaurantModel.name, color: white, size: 26, weight: FontWeight.w300,))), 83 | 84 | // average price 85 | Positioned.fill( 86 | bottom: 40, 87 | child: Align( 88 | alignment: Alignment.bottomCenter, 89 | child: CustomText(text: "Average Price: \$" + restaurantModel.avgPrice.toString(), color: white, size: 18, weight: FontWeight.w300,))), 90 | 91 | // rating widget 92 | Positioned.fill( 93 | bottom: 2, 94 | child: Align( 95 | alignment: Alignment.bottomCenter, 96 | child: Padding( 97 | padding: const EdgeInsets.all(8.0), 98 | child: Container( 99 | width: 50, 100 | decoration: BoxDecoration( 101 | color: white, 102 | borderRadius: BorderRadius.circular(5), 103 | ), 104 | child: Row( 105 | children: [ 106 | Padding( 107 | padding: const EdgeInsets.all(2.0), 108 | child: Icon( 109 | Icons.star, 110 | color: Colors.yellow[900], 111 | size: 20, 112 | ), 113 | ), 114 | Text(restaurantModel.rating.toString()), 115 | ], 116 | ), 117 | ), 118 | ), 119 | )), 120 | 121 | // close button 122 | Positioned.fill( 123 | top: 5, 124 | child: Align( 125 | alignment: Alignment.topLeft, 126 | child: Padding( 127 | padding: const EdgeInsets.all(4), 128 | child: GestureDetector( 129 | onTap: (){ 130 | Navigator.pop(context); 131 | }, 132 | child: Container( 133 | decoration: BoxDecoration( 134 | borderRadius: BorderRadius.circular(20), 135 | color: black.withOpacity(0.2) 136 | ), 137 | child: Icon(Icons.close, color: white,)), 138 | ), 139 | ),)), 140 | 141 | //like button 142 | Positioned.fill( 143 | top: 5, 144 | child: Align( 145 | alignment: Alignment.topRight, 146 | child: Padding( 147 | padding: const EdgeInsets.all(4), 148 | child: GestureDetector( 149 | onTap: (){ 150 | }, 151 | child: SmallButton(Icons.favorite), 152 | ), 153 | ),)), 154 | 155 | 156 | ], 157 | ), 158 | SizedBox( 159 | height: 10, 160 | ), 161 | 162 | 163 | // open & book section 164 | Row( 165 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 166 | children: [ 167 | CustomText(text: "Open", color: green, weight: FontWeight.w400, size: 18,), 168 | Container( 169 | child: FlatButton.icon(onPressed: (){}, icon: Icon(Icons.restaurant_menu), label: CustomText(text: "Book Now"))) 170 | ], 171 | ), 172 | 173 | // products 174 | Column( 175 | children: productProvider.productsByRestaurant 176 | .map((item) => GestureDetector( 177 | onTap: () { 178 | changeScreen(context, Details(product: item,)); 179 | }, 180 | child: ProductWidget( 181 | product: item, 182 | ), 183 | )) 184 | .toList(), 185 | ) 186 | 187 | 188 | ], 189 | 190 | )), 191 | ); 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | archive: 5 | dependency: transitive 6 | description: 7 | name: archive 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.0.11" 11 | args: 12 | dependency: transitive 13 | description: 14 | name: args 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "1.5.2" 18 | async: 19 | dependency: transitive 20 | description: 21 | name: async 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "2.4.0" 25 | boolean_selector: 26 | dependency: transitive 27 | description: 28 | name: boolean_selector 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.0.5" 32 | carousel_pro: 33 | dependency: "direct main" 34 | description: 35 | name: carousel_pro 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.0.0" 39 | charcode: 40 | dependency: transitive 41 | description: 42 | name: charcode 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.1.2" 46 | cloud_firestore: 47 | dependency: "direct main" 48 | description: 49 | name: cloud_firestore 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "0.13.0+1" 53 | collection: 54 | dependency: transitive 55 | description: 56 | name: collection 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "1.14.11" 60 | convert: 61 | dependency: transitive 62 | description: 63 | name: convert 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "2.1.1" 67 | crypto: 68 | dependency: transitive 69 | description: 70 | name: crypto 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "2.1.3" 74 | cupertino_icons: 75 | dependency: "direct main" 76 | description: 77 | name: cupertino_icons 78 | url: "https://pub.dartlang.org" 79 | source: hosted 80 | version: "0.1.3" 81 | firebase: 82 | dependency: transitive 83 | description: 84 | name: firebase 85 | url: "https://pub.dartlang.org" 86 | source: hosted 87 | version: "7.2.0" 88 | firebase_auth: 89 | dependency: "direct main" 90 | description: 91 | name: firebase_auth 92 | url: "https://pub.dartlang.org" 93 | source: hosted 94 | version: "0.15.3+1" 95 | firebase_auth_platform_interface: 96 | dependency: transitive 97 | description: 98 | name: firebase_auth_platform_interface 99 | url: "https://pub.dartlang.org" 100 | source: hosted 101 | version: "1.1.5" 102 | firebase_auth_web: 103 | dependency: transitive 104 | description: 105 | name: firebase_auth_web 106 | url: "https://pub.dartlang.org" 107 | source: hosted 108 | version: "0.1.1+4" 109 | firebase_core: 110 | dependency: transitive 111 | description: 112 | name: firebase_core 113 | url: "https://pub.dartlang.org" 114 | source: hosted 115 | version: "0.4.3+2" 116 | firebase_core_platform_interface: 117 | dependency: transitive 118 | description: 119 | name: firebase_core_platform_interface 120 | url: "https://pub.dartlang.org" 121 | source: hosted 122 | version: "1.0.2" 123 | firebase_core_web: 124 | dependency: transitive 125 | description: 126 | name: firebase_core_web 127 | url: "https://pub.dartlang.org" 128 | source: hosted 129 | version: "0.1.1+2" 130 | flutter: 131 | dependency: "direct main" 132 | description: flutter 133 | source: sdk 134 | version: "0.0.0" 135 | flutter_keyboard_visibility: 136 | dependency: transitive 137 | description: 138 | name: flutter_keyboard_visibility 139 | url: "https://pub.dartlang.org" 140 | source: hosted 141 | version: "0.7.0" 142 | flutter_spinkit: 143 | dependency: "direct main" 144 | description: 145 | name: flutter_spinkit 146 | url: "https://pub.dartlang.org" 147 | source: hosted 148 | version: "4.1.2+1" 149 | flutter_test: 150 | dependency: "direct dev" 151 | description: flutter 152 | source: sdk 153 | version: "0.0.0" 154 | flutter_typeahead: 155 | dependency: "direct main" 156 | description: 157 | name: flutter_typeahead 158 | url: "https://pub.dartlang.org" 159 | source: hosted 160 | version: "1.8.1" 161 | flutter_web_plugins: 162 | dependency: transitive 163 | description: flutter 164 | source: sdk 165 | version: "0.0.0" 166 | http: 167 | dependency: transitive 168 | description: 169 | name: http 170 | url: "https://pub.dartlang.org" 171 | source: hosted 172 | version: "0.12.0+4" 173 | http_parser: 174 | dependency: transitive 175 | description: 176 | name: http_parser 177 | url: "https://pub.dartlang.org" 178 | source: hosted 179 | version: "3.1.3" 180 | image: 181 | dependency: transitive 182 | description: 183 | name: image 184 | url: "https://pub.dartlang.org" 185 | source: hosted 186 | version: "2.1.4" 187 | js: 188 | dependency: transitive 189 | description: 190 | name: js 191 | url: "https://pub.dartlang.org" 192 | source: hosted 193 | version: "0.6.1+1" 194 | matcher: 195 | dependency: transitive 196 | description: 197 | name: matcher 198 | url: "https://pub.dartlang.org" 199 | source: hosted 200 | version: "0.12.6" 201 | meta: 202 | dependency: transitive 203 | description: 204 | name: meta 205 | url: "https://pub.dartlang.org" 206 | source: hosted 207 | version: "1.1.8" 208 | nested: 209 | dependency: transitive 210 | description: 211 | name: nested 212 | url: "https://pub.dartlang.org" 213 | source: hosted 214 | version: "0.0.4" 215 | path: 216 | dependency: transitive 217 | description: 218 | name: path 219 | url: "https://pub.dartlang.org" 220 | source: hosted 221 | version: "1.6.4" 222 | pedantic: 223 | dependency: transitive 224 | description: 225 | name: pedantic 226 | url: "https://pub.dartlang.org" 227 | source: hosted 228 | version: "1.8.0+1" 229 | petitparser: 230 | dependency: transitive 231 | description: 232 | name: petitparser 233 | url: "https://pub.dartlang.org" 234 | source: hosted 235 | version: "2.4.0" 236 | provider: 237 | dependency: "direct main" 238 | description: 239 | name: provider 240 | url: "https://pub.dartlang.org" 241 | source: hosted 242 | version: "4.0.4" 243 | quiver: 244 | dependency: transitive 245 | description: 246 | name: quiver 247 | url: "https://pub.dartlang.org" 248 | source: hosted 249 | version: "2.0.5" 250 | sky_engine: 251 | dependency: transitive 252 | description: flutter 253 | source: sdk 254 | version: "0.0.99" 255 | source_span: 256 | dependency: transitive 257 | description: 258 | name: source_span 259 | url: "https://pub.dartlang.org" 260 | source: hosted 261 | version: "1.5.5" 262 | stack_trace: 263 | dependency: transitive 264 | description: 265 | name: stack_trace 266 | url: "https://pub.dartlang.org" 267 | source: hosted 268 | version: "1.9.3" 269 | stream_channel: 270 | dependency: transitive 271 | description: 272 | name: stream_channel 273 | url: "https://pub.dartlang.org" 274 | source: hosted 275 | version: "2.0.0" 276 | string_scanner: 277 | dependency: transitive 278 | description: 279 | name: string_scanner 280 | url: "https://pub.dartlang.org" 281 | source: hosted 282 | version: "1.0.5" 283 | stripe_payment: 284 | dependency: "direct main" 285 | description: 286 | name: stripe_payment 287 | url: "https://pub.dartlang.org" 288 | source: hosted 289 | version: "1.0.7" 290 | term_glyph: 291 | dependency: transitive 292 | description: 293 | name: term_glyph 294 | url: "https://pub.dartlang.org" 295 | source: hosted 296 | version: "1.1.0" 297 | test_api: 298 | dependency: transitive 299 | description: 300 | name: test_api 301 | url: "https://pub.dartlang.org" 302 | source: hosted 303 | version: "0.2.11" 304 | transparent_image: 305 | dependency: "direct main" 306 | description: 307 | name: transparent_image 308 | url: "https://pub.dartlang.org" 309 | source: hosted 310 | version: "0.1.0" 311 | typed_data: 312 | dependency: transitive 313 | description: 314 | name: typed_data 315 | url: "https://pub.dartlang.org" 316 | source: hosted 317 | version: "1.1.6" 318 | uuid: 319 | dependency: "direct main" 320 | description: 321 | name: uuid 322 | url: "https://pub.dartlang.org" 323 | source: hosted 324 | version: "2.0.4" 325 | vector_math: 326 | dependency: transitive 327 | description: 328 | name: vector_math 329 | url: "https://pub.dartlang.org" 330 | source: hosted 331 | version: "2.0.8" 332 | xml: 333 | dependency: transitive 334 | description: 335 | name: xml 336 | url: "https://pub.dartlang.org" 337 | source: hosted 338 | version: "3.5.0" 339 | sdks: 340 | dart: ">=2.7.0-dev <3.0.0" 341 | flutter: ">=1.12.13+hotfix.4 <2.0.0" 342 | -------------------------------------------------------------------------------- /lib/scr/screens/home.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter/rendering.dart'; 4 | import 'package:food_course/scr/helpers/screen_navigation.dart'; 5 | import 'package:food_course/scr/helpers/style.dart'; 6 | import 'package:food_course/scr/providers/app.dart'; 7 | import 'package:food_course/scr/providers/category.dart'; 8 | import 'package:food_course/scr/providers/product.dart'; 9 | import 'package:food_course/scr/providers/restaurant.dart'; 10 | import 'package:food_course/scr/providers/user.dart'; 11 | import 'package:food_course/scr/screens/cart.dart'; 12 | import 'package:food_course/scr/screens/category.dart'; 13 | import 'package:food_course/scr/screens/login.dart'; 14 | import 'package:food_course/scr/screens/order.dart'; 15 | import 'package:food_course/scr/screens/product_search.dart'; 16 | import 'package:food_course/scr/screens/restaurant.dart'; 17 | import 'package:food_course/scr/screens/restaurants_search.dart'; 18 | import 'package:food_course/scr/widgets/categories.dart'; 19 | import 'package:food_course/scr/widgets/custom_text.dart'; 20 | import 'package:food_course/scr/widgets/featured_products.dart'; 21 | import 'package:food_course/scr/widgets/loading.dart'; 22 | import 'package:food_course/scr/widgets/restaurant.dart'; 23 | import 'package:provider/provider.dart'; 24 | 25 | class Home extends StatefulWidget { 26 | @override 27 | _HomeState createState() => _HomeState(); 28 | } 29 | 30 | class _HomeState extends State { 31 | @override 32 | Widget build(BuildContext context) { 33 | final user = Provider.of(context); 34 | final app = Provider.of(context); 35 | final categoryProvider = Provider.of(context); 36 | final restaurantProvider = Provider.of(context); 37 | final productProvider = Provider.of(context); 38 | restaurantProvider.loadSingleRestaurant(); 39 | return Scaffold( 40 | appBar: AppBar( 41 | iconTheme: IconThemeData(color: white), 42 | elevation: 0.5, 43 | backgroundColor: primary, 44 | title: CustomText( 45 | text: "FoodApp", 46 | color: white, 47 | ), 48 | actions: [ 49 | Stack( 50 | children: [ 51 | IconButton( 52 | icon: Icon(Icons.shopping_cart), 53 | onPressed: () { 54 | changeScreen(context, CartScreen()); 55 | }, 56 | ), 57 | ], 58 | ), 59 | ], 60 | ), 61 | drawer: Drawer( 62 | child: ListView( 63 | children: [ 64 | UserAccountsDrawerHeader( 65 | decoration: BoxDecoration(color: primary), 66 | accountName: CustomText( 67 | text: user.userModel?.name ?? "username lading...", 68 | color: white, 69 | weight: FontWeight.bold, 70 | size: 18, 71 | ), 72 | accountEmail: CustomText( 73 | text: user.userModel?.email ?? "email loading...", 74 | color: white, 75 | ), 76 | ), 77 | ListTile( 78 | onTap: () { 79 | changeScreen(context, Home()); 80 | }, 81 | leading: Icon(Icons.home), 82 | title: CustomText(text: "Home"), 83 | ), 84 | 85 | ListTile( 86 | onTap: () async{ 87 | await user.getOrders(); 88 | changeScreen(context, OrdersScreen()); 89 | }, 90 | leading: Icon(Icons.bookmark_border), 91 | title: CustomText(text: "My orders"), 92 | ), 93 | ListTile( 94 | onTap: () { 95 | changeScreen(context, CartScreen()); 96 | }, 97 | leading: Icon(Icons.shopping_cart), 98 | title: CustomText(text: "Cart"), 99 | ), 100 | ListTile( 101 | onTap: () { 102 | user.signOut(); 103 | changeScreenReplacement(context, LoginScreen()); 104 | }, 105 | leading: Icon(Icons.exit_to_app), 106 | title: CustomText(text: "Log out"), 107 | ), 108 | ], 109 | ), 110 | ), 111 | backgroundColor: white, 112 | body: app.isLoading 113 | ? Container( 114 | child: Column( 115 | mainAxisAlignment: MainAxisAlignment.center, 116 | children: [Loading()], 117 | ), 118 | ) 119 | : SafeArea( 120 | child: ListView( 121 | children: [ 122 | Container( 123 | decoration: BoxDecoration( 124 | color: primary, 125 | borderRadius: BorderRadius.only( 126 | bottomRight: Radius.circular(20), 127 | bottomLeft: Radius.circular(20))), 128 | child: Padding( 129 | padding: const EdgeInsets.only( 130 | top: 8, left: 8, right: 8, bottom: 10), 131 | child: Container( 132 | decoration: BoxDecoration( 133 | color: white, 134 | borderRadius: BorderRadius.circular(20), 135 | ), 136 | child: ListTile( 137 | leading: Icon( 138 | Icons.search, 139 | color: red, 140 | ), 141 | title: TextField( 142 | textInputAction: TextInputAction.search, 143 | onSubmitted: (pattern)async{ 144 | app.changeLoading(); 145 | if(app.search == SearchBy.PRODUCTS){ 146 | await productProvider.search(productName: pattern); 147 | changeScreen(context, ProductSearchScreen()); 148 | }else{ 149 | await restaurantProvider.search(name: pattern); 150 | changeScreen(context, RestaurantsSearchScreen()); 151 | } 152 | app.changeLoading(); 153 | }, 154 | decoration: InputDecoration( 155 | hintText: "Find food and restaurant", 156 | border: InputBorder.none, 157 | ), 158 | ), 159 | ), 160 | ), 161 | ), 162 | ), 163 | 164 | Row( 165 | mainAxisAlignment: MainAxisAlignment.spaceAround, 166 | children: [ 167 | CustomText(text: "Search by:", color: grey, weight: FontWeight.w300,), 168 | DropdownButton( 169 | value: app.filterBy, 170 | style: TextStyle( 171 | color: primary, 172 | fontWeight: FontWeight.w300 173 | ), 174 | icon: Icon(Icons.filter_list, 175 | color: primary,), 176 | elevation: 0, 177 | onChanged: (value){ 178 | if (value == "Products"){ 179 | app.changeSearchBy(newSearchBy: SearchBy.PRODUCTS); 180 | }else{ 181 | app.changeSearchBy(newSearchBy: SearchBy.RESTAURANTS); 182 | } 183 | }, 184 | items: ["Products", "Restaurants"].map>((String value){ 185 | return DropdownMenuItem( 186 | value: value, 187 | child: Text(value)); 188 | }).toList(), 189 | 190 | ), 191 | ], 192 | ), 193 | Divider(), 194 | SizedBox( 195 | height: 10, 196 | ), 197 | Container( 198 | height: 100, 199 | child: ListView.builder( 200 | scrollDirection: Axis.horizontal, 201 | itemCount: categoryProvider.categories.length, 202 | itemBuilder: (context, index) { 203 | return GestureDetector( 204 | onTap: () async { 205 | // app.changeLoading(); 206 | await productProvider.loadProductsByCategory( 207 | categoryName: 208 | categoryProvider.categories[index].name); 209 | 210 | changeScreen( 211 | context, 212 | CategoryScreen( 213 | categoryModel: 214 | categoryProvider.categories[index], 215 | )); 216 | 217 | // app.changeLoading(); 218 | 219 | }, 220 | child: CategoryWidget( 221 | category: categoryProvider.categories[index], 222 | ), 223 | ); 224 | }), 225 | ), 226 | SizedBox( 227 | height: 5, 228 | ), 229 | Padding( 230 | padding: const EdgeInsets.all(8.0), 231 | child: Row( 232 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 233 | children: [ 234 | CustomText( 235 | text: "Featured", 236 | size: 20, 237 | color: grey, 238 | ), 239 | ], 240 | ), 241 | ), 242 | Featured(), 243 | Padding( 244 | padding: const EdgeInsets.all(8.0), 245 | child: Row( 246 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 247 | children: [ 248 | CustomText( 249 | text: "Popular restaurants", 250 | size: 20, 251 | color: grey, 252 | ), 253 | ], 254 | ), 255 | ), 256 | Column( 257 | children: restaurantProvider.restaurants 258 | .map((item) => GestureDetector( 259 | onTap: () async { 260 | app.changeLoading(); 261 | 262 | await productProvider.loadProductsByRestaurant( 263 | restaurantId: item.id); 264 | app.changeLoading(); 265 | 266 | changeScreen( 267 | context, 268 | RestaurantScreen( 269 | restaurantModel: item, 270 | )); 271 | }, 272 | child: RestaurantWidget( 273 | restaurant: item, 274 | ), 275 | )) 276 | .toList(), 277 | ) 278 | ], 279 | ), 280 | ), 281 | ); 282 | } 283 | } 284 | -------------------------------------------------------------------------------- /lib/scr/screens/cart.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:food_course/scr/helpers/order.dart'; 3 | import 'package:food_course/scr/helpers/style.dart'; 4 | import 'package:food_course/scr/models/cart_item.dart'; 5 | import 'package:food_course/scr/models/products.dart'; 6 | import 'package:food_course/scr/providers/app.dart'; 7 | import 'package:food_course/scr/providers/user.dart'; 8 | import 'package:food_course/scr/widgets/custom_text.dart'; 9 | import 'package:food_course/scr/widgets/loading.dart'; 10 | import 'package:provider/provider.dart'; 11 | import 'package:uuid/uuid.dart'; 12 | 13 | class CartScreen extends StatefulWidget { 14 | @override 15 | _CartScreenState createState() => _CartScreenState(); 16 | } 17 | 18 | class _CartScreenState extends State { 19 | final _key = GlobalKey(); 20 | OrderServices _orderServices = OrderServices(); 21 | 22 | @override 23 | Widget build(BuildContext context) { 24 | final user = Provider.of(context); 25 | final app = Provider.of(context); 26 | 27 | 28 | 29 | return Scaffold( 30 | key: _key, 31 | appBar: AppBar( 32 | iconTheme: IconThemeData(color: black), 33 | backgroundColor: white, 34 | elevation: 0.0, 35 | title: CustomText(text: "Shopping Cart"), 36 | leading: IconButton( 37 | icon: Icon(Icons.close), 38 | onPressed: () { 39 | Navigator.pop(context); 40 | }), 41 | ), 42 | backgroundColor: white, 43 | body: app.isLoading ? Loading() : ListView.builder( 44 | itemCount: user.userModel.cart.length, 45 | itemBuilder: (_, index) { 46 | 47 | return Padding( 48 | padding: const EdgeInsets.all(16), 49 | child: Container( 50 | height: 120, 51 | decoration: BoxDecoration( 52 | borderRadius: BorderRadius.circular(20), 53 | color: white, 54 | boxShadow: [ 55 | BoxShadow( 56 | color: red.withOpacity(0.2), 57 | offset: Offset(3, 2), 58 | blurRadius: 30) 59 | ]), 60 | child: Row( 61 | children: [ 62 | ClipRRect( 63 | borderRadius: BorderRadius.only( 64 | bottomLeft: Radius.circular(20), 65 | topLeft: Radius.circular(20), 66 | ), 67 | child: Image.network( 68 | user.userModel.cart[index].image, 69 | height: 120, 70 | width: 140, 71 | fit: BoxFit.fill, 72 | ), 73 | ), 74 | SizedBox( 75 | width: 10, 76 | ), 77 | Expanded( 78 | child: Row( 79 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 80 | children: [ 81 | RichText( 82 | text: TextSpan(children: [ 83 | TextSpan( 84 | text: user.userModel.cart[index].name+ "\n", 85 | style: TextStyle( 86 | color: black, 87 | fontSize: 20, 88 | fontWeight: FontWeight.bold)), 89 | TextSpan( 90 | text: "\$${user.userModel.cart[index].price / 100} \n\n", 91 | style: TextStyle( 92 | color: black, 93 | fontSize: 18, 94 | fontWeight: FontWeight.w300)), 95 | TextSpan( 96 | text: "Quantity: ", 97 | style: TextStyle( 98 | color: grey, 99 | fontSize: 16, 100 | fontWeight: FontWeight.w400)), 101 | TextSpan( 102 | text: user.userModel.cart[index].quantity.toString(), 103 | style: TextStyle( 104 | color: primary, 105 | fontSize: 16, 106 | fontWeight: FontWeight.w400)), 107 | ]), 108 | ), 109 | IconButton( 110 | icon: Icon( 111 | Icons.delete, 112 | color: red, 113 | ), 114 | onPressed: ()async{ 115 | app.changeLoading(); 116 | bool value = await user.removeFromCart(cartItem: user.userModel.cart[index]); 117 | if(value){ 118 | user.reloadUserModel(); 119 | print("Item added to cart"); 120 | _key.currentState.showSnackBar( 121 | SnackBar(content: Text("Removed from Cart!")) 122 | ); 123 | app.changeLoading(); 124 | return; 125 | }else{ 126 | print("ITEM WAS NOT REMOVED"); 127 | app.changeLoading(); 128 | } 129 | }) 130 | ], 131 | ), 132 | ) 133 | ], 134 | ), 135 | ), 136 | ); 137 | }), 138 | bottomNavigationBar: Container( 139 | height: 70, 140 | child: Padding( 141 | padding: const EdgeInsets.all(8.0), 142 | child: Row( 143 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 144 | children: [ 145 | RichText( 146 | text: TextSpan(children: [ 147 | TextSpan( 148 | text: "Total: ", 149 | style: TextStyle( 150 | color: grey, 151 | fontSize: 22, 152 | fontWeight: FontWeight.w400)), 153 | TextSpan( 154 | text: " \$${user.userModel.totalCartPrice / 100}", 155 | style: TextStyle( 156 | color: primary, 157 | fontSize: 22, 158 | fontWeight: FontWeight.normal)), 159 | ]), 160 | ), 161 | Container( 162 | decoration: BoxDecoration( 163 | borderRadius: BorderRadius.circular(20), color: primary), 164 | child: FlatButton( 165 | onPressed: () { 166 | if(user.userModel.totalCartPrice == 0){ 167 | showDialog( 168 | context: context, 169 | builder: (BuildContext context) { 170 | return Dialog( 171 | shape: RoundedRectangleBorder( 172 | borderRadius: 173 | BorderRadius.circular(20.0)), //this right here 174 | child: Container( 175 | height: 200, 176 | child: Padding( 177 | padding: const EdgeInsets.all(12.0), 178 | child: Column( 179 | mainAxisAlignment: MainAxisAlignment.center, 180 | crossAxisAlignment: CrossAxisAlignment.start, 181 | children: [ 182 | Row( 183 | mainAxisAlignment: MainAxisAlignment.center, 184 | children: [ 185 | Text('Your cart is emty', textAlign: TextAlign.center,), 186 | ], 187 | ), 188 | ], 189 | ), 190 | ), 191 | ), 192 | ); 193 | }); 194 | return; 195 | } 196 | showDialog( 197 | context: context, 198 | builder: (BuildContext context) { 199 | return Dialog( 200 | shape: RoundedRectangleBorder( 201 | borderRadius: 202 | BorderRadius.circular(20.0)), //this right here 203 | child: Container( 204 | height: 200, 205 | child: Padding( 206 | padding: const EdgeInsets.all(12.0), 207 | child: Column( 208 | mainAxisAlignment: MainAxisAlignment.center, 209 | crossAxisAlignment: CrossAxisAlignment.start, 210 | children: [ 211 | Text('You will be charged \$${user.userModel.totalCartPrice / 100} upon delivery!', textAlign: TextAlign.center,), 212 | 213 | SizedBox( 214 | width: 320.0, 215 | child: RaisedButton( 216 | onPressed: () async{ 217 | var uuid = Uuid(); 218 | String id = uuid.v4(); 219 | _orderServices.createOrder( 220 | userId: user.user.uid, 221 | id: id, 222 | description: "Some random description", 223 | status: "complete", 224 | totalPrice: user.userModel.totalCartPrice, 225 | cart: user.userModel.cart 226 | ); 227 | for(CartItemModel cartItem in user.userModel.cart){ 228 | bool value = await user.removeFromCart(cartItem: cartItem); 229 | if(value){ 230 | user.reloadUserModel(); 231 | print("Item added to cart"); 232 | _key.currentState.showSnackBar( 233 | SnackBar(content: Text("Removed from Cart!")) 234 | ); 235 | }else{ 236 | print("ITEM WAS NOT REMOVED"); 237 | } 238 | } 239 | _key.currentState.showSnackBar( 240 | SnackBar(content: Text("Order created!")) 241 | ); 242 | Navigator.pop(context); 243 | 244 | }, 245 | child: Text( 246 | "Accept", 247 | style: TextStyle(color: Colors.white), 248 | ), 249 | color: const Color(0xFF1BC0C5), 250 | ), 251 | ), 252 | SizedBox( 253 | width: 320.0, 254 | child: RaisedButton( 255 | onPressed: () { 256 | Navigator.pop(context); 257 | }, 258 | child: Text( 259 | "Reject", 260 | style: TextStyle(color: Colors.white), 261 | ), 262 | color: red 263 | ), 264 | ) 265 | 266 | ], 267 | ), 268 | ), 269 | ), 270 | ); 271 | }); 272 | }, 273 | child: CustomText( 274 | text: "Check out", 275 | size: 20, 276 | color: white, 277 | weight: FontWeight.normal, 278 | )), 279 | ) 280 | ], 281 | ), 282 | ), 283 | ), 284 | ); 285 | } 286 | } 287 | -------------------------------------------------------------------------------- /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 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 13 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 14 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 15 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; 16 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 17 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 18 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 19 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXCopyFilesBuildPhase section */ 23 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 24 | isa = PBXCopyFilesBuildPhase; 25 | buildActionMask = 2147483647; 26 | dstPath = ""; 27 | dstSubfolderSpec = 10; 28 | files = ( 29 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, 30 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, 31 | ); 32 | name = "Embed Frameworks"; 33 | runOnlyForDeploymentPostprocessing = 0; 34 | }; 35 | /* End PBXCopyFilesBuildPhase section */ 36 | 37 | /* Begin PBXFileReference section */ 38 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 39 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 40 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 41 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 42 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 43 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 44 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 45 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 46 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 47 | 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 48 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 49 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 50 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 51 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 52 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 53 | /* End PBXFileReference section */ 54 | 55 | /* Begin PBXFrameworksBuildPhase section */ 56 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 57 | isa = PBXFrameworksBuildPhase; 58 | buildActionMask = 2147483647; 59 | files = ( 60 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, 61 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, 62 | ); 63 | runOnlyForDeploymentPostprocessing = 0; 64 | }; 65 | /* End PBXFrameworksBuildPhase section */ 66 | 67 | /* Begin PBXGroup section */ 68 | 9740EEB11CF90186004384FC /* Flutter */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | 3B80C3931E831B6300D905FE /* App.framework */, 72 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 73 | 9740EEBA1CF902C7004384FC /* Flutter.framework */, 74 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 75 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 76 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 77 | ); 78 | name = Flutter; 79 | sourceTree = ""; 80 | }; 81 | 97C146E51CF9000F007C117D = { 82 | isa = PBXGroup; 83 | children = ( 84 | 9740EEB11CF90186004384FC /* Flutter */, 85 | 97C146F01CF9000F007C117D /* Runner */, 86 | 97C146EF1CF9000F007C117D /* Products */, 87 | ); 88 | sourceTree = ""; 89 | }; 90 | 97C146EF1CF9000F007C117D /* Products */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 97C146EE1CF9000F007C117D /* Runner.app */, 94 | ); 95 | name = Products; 96 | sourceTree = ""; 97 | }; 98 | 97C146F01CF9000F007C117D /* Runner */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 102 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 103 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 104 | 97C147021CF9000F007C117D /* Info.plist */, 105 | 97C146F11CF9000F007C117D /* Supporting Files */, 106 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 107 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 108 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 109 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 110 | ); 111 | path = Runner; 112 | sourceTree = ""; 113 | }; 114 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | ); 118 | name = "Supporting Files"; 119 | sourceTree = ""; 120 | }; 121 | /* End PBXGroup section */ 122 | 123 | /* Begin PBXNativeTarget section */ 124 | 97C146ED1CF9000F007C117D /* Runner */ = { 125 | isa = PBXNativeTarget; 126 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 127 | buildPhases = ( 128 | 9740EEB61CF901F6004384FC /* Run Script */, 129 | 97C146EA1CF9000F007C117D /* Sources */, 130 | 97C146EB1CF9000F007C117D /* Frameworks */, 131 | 97C146EC1CF9000F007C117D /* Resources */, 132 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 133 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 134 | ); 135 | buildRules = ( 136 | ); 137 | dependencies = ( 138 | ); 139 | name = Runner; 140 | productName = Runner; 141 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 142 | productType = "com.apple.product-type.application"; 143 | }; 144 | /* End PBXNativeTarget section */ 145 | 146 | /* Begin PBXProject section */ 147 | 97C146E61CF9000F007C117D /* Project object */ = { 148 | isa = PBXProject; 149 | attributes = { 150 | LastUpgradeCheck = 1020; 151 | ORGANIZATIONNAME = "The Chromium Authors"; 152 | TargetAttributes = { 153 | 97C146ED1CF9000F007C117D = { 154 | CreatedOnToolsVersion = 7.3.1; 155 | LastSwiftMigration = 1100; 156 | }; 157 | }; 158 | }; 159 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 160 | compatibilityVersion = "Xcode 3.2"; 161 | developmentRegion = en; 162 | hasScannedForEncodings = 0; 163 | knownRegions = ( 164 | en, 165 | Base, 166 | ); 167 | mainGroup = 97C146E51CF9000F007C117D; 168 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 169 | projectDirPath = ""; 170 | projectRoot = ""; 171 | targets = ( 172 | 97C146ED1CF9000F007C117D /* Runner */, 173 | ); 174 | }; 175 | /* End PBXProject section */ 176 | 177 | /* Begin PBXResourcesBuildPhase section */ 178 | 97C146EC1CF9000F007C117D /* Resources */ = { 179 | isa = PBXResourcesBuildPhase; 180 | buildActionMask = 2147483647; 181 | files = ( 182 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 183 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 184 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 185 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 186 | ); 187 | runOnlyForDeploymentPostprocessing = 0; 188 | }; 189 | /* End PBXResourcesBuildPhase section */ 190 | 191 | /* Begin PBXShellScriptBuildPhase section */ 192 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 193 | isa = PBXShellScriptBuildPhase; 194 | buildActionMask = 2147483647; 195 | files = ( 196 | ); 197 | inputPaths = ( 198 | ); 199 | name = "Thin Binary"; 200 | outputPaths = ( 201 | ); 202 | runOnlyForDeploymentPostprocessing = 0; 203 | shellPath = /bin/sh; 204 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; 205 | }; 206 | 9740EEB61CF901F6004384FC /* Run Script */ = { 207 | isa = PBXShellScriptBuildPhase; 208 | buildActionMask = 2147483647; 209 | files = ( 210 | ); 211 | inputPaths = ( 212 | ); 213 | name = "Run Script"; 214 | outputPaths = ( 215 | ); 216 | runOnlyForDeploymentPostprocessing = 0; 217 | shellPath = /bin/sh; 218 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 219 | }; 220 | /* End PBXShellScriptBuildPhase section */ 221 | 222 | /* Begin PBXSourcesBuildPhase section */ 223 | 97C146EA1CF9000F007C117D /* Sources */ = { 224 | isa = PBXSourcesBuildPhase; 225 | buildActionMask = 2147483647; 226 | files = ( 227 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 228 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 229 | ); 230 | runOnlyForDeploymentPostprocessing = 0; 231 | }; 232 | /* End PBXSourcesBuildPhase section */ 233 | 234 | /* Begin PBXVariantGroup section */ 235 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 236 | isa = PBXVariantGroup; 237 | children = ( 238 | 97C146FB1CF9000F007C117D /* Base */, 239 | ); 240 | name = Main.storyboard; 241 | sourceTree = ""; 242 | }; 243 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 244 | isa = PBXVariantGroup; 245 | children = ( 246 | 97C147001CF9000F007C117D /* Base */, 247 | ); 248 | name = LaunchScreen.storyboard; 249 | sourceTree = ""; 250 | }; 251 | /* End PBXVariantGroup section */ 252 | 253 | /* Begin XCBuildConfiguration section */ 254 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 255 | isa = XCBuildConfiguration; 256 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 257 | buildSettings = { 258 | ALWAYS_SEARCH_USER_PATHS = NO; 259 | CLANG_ANALYZER_NONNULL = YES; 260 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 261 | CLANG_CXX_LIBRARY = "libc++"; 262 | CLANG_ENABLE_MODULES = YES; 263 | CLANG_ENABLE_OBJC_ARC = YES; 264 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 265 | CLANG_WARN_BOOL_CONVERSION = YES; 266 | CLANG_WARN_COMMA = YES; 267 | CLANG_WARN_CONSTANT_CONVERSION = YES; 268 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 269 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 270 | CLANG_WARN_EMPTY_BODY = YES; 271 | CLANG_WARN_ENUM_CONVERSION = YES; 272 | CLANG_WARN_INFINITE_RECURSION = YES; 273 | CLANG_WARN_INT_CONVERSION = YES; 274 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 275 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 276 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 277 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 278 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 279 | CLANG_WARN_STRICT_PROTOTYPES = YES; 280 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 281 | CLANG_WARN_UNREACHABLE_CODE = YES; 282 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 283 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 284 | COPY_PHASE_STRIP = NO; 285 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 286 | ENABLE_NS_ASSERTIONS = NO; 287 | ENABLE_STRICT_OBJC_MSGSEND = YES; 288 | GCC_C_LANGUAGE_STANDARD = gnu99; 289 | GCC_NO_COMMON_BLOCKS = YES; 290 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 291 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 292 | GCC_WARN_UNDECLARED_SELECTOR = YES; 293 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 294 | GCC_WARN_UNUSED_FUNCTION = YES; 295 | GCC_WARN_UNUSED_VARIABLE = YES; 296 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 297 | MTL_ENABLE_DEBUG_INFO = NO; 298 | SDKROOT = iphoneos; 299 | SUPPORTED_PLATFORMS = iphoneos; 300 | TARGETED_DEVICE_FAMILY = "1,2"; 301 | VALIDATE_PRODUCT = YES; 302 | }; 303 | name = Profile; 304 | }; 305 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 306 | isa = XCBuildConfiguration; 307 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 308 | buildSettings = { 309 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 310 | CLANG_ENABLE_MODULES = YES; 311 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 312 | ENABLE_BITCODE = NO; 313 | FRAMEWORK_SEARCH_PATHS = ( 314 | "$(inherited)", 315 | "$(PROJECT_DIR)/Flutter", 316 | ); 317 | INFOPLIST_FILE = Runner/Info.plist; 318 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 319 | LIBRARY_SEARCH_PATHS = ( 320 | "$(inherited)", 321 | "$(PROJECT_DIR)/Flutter", 322 | ); 323 | PRODUCT_BUNDLE_IDENTIFIER = com.dezeleven.foodCourse; 324 | PRODUCT_NAME = "$(TARGET_NAME)"; 325 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 326 | SWIFT_VERSION = 5.0; 327 | VERSIONING_SYSTEM = "apple-generic"; 328 | }; 329 | name = Profile; 330 | }; 331 | 97C147031CF9000F007C117D /* Debug */ = { 332 | isa = XCBuildConfiguration; 333 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 334 | buildSettings = { 335 | ALWAYS_SEARCH_USER_PATHS = NO; 336 | CLANG_ANALYZER_NONNULL = YES; 337 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 338 | CLANG_CXX_LIBRARY = "libc++"; 339 | CLANG_ENABLE_MODULES = YES; 340 | CLANG_ENABLE_OBJC_ARC = YES; 341 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 342 | CLANG_WARN_BOOL_CONVERSION = YES; 343 | CLANG_WARN_COMMA = YES; 344 | CLANG_WARN_CONSTANT_CONVERSION = YES; 345 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 346 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 347 | CLANG_WARN_EMPTY_BODY = YES; 348 | CLANG_WARN_ENUM_CONVERSION = YES; 349 | CLANG_WARN_INFINITE_RECURSION = YES; 350 | CLANG_WARN_INT_CONVERSION = YES; 351 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 352 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 353 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 354 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 355 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 356 | CLANG_WARN_STRICT_PROTOTYPES = YES; 357 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 358 | CLANG_WARN_UNREACHABLE_CODE = YES; 359 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 360 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 361 | COPY_PHASE_STRIP = NO; 362 | DEBUG_INFORMATION_FORMAT = dwarf; 363 | ENABLE_STRICT_OBJC_MSGSEND = YES; 364 | ENABLE_TESTABILITY = YES; 365 | GCC_C_LANGUAGE_STANDARD = gnu99; 366 | GCC_DYNAMIC_NO_PIC = NO; 367 | GCC_NO_COMMON_BLOCKS = YES; 368 | GCC_OPTIMIZATION_LEVEL = 0; 369 | GCC_PREPROCESSOR_DEFINITIONS = ( 370 | "DEBUG=1", 371 | "$(inherited)", 372 | ); 373 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 374 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 375 | GCC_WARN_UNDECLARED_SELECTOR = YES; 376 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 377 | GCC_WARN_UNUSED_FUNCTION = YES; 378 | GCC_WARN_UNUSED_VARIABLE = YES; 379 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 380 | MTL_ENABLE_DEBUG_INFO = YES; 381 | ONLY_ACTIVE_ARCH = YES; 382 | SDKROOT = iphoneos; 383 | TARGETED_DEVICE_FAMILY = "1,2"; 384 | }; 385 | name = Debug; 386 | }; 387 | 97C147041CF9000F007C117D /* Release */ = { 388 | isa = XCBuildConfiguration; 389 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 390 | buildSettings = { 391 | ALWAYS_SEARCH_USER_PATHS = NO; 392 | CLANG_ANALYZER_NONNULL = YES; 393 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 394 | CLANG_CXX_LIBRARY = "libc++"; 395 | CLANG_ENABLE_MODULES = YES; 396 | CLANG_ENABLE_OBJC_ARC = YES; 397 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 398 | CLANG_WARN_BOOL_CONVERSION = YES; 399 | CLANG_WARN_COMMA = YES; 400 | CLANG_WARN_CONSTANT_CONVERSION = YES; 401 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 402 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 403 | CLANG_WARN_EMPTY_BODY = YES; 404 | CLANG_WARN_ENUM_CONVERSION = YES; 405 | CLANG_WARN_INFINITE_RECURSION = YES; 406 | CLANG_WARN_INT_CONVERSION = YES; 407 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 408 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 409 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 410 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 411 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 412 | CLANG_WARN_STRICT_PROTOTYPES = YES; 413 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 414 | CLANG_WARN_UNREACHABLE_CODE = YES; 415 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 416 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 417 | COPY_PHASE_STRIP = NO; 418 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 419 | ENABLE_NS_ASSERTIONS = NO; 420 | ENABLE_STRICT_OBJC_MSGSEND = YES; 421 | GCC_C_LANGUAGE_STANDARD = gnu99; 422 | GCC_NO_COMMON_BLOCKS = YES; 423 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 424 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 425 | GCC_WARN_UNDECLARED_SELECTOR = YES; 426 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 427 | GCC_WARN_UNUSED_FUNCTION = YES; 428 | GCC_WARN_UNUSED_VARIABLE = YES; 429 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 430 | MTL_ENABLE_DEBUG_INFO = NO; 431 | SDKROOT = iphoneos; 432 | SUPPORTED_PLATFORMS = iphoneos; 433 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 434 | TARGETED_DEVICE_FAMILY = "1,2"; 435 | VALIDATE_PRODUCT = YES; 436 | }; 437 | name = Release; 438 | }; 439 | 97C147061CF9000F007C117D /* Debug */ = { 440 | isa = XCBuildConfiguration; 441 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 442 | buildSettings = { 443 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 444 | CLANG_ENABLE_MODULES = YES; 445 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 446 | ENABLE_BITCODE = NO; 447 | FRAMEWORK_SEARCH_PATHS = ( 448 | "$(inherited)", 449 | "$(PROJECT_DIR)/Flutter", 450 | ); 451 | INFOPLIST_FILE = Runner/Info.plist; 452 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 453 | LIBRARY_SEARCH_PATHS = ( 454 | "$(inherited)", 455 | "$(PROJECT_DIR)/Flutter", 456 | ); 457 | PRODUCT_BUNDLE_IDENTIFIER = com.dezeleven.foodCourse; 458 | PRODUCT_NAME = "$(TARGET_NAME)"; 459 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 460 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 461 | SWIFT_VERSION = 5.0; 462 | VERSIONING_SYSTEM = "apple-generic"; 463 | }; 464 | name = Debug; 465 | }; 466 | 97C147071CF9000F007C117D /* Release */ = { 467 | isa = XCBuildConfiguration; 468 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 469 | buildSettings = { 470 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 471 | CLANG_ENABLE_MODULES = YES; 472 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 473 | ENABLE_BITCODE = NO; 474 | FRAMEWORK_SEARCH_PATHS = ( 475 | "$(inherited)", 476 | "$(PROJECT_DIR)/Flutter", 477 | ); 478 | INFOPLIST_FILE = Runner/Info.plist; 479 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 480 | LIBRARY_SEARCH_PATHS = ( 481 | "$(inherited)", 482 | "$(PROJECT_DIR)/Flutter", 483 | ); 484 | PRODUCT_BUNDLE_IDENTIFIER = com.dezeleven.foodCourse; 485 | PRODUCT_NAME = "$(TARGET_NAME)"; 486 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 487 | SWIFT_VERSION = 5.0; 488 | VERSIONING_SYSTEM = "apple-generic"; 489 | }; 490 | name = Release; 491 | }; 492 | /* End XCBuildConfiguration section */ 493 | 494 | /* Begin XCConfigurationList section */ 495 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 496 | isa = XCConfigurationList; 497 | buildConfigurations = ( 498 | 97C147031CF9000F007C117D /* Debug */, 499 | 97C147041CF9000F007C117D /* Release */, 500 | 249021D3217E4FDB00AE95B9 /* Profile */, 501 | ); 502 | defaultConfigurationIsVisible = 0; 503 | defaultConfigurationName = Release; 504 | }; 505 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 506 | isa = XCConfigurationList; 507 | buildConfigurations = ( 508 | 97C147061CF9000F007C117D /* Debug */, 509 | 97C147071CF9000F007C117D /* Release */, 510 | 249021D4217E4FDB00AE95B9 /* Profile */, 511 | ); 512 | defaultConfigurationIsVisible = 0; 513 | defaultConfigurationName = Release; 514 | }; 515 | /* End XCConfigurationList section */ 516 | }; 517 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 518 | } 519 | --------------------------------------------------------------------------------