├── 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.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── WorkspaceSettings.xcsettings │ │ └── IDEWorkspaceChecks.plist └── .gitignore ├── web ├── favicon.png ├── icons │ ├── Icon-192.png │ └── Icon-512.png ├── manifest.json └── index.html ├── assets ├── FlyBuy logo.png ├── images │ ├── glap.png │ ├── visa.png │ ├── Helmet.png │ ├── shoes2.png │ ├── success.png │ ├── tshirt.png │ ├── splash_1.png │ ├── splash_2.png │ ├── splash_3.png │ ├── splash_5.png │ ├── splash_6.png │ ├── Image Banner 2.png │ ├── Image Banner 3.png │ ├── Profile Image.png │ ├── Pattern Success.png │ ├── wireless headset.png │ ├── ps4_console_blue_1.png │ ├── ps4_console_blue_2.png │ ├── ps4_console_blue_3.png │ ├── ps4_console_blue_4.png │ ├── ps4_console_white_1.png │ ├── ps4_console_white_2.png │ ├── ps4_console_white_3.png │ ├── ps4_console_white_4.png │ ├── Image Popular Product 1.png │ └── Image Popular Product 2.png ├── fonts │ └── muli │ │ ├── Muli.ttf │ │ ├── Muli-Bold.ttf │ │ ├── Muli-Light.ttf │ │ ├── Muli-Italic.ttf │ │ ├── Muli-SemiBold.ttf │ │ ├── Muli-BoldItalic.ttf │ │ ├── Muli-ExtraLight.ttf │ │ ├── Muli-LightItalic.ttf │ │ ├── Muli-Semi-BoldItalic.ttf │ │ └── Muli-ExtraLightItalic.ttf └── icons │ ├── Back ICon.svg │ ├── Success.svg │ ├── remove.svg │ ├── facebook-2.svg │ ├── ellipsis.svg │ ├── Plus Icon.svg │ ├── Heart Icon_2.svg │ ├── arrow_right.svg │ ├── Check mark rounde.svg │ ├── Flash Icon.svg │ ├── Phone.svg │ ├── Mail.svg │ ├── Search Icon.svg │ ├── receipt.svg │ ├── Heart Icon.svg │ ├── Location point.svg │ ├── Lock.svg │ ├── Close.svg │ ├── Error.svg │ ├── Star Icon.svg │ ├── twitter.svg │ ├── User Icon.svg │ ├── User.svg │ ├── Bell.svg │ ├── google-icon.svg │ ├── Discover.svg │ ├── Trash.svg │ ├── Question mark.svg │ ├── Parcel.svg │ ├── Cart Icon.svg │ ├── Log out.svg │ ├── Camera Icon.svg │ ├── Call.svg │ ├── Bill Icon.svg │ ├── Conversation.svg │ ├── Cash.svg │ ├── Gift Icon.svg │ ├── Chat bubble Icon.svg │ ├── Game Icon.svg │ ├── Shop Icon.svg │ └── Settings.svg ├── .vscode └── settings.json ├── android ├── gradle.properties ├── app │ ├── src │ │ ├── main │ │ │ ├── res │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── drawable │ │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable-v21 │ │ │ │ │ └── launch_background.xml │ │ │ │ ├── values │ │ │ │ │ └── styles.xml │ │ │ │ └── values-night │ │ │ │ │ └── styles.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── flybuy │ │ │ │ │ └── MainActivity.kt │ │ │ └── AndroidManifest.xml │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ └── profile │ │ │ └── AndroidManifest.xml │ └── build.gradle ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── .gitignore ├── settings.gradle └── build.gradle ├── .metadata ├── lib ├── screens │ ├── sign_up │ │ ├── sign_up_screen.dart │ │ └── components │ │ │ ├── body.dart │ │ │ └── sign_up_form.dart │ ├── sign_in │ │ ├── sign_in_screen.dart │ │ └── components │ │ │ ├── body.dart │ │ │ └── sign_in_form.dart │ ├── splash_screen │ │ ├── splash_screen.dart │ │ └── components │ │ │ ├── build_dot.dart │ │ │ ├── splash_content.dart │ │ │ └── body.dart │ ├── complete_profile │ │ ├── complete_profile_screen.dart │ │ └── components │ │ │ ├── body.dart │ │ │ └── complete_profile_form.dart │ ├── forgot_password │ │ ├── forgot_password_screen.dart │ │ └── components │ │ │ ├── body.dart │ │ │ └── forgot_password_form.dart │ ├── home │ │ ├── home_screen.dart │ │ └── components │ │ │ ├── section_title.dart │ │ │ ├── home_header.dart │ │ │ ├── body.dart │ │ │ ├── search_field.dart │ │ │ ├── discount_banner.dart │ │ │ ├── popular_products.dart │ │ │ ├── icon_button_with_counter.dart │ │ │ ├── categories.dart │ │ │ └── special_offers.dart │ ├── otp │ │ ├── otp_screen.dart │ │ └── components │ │ │ ├── body.dart │ │ │ └── otp_form.dart │ ├── login_success │ │ ├── login_success_screen.dart │ │ └── components │ │ │ └── body.dart │ ├── product_details │ │ ├── product_details_screen.dart │ │ └── components │ │ │ ├── top_rounded_container.dart │ │ │ ├── custom_appbar.dart │ │ │ ├── body.dart │ │ │ ├── product_images.dart │ │ │ ├── colors_dots.dart │ │ │ └── product_description.dart │ ├── profile │ │ ├── profile_screen.dart │ │ └── components │ │ │ ├── body.dart │ │ │ ├── profile_picture.dart │ │ │ └── profile_section_bar.dart │ └── cart │ │ ├── cart_screen.dart │ │ └── components │ │ ├── body.dart │ │ ├── cart_item_card.dart │ │ └── custom_bottom_navigation_bar.dart ├── models │ ├── Cart.dart │ └── Product.dart ├── main.dart ├── components │ ├── custom_suffix_icon.dart │ ├── no_account_text.dart │ ├── social_card.dart │ ├── rounded_icon_button.dart │ ├── default_button.dart │ ├── custom_bottom_navigation_bar.dart │ └── product_card.dart ├── size_config.dart ├── routes.dart ├── theme.dart └── constants.dart ├── .gitignore ├── LICENSE ├── test └── widget_test.dart ├── pubspec.yaml └── README.md /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/web/favicon.png -------------------------------------------------------------------------------- /assets/FlyBuy logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/FlyBuy logo.png -------------------------------------------------------------------------------- /assets/images/glap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/glap.png -------------------------------------------------------------------------------- /assets/images/visa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/visa.png -------------------------------------------------------------------------------- /web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/web/icons/Icon-192.png -------------------------------------------------------------------------------- /web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/web/icons/Icon-512.png -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "conventionalCommits.scopes": [ 3 | "profile" 4 | ] 5 | } -------------------------------------------------------------------------------- /assets/images/Helmet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/Helmet.png -------------------------------------------------------------------------------- /assets/images/shoes2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/shoes2.png -------------------------------------------------------------------------------- /assets/images/success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/success.png -------------------------------------------------------------------------------- /assets/images/tshirt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/tshirt.png -------------------------------------------------------------------------------- /assets/fonts/muli/Muli.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/fonts/muli/Muli.ttf -------------------------------------------------------------------------------- /assets/images/splash_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/splash_1.png -------------------------------------------------------------------------------- /assets/images/splash_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/splash_2.png -------------------------------------------------------------------------------- /assets/images/splash_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/splash_3.png -------------------------------------------------------------------------------- /assets/images/splash_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/splash_5.png -------------------------------------------------------------------------------- /assets/images/splash_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/splash_6.png -------------------------------------------------------------------------------- /assets/fonts/muli/Muli-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/fonts/muli/Muli-Bold.ttf -------------------------------------------------------------------------------- /assets/fonts/muli/Muli-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/fonts/muli/Muli-Light.ttf -------------------------------------------------------------------------------- /assets/images/Image Banner 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/Image Banner 2.png -------------------------------------------------------------------------------- /assets/images/Image Banner 3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/Image Banner 3.png -------------------------------------------------------------------------------- /assets/images/Profile Image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/Profile Image.png -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /assets/fonts/muli/Muli-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/fonts/muli/Muli-Italic.ttf -------------------------------------------------------------------------------- /assets/fonts/muli/Muli-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/fonts/muli/Muli-SemiBold.ttf -------------------------------------------------------------------------------- /assets/images/Pattern Success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/Pattern Success.png -------------------------------------------------------------------------------- /assets/images/wireless headset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/wireless headset.png -------------------------------------------------------------------------------- /assets/fonts/muli/Muli-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/fonts/muli/Muli-BoldItalic.ttf -------------------------------------------------------------------------------- /assets/fonts/muli/Muli-ExtraLight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/fonts/muli/Muli-ExtraLight.ttf -------------------------------------------------------------------------------- /assets/images/ps4_console_blue_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/ps4_console_blue_1.png -------------------------------------------------------------------------------- /assets/images/ps4_console_blue_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/ps4_console_blue_2.png -------------------------------------------------------------------------------- /assets/images/ps4_console_blue_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/ps4_console_blue_3.png -------------------------------------------------------------------------------- /assets/images/ps4_console_blue_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/ps4_console_blue_4.png -------------------------------------------------------------------------------- /assets/images/ps4_console_white_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/ps4_console_white_1.png -------------------------------------------------------------------------------- /assets/images/ps4_console_white_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/ps4_console_white_2.png -------------------------------------------------------------------------------- /assets/images/ps4_console_white_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/ps4_console_white_3.png -------------------------------------------------------------------------------- /assets/images/ps4_console_white_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/ps4_console_white_4.png -------------------------------------------------------------------------------- /assets/fonts/muli/Muli-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/fonts/muli/Muli-LightItalic.ttf -------------------------------------------------------------------------------- /assets/fonts/muli/Muli-Semi-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/fonts/muli/Muli-Semi-BoldItalic.ttf -------------------------------------------------------------------------------- /assets/images/Image Popular Product 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/Image Popular Product 1.png -------------------------------------------------------------------------------- /assets/images/Image Popular Product 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/images/Image Popular Product 2.png -------------------------------------------------------------------------------- /assets/fonts/muli/Muli-ExtraLightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/assets/fonts/muli/Muli-ExtraLightItalic.ttf -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/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/fxamar/FlyWebSite/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/fxamar/FlyWebSite/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/fxamar/FlyWebSite/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/fxamar/FlyWebSite/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/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/fxamar/FlyWebSite/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/fxamar/FlyWebSite/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/fxamar/FlyWebSite/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/fxamar/FlyWebSite/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/fxamar/FlyWebSite/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/fxamar/FlyWebSite/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/fxamar/FlyWebSite/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/fxamar/FlyWebSite/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/fxamar/FlyWebSite/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/fxamar/FlyWebSite/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/fxamar/FlyWebSite/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/fxamar/FlyWebSite/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxamar/FlyWebSite/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/fxamar/FlyWebSite/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/example/flybuy/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.flybuy 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity : FlutterActivity() {} 6 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /assets/icons/Back ICon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/icons/Success.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /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-6.7-all.zip 7 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | key.properties 8 | GeneratedPluginRegistrant.java 9 | 10 | # Remember to never publicly share your keystore. 11 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 12 | key.properties 13 | -------------------------------------------------------------------------------- /.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: adc687823a831bbebe28bdccfac1a628ca621513 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 | -------------------------------------------------------------------------------- /assets/icons/remove.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /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. -------------------------------------------------------------------------------- /assets/icons/facebook-2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/screens/sign_up/sign_up_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import './components/body.dart'; 4 | 5 | class SignUpScreen extends StatelessWidget { 6 | static const routeName = '/sign-up'; 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | return Scaffold( 11 | appBar: AppBar( 12 | title: Text("Sign Up"), 13 | ), 14 | body: Body(), 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lib/screens/sign_in/sign_in_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import './components/body.dart'; 4 | 5 | class SignInScreen extends StatelessWidget { 6 | static const String routeName = '/sign_in'; 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | return Scaffold( 11 | appBar: AppBar( 12 | title: Text("Sign in"), 13 | ), 14 | body: Body(), 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lib/screens/splash_screen/splash_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import './components/body.dart'; 3 | import '../../size_config.dart'; 4 | 5 | class SplashScreen extends StatelessWidget { 6 | static const String routeName = "/splash-screen"; 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | SizeConfig().init(context); 11 | return Scaffold( 12 | body: Body(), 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /assets/icons/ellipsis.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/models/Cart.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import './Product.dart'; 4 | 5 | class Cart { 6 | final Product product; 7 | final int numOfItem; 8 | 9 | Cart({@required this.product, @required this.numOfItem}); 10 | } 11 | 12 | List demoCarts = [ 13 | Cart(product: demoProducts[0], numOfItem: 2), 14 | Cart(product: demoProducts[1], numOfItem: 1), 15 | Cart(product: demoProducts[3], numOfItem: 1), 16 | ]; 17 | -------------------------------------------------------------------------------- /lib/screens/complete_profile/complete_profile_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import './components/body.dart'; 4 | 5 | class CompleteProfileScreen extends StatelessWidget { 6 | static const routeName = '/complete-profile'; 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | return Scaffold( 11 | appBar: AppBar( 12 | title: Text("Sign Up"), 13 | ), 14 | body: Body(), 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /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/screens/forgot_password/forgot_password_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import './components/body.dart'; 4 | 5 | class ForgotPasswordScreen extends StatelessWidget { 6 | static const String routeName = '/forgot-password'; 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | return Scaffold( 11 | appBar: AppBar( 12 | title: Text("Forgot password"), 13 | ), 14 | body: Body(), 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lib/screens/home/home_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import './components/body.dart'; 4 | import '../../components/custom_bottom_navigation_bar.dart'; 5 | 6 | class HomeScreen extends StatelessWidget { 7 | static const routeName = '/home'; 8 | 9 | @override 10 | Widget build(BuildContext context) { 11 | return Scaffold( 12 | body: Body(), 13 | bottomNavigationBar: CustomBottomNavigationBar(selectedMenu: Menu.home), 14 | ); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /lib/screens/otp/otp_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import './components/body.dart'; 4 | 5 | class OTPScreen extends StatelessWidget { 6 | OTPScreen(); 7 | static const routeName = '/otp'; 8 | 9 | @override 10 | Widget build(BuildContext context) { 11 | final phone = ModalRoute.of(context).settings.arguments; 12 | return Scaffold( 13 | appBar: AppBar( 14 | title: Text("OTP Verification"), 15 | ), 16 | body: Body(phone), 17 | ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /lib/screens/login_success/login_success_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import './components/body.dart'; 4 | 5 | class LoginSuccessScreen extends StatelessWidget { 6 | static const routeName = "/login-success"; 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | return Scaffold( 11 | appBar: AppBar( 12 | centerTitle: true, 13 | leading: SizedBox(), 14 | title: Text("Login Success"), 15 | ), 16 | body: Body(), 17 | ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/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 | -------------------------------------------------------------------------------- /assets/icons/Plus Icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/icons/Heart Icon_2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flybuy/screens/profile/profile_screen.dart'; 3 | 4 | import './theme.dart'; 5 | import './routes.dart'; 6 | 7 | import './screens/splash_screen/splash_screen.dart'; 8 | 9 | void main() { 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Fly Buy', 19 | theme: theme(), 20 | initialRoute: SplashScreen.routeName, 21 | routes: routes, 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/screens/product_details/product_details_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import './components/body.dart'; 4 | import '../../models/Product.dart'; 5 | import './components/custom_appbar.dart'; 6 | 7 | class ProductDetailsScreen extends StatelessWidget { 8 | static const routeName = '/product-details'; 9 | 10 | @override 11 | Widget build(BuildContext context) { 12 | final Product product = ModalRoute.of(context).settings.arguments; 13 | 14 | return Scaffold( 15 | backgroundColor: Color(0xFFF5F6F9), 16 | appBar: CustomAppBar(product.rating), 17 | body: Body(product: product,), 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/screens/profile/profile_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../../size_config.dart'; 4 | import './components/body.dart'; 5 | import '../../components/custom_bottom_navigation_bar.dart'; 6 | 7 | class ProfileScreen extends StatelessWidget { 8 | static const routeName = "/profile"; 9 | 10 | @override 11 | Widget build(BuildContext context) { 12 | SizeConfig().init(context); 13 | 14 | return Scaffold( 15 | appBar: AppBar( 16 | title: Text("Profile"), 17 | ), 18 | body: Body(), 19 | bottomNavigationBar: 20 | CustomBottomNavigationBar(selectedMenu: Menu.profile), 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flybuy", 3 | "short_name": "flybuy", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.50' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:4.1.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | jcenter() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /assets/icons/arrow_right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/components/custom_suffix_icon.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_svg/flutter_svg.dart'; 3 | 4 | import '../size_config.dart'; 5 | 6 | class CustomSuffixIcon extends StatelessWidget { 7 | const CustomSuffixIcon({ 8 | Key key, 9 | @required this.iconPath, 10 | }) : super(key: key); 11 | 12 | final String iconPath; 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return Padding( 17 | padding: EdgeInsets.fromLTRB( 18 | 0, 19 | getProportionateScreenWidth(20), 20 | getProportionateScreenWidth(20), 21 | getProportionateScreenWidth(20), 22 | ), 23 | child: SvgPicture.asset( 24 | iconPath, 25 | height: getProportionateScreenHeight(18), 26 | ), 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/screens/splash_screen/components/build_dot.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../../../constants.dart'; 4 | 5 | 6 | class BuildDot extends StatelessWidget { 7 | const BuildDot({ 8 | Key key, 9 | this.pageNumber, 10 | this.currentPage, 11 | }) : super(key: key); 12 | 13 | final int pageNumber, currentPage; 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return AnimatedContainer( 18 | duration: kAnimationDuration, 19 | margin: EdgeInsets.only(right: 6), 20 | width: pageNumber == currentPage ? 20 : 6, 21 | height: 6, 22 | decoration: BoxDecoration( 23 | color: pageNumber == currentPage ? kPrimaryColor : Color(0xFFD8D8D8), 24 | borderRadius: BorderRadius.circular(3), 25 | ), 26 | ); 27 | } 28 | } -------------------------------------------------------------------------------- /lib/components/no_account_text.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flybuy/screens/sign_up/sign_up_screen.dart'; 3 | 4 | import '../constants.dart'; 5 | 6 | class NoAccountText extends StatelessWidget { 7 | const NoAccountText({ 8 | Key key, 9 | }) : super(key: key); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return Row( 14 | mainAxisAlignment: MainAxisAlignment.center, 15 | children: [ 16 | Text("Don't have an account? "), 17 | TextButton( 18 | child: Text( 19 | "Sign Up", 20 | style: TextStyle(color: kPrimaryColor), 21 | ), 22 | onPressed: () => Navigator.pushNamed( 23 | context, 24 | SignUpScreen.routeName, 25 | ), 26 | ), 27 | ], 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /assets/icons/Check mark rounde.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/icons/Flash Icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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 | -------------------------------------------------------------------------------- /.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 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /assets/icons/Phone.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/screens/cart/cart_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import './components/body.dart'; 4 | import '../../models/Cart.dart'; 5 | import './components/custom_bottom_navigation_bar.dart'; 6 | 7 | class CartScreen extends StatelessWidget { 8 | static const routeName = '/cart'; 9 | 10 | @override 11 | Widget build(BuildContext context) { 12 | return Scaffold( 13 | appBar: appBar(context), 14 | body: Body(), 15 | bottomNavigationBar: CustomBottomNavigationBar(), 16 | ); 17 | } 18 | 19 | AppBar appBar(BuildContext context) { 20 | return AppBar( 21 | title: Column( 22 | children: [ 23 | Text( 24 | "Your Cart", 25 | style: TextStyle(color: Colors.black), 26 | ), 27 | Text( 28 | "${demoCarts.length} items", 29 | style: Theme.of(context).textTheme.caption, 30 | ), 31 | ], 32 | ), 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /assets/icons/Mail.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/icons/Search Icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/icons/receipt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/components/social_card.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_svg/flutter_svg.dart'; 3 | 4 | import '../size_config.dart'; 5 | 6 | class SocialCard extends StatelessWidget { 7 | SocialCard({ 8 | Key key, 9 | this.icon, 10 | this.press, 11 | }) : super(key: key); 12 | 13 | final String icon; 14 | final Function press; 15 | 16 | @override 17 | Widget build(BuildContext context) { 18 | return GestureDetector( 19 | onTap: press, 20 | child: Container( 21 | margin: 22 | EdgeInsets.symmetric(horizontal: getProportionateScreenWidth(10)), 23 | padding: EdgeInsets.all(getProportionateScreenWidth(12)), 24 | height: getProportionateScreenHeight(40), 25 | width: getProportionateScreenWidth(40), 26 | decoration: BoxDecoration( 27 | color: Color(0xFFF5F6F9), 28 | shape: BoxShape.circle, 29 | ), 30 | child: SvgPicture.asset(icon), 31 | ), 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/screens/home/components/section_title.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../../../size_config.dart'; 4 | 5 | class SectionTitle extends StatelessWidget { 6 | const SectionTitle({ 7 | Key key, 8 | @required this.title, 9 | @required this.press, 10 | }) : super(key: key); 11 | 12 | final String title; 13 | final GestureTapCallback press; 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return Padding( 18 | padding: 19 | EdgeInsets.symmetric(horizontal: getProportionateScreenWidth(20)), 20 | child: Row( 21 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 22 | children: [ 23 | Text( 24 | title, 25 | style: TextStyle( 26 | color: Colors.black, 27 | fontSize: getProportionateScreenWidth(20), 28 | ), 29 | ), 30 | GestureDetector(onTap: press, child: Text("See more")) 31 | ], 32 | ), 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/screens/product_details/components/top_rounded_container.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../../../size_config.dart'; 4 | 5 | class TopRoundedContainer extends StatelessWidget { 6 | const TopRoundedContainer({ 7 | Key key, 8 | @required this.color, 9 | @required this.child, 10 | }) : super(key: key); 11 | 12 | final Color color; 13 | final Widget child; 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return Container( 18 | width: double.infinity, 19 | // margin: EdgeInsets.only(top: getProportionateScreenWidth(20)), 20 | padding: EdgeInsets.only( 21 | top: getProportionateScreenWidth(20), 22 | bottom: getProportionateScreenWidth(20), 23 | ), 24 | decoration: BoxDecoration( 25 | color: color, 26 | borderRadius: BorderRadius.only( 27 | topLeft: Radius.circular(40), 28 | topRight: Radius.circular(40), 29 | ), 30 | ), 31 | child: child, 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /assets/icons/Heart Icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/components/rounded_icon_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../size_config.dart'; 4 | 5 | class RoundedIconButton extends StatelessWidget { 6 | const RoundedIconButton({ 7 | Key key, 8 | @required this.icon, 9 | @required this.press, 10 | }) : super(key: key); 11 | 12 | final icon; 13 | final GestureTapCallback press; 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return SizedBox( 18 | width: getProportionateScreenWidth(40), 19 | height: getProportionateScreenHeight(40), 20 | child: TextButton( 21 | onPressed: press, 22 | child: Icon( 23 | icon, 24 | color: Colors.black, 25 | ), 26 | style: ButtonStyle( 27 | shape: MaterialStateProperty.all( 28 | RoundedRectangleBorder( 29 | borderRadius: BorderRadius.circular(50), 30 | ), 31 | ), 32 | backgroundColor: MaterialStateProperty.all(Colors.white)), 33 | ), 34 | ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /assets/icons/Location point.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/icons/Lock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/icons/Close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /assets/icons/Error.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /lib/size_config.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class SizeConfig { 4 | static MediaQueryData _mediaQueryData; 5 | static double screenWidth; 6 | static double screenHeight; 7 | static double defaultSize; 8 | static Orientation orientation; 9 | 10 | void init(BuildContext context) { 11 | _mediaQueryData = MediaQuery.of(context); 12 | screenWidth = _mediaQueryData.size.width; 13 | screenHeight = _mediaQueryData.size.height; 14 | orientation = _mediaQueryData.orientation; 15 | } 16 | } 17 | 18 | // Get the proportionate height as per screen size 19 | double getProportionateScreenHeight(double inputHeight) { 20 | double screenHeight = SizeConfig.screenHeight; 21 | // 812 is the layout height that designer use 22 | return (inputHeight / 812.0) * screenHeight; 23 | } 24 | 25 | // Get the proportionate height as per screen size 26 | double getProportionateScreenWidth(double inputWidth) { 27 | double screenWidth = SizeConfig.screenWidth; 28 | // 375 is the layout width that designer use 29 | return (inputWidth / 375.0) * screenWidth; 30 | } 31 | -------------------------------------------------------------------------------- /assets/icons/Star Icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/screens/splash_screen/components/splash_content.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../../../constants.dart'; 4 | import '../../../size_config.dart'; 5 | 6 | class SplashContent extends StatelessWidget { 7 | const SplashContent({ 8 | Key key, 9 | this.text, 10 | this.image, 11 | }) : super(key: key); 12 | final String text, image; 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return Column( 17 | children: [ 18 | Spacer(flex: 2), 19 | Text( 20 | "FlyBuy", 21 | style: TextStyle( 22 | fontSize: getProportionateScreenWidth(36), 23 | color: kPrimaryColor, 24 | fontWeight: FontWeight.bold, 25 | ), 26 | ), 27 | Text( 28 | text, 29 | textAlign: TextAlign.center, 30 | ), 31 | Spacer(flex: 2), 32 | Image.asset( 33 | image, 34 | width: getProportionateScreenWidth(240), 35 | height: getProportionateScreenHeight(270), 36 | ), 37 | ], 38 | ); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /assets/icons/twitter.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/screens/home/components/home_header.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flybuy/screens/cart/cart_screen.dart'; 3 | 4 | import './search_field.dart'; 5 | import '../../../size_config.dart'; 6 | import './icon_button_with_counter.dart'; 7 | 8 | class HomeHeader extends StatelessWidget { 9 | const HomeHeader({ 10 | Key key, 11 | }) : super(key: key); 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return Padding( 16 | padding: EdgeInsets.symmetric( 17 | horizontal: getProportionateScreenWidth(20), 18 | ), 19 | child: Row( 20 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 21 | children: [ 22 | SearchField(), 23 | IconButtonWithCounter( 24 | svgSrc: 'assets/icons/Cart Icon.svg', 25 | press: () => Navigator.pushNamed(context, CartScreen.routeName), 26 | ), 27 | IconButtonWithCounter( 28 | svgSrc: 'assets/icons/Bell.svg', 29 | noOfItems: 3, 30 | press: () {}, 31 | ), 32 | ], 33 | ), 34 | ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 AdelRizq 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /lib/screens/login_success/components/body.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flybuy/components/default_button.dart'; 3 | import 'package:flybuy/constants.dart'; 4 | import 'package:flybuy/screens/home/home_screen.dart'; 5 | import 'package:flybuy/size_config.dart'; 6 | 7 | class Body extends StatelessWidget { 8 | @override 9 | Widget build(BuildContext context) { 10 | return Column( 11 | children: [ 12 | SizedBox(height: SizeConfig.screenHeight * 0.04), 13 | Image.asset( 14 | 'assets/images/success.png', 15 | height: SizeConfig.screenHeight * 0.4, 16 | ), 17 | SizedBox(height: SizeConfig.screenHeight * 0.08), 18 | Text( 19 | "Login Success", 20 | style: headingStyle, 21 | ), 22 | Spacer(), 23 | SizedBox( 24 | width: SizeConfig.screenWidth * .6, 25 | child: DefaultButton( 26 | text: "Back to home", 27 | press: () => Navigator.pushNamed(context, HomeScreen.routeName), 28 | ), 29 | ), 30 | Spacer(), 31 | ], 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /assets/icons/User Icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/icons/User.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/screens/home/components/body.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import './categories.dart'; 4 | import './home_header.dart'; 5 | import './special_offers.dart'; 6 | import './discount_banner.dart'; 7 | import './popular_products.dart'; 8 | import '../../../size_config.dart'; 9 | 10 | class Body extends StatelessWidget { 11 | @override 12 | Widget build(BuildContext context) { 13 | return SafeArea( 14 | child: SingleChildScrollView( 15 | child: Column( 16 | children: [ 17 | SizedBox(height: getProportionateScreenHeight(20)), 18 | HomeHeader(), 19 | SizedBox(height: getProportionateScreenHeight(30)), 20 | DiscountBanner(), 21 | SizedBox(height: getProportionateScreenHeight(30)), 22 | Categories(), 23 | SizedBox(height: getProportionateScreenHeight(30)), 24 | SpecialOffers(), 25 | SizedBox(height: getProportionateScreenHeight(30)), 26 | PopularProducts(), 27 | SizedBox(height: getProportionateScreenHeight(30)), 28 | ], 29 | ), 30 | ), 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /assets/icons/Bell.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/components/default_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../constants.dart'; 4 | import '../size_config.dart'; 5 | 6 | class DefaultButton extends StatelessWidget { 7 | const DefaultButton({ 8 | Key key, 9 | this.text, 10 | this.press, 11 | }) : super(key: key); 12 | final String text; 13 | final Function press; 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return ElevatedButton( 18 | onPressed: press, 19 | child: Text( 20 | text, 21 | style: TextStyle( 22 | fontSize: getProportionateScreenWidth(18), 23 | ), 24 | ), 25 | style: ButtonStyle( 26 | backgroundColor: MaterialStateProperty.all(kPrimaryColor), 27 | shape: MaterialStateProperty.all( 28 | RoundedRectangleBorder( 29 | borderRadius: BorderRadius.circular(20), 30 | ), 31 | ), 32 | minimumSize: MaterialStateProperty.all( 33 | Size( 34 | getProportionateScreenWidth(double.infinity), 35 | getProportionateScreenHeight(56), 36 | ), 37 | ), 38 | ), 39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:flybuy/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /lib/screens/home/components/search_field.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../../../constants.dart'; 4 | import '../../../size_config.dart'; 5 | 6 | class SearchField extends StatelessWidget { 7 | const SearchField({ 8 | Key key, 9 | }) : super(key: key); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return Container( 14 | width: SizeConfig.screenWidth * .6, 15 | // height: 50, 16 | decoration: BoxDecoration( 17 | color: kSecondaryColor.withOpacity(.1), 18 | borderRadius: BorderRadius.circular(15), 19 | ), 20 | child: TextFormField( 21 | onChanged: (value) { 22 | // search value 🔍 23 | }, 24 | decoration: InputDecoration( 25 | enabledBorder: InputBorder.none, 26 | focusedBorder: InputBorder.none, 27 | contentPadding: EdgeInsets.symmetric( 28 | horizontal: getProportionateScreenWidth(20), 29 | vertical: getProportionateScreenHeight(9), 30 | ), 31 | hintText: "Search product", 32 | prefixIcon: Icon(Icons.search), 33 | ), 34 | ), 35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /assets/icons/google-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /assets/icons/Discover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/icons/Trash.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/icons/Question mark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/icons/Parcel.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/icons/Cart Icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/screens/home/components/discount_banner.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../../../constants.dart'; 4 | import '../../../size_config.dart'; 5 | 6 | class DiscountBanner extends StatelessWidget { 7 | const DiscountBanner({ 8 | Key key, 9 | }) : super(key: key); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return Container( 14 | margin: EdgeInsets.symmetric( 15 | horizontal: getProportionateScreenWidth(20), 16 | ), 17 | padding: EdgeInsets.symmetric( 18 | horizontal: getProportionateScreenWidth(20), 19 | vertical: getProportionateScreenHeight(15), 20 | ), 21 | width: double.infinity, 22 | decoration: BoxDecoration( 23 | color: kPrimaryColor, borderRadius: BorderRadius.circular(20)), 24 | child: Text.rich( 25 | TextSpan( 26 | text: "A Summer Surprise\n", 27 | style: TextStyle( 28 | color: Colors.white, 29 | ), 30 | children: [ 31 | TextSpan( 32 | text: "Cashback 20%", 33 | style: TextStyle( 34 | fontSize: 24, 35 | fontWeight: FontWeight.bold, 36 | ), 37 | ), 38 | ], 39 | ), 40 | ), 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lib/screens/forgot_password/components/body.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../../../constants.dart'; 4 | import '../../../size_config.dart'; 5 | import './forgot_password_form.dart'; 6 | 7 | 8 | class Body extends StatelessWidget { 9 | @override 10 | Widget build(BuildContext context) { 11 | return SafeArea( 12 | child: SizedBox( 13 | width: double.infinity, 14 | child: SingleChildScrollView( 15 | child: Padding( 16 | padding: EdgeInsets.symmetric( 17 | horizontal: getProportionateScreenWidth(20)), 18 | child: Column( 19 | children: [ 20 | SizedBox(height: SizeConfig.screenHeight * 0.04), 21 | Text( 22 | "Forgot Password", 23 | style: headingStyle, 24 | textAlign: TextAlign.center, 25 | ), 26 | Text( 27 | "Please enter your email and we will send/nyou a link to return to your account", 28 | textAlign: TextAlign.center, 29 | ), 30 | SizedBox(height: SizeConfig.screenHeight * 0.08), 31 | ForgotPasswordForm(), 32 | ], 33 | ), 34 | ), 35 | ), 36 | ), 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /assets/icons/Log out.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/routes.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import './screens/otp/otp_screen.dart'; 4 | import './screens/cart/cart_screen.dart'; 5 | import './screens/home/home_screen.dart'; 6 | import './screens/sign_in/sign_in_screen.dart'; 7 | import './screens/sign_up/sign_up_screen.dart'; 8 | import './screens/profile/profile_screen.dart'; 9 | import './screens/splash_screen/splash_screen.dart'; 10 | import './screens/login_success/login_success_screen.dart'; 11 | import './screens/forgot_password/forgot_password_screen.dart'; 12 | import './screens/complete_profile/complete_profile_screen.dart'; 13 | import './screens/product_details/product_details_screen.dart'; 14 | 15 | Map routes = { 16 | OTPScreen.routeName: (ctx) => OTPScreen(), 17 | CartScreen.routeName: (ctx) => CartScreen(), 18 | HomeScreen.routeName: (ctx) => HomeScreen(), 19 | SplashScreen.routeName: (ctx) => SplashScreen(), 20 | SignInScreen.routeName: (ctx) => SignInScreen(), 21 | SignUpScreen.routeName: (ctx) => SignUpScreen(), 22 | ProfileScreen.routeName: (ctx) => ProfileScreen(), 23 | LoginSuccessScreen.routeName: (ctx) => LoginSuccessScreen(), 24 | ForgotPasswordScreen.routeName: (ctx) => ForgotPasswordScreen(), 25 | ProductDetailsScreen.routeName: (ctx) => ProductDetailsScreen(), 26 | CompleteProfileScreen.routeName: (ctx) => CompleteProfileScreen(), 27 | }; 28 | -------------------------------------------------------------------------------- /assets/icons/Camera Icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/icons/Call.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/icons/Bill Icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/icons/Conversation.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/screens/home/components/popular_products.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import './section_title.dart'; 4 | import '../../../size_config.dart'; 5 | import '../../../models/Product.dart'; 6 | import '../../../components/product_card.dart'; 7 | import '../../product_details/product_details_screen.dart'; 8 | 9 | class PopularProducts extends StatelessWidget { 10 | const PopularProducts({ 11 | Key key, 12 | }) : super(key: key); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return Column( 17 | children: [ 18 | SectionTitle(title: "Popular Products", press: () {}), 19 | SizedBox(height: getProportionateScreenHeight(20)), 20 | SingleChildScrollView( 21 | scrollDirection: Axis.horizontal, 22 | child: Row( 23 | crossAxisAlignment: CrossAxisAlignment.start, 24 | children: [ 25 | ...List.generate( 26 | demoProducts.length, 27 | (index) => ProductCard( 28 | product: demoProducts[index], 29 | press: () => Navigator.pushNamed( 30 | context, 31 | ProductDetailsScreen.routeName, 32 | arguments: demoProducts[index], 33 | ), 34 | ), 35 | ), 36 | SizedBox( 37 | width: getProportionateScreenWidth(20), 38 | ) 39 | ], 40 | ), 41 | ), 42 | ], 43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/theme.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'constants.dart'; 4 | 5 | ThemeData theme() { 6 | return ThemeData( 7 | scaffoldBackgroundColor: Colors.white, 8 | fontFamily: 'Muli', 9 | appBarTheme: appBarTheme(), 10 | textTheme: testTheme(), 11 | inputDecorationTheme: inputDecorationTheme(), 12 | primarySwatch: Colors.blue, 13 | ); 14 | } 15 | 16 | InputDecorationTheme inputDecorationTheme() { 17 | OutlineInputBorder outlineInputBorder = OutlineInputBorder( 18 | borderRadius: BorderRadius.circular(24), 19 | borderSide: BorderSide(color: kTextColor), 20 | gapPadding: 6, 21 | ); 22 | return InputDecorationTheme( 23 | floatingLabelBehavior: FloatingLabelBehavior.always, 24 | contentPadding: EdgeInsets.symmetric( 25 | vertical: 20, 26 | horizontal: 30, 27 | ), 28 | border: outlineInputBorder, 29 | enabledBorder: outlineInputBorder, 30 | focusedBorder: outlineInputBorder, 31 | ); 32 | } 33 | 34 | TextTheme testTheme() { 35 | return TextTheme( 36 | bodyText1: TextStyle(color: kTextColor), 37 | bodyText2: TextStyle(color: kTextColor), 38 | ); 39 | } 40 | 41 | AppBarTheme appBarTheme() { 42 | return AppBarTheme( 43 | centerTitle: true, 44 | color: Colors.white, 45 | elevation: 0, 46 | brightness: Brightness.light, 47 | iconTheme: IconThemeData(color: Colors.black), 48 | textTheme: TextTheme( 49 | headline6: TextStyle( 50 | color: Color(0xFF8b8b8b), 51 | fontSize: 18, 52 | ), 53 | ), 54 | ); 55 | } 56 | -------------------------------------------------------------------------------- /assets/icons/Cash.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/screens/complete_profile/components/body.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../../../constants.dart'; 4 | import './complete_profile_form.dart'; 5 | import '../../../size_config.dart'; 6 | 7 | class Body extends StatelessWidget { 8 | @override 9 | Widget build(BuildContext context) { 10 | return SafeArea( 11 | child: SizedBox( 12 | width: double.infinity, 13 | child: Padding( 14 | padding: 15 | EdgeInsets.symmetric(horizontal: getProportionateScreenWidth(25)), 16 | child: SingleChildScrollView( 17 | child: Column( 18 | children: [ 19 | SizedBox(height: SizeConfig.screenHeight * 0.02), 20 | Text( 21 | "Complete Profile", 22 | style: headingStyle, 23 | textAlign: TextAlign.center, 24 | ), 25 | Text( 26 | "Complete your profile details", 27 | textAlign: TextAlign.center, 28 | ), 29 | SizedBox(height: SizeConfig.screenHeight * 0.06), 30 | CompleteProfileForm(), 31 | SizedBox(height: SizeConfig.screenHeight * 0.06), 32 | Text( 33 | "By continuing you confirm that you agree\nwith our terms and conditions", 34 | textAlign: TextAlign.center, 35 | ), 36 | SizedBox(height: SizeConfig.screenHeight * 0.03), 37 | ], 38 | ), 39 | ), 40 | ), 41 | ), 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /lib/screens/cart/components/body.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_svg/flutter_svg.dart'; 3 | import 'package:flybuy/size_config.dart'; 4 | 5 | import './cart_item_card.dart'; 6 | import '../../../models/Cart.dart'; 7 | 8 | class Body extends StatelessWidget { 9 | @override 10 | Widget build(BuildContext context) { 11 | return Padding( 12 | padding: 13 | EdgeInsets.symmetric(horizontal: getProportionateScreenWidth(20)), 14 | child: ListView.builder( 15 | itemCount: demoCarts.length, 16 | itemBuilder: (ctx, index) => Padding( 17 | padding: 18 | EdgeInsets.symmetric(vertical: getProportionateScreenWidth(10)), 19 | child: Dismissible( 20 | key: Key(demoCarts[index].product.id.toString()), 21 | direction: DismissDirection.endToStart, 22 | onDismissed: (direction) { 23 | demoCarts.removeAt(index); 24 | }, 25 | background: Container( 26 | decoration: BoxDecoration( 27 | color: Color(0xFFFFE5E5), 28 | borderRadius: BorderRadius.circular(15)), 29 | padding: EdgeInsets.symmetric(horizontal: 20), 30 | child: Row( 31 | children: [ 32 | Spacer(), 33 | SvgPicture.asset("assets/icons/Trash.svg"), 34 | ], 35 | ), 36 | ), 37 | child: CartItemCard( 38 | cartItem: demoCarts[index], 39 | ), 40 | ), 41 | ), 42 | ), 43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | flybuy 30 | 31 | 32 | 33 | 36 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /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 | flybuy 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 | -------------------------------------------------------------------------------- /assets/icons/Gift Icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/screens/profile/components/body.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import './profile_picture.dart'; 4 | import '../../../size_config.dart'; 5 | import './profile_section_bar.dart'; 6 | 7 | class Body extends StatelessWidget { 8 | @override 9 | Widget build(BuildContext context) { 10 | return SizedBox( 11 | width: double.infinity, 12 | child: Column( 13 | children: [ 14 | SizedBox(height: getProportionateScreenHeight(40)), 15 | ProfilePicture(), 16 | SizedBox(height: getProportionateScreenHeight(60)), 17 | ProfileSectionButton( 18 | text: "My Account", 19 | icon: "assets/icons/User Icon.svg", 20 | press: () {}, 21 | ), 22 | SizedBox(height: getProportionateScreenHeight(20)), 23 | ProfileSectionButton( 24 | text: "Notifications", 25 | icon: "assets/icons/Bell.svg", 26 | press: () {}, 27 | ), 28 | SizedBox(height: getProportionateScreenHeight(20)), 29 | ProfileSectionButton( 30 | text: "Settings", 31 | icon: "assets/icons/Settings.svg", 32 | press: () {}, 33 | ), 34 | SizedBox(height: getProportionateScreenHeight(20)), 35 | ProfileSectionButton( 36 | text: "Help Center", 37 | icon: "assets/icons/Question mark.svg", 38 | press: () {}, 39 | ), 40 | SizedBox(height: getProportionateScreenHeight(20)), 41 | ProfileSectionButton( 42 | text: "Log Out", 43 | icon: "assets/icons/Log out.svg", 44 | press: () {}, 45 | ), 46 | ], 47 | ), 48 | ); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib/screens/profile/components/profile_picture.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_svg/flutter_svg.dart'; 3 | 4 | import '../../../size_config.dart'; 5 | 6 | class ProfilePicture extends StatelessWidget { 7 | const ProfilePicture({ 8 | Key key, 9 | }) : super(key: key); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return Stack( 14 | clipBehavior: Clip.none, 15 | children: [ 16 | SizedBox( 17 | width: getProportionateScreenWidth(120), 18 | height: getProportionateScreenWidth(120), 19 | child: ClipRRect( 20 | borderRadius: BorderRadius.circular(60), 21 | child: Image.asset( 22 | "assets/images/Profile Image.png", 23 | fit: BoxFit.cover, 24 | width: getProportionateScreenWidth(120), 25 | ), 26 | ), 27 | ), 28 | Positioned( 29 | bottom: 0, 30 | right: -10, 31 | child: SizedBox( 32 | width: getProportionateScreenWidth(48), 33 | height: getProportionateScreenWidth(48), 34 | child: TextButton( 35 | onPressed: () {}, 36 | child: SvgPicture.asset("assets/icons/Camera Icon.svg"), 37 | style: ButtonStyle( 38 | shape: MaterialStateProperty.all( 39 | RoundedRectangleBorder( 40 | side: BorderSide(color: Colors.white), 41 | borderRadius: BorderRadius.circular(50), 42 | ), 43 | ), 44 | backgroundColor: MaterialStateProperty.all(Color(0xFFF5F6F9)), 45 | ), 46 | ), 47 | ), 48 | ) 49 | ], 50 | ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/screens/product_details/components/custom_appbar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_svg/flutter_svg.dart'; 3 | 4 | import '../../../size_config.dart'; 5 | import '../../../components/rounded_icon_button.dart'; 6 | 7 | class CustomAppBar extends PreferredSize { 8 | final double rating; 9 | 10 | CustomAppBar(this.rating); 11 | 12 | @override 13 | // TODO: implement preferredSize 14 | Size get preferredSize => Size.fromHeight(AppBar().preferredSize.height); 15 | 16 | @override 17 | Widget build(BuildContext context) { 18 | return SafeArea( 19 | child: Padding( 20 | padding: EdgeInsets.symmetric( 21 | horizontal: getProportionateScreenWidth(20), 22 | vertical: getProportionateScreenHeight(5), 23 | ), 24 | child: Row( 25 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 26 | children: [ 27 | RoundedIconButton( 28 | icon: Icons.arrow_back, 29 | press: () => Navigator.pop(context), 30 | ), 31 | Container( 32 | decoration: BoxDecoration( 33 | color: Colors.white, 34 | borderRadius: BorderRadius.circular(15), 35 | ), 36 | padding: EdgeInsets.symmetric(horizontal: 15, vertical: 5), 37 | child: Row( 38 | children: [ 39 | Text( 40 | "$rating", 41 | style: TextStyle(fontWeight: FontWeight.w600), 42 | ), 43 | const SizedBox(width: 5), 44 | SvgPicture.asset("assets/icons/Star Icon.svg"), 45 | ], 46 | ), 47 | ) 48 | ], 49 | ), 50 | ), 51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /assets/icons/Chat bubble Icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/icons/Game Icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/screens/profile/components/profile_section_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_svg/flutter_svg.dart'; 3 | 4 | import '../../../constants.dart'; 5 | import '../../../size_config.dart'; 6 | 7 | 8 | class ProfileSectionButton extends StatelessWidget { 9 | const ProfileSectionButton({ 10 | Key key, 11 | @required this.text, 12 | @required this.icon, 13 | @required this.press, 14 | }) : super(key: key); 15 | 16 | final String text, icon; 17 | final GestureTapCallback press; 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | return Padding( 22 | padding: EdgeInsets.symmetric( 23 | horizontal: getProportionateScreenWidth(20), 24 | ), 25 | child: TextButton( 26 | style: ButtonStyle( 27 | backgroundColor: MaterialStateProperty.all(Color(0xFFF2F6F5)), 28 | padding: MaterialStateProperty.all(EdgeInsets.all(20)), 29 | shape: MaterialStateProperty.all( 30 | RoundedRectangleBorder( 31 | borderRadius: BorderRadius.circular(20), 32 | ), 33 | ), 34 | ), 35 | onPressed: press, 36 | child: Row( 37 | children: [ 38 | SizedBox( 39 | height: getProportionateScreenHeight(24), 40 | child: SvgPicture.asset( 41 | icon, 42 | width: 20, 43 | color: kPrimaryColor, 44 | ), 45 | ), 46 | SizedBox( 47 | width: getProportionateScreenWidth(20) 48 | ), 49 | Text( 50 | text, 51 | style: TextStyle(color: Colors.black54), 52 | ), 53 | Spacer(), 54 | Icon( 55 | Icons.arrow_forward_ios_rounded, 56 | size: 18, 57 | color: Colors.black45, 58 | ), 59 | ], 60 | ), 61 | ), 62 | ); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /lib/constants.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import './size_config.dart'; 3 | 4 | const kPrimaryColor = Color(0xFF6776FF); 5 | const kPrimaryLightColor = Color(0xFFDFECFF); 6 | const kPrimaryGradientColor = LinearGradient( 7 | begin: Alignment.topLeft, 8 | end: Alignment.bottomRight, 9 | colors: [Color(0xFF3EA5FF), Color(0xFF4376FF)], 10 | ); 11 | const kSecondaryColor = Color(0xFF979797); 12 | const kTextColor = Color(0xFF757575); 13 | 14 | const kAnimationDuration = Duration(milliseconds: 200); 15 | 16 | final headingStyle = TextStyle( 17 | fontSize: getProportionateScreenWidth(28), 18 | fontWeight: FontWeight.bold, 19 | color: Colors.black, 20 | height: 1.5, 21 | ); 22 | 23 | const defaultDuration = Duration(milliseconds: 250); 24 | 25 | // Form Error 26 | final RegExp emailValidatorRegExp = 27 | RegExp(r"^[a-zA-Z0-9.]+@[a-zA-Z0-9]+\.[a-zA-Z]+"); 28 | const String kEmailNullError = "Please Enter your email"; 29 | const String kInvalidEmailError = "Please Enter Valid Email"; 30 | const String kPassNullError = "Please Enter your password"; 31 | const String kShortPassError = "Password is too short, at least 8 chars"; 32 | const String kMatchPassError = "Passwords don't match"; 33 | const String kFirstNamelNullError = "Please Enter your first name"; 34 | const String kLastNamelNullError = "Please Enter your last name"; 35 | const String kPhoneNumberNullError = "Please Enter your phone number"; 36 | const String kAddressNullError = "Please Enter your address"; 37 | 38 | final otpInputDecoration = InputDecoration( 39 | contentPadding: 40 | EdgeInsets.symmetric(vertical: getProportionateScreenWidth(15)), 41 | border: outlineInputBorder(), 42 | focusedBorder: outlineInputBorder(), 43 | enabledBorder: outlineInputBorder(), 44 | ); 45 | 46 | OutlineInputBorder outlineInputBorder() { 47 | return OutlineInputBorder( 48 | borderRadius: BorderRadius.circular(getProportionateScreenWidth(15)), 49 | borderSide: BorderSide(color: kTextColor), 50 | ); 51 | } 52 | -------------------------------------------------------------------------------- /lib/screens/cart/components/cart_item_card.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../../../constants.dart'; 4 | import '../../../size_config.dart'; 5 | 6 | class CartItemCard extends StatelessWidget { 7 | const CartItemCard({ 8 | Key key, 9 | @required this.cartItem, 10 | }) : super(key: key); 11 | 12 | final cartItem; 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return Row( 17 | children: [ 18 | SizedBox( 19 | width: getProportionateScreenWidth(88), 20 | child: AspectRatio( 21 | aspectRatio: .88, 22 | child: Container( 23 | padding: const EdgeInsets.all(10), 24 | decoration: BoxDecoration( 25 | color: Color(0xFFF5F6F9), 26 | borderRadius: BorderRadius.circular(15), 27 | ), 28 | child: Image.asset(cartItem.product.images[0]), 29 | ), 30 | ), 31 | ), 32 | SizedBox(width: getProportionateScreenWidth(20)), 33 | Column( 34 | crossAxisAlignment: CrossAxisAlignment.start, 35 | children: [ 36 | Text( 37 | "${cartItem.product.title}", 38 | maxLines: 2, 39 | style: TextStyle(color: Colors.black, fontSize: 16), 40 | ), 41 | const SizedBox(height: 8), 42 | Text.rich( 43 | TextSpan( 44 | text: '\$${cartItem.product.price}', 45 | style: TextStyle( 46 | fontWeight: FontWeight.w600, 47 | color: kPrimaryColor, 48 | ), 49 | children: [ 50 | TextSpan( 51 | text: ' x${cartItem.numOfItem}', 52 | style: TextStyle(color: kTextColor), 53 | ), 54 | ], 55 | ), 56 | ), 57 | ], 58 | ), 59 | ], 60 | ); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /lib/screens/product_details/components/body.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flybuy/components/default_button.dart'; 3 | 4 | import '../../../size_config.dart'; 5 | import './colors_dots.dart'; 6 | import './product_images.dart'; 7 | import './product_description.dart'; 8 | import './top_rounded_container.dart'; 9 | import '../../../models/Product.dart'; 10 | 11 | class Body extends StatelessWidget { 12 | final Product product; 13 | 14 | const Body({Key key, this.product}) : super(key: key); 15 | @override 16 | Widget build(BuildContext context) { 17 | return SingleChildScrollView( 18 | child: Column( 19 | children: [ 20 | ProductImages(product: product), 21 | Container( 22 | margin: EdgeInsets.only(top: getProportionateScreenWidth(20)), 23 | child: TopRoundedContainer( 24 | color: Colors.white, 25 | child: ProductDescription( 26 | product: product, 27 | pressOnSeeMore: () {}, 28 | ), 29 | ), 30 | ), 31 | Container( 32 | color: Colors.white, 33 | child: TopRoundedContainer( 34 | color: Color(0xFFF9F7F6), 35 | child: Column( 36 | children: [ 37 | ColorDots(product: product), 38 | ], 39 | ), 40 | ), 41 | ), 42 | TopRoundedContainer( 43 | color: Colors.white, 44 | child: Padding( 45 | padding: EdgeInsets.only( 46 | left: SizeConfig.screenWidth * .15, 47 | right: SizeConfig.screenWidth * .15, 48 | top: getProportionateScreenWidth(10), 49 | bottom: getProportionateScreenWidth(20), 50 | ), 51 | child: DefaultButton(text: "Add to Cart", press: () {}), 52 | ), 53 | ), 54 | ], 55 | ), 56 | ); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /assets/icons/Shop Icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/screens/product_details/components/product_images.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../../../constants.dart'; 4 | import '../../../size_config.dart'; 5 | import '../../../models/Product.dart'; 6 | 7 | class ProductImages extends StatefulWidget { 8 | const ProductImages({ 9 | Key key, 10 | @required this.product, 11 | }) : super(key: key); 12 | 13 | final Product product; 14 | 15 | @override 16 | _ProductImagesState createState() => _ProductImagesState(); 17 | } 18 | 19 | class _ProductImagesState extends State { 20 | int selectedImage = 0; 21 | 22 | @override 23 | Widget build(BuildContext context) { 24 | return Column( 25 | children: [ 26 | SizedBox( 27 | width: getProportionateScreenHeight(240), 28 | child: AspectRatio( 29 | aspectRatio: 1, 30 | child: Image.asset(widget.product.images[selectedImage]), 31 | ), 32 | ), 33 | Row( 34 | mainAxisAlignment: MainAxisAlignment.center, 35 | children: [ 36 | ...List.generate( 37 | widget.product.images.length, 38 | (index) => buildSmallImagePreview(index), 39 | ), 40 | ], 41 | ), 42 | ], 43 | ); 44 | } 45 | 46 | GestureDetector buildSmallImagePreview(int index) { 47 | return GestureDetector( 48 | onTap: () { 49 | setState(() { 50 | selectedImage = index; 51 | }); 52 | }, 53 | child: Container( 54 | margin: EdgeInsets.symmetric( 55 | horizontal: getProportionateScreenWidth(10), 56 | ), 57 | padding: EdgeInsets.all(getProportionateScreenHeight(4)), 58 | height: getProportionateScreenHeight(48), 59 | width: getProportionateScreenWidth(48), 60 | decoration: BoxDecoration( 61 | color: Colors.white, 62 | borderRadius: BorderRadius.circular(10), 63 | border: Border.all( 64 | color: selectedImage == index ? kPrimaryColor : Colors.transparent, 65 | ), 66 | ), 67 | child: Image.asset(widget.product.images[index]), 68 | ), 69 | ); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /lib/screens/forgot_password/components/forgot_password_form.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../../../constants.dart'; 4 | import '../../../size_config.dart'; 5 | import '../../../components/default_button.dart'; 6 | import '../../../components/no_account_text.dart'; 7 | import '../../../components/custom_suffix_icon.dart'; 8 | 9 | 10 | class ForgotPasswordForm extends StatefulWidget { 11 | @override 12 | _ForgotPasswordFormState createState() => _ForgotPasswordFormState(); 13 | } 14 | 15 | class _ForgotPasswordFormState extends State { 16 | final _formKey = GlobalKey(); 17 | List errors = []; 18 | String email; 19 | bool firstSubmit = false; 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return Column( 24 | children: [ 25 | Form( 26 | key: _formKey, 27 | child: TextFormField( 28 | onSaved: (newEmail) => this.email = newEmail, 29 | onChanged: (email) { 30 | if (firstSubmit) _formKey.currentState.validate(); 31 | }, 32 | validator: (email) { 33 | if (email.isEmpty) { 34 | return kEmailNullError; 35 | } else if (email.isNotEmpty && 36 | !emailValidatorRegExp.hasMatch(email)) { 37 | return kInvalidEmailError; 38 | } 39 | 40 | return null; 41 | }, 42 | decoration: InputDecoration( 43 | labelText: "Email", 44 | hintText: "Enter your email", 45 | suffixIcon: CustomSuffixIcon(iconPath: "assets/icons/Mail.svg"), 46 | ), 47 | keyboardType: TextInputType.emailAddress, 48 | ), 49 | ), 50 | SizedBox(height: SizeConfig.screenHeight * 0.1), 51 | DefaultButton( 52 | text: 'Continue', 53 | press: () { 54 | if (_formKey.currentState.validate()) { 55 | // send an email 56 | } 57 | firstSubmit = true; 58 | }, 59 | ), 60 | SizedBox(height: SizeConfig.screenHeight * 0.1), 61 | NoAccountText(), 62 | ], 63 | ); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /lib/screens/sign_in/components/body.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flybuy/constants.dart'; 3 | 4 | import './sign_in_form.dart'; 5 | import '../../../size_config.dart'; 6 | import '../../../components/social_card.dart'; 7 | import '../../../components/no_account_text.dart'; 8 | 9 | class Body extends StatelessWidget { 10 | @override 11 | Widget build(BuildContext context) { 12 | return SafeArea( 13 | child: SizedBox( 14 | width: double.infinity, 15 | child: Padding( 16 | padding: 17 | EdgeInsets.symmetric(horizontal: getProportionateScreenWidth(25)), 18 | child: SingleChildScrollView( 19 | child: Column( 20 | children: [ 21 | SizedBox(height: SizeConfig.screenHeight * 0.04), 22 | Text( 23 | "Welcome Back", 24 | style: headingStyle, 25 | textAlign: TextAlign.center, 26 | ), 27 | Text( 28 | "Sign in with your email and password\nor continue with social media", 29 | textAlign: TextAlign.center, 30 | ), 31 | SizedBox(height: SizeConfig.screenHeight * 0.08), 32 | SignForm(), 33 | SizedBox(height: SizeConfig.screenHeight * 0.08), 34 | Row( 35 | mainAxisAlignment: MainAxisAlignment.center, 36 | children: [ 37 | SocialCard( 38 | icon: "assets/icons/google-icon.svg", 39 | press: () {}, 40 | ), 41 | SocialCard( 42 | icon: "assets/icons/facebook-2.svg", 43 | press: () {}, 44 | ), 45 | SocialCard( 46 | icon: "assets/icons/twitter.svg", 47 | press: () {}, 48 | ), 49 | ], 50 | ), 51 | SizedBox(height: getProportionateScreenHeight(20)), 52 | NoAccountText() 53 | ], 54 | ), 55 | ), 56 | ), 57 | ), 58 | ); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 13 | 17 | 21 | 26 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /lib/screens/sign_up/components/body.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../../../constants.dart'; 4 | import './sign_up_form.dart'; 5 | import '../../../size_config.dart'; 6 | import '../../../components/social_card.dart'; 7 | 8 | class Body extends StatelessWidget { 9 | @override 10 | Widget build(BuildContext context) { 11 | return SafeArea( 12 | child: SizedBox( 13 | width: double.infinity, 14 | child: Padding( 15 | padding: 16 | EdgeInsets.symmetric(horizontal: getProportionateScreenWidth(25)), 17 | child: SingleChildScrollView( 18 | child: Column( 19 | children: [ 20 | SizedBox(height: SizeConfig.screenHeight * 0.02), 21 | Text( 22 | "Register Account", 23 | style: headingStyle, 24 | textAlign: TextAlign.center, 25 | ), 26 | Text( 27 | "Complete your details or continue\nwith social media", 28 | textAlign: TextAlign.center, 29 | ), 30 | SizedBox(height: SizeConfig.screenHeight * 0.06), 31 | SignUpForm(), 32 | SizedBox(height: SizeConfig.screenHeight * 0.06), 33 | Row( 34 | mainAxisAlignment: MainAxisAlignment.center, 35 | children: [ 36 | SocialCard( 37 | icon: "assets/icons/google-icon.svg", 38 | press: () {}, 39 | ), 40 | SocialCard( 41 | icon: "assets/icons/facebook-2.svg", 42 | press: () {}, 43 | ), 44 | SocialCard( 45 | icon: "assets/icons/twitter.svg", 46 | press: () {}, 47 | ), 48 | ], 49 | ), 50 | SizedBox(height: getProportionateScreenHeight(20)), 51 | Text( 52 | "By continuing you confirm that you agree\nwith our terms and conditions", 53 | textAlign: TextAlign.center, 54 | ), 55 | ], 56 | ), 57 | ), 58 | ), 59 | ), 60 | ); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /lib/screens/home/components/icon_button_with_counter.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_svg/flutter_svg.dart'; 3 | 4 | import '../../../constants.dart'; 5 | import '../../../size_config.dart'; 6 | 7 | class IconButtonWithCounter extends StatelessWidget { 8 | const IconButtonWithCounter({ 9 | Key key, 10 | @required this.svgSrc, 11 | this.noOfItems = 0, 12 | @required this.press, 13 | }) : super(key: key); 14 | 15 | final String svgSrc; 16 | final int noOfItems; 17 | final GestureTapCallback press; 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | return InkWell( 22 | onTap: press, 23 | borderRadius: BorderRadius.circular(50), 24 | child: Stack( 25 | clipBehavior: Clip.none, 26 | children: [ 27 | Container( 28 | padding: EdgeInsets.all( 29 | getProportionateScreenWidth(12), 30 | ), 31 | height: getProportionateScreenHeight(46), 32 | width: getProportionateScreenWidth(46), 33 | decoration: BoxDecoration( 34 | color: kSecondaryColor.withOpacity(.1), 35 | shape: BoxShape.circle, 36 | ), 37 | child: SvgPicture.asset(svgSrc), 38 | ), 39 | if (noOfItems != 0) 40 | Positioned( 41 | top: -3, 42 | right: 0, 43 | child: Container( 44 | height: getProportionateScreenHeight(12), 45 | width: getProportionateScreenWidth(12), 46 | decoration: BoxDecoration( 47 | color: Color(0xFF4848FF), 48 | border: Border.all(width: 1, color: Colors.white), 49 | shape: BoxShape.circle, 50 | ), 51 | child: Center( 52 | child: Text( 53 | "$noOfItems", 54 | style: TextStyle( 55 | color: Colors.white, 56 | fontSize: getProportionateScreenWidth(10), 57 | height: getProportionateScreenHeight(1), 58 | fontWeight: FontWeight.w600, 59 | ), 60 | ), 61 | ), 62 | ), 63 | ), 64 | ], 65 | ), 66 | ); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | def keystoreProperties = new Properties() 29 | def keystorePropertiesFile = rootProject.file('key.properties') 30 | if (keystorePropertiesFile.exists()) { 31 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) 32 | } 33 | 34 | android { 35 | compileSdkVersion 30 36 | 37 | sourceSets { 38 | main.java.srcDirs += 'src/main/kotlin' 39 | } 40 | 41 | defaultConfig { 42 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 43 | applicationId "com.example.flybuy" 44 | minSdkVersion 16 45 | targetSdkVersion 30 46 | versionCode flutterVersionCode.toInteger() 47 | versionName flutterVersionName 48 | } 49 | 50 | signingConfigs { 51 | release { 52 | keyAlias keystoreProperties['keyAlias'] 53 | keyPassword keystoreProperties['keyPassword'] 54 | storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null 55 | storePassword keystoreProperties['storePassword'] 56 | } 57 | } 58 | buildTypes { 59 | release { 60 | signingConfig signingConfigs.release 61 | } 62 | } 63 | } 64 | 65 | flutter { 66 | source '../..' 67 | } 68 | 69 | dependencies { 70 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 71 | } 72 | -------------------------------------------------------------------------------- /lib/screens/product_details/components/colors_dots.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../../../constants.dart'; 4 | import '../../../size_config.dart'; 5 | import '../../../models/Product.dart'; 6 | import '../../../components/rounded_icon_button.dart'; 7 | 8 | 9 | class ColorDots extends StatefulWidget { 10 | ColorDots({ 11 | Key key, 12 | @required this.product, 13 | }) : super(key: key); 14 | 15 | final Product product; 16 | 17 | @override 18 | _ColorDotsState createState() => _ColorDotsState(); 19 | } 20 | 21 | class _ColorDotsState extends State { 22 | int selectedColor = 2; 23 | 24 | @override 25 | Widget build(BuildContext context) { 26 | return Padding( 27 | padding: 28 | EdgeInsets.symmetric(horizontal: getProportionateScreenWidth(20)), 29 | child: Row( 30 | children: [ 31 | ...List.generate( 32 | widget.product.colors.length, 33 | (index) => GestureDetector( 34 | onTap: () => setState(() => selectedColor = index), 35 | child: ColorDot( 36 | color: widget.product.colors[index], 37 | isSelected: selectedColor == index, 38 | ), 39 | ), 40 | ), 41 | Spacer(), 42 | RoundedIconButton(icon: Icons.remove, press: () {}), 43 | SizedBox(width: getProportionateScreenWidth(15)), 44 | RoundedIconButton(icon: Icons.add, press: () {}), 45 | ], 46 | ), 47 | ); 48 | } 49 | } 50 | 51 | class ColorDot extends StatelessWidget { 52 | const ColorDot({ 53 | Key key, 54 | @required this.color, 55 | this.isSelected = false, 56 | }) : super(key: key); 57 | 58 | final Color color; 59 | final bool isSelected; 60 | 61 | @override 62 | Widget build(BuildContext context) { 63 | return Container( 64 | margin: EdgeInsets.all(2), 65 | padding: EdgeInsets.all(8), 66 | width: getProportionateScreenWidth(40), 67 | height: getProportionateScreenWidth(40), 68 | decoration: BoxDecoration( 69 | border: 70 | Border.all(color: isSelected ? kPrimaryColor : Colors.transparent), 71 | shape: BoxShape.circle, 72 | ), 73 | child: DecoratedBox( 74 | decoration: BoxDecoration( 75 | color: color, 76 | shape: BoxShape.circle, 77 | ), 78 | ), 79 | ); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /lib/screens/otp/components/body.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import './otp_form.dart'; 4 | import '../../../constants.dart'; 5 | import '../../../size_config.dart'; 6 | import '../../../components/default_button.dart'; 7 | 8 | class Body extends StatelessWidget { 9 | final String phone; 10 | Body(this.phone); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | return SafeArea( 15 | child: SizedBox( 16 | width: double.infinity, 17 | child: Padding( 18 | padding: 19 | EdgeInsets.symmetric(horizontal: getProportionateScreenWidth(25)), 20 | child: SingleChildScrollView( 21 | child: Column( 22 | children: [ 23 | SizedBox(height: SizeConfig.screenHeight * 0.05), 24 | Text("OTP Verification", style: headingStyle), 25 | Text("We sent your code to ${this.phone}", 26 | textAlign: TextAlign.center), 27 | buildTimer(), 28 | SizedBox(height: SizeConfig.screenHeight * 0.1), 29 | OtpForm(), 30 | SizedBox(height: SizeConfig.screenHeight * 0.15), 31 | DefaultButton( 32 | text: "Continue", 33 | press: () {}, 34 | ), 35 | SizedBox(height: SizeConfig.screenHeight * 0.2), 36 | TextButton( 37 | onPressed: () { 38 | // resend OTP code 39 | }, 40 | child: Text( 41 | "Resend OTP Code", 42 | style: TextStyle( 43 | color: kPrimaryColor, 44 | ), 45 | ), 46 | ), 47 | SizedBox(height: SizeConfig.screenHeight * 0.03), 48 | ], 49 | ), 50 | ), 51 | ), 52 | ), 53 | ); 54 | } 55 | 56 | Row buildTimer() { 57 | return Row( 58 | mainAxisAlignment: MainAxisAlignment.center, 59 | children: [ 60 | Text("This code will expired in "), 61 | TweenAnimationBuilder( 62 | tween: Tween(begin: 30.0, end: 0.00), 63 | duration: Duration(seconds: 30), 64 | builder: (context, value, child) => Text( 65 | "00:${value.toInt()}", 66 | style: TextStyle(color: kPrimaryColor), 67 | ), 68 | onEnd: () {}, 69 | ) 70 | ], 71 | ); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /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/screens/home/components/categories.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_svg/flutter_svg.dart'; 3 | import 'package:flybuy/constants.dart'; 4 | 5 | import '../../../size_config.dart'; 6 | 7 | // ignore: must_be_immutable 8 | class Categories extends StatelessWidget { 9 | List> categories = [ 10 | {"icon": "assets/icons/Flash Icon.svg", "text": "Flash Deal"}, 11 | {"icon": "assets/icons/Bill Icon.svg", "text": "Bill"}, 12 | {"icon": "assets/icons/Game Icon.svg", "text": "Game"}, 13 | {"icon": "assets/icons/Gift Icon.svg", "text": "Daily Gift"}, 14 | {"icon": "assets/icons/ellipsis.svg", "text": "More"}, 15 | ]; 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | return Padding( 20 | padding: 21 | EdgeInsets.symmetric(horizontal: getProportionateScreenWidth(20)), 22 | child: Row( 23 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 24 | crossAxisAlignment: CrossAxisAlignment.start, 25 | children: [ 26 | ...List.generate( 27 | categories.length, 28 | (index) => CategoryCard( 29 | icon: categories[index]['icon'], 30 | text: categories[index]['text'], 31 | press: () {}, 32 | ), 33 | ), 34 | ], 35 | ), 36 | ); 37 | } 38 | } 39 | 40 | class CategoryCard extends StatelessWidget { 41 | const CategoryCard({ 42 | Key key, 43 | @required this.icon, 44 | @required this.text, 45 | @required this.press, 46 | }) : super(key: key); 47 | 48 | final String icon, text; 49 | final GestureTapCallback press; 50 | 51 | @override 52 | Widget build(BuildContext context) { 53 | return GestureDetector( 54 | onTap: press, 55 | child: SizedBox( 56 | width: getProportionateScreenWidth(55), 57 | child: Column( 58 | children: [ 59 | AspectRatio( 60 | aspectRatio: 1, 61 | child: Container( 62 | padding: EdgeInsets.symmetric( 63 | horizontal: getProportionateScreenWidth(15)), 64 | decoration: BoxDecoration( 65 | color: Color(0xFFDFECFF), 66 | borderRadius: BorderRadius.circular(10), 67 | ), 68 | child: SvgPicture.asset( 69 | icon, 70 | color: kPrimaryColor.withOpacity(.8), 71 | ), 72 | ), 73 | ), 74 | SizedBox( 75 | height: 5, 76 | ), 77 | Text(text, textAlign: TextAlign.center), 78 | ], 79 | ), 80 | ), 81 | ); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /lib/screens/splash_screen/components/body.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import './build_dot.dart'; 4 | import './splash_content.dart'; 5 | import '../../../size_config.dart'; 6 | import '../../sign_in/sign_in_screen.dart'; 7 | import '../../../components/default_button.dart'; 8 | 9 | class Body extends StatefulWidget { 10 | @override 11 | _BodyState createState() => _BodyState(); 12 | } 13 | 14 | class _BodyState extends State { 15 | int _currentPage = 0; 16 | List> splashData = [ 17 | { 18 | "text": "Welcome to FlyBuy, Let’s shop!", 19 | "image": "assets/images/splash_1.png" 20 | }, 21 | { 22 | "text": "We help people connect with store \naround the world", 23 | "image": "assets/images/splash_2.png" 24 | }, 25 | { 26 | "text": "We show the easy way to shop. \nJust stay at home with us", 27 | "image": "assets/images/splash_3.png" 28 | }, 29 | ]; 30 | 31 | @override 32 | Widget build(BuildContext context) { 33 | return SafeArea( 34 | child: SizedBox( 35 | width: double.infinity, 36 | child: Column( 37 | children: [ 38 | Expanded( 39 | flex: 3, 40 | child: PageView.builder( 41 | onPageChanged: (pageNumber) => 42 | setState(() => _currentPage = pageNumber), 43 | itemCount: splashData.length, 44 | itemBuilder: (ctx, index) => SplashContent( 45 | text: splashData[index]['text'], 46 | image: splashData[index]['image'], 47 | ), 48 | ), 49 | ), 50 | SizedBox(height: 15), 51 | Expanded( 52 | flex: 2, 53 | child: Column( 54 | children: [ 55 | Row( 56 | mainAxisAlignment: MainAxisAlignment.center, 57 | children: List.generate( 58 | splashData.length, 59 | (index) => BuildDot( 60 | pageNumber: index, currentPage: _currentPage)), 61 | ), 62 | Spacer(flex: 4), 63 | Padding( 64 | padding: EdgeInsets.all(getProportionateScreenWidth(20)), 65 | child: DefaultButton( 66 | text: "Continue", 67 | press: () { 68 | Navigator.pushNamed(context, SignInScreen.routeName); 69 | }, 70 | ), 71 | ), 72 | Spacer(flex: 2), 73 | ], 74 | ), 75 | ), 76 | ], 77 | ), 78 | ), 79 | ); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /lib/components/custom_bottom_navigation_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_svg/flutter_svg.dart'; 3 | import 'package:flybuy/screens/home/home_screen.dart'; 4 | import 'package:flybuy/screens/profile/profile_screen.dart'; 5 | 6 | import '../constants.dart'; 7 | 8 | enum Menu { home, favourites, message, profile } 9 | 10 | class CustomBottomNavigationBar extends StatelessWidget { 11 | CustomBottomNavigationBar({ 12 | Key key, 13 | @required this.selectedMenu, 14 | }) : super(key: key); 15 | 16 | final Menu selectedMenu; 17 | final Color inActiveColor = Color(0xFFADADAD); 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | return Container( 22 | padding: EdgeInsets.symmetric(vertical: 20), 23 | decoration: BoxDecoration( 24 | color: Colors.white, 25 | boxShadow: [ 26 | BoxShadow( 27 | blurRadius: 20, 28 | offset: Offset(0, -15), 29 | color: Color(0xFFDADADA).withOpacity(.40), 30 | ), 31 | ], 32 | borderRadius: BorderRadius.only( 33 | topLeft: Radius.circular(40), 34 | topRight: Radius.circular(40), 35 | ), 36 | ), 37 | child: SafeArea( 38 | child: Row( 39 | mainAxisAlignment: MainAxisAlignment.spaceAround, 40 | children: [ 41 | IconButton( 42 | icon: SvgPicture.asset( 43 | "assets/icons/Shop Icon.svg", 44 | color: 45 | selectedMenu == Menu.home ? kPrimaryColor : inActiveColor, 46 | ), 47 | onPressed: () => 48 | selectedMenu == Menu.home ? null : Navigator.pop(context), 49 | ), 50 | IconButton( 51 | icon: SvgPicture.asset( 52 | "assets/icons/Heart Icon.svg", 53 | color: selectedMenu == Menu.favourites 54 | ? kPrimaryColor 55 | : inActiveColor, 56 | ), 57 | onPressed: () {}, 58 | ), 59 | IconButton( 60 | icon: SvgPicture.asset( 61 | "assets/icons/Chat bubble Icon.svg", 62 | color: selectedMenu == Menu.message 63 | ? kPrimaryColor 64 | : inActiveColor, 65 | ), 66 | onPressed: () {}, 67 | ), 68 | IconButton( 69 | icon: SvgPicture.asset( 70 | "assets/icons/User Icon.svg", 71 | color: selectedMenu == Menu.profile 72 | ? kPrimaryColor 73 | : inActiveColor, 74 | ), 75 | onPressed: () => selectedMenu == Menu.profile 76 | ? null 77 | : Navigator.pushNamed(context, ProfileScreen.routeName), 78 | ), 79 | ], 80 | ), 81 | ), 82 | ); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /lib/screens/product_details/components/product_description.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_svg/flutter_svg.dart'; 3 | 4 | import '../../../constants.dart'; 5 | import '../../../size_config.dart'; 6 | import '../../../models/Product.dart'; 7 | 8 | class ProductDescription extends StatelessWidget { 9 | const ProductDescription({ 10 | Key key, 11 | @required this.product, 12 | @required this.pressOnSeeMore, 13 | }) : super(key: key); 14 | 15 | final Product product; 16 | final GestureTapCallback pressOnSeeMore; 17 | 18 | @override 19 | Widget build(BuildContext context) { 20 | return Column( 21 | crossAxisAlignment: CrossAxisAlignment.start, 22 | children: [ 23 | Padding( 24 | padding: 25 | EdgeInsets.symmetric(horizontal: getProportionateScreenWidth(20)), 26 | child: Text( 27 | product.title, 28 | style: Theme.of(context).textTheme.headline6, 29 | ), 30 | ), 31 | SizedBox(height: 5), 32 | Align( 33 | alignment: Alignment.centerRight, 34 | child: Container( 35 | width: getProportionateScreenWidth(64), 36 | padding: EdgeInsets.all(getProportionateScreenWidth(15)), 37 | decoration: BoxDecoration( 38 | color: product.isFavourite 39 | ? kPrimaryColor.withOpacity(.17) 40 | : kSecondaryColor.withOpacity(.12), 41 | borderRadius: BorderRadius.only( 42 | bottomLeft: Radius.circular(15), 43 | topLeft: Radius.circular(15), 44 | ), 45 | ), 46 | child: SvgPicture.asset( 47 | product.isFavourite 48 | ? "assets/icons/Heart Icon_2.svg" 49 | : "assets/icons/Heart Icon.svg", 50 | color: product.isFavourite 51 | ? Color(0xFFFF4848).withOpacity(.9) 52 | : Color(0xFFDBDEE4), 53 | ), 54 | ), 55 | ), 56 | Padding( 57 | padding: EdgeInsets.only( 58 | left: getProportionateScreenWidth(20), 59 | right: getProportionateScreenWidth(64), 60 | ), 61 | child: Text( 62 | product.description, 63 | maxLines: 3, 64 | ), 65 | ), 66 | Padding( 67 | padding: EdgeInsets.only( 68 | bottom: 5, 69 | left: getProportionateScreenWidth(20), 70 | right: getProportionateScreenWidth(20), 71 | ), 72 | child: SizedBox( 73 | child: TextButton( 74 | onPressed: pressOnSeeMore, 75 | child: Row( 76 | children: [ 77 | Text("See More Details"), 78 | SizedBox(width: 5), 79 | Icon(Icons.arrow_forward_ios, size: 12), 80 | ], 81 | ), 82 | ), 83 | ), 84 | ), 85 | ], 86 | ); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /lib/screens/cart/components/custom_bottom_navigation_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_svg/flutter_svg.dart'; 3 | 4 | import '../../../size_config.dart'; 5 | import '../../../components/default_button.dart'; 6 | 7 | class CustomBottomNavigationBar extends StatelessWidget { 8 | const CustomBottomNavigationBar({ 9 | Key key, 10 | }) : super(key: key); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | return Container( 15 | decoration: BoxDecoration( 16 | color: Colors.white, 17 | borderRadius: BorderRadius.only( 18 | topLeft: Radius.circular(30), 19 | topRight: Radius.circular(30), 20 | ), 21 | boxShadow: [ 22 | BoxShadow( 23 | offset: Offset(0, -15), 24 | blurRadius: 20, 25 | color: Color(0xFFDADADA), 26 | ), 27 | ], 28 | ), 29 | padding: EdgeInsets.symmetric( 30 | vertical: getProportionateScreenHeight(20), 31 | horizontal: getProportionateScreenWidth(20), 32 | ), 33 | child: SafeArea( 34 | child: Column( 35 | mainAxisSize: MainAxisSize.min, 36 | children: [ 37 | Row( 38 | children: [ 39 | Container( 40 | width: getProportionateScreenWidth(40), 41 | height: getProportionateScreenWidth(40), 42 | padding: const EdgeInsets.all(8), 43 | decoration: BoxDecoration( 44 | color: Color(0xFFF9F6F5), 45 | borderRadius: BorderRadius.circular(10), 46 | ), 47 | child: SvgPicture.asset("assets/icons/receipt.svg"), 48 | ), 49 | Spacer(), 50 | Text("Add voucher code"), 51 | SizedBox(width: 10), 52 | Icon(Icons.arrow_forward_ios_rounded, size: 12), 53 | ], 54 | ), 55 | SizedBox( 56 | height: getProportionateScreenHeight(20), 57 | ), 58 | Row( 59 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 60 | children: [ 61 | Text.rich( 62 | TextSpan( 63 | text: "Total:\n", 64 | children: [ 65 | TextSpan( 66 | text: "\$232.2", 67 | style: TextStyle( 68 | color: Colors.black, 69 | fontSize: 16, 70 | fontWeight: FontWeight.w600), 71 | ), 72 | ], 73 | ), 74 | ), 75 | SizedBox( 76 | width: getProportionateScreenWidth(190), 77 | child: DefaultButton( 78 | text: "Check out", 79 | press: () {}, 80 | ), 81 | ), 82 | ], 83 | ), 84 | ], 85 | ), 86 | ), 87 | ); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /lib/models/Product.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class Product { 4 | final int id; 5 | final String title, description; 6 | final List images; 7 | final List colors; 8 | final double rating, price; 9 | final bool isFavourite, isPopular; 10 | 11 | Product({ 12 | @required this.id, 13 | @required this.images, 14 | @required this.colors, 15 | this.rating = 0.0, 16 | this.isFavourite = false, 17 | this.isPopular = false, 18 | @required this.title, 19 | @required this.price, 20 | @required this.description, 21 | }); 22 | } 23 | 24 | // Our demo Products 25 | 26 | List demoProducts = [ 27 | Product( 28 | id: 1, 29 | images: [ 30 | "assets/images/Helmet.png", 31 | ], 32 | colors: [ 33 | Color(0xFFF6625E), 34 | Color(0xFF836DB8), 35 | Color(0xFFDECB9C), 36 | Colors.white, 37 | ], 38 | title: "Colored Helmet", 39 | price: 29.99, 40 | description: 41 | "A form of protective gear worn to protect the head. More specifically, a helmet complements the skull in protecting the human brain.", 42 | rating: 4.3, 43 | isPopular: true, 44 | ), 45 | Product( 46 | id: 2, 47 | images: [ 48 | "assets/images/ps4_console_white_1.png", 49 | "assets/images/ps4_console_white_2.png", 50 | "assets/images/ps4_console_white_3.png", 51 | "assets/images/ps4_console_white_4.png", 52 | ], 53 | colors: [ 54 | Color(0xFFF6625E), 55 | Color(0xFF836DB8), 56 | Color(0xFFDECB9C), 57 | Colors.white, 58 | ], 59 | title: "Wireless Controller for PS4™", 60 | price: 64.99, 61 | description: description, 62 | rating: 4.8, 63 | isFavourite: true, 64 | isPopular: true, 65 | ), 66 | Product( 67 | id: 5, 68 | images: [ 69 | "assets/images/shoes2.png", 70 | ], 71 | colors: [ 72 | Color(0xFFF6625E), 73 | Color(0xFF836DB8), 74 | Color(0xFFDECB9C), 75 | Colors.white, 76 | ], 77 | title: "Nike Shoes", 78 | price: 40.00, 79 | description: "A very nice shoes with attractive colors", 80 | rating: 4.5, 81 | isFavourite: false, 82 | ), 83 | Product( 84 | id: 3, 85 | images: [ 86 | "assets/images/glap.png", 87 | ], 88 | colors: [ 89 | Color(0xFFF6625E), 90 | Color(0xFF836DB8), 91 | Color(0xFFDECB9C), 92 | Colors.white, 93 | ], 94 | title: "Gloves XC Omega - Polygon", 95 | price: 36.55, 96 | description: description, 97 | rating: 4.1, 98 | isFavourite: true, 99 | isPopular: true, 100 | ), 101 | Product( 102 | id: 4, 103 | images: [ 104 | "assets/images/wireless headset.png", 105 | ], 106 | colors: [ 107 | Color(0xFFF6625E), 108 | Color(0xFF836DB8), 109 | Color(0xFFDECB9C), 110 | Colors.white, 111 | ], 112 | title: "Logitech Head", 113 | price: 20.20, 114 | description: description, 115 | rating: 4.1, 116 | isFavourite: true, 117 | ), 118 | ]; 119 | 120 | const String description = 121 | "Wireless Controller for PS4™ gives you what you want in your gaming from over precision control your games to sharing …"; 122 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flybuy 2 | description: A new Flutter project. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `pub publish`. This is preferred for private packages. 6 | publish_to: "none" # Remove this line if you wish to publish to pub.dev 7 | 8 | # The following defines the version and build number for your application. 9 | # A version number is three numbers separated by dots, like 1.2.43 10 | # followed by an optional build number separated by a +. 11 | # Both the version and the builder number may be overridden in flutter 12 | # build by specifying --build-name and --build-number, respectively. 13 | # In Android, build-name is used as versionName while build-number used as versionCode. 14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 16 | # Read more about iOS versioning at 17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 18 | version: 1.0.0+1 19 | 20 | environment: 21 | sdk: ">=2.7.0 <3.0.0" 22 | 23 | dependencies: 24 | flutter: 25 | sdk: flutter 26 | provider: ^5.0.0 27 | flutter_svg: ^0.22.0 28 | 29 | # The following adds the Cupertino Icons font to your application. 30 | # Use with the CupertinoIcons class for iOS style icons. 31 | cupertino_icons: ^1.0.2 32 | 33 | dev_dependencies: 34 | flutter_test: 35 | sdk: flutter 36 | flutter_launcher_icons: ^0.9.0 37 | 38 | flutter_icons: 39 | ios: true 40 | android: true 41 | image_path: "assets/FlyBuy logo.png" 42 | apaptive_icon_background: "#191919" 43 | 44 | # For information on the generic Dart part of this file, see the 45 | # following page: https://dart.dev/tools/pub/pubspec 46 | 47 | # The following section is specific to Flutter. 48 | flutter: 49 | # The following line ensures that the Material Icons font is 50 | # included with your application, so that you can use the icons in 51 | # the material Icons class. 52 | uses-material-design: true 53 | 54 | # To add assets to your application, add an assets section, like this: 55 | assets: 56 | - assets/images/ 57 | - assets/icons/ 58 | 59 | # An image asset can refer to one or more resolution-specific "variants", see 60 | # https://flutter.dev/assets-and-images/#resolution-aware. 61 | 62 | # For details regarding adding assets from package dependencies, see 63 | # https://flutter.dev/assets-and-images/#from-packages 64 | 65 | # To add custom fonts to your application, add a fonts section here, 66 | # in this "flutter" section. Each entry in this list should have a 67 | # "family" key with the font family name, and a "fonts" key with a 68 | # list giving the asset and other descriptors for the font. For 69 | # example: 70 | fonts: 71 | - family: Muli 72 | fonts: 73 | - asset: assets/fonts/muli/Muli.ttf 74 | - asset: assets/fonts/muli/Muli-Bold.ttf 75 | weight: 700 76 | - asset: assets/fonts/muli/Muli-Light.ttf 77 | weight: 300 78 | # - family: Trajan Pro 79 | # fonts: 80 | # - asset: fonts/TrajanPro.ttf 81 | # - asset: fonts/TrajanPro_Bold.ttf 82 | # weight: 700 83 | # 84 | # For details regarding fonts from package dependencies, 85 | # see https://flutter.dev/custom-fonts/#from-packages 86 | -------------------------------------------------------------------------------- /lib/components/product_card.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_svg/flutter_svg.dart'; 3 | 4 | import '../constants.dart'; 5 | import '../size_config.dart'; 6 | import '../models/Product.dart'; 7 | 8 | class ProductCard extends StatelessWidget { 9 | const ProductCard({ 10 | Key key, 11 | this.width = 140, 12 | this.aspectRatio = 1.02, 13 | @required this.product, 14 | @required this.press, 15 | }) : super(key: key); 16 | 17 | final Product product; 18 | final double width, aspectRatio; 19 | final GestureTapCallback press; 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return GestureDetector( 24 | onTap: press, 25 | child: Padding( 26 | padding: EdgeInsets.only(left: getProportionateScreenWidth(20)), 27 | child: SizedBox( 28 | width: getProportionateScreenWidth(width), 29 | height: getProportionateScreenHeight(210), 30 | child: Column( 31 | children: [ 32 | AspectRatio( 33 | aspectRatio: aspectRatio, 34 | child: Container( 35 | decoration: BoxDecoration( 36 | color: kSecondaryColor.withOpacity(.1), 37 | borderRadius: BorderRadius.circular(15), 38 | ), 39 | child: Image.asset( 40 | product.images[0], 41 | ), 42 | ), 43 | ), 44 | const SizedBox( 45 | height: 5, 46 | ), 47 | Text( 48 | "${product.title}", 49 | style: TextStyle(color: Colors.black), 50 | textAlign: TextAlign.center, 51 | maxLines: 2, 52 | ), 53 | Spacer(), 54 | Row( 55 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 56 | children: [ 57 | Text( 58 | "\$${product.price}", 59 | style: TextStyle( 60 | fontSize: getProportionateScreenWidth(18), 61 | fontWeight: FontWeight.bold, 62 | color: kPrimaryColor, 63 | ), 64 | ), 65 | InkWell( 66 | onTap: () {}, 67 | borderRadius: BorderRadius.circular(30), 68 | child: Container( 69 | padding: EdgeInsets.all(getProportionateScreenWidth(6)), 70 | width: getProportionateScreenWidth(28), 71 | height: getProportionateScreenHeight(28), 72 | decoration: BoxDecoration( 73 | color: product.isFavourite 74 | ? kPrimaryColor.withOpacity(.17) 75 | : kSecondaryColor.withOpacity(.12), 76 | shape: BoxShape.circle, 77 | ), 78 | child: SvgPicture.asset( 79 | product.isFavourite 80 | ? "assets/icons/Heart Icon_2.svg" 81 | : "assets/icons/Heart Icon.svg", 82 | color: product.isFavourite 83 | ? Color(0xFFFF4848).withOpacity(.9) 84 | : Color(0xFFDBDEE4), 85 | ), 86 | ), 87 | ), 88 | ], 89 | ) 90 | ], 91 | ), 92 | ), 93 | ), 94 | ); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /lib/screens/otp/components/otp_form.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../../../constants.dart'; 4 | import '../../../size_config.dart'; 5 | 6 | 7 | class OtpForm extends StatefulWidget { 8 | @override 9 | _OtpFormState createState() => _OtpFormState(); 10 | } 11 | 12 | class _OtpFormState extends State { 13 | FocusNode pin2FocusNode; 14 | FocusNode pin3FocusNode; 15 | FocusNode pin4FocusNode; 16 | 17 | @override 18 | void initState() { 19 | super.initState(); 20 | pin2FocusNode = FocusNode(); 21 | pin3FocusNode = FocusNode(); 22 | pin4FocusNode = FocusNode(); 23 | } 24 | 25 | @override 26 | void dispose() { 27 | pin2FocusNode.dispose(); 28 | pin3FocusNode.dispose(); 29 | pin4FocusNode.dispose(); 30 | super.dispose(); 31 | } 32 | 33 | void nextNode({String value, FocusNode focusNode}) { 34 | if (value.length == 1) { 35 | focusNode.requestFocus(); 36 | } 37 | } 38 | 39 | @override 40 | Widget build(BuildContext context) { 41 | return Form( 42 | child: Row( 43 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 44 | children: [ 45 | SizedBox( 46 | width: getProportionateScreenWidth(60), 47 | child: TextFormField( 48 | autofocus: true, 49 | obscureText: true, 50 | textAlign: TextAlign.center, 51 | style: TextStyle(fontSize: 24), 52 | decoration: otpInputDecoration, 53 | keyboardType: TextInputType.number, 54 | onChanged: (value) { 55 | nextNode(value: value, focusNode: pin2FocusNode); 56 | }, 57 | ), 58 | ), 59 | SizedBox( 60 | width: getProportionateScreenWidth(60), 61 | child: TextFormField( 62 | focusNode: pin2FocusNode, 63 | style: TextStyle(fontSize: 24), 64 | autofocus: true, 65 | decoration: otpInputDecoration, 66 | obscureText: true, 67 | textAlign: TextAlign.center, 68 | keyboardType: TextInputType.number, 69 | onChanged: (value) { 70 | nextNode(value: value, focusNode: pin3FocusNode); 71 | }, 72 | ), 73 | ), 74 | SizedBox( 75 | width: getProportionateScreenWidth(60), 76 | child: TextFormField( 77 | focusNode: pin3FocusNode, 78 | style: TextStyle(fontSize: 24), 79 | autofocus: true, 80 | decoration: otpInputDecoration, 81 | obscureText: true, 82 | textAlign: TextAlign.center, 83 | keyboardType: TextInputType.number, 84 | onChanged: (value) { 85 | nextNode(value: value, focusNode: pin4FocusNode); 86 | }, 87 | ), 88 | ), 89 | SizedBox( 90 | width: getProportionateScreenWidth(60), 91 | child: TextFormField( 92 | focusNode: pin4FocusNode, 93 | style: TextStyle(fontSize: 24), 94 | autofocus: true, 95 | decoration: otpInputDecoration, 96 | obscureText: true, 97 | textAlign: TextAlign.center, 98 | keyboardType: TextInputType.number, 99 | onChanged: (value) { 100 | pin4FocusNode.unfocus(); 101 | }, 102 | ), 103 | ), 104 | ], 105 | ), 106 | ); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | [![GitHub contributors](https://img.shields.io/github/contributors/AdelRizq/FlyBuy)](https://github.com/AdelRizq/FlyBuy/contributors) 6 | [![GitHub issues](https://img.shields.io/github/issues/AdelRizq/FlyBuy)](https://github.com/AdelRizq/FlyBuy/issues) 7 | [![GitHub forks](https://img.shields.io/github/forks/AdelRizq/FlyBuy)](https://github.com/AdelRizq/FlyBuy/network) 8 | [![GitHub stars](https://img.shields.io/github/stars/AdelRizq/FlyBuy)](https://github.com/AdelRizq/FlyBuy/stargazers) 9 | [![GitHub license](https://img.shields.io/github/license/AdelRizq/FlyBuy)](https://github.com/AdelRizq/FlyBuy/blob/master/LICENSE) 10 | 11 | 12 | 13 | 14 | 15 | ## About ([Download](https://drive.google.com/file/d/1gfylFNrzI2LVfqYeyAaBgNtoaqqdjjPg/view?usp=sharing)) 16 | 17 | > 🛍 A full E-commerce app with nice UI consists of on-boarding, login, sign-up, home, product details, cart and user profile. 18 | 19 | ## 📱 Screenshots 20 | 21 |

22 | 23 | 24 |

25 | 26 |

27 | 28 | 29 |

30 | 31 |

32 | 33 | 34 |

35 | 36 |

37 | 38 | 39 | 40 |

41 | 42 |

43 | 44 | 45 |

46 | 47 |

48 | 49 | 50 |

51 | 52 | ## Licence 53 | 54 | [MIT LICENCE](https://github.com/AdelRizq/FlyBuy/blob/main/LICENSE) 55 | -------------------------------------------------------------------------------- /lib/screens/home/components/special_offers.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import './section_title.dart'; 4 | import '../../../size_config.dart'; 5 | 6 | class SpecialOffers extends StatelessWidget { 7 | const SpecialOffers({ 8 | Key key, 9 | }) : super(key: key); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return Column( 14 | children: [ 15 | SectionTitle( 16 | title: "Special for you", 17 | press: () {}, 18 | ), 19 | SizedBox(height: getProportionateScreenHeight(20)), 20 | SingleChildScrollView( 21 | scrollDirection: Axis.horizontal, 22 | child: Row( 23 | children: [ 24 | SpecialOfferCard( 25 | image: "assets/images/Image Banner 2.png", 26 | text: "Smartphones", 27 | noOfBrands: 10, 28 | press: () {}, 29 | ), 30 | SpecialOfferCard( 31 | image: "assets/images/Image Banner 3.png", 32 | text: "Fashion", 33 | noOfBrands: 15, 34 | press: () {}, 35 | ), 36 | SizedBox(width: getProportionateScreenWidth(20)), 37 | ], 38 | ), 39 | ), 40 | ], 41 | ); 42 | } 43 | } 44 | 45 | class SpecialOfferCard extends StatelessWidget { 46 | const SpecialOfferCard({ 47 | Key key, 48 | @required this.noOfBrands, 49 | @required this.image, 50 | @required this.text, 51 | @required this.press, 52 | }) : super(key: key); 53 | 54 | final int noOfBrands; 55 | final String image, text; 56 | final GestureTapCallback press; 57 | 58 | @override 59 | Widget build(BuildContext context) { 60 | return Padding( 61 | padding: EdgeInsets.only(left: getProportionateScreenWidth(20)), 62 | child: GestureDetector( 63 | onTap: press, 64 | child: SizedBox( 65 | height: getProportionateScreenHeight(100), 66 | width: getProportionateScreenWidth(242), 67 | child: ClipRRect( 68 | borderRadius: BorderRadius.circular(15), 69 | child: Stack( 70 | children: [ 71 | Image.asset(image), 72 | Container( 73 | decoration: BoxDecoration( 74 | gradient: LinearGradient( 75 | begin: Alignment.topCenter, 76 | end: Alignment.bottomCenter, 77 | colors: [ 78 | Color(0xFF343434).withOpacity(.4), 79 | Color(0xFF343434).withOpacity(.12), 80 | ], 81 | ), 82 | ), 83 | ), 84 | Positioned( 85 | top: getProportionateScreenHeight(10), 86 | left: getProportionateScreenWidth(20), 87 | child: Text.rich( 88 | TextSpan( 89 | children: [ 90 | TextSpan( 91 | text: "$text\n", 92 | style: TextStyle( 93 | color: Colors.white, 94 | fontSize: getProportionateScreenWidth(18), 95 | fontWeight: FontWeight.bold, 96 | ), 97 | ), 98 | TextSpan( 99 | text: "$noOfBrands Brands", 100 | style: TextStyle(color: Colors.white), 101 | ), 102 | ], 103 | ), 104 | ), 105 | ), 106 | ], 107 | ), 108 | ), 109 | ), 110 | ), 111 | ); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /lib/screens/sign_in/components/sign_in_form.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../../../constants.dart'; 4 | import '../../../size_config.dart'; 5 | import '../../../components/default_button.dart'; 6 | import '../../../components/custom_suffix_icon.dart'; 7 | import '../../login_success/login_success_screen.dart'; 8 | import '../../forgot_password/forgot_password_screen.dart'; 9 | 10 | class SignForm extends StatefulWidget { 11 | @override 12 | _SignFormState createState() => _SignFormState(); 13 | } 14 | 15 | class _SignFormState extends State { 16 | final _formKey = GlobalKey(); 17 | final List errors = []; 18 | 19 | String email, password; 20 | 21 | bool firstSubmit = false; 22 | bool remember = false; 23 | 24 | @override 25 | Widget build(BuildContext context) { 26 | return Form( 27 | key: _formKey, 28 | child: Column( 29 | children: [ 30 | buildEmailFormField(), 31 | SizedBox(height: getProportionateScreenHeight(30)), 32 | buildPasswordFormField(), 33 | SizedBox(height: getProportionateScreenHeight(30)), 34 | Row( 35 | children: [ 36 | Checkbox( 37 | value: remember, 38 | activeColor: kPrimaryColor, 39 | onChanged: (value) => setState(() => remember = value), 40 | ), 41 | Text("Remember me"), 42 | Spacer(), 43 | TextButton( 44 | onPressed: () => Navigator.push( 45 | context, 46 | MaterialPageRoute( 47 | builder: (context) => ForgotPasswordScreen(), 48 | ), 49 | ), 50 | child: Text( 51 | "Forgot password", 52 | ), 53 | ), 54 | ], 55 | ), 56 | SizedBox(height: getProportionateScreenHeight(30)), 57 | DefaultButton( 58 | text: "Continue", 59 | press: () { 60 | if (_formKey.currentState.validate()) { 61 | _formKey.currentState.save(); 62 | Navigator.pushNamed(context, LoginSuccessScreen.routeName); 63 | } 64 | firstSubmit = true; 65 | }, 66 | ), 67 | ], 68 | ), 69 | ); 70 | } 71 | 72 | TextFormField buildPasswordFormField() { 73 | return TextFormField( 74 | onSaved: (newPassword) => this.password = newPassword, 75 | onChanged: (password) { 76 | if (firstSubmit) _formKey.currentState.validate(); 77 | }, 78 | validator: (password) { 79 | if (password.isEmpty) { 80 | return kPassNullError; 81 | } else if (password.isNotEmpty && password.length <= 7) { 82 | return kShortPassError; 83 | } 84 | 85 | return null; 86 | }, 87 | decoration: InputDecoration( 88 | labelText: "Password", 89 | hintText: "Enter your password", 90 | suffixIcon: CustomSuffixIcon(iconPath: "assets/icons/Lock.svg"), 91 | ), 92 | obscureText: true, 93 | ); 94 | } 95 | 96 | TextFormField buildEmailFormField() { 97 | return TextFormField( 98 | onSaved: (newEmail) => this.email = newEmail, 99 | onChanged: (email) { 100 | if (firstSubmit) _formKey.currentState.validate(); 101 | }, 102 | validator: (email) { 103 | if (email.isEmpty) { 104 | return kEmailNullError; 105 | } else if (email.isNotEmpty && !emailValidatorRegExp.hasMatch(email)) { 106 | return kInvalidEmailError; 107 | } 108 | 109 | return null; 110 | }, 111 | decoration: InputDecoration( 112 | labelText: "Email", 113 | hintText: "Enter your email", 114 | suffixIcon: CustomSuffixIcon(iconPath: "assets/icons/Mail.svg"), 115 | ), 116 | keyboardType: TextInputType.emailAddress, 117 | ); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /lib/screens/sign_up/components/sign_up_form.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flybuy/screens/complete_profile/complete_profile_screen.dart'; 3 | 4 | import '../../../constants.dart'; 5 | import '../../../size_config.dart'; 6 | import '../../../components/default_button.dart'; 7 | import '../../../components/custom_suffix_icon.dart'; 8 | 9 | class SignUpForm extends StatefulWidget { 10 | @override 11 | _SignFormState createState() => _SignFormState(); 12 | } 13 | 14 | class _SignFormState extends State { 15 | final _formKey = GlobalKey(); 16 | String email, password, confirmPassword; 17 | final List errors = []; 18 | bool firstSubmit = false; 19 | bool remember = false; 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return Form( 24 | key: _formKey, 25 | child: Column( 26 | children: [ 27 | buildEmailFormField(), 28 | SizedBox(height: getProportionateScreenHeight(30)), 29 | buildPasswordFormField(), 30 | SizedBox(height: getProportionateScreenHeight(30)), 31 | buildConfirmPasswordFormField(), 32 | SizedBox(height: getProportionateScreenHeight(40)), 33 | DefaultButton( 34 | text: "Continue", 35 | press: () { 36 | if (_formKey.currentState.validate()) { 37 | _formKey.currentState.save(); 38 | Navigator.pushNamed(context, CompleteProfileScreen.routeName); 39 | } 40 | firstSubmit = true; 41 | }, 42 | ), 43 | ], 44 | ), 45 | ); 46 | } 47 | 48 | TextFormField buildEmailFormField() { 49 | return TextFormField( 50 | onSaved: (newEmail) => this.email = newEmail, 51 | onChanged: (email) { 52 | if (firstSubmit) _formKey.currentState.validate(); 53 | }, 54 | validator: (email) { 55 | if (email.isEmpty) { 56 | return kEmailNullError; 57 | } else if (email.isNotEmpty && !emailValidatorRegExp.hasMatch(email)) { 58 | return kInvalidEmailError; 59 | } 60 | 61 | return null; 62 | }, 63 | decoration: InputDecoration( 64 | labelText: "Email", 65 | hintText: "Enter your email", 66 | suffixIcon: CustomSuffixIcon(iconPath: "assets/icons/Mail.svg"), 67 | ), 68 | keyboardType: TextInputType.emailAddress, 69 | ); 70 | } 71 | 72 | TextFormField buildPasswordFormField() { 73 | return TextFormField( 74 | onSaved: (newPassword) => this.password = newPassword, 75 | onChanged: (password) { 76 | if (firstSubmit) _formKey.currentState.validate(); 77 | this.password = password; 78 | }, 79 | validator: (password) { 80 | if (password.isEmpty) { 81 | return kPassNullError; 82 | } else if (password.isNotEmpty && password.length <= 7) { 83 | return kShortPassError; 84 | } 85 | 86 | return null; 87 | }, 88 | decoration: InputDecoration( 89 | labelText: "Password", 90 | hintText: "Enter your password", 91 | suffixIcon: CustomSuffixIcon(iconPath: "assets/icons/Lock.svg"), 92 | ), 93 | obscureText: true, 94 | ); 95 | } 96 | 97 | TextFormField buildConfirmPasswordFormField() { 98 | return TextFormField( 99 | onSaved: (newPassword) => this.confirmPassword = newPassword, 100 | onChanged: (password) { 101 | if (firstSubmit) _formKey.currentState.validate(); 102 | }, 103 | validator: (password) { 104 | if (password != this.password) { 105 | return kMatchPassError; 106 | } 107 | 108 | return null; 109 | }, 110 | decoration: InputDecoration( 111 | labelText: "Confirm Password", 112 | hintText: "Repeat your password", 113 | suffixIcon: CustomSuffixIcon(iconPath: "assets/icons/Lock.svg"), 114 | ), 115 | obscureText: true, 116 | ); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /lib/screens/complete_profile/components/complete_profile_form.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flybuy/screens/otp/otp_screen.dart'; 3 | 4 | import '../../../constants.dart'; 5 | import '../../../size_config.dart'; 6 | import '../../../components/default_button.dart'; 7 | import '../../../components/custom_suffix_icon.dart'; 8 | 9 | class CompleteProfileForm extends StatefulWidget { 10 | @override 11 | _SignFormState createState() => _SignFormState(); 12 | } 13 | 14 | class _SignFormState extends State { 15 | final _formKey = GlobalKey(); 16 | String firstName, lastName, phone, address; 17 | final List errors = []; 18 | bool remember = false; 19 | bool firstSubmit = false; 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return Form( 24 | key: _formKey, 25 | child: Column( 26 | children: [ 27 | buildFirstNameFormField(), 28 | SizedBox(height: getProportionateScreenHeight(30)), 29 | buildLastNameFormField(), 30 | SizedBox(height: getProportionateScreenHeight(30)), 31 | buildPhoneFormField(), 32 | SizedBox(height: getProportionateScreenHeight(30)), 33 | buildAddressFormField(), 34 | SizedBox(height: getProportionateScreenHeight(30)), 35 | DefaultButton( 36 | text: "Continue", 37 | press: () { 38 | if (_formKey.currentState.validate()) { 39 | _formKey.currentState.save(); 40 | print(this.phone); 41 | Navigator.pushNamed( 42 | context, 43 | OTPScreen.routeName, 44 | arguments: this.phone, 45 | ); 46 | } 47 | firstSubmit = true; 48 | }, 49 | ), 50 | ], 51 | ), 52 | ); 53 | } 54 | 55 | TextFormField buildFirstNameFormField() { 56 | return TextFormField( 57 | onSaved: (newName) => this.firstName = newName, 58 | onChanged: (name) { 59 | if (firstSubmit) _formKey.currentState.validate(); 60 | }, 61 | validator: (name) { 62 | if (name.isEmpty) { 63 | return kFirstNamelNullError; 64 | } 65 | 66 | return null; 67 | }, 68 | decoration: InputDecoration( 69 | labelText: "First Name", 70 | hintText: "Enter your first name", 71 | suffixIcon: CustomSuffixIcon(iconPath: "assets/icons/User Icon.svg"), 72 | ), 73 | keyboardType: TextInputType.name, 74 | ); 75 | } 76 | 77 | TextFormField buildLastNameFormField() { 78 | return TextFormField( 79 | onSaved: (newName) => this.lastName = newName, 80 | onChanged: (name) { 81 | if (firstSubmit) _formKey.currentState.validate(); 82 | }, 83 | validator: (name) { 84 | if (name.isEmpty) { 85 | return kLastNamelNullError; 86 | } 87 | 88 | return null; 89 | }, 90 | decoration: InputDecoration( 91 | labelText: "Last Name", 92 | hintText: "Enter your last name", 93 | suffixIcon: CustomSuffixIcon(iconPath: "assets/icons/User Icon.svg"), 94 | ), 95 | keyboardType: TextInputType.name, 96 | ); 97 | } 98 | 99 | TextFormField buildPhoneFormField() { 100 | return TextFormField( 101 | onSaved: (newPhone) => this.phone = newPhone, 102 | onChanged: (phone) { 103 | if (firstSubmit) _formKey.currentState.validate(); 104 | }, 105 | validator: (phone) { 106 | if (phone.isEmpty) { 107 | return kPhoneNumberNullError; 108 | } 109 | 110 | return null; 111 | }, 112 | decoration: InputDecoration( 113 | labelText: "Phone Number", 114 | hintText: "Enter your phone number", 115 | suffixIcon: CustomSuffixIcon(iconPath: "assets/icons/Phone.svg"), 116 | ), 117 | keyboardType: TextInputType.phone, 118 | ); 119 | } 120 | 121 | TextFormField buildAddressFormField() { 122 | return TextFormField( 123 | onSaved: (newAddress) => this.address = newAddress, 124 | onChanged: (address) { 125 | if (firstSubmit) _formKey.currentState.validate(); 126 | }, 127 | validator: (address) { 128 | if (address.isEmpty) { 129 | return kAddressNullError; 130 | } 131 | 132 | return null; 133 | }, 134 | decoration: InputDecoration( 135 | labelText: "Address", 136 | hintText: "Enter your address", 137 | suffixIcon: 138 | CustomSuffixIcon(iconPath: "assets/icons/Location point.svg"), 139 | ), 140 | keyboardType: TextInputType.streetAddress, 141 | ); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /assets/icons/Settings.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | --------------------------------------------------------------------------------