├── 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
│ │ │ ├── LaunchImageDark.png
│ │ │ ├── LaunchImageDark@2x.png
│ │ │ ├── LaunchImageDark@3x.png
│ │ │ ├── README.md
│ │ │ └── Contents.json
│ │ ├── AppIcon.appiconset
│ │ │ ├── Icon-App-20x20@1x.png
│ │ │ ├── Icon-App-20x20@2x.png
│ │ │ ├── Icon-App-20x20@3x.png
│ │ │ ├── Icon-App-29x29@1x.png
│ │ │ ├── Icon-App-29x29@2x.png
│ │ │ ├── Icon-App-29x29@3x.png
│ │ │ ├── Icon-App-40x40@1x.png
│ │ │ ├── Icon-App-40x40@2x.png
│ │ │ ├── Icon-App-40x40@3x.png
│ │ │ ├── Icon-App-50x50@1x.png
│ │ │ ├── Icon-App-50x50@2x.png
│ │ │ ├── Icon-App-57x57@1x.png
│ │ │ ├── Icon-App-57x57@2x.png
│ │ │ ├── Icon-App-60x60@2x.png
│ │ │ ├── Icon-App-60x60@3x.png
│ │ │ ├── Icon-App-72x72@1x.png
│ │ │ ├── Icon-App-72x72@2x.png
│ │ │ ├── Icon-App-76x76@1x.png
│ │ │ ├── Icon-App-76x76@2x.png
│ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ └── Icon-App-83.5x83.5@2x.png
│ │ └── LaunchBackground.imageset
│ │ │ ├── background.png
│ │ │ ├── darkbackground.png
│ │ │ └── Contents.json
│ ├── AppDelegate.swift
│ └── GoogleService-Info.plist
├── Runner.xcodeproj
│ └── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ ├── WorkspaceSettings.xcsettings
│ │ └── IDEWorkspaceChecks.plist
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── WorkspaceSettings.xcsettings
│ │ └── IDEWorkspaceChecks.plist
├── firebase_app_id_file.json
├── RunnerTests
│ └── RunnerTests.swift
└── .gitignore
├── lib
├── core
│ ├── helpers
│ │ ├── enums.dart
│ │ ├── debouncer.dart
│ │ ├── cache_keys.dart
│ │ ├── hive_boxes.dart
│ │ ├── hive_keys.dart
│ │ ├── app_regex.dart
│ │ └── hive_type_ids.dart
│ ├── api
│ │ ├── api_result.dart
│ │ ├── api_error_model.dart
│ │ └── api_error_model.g.dart
│ ├── utils
│ │ ├── app_strings.dart
│ │ ├── functions
│ │ │ ├── check_if_onboarding_visited.dart
│ │ │ ├── check_if_android_above_12.dart
│ │ │ ├── toggle_lang.dart
│ │ │ ├── check_if_user_is_logged_in.dart
│ │ │ ├── get_color_from_string.dart
│ │ │ ├── check_for_first_launch_and_device_theme.dart
│ │ │ ├── circular_indicator_or_text_widget.dart
│ │ │ └── execute_and_handle_errors.dart
│ │ ├── bloc_observer.dart
│ │ └── auto_route_observer.dart
│ ├── widgets
│ │ ├── products_grid_view_shimmer.dart
│ │ ├── cancel_outlined_button.dart
│ │ ├── custom_circular_progress_indicator.dart
│ │ ├── stores_grid_view_shimmer.dart
│ │ ├── horizontal_separated_list_view.dart
│ │ ├── custom_cached_network_image.dart
│ │ ├── email_text_form_field.dart
│ │ └── username_text_form_field.dart
│ ├── models
│ │ ├── product_size.dart
│ │ ├── sub_category.dart
│ │ ├── product_color.dart
│ │ ├── pagination.dart
│ │ ├── store.dart
│ │ └── storeify_user.dart
│ └── themes
│ │ └── app_colors.dart
└── features
│ ├── categories
│ ├── data
│ │ ├── models
│ │ │ ├── fetch_sub_category_params.dart
│ │ │ ├── fetch_sub_category_response.dart
│ │ │ ├── fetch_categories_response.dart
│ │ │ ├── fetch_sub_category_response.g.dart
│ │ │ └── category.dart
│ │ └── api
│ │ │ └── categories_api_service.dart
│ └── presentation
│ │ ├── cubit
│ │ ├── categories
│ │ │ ├── categories_state.dart
│ │ │ └── categories_cubit.dart
│ │ └── sub_category
│ │ │ └── sub_category_state.dart
│ │ └── widgets
│ │ ├── empty_sub_category_view.dart
│ │ └── categories_sliver_shimmer_loading.dart
│ ├── profile
│ ├── data
│ │ └── models
│ │ │ ├── update_profile_params.dart
│ │ │ ├── change_api_lang_params.dart
│ │ │ ├── change_password_params.dart
│ │ │ ├── change_api_lang_params.g.dart
│ │ │ └── change_password_params.g.dart
│ └── presentation
│ │ ├── cubits
│ │ ├── profile_state.dart
│ │ ├── change_pass
│ │ │ └── change_pass_state.dart
│ │ └── update_profile
│ │ │ └── update_profile_state.dart
│ │ └── widgets
│ │ ├── profile_settings_title.dart
│ │ ├── dark_mode_switch_bloc_selector.dart
│ │ ├── profile_view_sliver_app_bar.dart
│ │ ├── profile_img.dart
│ │ └── update_profile_form.dart
│ ├── checkout
│ ├── data
│ │ └── models
│ │ │ ├── payment_method.dart
│ │ │ ├── fetch_city_data.dart
│ │ │ ├── checkout_params.dart
│ │ │ ├── fetch_city_data.g.dart
│ │ │ ├── choose_payment_method_params.dart
│ │ │ ├── choose_payment_method_params.g.dart
│ │ │ ├── checkout_params.g.dart
│ │ │ ├── checkout_response.dart
│ │ │ └── checkout_response.g.dart
│ └── presentation
│ │ ├── widgets
│ │ ├── check_circle.dart
│ │ ├── custom_checkout_divider.dart
│ │ ├── custom_progress_circle.dart
│ │ ├── payment_method_process_progress.dart
│ │ ├── container_contains_dot.dart
│ │ ├── checkout_process_progress_dots.dart
│ │ ├── how_do_u_want_to_pay_question.dart
│ │ └── enable_location_error_widget.dart
│ │ └── cubits
│ │ └── payment_method
│ │ └── payment_method_state.dart
│ ├── layout
│ ├── data
│ │ └── models
│ │ │ └── bottom_nav_item_attributes.dart
│ └── presentation
│ │ └── views
│ │ └── layout_view.dart
│ ├── onboarding
│ ├── data
│ │ └── models
│ │ │ └── onboarding_attributes.dart
│ └── presentation
│ │ ├── cubit
│ │ └── onboarding_state.dart
│ │ └── widgets
│ │ ├── custom_indicators.dart
│ │ └── next_button_bloc_selector.dart
│ ├── search
│ ├── data
│ │ ├── models
│ │ │ ├── search_params.dart
│ │ │ ├── search_params.g.dart
│ │ │ ├── search_response.dart
│ │ │ ├── search_response.g.dart
│ │ │ └── fetch_search_data_response.dart
│ │ ├── api
│ │ │ └── search_api_service.dart
│ │ └── datasource
│ │ │ └── search_local_datasource.dart
│ └── presentation
│ │ └── cubit
│ │ └── search_state.dart
│ ├── auth
│ ├── data
│ │ ├── models
│ │ │ ├── forgot_password_params.dart
│ │ │ ├── validate_otp_params.dart
│ │ │ ├── login_params.dart
│ │ │ ├── reset_password_params.dart
│ │ │ ├── login_params.g.dart
│ │ │ ├── register_params.dart
│ │ │ ├── forgot_password_params.g.dart
│ │ │ ├── validate_otp_params.g.dart
│ │ │ ├── reset_password_params.g.dart
│ │ │ └── register_params.g.dart
│ │ ├── api
│ │ │ ├── validate_otp_api_service.dart
│ │ │ ├── login_api_service.dart
│ │ │ ├── reset_password_api_service.dart
│ │ │ ├── forgot_password_api_service.dart
│ │ │ └── register_api_service.dart
│ │ ├── repos
│ │ │ ├── validate_otp_repo.dart
│ │ │ ├── login_repo.dart
│ │ │ ├── register_repo.dart
│ │ │ ├── reset_password_repo.dart
│ │ │ └── forgot_password_repo.dart
│ │ └── datasources
│ │ │ └── auth_local_datasource.dart
│ └── presentation
│ │ ├── cubits
│ │ ├── validate_otp
│ │ │ └── validate_otp_state.dart
│ │ ├── forgot_password
│ │ │ └── forgot_password_state.dart
│ │ ├── login
│ │ │ └── login_state.dart
│ │ ├── reset_password
│ │ │ └── reset_password_state.dart
│ │ └── register
│ │ │ └── register_state.dart
│ │ ├── widgets
│ │ ├── sign_up_text_button.dart
│ │ ├── text_field_label.dart
│ │ └── forgot_password
│ │ │ └── forgot_password_form.dart
│ │ └── views
│ │ ├── login_view.dart
│ │ ├── register_view.dart
│ │ └── verification_view.dart
│ ├── cart
│ ├── presentation
│ │ ├── widgets
│ │ │ ├── cart_summary_divider.dart
│ │ │ ├── cart_sliver_shimmer_loading.dart
│ │ │ ├── cart_loading_view.dart
│ │ │ ├── empty_cart_widget.dart
│ │ │ ├── summary_info.dart
│ │ │ └── control_cart_product_quantity.dart
│ │ └── cubit
│ │ │ └── cart_state.dart
│ └── data
│ │ ├── models
│ │ ├── add_product_to_cart_params.dart
│ │ ├── fetch_cart_response.dart
│ │ ├── add_product_to_cart_params.g.dart
│ │ ├── cart.dart
│ │ ├── fetch_cart_response.g.dart
│ │ └── cart.g.dart
│ │ └── api
│ │ └── cart_api_service.dart
│ ├── home
│ ├── data
│ │ ├── api
│ │ │ └── home_api_service.dart
│ │ ├── models
│ │ │ └── fetch_home_response.dart
│ │ ├── datasources
│ │ │ └── home_local_datasource.dart
│ │ └── repos
│ │ │ └── home_repo.dart
│ └── presentation
│ │ └── widgets
│ │ └── list_title.dart
│ ├── favorites
│ ├── data
│ │ └── models
│ │ │ ├── prefer_params.dart
│ │ │ ├── prefer_params.g.dart
│ │ │ ├── fetch_fav_stores_response.dart
│ │ │ └── fetch_favorite_products_response.dart
│ └── presentation
│ │ ├── widgets
│ │ └── favorite_products_grid_view.dart
│ │ └── cubits
│ │ ├── fetch_favorites
│ │ └── fetch_favorites_state.dart
│ │ └── favorites
│ │ └── general_state.dart
│ ├── payment
│ ├── data
│ │ ├── models
│ │ │ ├── card_type.dart
│ │ │ └── payment_card_details.dart
│ │ ├── api
│ │ │ └── payment_api_service.dart
│ │ ├── repositories
│ │ │ └── payment_repo.dart
│ │ └── datasource
│ │ │ └── payment_local_datasource.dart
│ └── presentation
│ │ ├── widgets
│ │ ├── payment_text_field_label.dart
│ │ ├── payment_progress_circles.dart
│ │ ├── card_details_text.dart
│ │ └── check_box_bloc_selector.dart
│ │ └── cubits
│ │ └── payment_state.dart
│ ├── product_details
│ └── presentation
│ │ ├── widgets
│ │ └── product_details_section_title.dart
│ │ └── cubit
│ │ └── product_details_state.dart
│ └── stores
│ ├── data
│ └── models
│ │ ├── fetch_store_categories_response.dart
│ │ ├── fetch_stores_response.dart
│ │ ├── fetch_store_offers_response.dart
│ │ └── fetch_store_branches.dart
│ └── presentation
│ ├── cubits
│ ├── stores
│ │ └── stores_state.dart
│ └── store_details
│ │ └── store_details_state.dart
│ └── widgets
│ ├── categories_grid_view_shimmer.dart
│ └── stores_shimmer_loading.dart
├── assets
├── app_icon.png
├── icons
│ ├── Search.png
│ ├── profile.png
│ └── location_icon.png
├── images
│ ├── cash.png
│ ├── visa.png
│ ├── paypal.png
│ ├── splash.png
│ ├── empty-cart.png
│ ├── credit_card.png
│ ├── dark_splash.png
│ ├── master_card.png
│ ├── no_internet.png
│ ├── on_boarding1.png
│ ├── on_boarding2.png
│ ├── on_boarding3.png
│ ├── default_error.png
│ ├── empty-favorites.png
│ ├── no-notifications.png
│ ├── otp_verification.png
│ ├── splash_android_12.png
│ ├── payment_successfully.png
│ └── dark_splash_android_12.png
└── fonts
│ ├── Poppins
│ ├── Poppins-Bold.ttf
│ ├── Poppins-Medium.ttf
│ ├── Poppins-Regular.ttf
│ ├── Poppins-ExtraBold.ttf
│ └── Poppins-SemiBold.ttf
│ └── PottaOne
│ └── PottaOne-Regular.ttf
├── android
├── gradle.properties
├── app
│ ├── src
│ │ ├── main
│ │ │ ├── res
│ │ │ │ ├── drawable
│ │ │ │ │ ├── background.png
│ │ │ │ │ └── launch_background.xml
│ │ │ │ ├── drawable-hdpi
│ │ │ │ │ ├── splash.png
│ │ │ │ │ └── android12splash.png
│ │ │ │ ├── drawable-mdpi
│ │ │ │ │ ├── splash.png
│ │ │ │ │ └── android12splash.png
│ │ │ │ ├── drawable-xhdpi
│ │ │ │ │ ├── splash.png
│ │ │ │ │ └── android12splash.png
│ │ │ │ ├── drawable-v21
│ │ │ │ │ ├── background.png
│ │ │ │ │ └── launch_background.xml
│ │ │ │ ├── drawable-xxhdpi
│ │ │ │ │ ├── splash.png
│ │ │ │ │ └── android12splash.png
│ │ │ │ ├── drawable-xxxhdpi
│ │ │ │ │ ├── splash.png
│ │ │ │ │ └── android12splash.png
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── drawable-night-hdpi
│ │ │ │ │ ├── splash.png
│ │ │ │ │ └── android12splash.png
│ │ │ │ ├── drawable-night-mdpi
│ │ │ │ │ ├── splash.png
│ │ │ │ │ └── android12splash.png
│ │ │ │ ├── drawable-night
│ │ │ │ │ ├── background.png
│ │ │ │ │ └── launch_background.xml
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── drawable-night-v21
│ │ │ │ │ ├── background.png
│ │ │ │ │ └── launch_background.xml
│ │ │ │ ├── drawable-night-xhdpi
│ │ │ │ │ ├── splash.png
│ │ │ │ │ └── android12splash.png
│ │ │ │ ├── drawable-night-xxhdpi
│ │ │ │ │ ├── splash.png
│ │ │ │ │ └── android12splash.png
│ │ │ │ ├── drawable-night-xxxhdpi
│ │ │ │ │ ├── splash.png
│ │ │ │ │ └── android12splash.png
│ │ │ │ ├── values-v31
│ │ │ │ │ └── styles.xml
│ │ │ │ ├── values-night-v31
│ │ │ │ │ └── styles.xml
│ │ │ │ ├── values
│ │ │ │ │ └── styles.xml
│ │ │ │ └── values-night
│ │ │ │ │ └── styles.xml
│ │ │ └── kotlin
│ │ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── store_ify
│ │ │ │ └── MainActivity.kt
│ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ └── profile
│ │ │ └── AndroidManifest.xml
│ └── google-services.json
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── .gitignore
├── build.gradle
└── settings.gradle
├── devtools_options.yaml
├── analysis_options.yaml
├── flutter_native_splash.yaml
├── .gitignore
└── LICENSE.txt
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/lib/core/helpers/enums.dart:
--------------------------------------------------------------------------------
1 | enum FavItemType { product, store }
2 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/assets/app_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/app_icon.png
--------------------------------------------------------------------------------
/assets/icons/Search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/icons/Search.png
--------------------------------------------------------------------------------
/assets/images/cash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/images/cash.png
--------------------------------------------------------------------------------
/assets/images/visa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/images/visa.png
--------------------------------------------------------------------------------
/assets/icons/profile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/icons/profile.png
--------------------------------------------------------------------------------
/assets/images/paypal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/images/paypal.png
--------------------------------------------------------------------------------
/assets/images/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/images/splash.png
--------------------------------------------------------------------------------
/assets/images/empty-cart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/images/empty-cart.png
--------------------------------------------------------------------------------
/assets/icons/location_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/icons/location_icon.png
--------------------------------------------------------------------------------
/assets/images/credit_card.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/images/credit_card.png
--------------------------------------------------------------------------------
/assets/images/dark_splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/images/dark_splash.png
--------------------------------------------------------------------------------
/assets/images/master_card.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/images/master_card.png
--------------------------------------------------------------------------------
/assets/images/no_internet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/images/no_internet.png
--------------------------------------------------------------------------------
/assets/images/on_boarding1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/images/on_boarding1.png
--------------------------------------------------------------------------------
/assets/images/on_boarding2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/images/on_boarding2.png
--------------------------------------------------------------------------------
/assets/images/on_boarding3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/images/on_boarding3.png
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/assets/images/default_error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/images/default_error.png
--------------------------------------------------------------------------------
/assets/images/empty-favorites.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/images/empty-favorites.png
--------------------------------------------------------------------------------
/assets/images/no-notifications.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/images/no-notifications.png
--------------------------------------------------------------------------------
/assets/images/otp_verification.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/images/otp_verification.png
--------------------------------------------------------------------------------
/assets/images/splash_android_12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/images/splash_android_12.png
--------------------------------------------------------------------------------
/assets/fonts/Poppins/Poppins-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/fonts/Poppins/Poppins-Bold.ttf
--------------------------------------------------------------------------------
/assets/images/payment_successfully.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/images/payment_successfully.png
--------------------------------------------------------------------------------
/assets/fonts/Poppins/Poppins-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/fonts/Poppins/Poppins-Medium.ttf
--------------------------------------------------------------------------------
/assets/fonts/Poppins/Poppins-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/fonts/Poppins/Poppins-Regular.ttf
--------------------------------------------------------------------------------
/assets/images/dark_splash_android_12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/images/dark_splash_android_12.png
--------------------------------------------------------------------------------
/assets/fonts/Poppins/Poppins-ExtraBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/fonts/Poppins/Poppins-ExtraBold.ttf
--------------------------------------------------------------------------------
/assets/fonts/Poppins/Poppins-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/fonts/Poppins/Poppins-SemiBold.ttf
--------------------------------------------------------------------------------
/assets/fonts/PottaOne/PottaOne-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/assets/fonts/PottaOne/PottaOne-Regular.ttf
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable/background.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-hdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-hdpi/splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-mdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-mdpi/splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-xhdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-xhdpi/splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-v21/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-v21/background.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-xxhdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-xxhdpi/splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-xxxhdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-xxxhdpi/splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/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/ahmedghaly15/Storeify/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/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-night-hdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-night-hdpi/splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-night-mdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-night-mdpi/splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-night/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-night/background.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/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/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-hdpi/android12splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-hdpi/android12splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-mdpi/android12splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-mdpi/android12splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-night-v21/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-night-v21/background.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-night-xhdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-night-xhdpi/splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-night-xxhdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-night-xxhdpi/splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-night-xxxhdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-night-xxxhdpi/splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-xhdpi/android12splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-xhdpi/android12splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-xxhdpi/android12splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-xxhdpi/android12splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-xxxhdpi/android12splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-xxxhdpi/android12splash.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-night-hdpi/android12splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-night-hdpi/android12splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-night-mdpi/android12splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-night-mdpi/android12splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-night-xhdpi/android12splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-night-xhdpi/android12splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/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/ahmedghaly15/Storeify/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/ahmedghaly15/Storeify/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/ahmedghaly15/Storeify/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/ahmedghaly15/Storeify/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/ahmedghaly15/Storeify/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/ahmedghaly15/Storeify/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/ahmedghaly15/Storeify/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/ahmedghaly15/Storeify/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/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/ahmedghaly15/Storeify/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/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/ahmedghaly15/Storeify/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark.png
--------------------------------------------------------------------------------
/devtools_options.yaml:
--------------------------------------------------------------------------------
1 | description: This file stores settings for Dart & Flutter DevTools.
2 | documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/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/ahmedghaly15/Storeify/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedghaly15/Storeify/HEAD/ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/example/store_ify/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.store_ify
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
6 |
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: package:flutter_lints/flutter.yaml
2 |
3 | analyzer:
4 | exclude:
5 | - "**/*.g.dart"
6 | - "**/*.freezed.dart"
7 | errors:
8 | invalid_annotation_target: ignore
9 | use_build_context_synchronously: ignore
10 |
--------------------------------------------------------------------------------
/lib/features/categories/data/models/fetch_sub_category_params.dart:
--------------------------------------------------------------------------------
1 | class FetchSubCategoryParams {
2 | final int categoryId;
3 | final int subCategoryId;
4 |
5 | const FetchSubCategoryParams({
6 | required this.categoryId,
7 | required this.subCategoryId,
8 | });
9 | }
10 |
--------------------------------------------------------------------------------
/lib/features/profile/data/models/update_profile_params.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | class UpdateProfileParams {
4 | final String? username, email;
5 | final File? img;
6 |
7 | const UpdateProfileParams({
8 | this.username,
9 | this.email,
10 | this.img,
11 | });
12 | }
13 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/firebase_app_id_file.json:
--------------------------------------------------------------------------------
1 | {
2 | "file_generated_by": "FlutterFire CLI",
3 | "purpose": "FirebaseAppID & ProjectID for this Firebase app in this directory",
4 | "GOOGLE_APP_ID": "1:74739450491:ios:bd1f70b20eb2a84e8e58de",
5 | "FIREBASE_PROJECT_ID": "store-ify-ecommerce",
6 | "GCM_SENDER_ID": "74739450491"
7 | }
--------------------------------------------------------------------------------
/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 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 | **/*.keystore
13 | **/*.jks
14 |
--------------------------------------------------------------------------------
/lib/core/helpers/debouncer.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter/material.dart';
4 |
5 | class Debouncer {
6 | final Duration duration;
7 | Timer? _timer;
8 |
9 | Debouncer({required this.duration});
10 |
11 | void run(VoidCallback action) {
12 | _timer?.cancel();
13 | _timer = Timer(duration, action);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/ios/RunnerTests/RunnerTests.swift:
--------------------------------------------------------------------------------
1 | import Flutter
2 | import UIKit
3 | import XCTest
4 |
5 | class RunnerTests: XCTestCase {
6 |
7 | func testExample() {
8 | // If you add code to the Runner application, consider adding tests here.
9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/lib/features/checkout/data/models/payment_method.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 |
3 | part 'payment_method.freezed.dart';
4 |
5 | @freezed
6 | class PaymentMethod with _$PaymentMethod {
7 | const factory PaymentMethod({
8 | required int id,
9 | required String name,
10 | required String image,
11 | }) = _PaymentMethod;
12 | }
13 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 | -
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/lib/core/api/api_result.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 | import 'package:store_ify/core/api/api_error_model.dart';
3 |
4 | part 'api_result.freezed.dart';
5 |
6 | @Freezed()
7 | abstract class ApiResult with _$ApiResult {
8 | const factory ApiResult.success(T data) = Success;
9 | const factory ApiResult.error(ApiErrorModel errorModel) = Error;
10 | }
11 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-night/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 | -
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 | -
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-night-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 | -
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | allprojects {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | }
6 | }
7 |
8 | rootProject.buildDir = '../build'
9 | subprojects {
10 | project.buildDir = "${rootProject.buildDir}/${project.name}"
11 | }
12 | subprojects {
13 | project.evaluationDependsOn(':app')
14 | }
15 |
16 | tasks.register("clean", Delete) {
17 | delete rootProject.buildDir
18 | }
19 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/lib/features/layout/data/models/bottom_nav_item_attributes.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class BottomNavItemAttributes {
4 | const BottomNavItemAttributes({
5 | required this.index,
6 | required this.icon,
7 | required this.labelKey,
8 | required this.color,
9 | });
10 |
11 | final int index;
12 | final IconData icon;
13 | final String labelKey;
14 | final Color color;
15 | }
16 |
--------------------------------------------------------------------------------
/lib/features/onboarding/data/models/onboarding_attributes.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 |
3 | part 'onboarding_attributes.freezed.dart';
4 |
5 | @freezed
6 | class OnboardingAttributes with _$OnboardingAttributes {
7 | const factory OnboardingAttributes({
8 | required String image,
9 | required String titleKey,
10 | required String subTitleKey,
11 | }) = _OnboardingAttributes;
12 | }
13 |
--------------------------------------------------------------------------------
/flutter_native_splash.yaml:
--------------------------------------------------------------------------------
1 | flutter_native_splash:
2 | # IOS & Android below 12
3 | color: "#ffffff"
4 | image: assets/images/splash.png
5 | image_dark: assets/images/dark_splash.png
6 | color_dark: "#000000"
7 |
8 | android_12:
9 | image: assets/images/splash_android_12.png
10 | color: "#ffffff"
11 | image_dark: assets/images/dark_splash_android_12.png
12 | color_dark: "#000000"
13 |
14 | android: true
15 | ios: true
--------------------------------------------------------------------------------
/lib/features/search/data/models/search_params.dart:
--------------------------------------------------------------------------------
1 | import 'package:json_annotation/json_annotation.dart';
2 |
3 | part 'search_params.g.dart';
4 |
5 | @JsonSerializable()
6 | class SearchParams {
7 | final String search;
8 |
9 | const SearchParams(this.search);
10 |
11 | factory SearchParams.fromJson(Map json) =>
12 | _$SearchParamsFromJson(json);
13 | Map toJson() => _$SearchParamsToJson(this);
14 | }
15 |
--------------------------------------------------------------------------------
/lib/core/api/api_error_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 |
3 | part 'api_error_model.g.dart';
4 | part 'api_error_model.freezed.dart';
5 |
6 | @freezed
7 | class ApiErrorModel with _$ApiErrorModel {
8 | const factory ApiErrorModel({
9 | @JsonKey(name: 'code') String? error,
10 | }) = _ApiErrorModel;
11 |
12 | factory ApiErrorModel.fromJson(Map json) =>
13 | _$ApiErrorModelFromJson(json);
14 | }
15 |
--------------------------------------------------------------------------------
/lib/core/helpers/cache_keys.dart:
--------------------------------------------------------------------------------
1 | class CacheKeys {
2 | CacheKeys._();
3 |
4 | static const String locale = 'locale';
5 | static const String onboarding = 'onboarding';
6 | static const String storeifyUser = 'storeifyUser';
7 | static const String appTheme = 'appTheme';
8 | static const String firstLaunch = 'firstLaunch';
9 | static const String countryCodeTimestamp = 'countryCodeTimestamp';
10 | static const String countryCode = 'countryCode';
11 | }
12 |
--------------------------------------------------------------------------------
/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/core/utils/app_strings.dart:
--------------------------------------------------------------------------------
1 | class AppStrings {
2 | static const String appTitle = 'Store-ify';
3 | static const String fontFamily = 'Poppins';
4 | static const String pottaOneFont = 'PottaOne';
5 | static const String localePath = 'assets/translations';
6 | static const String arabicLangCode = 'ar';
7 | static const String englishLangCode = 'en';
8 | static const String searchRequiredErrorKey = 'SEARCH_REQUIRED';
9 | static const String checkoutDateFormat = 'yyyy-MM-dd';
10 | }
11 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "background.png",
5 | "idiom" : "universal"
6 | },
7 | {
8 | "appearances" : [
9 | {
10 | "appearance" : "luminosity",
11 | "value" : "dark"
12 | }
13 | ],
14 | "filename" : "darkbackground.png",
15 | "idiom" : "universal"
16 | }
17 | ],
18 | "info" : {
19 | "author" : "xcode",
20 | "version" : 1
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lib/features/checkout/data/models/fetch_city_data.dart:
--------------------------------------------------------------------------------
1 | import 'package:json_annotation/json_annotation.dart';
2 |
3 | part 'fetch_city_data.g.dart';
4 |
5 | @JsonSerializable()
6 | class FetchCityData {
7 | @JsonKey(name: 'display_name')
8 | final String displayName;
9 |
10 | FetchCityData({required this.displayName});
11 |
12 | factory FetchCityData.fromJson(Map json) =>
13 | _$FetchCityDataFromJson(json);
14 | Map toJson() => _$FetchCityDataToJson(this);
15 | }
16 |
--------------------------------------------------------------------------------
/lib/features/profile/data/models/change_api_lang_params.dart:
--------------------------------------------------------------------------------
1 | import 'package:json_annotation/json_annotation.dart';
2 |
3 | part 'change_api_lang_params.g.dart';
4 |
5 | @JsonSerializable()
6 | class ChangeApiLangParams {
7 | final String lang;
8 |
9 | const ChangeApiLangParams({required this.lang});
10 |
11 | factory ChangeApiLangParams.fromJson(Map json) =>
12 | _$ChangeApiLangParamsFromJson(json);
13 |
14 | Map toJson() => _$ChangeApiLangParamsToJson(this);
15 | }
16 |
--------------------------------------------------------------------------------
/lib/core/utils/functions/check_if_onboarding_visited.dart:
--------------------------------------------------------------------------------
1 | import 'package:store_ify/core/helpers/shared_pref_helper.dart';
2 | import 'package:store_ify/core/helpers/cache_keys.dart';
3 | import 'package:store_ify/core/utils/app_constants.dart';
4 |
5 | Future checkIfOnboardingIsVisited() async {
6 | final onboarding = await SharedPrefHelper.getBool(CacheKeys.onboarding);
7 | if (onboarding != null) {
8 | isOnboardingVisited = onboarding;
9 | } else {
10 | isOnboardingVisited = false;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/lib/features/auth/data/models/forgot_password_params.dart:
--------------------------------------------------------------------------------
1 | import 'package:json_annotation/json_annotation.dart';
2 |
3 | part 'forgot_password_params.g.dart';
4 |
5 | @JsonSerializable()
6 | class ForgotPasswordParams {
7 | final String email;
8 |
9 | const ForgotPasswordParams({required this.email});
10 |
11 | factory ForgotPasswordParams.fromJson(Map json) =>
12 | _$ForgotPasswordParamsFromJson(json);
13 |
14 | Map toJson() => _$ForgotPasswordParamsToJson(this);
15 | }
16 |
--------------------------------------------------------------------------------
/lib/features/auth/data/models/validate_otp_params.dart:
--------------------------------------------------------------------------------
1 | import 'package:json_annotation/json_annotation.dart';
2 |
3 | part 'validate_otp_params.g.dart';
4 |
5 | @JsonSerializable()
6 | class ValidateOtpParams {
7 | final String otp, email;
8 |
9 | const ValidateOtpParams({required this.otp, required this.email});
10 |
11 | factory ValidateOtpParams.fromJson(Map json) =>
12 | _$ValidateOtpParamsFromJson(json);
13 |
14 | Map toJson() => _$ValidateOtpParamsToJson(this);
15 | }
16 |
--------------------------------------------------------------------------------
/lib/features/auth/data/models/login_params.dart:
--------------------------------------------------------------------------------
1 | import 'package:json_annotation/json_annotation.dart';
2 |
3 | part 'login_params.g.dart';
4 |
5 | @JsonSerializable()
6 | class LoginParams {
7 | final String email;
8 | final String password;
9 |
10 | const LoginParams({
11 | required this.email,
12 | required this.password,
13 | });
14 |
15 | factory LoginParams.fromJson(Map json) =>
16 | _$LoginParamsFromJson(json);
17 |
18 | Map toJson() => _$LoginParamsToJson(this);
19 | }
20 |
--------------------------------------------------------------------------------
/lib/features/cart/presentation/widgets/cart_summary_divider.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_screenutil/flutter_screenutil.dart';
3 | import 'package:store_ify/core/themes/app_colors.dart';
4 |
5 | class CartSummaryDivider extends StatelessWidget {
6 | const CartSummaryDivider({super.key});
7 |
8 | @override
9 | Widget build(BuildContext context) {
10 | return Divider(
11 | color: AppColors.colorBEBEC3,
12 | thickness: 0.5.w,
13 | height: 1.h,
14 | );
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/lib/features/home/data/api/home_api_service.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:retrofit/retrofit.dart';
3 | import 'package:store_ify/core/api/end_points.dart';
4 | import 'package:store_ify/features/home/data/models/fetch_home_response.dart';
5 |
6 | part 'home_api_service.g.dart';
7 |
8 | @RestApi(baseUrl: EndPoints.baseUrl)
9 | abstract class HomeApiService {
10 | factory HomeApiService(Dio dio, {String baseUrl}) = _HomeApiService;
11 |
12 | @GET(EndPoints.fetchHomeData)
13 | Future fetchHomeData();
14 | }
15 |
--------------------------------------------------------------------------------
/lib/features/favorites/data/models/prefer_params.dart:
--------------------------------------------------------------------------------
1 | import 'package:json_annotation/json_annotation.dart';
2 |
3 | part 'prefer_params.g.dart';
4 |
5 | @JsonSerializable()
6 | class PreferParams {
7 | @JsonKey(name: 'product_id')
8 | final int? productId;
9 | @JsonKey(name: 'store_id')
10 | final int? storeId;
11 |
12 | const PreferParams({this.productId, this.storeId});
13 |
14 | factory PreferParams.fromJson(Map json) =>
15 | _$PreferParamsFromJson(json);
16 | Map toJson() => _$PreferParamsToJson(this);
17 | }
18 |
--------------------------------------------------------------------------------
/lib/features/auth/presentation/cubits/validate_otp/validate_otp_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 |
3 | part 'validate_otp_state.freezed.dart';
4 |
5 | @freezed
6 | class ValidateOtpState with _$ValidateOtpState {
7 | const factory ValidateOtpState.initial() = _Initial;
8 | const factory ValidateOtpState.validateOtpLoading() = ValidateOtpLoading;
9 | const factory ValidateOtpState.validateOtpSuccess() = ValidateOtpSuccess;
10 | const factory ValidateOtpState.validateOtpError(String error) =
11 | ValidateOtpError;
12 | }
13 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/lib/core/utils/functions/check_if_android_above_12.dart:
--------------------------------------------------------------------------------
1 | import 'package:device_info_plus/device_info_plus.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:store_ify/core/di/dependency_injection.dart';
4 | import 'package:store_ify/core/utils/app_constants.dart';
5 |
6 | Future checkIfAndroidAbove12() async {
7 | final androidInfo = await getIt.get().androidInfo;
8 | debugPrint(
9 | '*#*#*#*#*#* ANDROID VERSION: ${androidInfo.version.release} *#*#*#*#*#*');
10 | isAndroidAbove12 =
11 | int.parse(androidInfo.version.release) >= 12 ? true : false;
12 | }
13 |
--------------------------------------------------------------------------------
/lib/features/onboarding/presentation/cubit/onboarding_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 |
3 | part 'onboarding_state.freezed.dart';
4 |
5 | enum OnboardingStateStatus {
6 | initial,
7 | onPageChanged,
8 | }
9 |
10 | @freezed
11 | class OnboardingState with _$OnboardingState {
12 | const factory OnboardingState({
13 | required OnboardingStateStatus status,
14 | @Default(false) bool isLastPage,
15 | }) = _OnboardingState;
16 |
17 | factory OnboardingState.initial() => const OnboardingState(
18 | status: OnboardingStateStatus.initial,
19 | );
20 | }
21 |
--------------------------------------------------------------------------------
/lib/features/search/data/models/search_params.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'search_params.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | SearchParams _$SearchParamsFromJson(Map json) => SearchParams(
10 | json['search'] as String,
11 | );
12 |
13 | Map _$SearchParamsToJson(SearchParams instance) =>
14 | {
15 | 'search': instance.search,
16 | };
17 |
--------------------------------------------------------------------------------
/lib/core/widgets/products_grid_view_shimmer.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:store_ify/core/utils/app_constants.dart';
3 | import 'package:store_ify/core/widgets/shimmer_widget.dart';
4 |
5 | class ProductsGridViewShimmer extends StatelessWidget {
6 | const ProductsGridViewShimmer({super.key});
7 |
8 | @override
9 | Widget build(BuildContext context) {
10 | return GridView.builder(
11 | gridDelegate: AppConstants.favProductsGridDelegate,
12 | padding: AppConstants.categoryPadding,
13 | itemCount: 10,
14 | itemBuilder: (_, __) => const ShimmerWidget(),
15 | );
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/lib/features/auth/presentation/cubits/forgot_password/forgot_password_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 |
3 | part 'forgot_password_state.freezed.dart';
4 |
5 | @freezed
6 | class ForgotPasswordState with _$ForgotPasswordState {
7 | const factory ForgotPasswordState.initial() = _Initial;
8 | const factory ForgotPasswordState.forgotPasswordLoading() =
9 | ForgotPasswordLoading;
10 | const factory ForgotPasswordState.forgotPasswordSuccess() =
11 | ForgotPasswordSuccess;
12 | const factory ForgotPasswordState.forgotPasswordError(String error) =
13 | ForgotPasswordError;
14 | }
15 |
--------------------------------------------------------------------------------
/lib/core/api/api_error_model.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'api_error_model.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | _$ApiErrorModelImpl _$$ApiErrorModelImplFromJson(Map json) =>
10 | _$ApiErrorModelImpl(
11 | error: json['code'] as String?,
12 | );
13 |
14 | Map _$$ApiErrorModelImplToJson(_$ApiErrorModelImpl instance) =>
15 | {
16 | 'code': instance.error,
17 | };
18 |
--------------------------------------------------------------------------------
/lib/features/checkout/data/models/checkout_params.dart:
--------------------------------------------------------------------------------
1 | import 'package:json_annotation/json_annotation.dart';
2 |
3 | part 'checkout_params.g.dart';
4 |
5 | @JsonSerializable()
6 | class CheckoutParams {
7 | final String username, address, phone, date, time;
8 |
9 | const CheckoutParams({
10 | required this.username,
11 | required this.address,
12 | required this.phone,
13 | required this.date,
14 | required this.time,
15 | });
16 |
17 | factory CheckoutParams.fromJson(Map json) =>
18 | _$CheckoutParamsFromJson(json);
19 |
20 | Map toJson() => _$CheckoutParamsToJson(this);
21 | }
22 |
--------------------------------------------------------------------------------
/lib/features/checkout/data/models/fetch_city_data.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'fetch_city_data.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | FetchCityData _$FetchCityDataFromJson(Map json) =>
10 | FetchCityData(
11 | displayName: json['display_name'] as String,
12 | );
13 |
14 | Map _$FetchCityDataToJson(FetchCityData instance) =>
15 | {
16 | 'display_name': instance.displayName,
17 | };
18 |
--------------------------------------------------------------------------------
/lib/core/models/product_size.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 | import 'package:hive_flutter/hive_flutter.dart';
3 | import 'package:store_ify/core/helpers/hive_type_ids.dart';
4 |
5 | part 'product_size.freezed.dart';
6 | part 'product_size.g.dart';
7 |
8 | @HiveType(typeId: HiveTypeIds.productSize)
9 | @freezed
10 | class ProductSize with _$ProductSize {
11 | @JsonSerializable()
12 | const factory ProductSize({
13 | @HiveField(0) required int id,
14 | @HiveField(1) required String size,
15 | }) = _ProductSize;
16 |
17 | factory ProductSize.fromJson(Map json) =>
18 | _$ProductSizeFromJson(json);
19 | }
20 |
--------------------------------------------------------------------------------
/lib/core/models/sub_category.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 | import 'package:hive_flutter/hive_flutter.dart';
3 | import 'package:store_ify/core/helpers/hive_type_ids.dart';
4 |
5 | part 'sub_category.g.dart';
6 | part 'sub_category.freezed.dart';
7 |
8 | @HiveType(typeId: HiveTypeIds.subCategory)
9 | @freezed
10 | class SubCategory with _$SubCategory {
11 | @JsonSerializable()
12 | const factory SubCategory({
13 | @HiveField(0) required int id,
14 | @HiveField(1) required String name,
15 | }) = _SubCategory;
16 |
17 | factory SubCategory.fromJson(Map json) =>
18 | _$SubCategoryFromJson(json);
19 | }
20 |
--------------------------------------------------------------------------------
/lib/features/payment/data/models/card_type.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 | import 'package:hive_flutter/hive_flutter.dart';
3 | import 'package:store_ify/core/helpers/hive_type_ids.dart';
4 |
5 | part 'card_type.freezed.dart';
6 | part 'card_type.g.dart';
7 |
8 | @HiveType(typeId: HiveTypeIds.cardType)
9 | @freezed
10 | class CardType with _$CardType {
11 | @JsonSerializable()
12 | const factory CardType({
13 | @HiveField(0) required String image,
14 | @HiveField(1) required String nameKey,
15 | }) = _CardType;
16 |
17 | factory CardType.fromJson(Map json) =>
18 | _$$CardTypeImplFromJson(json);
19 | }
20 |
--------------------------------------------------------------------------------
/lib/core/models/product_color.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 | import 'package:hive_flutter/hive_flutter.dart';
3 | import 'package:store_ify/core/helpers/hive_type_ids.dart';
4 |
5 | part 'product_color.freezed.dart';
6 | part 'product_color.g.dart';
7 |
8 | @HiveType(typeId: HiveTypeIds.productColor)
9 | @freezed
10 | class ProductColor with _$ProductColor {
11 | @JsonSerializable()
12 | const factory ProductColor({
13 | @HiveField(0) required int id,
14 | @HiveField(1) required String color,
15 | }) = _ProductColor;
16 |
17 | factory ProductColor.fromJson(Map json) =>
18 | _$ProductColorFromJson(json);
19 | }
20 |
--------------------------------------------------------------------------------
/lib/features/profile/data/models/change_password_params.dart:
--------------------------------------------------------------------------------
1 | import 'package:json_annotation/json_annotation.dart';
2 |
3 | part 'change_password_params.g.dart';
4 |
5 | @JsonSerializable(fieldRename: FieldRename.snake)
6 | class ChangePasswordParams {
7 | final String currentPassword, password, passwordConfirmation;
8 |
9 | ChangePasswordParams({
10 | required this.currentPassword,
11 | required this.password,
12 | required this.passwordConfirmation,
13 | });
14 |
15 | factory ChangePasswordParams.fromJson(Map json) =>
16 | _$ChangePasswordParamsFromJson(json);
17 |
18 | Map toJson() => _$ChangePasswordParamsToJson(this);
19 | }
20 |
--------------------------------------------------------------------------------
/lib/features/search/data/models/search_response.dart:
--------------------------------------------------------------------------------
1 | import 'package:json_annotation/json_annotation.dart';
2 | import 'package:store_ify/core/models/pagination.dart';
3 | import 'package:store_ify/core/models/product.dart';
4 |
5 | part 'search_response.g.dart';
6 |
7 | @JsonSerializable()
8 | class SearchResponse {
9 | final List products;
10 | final Pagination? pagination;
11 |
12 | const SearchResponse({
13 | required this.products,
14 | required this.pagination,
15 | });
16 |
17 | factory SearchResponse.fromJson(Map json) =>
18 | _$SearchResponseFromJson(json);
19 | Map toJson() => _$SearchResponseToJson(this);
20 | }
21 |
--------------------------------------------------------------------------------
/lib/core/utils/functions/toggle_lang.dart:
--------------------------------------------------------------------------------
1 | import 'package:easy_localization/easy_localization.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_bloc/flutter_bloc.dart';
4 | import 'package:store_ify/core/utils/app_strings.dart';
5 | import 'package:store_ify/features/profile/presentation/cubits/profile_cubit.dart';
6 |
7 | void toggleLang(BuildContext context) {
8 | final newLocale = context.locale.languageCode == AppStrings.englishLangCode
9 | ? const Locale(AppStrings.arabicLangCode)
10 | : const Locale(AppStrings.englishLangCode);
11 |
12 | context.setLocale(newLocale);
13 | context.read().toggleLocale(newLocale.languageCode);
14 | }
15 |
--------------------------------------------------------------------------------
/lib/core/widgets/cancel_outlined_button.dart:
--------------------------------------------------------------------------------
1 | import 'package:auto_route/auto_route.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:store_ify/core/widgets/main_button.dart';
4 | import 'package:store_ify/generated/locale_keys.g.dart';
5 |
6 | class CancelOutlinedButton extends StatelessWidget {
7 | const CancelOutlinedButton({super.key, this.onCancel});
8 |
9 | final VoidCallback? onCancel;
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | return MainButton(
14 | onPressed: onCancel ?? () => context.maybePop(),
15 | textKey: LocaleKeys.cancel,
16 | isOutlined: true,
17 | margin: EdgeInsets.zero,
18 | );
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lib/features/checkout/data/models/choose_payment_method_params.dart:
--------------------------------------------------------------------------------
1 | import 'package:json_annotation/json_annotation.dart';
2 |
3 | part 'choose_payment_method_params.g.dart';
4 |
5 | @JsonSerializable()
6 | class ChoosePaymentMethodParams {
7 | final int paymentId;
8 | @JsonKey(name: 'payment_method')
9 | final String paymentMethod;
10 |
11 | const ChoosePaymentMethodParams({
12 | required this.paymentId,
13 | required this.paymentMethod,
14 | });
15 |
16 | factory ChoosePaymentMethodParams.fromJson(Map json) =>
17 | _$ChoosePaymentMethodParamsFromJson(json);
18 |
19 | Map toJson() => _$ChoosePaymentMethodParamsToJson(this);
20 | }
21 |
--------------------------------------------------------------------------------
/lib/features/profile/data/models/change_api_lang_params.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'change_api_lang_params.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | ChangeApiLangParams _$ChangeApiLangParamsFromJson(Map json) =>
10 | ChangeApiLangParams(
11 | lang: json['lang'] as String,
12 | );
13 |
14 | Map _$ChangeApiLangParamsToJson(
15 | ChangeApiLangParams instance) =>
16 | {
17 | 'lang': instance.lang,
18 | };
19 |
--------------------------------------------------------------------------------
/lib/features/auth/data/models/reset_password_params.dart:
--------------------------------------------------------------------------------
1 | import 'package:json_annotation/json_annotation.dart';
2 |
3 | part 'reset_password_params.g.dart';
4 |
5 | @JsonSerializable()
6 | class ResetPasswordParams {
7 | final String email, password;
8 | @JsonKey(name: 'password_confirmation')
9 | final String passwordConfirmation;
10 |
11 | const ResetPasswordParams({
12 | required this.email,
13 | required this.password,
14 | required this.passwordConfirmation,
15 | });
16 |
17 | factory ResetPasswordParams.fromJson(Map json) =>
18 | _$ResetPasswordParamsFromJson(json);
19 | Map toJson() => _$ResetPasswordParamsToJson(this);
20 | }
21 |
--------------------------------------------------------------------------------
/lib/features/auth/data/models/login_params.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'login_params.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | LoginParams _$LoginParamsFromJson(Map json) => LoginParams(
10 | email: json['email'] as String,
11 | password: json['password'] as String,
12 | );
13 |
14 | Map _$LoginParamsToJson(LoginParams instance) =>
15 | {
16 | 'email': instance.email,
17 | 'password': instance.password,
18 | };
19 |
--------------------------------------------------------------------------------
/lib/features/payment/data/api/payment_api_service.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:retrofit/retrofit.dart';
3 | import 'package:store_ify/core/api/end_points.dart';
4 | import 'package:store_ify/features/payment/data/models/payment_card_details.dart';
5 |
6 | part 'payment_api_service.g.dart';
7 |
8 | @RestApi(baseUrl: EndPoints.baseUrl)
9 | abstract class PaymentApiService {
10 | factory PaymentApiService(Dio dio, {String baseUrl}) = _PaymentApiService;
11 |
12 | @POST('${EndPoints.pay}{orderId}')
13 | Future orderPay(
14 | @Path('orderId') int orderId,
15 | @Body() PaymentCardDetails params, [
16 | @CancelRequest() CancelToken? cancelToken,
17 | ]);
18 | }
19 |
--------------------------------------------------------------------------------
/lib/features/auth/data/models/register_params.dart:
--------------------------------------------------------------------------------
1 | import 'package:json_annotation/json_annotation.dart';
2 |
3 | part 'register_params.g.dart';
4 |
5 | @JsonSerializable()
6 | class RegisterParams {
7 | final String username, email, password;
8 | @JsonKey(name: 'password_confirmation')
9 | final String passwordConfirmation;
10 |
11 | const RegisterParams({
12 | required this.username,
13 | required this.email,
14 | required this.password,
15 | required this.passwordConfirmation,
16 | });
17 |
18 | factory RegisterParams.fromJson(Map json) =>
19 | _$RegisterParamsFromJson(json);
20 |
21 | Map toJson() => _$RegisterParamsToJson(this);
22 | }
23 |
--------------------------------------------------------------------------------
/lib/features/auth/data/models/forgot_password_params.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'forgot_password_params.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | ForgotPasswordParams _$ForgotPasswordParamsFromJson(
10 | Map json) =>
11 | ForgotPasswordParams(
12 | email: json['email'] as String,
13 | );
14 |
15 | Map _$ForgotPasswordParamsToJson(
16 | ForgotPasswordParams instance) =>
17 | {
18 | 'email': instance.email,
19 | };
20 |
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | **/dgph
2 | *.mode1v3
3 | *.mode2v3
4 | *.moved-aside
5 | *.pbxuser
6 | *.perspectivev3
7 | **/*sync/
8 | .sconsign.dblite
9 | .tags*
10 | **/.vagrant/
11 | **/DerivedData/
12 | Icon?
13 | **/Pods/
14 | **/.symlinks/
15 | profile
16 | xcuserdata
17 | **/.generated/
18 | Flutter/App.framework
19 | Flutter/Flutter.framework
20 | Flutter/Flutter.podspec
21 | Flutter/Generated.xcconfig
22 | Flutter/ephemeral/
23 | Flutter/app.flx
24 | Flutter/app.zip
25 | Flutter/flutter_assets/
26 | Flutter/flutter_export_environment.sh
27 | ServiceDefinitions.json
28 | Runner/GeneratedPluginRegistrant.*
29 |
30 | # Exceptions to above rules.
31 | !default.mode1v3
32 | !default.mode2v3
33 | !default.pbxuser
34 | !default.perspectivev3
35 |
--------------------------------------------------------------------------------
/lib/features/auth/data/models/validate_otp_params.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'validate_otp_params.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | ValidateOtpParams _$ValidateOtpParamsFromJson(Map json) =>
10 | ValidateOtpParams(
11 | otp: json['otp'] as String,
12 | email: json['email'] as String,
13 | );
14 |
15 | Map _$ValidateOtpParamsToJson(ValidateOtpParams instance) =>
16 | {
17 | 'otp': instance.otp,
18 | 'email': instance.email,
19 | };
20 |
--------------------------------------------------------------------------------
/lib/core/utils/functions/check_if_user_is_logged_in.dart:
--------------------------------------------------------------------------------
1 | import 'package:store_ify/core/helpers/extensions.dart';
2 | import 'package:store_ify/core/helpers/secure_storage_helper.dart';
3 | import 'package:store_ify/core/helpers/cache_keys.dart';
4 | import 'package:store_ify/core/utils/app_constants.dart';
5 | import 'package:store_ify/features/auth/data/datasources/auth_local_datasource.dart';
6 |
7 | Future checkIfUserIsLoggedIn() async {
8 | final cachedUser =
9 | await SecureStorageHelper.getSecuredString(CacheKeys.storeifyUser);
10 | if (cachedUser.isNullOrEmpty) {
11 | isUserLoggedIn = false;
12 | } else {
13 | isUserLoggedIn = true;
14 | currentUser = await AuthLocalDatasource.getCachedUser();
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/lib/core/utils/functions/get_color_from_string.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | Color? getColorFromString(String colorName) {
4 | final Map colorMap = {
5 | 'red': Colors.red,
6 | 'blue': Colors.blue,
7 | 'green': Colors.green,
8 | 'yellow': Colors.yellow,
9 | 'orange': Colors.orange,
10 | 'purple': Colors.purple,
11 | 'pink': Colors.pink,
12 | 'brown': Colors.brown,
13 | 'grey': Colors.grey,
14 | 'black': Colors.black,
15 | 'white': Colors.white,
16 | 'cyan': Colors.cyan,
17 | 'amber': Colors.amber,
18 | 'indigo': Colors.indigo,
19 | 'lime': Colors.lime,
20 | 'teal': Colors.teal,
21 | };
22 |
23 | return colorMap[colorName.toLowerCase()];
24 | }
25 |
--------------------------------------------------------------------------------
/lib/features/checkout/presentation/widgets/check_circle.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_screenutil/flutter_screenutil.dart';
3 | import 'package:store_ify/core/themes/app_colors.dart';
4 |
5 | class CheckCircle extends StatelessWidget {
6 | const CheckCircle({super.key});
7 |
8 | @override
9 | Widget build(BuildContext context) {
10 | return Container(
11 | height: 20.48.h,
12 | width: 20.48.h,
13 | decoration: const BoxDecoration(
14 | shape: BoxShape.circle,
15 | color: AppColors.primaryColor,
16 | ),
17 | child: Icon(
18 | Icons.check,
19 | color: AppColors.lightModeColor,
20 | size: 16.w,
21 | ),
22 | );
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/lib/features/favorites/data/models/prefer_params.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'prefer_params.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | PreferParams _$PreferParamsFromJson(Map json) => PreferParams(
10 | productId: (json['product_id'] as num?)?.toInt(),
11 | storeId: (json['store_id'] as num?)?.toInt(),
12 | );
13 |
14 | Map _$PreferParamsToJson(PreferParams instance) =>
15 | {
16 | 'product_id': instance.productId,
17 | 'store_id': instance.storeId,
18 | };
19 |
--------------------------------------------------------------------------------
/lib/features/auth/presentation/cubits/login/login_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 | import 'package:store_ify/core/models/storeify_user.dart';
3 |
4 | part 'login_state.freezed.dart';
5 |
6 | enum LoginStateStatus {
7 | initial,
8 | loginLoading,
9 | loginSuccess,
10 | loginError,
11 | togglePassVisibility,
12 | }
13 |
14 | @freezed
15 | class LoginState with _$LoginState {
16 | const factory LoginState({
17 | required LoginStateStatus status,
18 | StoreifyUser? user,
19 | String? error,
20 | @Default(true) bool isPasswordObscure,
21 | }) = _LoginState;
22 |
23 | factory LoginState.initial() => const LoginState(
24 | status: LoginStateStatus.initial,
25 | );
26 | }
27 |
--------------------------------------------------------------------------------
/lib/features/product_details/presentation/widgets/product_details_section_title.dart:
--------------------------------------------------------------------------------
1 | import 'package:easy_localization/easy_localization.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:store_ify/core/themes/app_colors.dart';
4 | import 'package:store_ify/core/themes/app_text_styles.dart';
5 |
6 | class ProductDetailsSectionTitle extends StatelessWidget {
7 | const ProductDetailsSectionTitle({
8 | super.key,
9 | required this.titleKey,
10 | });
11 |
12 | final String titleKey;
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | return Text(
17 | context.tr(titleKey),
18 | style: AppTextStyles.textStyle16Medium
19 | .copyWith(color: AppColors.primaryColor),
20 | );
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lib/features/cart/data/models/add_product_to_cart_params.dart:
--------------------------------------------------------------------------------
1 | import 'package:json_annotation/json_annotation.dart';
2 |
3 | part 'add_product_to_cart_params.g.dart';
4 |
5 | @JsonSerializable()
6 | class AddProductToCartParams {
7 | final int productId;
8 | @JsonKey(name: 'color_id')
9 | final int? colorId;
10 | @JsonKey(name: 'size_id')
11 | final int? sizeId;
12 | final int quantity;
13 |
14 | const AddProductToCartParams({
15 | required this.productId,
16 | required this.quantity,
17 | this.sizeId,
18 | this.colorId,
19 | });
20 |
21 | factory AddProductToCartParams.fromJson(Map json) =>
22 | _$AddProductToCartParamsFromJson(json);
23 | Map toJson() => _$AddProductToCartParamsToJson(this);
24 | }
25 |
--------------------------------------------------------------------------------
/lib/features/payment/presentation/widgets/payment_text_field_label.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_screenutil/flutter_screenutil.dart';
3 | import 'package:store_ify/core/themes/app_text_styles.dart';
4 | import 'package:store_ify/features/auth/presentation/widgets/text_field_label.dart';
5 |
6 | class PaymentTextFieldLabel extends StatelessWidget {
7 | const PaymentTextFieldLabel({
8 | super.key,
9 | required this.labelKey,
10 | });
11 |
12 | final String labelKey;
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | return TextFieldLabel(
17 | labelKey: labelKey,
18 | margin: EdgeInsetsDirectional.only(bottom: 11.h),
19 | textStyle: AppTextStyles.textStyle14Regular,
20 | );
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lib/features/favorites/data/models/fetch_fav_stores_response.dart:
--------------------------------------------------------------------------------
1 | import 'package:hive_flutter/hive_flutter.dart';
2 | import 'package:json_annotation/json_annotation.dart';
3 | import 'package:store_ify/core/helpers/hive_type_ids.dart';
4 | import 'package:store_ify/core/models/store.dart';
5 |
6 | part 'fetch_fav_stores_response.g.dart';
7 |
8 | @HiveType(typeId: HiveTypeIds.fetchFavStoresResponse)
9 | @JsonSerializable()
10 | class FetchFavStoresResponse {
11 | @HiveField(0)
12 | final List stores;
13 |
14 | const FetchFavStoresResponse({required this.stores});
15 |
16 | factory FetchFavStoresResponse.fromJson(Map json) =>
17 | _$FetchFavStoresResponseFromJson(json);
18 | Map toJson() => _$FetchFavStoresResponseToJson(this);
19 | }
20 |
--------------------------------------------------------------------------------
/lib/features/auth/data/api/validate_otp_api_service.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:retrofit/retrofit.dart';
3 | import 'package:retrofit/retrofit.dart' as retrofit;
4 | import 'package:store_ify/core/api/end_points.dart';
5 | import 'package:store_ify/features/auth/data/models/validate_otp_params.dart';
6 |
7 | part 'validate_otp_api_service.g.dart';
8 |
9 | @RestApi(baseUrl: EndPoints.baseUrl)
10 | abstract class ValidateOtpApiService {
11 | factory ValidateOtpApiService(Dio dio, {String baseUrl}) =
12 | _ValidateOtpApiService;
13 |
14 | @POST(EndPoints.validateOtp)
15 | @retrofit.Headers({'Accept-Language': 'en'})
16 | Future validateOtp(
17 | @Body() ValidateOtpParams params, [
18 | @CancelRequest() CancelToken? cancelToken,
19 | ]);
20 | }
21 |
--------------------------------------------------------------------------------
/lib/features/auth/data/api/login_api_service.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:retrofit/retrofit.dart' as retrofit;
3 | import 'package:retrofit/retrofit.dart';
4 |
5 | import 'package:store_ify/core/api/end_points.dart';
6 | import 'package:store_ify/core/models/storeify_user.dart';
7 | import 'package:store_ify/features/auth/data/models/login_params.dart';
8 |
9 | part 'login_api_service.g.dart';
10 |
11 | @RestApi(baseUrl: EndPoints.baseUrl)
12 | abstract class LoginApiService {
13 | factory LoginApiService(Dio dio, {String baseUrl}) = _LoginApiService;
14 |
15 | @POST(EndPoints.login)
16 | @retrofit.Headers({'Accept-Language': 'en'})
17 | Future login(
18 | @Body() LoginParams params, [
19 | @CancelRequest() CancelToken? cancelToken,
20 | ]);
21 | }
22 |
--------------------------------------------------------------------------------
/lib/features/cart/presentation/widgets/cart_sliver_shimmer_loading.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_screenutil/flutter_screenutil.dart';
3 | import 'package:store_ify/core/utils/app_constants.dart';
4 | import 'package:store_ify/core/widgets/shimmer_widget.dart';
5 |
6 | class CartSliverShimmerLoading extends StatelessWidget {
7 | const CartSliverShimmerLoading({super.key});
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | return SliverList.builder(
12 | itemCount: 6,
13 | itemBuilder: (_, __) => ShimmerWidget(
14 | margin: AppConstants.cartItemMargin,
15 | constraints: BoxConstraints(
16 | maxHeight: 110.h,
17 | maxWidth: double.infinity,
18 | ),
19 | ),
20 | );
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lib/features/checkout/presentation/widgets/custom_checkout_divider.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_screenutil/flutter_screenutil.dart';
3 | import 'package:store_ify/core/themes/app_colors.dart';
4 |
5 | class CustomCheckoutDivider extends StatelessWidget {
6 | const CustomCheckoutDivider({
7 | super.key,
8 | this.color = AppColors.primaryColor,
9 | });
10 |
11 | final Color color;
12 |
13 | @override
14 | Widget build(BuildContext context) {
15 | return Container(
16 | height: 2.h,
17 | width: 25.87.w,
18 | margin: EdgeInsets.symmetric(horizontal: 4.w),
19 | decoration: BoxDecoration(
20 | borderRadius: BorderRadius.all(Radius.circular(2.16.r)),
21 | color: color,
22 | ),
23 | );
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lib/features/auth/data/api/reset_password_api_service.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:retrofit/retrofit.dart';
3 | import 'package:retrofit/retrofit.dart' as retrofit;
4 | import 'package:store_ify/core/api/end_points.dart';
5 | import 'package:store_ify/features/auth/data/models/reset_password_params.dart';
6 |
7 | part 'reset_password_api_service.g.dart';
8 |
9 | @RestApi(baseUrl: EndPoints.baseUrl)
10 | abstract class ResetPasswordApiService {
11 | factory ResetPasswordApiService(Dio dio, {String baseUrl}) =
12 | _ResetPasswordApiService;
13 |
14 | @POST(EndPoints.resetPassword)
15 | @retrofit.Headers({'Accept-Language': 'en'})
16 | Future resetPassword(
17 | @Body() ResetPasswordParams params, [
18 | @CancelRequest() CancelToken? cancelToken,
19 | ]);
20 | }
21 |
--------------------------------------------------------------------------------
/lib/features/auth/data/repos/validate_otp_repo.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:store_ify/core/api/api_result.dart';
3 | import 'package:store_ify/core/utils/functions/execute_and_handle_errors.dart';
4 | import 'package:store_ify/features/auth/data/api/validate_otp_api_service.dart';
5 | import 'package:store_ify/features/auth/data/models/validate_otp_params.dart';
6 |
7 | class ValidateOtpRepo {
8 | final ValidateOtpApiService _validateOtpApiService;
9 |
10 | ValidateOtpRepo(this._validateOtpApiService);
11 |
12 | Future> validateOtp(
13 | ValidateOtpParams params, [
14 | CancelToken? cancelToken,
15 | ]) {
16 | return executeAndHandleErrors(
17 | () async => await _validateOtpApiService.validateOtp(params, cancelToken),
18 | );
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/android/app/google-services.json:
--------------------------------------------------------------------------------
1 | {
2 | "project_info": {
3 | "project_number": "74739450491",
4 | "project_id": "store-ify-ecommerce",
5 | "storage_bucket": "store-ify-ecommerce.appspot.com"
6 | },
7 | "client": [
8 | {
9 | "client_info": {
10 | "mobilesdk_app_id": "1:74739450491:android:0a91c6343db878cb8e58de",
11 | "android_client_info": {
12 | "package_name": "com.example.store_ify"
13 | }
14 | },
15 | "oauth_client": [],
16 | "api_key": [
17 | {
18 | "current_key": "AIzaSyA1RcgQdie4CIh6UMl1fH1Ze5VFk8uP6jI"
19 | }
20 | ],
21 | "services": {
22 | "appinvite_service": {
23 | "other_platform_oauth_client": []
24 | }
25 | }
26 | }
27 | ],
28 | "configuration_version": "1"
29 | }
--------------------------------------------------------------------------------
/lib/features/auth/data/api/forgot_password_api_service.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:retrofit/retrofit.dart';
3 | import 'package:retrofit/retrofit.dart' as retrofit;
4 | import 'package:store_ify/core/api/end_points.dart';
5 | import 'package:store_ify/features/auth/data/models/forgot_password_params.dart';
6 |
7 | part 'forgot_password_api_service.g.dart';
8 |
9 | @RestApi(baseUrl: EndPoints.baseUrl)
10 | abstract class ForgotPasswordApiService {
11 | factory ForgotPasswordApiService(Dio dio, {String baseUrl}) =
12 | _ForgotPasswordApiService;
13 |
14 | @POST(EndPoints.forgotPassword)
15 | @retrofit.Headers({'Accept-Language': 'en'})
16 | Future forgotPassword(
17 | @Body() ForgotPasswordParams params, [
18 | @CancelRequest() CancelToken? cancelToken,
19 | ]);
20 | }
21 |
--------------------------------------------------------------------------------
/lib/features/auth/data/repos/login_repo.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:store_ify/core/api/api_result.dart';
3 | import 'package:store_ify/core/models/storeify_user.dart';
4 | import 'package:store_ify/core/utils/functions/execute_and_handle_errors.dart';
5 | import 'package:store_ify/features/auth/data/api/login_api_service.dart';
6 | import 'package:store_ify/features/auth/data/models/login_params.dart';
7 |
8 | class LoginRepo {
9 | final LoginApiService _loginApiService;
10 |
11 | LoginRepo(this._loginApiService);
12 |
13 | Future> login(
14 | LoginParams params, [
15 | CancelToken? cancelToken,
16 | ]) {
17 | return executeAndHandleErrors(
18 | () async => await _loginApiService.login(params, cancelToken),
19 | );
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/lib/features/cart/data/models/fetch_cart_response.dart:
--------------------------------------------------------------------------------
1 | import 'package:json_annotation/json_annotation.dart';
2 | import 'package:store_ify/features/cart/data/models/cart.dart';
3 |
4 | part 'fetch_cart_response.g.dart';
5 |
6 | @JsonSerializable(explicitToJson: true)
7 | class FetchCartResponse {
8 | final List cart;
9 | final int totalItems, delivery;
10 | final double totalPrice, subTotalPrice;
11 |
12 | const FetchCartResponse({
13 | required this.cart,
14 | required this.totalItems,
15 | required this.totalPrice,
16 | required this.subTotalPrice,
17 | required this.delivery,
18 | });
19 |
20 | factory FetchCartResponse.fromJson(Map json) =>
21 | _$FetchCartResponseFromJson(json);
22 | Map toJson() => _$FetchCartResponseToJson(this);
23 | }
24 |
--------------------------------------------------------------------------------
/lib/features/categories/presentation/cubit/categories/categories_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 | import 'package:store_ify/features/categories/data/models/fetch_categories_response.dart';
3 |
4 | part 'categories_state.freezed.dart';
5 |
6 | enum CategoriesStateStatus {
7 | initial,
8 | fetchCategoriesLoading,
9 | fetchCategoriesSuccess,
10 | fetchCategoriesError,
11 | }
12 |
13 | @freezed
14 | class CategoriesState with _$CategoriesState {
15 | const factory CategoriesState({
16 | required CategoriesStateStatus status,
17 | FetchCategoriesResponse? categoriesResponse,
18 | String? error,
19 | }) = _CategoriesState;
20 |
21 | factory CategoriesState.initial() => const CategoriesState(
22 | status: CategoriesStateStatus.initial,
23 | );
24 | }
25 |
--------------------------------------------------------------------------------
/lib/features/auth/data/api/register_api_service.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:retrofit/retrofit.dart' as retrofit;
3 | import 'package:retrofit/retrofit.dart';
4 |
5 | import 'package:store_ify/core/api/end_points.dart';
6 | import 'package:store_ify/core/models/storeify_user.dart';
7 | import 'package:store_ify/features/auth/data/models/register_params.dart';
8 |
9 | part 'register_api_service.g.dart';
10 |
11 | @RestApi(baseUrl: EndPoints.baseUrl)
12 | abstract class RegisterApiService {
13 | factory RegisterApiService(Dio dio, {String baseUrl}) = _RegisterApiService;
14 |
15 | @POST(EndPoints.register)
16 | @retrofit.Headers({'Accept-Language': 'en'})
17 | Future register(
18 | @Body() RegisterParams params, [
19 | @CancelRequest() CancelToken? cancelToken,
20 | ]);
21 | }
22 |
--------------------------------------------------------------------------------
/lib/features/auth/presentation/cubits/reset_password/reset_password_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 |
3 | part 'reset_password_state.freezed.dart';
4 |
5 | enum ResetPassStateStatus {
6 | initial,
7 | resetPassLoading,
8 | resetPassSuccess,
9 | resetPassError,
10 | togglePassVisibility,
11 | toggleConfirmPassVisibility,
12 | }
13 |
14 | @freezed
15 | class ResetPasswordState with _$ResetPasswordState {
16 | const factory ResetPasswordState({
17 | required ResetPassStateStatus status,
18 | String? error,
19 | @Default(true) bool isPassObscure,
20 | @Default(true) bool isConfirmPassObscure,
21 | }) = _ResetPasswordState;
22 |
23 | factory ResetPasswordState.initial() => const ResetPasswordState(
24 | status: ResetPassStateStatus.initial,
25 | );
26 | }
27 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | def flutterSdkPath = {
3 | def properties = new Properties()
4 | file("local.properties").withInputStream { properties.load(it) }
5 | def flutterSdkPath = properties.getProperty("flutter.sdk")
6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
7 | return flutterSdkPath
8 | }()
9 |
10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
11 |
12 | repositories {
13 | google()
14 | mavenCentral()
15 | gradlePluginPortal()
16 | }
17 | }
18 |
19 | plugins {
20 | id "dev.flutter.flutter-plugin-loader" version "1.0.0"
21 | id "com.android.application" version "7.3.0" apply false
22 | id "org.jetbrains.kotlin.android" version "1.9.20" apply false
23 | }
24 |
25 | include ":app"
--------------------------------------------------------------------------------
/lib/core/themes/app_colors.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class AppColors {
4 | static const Color primaryColor = Color(0xFFFE431A);
5 | static const Color lightModeColor = Colors.white;
6 | static const Color subTitleColor = Color(0xFF575757);
7 | static const Color blueColor = Color(0xFF0F3557);
8 | static const Color greyColor = Color(0xffD0CFCE);
9 | static const Color discountColor = Color(0xff3E3D3B);
10 | static const Color fontPrimaryColor = Color(0xff0B2841);
11 | static const Color color2A94F4 = Color(0xff2A94F4);
12 | static const Color colorBEBEC3 = Color(0xffBEBEC3);
13 | static const Color colorD9D9D9 = Color(0xffD9D9D9);
14 | static const Color colorF6F6F6 = Color(0xffF6F6F6);
15 | static const Color darkColor = Colors.black;
16 | static Color? secondaryDarkColor = Colors.grey[900];
17 | }
18 |
--------------------------------------------------------------------------------
/lib/features/auth/presentation/widgets/sign_up_text_button.dart:
--------------------------------------------------------------------------------
1 | import 'package:auto_route/auto_route.dart';
2 | import 'package:easy_localization/easy_localization.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:store_ify/core/router/app_router.dart';
5 | import 'package:store_ify/core/themes/app_text_styles.dart';
6 | import 'package:store_ify/generated/locale_keys.g.dart';
7 |
8 | class SignUpTextButton extends StatelessWidget {
9 | const SignUpTextButton({super.key});
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | return TextButton(
14 | style: TextButton.styleFrom(
15 | textStyle: AppTextStyles.textStyle16Regular,
16 | ),
17 | onPressed: () => context.pushRoute(const RegisterRoute()),
18 | child: Text(context.tr(LocaleKeys.signUp)),
19 | );
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/lib/features/home/presentation/widgets/list_title.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_screenutil/flutter_screenutil.dart';
3 | import 'package:easy_localization/easy_localization.dart';
4 | import 'package:store_ify/core/themes/app_text_styles.dart';
5 |
6 | class ListTitle extends StatelessWidget {
7 | const ListTitle({
8 | super.key,
9 | required this.titleKey,
10 | this.bottomPadding = 0,
11 | });
12 |
13 | final String titleKey;
14 | final double bottomPadding;
15 |
16 | @override
17 | Widget build(BuildContext context) {
18 | return Container(
19 | margin: EdgeInsetsDirectional.only(bottom: bottomPadding.h, start: 16.w),
20 | child: Text(
21 | context.tr(titleKey),
22 | style: AppTextStyles.textStyle16Regular,
23 | ),
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/features/favorites/data/models/fetch_favorite_products_response.dart:
--------------------------------------------------------------------------------
1 | import 'package:hive_flutter/hive_flutter.dart';
2 | import 'package:json_annotation/json_annotation.dart';
3 | import 'package:store_ify/core/helpers/hive_type_ids.dart';
4 | import 'package:store_ify/core/models/product.dart';
5 |
6 | part 'fetch_favorite_products_response.g.dart';
7 |
8 | @HiveType(typeId: HiveTypeIds.fetchFavoriteProductsResponse)
9 | @JsonSerializable()
10 | class FetchFavoriteProductsResponse {
11 | @HiveField(0)
12 | final List products;
13 |
14 | const FetchFavoriteProductsResponse({required this.products});
15 |
16 | factory FetchFavoriteProductsResponse.fromJson(Map json) =>
17 | _$FetchFavoriteProductsResponseFromJson(json);
18 | Map toJson() => _$FetchFavoriteProductsResponseToJson(this);
19 | }
20 |
--------------------------------------------------------------------------------
/lib/features/auth/data/repos/register_repo.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:store_ify/core/api/api_result.dart';
3 | import 'package:store_ify/core/models/storeify_user.dart';
4 | import 'package:store_ify/core/utils/functions/execute_and_handle_errors.dart';
5 | import 'package:store_ify/features/auth/data/api/register_api_service.dart';
6 | import 'package:store_ify/features/auth/data/models/register_params.dart';
7 |
8 | class RegisterRepo {
9 | final RegisterApiService _registerApiService;
10 |
11 | RegisterRepo(this._registerApiService);
12 |
13 | Future> register(
14 | RegisterParams params, [
15 | CancelToken? cancelToken,
16 | ]) {
17 | return executeAndHandleErrors(
18 | () async => await _registerApiService.register(params, cancelToken),
19 | );
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/lib/features/layout/presentation/views/layout_view.dart:
--------------------------------------------------------------------------------
1 | import 'package:auto_route/auto_route.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:store_ify/core/router/app_router.dart';
4 | import 'package:store_ify/features/layout/presentation/widgets/custom_bottom_nav_bar.dart';
5 |
6 | @RoutePage()
7 | class LayoutView extends StatelessWidget {
8 | const LayoutView({super.key});
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | return AutoTabsScaffold(
13 | routes: const [
14 | HomeRouteBody(),
15 | StoresRoute(),
16 | CartRoute(),
17 | FavoritesRoute()
18 | ],
19 | bottomNavigationBuilder: (_, tabsRouter) => CustomBottomNavBar(
20 | currentIndex: tabsRouter.activeIndex,
21 | onTap: tabsRouter.setActiveIndex,
22 | ),
23 | );
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lib/core/utils/functions/check_for_first_launch_and_device_theme.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/foundation.dart';
2 | import 'package:store_ify/core/helpers/shared_pref_helper.dart';
3 | import 'package:store_ify/core/helpers/cache_keys.dart';
4 | import 'package:store_ify/core/utils/app_constants.dart';
5 |
6 | Future checkForFirstLaunchAndDeviceTheme() async {
7 | final firstLaunch = await SharedPrefHelper.getBool(CacheKeys.firstLaunch);
8 | if (firstLaunch == null) {
9 | isFirstLaunch = true;
10 | await SharedPrefHelper.setData(CacheKeys.firstLaunch, true);
11 | _checkTheDeviceTheme();
12 | } else {
13 | isFirstLaunch = false;
14 | }
15 | }
16 |
17 | void _checkTheDeviceTheme() {
18 | final brightness = PlatformDispatcher.instance.platformBrightness;
19 | isDeviceDarkModeActive = brightness == Brightness.dark ? true : false;
20 | }
21 |
--------------------------------------------------------------------------------
/lib/core/helpers/hive_boxes.dart:
--------------------------------------------------------------------------------
1 | class HiveBoxes {
2 | HiveBoxes._();
3 |
4 | static const String homeResponseBox = 'homeResponseBox';
5 | static const String categoriesResponseBox = 'categoriesResponseBox';
6 | static const String favProductsBox = 'favProductsBox';
7 | static const String favStoresBox = 'favStoresBox';
8 | static const String fetchStoresBox = 'fetchStoresBox';
9 | static const String fetchCategoryStoresBox = 'fetchCategoryStoresBox';
10 | static const String subCategoryBox = 'fetchSubCategoryBox';
11 | static const String fetchStoreBranchesBox = 'fetchStoreBranchesBox';
12 | static const String fetchStoreCategoriesBox = 'fetchStoreCategoriesBox';
13 | static const String fetchStoreOffersBox = 'fetchStoreOffersBox';
14 | static const String searchDataBox = 'searchDataBox';
15 | static const String paymentBox = 'paymentBox';
16 | }
17 |
--------------------------------------------------------------------------------
/lib/features/auth/data/repos/reset_password_repo.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:store_ify/core/api/api_result.dart';
3 | import 'package:store_ify/core/utils/functions/execute_and_handle_errors.dart';
4 | import 'package:store_ify/features/auth/data/api/reset_password_api_service.dart';
5 | import 'package:store_ify/features/auth/data/models/reset_password_params.dart';
6 |
7 | class ResetPasswordRepo {
8 | final ResetPasswordApiService _resetPasswordApiService;
9 |
10 | ResetPasswordRepo(this._resetPasswordApiService);
11 |
12 | Future> resetPassword(
13 | ResetPasswordParams params, [
14 | CancelToken? cancelToken,
15 | ]) {
16 | return executeAndHandleErrors(
17 | () async => await _resetPasswordApiService.resetPassword(
18 | params,
19 | cancelToken,
20 | ),
21 | );
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lib/features/auth/presentation/cubits/register/register_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 | import 'package:store_ify/core/models/storeify_user.dart';
3 |
4 | part 'register_state.freezed.dart';
5 |
6 | enum RegisterStateStatus {
7 | initial,
8 | registerLoading,
9 | registerSuccess,
10 | registerError,
11 | togglePassVisibility,
12 | toggleConfirmPassVisibility,
13 | }
14 |
15 | @freezed
16 | class RegisterState with _$RegisterState {
17 | const factory RegisterState({
18 | required RegisterStateStatus status,
19 | StoreifyUser? user,
20 | String? error,
21 | @Default(true) bool isPassObscure,
22 | @Default(true) bool isConfirmPassObscure,
23 | }) = _RegisterState;
24 |
25 | factory RegisterState.initial() => const RegisterState(
26 | status: RegisterStateStatus.initial,
27 | );
28 | }
29 |
--------------------------------------------------------------------------------
/lib/features/checkout/data/models/choose_payment_method_params.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'choose_payment_method_params.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | ChoosePaymentMethodParams _$ChoosePaymentMethodParamsFromJson(
10 | Map json) =>
11 | ChoosePaymentMethodParams(
12 | paymentId: (json['paymentId'] as num).toInt(),
13 | paymentMethod: json['payment_method'] as String,
14 | );
15 |
16 | Map _$ChoosePaymentMethodParamsToJson(
17 | ChoosePaymentMethodParams instance) =>
18 | {
19 | 'paymentId': instance.paymentId,
20 | 'payment_method': instance.paymentMethod,
21 | };
22 |
--------------------------------------------------------------------------------
/lib/features/payment/presentation/widgets/payment_progress_circles.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:store_ify/features/checkout/presentation/widgets/check_circle.dart';
3 | import 'package:store_ify/features/checkout/presentation/widgets/custom_checkout_divider.dart';
4 | import 'package:store_ify/features/checkout/presentation/widgets/custom_progress_circle.dart';
5 |
6 | class PaymentProgressCircles extends StatelessWidget {
7 | const PaymentProgressCircles({super.key});
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | return const Row(
12 | mainAxisAlignment: MainAxisAlignment.center,
13 | children: [
14 | CustomProgressCircle(),
15 | CustomCheckoutDivider(),
16 | CustomProgressCircle(),
17 | CustomCheckoutDivider(),
18 | CheckCircle(),
19 | ],
20 | );
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lib/core/widgets/custom_circular_progress_indicator.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_screenutil/flutter_screenutil.dart';
3 | import 'package:store_ify/core/themes/app_colors.dart';
4 |
5 | class CustomCircularProgressIndicator extends StatelessWidget {
6 | const CustomCircularProgressIndicator({
7 | super.key,
8 | this.color = AppColors.primaryColor,
9 | this.strokeWidth = 4,
10 | this.backgroundColor,
11 | });
12 |
13 | final Color color;
14 | final Color? backgroundColor;
15 | final double strokeWidth;
16 |
17 | @override
18 | Widget build(BuildContext context) {
19 | return CircularProgressIndicator.adaptive(
20 | valueColor: AlwaysStoppedAnimation(color),
21 | strokeCap: StrokeCap.butt,
22 | strokeWidth: strokeWidth.w,
23 | backgroundColor: backgroundColor,
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/features/auth/data/repos/forgot_password_repo.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:store_ify/core/api/api_result.dart';
3 | import 'package:store_ify/core/utils/functions/execute_and_handle_errors.dart';
4 | import 'package:store_ify/features/auth/data/api/forgot_password_api_service.dart';
5 | import 'package:store_ify/features/auth/data/models/forgot_password_params.dart';
6 |
7 | class ForgotPasswordRepo {
8 | final ForgotPasswordApiService _forgotPasswordApiService;
9 |
10 | ForgotPasswordRepo(this._forgotPasswordApiService);
11 |
12 | Future> forgotPassword(
13 | ForgotPasswordParams params, [
14 | CancelToken? cancelToken,
15 | ]) {
16 | return executeAndHandleErrors(
17 | () async => await _forgotPasswordApiService.forgotPassword(
18 | params,
19 | cancelToken,
20 | ),
21 | );
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lib/features/stores/data/models/fetch_store_categories_response.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 | import 'package:hive_flutter/hive_flutter.dart';
3 | import 'package:store_ify/core/helpers/hive_type_ids.dart';
4 | import 'package:store_ify/features/categories/data/models/category.dart';
5 |
6 | part 'fetch_store_categories_response.g.dart';
7 |
8 | @HiveType(typeId: HiveTypeIds.fetchStoreCategoriesResponse)
9 | @JsonSerializable(explicitToJson: true)
10 | class FetchStoreCategoriesResponse {
11 | @HiveField(0)
12 | final List categories;
13 |
14 | const FetchStoreCategoriesResponse({required this.categories});
15 |
16 | factory FetchStoreCategoriesResponse.fromJson(Map json) =>
17 | _$FetchStoreCategoriesResponseFromJson(json);
18 | Map toJson() => _$FetchStoreCategoriesResponseToJson(this);
19 | }
20 |
--------------------------------------------------------------------------------
/lib/features/profile/presentation/cubits/profile_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 | import 'package:store_ify/core/utils/app_strings.dart';
3 |
4 | part 'profile_state.freezed.dart';
5 |
6 | enum ProfileStateStatus {
7 | initial,
8 | logoutLoading,
9 | logoutSuccess,
10 | logoutError,
11 | deleteAccountLoading,
12 | deleteAccountSuccess,
13 | deleteAccountError,
14 | changeLocaleLocally,
15 | changeApiLangSuccess,
16 | changeApiLangError,
17 | }
18 |
19 | @freezed
20 | sealed class ProfileState with _$ProfileState {
21 | const factory ProfileState({
22 | required ProfileStateStatus status,
23 | @Default(AppStrings.englishLangCode) String langCode,
24 | String? error,
25 | }) = _ProfileState;
26 |
27 | factory ProfileState.initial() => const ProfileState(
28 | status: ProfileStateStatus.initial,
29 | );
30 | }
31 |
--------------------------------------------------------------------------------
/lib/features/profile/presentation/widgets/profile_settings_title.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_screenutil/flutter_screenutil.dart';
3 | import 'package:easy_localization/easy_localization.dart';
4 | import 'package:store_ify/core/themes/app_colors.dart';
5 | import 'package:store_ify/core/themes/app_text_styles.dart';
6 |
7 | class ProfileSettingsTitle extends StatelessWidget {
8 | const ProfileSettingsTitle({super.key, required this.titleKey});
9 |
10 | final String titleKey;
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | return Container(
15 | margin: EdgeInsetsDirectional.only(bottom: 6.h, start: 22.w),
16 | child: Text(
17 | context.tr(titleKey),
18 | style: AppTextStyles.textStyle16Medium.copyWith(
19 | color: AppColors.primaryColor,
20 | ),
21 | ),
22 | );
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/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 | 11.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/lib/features/auth/data/models/reset_password_params.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'reset_password_params.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | ResetPasswordParams _$ResetPasswordParamsFromJson(Map json) =>
10 | ResetPasswordParams(
11 | email: json['email'] as String,
12 | password: json['password'] as String,
13 | passwordConfirmation: json['password_confirmation'] as String,
14 | );
15 |
16 | Map _$ResetPasswordParamsToJson(
17 | ResetPasswordParams instance) =>
18 | {
19 | 'email': instance.email,
20 | 'password': instance.password,
21 | 'password_confirmation': instance.passwordConfirmation,
22 | };
23 |
--------------------------------------------------------------------------------
/lib/features/categories/data/models/fetch_sub_category_response.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 | import 'package:store_ify/core/models/pagination.dart';
3 | import 'package:store_ify/core/models/product.dart';
4 | import 'package:store_ify/core/models/sub_category.dart';
5 |
6 | part 'fetch_sub_category_response.g.dart';
7 |
8 | @JsonSerializable(explicitToJson: true)
9 | class FetchSubCategoryResponse {
10 | final SubCategory category;
11 | final List products;
12 | final Pagination pagination;
13 |
14 | const FetchSubCategoryResponse({
15 | required this.category,
16 | required this.products,
17 | required this.pagination,
18 | });
19 |
20 | factory FetchSubCategoryResponse.fromJson(Map json) =>
21 | _$FetchSubCategoryResponseFromJson(json);
22 | Map toJson() => _$FetchSubCategoryResponseToJson(this);
23 | }
24 |
--------------------------------------------------------------------------------
/lib/features/payment/data/repositories/payment_repo.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:store_ify/core/api/api_result.dart';
3 | import 'package:store_ify/core/utils/functions/execute_and_handle_errors.dart';
4 | import 'package:store_ify/features/payment/data/api/payment_api_service.dart';
5 | import 'package:store_ify/features/payment/data/models/payment_card_details.dart';
6 |
7 | class PaymentRepo {
8 | final PaymentApiService _paymentApiService;
9 |
10 | const PaymentRepo(this._paymentApiService);
11 |
12 | Future> pay({
13 | required int orderId,
14 | required PaymentCardDetails paymentCardDetails,
15 | CancelToken? cancelToken,
16 | }) {
17 | return executeAndHandleErrors(
18 | () async => await _paymentApiService.orderPay(
19 | orderId,
20 | paymentCardDetails,
21 | cancelToken,
22 | ),
23 | );
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lib/features/profile/presentation/cubits/change_pass/change_pass_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 |
3 | part 'change_pass_state.freezed.dart';
4 |
5 | enum ChangePassStateStatus {
6 | initial,
7 | changePasswordLoading,
8 | changePasswordSuccess,
9 | changePasswordError,
10 | toggleOldPassVisibility,
11 | toggleNewPassVisibility,
12 | toggleConfirmNewPassVisibility,
13 | }
14 |
15 | @freezed
16 | class ChangePassState with _$ChangePassState {
17 | const factory ChangePassState({
18 | required ChangePassStateStatus status,
19 | String? error,
20 | @Default(true) bool oldPasswordObscured,
21 | @Default(true) bool newPasswordObscured,
22 | @Default(true) bool confirmNewPassObscured,
23 | }) = _ChangePassState;
24 |
25 | factory ChangePassState.initial() => const ChangePassState(
26 | status: ChangePassStateStatus.initial,
27 | );
28 | }
29 |
--------------------------------------------------------------------------------
/lib/features/auth/presentation/views/login_view.dart:
--------------------------------------------------------------------------------
1 | import 'package:auto_route/auto_route.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_bloc/flutter_bloc.dart';
4 | import 'package:store_ify/core/di/dependency_injection.dart';
5 | import 'package:store_ify/features/auth/presentation/cubits/login/login_cubit.dart';
6 | import 'package:store_ify/features/auth/presentation/widgets/login/login_view_body.dart';
7 |
8 | @RoutePage()
9 | class LoginView extends StatelessWidget implements AutoRouteWrapper {
10 | const LoginView({super.key});
11 |
12 | @override
13 | Widget wrappedRoute(BuildContext context) {
14 | return BlocProvider(
15 | create: (_) => getIt.get(),
16 | child: this,
17 | );
18 | }
19 |
20 | @override
21 | Widget build(BuildContext context) {
22 | return const Scaffold(
23 | body: LoginViewBody(),
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/features/search/presentation/cubit/search_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 | import 'package:store_ify/features/search/data/models/fetch_search_data_response.dart';
3 | import 'package:store_ify/features/search/data/models/search_response.dart';
4 |
5 | part 'search_state.freezed.dart';
6 |
7 | enum SearchStateStatus {
8 | initial,
9 | searchLoading,
10 | searchSuccess,
11 | searchError,
12 | fetchSearchDataLoading,
13 | fetchSearchDataSuccess,
14 | fetchSearchDataError,
15 | }
16 |
17 | @freezed
18 | class SearchState with _$SearchState {
19 | const factory SearchState({
20 | required SearchStateStatus status,
21 | SearchResponse? searchResult,
22 | FetchSearchDataResponse? searchData,
23 | String? error,
24 | }) = _SearchState;
25 |
26 | factory SearchState.initial() => const SearchState(
27 | status: SearchStateStatus.initial,
28 | );
29 | }
30 |
--------------------------------------------------------------------------------
/lib/features/stores/data/models/fetch_stores_response.dart:
--------------------------------------------------------------------------------
1 | import 'package:hive_flutter/hive_flutter.dart';
2 | import 'package:json_annotation/json_annotation.dart';
3 | import 'package:store_ify/core/helpers/hive_type_ids.dart';
4 | import 'package:store_ify/core/models/pagination.dart';
5 | import 'package:store_ify/core/models/store.dart';
6 |
7 | part 'fetch_stores_response.g.dart';
8 |
9 | @HiveType(typeId: HiveTypeIds.fetchStores)
10 | @JsonSerializable(explicitToJson: true)
11 | class FetchStoresResponse {
12 | @HiveField(0)
13 | final List stores;
14 | @HiveField(1)
15 | final Pagination pagination;
16 |
17 | const FetchStoresResponse({
18 | required this.stores,
19 | required this.pagination,
20 | });
21 |
22 | factory FetchStoresResponse.fromJson(Map json) =>
23 | _$FetchStoresResponseFromJson(json);
24 | Map toJson() => _$FetchStoresResponseToJson(this);
25 | }
26 |
--------------------------------------------------------------------------------
/lib/core/widgets/stores_grid_view_shimmer.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_screenutil/flutter_screenutil.dart';
3 | import 'package:store_ify/core/utils/app_constants.dart';
4 | import 'package:store_ify/core/widgets/shimmer_widget.dart';
5 |
6 | class StoresGridViewShimmer extends StatelessWidget {
7 | const StoresGridViewShimmer({super.key});
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | return GridView.builder(
12 | itemCount: 10,
13 | padding: AppConstants.categoryPadding,
14 | physics: AppConstants.physics,
15 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
16 | crossAxisCount: AppConstants.gridCrossAxisCount,
17 | crossAxisSpacing: 8.w,
18 | mainAxisSpacing: 16.h,
19 | childAspectRatio: AppConstants.storeItemAspectRatio,
20 | ),
21 | itemBuilder: (_, __) => const ShimmerWidget(),
22 | );
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/lib/features/auth/data/models/register_params.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'register_params.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | RegisterParams _$RegisterParamsFromJson(Map json) =>
10 | RegisterParams(
11 | username: json['username'] as String,
12 | email: json['email'] as String,
13 | password: json['password'] as String,
14 | passwordConfirmation: json['password_confirmation'] as String,
15 | );
16 |
17 | Map _$RegisterParamsToJson(RegisterParams instance) =>
18 | {
19 | 'username': instance.username,
20 | 'email': instance.email,
21 | 'password': instance.password,
22 | 'password_confirmation': instance.passwordConfirmation,
23 | };
24 |
--------------------------------------------------------------------------------
/lib/features/auth/presentation/views/register_view.dart:
--------------------------------------------------------------------------------
1 | import 'package:auto_route/auto_route.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_bloc/flutter_bloc.dart';
4 | import 'package:store_ify/core/di/dependency_injection.dart';
5 | import 'package:store_ify/features/auth/presentation/cubits/register/register_cubit.dart';
6 | import 'package:store_ify/features/auth/presentation/widgets/register/register_view_body.dart';
7 |
8 | @RoutePage()
9 | class RegisterView extends StatelessWidget implements AutoRouteWrapper {
10 | const RegisterView({super.key});
11 |
12 | @override
13 | Widget wrappedRoute(BuildContext context) {
14 | return BlocProvider(
15 | create: (_) => getIt.get(),
16 | child: this,
17 | );
18 | }
19 |
20 | @override
21 | Widget build(BuildContext context) {
22 | return const Scaffold(
23 | body: RegisterViewBody(),
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/features/search/data/models/search_response.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'search_response.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | SearchResponse _$SearchResponseFromJson(Map json) =>
10 | SearchResponse(
11 | products: (json['products'] as List)
12 | .map((e) => Product.fromJson(e as Map))
13 | .toList(),
14 | pagination: json['pagination'] == null
15 | ? null
16 | : Pagination.fromJson(json['pagination'] as Map),
17 | );
18 |
19 | Map _$SearchResponseToJson(SearchResponse instance) =>
20 | {
21 | 'products': instance.products,
22 | 'pagination': instance.pagination,
23 | };
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 | migrate_working_dir/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # The .vscode folder contains launch configuration and tasks you configure in
20 | # VS Code which you may wish to be included in version control, so this line
21 | # is commented out by default.
22 | #.vscode/
23 |
24 | # Flutter/Dart/Pub related
25 | **/doc/api/
26 | **/ios/Flutter/.last_build_id
27 | .dart_tool/
28 | .flutter-plugins
29 | .flutter-plugins-dependencies
30 | .packages
31 | .pub-cache/
32 | .pub/
33 | /build/
34 |
35 | # Symbolication related
36 | app.*.symbols
37 |
38 | # Obfuscation related
39 | app.*.map.json
40 |
41 | # Android Studio will place build artifacts here
42 | /android/app/debug
43 | /android/app/profile
44 | /android/app/release
45 |
46 |
47 | .vscode
48 | macos
49 | windows
50 | linux
51 | web
--------------------------------------------------------------------------------
/lib/core/helpers/hive_keys.dart:
--------------------------------------------------------------------------------
1 | class HiveKeys {
2 | HiveKeys._();
3 |
4 | static const String homeResponse = 'homeResponse';
5 | static const String cartResponse = 'cartResponse';
6 | static const String categoriesResponse = 'categoriesResponse';
7 | static const String favProductsResponse = 'favProductsResponse';
8 | static const String favStoresResponse = 'favStoresResponse';
9 | static const String fetchedStoresResponse = 'fetchedStoresResponse';
10 | static const String fetchedCategoryStoresResponse =
11 | 'fetchedCategoryStoresResponse';
12 | static const String fetchedStoreBranchesResponse =
13 | 'fetchedStoreBranchesResponse';
14 | static const String fetchedStoreCategoriesResponse =
15 | 'fetchedStoreCategoriesResponse';
16 | static const String fetchedStoreOffersResponse = 'fetchedStoreOffersResponse';
17 | static const String searchData = 'searchData';
18 | static const String cardDetails = 'cardDetails';
19 | }
20 |
--------------------------------------------------------------------------------
/lib/features/stores/presentation/cubits/stores/stores_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 | import 'package:store_ify/features/stores/data/models/fetch_stores_response.dart';
3 |
4 | part 'stores_state.freezed.dart';
5 |
6 | enum StoresStateStatus {
7 | initial,
8 | fetchStoresLoading,
9 | fetchStoresSuccess,
10 | fetchStoresError,
11 | fetchCategoryStoresLoading,
12 | fetchCategoryStoresSuccess,
13 | fetchCategoryStoresError,
14 | updateCurrentSelectedStore
15 | }
16 |
17 | @freezed
18 | class StoresState with _$StoresState {
19 | const factory StoresState({
20 | required StoresStateStatus status,
21 | FetchStoresResponse? stores,
22 | FetchStoresResponse? categoryStores,
23 | String? error,
24 | @Default(0) int currentStoreIndex,
25 | }) = _StoresState;
26 |
27 | factory StoresState.initial() => const StoresState(
28 | status: StoresStateStatus.initial,
29 | );
30 | }
31 |
--------------------------------------------------------------------------------
/lib/core/helpers/app_regex.dart:
--------------------------------------------------------------------------------
1 | class AppRegex {
2 | static bool isEmailValid(String email) {
3 | return RegExp(r'^.+@[a-zA-Z]+\.{1}[a-zA-Z]+(\.{0,1}[a-zA-Z]+)$')
4 | .hasMatch(email);
5 | }
6 |
7 | static bool passwordHasSpecialCharacter(String password) {
8 | return RegExp(r"[@$#!%*?&]").hasMatch(password);
9 | }
10 |
11 | static bool passwordHasCapitalCharacter(String password) {
12 | return RegExp(r"[A-Z]").hasMatch(password);
13 | }
14 |
15 | static bool passwordHasLowercaseCharacter(String password) {
16 | return RegExp(r"[a-z]").hasMatch(password);
17 | }
18 |
19 | static bool passwordHasNumber(String password) {
20 | return RegExp(r"\d").hasMatch(password);
21 | }
22 |
23 | static bool containsOnlyDigits(String val) {
24 | return RegExp(r'^[0-9]+$').hasMatch(val);
25 | }
26 |
27 | static bool containsAlphabeticAndSpaces(String val) {
28 | return RegExp(r'^[a-zA-Z\s]+$').hasMatch(val);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/lib/features/checkout/data/models/checkout_params.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'checkout_params.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | CheckoutParams _$CheckoutParamsFromJson(Map json) =>
10 | CheckoutParams(
11 | username: json['username'] as String,
12 | address: json['address'] as String,
13 | phone: json['phone'] as String,
14 | date: json['date'] as String,
15 | time: json['time'] as String,
16 | );
17 |
18 | Map _$CheckoutParamsToJson(CheckoutParams instance) =>
19 | {
20 | 'username': instance.username,
21 | 'address': instance.address,
22 | 'phone': instance.phone,
23 | 'date': instance.date,
24 | 'time': instance.time,
25 | };
26 |
--------------------------------------------------------------------------------
/lib/features/payment/presentation/widgets/card_details_text.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_screenutil/flutter_screenutil.dart';
3 | import 'package:easy_localization/easy_localization.dart';
4 | import 'package:store_ify/generated/locale_keys.g.dart';
5 | import 'package:store_ify/core/themes/app_colors.dart';
6 | import 'package:store_ify/core/themes/app_text_styles.dart';
7 |
8 | class CardDetailsText extends StatelessWidget {
9 | const CardDetailsText({super.key});
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | return Container(
14 | margin: EdgeInsetsDirectional.only(
15 | start: 14.w,
16 | top: 29.h,
17 | bottom: 27.h,
18 | ),
19 | child: Text(
20 | context.tr(LocaleKeys.cardDetails),
21 | style: AppTextStyles.textStyle20Medium.copyWith(
22 | color: AppColors.primaryColor,
23 | ),
24 | ),
25 | );
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/lib/features/search/data/api/search_api_service.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:retrofit/retrofit.dart';
3 | import 'package:store_ify/core/api/end_points.dart';
4 | import 'package:store_ify/features/search/data/models/fetch_search_data_response.dart';
5 | import 'package:store_ify/features/search/data/models/search_params.dart';
6 | import 'package:store_ify/features/search/data/models/search_response.dart';
7 |
8 | part 'search_api_service.g.dart';
9 |
10 | @RestApi(baseUrl: EndPoints.baseUrl)
11 | abstract class SearchApiService {
12 | factory SearchApiService(Dio dio, {String baseUrl}) = _SearchApiService;
13 |
14 | @POST(EndPoints.search)
15 | Future search(
16 | @Body() SearchParams params, [
17 | @CancelRequest() CancelToken? cancelToken,
18 | ]);
19 |
20 | @GET(EndPoints.searchData)
21 | Future fetchSearchData([
22 | @CancelRequest() CancelToken? cancelToken,
23 | ]);
24 | }
25 |
--------------------------------------------------------------------------------
/lib/features/stores/presentation/widgets/categories_grid_view_shimmer.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_screenutil/flutter_screenutil.dart';
3 | import 'package:store_ify/core/utils/app_constants.dart';
4 | import 'package:store_ify/core/widgets/shimmer_widget.dart';
5 |
6 | class CategoriesGridViewShimmer extends StatelessWidget {
7 | const CategoriesGridViewShimmer({super.key});
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | return GridView.builder(
12 | itemCount: 10,
13 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
14 | crossAxisCount: AppConstants.gridCrossAxisCount,
15 | crossAxisSpacing: AppConstants.gridCrossAxisSpacing,
16 | mainAxisSpacing: AppConstants.gridMainAxisSpacing,
17 | ),
18 | itemBuilder: (_, __) => ShimmerWidget(
19 | constraints: BoxConstraints(maxHeight: 165.h, maxWidth: 170.w),
20 | ),
21 | );
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lib/features/categories/presentation/cubit/sub_category/sub_category_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 | import 'package:store_ify/core/models/sub_category.dart';
3 | import 'package:store_ify/features/categories/data/models/fetch_sub_category_response.dart';
4 |
5 | part 'sub_category_state.freezed.dart';
6 |
7 | enum SubCategoryStateStatus {
8 | initial,
9 | fetchSubCategoryLoading,
10 | fetchSubCategorySuccess,
11 | fetchSubCategoryError,
12 | updateSelectedSubCategory,
13 | }
14 |
15 | @freezed
16 | class SubCategoryState with _$SubCategoryState {
17 | const factory SubCategoryState({
18 | required SubCategoryStateStatus status,
19 | FetchSubCategoryResponse? subCategoryResponse,
20 | String? error,
21 | SubCategory? selectedSubCategory,
22 | }) = _SubCategoryState;
23 |
24 | factory SubCategoryState.initial() => const SubCategoryState(
25 | status: SubCategoryStateStatus.initial,
26 | );
27 | }
28 |
--------------------------------------------------------------------------------
/lib/features/profile/data/models/change_password_params.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'change_password_params.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | ChangePasswordParams _$ChangePasswordParamsFromJson(
10 | Map json) =>
11 | ChangePasswordParams(
12 | currentPassword: json['current_password'] as String,
13 | password: json['password'] as String,
14 | passwordConfirmation: json['password_confirmation'] as String,
15 | );
16 |
17 | Map _$ChangePasswordParamsToJson(
18 | ChangePasswordParams instance) =>
19 | {
20 | 'current_password': instance.currentPassword,
21 | 'password': instance.password,
22 | 'password_confirmation': instance.passwordConfirmation,
23 | };
24 |
--------------------------------------------------------------------------------
/lib/features/cart/presentation/cubit/cart_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 | import 'package:store_ify/features/cart/data/models/fetch_cart_response.dart';
3 |
4 | part 'cart_state.freezed.dart';
5 |
6 | enum CartStateStatus {
7 | initial,
8 | addProductToCartLoading,
9 | addProductToCartSuccess,
10 | addProductToCartError,
11 | fetchCartLoading,
12 | fetchCartSuccess,
13 | fetchCartError,
14 | removeProductFromCartLoading,
15 | removeProductFromCartSuccess,
16 | removeProductFromCartError,
17 | increaseProductQuantity,
18 | decreaseProductQuantity,
19 | }
20 |
21 | @freezed
22 | class CartState with _$CartState {
23 | const factory CartState({
24 | required CartStateStatus status,
25 | String? error,
26 | FetchCartResponse? cart,
27 | @Default(1) int productQuantity,
28 | }) = _CartState;
29 |
30 | factory CartState.initial() => const CartState(
31 | status: CartStateStatus.initial,
32 | );
33 | }
34 |
--------------------------------------------------------------------------------
/lib/features/stores/data/models/fetch_store_offers_response.dart:
--------------------------------------------------------------------------------
1 | import 'package:hive_flutter/hive_flutter.dart';
2 | import 'package:json_annotation/json_annotation.dart';
3 | import 'package:store_ify/core/helpers/hive_type_ids.dart';
4 | import 'package:store_ify/core/models/pagination.dart';
5 | import 'package:store_ify/core/models/product.dart';
6 |
7 | part 'fetch_store_offers_response.g.dart';
8 |
9 | @HiveType(typeId: HiveTypeIds.fetchStoreOffersResponse)
10 | @JsonSerializable(explicitToJson: true)
11 | class FetchStoreOffersResponse {
12 | @HiveField(0)
13 | final List products;
14 | @HiveField(1)
15 | final Pagination pagination;
16 |
17 | const FetchStoreOffersResponse({
18 | required this.products,
19 | required this.pagination,
20 | });
21 |
22 | factory FetchStoreOffersResponse.fromJson(Map json) =>
23 | _$FetchStoreOffersResponseFromJson(json);
24 | Map toJson() => _$FetchStoreOffersResponseToJson(this);
25 | }
26 |
--------------------------------------------------------------------------------
/lib/features/checkout/presentation/widgets/custom_progress_circle.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_screenutil/flutter_screenutil.dart';
3 | import 'package:store_ify/core/themes/app_colors.dart';
4 |
5 | class CustomProgressCircle extends StatelessWidget {
6 | const CustomProgressCircle({
7 | super.key,
8 | this.isColoredPrimary = true,
9 | });
10 |
11 | final bool isColoredPrimary;
12 |
13 | @override
14 | Widget build(BuildContext context) {
15 | return Container(
16 | height: 25.87.h,
17 | width: 25.87.h,
18 | decoration: BoxDecoration(
19 | shape: BoxShape.circle,
20 | color:
21 | isColoredPrimary ? AppColors.primaryColor : AppColors.colorD9D9D9,
22 | border: Border.all(
23 | color:
24 | isColoredPrimary ? AppColors.primaryColor : AppColors.colorD9D9D9,
25 | width: isColoredPrimary ? 0 : 1.08.w,
26 | ),
27 | ),
28 | );
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/lib/features/checkout/presentation/widgets/payment_method_process_progress.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:store_ify/features/checkout/presentation/widgets/check_circle.dart';
3 | import 'package:store_ify/features/checkout/presentation/widgets/container_contains_dot.dart';
4 | import 'package:store_ify/features/checkout/presentation/widgets/custom_checkout_divider.dart';
5 | import 'package:store_ify/features/checkout/presentation/widgets/custom_progress_circle.dart';
6 |
7 | class PaymentMethodProcessProgress extends StatelessWidget {
8 | const PaymentMethodProcessProgress({super.key});
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | return const Row(
13 | mainAxisAlignment: MainAxisAlignment.center,
14 | children: [
15 | CustomProgressCircle(),
16 | CustomCheckoutDivider(),
17 | CheckCircle(),
18 | CustomCheckoutDivider(),
19 | ContainerContainsDot(),
20 | ],
21 | );
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lib/features/checkout/presentation/cubits/payment_method/payment_method_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 | import 'package:store_ify/core/utils/app_constants.dart';
3 | import 'package:store_ify/features/checkout/data/models/payment_method.dart';
4 |
5 | part 'payment_method_state.freezed.dart';
6 |
7 | enum PaymentMethodStateStatus {
8 | initial,
9 | selectingPaymentMethod,
10 | choosePaymentMethodLoading,
11 | choosePaymentMethodSuccess,
12 | choosePaymentMethodError,
13 | }
14 |
15 | @freezed
16 | class PaymentMethodState with _$PaymentMethodState {
17 | const factory PaymentMethodState({
18 | required PaymentMethodStateStatus status,
19 | PaymentMethod? selectedPaymentMethod,
20 | String? error,
21 | }) = _PaymentMethodState;
22 |
23 | factory PaymentMethodState.initial() => PaymentMethodState(
24 | status: PaymentMethodStateStatus.initial,
25 | selectedPaymentMethod: AppConstants.paymentMethods[0],
26 | );
27 | }
28 |
--------------------------------------------------------------------------------
/lib/features/categories/presentation/widgets/empty_sub_category_view.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:store_ify/core/widgets/custom_sliver_app_bar.dart';
3 | import 'package:store_ify/core/widgets/empty_widget.dart';
4 | import 'package:store_ify/generated/locale_keys.g.dart';
5 |
6 | class EmptySubCategoryView extends StatelessWidget {
7 | const EmptySubCategoryView({
8 | super.key,
9 | required this.appBarTitleText,
10 | });
11 |
12 | final String appBarTitleText;
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | return CustomScrollView(
17 | slivers: [
18 | CustomSliverAppBar(titleText: appBarTitleText),
19 | const SliverFillRemaining(
20 | hasScrollBody: false,
21 | child: EmptyWidget(
22 | titleKey: LocaleKeys.emptySubCategories,
23 | descriptionKey: LocaleKeys.emptySubCategoriesDescription,
24 | ),
25 | ),
26 | ],
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lib/features/profile/presentation/cubits/update_profile/update_profile_state.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:freezed_annotation/freezed_annotation.dart';
4 | import 'package:store_ify/core/models/storeify_user.dart';
5 |
6 | part 'update_profile_state.freezed.dart';
7 |
8 | enum UpdateProfileStateStatus {
9 | initial,
10 | updateProfileLoading,
11 | updateProfileSuccess,
12 | updateProfileError,
13 | updateSelectedImg,
14 | onChangeEmail,
15 | onChangeUsername,
16 | }
17 |
18 | @freezed
19 | class UpdateProfileState with _$UpdateProfileState {
20 | const factory UpdateProfileState({
21 | required UpdateProfileStateStatus status,
22 | StoreifyUser? updatedUser,
23 | File? selectedImg,
24 | String? error,
25 | @Default('') String email,
26 | @Default('') String username,
27 | }) = _UpdateProfileState;
28 |
29 | factory UpdateProfileState.initial() => const UpdateProfileState(
30 | status: UpdateProfileStateStatus.initial,
31 | );
32 | }
33 |
--------------------------------------------------------------------------------
/lib/features/profile/presentation/widgets/dark_mode_switch_bloc_selector.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_bloc/flutter_bloc.dart';
3 | import 'package:store_ify/core/helpers/extensions.dart';
4 | import 'package:store_ify/core/widgets/custom_adaptive_switch.dart';
5 | import 'package:store_ify/features/favorites/presentation/cubits/favorites/general_cubit.dart';
6 | import 'package:store_ify/features/favorites/presentation/cubits/favorites/general_state.dart';
7 |
8 | class DarkModeSwitchBlocSelector extends StatelessWidget {
9 | const DarkModeSwitchBlocSelector({super.key});
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | return BlocSelector(
14 | selector: (state) => state.theme!,
15 | builder: (context, state) => CustomAdaptiveSwitch(
16 | value: context.isDarkModeActive,
17 | onChanged: (_) => context.read().toggleTheme(),
18 | ),
19 | );
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/lib/core/utils/bloc_observer.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/foundation.dart';
2 | import 'package:flutter_bloc/flutter_bloc.dart';
3 |
4 | class MyBlocObserver extends BlocObserver {
5 | @override
6 | void onCreate(BlocBase bloc) {
7 | super.onCreate(bloc);
8 | if (kDebugMode) {
9 | print('onCreate -- ${bloc.runtimeType}');
10 | }
11 | }
12 |
13 | @override
14 | void onChange(BlocBase bloc, Change change) {
15 | super.onChange(bloc, change);
16 | if (kDebugMode) {
17 | print('onChange -- ${bloc.runtimeType}, $change');
18 | }
19 | }
20 |
21 | @override
22 | void onError(BlocBase bloc, Object error, StackTrace stackTrace) {
23 | if (kDebugMode) {
24 | print('onError -- ${bloc.runtimeType}, $error');
25 | }
26 | super.onError(bloc, error, stackTrace);
27 | }
28 |
29 | @override
30 | void onClose(BlocBase bloc) {
31 | super.onClose(bloc);
32 | if (kDebugMode) {
33 | print('onClose -- ${bloc.runtimeType}');
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/lib/features/categories/data/models/fetch_categories_response.dart:
--------------------------------------------------------------------------------
1 | import 'package:hive_flutter/hive_flutter.dart';
2 | import 'package:json_annotation/json_annotation.dart';
3 | import 'package:store_ify/core/helpers/hive_type_ids.dart';
4 | import 'package:store_ify/core/models/pagination.dart';
5 | import 'package:store_ify/features/categories/data/models/category.dart';
6 |
7 | part 'fetch_categories_response.g.dart';
8 |
9 | @HiveType(typeId: HiveTypeIds.fetchCategoriesResponse)
10 | @JsonSerializable(explicitToJson: true)
11 | class FetchCategoriesResponse {
12 | @HiveField(0)
13 | final List categories;
14 | @HiveField(1)
15 | final Pagination pagination;
16 |
17 | const FetchCategoriesResponse({
18 | required this.categories,
19 | required this.pagination,
20 | });
21 |
22 | factory FetchCategoriesResponse.fromJson(Map json) =>
23 | _$FetchCategoriesResponseFromJson(json);
24 | Map toJson() => _$FetchCategoriesResponseToJson(this);
25 | }
26 |
--------------------------------------------------------------------------------
/lib/features/checkout/presentation/widgets/container_contains_dot.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_screenutil/flutter_screenutil.dart';
3 | import 'package:store_ify/core/helpers/extensions.dart';
4 | import 'package:store_ify/core/themes/app_colors.dart';
5 |
6 | class ContainerContainsDot extends StatelessWidget {
7 | const ContainerContainsDot({super.key});
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | return Container(
12 | padding: EdgeInsets.all(6.47.h),
13 | decoration: BoxDecoration(
14 | shape: BoxShape.circle,
15 | color: context.isDarkModeActive
16 | ? Colors.transparent
17 | : AppColors.lightModeColor,
18 | border: Border.all(
19 | color: AppColors.colorD9D9D9,
20 | width: 1.08.w,
21 | ),
22 | ),
23 | child: CircleAvatar(
24 | radius: 6.5.r,
25 | backgroundColor: AppColors.primaryColor,
26 | ),
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/ios/Runner/GoogleService-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | API_KEY
6 | AIzaSyCRb8UgDVHf6MMQUx9PCzjOyYV88u88fIU
7 | GCM_SENDER_ID
8 | 74739450491
9 | PLIST_VERSION
10 | 1
11 | BUNDLE_ID
12 | com.example.storeIfy
13 | PROJECT_ID
14 | store-ify-ecommerce
15 | STORAGE_BUCKET
16 | store-ify-ecommerce.appspot.com
17 | IS_ADS_ENABLED
18 |
19 | IS_ANALYTICS_ENABLED
20 |
21 | IS_APPINVITE_ENABLED
22 |
23 | IS_GCM_ENABLED
24 |
25 | IS_SIGNIN_ENABLED
26 |
27 | GOOGLE_APP_ID
28 | 1:74739450491:ios:bd1f70b20eb2a84e8e58de
29 |
30 |
--------------------------------------------------------------------------------
/lib/features/cart/data/models/add_product_to_cart_params.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'add_product_to_cart_params.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | AddProductToCartParams _$AddProductToCartParamsFromJson(
10 | Map json) =>
11 | AddProductToCartParams(
12 | productId: (json['productId'] as num).toInt(),
13 | quantity: (json['quantity'] as num).toInt(),
14 | sizeId: (json['size_id'] as num?)?.toInt(),
15 | colorId: (json['color_id'] as num?)?.toInt(),
16 | );
17 |
18 | Map _$AddProductToCartParamsToJson(
19 | AddProductToCartParams instance) =>
20 | {
21 | 'productId': instance.productId,
22 | 'color_id': instance.colorId,
23 | 'size_id': instance.sizeId,
24 | 'quantity': instance.quantity,
25 | };
26 |
--------------------------------------------------------------------------------
/lib/features/cart/data/models/cart.dart:
--------------------------------------------------------------------------------
1 | import 'package:json_annotation/json_annotation.dart';
2 | import 'package:store_ify/core/models/product_color.dart';
3 | import 'package:store_ify/core/models/product.dart';
4 | import 'package:store_ify/core/models/product_size.dart';
5 |
6 | part 'cart.g.dart';
7 |
8 | @JsonSerializable(explicitToJson: true)
9 | class Cart {
10 | final int id;
11 | final int quantity;
12 | final double price;
13 | final double total;
14 | @JsonKey(name: 'cart_id')
15 | final int cartId;
16 | final Product product;
17 | final ProductColor color;
18 | final ProductSize size;
19 |
20 | const Cart({
21 | required this.id,
22 | required this.quantity,
23 | required this.cartId,
24 | required this.product,
25 | required this.price,
26 | required this.total,
27 | required this.color,
28 | required this.size,
29 | });
30 |
31 | factory Cart.fromJson(Map json) => _$CartFromJson(json);
32 | Map toJson() => _$CartToJson(this);
33 | }
34 |
--------------------------------------------------------------------------------
/lib/features/cart/presentation/widgets/cart_loading_view.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:store_ify/core/utils/app_constants.dart';
3 | import 'package:store_ify/core/widgets/custom_sliver_app_bar.dart';
4 | import 'package:store_ify/core/widgets/shimmer_widget.dart';
5 | import 'package:store_ify/generated/locale_keys.g.dart';
6 |
7 | class CartLoadingView extends StatelessWidget {
8 | const CartLoadingView({super.key});
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | return CustomScrollView(
13 | slivers: [
14 | const CustomSliverAppBar(
15 | titleKey: LocaleKeys.cart,
16 | hasLeading: false,
17 | ),
18 | SliverList.builder(
19 | itemCount: 8,
20 | itemBuilder: (_, index) => AspectRatio(
21 | aspectRatio: 367 / 109,
22 | child: ShimmerWidget(
23 | margin: AppConstants.cartItemMargin,
24 | ),
25 | ),
26 | ),
27 | ],
28 | );
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/lib/features/cart/presentation/widgets/empty_cart_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:store_ify/core/utils/app_assets.dart';
3 | import 'package:store_ify/core/widgets/custom_sliver_app_bar.dart';
4 | import 'package:store_ify/core/widgets/empty_widget.dart';
5 | import 'package:store_ify/generated/locale_keys.g.dart';
6 |
7 | class EmptyCartWidget extends StatelessWidget {
8 | const EmptyCartWidget({super.key});
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | return const CustomScrollView(
13 | slivers: [
14 | CustomSliverAppBar(
15 | titleKey: LocaleKeys.cart,
16 | hasLeading: false,
17 | ),
18 | SliverFillRemaining(
19 | hasScrollBody: false,
20 | child: EmptyWidget(
21 | imagePath: AppAssets.imagesEmptyCart,
22 | titleKey: LocaleKeys.putToYourCart,
23 | descriptionKey: LocaleKeys.putToYourCartToStartShopping),
24 | ),
25 | ],
26 | );
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/lib/features/payment/presentation/widgets/check_box_bloc_selector.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_bloc/flutter_bloc.dart';
3 | import 'package:flutter_screenutil/flutter_screenutil.dart';
4 | import 'package:store_ify/features/payment/presentation/cubits/payment_cubit.dart';
5 | import 'package:store_ify/features/payment/presentation/cubits/payment_state.dart';
6 |
7 | class CheckboxBlocSelector extends StatelessWidget {
8 | const CheckboxBlocSelector({super.key});
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | return BlocSelector(
13 | selector: (state) => state.checkboxValue,
14 | builder: (context, checkboxValue) => Checkbox.adaptive(
15 | value: checkboxValue,
16 | onChanged: (value) =>
17 | context.read().toggleCheckBox(value),
18 | shape: RoundedRectangleBorder(
19 | borderRadius: BorderRadius.circular(4.r),
20 | ),
21 | ),
22 | );
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/lib/features/auth/presentation/views/verification_view.dart:
--------------------------------------------------------------------------------
1 | import 'package:auto_route/auto_route.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_bloc/flutter_bloc.dart';
4 | import 'package:store_ify/core/di/dependency_injection.dart';
5 | import 'package:store_ify/features/auth/presentation/cubits/validate_otp/validate_otp_cubit.dart';
6 | import 'package:store_ify/features/auth/presentation/widgets/verification/verification_view_body.dart';
7 |
8 | @RoutePage()
9 | class VerificationView extends StatelessWidget implements AutoRouteWrapper {
10 | const VerificationView({super.key, required this.email});
11 |
12 | final String email;
13 |
14 | @override
15 | Widget wrappedRoute(BuildContext context) {
16 | return BlocProvider(
17 | create: (_) => getIt.get(),
18 | child: this,
19 | );
20 | }
21 |
22 | @override
23 | Widget build(BuildContext context) {
24 | return Scaffold(
25 | body: VerificationViewBody(email: email),
26 | );
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/lib/features/auth/presentation/widgets/text_field_label.dart:
--------------------------------------------------------------------------------
1 | import 'package:easy_localization/easy_localization.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_screenutil/flutter_screenutil.dart';
4 | import 'package:store_ify/core/themes/app_colors.dart';
5 | import 'package:store_ify/core/themes/app_text_styles.dart';
6 |
7 | class TextFieldLabel extends StatelessWidget {
8 | const TextFieldLabel({
9 | super.key,
10 | required this.labelKey,
11 | this.textStyle,
12 | this.margin,
13 | });
14 |
15 | final String labelKey;
16 | final TextStyle? textStyle;
17 | final EdgeInsetsGeometry? margin;
18 |
19 | @override
20 | Widget build(BuildContext context) {
21 | return Container(
22 | margin: margin ?? EdgeInsetsDirectional.only(bottom: 9.h, start: 9.w),
23 | child: Text(
24 | context.tr(labelKey),
25 | style: textStyle ??
26 | AppTextStyles.textStyle16Regular
27 | .copyWith(color: AppColors.primaryColor),
28 | ),
29 | );
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/lib/features/categories/data/api/categories_api_service.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:retrofit/retrofit.dart';
3 | import 'package:store_ify/core/api/end_points.dart';
4 | import 'package:store_ify/features/categories/data/models/fetch_categories_response.dart';
5 | import 'package:store_ify/features/categories/data/models/fetch_sub_category_response.dart';
6 |
7 | part 'categories_api_service.g.dart';
8 |
9 | @RestApi(baseUrl: EndPoints.baseUrl)
10 | abstract class CategoriesApiService {
11 | factory CategoriesApiService(Dio dio, {String baseUrl}) =
12 | _CategoriesApiService;
13 |
14 | @GET(EndPoints.fetchCategories)
15 | Future fetchCategories([
16 | @CancelRequest() CancelToken? cancelToken,
17 | ]);
18 |
19 | @GET('${EndPoints.fetchCategories}/{category_id}/{sub_category_id}')
20 | Future fetchSubCategory(
21 | @Path('category_id') int categoryId,
22 | @Path('sub_category_id') int subCategoryId, [
23 | @CancelRequest() CancelToken? cancelToken,
24 | ]);
25 | }
26 |
--------------------------------------------------------------------------------
/lib/features/profile/presentation/widgets/profile_view_sliver_app_bar.dart:
--------------------------------------------------------------------------------
1 | import 'package:auto_route/auto_route.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:store_ify/generated/locale_keys.g.dart';
4 | import 'package:store_ify/core/router/app_router.dart';
5 | import 'package:store_ify/core/themes/app_colors.dart';
6 | import 'package:store_ify/core/utils/app_constants.dart';
7 | import 'package:store_ify/core/widgets/custom_sliver_app_bar.dart';
8 |
9 | class ProfileViewSliverAppBar extends StatelessWidget {
10 | const ProfileViewSliverAppBar({super.key});
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | return CustomSliverAppBar(
15 | titleKey: LocaleKeys.profile,
16 | actions: [
17 | const Icon(
18 | AppConstants.personIcon,
19 | color: AppColors.primaryColor,
20 | ),
21 | IconButton(
22 | onPressed: () => context.pushRoute(const UpdateProfileRoute()),
23 | icon: const Icon(Icons.edit_sharp),
24 | ),
25 | ],
26 | );
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/lib/features/product_details/presentation/cubit/product_details_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 | import 'package:store_ify/core/models/product_color.dart';
3 | import 'package:store_ify/core/models/product_size.dart';
4 |
5 | part 'product_details_state.freezed.dart';
6 |
7 | enum ProductDetailsStateStatus {
8 | initial,
9 | selectProductSize,
10 | selectProductColor,
11 | addProductToCartLoading,
12 | addProductToCartSuccess,
13 | addProductToCartError,
14 | increaseProductQuantity,
15 | decreaseProductQuantity,
16 | }
17 |
18 | @freezed
19 | class ProductDetailsState with _$ProductDetailsState {
20 | const factory ProductDetailsState({
21 | required ProductDetailsStateStatus status,
22 | ProductSize? selectedProductSize,
23 | ProductColor? selectedProductColor,
24 | @Default(1) int productQuantity,
25 | String? error,
26 | }) = _ProductDetailsState;
27 |
28 | factory ProductDetailsState.initial() => const ProductDetailsState(
29 | status: ProductDetailsStateStatus.initial,
30 | );
31 | }
32 |
--------------------------------------------------------------------------------
/lib/core/helpers/hive_type_ids.dart:
--------------------------------------------------------------------------------
1 | class HiveTypeIds {
2 | HiveTypeIds._();
3 |
4 | static const int storeifyUser = 0;
5 | static const int storeifyUserData = 1;
6 | static const int fetchHomeResponse = 2;
7 | static const int product = 3;
8 | static const int productImg = 4;
9 | static const int productColor = 5;
10 | static const int productSize = 6;
11 | static const int store = 7;
12 | static const int category = 8;
13 | static const int pagination = 10;
14 | static const int fetchStores = 11;
15 | static const int subCategory = 12;
16 | static const int fetchCategoriesResponse = 14;
17 | static const int fetchFavoriteProductsResponse = 16;
18 | static const int fetchFavStoresResponse = 17;
19 | static const int fetchStoreBranchesResponse = 18;
20 | static const int fetchStoreCategoriesResponse = 19;
21 | static const int fetchStoreOffersResponse = 20;
22 | static const int storeBranch = 21;
23 | static const int searchData = 22;
24 | static const int searchDataItem = 23;
25 | static const int payParams = 24;
26 | static const int cardType = 25;
27 | }
28 |
--------------------------------------------------------------------------------
/lib/features/auth/data/datasources/auth_local_datasource.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:store_ify/core/api/dio_factory.dart';
4 | import 'package:store_ify/core/helpers/secure_storage_helper.dart';
5 | import 'package:store_ify/core/helpers/cache_keys.dart';
6 | import 'package:store_ify/core/models/storeify_user.dart';
7 |
8 | class AuthLocalDatasource {
9 | AuthLocalDatasource._();
10 |
11 | static Future cacheUser(StoreifyUser user) async {
12 | await SecureStorageHelper.setSecuredString(
13 | CacheKeys.storeifyUser,
14 | json.encode(user.toJson()),
15 | );
16 | }
17 |
18 | static Future cacheUserAndSetTokenIntoHeaders(StoreifyUser user) async {
19 | await cacheUser(user);
20 | DioFactory.setTokenIntoHeadersAfterLogin(user.token!);
21 | }
22 |
23 | static Future getCachedUser() async {
24 | final cachedUser =
25 | await SecureStorageHelper.getSecuredString(CacheKeys.storeifyUser);
26 | final StoreifyUser user = StoreifyUser.fromJson(json.decode(cachedUser));
27 | return user;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lib/features/cart/presentation/widgets/summary_info.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:easy_localization/easy_localization.dart';
3 | import 'package:store_ify/core/themes/app_colors.dart';
4 | import 'package:store_ify/core/themes/app_text_styles.dart';
5 |
6 | class SummaryInfo extends StatelessWidget {
7 | const SummaryInfo({
8 | super.key,
9 | required this.nameKey,
10 | required this.price,
11 | });
12 |
13 | final String nameKey;
14 | final double price;
15 |
16 | @override
17 | Widget build(BuildContext context) {
18 | return Row(
19 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
20 | children: [
21 | Text(
22 | '${context.tr(nameKey)}:',
23 | style: AppTextStyles.textStyle12Regular.copyWith(
24 | color: AppColors.colorBEBEC3,
25 | ),
26 | ),
27 | Text(
28 | '$price LE',
29 | style: AppTextStyles.textStyle12Regular.copyWith(
30 | color: AppColors.colorBEBEC3,
31 | ),
32 | ),
33 | ],
34 | );
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/lib/features/checkout/presentation/widgets/checkout_process_progress_dots.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:store_ify/core/themes/app_colors.dart';
3 | import 'package:store_ify/features/checkout/presentation/widgets/check_circle.dart';
4 | import 'package:store_ify/features/checkout/presentation/widgets/container_contains_dot.dart';
5 | import 'package:store_ify/features/checkout/presentation/widgets/custom_checkout_divider.dart';
6 | import 'package:store_ify/features/checkout/presentation/widgets/custom_progress_circle.dart';
7 |
8 | class CheckoutProcessProgressDots extends StatelessWidget {
9 | const CheckoutProcessProgressDots({super.key});
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | return const Row(
14 | mainAxisAlignment: MainAxisAlignment.center,
15 | children: [
16 | CheckCircle(),
17 | CustomCheckoutDivider(),
18 | ContainerContainsDot(),
19 | CustomCheckoutDivider(color: AppColors.colorD9D9D9),
20 | CustomProgressCircle(isColoredPrimary: false),
21 | ],
22 | );
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/lib/features/auth/presentation/widgets/forgot_password/forgot_password_form.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_bloc/flutter_bloc.dart';
3 | import 'package:store_ify/core/widgets/email_text_form_field.dart';
4 | import 'package:store_ify/generated/locale_keys.g.dart';
5 | import 'package:store_ify/features/auth/presentation/cubits/forgot_password/forgot_password_cubit.dart';
6 | import 'package:store_ify/features/auth/presentation/widgets/text_field_label.dart';
7 |
8 | class ForgotPasswordForm extends StatelessWidget {
9 | const ForgotPasswordForm({super.key});
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | return Form(
14 | key: context.read().formKey,
15 | child: Column(
16 | crossAxisAlignment: CrossAxisAlignment.start,
17 | children: [
18 | const TextFieldLabel(labelKey: LocaleKeys.email),
19 | EmailTextFormField(
20 | controller: context.read().emailController,
21 | ),
22 | ],
23 | ),
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/features/categories/presentation/widgets/categories_sliver_shimmer_loading.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_screenutil/flutter_screenutil.dart';
3 | import 'package:store_ify/core/utils/app_constants.dart';
4 | import 'package:store_ify/core/widgets/shimmer_widget.dart';
5 |
6 | class CategoriesSliverShimmerLoading extends StatelessWidget {
7 | const CategoriesSliverShimmerLoading({super.key});
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | return SliverPadding(
12 | padding: AppConstants.categoriesGridPadding,
13 | sliver: SliverGrid.builder(
14 | itemCount: 10,
15 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
16 | crossAxisCount: AppConstants.gridCrossAxisCount,
17 | crossAxisSpacing: AppConstants.gridCrossAxisSpacing,
18 | mainAxisSpacing: AppConstants.gridMainAxisSpacing,
19 | ),
20 | itemBuilder: (_, __) => ShimmerWidget(
21 | constraints: BoxConstraints(maxHeight: 165.h, maxWidth: 170.w),
22 | ),
23 | ),
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/features/cart/data/api/cart_api_service.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:retrofit/retrofit.dart';
3 | import 'package:store_ify/core/api/end_points.dart';
4 | import 'package:store_ify/features/cart/data/models/add_product_to_cart_params.dart';
5 | import 'package:store_ify/features/cart/data/models/fetch_cart_response.dart';
6 |
7 | part 'cart_api_service.g.dart';
8 |
9 | @RestApi(baseUrl: EndPoints.baseUrl)
10 | abstract class CartApiService {
11 | factory CartApiService(Dio dio, {String baseUrl}) = _CartApiService;
12 |
13 | @POST('${EndPoints.addProductToCart}{productId}')
14 | Future addProductToCart(
15 | @Path('productId') int productId,
16 | @Body() AddProductToCartParams params, [
17 | @CancelRequest() CancelToken? cancelToken,
18 | ]);
19 |
20 | @GET(EndPoints.cart)
21 | Future fetchCart([
22 | @CancelRequest() CancelToken? cancelToken,
23 | ]);
24 |
25 | @DELETE('${EndPoints.cart}{product_id}')
26 | Future removeProductFromCart(
27 | @Path('product_id') int productId, [
28 | @CancelRequest() CancelToken? cancelToken,
29 | ]);
30 | }
31 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 ahmedghaly15
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/core/widgets/horizontal_separated_list_view.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_screenutil/flutter_screenutil.dart';
3 | import 'package:store_ify/core/utils/app_constants.dart';
4 | import 'package:store_ify/core/widgets/my_sized_box.dart';
5 |
6 | class HorizontalSeparatedListView extends StatelessWidget {
7 | const HorizontalSeparatedListView({
8 | super.key,
9 | required this.itemBuilder,
10 | required this.itemCount,
11 | this.padding,
12 | this.separatorWidget,
13 | });
14 |
15 | final Widget? Function(BuildContext, int) itemBuilder;
16 | final EdgeInsetsGeometry? padding;
17 | final Widget? separatorWidget;
18 | final int itemCount;
19 |
20 | @override
21 | Widget build(BuildContext context) {
22 | return ListView.separated(
23 | padding: padding ??
24 | EdgeInsetsDirectional.only(end: 16.w, start: 16.w, bottom: 8.h),
25 | physics: AppConstants.physics,
26 | scrollDirection: Axis.horizontal,
27 | itemBuilder: itemBuilder,
28 | separatorBuilder: ((_, __) => separatorWidget ?? MySizedBox.width19),
29 | itemCount: itemCount,
30 | );
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/lib/features/favorites/presentation/widgets/favorite_products_grid_view.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
3 | import 'package:store_ify/core/models/product.dart';
4 | import 'package:store_ify/core/utils/app_constants.dart';
5 | import 'package:store_ify/core/widgets/product_item.dart';
6 |
7 | class FavoriteProductsGridView extends StatelessWidget {
8 | const FavoriteProductsGridView({
9 | super.key,
10 | required this.products,
11 | });
12 |
13 | final List products;
14 |
15 | @override
16 | Widget build(BuildContext context) {
17 | return GridView.builder(
18 | itemCount: products.length,
19 | padding: AppConstants.categoryPadding,
20 | gridDelegate: AppConstants.favProductsGridDelegate,
21 | itemBuilder: (_, index) => AnimationConfiguration.staggeredGrid(
22 | position: index,
23 | columnCount: products.length,
24 | duration: AppConstants.gridDuration,
25 | child: ScaleAnimation(
26 | child: ProductItem(product: products[index]),
27 | ),
28 | ),
29 | );
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/lib/features/categories/data/models/fetch_sub_category_response.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'fetch_sub_category_response.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | FetchSubCategoryResponse _$FetchSubCategoryResponseFromJson(
10 | Map json) =>
11 | FetchSubCategoryResponse(
12 | category: SubCategory.fromJson(json['category'] as Map),
13 | products: (json['products'] as List)
14 | .map((e) => Product.fromJson(e as Map))
15 | .toList(),
16 | pagination:
17 | Pagination.fromJson(json['pagination'] as Map),
18 | );
19 |
20 | Map _$FetchSubCategoryResponseToJson(
21 | FetchSubCategoryResponse instance) =>
22 | {
23 | 'category': instance.category.toJson(),
24 | 'products': instance.products.map((e) => e.toJson()).toList(),
25 | 'pagination': instance.pagination.toJson(),
26 | };
27 |
--------------------------------------------------------------------------------
/lib/features/favorites/presentation/cubits/fetch_favorites/fetch_favorites_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 | import 'package:store_ify/features/favorites/data/models/fetch_fav_stores_response.dart';
3 | import 'package:store_ify/features/favorites/data/models/fetch_favorite_products_response.dart';
4 |
5 | part 'fetch_favorites_state.freezed.dart';
6 |
7 | enum FetchFavoritesStatus {
8 | initial,
9 | fetchFavoriteProductsLoading,
10 | fetchFavoriteProductsSuccess,
11 | fetchFavoriteProductsError,
12 | fetchFavStoresLoading,
13 | fetchFavStoresSuccess,
14 | fetchFavStoresError,
15 | updateSelectedFavCategory,
16 | }
17 |
18 | @freezed
19 | class FetchFavoritesState with _$FetchFavoritesState {
20 | const factory FetchFavoritesState({
21 | required FetchFavoritesStatus status,
22 | FetchFavoriteProductsResponse? favProducts,
23 | FetchFavStoresResponse? favStores,
24 | String? error,
25 | @Default(0) int selectedFavCategory,
26 | }) = _FetchFavoritesState;
27 |
28 | factory FetchFavoritesState.initial() => const FetchFavoritesState(
29 | status: FetchFavoritesStatus.initial,
30 | );
31 | }
32 |
--------------------------------------------------------------------------------
/lib/features/cart/presentation/widgets/control_cart_product_quantity.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:store_ify/core/themes/app_colors.dart';
3 |
4 | class ControlCartProductQuantity extends StatelessWidget {
5 | const ControlCartProductQuantity({
6 | super.key,
7 | required this.icon,
8 | required this.onTap,
9 | required this.borderRadius,
10 | });
11 |
12 | final BorderRadiusGeometry borderRadius;
13 | final IconData icon;
14 | final VoidCallback? onTap;
15 |
16 | @override
17 | Widget build(BuildContext context) {
18 | return Container(
19 | decoration: BoxDecoration(
20 | borderRadius: borderRadius,
21 | color: AppColors.primaryColor,
22 | ),
23 | child: MaterialButton(
24 | padding: EdgeInsets.zero,
25 | materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
26 | shape: RoundedRectangleBorder(
27 | borderRadius: borderRadius,
28 | ),
29 | minWidth: 0,
30 | height: 0,
31 | onPressed: onTap,
32 | child: Icon(
33 | icon,
34 | color: Colors.white,
35 | ),
36 | ),
37 | );
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/lib/features/categories/data/models/category.dart:
--------------------------------------------------------------------------------
1 | import 'package:hive_flutter/hive_flutter.dart';
2 | import 'package:json_annotation/json_annotation.dart';
3 | import 'package:store_ify/core/helpers/hive_type_ids.dart';
4 | import 'package:store_ify/core/models/product.dart';
5 | import 'package:store_ify/core/models/sub_category.dart';
6 |
7 | part 'category.g.dart';
8 |
9 | @HiveType(typeId: HiveTypeIds.category)
10 | @JsonSerializable(explicitToJson: true)
11 | class Category {
12 | @HiveField(0)
13 | final int id;
14 | @HiveField(1)
15 | final String name;
16 | @HiveField(2)
17 | final String? description;
18 | @HiveField(3)
19 | final String? img;
20 | @HiveField(4)
21 | @JsonKey(name: 'sub_categories')
22 | final List? subCategories;
23 | @HiveField(5)
24 | final List? products;
25 |
26 | const Category({
27 | required this.id,
28 | required this.name,
29 | this.description,
30 | this.img,
31 | this.subCategories,
32 | this.products,
33 | });
34 |
35 | factory Category.fromJson(Map json) =>
36 | _$CategoryFromJson(json);
37 | Map toJson() => _$CategoryToJson(this);
38 | }
39 |
--------------------------------------------------------------------------------
/lib/core/models/pagination.dart:
--------------------------------------------------------------------------------
1 | import 'package:hive_flutter/hive_flutter.dart';
2 | import 'package:json_annotation/json_annotation.dart';
3 | import 'package:store_ify/core/helpers/hive_type_ids.dart';
4 |
5 | part 'pagination.g.dart';
6 |
7 | @HiveType(typeId: HiveTypeIds.pagination)
8 | @JsonSerializable()
9 | class Pagination {
10 | @HiveField(0)
11 | final int total;
12 | @HiveField(1)
13 | @JsonKey(name: 'per_page')
14 | final int perPage;
15 | @HiveField(2)
16 | @JsonKey(name: 'current_page')
17 | final int currentPage;
18 | @HiveField(3)
19 | @JsonKey(name: 'last_page')
20 | final int lastPage;
21 | @HiveField(4)
22 | @JsonKey(name: 'next_page_url')
23 | final String? nextPageUrl;
24 | @HiveField(5)
25 | @JsonKey(name: 'prev_page_url')
26 | final String? prevPageUrl;
27 |
28 | const Pagination({
29 | required this.total,
30 | required this.perPage,
31 | required this.currentPage,
32 | required this.lastPage,
33 | this.nextPageUrl,
34 | this.prevPageUrl,
35 | });
36 |
37 | factory Pagination.fromJson(Map json) =>
38 | _$PaginationFromJson(json);
39 | Map toJson() => _$PaginationToJson(this);
40 | }
41 |
--------------------------------------------------------------------------------
/lib/features/checkout/data/models/checkout_response.dart:
--------------------------------------------------------------------------------
1 | import 'package:json_annotation/json_annotation.dart';
2 |
3 | part 'checkout_response.g.dart';
4 |
5 | @JsonSerializable(explicitToJson: true)
6 | class CheckoutResponse {
7 | final Order order;
8 |
9 | const CheckoutResponse({required this.order});
10 |
11 | factory CheckoutResponse.fromJson(Map json) =>
12 | _$CheckoutResponseFromJson(json);
13 | Map toJson() => _$CheckoutResponseToJson(this);
14 | }
15 |
16 | @JsonSerializable()
17 | class Order {
18 | final int id;
19 | @JsonKey(name: 'user_id')
20 | final int userId;
21 | final double total;
22 | final String status;
23 | @JsonKey(name: 'delivery_date')
24 | final String deliveryDate;
25 | @JsonKey(name: 'delivery_time')
26 | final String deliveryTime;
27 |
28 | const Order({
29 | required this.id,
30 | required this.userId,
31 | required this.total,
32 | required this.status,
33 | required this.deliveryDate,
34 | required this.deliveryTime,
35 | });
36 |
37 | factory Order.fromJson(Map json) => _$OrderFromJson(json);
38 | Map toJson() => _$OrderToJson(this);
39 | }
40 |
--------------------------------------------------------------------------------
/lib/core/models/store.dart:
--------------------------------------------------------------------------------
1 | import 'package:hive_flutter/hive_flutter.dart';
2 | import 'package:json_annotation/json_annotation.dart';
3 | import 'package:store_ify/core/helpers/hive_type_ids.dart';
4 | import 'package:store_ify/features/categories/data/models/category.dart';
5 |
6 | part 'store.g.dart';
7 |
8 | @HiveType(typeId: HiveTypeIds.store)
9 | @JsonSerializable(explicitToJson: true, fieldRename: FieldRename.snake)
10 | class Store {
11 | @HiveField(0)
12 | final int id;
13 | @HiveField(1)
14 | final String name;
15 | @HiveField(2)
16 | final String img;
17 | @HiveField(3)
18 | final List? categories;
19 | @HiveField(4)
20 | final int totalProductsOrdered;
21 | @HiveField(5)
22 | final bool isFavorited;
23 | @HiveField(6)
24 | final String averageRating;
25 |
26 | Store({
27 | required this.id,
28 | required this.name,
29 | required this.img,
30 | required this.categories,
31 | required this.totalProductsOrdered,
32 | required this.isFavorited,
33 | required this.averageRating,
34 | });
35 |
36 | factory Store.fromJson(Map json) => _$StoreFromJson(json);
37 | Map toJson() => _$StoreToJson(this);
38 | }
39 |
--------------------------------------------------------------------------------
/lib/features/onboarding/presentation/widgets/custom_indicators.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_bloc/flutter_bloc.dart';
3 | import 'package:flutter_screenutil/flutter_screenutil.dart';
4 | import 'package:smooth_page_indicator/smooth_page_indicator.dart';
5 | import 'package:store_ify/core/helpers/extensions.dart';
6 | import 'package:store_ify/core/themes/app_colors.dart';
7 | import 'package:store_ify/core/utils/app_constants.dart';
8 | import 'package:store_ify/features/onboarding/presentation/cubit/onboarding_cubit.dart';
9 |
10 | class CustomIndicators extends StatelessWidget {
11 | const CustomIndicators({super.key});
12 |
13 | @override
14 | Widget build(BuildContext context) {
15 | return SmoothPageIndicator(
16 | controller: context.read().pageController,
17 | count: AppConstants.onboardingPages.length,
18 | effect: ExpandingDotsEffect(
19 | dotColor: context.isDarkModeActive ? Colors.white : Colors.grey,
20 | activeDotColor: AppColors.primaryColor,
21 | dotHeight: 6.h,
22 | expansionFactor: 5.w,
23 | dotWidth: 6.h,
24 | spacing: 5.w,
25 | ),
26 | );
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/lib/features/cart/data/models/fetch_cart_response.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'fetch_cart_response.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | FetchCartResponse _$FetchCartResponseFromJson(Map json) =>
10 | FetchCartResponse(
11 | cart: (json['cart'] as List)
12 | .map((e) => Cart.fromJson(e as Map))
13 | .toList(),
14 | totalItems: (json['totalItems'] as num).toInt(),
15 | totalPrice: (json['totalPrice'] as num).toDouble(),
16 | subTotalPrice: (json['subTotalPrice'] as num).toDouble(),
17 | delivery: (json['delivery'] as num).toInt(),
18 | );
19 |
20 | Map _$FetchCartResponseToJson(FetchCartResponse instance) =>
21 | {
22 | 'cart': instance.cart.map((e) => e.toJson()).toList(),
23 | 'totalItems': instance.totalItems,
24 | 'delivery': instance.delivery,
25 | 'totalPrice': instance.totalPrice,
26 | 'subTotalPrice': instance.subTotalPrice,
27 | };
28 |
--------------------------------------------------------------------------------
/lib/core/utils/auto_route_observer.dart:
--------------------------------------------------------------------------------
1 | import 'package:auto_route/auto_route.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | class AppRoutesObserver extends AutoRouterObserver {
5 | @override
6 | void didPush(Route route, Route? previousRoute) {
7 | debugPrint('Previous route : ${previousRoute?.settings.name}');
8 | debugPrint('New route pushed: ${route.settings.name}');
9 | }
10 |
11 | @override
12 | void didPop(Route route, Route? previousRoute) {
13 | debugPrint('Route Popped : ${route.settings.name}');
14 | }
15 |
16 | @override
17 | void didRemove(Route route, Route? previousRoute) {
18 | debugPrint('Route Removed : ${route.settings.name}');
19 | }
20 |
21 | @override
22 | void didReplace({Route? newRoute, Route? oldRoute}) {
23 | debugPrint(
24 | 'OldRoute : ${oldRoute!.settings.name} was replaced by ${newRoute!.settings.name}');
25 | }
26 |
27 | @override
28 | void didInitTabRoute(TabPageRoute route, TabPageRoute? previousRoute) {
29 | debugPrint('Tab route visited: ${route.name}');
30 | }
31 |
32 | @override
33 | void didChangeTabRoute(TabPageRoute route, TabPageRoute previousRoute) {
34 | debugPrint('Tab route re-visited: ${route.name}');
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/lib/features/home/data/models/fetch_home_response.dart:
--------------------------------------------------------------------------------
1 | import 'package:hive_flutter/hive_flutter.dart';
2 | import 'package:json_annotation/json_annotation.dart';
3 | import 'package:store_ify/core/helpers/hive_type_ids.dart';
4 | import 'package:store_ify/core/models/pagination.dart';
5 | import 'package:store_ify/core/models/product.dart';
6 | import 'package:store_ify/features/categories/data/models/category.dart';
7 | import 'package:store_ify/core/models/store.dart';
8 |
9 | part 'fetch_home_response.g.dart';
10 |
11 | @HiveType(typeId: HiveTypeIds.fetchHomeResponse)
12 | @JsonSerializable(explicitToJson: true)
13 | class FetchHomeResponse {
14 | @HiveField(0)
15 | final List bestSelling;
16 | @HiveField(1)
17 | final List categories;
18 | @HiveField(2)
19 | final List topStores;
20 | @HiveField(3)
21 | final Pagination pagination;
22 |
23 | const FetchHomeResponse({
24 | required this.bestSelling,
25 | required this.categories,
26 | required this.topStores,
27 | required this.pagination,
28 | });
29 |
30 | factory FetchHomeResponse.fromJson(Map json) =>
31 | _$FetchHomeResponseFromJson(json);
32 | Map toJson() => _$FetchHomeResponseToJson(this);
33 | }
34 |
--------------------------------------------------------------------------------
/lib/features/cart/data/models/cart.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'cart.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | Cart _$CartFromJson(Map json) => Cart(
10 | id: (json['id'] as num).toInt(),
11 | quantity: (json['quantity'] as num).toInt(),
12 | cartId: (json['cart_id'] as num).toInt(),
13 | product: Product.fromJson(json['product'] as Map),
14 | price: (json['price'] as num).toDouble(),
15 | total: (json['total'] as num).toDouble(),
16 | color: ProductColor.fromJson(json['color'] as Map),
17 | size: ProductSize.fromJson(json['size'] as Map),
18 | );
19 |
20 | Map _$CartToJson(Cart instance) => {
21 | 'id': instance.id,
22 | 'quantity': instance.quantity,
23 | 'price': instance.price,
24 | 'total': instance.total,
25 | 'cart_id': instance.cartId,
26 | 'product': instance.product.toJson(),
27 | 'color': instance.color.toJson(),
28 | 'size': instance.size.toJson(),
29 | };
30 |
--------------------------------------------------------------------------------
/lib/features/profile/presentation/widgets/profile_img.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_screenutil/flutter_screenutil.dart';
3 | import 'package:store_ify/core/themes/app_colors.dart';
4 | import 'package:store_ify/core/utils/app_constants.dart';
5 | import 'package:store_ify/core/widgets/custom_cached_network_image.dart';
6 |
7 | class ProfileImg extends StatelessWidget {
8 | const ProfileImg({super.key, this.radius = 30});
9 |
10 | final double radius;
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | return ValueListenableBuilder(
15 | valueListenable: userNotifier,
16 | builder: (context, user, __) => CustomCachedNetworkImage(
17 | imageUrl: user!.user.img != 'http://192.168.1.6:8081/uploads'
18 | ? user.user.img!
19 | : 'https://img.freepik.com/free-photo/confident-handsome-guy-posing-against-white-wall_176420-32936.jpg?t=st=1726145242~exp=1726148842~hmac=d88f0854b224a4b284dd8236414a4e0854ca07915b501ad2375b8032fed3456e&w=1060',
20 | imageBuilder: (_, image) => CircleAvatar(
21 | radius: radius.r,
22 | backgroundImage: image,
23 | backgroundColor: AppColors.primaryColor,
24 | ),
25 | ),
26 | );
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/lib/features/payment/presentation/cubits/payment_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:freezed_annotation/freezed_annotation.dart';
3 | import 'package:store_ify/core/utils/app_constants.dart';
4 | import 'package:store_ify/features/payment/data/models/card_type.dart';
5 | import 'package:store_ify/features/payment/data/models/payment_card_details.dart';
6 |
7 | part 'payment_state.freezed.dart';
8 |
9 | enum PaymentStateStatus {
10 | initial,
11 | updateSelectedCardType,
12 | alwaysAutoValidateMode,
13 | toggleCheckBox,
14 | payLoading,
15 | paySuccess,
16 | payError,
17 | retrieveCachedPaymentCardDetails,
18 | retrievedCachedPaymentCardDetails,
19 | }
20 |
21 | @freezed
22 | class PaymentState with _$PaymentState {
23 | const factory PaymentState({
24 | required PaymentStateStatus status,
25 | CardType? selectedCardType,
26 | @Default(AutovalidateMode.disabled) AutovalidateMode autovalidateMode,
27 | @Default(false) bool checkboxValue,
28 | String? error,
29 | PaymentCardDetails? paymentCardDetails,
30 | }) = _PaymentState;
31 |
32 | factory PaymentState.initial() => PaymentState(
33 | status: PaymentStateStatus.initial,
34 | selectedCardType: AppConstants.cardTypes[0],
35 | );
36 | }
37 |
--------------------------------------------------------------------------------
/lib/features/payment/data/models/payment_card_details.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 | import 'package:hive_flutter/hive_flutter.dart';
3 | import 'package:store_ify/core/helpers/hive_type_ids.dart';
4 | import 'package:store_ify/features/payment/data/models/card_type.dart';
5 |
6 | part 'payment_card_details.g.dart';
7 |
8 | @HiveType(typeId: HiveTypeIds.payParams)
9 | @JsonSerializable(explicitToJson: true)
10 | class PaymentCardDetails {
11 | @HiveField(0)
12 | final String? number;
13 | @HiveField(1)
14 | final String? cvv;
15 | @HiveField(2)
16 | final String? amount;
17 | @HiveField(3)
18 | @JsonKey(name: 'exp_month')
19 | final String? expMonth;
20 | @HiveField(4)
21 | @JsonKey(name: 'exp_year')
22 | final String? expYear;
23 | @HiveField(5)
24 | final CardType? cardType;
25 | @HiveField(6)
26 | final int? holderNumber;
27 |
28 | PaymentCardDetails({
29 | this.number,
30 | this.cvv,
31 | this.amount,
32 | this.expMonth,
33 | this.expYear,
34 | this.cardType,
35 | this.holderNumber,
36 | });
37 |
38 | factory PaymentCardDetails.fromJson(Map json) =>
39 | _$PaymentCardDetailsFromJson(json);
40 | Map toJson() => _$PaymentCardDetailsToJson(this);
41 | }
42 |
--------------------------------------------------------------------------------
/lib/features/checkout/presentation/widgets/how_do_u_want_to_pay_question.dart:
--------------------------------------------------------------------------------
1 | import 'package:animate_do/animate_do.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_screenutil/flutter_screenutil.dart';
4 | import 'package:easy_localization/easy_localization.dart';
5 | import 'package:store_ify/generated/locale_keys.g.dart';
6 | import 'package:store_ify/core/themes/app_colors.dart';
7 | import 'package:store_ify/core/themes/app_text_styles.dart';
8 | import 'package:store_ify/core/utils/app_constants.dart';
9 |
10 | class HowDoUWantToPayQuestion extends StatelessWidget {
11 | const HowDoUWantToPayQuestion({super.key});
12 |
13 | @override
14 | Widget build(BuildContext context) {
15 | return FadeInDown(
16 | from: 30.h,
17 | child: Container(
18 | margin: EdgeInsetsDirectional.only(
19 | start: AppConstants.mainButtonHorizontalMarginVal.w,
20 | end: AppConstants.mainButtonHorizontalMarginVal.w,
21 | top: 32.h,
22 | bottom: 40.h,
23 | ),
24 | child: Text(
25 | context.tr(LocaleKeys.howDoUWantToPay),
26 | style: AppTextStyles.textStyle16Medium.copyWith(
27 | color: AppColors.primaryColor,
28 | ),
29 | ),
30 | ),
31 | );
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/lib/core/models/storeify_user.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 | import 'package:hive_flutter/hive_flutter.dart';
3 | import 'package:store_ify/core/helpers/hive_type_ids.dart';
4 |
5 | part 'storeify_user.freezed.dart';
6 | part 'storeify_user.g.dart';
7 |
8 | @HiveType(typeId: HiveTypeIds.storeifyUser)
9 | @freezed
10 | class StoreifyUser with _$StoreifyUser {
11 | @JsonSerializable(explicitToJson: true)
12 | const factory StoreifyUser({
13 | @HiveField(0) String? token,
14 | @HiveField(1) required UserData user,
15 | }) = _StoreifyUser;
16 |
17 | factory StoreifyUser.fromJson(Map json) =>
18 | _$StoreifyUserFromJson(json);
19 | }
20 |
21 | @HiveType(typeId: HiveTypeIds.storeifyUserData)
22 | @JsonSerializable()
23 | class UserData {
24 | @HiveField(0)
25 | final int id;
26 | @HiveField(1)
27 | final String username;
28 | @HiveField(2)
29 | final String email;
30 | @HiveField(3)
31 | final String? img;
32 |
33 | const UserData({
34 | required this.id,
35 | required this.username,
36 | required this.email,
37 | this.img,
38 | });
39 |
40 | factory UserData.fromJson(Map json) =>
41 | _$UserDataFromJson(json);
42 | Map toJson() => _$UserDataToJson(this);
43 | }
44 |
--------------------------------------------------------------------------------
/lib/core/utils/functions/circular_indicator_or_text_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:easy_localization/easy_localization.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_screenutil/flutter_screenutil.dart';
4 | import 'package:store_ify/core/helpers/extensions.dart';
5 | import 'package:store_ify/core/themes/app_colors.dart';
6 | import 'package:store_ify/core/themes/app_text_styles.dart';
7 | import 'package:store_ify/core/widgets/custom_circular_progress_indicator.dart';
8 |
9 | Widget circularIndicatorOrTextWidget({
10 | required bool isLoading,
11 | required BuildContext context,
12 | required String textKey,
13 | bool isOutlined = false,
14 | }) {
15 | return isLoading
16 | ? SizedBox.square(
17 | dimension: 24.h,
18 | child: CustomCircularProgressIndicator(
19 | color: isOutlined
20 | ? AppColors.primaryColor
21 | : (context.isDarkModeActive
22 | ? AppColors.darkColor
23 | : AppColors.lightModeColor),
24 | ),
25 | )
26 | : Text(
27 | context.tr(textKey),
28 | style: AppTextStyles.textStyle16Medium.copyWith(
29 | color: isOutlined ? AppColors.primaryColor : Colors.white,
30 | ),
31 | );
32 | }
33 |
--------------------------------------------------------------------------------
/lib/features/stores/data/models/fetch_store_branches.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 | import 'package:hive_flutter/hive_flutter.dart';
3 | import 'package:store_ify/core/helpers/hive_type_ids.dart';
4 |
5 | part 'fetch_store_branches.g.dart';
6 |
7 | @HiveType(typeId: HiveTypeIds.fetchStoreBranchesResponse)
8 | @JsonSerializable(explicitToJson: true)
9 | class FetchStoreBranchesResponse {
10 | @HiveField(0)
11 | final List branches;
12 |
13 | const FetchStoreBranchesResponse({required this.branches});
14 |
15 | factory FetchStoreBranchesResponse.fromJson(Map json) =>
16 | _$FetchStoreBranchesResponseFromJson(json);
17 | Map toJson() => _$FetchStoreBranchesResponseToJson(this);
18 | }
19 |
20 | @HiveType(typeId: HiveTypeIds.storeBranch)
21 | @JsonSerializable()
22 | class StoreBranch {
23 | @HiveField(0)
24 | final int id;
25 | @HiveField(1)
26 | final String name;
27 | @HiveField(2)
28 | final String address;
29 |
30 | const StoreBranch({
31 | required this.id,
32 | required this.name,
33 | required this.address,
34 | });
35 |
36 | factory StoreBranch.fromJson(Map json) =>
37 | _$StoreBranchFromJson(json);
38 | Map toJson() => _$StoreBranchToJson(this);
39 | }
40 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values-v31/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
18 |
21 |
22 |
--------------------------------------------------------------------------------
/lib/core/utils/functions/execute_and_handle_errors.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:store_ify/core/api/api_error_handler.dart';
3 | import 'package:store_ify/core/api/api_result.dart';
4 |
5 | /// Executes a given asynchronous function and handles any errors that occur during its execution.
6 | ///
7 | /// This method takes a [function] that returns a [Future] and attempts to execute it.
8 | /// If the function completes successfully, the result is wrapped in an [ApiResult.success] object and returned.
9 | /// If an error occurs during execution, the error is caught, logged using [debugPrint], and
10 | /// an [ApiResult.error] object is returned with the error handled by [ApiErrorHandler].
11 | ///
12 | /// Example usage:
13 | /// ```dart
14 | /// Future> result = executeAndHandleErrors(() async {
15 | /// // Your asynchronous code here
16 | /// });
17 | /// ```
18 | ///
19 | /// [T] is the type of the result that the function returns.
20 | Future> executeAndHandleErrors(
21 | Future Function() function,
22 | ) async {
23 | try {
24 | return ApiResult.success(await function());
25 | } catch (error) {
26 | debugPrint('********* Error in executeAndHandleErrors: $error **********');
27 | return ApiResult.error(ApiErrorHandler.handle(error));
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values-night-v31/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
18 |
21 |
22 |
--------------------------------------------------------------------------------
/lib/features/favorites/presentation/cubits/favorites/general_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:freezed_annotation/freezed_annotation.dart';
3 | import 'package:store_ify/core/themes/app_themes.dart';
4 | import 'package:store_ify/features/home/data/models/fetch_home_response.dart';
5 |
6 | part 'general_state.freezed.dart';
7 |
8 | enum GeneralStateStatus {
9 | initial,
10 | preferProductLoading,
11 | preferProductSuccess,
12 | preferProductError,
13 | removeProductFromFavsLoading,
14 | removeProductFromFavsSuccess,
15 | removeProductFromFavsError,
16 | preferStoreLoading,
17 | preferStoreSuccess,
18 | preferStoreError,
19 | removeStoreFromFavsLoading,
20 | removeStoreFromFavsSuccess,
21 | removeStoreFromFavsError,
22 | toggleTheme,
23 | fetchHomeDataLoading,
24 | fetchHomeDataSuccess,
25 | fetchHomeDataError,
26 | }
27 |
28 | @freezed
29 | class GeneralState with _$GeneralState {
30 | const factory GeneralState({
31 | required GeneralStateStatus status,
32 | String? error,
33 | ThemeData? theme,
34 | FetchHomeResponse? homeData,
35 | int? favAffectedItem,
36 | }) = _GeneralState;
37 |
38 | factory GeneralState.initial() => GeneralState(
39 | status: GeneralStateStatus.initial,
40 | theme: AppThemes.lightMode,
41 | );
42 | }
43 |
--------------------------------------------------------------------------------
/lib/features/onboarding/presentation/widgets/next_button_bloc_selector.dart:
--------------------------------------------------------------------------------
1 | import 'package:auto_route/auto_route.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_bloc/flutter_bloc.dart';
4 | import 'package:flutter_screenutil/flutter_screenutil.dart';
5 | import 'package:store_ify/core/router/app_router.dart';
6 | import 'package:store_ify/core/widgets/main_button.dart';
7 | import 'package:store_ify/features/onboarding/presentation/cubit/onboarding_cubit.dart';
8 | import 'package:store_ify/features/onboarding/presentation/cubit/onboarding_state.dart';
9 | import 'package:store_ify/generated/locale_keys.g.dart';
10 |
11 | class NextButtonBlocSelector extends StatelessWidget {
12 | const NextButtonBlocSelector({super.key});
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | return BlocSelector(
17 | selector: (state) => state.isLastPage,
18 | builder: (context, isLastPage) => MainButton(
19 | margin: EdgeInsets.symmetric(horizontal: 61.w),
20 | onPressed: () => context.read().navigateAmongPages(
21 | onSkip: () => context.replaceRoute(const LoginRoute()),
22 | ),
23 | textKey: isLastPage ? LocaleKeys.getStarted : LocaleKeys.next,
24 | ),
25 | );
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/lib/features/checkout/presentation/widgets/enable_location_error_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_bloc/flutter_bloc.dart';
3 | import 'package:store_ify/core/widgets/custom_error_widget.dart';
4 | import 'package:store_ify/core/widgets/custom_sliver_app_bar.dart';
5 | import 'package:store_ify/features/checkout/presentation/cubits/checkout/checkout_cubit.dart';
6 | import 'package:store_ify/generated/locale_keys.g.dart';
7 |
8 | class EnableLocationErrorWidget extends StatelessWidget {
9 | const EnableLocationErrorWidget({
10 | super.key,
11 | required this.error,
12 | });
13 |
14 | final String error;
15 |
16 | @override
17 | Widget build(BuildContext context) {
18 | return CustomScrollView(
19 | slivers: [
20 | const CustomSliverAppBar(titleKey: LocaleKeys.checkout),
21 | SliverFillRemaining(
22 | hasScrollBody: false,
23 | child: CustomErrorWidget(
24 | errorKey: error,
25 | errorDescriptionKey: error == LocaleKeys.locationDenied
26 | ? LocaleKeys.locationDeniedDescription
27 | : null,
28 | tryAgainOnPressed: () =>
29 | context.read().enableLocationPermission(),
30 | ),
31 | ),
32 | ],
33 | );
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/lib/core/widgets/custom_cached_network_image.dart:
--------------------------------------------------------------------------------
1 | import 'package:cached_network_image/cached_network_image.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:store_ify/core/themes/app_colors.dart';
4 |
5 | class CustomCachedNetworkImage extends StatelessWidget {
6 | const CustomCachedNetworkImage({
7 | super.key,
8 | required this.imageUrl,
9 | this.fit = BoxFit.cover,
10 | this.imageBuilder,
11 | this.height,
12 | this.width,
13 | this.fadeInDuration = const Duration(milliseconds: 500),
14 | this.fadeOutDuration = const Duration(milliseconds: 1000),
15 | });
16 |
17 | final String imageUrl;
18 | final BoxFit fit;
19 | final Widget Function(BuildContext, ImageProvider