From 2f0272f1c6c64fcfb34c824709dbf71847b0f1c7 Mon Sep 17 00:00:00 2001 From: doann221 Date: Sun, 17 Mar 2024 22:26:20 +0700 Subject: [PATCH 1/4] fix import error in development --- lib/API/api_order.dart | 9 +- lib/API/api_profile.dart | 1 - lib/API/api_sign_up.dart | 6 +- lib/Pages/Screens/noti_screen.dart | 2 +- lib/Pages/Screens/setting_screen.dart | 2 +- lib/Pages/Tabs/cart_tap.dart | 21 --- lib/Pages/Tabs/information_user.dart | 2 +- lib/Pages/Tabs/user_profile.dart | 2 +- lib/Providers/token_manager.dart | 2 +- macos/Flutter/GeneratedPluginRegistrant.swift | 4 +- pubspec.lock | 163 ++++++++---------- pubspec.yaml | 5 +- windows/flutter/CMakeLists.txt | 7 +- 13 files changed, 94 insertions(+), 132 deletions(-) diff --git a/lib/API/api_order.dart b/lib/API/api_order.dart index c28b623..69901be 100644 --- a/lib/API/api_order.dart +++ b/lib/API/api_order.dart @@ -139,7 +139,8 @@ class OrderApi { return orederResPonse; } - Future cancelOrder(BuildContext context, {required String orderId}) async { + Future cancelOrder(BuildContext context, + {required String orderId, required String reaSon}) async { try { var accessToken = Provider.of(context, listen: false).user.accessToken; @@ -147,11 +148,11 @@ class OrderApi { final newAccessToken = await AuthLogin.getAccessToken(); accessToken = newAccessToken!; } - http.Response res = - await http.patch(Uri.parse('${uri}orders-mnt/$orderId'), headers: { + http.Response res = await http + .put(Uri.parse('${uri}orders-mnt/$orderId/cancel'), headers: { 'Authorization': 'Bearer $accessToken', }, body: { - "orderStatus": "cancelled" + "cancelReason": reaSon }); httpErrorHandle( response: res, diff --git a/lib/API/api_profile.dart b/lib/API/api_profile.dart index d7afdc4..a3cf815 100644 --- a/lib/API/api_profile.dart +++ b/lib/API/api_profile.dart @@ -6,7 +6,6 @@ import 'package:my_app/API/api_login.dart'; import 'package:my_app/Providers/token_manager.dart'; import 'package:my_app/Providers/user_provider.dart'; import 'package:my_app/models/user_models.dart'; -import 'package:my_app/models/user_model.dart'; import 'package:my_app/utils/constant.dart'; import 'package:my_app/utils/snackbar.dart'; import 'package:provider/provider.dart'; diff --git a/lib/API/api_sign_up.dart b/lib/API/api_sign_up.dart index 8d1d886..d1aed11 100644 --- a/lib/API/api_sign_up.dart +++ b/lib/API/api_sign_up.dart @@ -38,7 +38,11 @@ class AuthSignUp { context: context, onSuccess: () { showSnackBarSuccess(context, 'Đăng ký thành công'); - sendOTPVerifyEmail(context: context, email: email); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => VerifyEmail(email: email))); + // sendOTPVerifyEmail(context: context, email: email); }, ); } catch (e) { diff --git a/lib/Pages/Screens/noti_screen.dart b/lib/Pages/Screens/noti_screen.dart index 8cb473b..3dbc02f 100644 --- a/lib/Pages/Screens/noti_screen.dart +++ b/lib/Pages/Screens/noti_screen.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:my_app/Pages/Tabs/notification_after_login_tab.dart'; import 'package:my_app/Providers/token_manager.dart'; -import 'package:my_app/models/user_model.dart'; +import 'package:my_app/models/user_models.dart'; class NotiScreen extends StatefulWidget { const NotiScreen({super.key}); diff --git a/lib/Pages/Screens/setting_screen.dart b/lib/Pages/Screens/setting_screen.dart index 7f70790..eba7136 100644 --- a/lib/Pages/Screens/setting_screen.dart +++ b/lib/Pages/Screens/setting_screen.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:my_app/Pages/Tabs/login_tap.dart'; import 'package:my_app/Pages/Tabs/user_profile.dart'; import 'package:my_app/Providers/token_manager.dart'; -import 'package:my_app/models/user_model.dart'; +import 'package:my_app/models/user_models.dart'; class SettingScreen extends StatefulWidget { const SettingScreen({super.key}); diff --git a/lib/Pages/Tabs/cart_tap.dart b/lib/Pages/Tabs/cart_tap.dart index aa8efdc..9405365 100644 --- a/lib/Pages/Tabs/cart_tap.dart +++ b/lib/Pages/Tabs/cart_tap.dart @@ -6,7 +6,6 @@ import 'package:my_app/Providers/product_provider.dart'; import 'package:my_app/Widgets/Cart/open_diaolog_address.dart'; import 'package:my_app/Pages/Tabs/add_address._tap.dart'; import 'package:my_app/Pages/Tabs/change_address.dart'; -import 'package:my_app/Providers/product_provider.dart'; import 'package:my_app/Providers/user_provider.dart'; import 'package:my_app/Widgets/Login/button.dart'; import 'package:my_app/models/address_model.dart'; @@ -548,20 +547,8 @@ class _CartTapState extends State { ); }, ), - ) ], - - Padding( - padding: EdgeInsets.all(10), - child: ButtonSendrequest( - text: 'Thanh toán', - submit: openDiaologAddress, - ), - ) - ], - ), - ), ); } @@ -784,12 +771,4 @@ class _CartTapState extends State { ); }); } - - void getReviewOder() { - OrderApi().reviewOrder( - context: context, - addressSelected: valueChecked, - productSelected: (productCart.product), - ); - } } diff --git a/lib/Pages/Tabs/information_user.dart b/lib/Pages/Tabs/information_user.dart index 2950862..beae117 100644 --- a/lib/Pages/Tabs/information_user.dart +++ b/lib/Pages/Tabs/information_user.dart @@ -7,7 +7,7 @@ import 'package:my_app/API/api_image.dart'; import 'package:my_app/API/api_profile.dart'; import 'package:my_app/Providers/user_provider.dart'; import 'package:my_app/Widgets/Login/button.dart'; -import 'package:my_app/models/user_model.dart'; +import 'package:my_app/models/user_models.dart'; import 'package:my_app/utils/constant.dart'; import 'package:my_app/utils/snackbar.dart'; import 'package:provider/provider.dart'; diff --git a/lib/Pages/Tabs/user_profile.dart b/lib/Pages/Tabs/user_profile.dart index c34904d..95d59e6 100644 --- a/lib/Pages/Tabs/user_profile.dart +++ b/lib/Pages/Tabs/user_profile.dart @@ -7,7 +7,7 @@ import 'package:my_app/Providers/user_provider.dart'; import 'package:my_app/Widgets/Login/button.dart'; import 'package:my_app/Widgets/SettingScreen/setting_title.dart'; import 'package:my_app/models/setting.dart'; -import 'package:my_app/models/user_model.dart'; +import 'package:my_app/models/user_models.dart'; import 'package:my_app/utils/constant.dart'; import 'package:provider/provider.dart'; diff --git a/lib/Providers/token_manager.dart b/lib/Providers/token_manager.dart index fab07e2..1cdd2d6 100644 --- a/lib/Providers/token_manager.dart +++ b/lib/Providers/token_manager.dart @@ -1,6 +1,6 @@ import 'dart:convert'; -import 'package:my_app/models/user_model.dart'; +import 'package:my_app/models/user_models.dart'; import 'package:shared_preferences/shared_preferences.dart'; class TokenManager { diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 2ba2efa..7a0eb66 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -9,10 +9,10 @@ import audio_session import file_selector_macos import firebase_auth import firebase_core +import google_sign_in_ios import just_audio import package_info_plus import path_provider_foundation -import google_sign_in_ios import shared_preferences_foundation import sqflite import url_launcher_macos @@ -24,10 +24,10 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) + FLTGoogleSignInPlugin.register(with: registry.registrar(forPlugin: "FLTGoogleSignInPlugin")) JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) - FLTGoogleSignInPlugin.register(with: registry.registrar(forPlugin: "FLTGoogleSignInPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) diff --git a/pubspec.lock b/pubspec.lock index 86de550..4c52032 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,18 +5,26 @@ packages: dependency: transitive description: name: _flutterfire_internals - sha256: f5628cd9c92ed11083f425fd1f8f1bc60ecdda458c81d73b143aeda036c35fe7 + sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd" url: "https://pub.dev" source: hosted - version: "1.3.16" + version: "1.3.25" animated_bottom_navigation_bar: dependency: "direct main" description: name: animated_bottom_navigation_bar - sha256: "573524584893ad0114ca8ab39f122e064ed2b3f876e4a3a70aec82378a25c617" + sha256: "2b04a2ae4b0742669e60ddf309467d6a354cefd2d0cd20f4737b1efaf9834cda" url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.3.3" + args: + dependency: transitive + description: + name: args + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + url: "https://pub.dev" + source: hosted + version: "2.4.2" async: dependency: transitive description: @@ -120,6 +128,14 @@ packages: sha256: fedaadfa3a6996f75211d835aaeb8fede285dae94262485698afd832371b9a5e url: "https://pub.dev" source: hosted + version: "0.3.3+8" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted version: "3.0.3" csslib: dependency: transitive @@ -129,7 +145,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" - version: "0.3.3+8" cupertino_icons: dependency: "direct main" description: @@ -150,10 +165,10 @@ packages: dependency: "direct main" description: name: dio - sha256: "797e1e341c3dd2f69f2dad42564a6feff3bfb87187d05abb93b9609e6f1645c3" + sha256: "49af28382aefc53562459104f64d16b9dfd1e8ef68c862d5af436cc8356ce5a8" url: "https://pub.dev" source: hosted - version: "5.4.0" + version: "5.4.1" fake_async: dependency: transitive description: @@ -214,34 +229,34 @@ packages: dependency: "direct main" description: name: firebase_auth - sha256: "279b2773ff61afd9763202cb5582e2b995ee57419d826b9af6517302a59b672f" + sha256: "17b841e1b000c3441b8ffceca88f468e078d0443db9643e77541bdfb7a3fd16b" url: "https://pub.dev" source: hosted - version: "4.16.0" + version: "4.17.8" firebase_auth_platform_interface: dependency: transitive description: name: firebase_auth_platform_interface - sha256: "3c9cfaccb7549492edf5b0c67c6dd1c6727c7830891aa6727f2fb225f0226626" + sha256: f294ceef40409a36c819a14280ca864fe487b44033e5276443377c66cb448310 url: "https://pub.dev" source: hosted - version: "7.0.9" + version: "7.1.8" firebase_auth_web: dependency: transitive description: name: firebase_auth_web - sha256: c7b1379ccef7abf4b6816eede67a868c44142198e42350f51c01d8fc03f95a7d + sha256: "1f231da900fe7ff9f2974f8adcbdb3363c410c24725978afa5dc33e1e7e62e06" url: "https://pub.dev" source: hosted - version: "5.8.13" + version: "5.9.8" firebase_core: dependency: "direct main" description: name: firebase_core - sha256: "96607c0e829a581c2a483c658f04e8b159964c3bae2730f73297070bc85d40bb" + sha256: "53316975310c8af75a96e365f9fccb67d1c544ef0acdbf0d88bbe30eedd1c4f9" url: "https://pub.dev" source: hosted - version: "2.24.2" + version: "2.27.0" firebase_core_platform_interface: dependency: transitive description: @@ -254,10 +269,18 @@ packages: dependency: transitive description: name: firebase_core_web - sha256: d585bdf3c656c3f7821ba1bd44da5f13365d22fcecaf5eb75c4295246aaa83c0 + sha256: c8e1d59385eee98de63c92f961d2a7062c5d9a65e7f45bdc7f1b0b205aab2492 url: "https://pub.dev" source: hosted - version: "2.10.0" + version: "2.11.5" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" flutter: dependency: "direct main" description: flutter @@ -421,10 +444,10 @@ packages: dependency: transitive description: name: google_sign_in_ios - sha256: f3336d9e44d4d28063ac90271f6db5caf99f0480cb07281330e7a432edb95226 + sha256: a7d653803468d30b82ceb47ea00fe86d23c56e63eb2e5c2248bb68e9df203217 url: "https://pub.dev" source: hosted - version: "5.7.3" + version: "5.7.4" google_sign_in_platform_interface: dependency: transitive description: @@ -440,8 +463,7 @@ packages: sha256: a278ea2d01013faf341cbb093da880d0f2a552bbd1cb6ee90b5bebac9ba69d77 url: "https://pub.dev" source: hosted - - version: "0.12.2+1" + version: "0.12.3+2" html: dependency: transitive description: @@ -450,9 +472,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.15.4" - - version: "0.12.3+2" - http: dependency: "direct main" description: @@ -497,10 +516,10 @@ packages: dependency: transitive description: name: image_picker_ios - sha256: fadafce49e8569257a0cad56d24438a6fa1f0cbd7ee0af9b631f7492818a4ca3 + sha256: "917a5cadd67d052554cfb258595e54217de53fac5b52939426e26319a02e6297" url: "https://pub.dev" source: hosted - version: "0.8.9+1" + version: "0.8.9+2" image_picker_linux: dependency: transitive description: @@ -637,22 +656,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" - package_config: - dependency: transitive - description: - name: package_config - sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" - url: "https://pub.dev" - source: hosted - version: "2.1.0" package_info_plus: dependency: transitive description: name: package_info_plus - sha256: "7e76fad405b3e4016cd39d08f455a4eb5199723cf594cd1b8916d47140d93017" + sha256: "88bc797f44a94814f2213db1c9bd5badebafdfb8290ca9f78d4b9ee2a3db4d79" url: "https://pub.dev" source: hosted - version: "4.2.0" + version: "5.0.1" package_info_plus_platform_interface: dependency: transitive description: @@ -729,18 +740,10 @@ packages: dependency: transitive description: name: petitparser - sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 url: "https://pub.dev" source: hosted - version: "5.4.0" - pigeon: - dependency: transitive - description: - name: pigeon - sha256: "5a79fd0b10423f6b5705525e32015597f861c31220b522a67d1e6b580da96719" - url: "https://pub.dev" - source: hosted - version: "11.0.1" + version: "6.0.2" platform: dependency: transitive description: @@ -761,19 +764,10 @@ packages: dependency: "direct main" description: name: provider - sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" - url: "https://pub.dev" - source: hosted - version: "6.1.1" - - pub_semver: - dependency: transitive - description: - name: pub_semver - sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "6.1.2" rxdart: dependency: transitive description: @@ -959,10 +953,10 @@ packages: dependency: transitive description: name: url_launcher - sha256: c512655380d241a337521703af62d2c122bf7b77a46ff7dd750092aa9433499c + sha256: "0ecc004c62fd3ed36a2ffcbe0dd9700aee63bd7532d0b642a488b1ec310f492e" url: "https://pub.dev" source: hosted - version: "6.2.4" + version: "6.2.5" url_launcher_android: dependency: transitive description: @@ -975,10 +969,10 @@ packages: dependency: transitive description: name: url_launcher_ios - sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03" + sha256: "9149d493b075ed740901f3ee844a38a00b33116c7c5c10d7fb27df8987fb51d5" url: "https://pub.dev" source: hosted - version: "6.2.4" + version: "6.2.5" url_launcher_linux: dependency: transitive description: @@ -1007,10 +1001,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "7fd2f55fe86cea2897b963e864dc01a7eb0719ecc65fcef4c1cc3d686d718bb2" + sha256: fff0932192afeedf63cdd50ecbb1bc825d31aed259f02bb8dba0f3b729a5e88b url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.3" url_launcher_windows: dependency: transitive description: @@ -1023,10 +1017,10 @@ packages: dependency: transitive description: name: uuid - sha256: "22c94e5ad1e75f9934b766b53c742572ee2677c56bc871d850a57dad0f82127f" + sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8 url: "https://pub.dev" source: hosted - version: "4.2.2" + version: "4.3.3" vector_graphics: dependency: transitive description: @@ -1079,10 +1073,10 @@ packages: dependency: transitive description: name: video_player_avfoundation - sha256: bc923884640d6dc403050586eb40713cdb8d1d84e6886d8aca50ab04c59124c2 + sha256: "309e3962795e761be010869bae65c0b0e45b5230c5cee1bec72197ca7db040ed" url: "https://pub.dev" source: hosted - version: "2.5.2" + version: "2.5.6" video_player_platform_interface: dependency: transitive description: @@ -1115,14 +1109,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" - watcher: - dependency: transitive - description: - name: watcher - sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" - url: "https://pub.dev" - source: hosted - version: "1.1.0" web: dependency: transitive description: @@ -1130,15 +1116,15 @@ packages: sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.1.4-beta" + version: "0.3.0" webview_flutter: dependency: transitive description: name: webview_flutter - sha256: d81b68e88cc353e546afb93fb38958e3717282c5ac6e5d3be4a4aef9fc3c1413 + sha256: "25e1b6e839e8cbfbd708abc6f85ed09d1727e24e08e08c6b8590d7c65c9a8932" url: "https://pub.dev" source: hosted - version: "4.5.0" + version: "4.7.0" webview_flutter_android: dependency: transitive description: @@ -1159,11 +1145,10 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "4d062ad505390ecef1c4bfb6001cd857a51e00912cc9dfb66edb1886a9ebd80c" + sha256: "9bf168bccdf179ce90450b5f37e36fe263f591c9338828d6bf09b6f8d0f57f86" url: "https://pub.dev" source: hosted - version: "3.10.2" - version: "0.3.0" + version: "3.12.0" win32: dependency: transitive description: @@ -1184,18 +1169,10 @@ packages: dependency: transitive description: name: xml - sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 url: "https://pub.dev" source: hosted - version: "6.3.0" - yaml: - dependency: transitive - description: - name: yaml - sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" - url: "https://pub.dev" - source: hosted - version: "3.1.2" + version: "6.5.0" sdks: - dart: ">=3.2.0 <4.0.0" - flutter: ">=3.16.0" + dart: ">=3.2.3 <4.0.0" + flutter: ">=3.16.6" diff --git a/pubspec.yaml b/pubspec.yaml index 3987e28..824fdd3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -53,10 +53,7 @@ dependencies: socket_io_client: ^2.0.3+1 intl: ^0.19.0 flutter_widget_from_html: ^0.14.11 - intl: ^0.19.0 - flutter_rating_bar: ^4.0.1 - sms_otp_auto_verify: ^2.1.0 - socket_io_client: ^2.0.3+1 + dev_dependencies: diff --git a/windows/flutter/CMakeLists.txt b/windows/flutter/CMakeLists.txt index 930d207..903f489 100644 --- a/windows/flutter/CMakeLists.txt +++ b/windows/flutter/CMakeLists.txt @@ -10,6 +10,11 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # https://github.com/flutter/flutter/issues/57146. set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + # === Flutter Library === set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") @@ -92,7 +97,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - windows-x64 $ + ${FLUTTER_TARGET_PLATFORM} $ VERBATIM ) add_custom_target(flutter_assemble DEPENDS From 14370ba42a125996b13a30c29ea4ce949d3f1dba Mon Sep 17 00:00:00 2001 From: doann221 Date: Wed, 20 Mar 2024 19:37:49 +0700 Subject: [PATCH 2/4] fixed merge --- lib/API/api_address_user.dart | 7 +- lib/API/api_cart.dart | 1 - lib/API/api_image.dart | 8 +- lib/API/api_login.dart | 2 +- lib/API/api_order.dart | 25 +- lib/API/api_product.dart | 2 - lib/API/api_profile.dart | 3 +- lib/API/api_sign_up.dart | 4 +- lib/Pages/Screens/cart_screen.dart | 14 +- lib/Pages/Screens/main_screen.dart | 4 +- lib/Pages/Screens/noti_screen.dart | 5 +- lib/Pages/Screens/setting_screen.dart | 2 +- lib/Pages/Tabs/add_address._tap.dart | 12 +- lib/Pages/Tabs/cart_tab.dart | 2 +- lib/Pages/Tabs/cart_tap.dart | 1114 +++++++++-------- lib/Pages/Tabs/confirm_order.dart | 836 ++++++++----- lib/Pages/Tabs/information_user.dart | 35 +- .../Tabs/notification_after_login_tab.dart | 140 ++- lib/Pages/Tabs/order_detail.dart | 699 ++++++++++- lib/Pages/Tabs/order_user.dart | 603 ++++----- lib/Pages/Tabs/product_detail.dart | 43 +- lib/Pages/Tabs/reason_cancelled_order.dart | 212 ++++ lib/Pages/Tabs/user_profile.dart | 16 +- lib/Providers/token_manager.dart | 2 +- lib/Providers/user_provider.dart | 2 +- lib/Widgets/Address/button_in_address.dart | 6 +- lib/Widgets/Cart/open_diaolog_address.dart | 402 +++--- lib/Widgets/HomeScreen/category.dart | 3 +- lib/Widgets/HomeScreen/product_hot_sale.dart | 6 +- lib/Widgets/Login/button.dart | 6 +- lib/Widgets/ProductDetail/add_to_store.dart | 9 + lib/Widgets/ProductHome/in_frame.dart | 2 +- lib/main.dart | 3 +- lib/models/address_model.dart | 2 +- lib/models/order_model.dart | 15 +- .../{user_models.dart => user_model.dart} | 1 - lib/utils/constant.dart | 11 + lib/utils/snackbar.dart | 189 ++- 38 files changed, 2779 insertions(+), 1669 deletions(-) create mode 100644 lib/Pages/Tabs/reason_cancelled_order.dart rename lib/models/{user_models.dart => user_model.dart} (99%) diff --git a/lib/API/api_address_user.dart b/lib/API/api_address_user.dart index 8315b7a..ac6b1ea 100644 --- a/lib/API/api_address_user.dart +++ b/lib/API/api_address_user.dart @@ -18,7 +18,12 @@ class Address { ) async { try { var userProvider = Provider.of(context, listen: false); - String accessToken = userProvider.user.accessToken; + var accessToken = + Provider.of(context, listen: false).user.accessToken; + if (accessToken.isEmpty) { + final newAccessToken = await AuthLogin.getAccessToken(); + accessToken = newAccessToken!; + } List allAddress = userProvider.user.address; allAddress.add(address); http.Response res = await http.patch( diff --git a/lib/API/api_cart.dart b/lib/API/api_cart.dart index 77b2960..2c9c14f 100644 --- a/lib/API/api_cart.dart +++ b/lib/API/api_cart.dart @@ -1,7 +1,6 @@ // ignore_for_file: use_build_context_synchronously import 'dart:convert'; - import 'package:flutter/material.dart'; import 'package:my_app/API/api_login.dart'; import 'package:my_app/Providers/user_provider.dart'; diff --git a/lib/API/api_image.dart b/lib/API/api_image.dart index bb07a48..9d730c3 100644 --- a/lib/API/api_image.dart +++ b/lib/API/api_image.dart @@ -1,19 +1,17 @@ // ignore: avoid_web_libraries_in_flutter - +// ignore: depend_on_referenced_packages // ignore_for_file: use_build_context_synchronously import 'dart:convert'; import 'dart:io'; - import 'package:flutter/material.dart'; import 'package:my_app/API/api_login.dart'; import 'package:my_app/Providers/user_provider.dart'; import 'package:http/http.dart' as http; -import 'package:my_app/models/user_models.dart'; +import 'package:my_app/models/user_model.dart'; import 'package:my_app/utils/constant.dart'; import 'package:my_app/utils/snackbar.dart'; import 'package:provider/provider.dart'; -// ignore: depend_on_referenced_packages import 'package:http_parser/http_parser.dart'; class Avatar { @@ -53,7 +51,7 @@ class Avatar { return null; } } catch (e) { - showSnackBarError(context, 'allololl'); + showSnackBarError(context, 'loi o trong file nay'); return null; } } diff --git a/lib/API/api_login.dart b/lib/API/api_login.dart index 6144e27..a3d3fa1 100644 --- a/lib/API/api_login.dart +++ b/lib/API/api_login.dart @@ -49,7 +49,7 @@ class AuthLogin { json.decode(res.body)['firstName'], json.decode(res.body)['lastName']); Navigator.of(context).pushAndRemoveUntil( - MaterialPageRoute(builder: (context) => const MainScreen()), + MaterialPageRoute(builder: (context) => MainScreen()), (route) => false); }, ); diff --git a/lib/API/api_order.dart b/lib/API/api_order.dart index 69901be..be02029 100644 --- a/lib/API/api_order.dart +++ b/lib/API/api_order.dart @@ -32,7 +32,7 @@ class OrderApi { {"productId": e.productId, "quantity": e.quantity, "sku": e.sku}) .toList(); http.Response res = await http.post( - Uri.parse('${uri}order'), + Uri.parse('${uri}orders'), body: jsonEncode({ "paymentMethod": paymentMethod, "addressSelected": addressSelected, @@ -78,7 +78,7 @@ class OrderApi { }); http.Response res = await http.post( - Uri.parse('${uri}order/review'), + Uri.parse('${uri}orders/review'), body: bodyData, headers: { 'Authorization': 'Bearer $accessToken', @@ -109,7 +109,6 @@ class OrderApi { BuildContext context, String orderStatus) async { OrderResponse orederResPonse = OrderResponse( page: 1, pageSize: 5, totalPage: 11, totalRecord: 11, data: []); - var userId = Provider.of(context, listen: false).user.id; try { var accessToken = Provider.of(context, listen: false).user.accessToken; @@ -118,11 +117,14 @@ class OrderApi { accessToken = newAccessToken!; } http.Response res = await http.get( - Uri.parse('${uri}orders-mnt?userId=$userId&orderStatus=$orderStatus'), + Uri.parse('${uri}orders?&orderStatus=$orderStatus'), headers: { 'Authorization': 'Bearer $accessToken', }, ); + if (res.statusCode == 404) { + return orederResPonse; + } httpErrorHandle( response: res, context: context, @@ -134,13 +136,13 @@ class OrderApi { }, ); } catch (e) { - // showSnackBarError(context, e.toString()); + showSnackBarError(context, e.toString()); } return orederResPonse; } Future cancelOrder(BuildContext context, - {required String orderId, required String reaSon}) async { + {required String orderId, required String reaSonCancelled}) async { try { var accessToken = Provider.of(context, listen: false).user.accessToken; @@ -148,11 +150,12 @@ class OrderApi { final newAccessToken = await AuthLogin.getAccessToken(); accessToken = newAccessToken!; } - http.Response res = await http - .put(Uri.parse('${uri}orders-mnt/$orderId/cancel'), headers: { + + http.Response res = + await http.put(Uri.parse('${uri}orders/$orderId/cancel'), headers: { 'Authorization': 'Bearer $accessToken', }, body: { - "cancelReason": reaSon + "cancelReason": reaSonCancelled, }); httpErrorHandle( response: res, @@ -162,6 +165,8 @@ class OrderApi { showSnackBarSuccess(context, 'Thanh cong'); }, ); - } catch (e) {} + } catch (e) { + showSnackBarError(context, e.toString()); + } } } diff --git a/lib/API/api_product.dart b/lib/API/api_product.dart index 7e0e0f1..c28183c 100644 --- a/lib/API/api_product.dart +++ b/lib/API/api_product.dart @@ -1,5 +1,4 @@ import 'dart:convert'; - import 'package:http/http.dart' as http; import 'package:my_app/models/product_model.dart'; @@ -10,7 +9,6 @@ class ProductAPI { final url = 'https://api.techcell.cloud/products?select_type=only_active'; final uri = Uri.parse(url); final response = await http.get(uri); - List result = []; try { diff --git a/lib/API/api_profile.dart b/lib/API/api_profile.dart index a3cf815..b089f0c 100644 --- a/lib/API/api_profile.dart +++ b/lib/API/api_profile.dart @@ -5,7 +5,8 @@ import 'package:http/http.dart' as http; import 'package:my_app/API/api_login.dart'; import 'package:my_app/Providers/token_manager.dart'; import 'package:my_app/Providers/user_provider.dart'; -import 'package:my_app/models/user_models.dart'; + +import 'package:my_app/models/user_model.dart'; import 'package:my_app/utils/constant.dart'; import 'package:my_app/utils/snackbar.dart'; import 'package:provider/provider.dart'; diff --git a/lib/API/api_sign_up.dart b/lib/API/api_sign_up.dart index d1aed11..b52e1c2 100644 --- a/lib/API/api_sign_up.dart +++ b/lib/API/api_sign_up.dart @@ -74,7 +74,7 @@ class AuthSignUp { }, ); } catch (e) { - showSnackBarError(context, 'loi cho nay'); + showSnackBarError(context, e.toString()); } } @@ -97,7 +97,7 @@ class AuthSignUp { }, ); } catch (e) { - showSnackBarError(context, 'loi cho nay'); + showSnackBarError(context, e.toString()); } } diff --git a/lib/Pages/Screens/cart_screen.dart b/lib/Pages/Screens/cart_screen.dart index bc08e8e..c791a0a 100644 --- a/lib/Pages/Screens/cart_screen.dart +++ b/lib/Pages/Screens/cart_screen.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:my_app/API/api_login.dart'; import 'package:my_app/Pages/Tabs/cart_tap.dart'; +import 'package:my_app/Pages/Tabs/login_tap.dart'; +import 'package:my_app/Providers/token_manager.dart'; +import 'package:my_app/models/user_model.dart'; class CartScreen extends StatefulWidget { const CartScreen({super.key}); @@ -13,11 +15,11 @@ class _CartScreenState extends State { @override Widget build(BuildContext context) { return Scaffold( - body: FutureBuilder( - future: AuthLogin.getAccessToken(), - builder: (context, snapshot) { - if (snapshot.data == null) { - return Container(); + body: FutureBuilder( + future: TokenManager.getUserfromStorage(), + builder: (context, snapshoot) { + if (snapshoot.data == null) { + return LoginTap(); } else { return CartTap(); } diff --git a/lib/Pages/Screens/main_screen.dart b/lib/Pages/Screens/main_screen.dart index 056628a..962fd0e 100644 --- a/lib/Pages/Screens/main_screen.dart +++ b/lib/Pages/Screens/main_screen.dart @@ -35,8 +35,8 @@ class _MainScreenState extends State { padding: EdgeInsets.symmetric(horizontal: 15, vertical: 8), child: GNav( gap: 4, - backgroundColor: Colors.white.withOpacity(0.8), - color: Colors.black.withOpacity(0.6), + backgroundColor: Colors.white, + color: Colors.black, activeColor: Colors.white, tabBackgroundColor: primaryColors, padding: EdgeInsets.all(16), diff --git a/lib/Pages/Screens/noti_screen.dart b/lib/Pages/Screens/noti_screen.dart index 3dbc02f..895e071 100644 --- a/lib/Pages/Screens/noti_screen.dart +++ b/lib/Pages/Screens/noti_screen.dart @@ -1,7 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:my_app/Pages/Tabs/login_tap.dart'; import 'package:my_app/Pages/Tabs/notification_after_login_tab.dart'; import 'package:my_app/Providers/token_manager.dart'; -import 'package:my_app/models/user_models.dart'; +import 'package:my_app/models/user_model.dart'; class NotiScreen extends StatefulWidget { const NotiScreen({super.key}); @@ -18,7 +19,7 @@ class _NotiScreenState extends State { future: TokenManager.getUserfromStorage(), builder: (context, snapshoot) { if (snapshoot.data == null) { - return Container(); + return LoginTap(); } else { return NotificationAfterLoginTab(); } diff --git a/lib/Pages/Screens/setting_screen.dart b/lib/Pages/Screens/setting_screen.dart index eba7136..7f70790 100644 --- a/lib/Pages/Screens/setting_screen.dart +++ b/lib/Pages/Screens/setting_screen.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:my_app/Pages/Tabs/login_tap.dart'; import 'package:my_app/Pages/Tabs/user_profile.dart'; import 'package:my_app/Providers/token_manager.dart'; -import 'package:my_app/models/user_models.dart'; +import 'package:my_app/models/user_model.dart'; class SettingScreen extends StatefulWidget { const SettingScreen({super.key}); diff --git a/lib/Pages/Tabs/add_address._tap.dart b/lib/Pages/Tabs/add_address._tap.dart index 557076d..90cabd3 100644 --- a/lib/Pages/Tabs/add_address._tap.dart +++ b/lib/Pages/Tabs/add_address._tap.dart @@ -32,6 +32,7 @@ class _AddAddressTapState extends State { //giúp hiện các widget sau khi chọn ở trên bool isProvinceSelected = false; bool isDistrictSelected = false; + bool isDefaul = false; void addAddress() { if (_formKey.currentState!.validate()) { @@ -51,7 +52,7 @@ class _AddAddressTapState extends State { wardCode: selectedWards!.wardCode, wardName: selectedWards!.wardName), detail: detailController.text, - isDefault: false, + isDefault: isDefaul, ), ); } @@ -250,9 +251,12 @@ class _AddAddressTapState extends State { validate: (value) => Validator.validateText(value ?? ''), ), const SizedBox(height: 50), - ButtonInAddress( - functionAddress: addAddress, - textInAddress: 'Thêm địa chỉ', + Padding( + padding: const EdgeInsets.all(8.0), + child: ButtonInAddress( + functionAddress: addAddress, + textInAddress: 'Thêm địa chỉ', + ), ) ], ), diff --git a/lib/Pages/Tabs/cart_tab.dart b/lib/Pages/Tabs/cart_tab.dart index 0cb5ab1..1ad03f5 100644 --- a/lib/Pages/Tabs/cart_tab.dart +++ b/lib/Pages/Tabs/cart_tab.dart @@ -310,7 +310,7 @@ class _CartTabState extends State { ), ), Padding( - padding: const EdgeInsets.all(8.0), + padding: EdgeInsets.all(50), child: ButtonSendrequest( text: "Xác nhận", submit: getReviewOder, diff --git a/lib/Pages/Tabs/cart_tap.dart b/lib/Pages/Tabs/cart_tap.dart index 9405365..2c9934d 100644 --- a/lib/Pages/Tabs/cart_tap.dart +++ b/lib/Pages/Tabs/cart_tap.dart @@ -1,16 +1,18 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:my_app/API/api_cart.dart'; -import 'package:my_app/API/api_order.dart'; +import 'package:my_app/API/api_product.dart'; +import 'package:my_app/Pages/Tabs/product_detail.dart'; import 'package:my_app/Providers/product_provider.dart'; import 'package:my_app/Widgets/Cart/open_diaolog_address.dart'; import 'package:my_app/Pages/Tabs/add_address._tap.dart'; import 'package:my_app/Pages/Tabs/change_address.dart'; +import 'package:my_app/Providers/product_provider.dart'; import 'package:my_app/Providers/user_provider.dart'; import 'package:my_app/Widgets/Login/button.dart'; -import 'package:my_app/models/address_model.dart'; import 'package:my_app/models/cart_model.dart'; +import 'package:my_app/models/product_model.dart'; import 'package:my_app/utils/constant.dart'; +import 'package:my_app/utils/snackbar.dart'; import 'package:provider/provider.dart'; class CartTap extends StatefulWidget { @@ -45,6 +47,7 @@ class _CartTapState extends State { sku: productCart.product[index].sku, quantity: productCart.product[index].quantity, ); + showSnackBarSuccess(context, 'Thành công'); } void deCrementQuantity(int index) { @@ -61,6 +64,7 @@ class _CartTapState extends State { sku: productCart.product[index].sku, quantity: productCart.product[index].quantity, ); + showSnackBarSuccess(context, 'Thành công'); } void deleteCart(int index) { @@ -70,6 +74,7 @@ class _CartTapState extends State { sku: productCart.product[index].sku, quantity: 0, ); + showSnackBarSuccess(context, 'Xóa thành công'); } double getTotalAmount() { @@ -88,14 +93,6 @@ class _CartTapState extends State { return total; } - void getReviewOder() { - OrderApi().reviewOrder( - context: context, - addressSelected: valueChecked, - productSelected: (productCart.product), - ); - } - @override void initState() { super.initState(); @@ -130,7 +127,6 @@ class _CartTapState extends State { controller: scrollController, child: Container( padding: EdgeInsets.all(10), - // decoration: BoxDecoration(color: Color(0xFFEDECF2)), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -169,6 +165,7 @@ class _CartTapState extends State { width: 10, child: Checkbox( value: selectAll, + activeColor: primaryColors, onChanged: (bool? value) { setState(() { selectAll = value ?? false; @@ -198,294 +195,629 @@ class _CartTapState extends State { itemCount: productCart.product.length, itemBuilder: (context, indexCart) { final itemCart = productCart.product[indexCart]; - final productProvider = - Provider.of(context, listen: false).products; - return Container( - child: ListView.builder( - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - scrollDirection: Axis.vertical, - itemCount: productProvider.length, - itemBuilder: (context, indexProduct) { - final itemProduct = productProvider[indexProduct]; - if (itemCart.productId == itemProduct.id) { - return Dismissible( - key: Key(itemCart.productId), - direction: DismissDirection.endToStart, - onDismissed: (direction) { - deleteCart(indexCart); - }, - background: Container( - color: Colors.red, - alignment: Alignment.centerRight, - child: Center( - child: Icon( - Icons.delete, - color: Colors.white, - size: 40, - ), - ), - ), - child: Container( - width: 400, - padding: EdgeInsets.symmetric(vertical: 20), - margin: EdgeInsets.symmetric(vertical: 5), - decoration: BoxDecoration( - color: Color.fromARGB(255, 240, 239, 239), - borderRadius: BorderRadius.circular(10), - ), - child: Row( - children: [ - Padding( - padding: EdgeInsets.symmetric(horizontal: 10), - child: SizedBox( - width: 10, - child: Checkbox( - value: productSelected[indexCart], - onChanged: (bool? value) { - setState(() { - productSelected[indexCart] = - value ?? false; - if (!value!) { - selectAll = false; - } else { - selectAll = productSelected.every( - (isSelected) => isSelected); - } - }); - }, - ), + return FutureBuilder>( + future: ProductAPI().getAllProducts(), + builder: (context, snapshot) { + if ((snapshot.hasError) || (!snapshot.hasData)) { + return Padding( + padding: EdgeInsets.all(15), + child: Center( + child: CircularProgressIndicator(), + ), + ); + } + + List? products = snapshot.data; + return Container( + child: ListView.builder( + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + scrollDirection: Axis.vertical, + itemCount: products?.length, + itemBuilder: (context, indexProduct) { + final itemProduct = products?[indexProduct]; + if (itemCart.productId == itemProduct!.id) { + return Dismissible( + key: Key(itemCart.productId), + direction: DismissDirection.endToStart, + onDismissed: (direction) { + deleteCart(indexCart); + }, + background: Container( + color: Colors.red, + alignment: Alignment.centerRight, + child: Center( + child: Icon( + Icons.delete, + color: Colors.white, + size: 40, ), ), - Expanded( - child: ListView.builder( - shrinkWrap: true, - scrollDirection: Axis.vertical, - physics: NeverScrollableScrollPhysics(), - itemCount: itemProduct.variations.length, - itemBuilder: (context, indexVariation) { - final variation = - itemProduct.variations[indexVariation]; + ), + child: Container( + width: 400, + padding: EdgeInsets.symmetric(vertical: 10), + margin: EdgeInsets.symmetric(vertical: 5), + decoration: BoxDecoration( + color: Color.fromARGB(255, 240, 239, 239), + borderRadius: BorderRadius.circular(10), + ), + child: Row( + children: [ + Padding( + padding: + EdgeInsets.symmetric(horizontal: 10), + child: SizedBox( + width: 15, + child: Checkbox( + activeColor: primaryColors, + value: productSelected[indexCart], + onChanged: (bool? value) { + setState(() { + productSelected[indexCart] = + value ?? false; + if (!value!) { + selectAll = false; + } else { + selectAll = productSelected.every( + (isSelected) => isSelected); + } + }); + }, + ), + ), + ), + Expanded( + child: ListView.builder( + shrinkWrap: true, + scrollDirection: Axis.vertical, + physics: NeverScrollableScrollPhysics(), + itemCount: itemProduct.variations.length, + itemBuilder: (context, indexVariation) { + final variation = itemProduct + .variations[indexVariation]; - if (itemCart.sku == variation.sku) { - return Row( - children: [ - Container( - height: 120, - width: 120, - child: ListView.builder( - scrollDirection: Axis.horizontal, - itemCount: - variation.images.length, - itemBuilder: (context, index) { - final image = - variation.images[index]; - if (image.isThumbnail == true) { - return Image( - image: NetworkImage( - '${image.url}'), - ); - } else if (index == 0) { - return Image( - image: NetworkImage( - '${image.url}'), - ); - } - return Container(); - }, - ), - ), - SizedBox(width: 5), - Column( - crossAxisAlignment: - CrossAxisAlignment.start, + if (itemCart.sku == variation.sku) { + return Row( children: [ - Container( - width: 220, - child: Text( - '${itemProduct.name}', - overflow: - TextOverflow.ellipsis, - maxLines: 1, - style: TextStyle( - color: Colors.black, - fontSize: 18, - fontWeight: FontWeight.w400, + InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + ProductDetail( + productDetail: + itemProduct), + ), + ); + }, + child: Container( + height: 120, + width: 120, + child: ListView.builder( + scrollDirection: + Axis.horizontal, + itemCount: + variation.images.length, + itemBuilder: + (context, index) { + final image = variation + .images[index]; + if (image.isThumbnail == + true) { + return Image( + image: NetworkImage( + '${image.url}'), + ); + } else if (index == 0) { + return Image( + image: NetworkImage( + '${image.url}'), + ); + } + return Container(); + }, ), ), ), - SizedBox(height: 5), - Row( + SizedBox(width: 5), + Column( + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - Text('Phân loại:'), Container( - height: - 15, // Adjust the height as needed - width: 150, - child: ListView.builder( - scrollDirection: - Axis.horizontal, - itemCount: variation - .attributes.length, - itemBuilder: - (context, index) { - final attribute = - variation - .attributes[ - index]; - return Text( - ' ${attribute.v.toUpperCase()}${attribute.u ?? ''}', - ); - }, - ), - ), - ], - ), - SizedBox(height: 5), - Row( - children: [ - Text( - '${formatCurrency.format(variation.price.special)}', - style: TextStyle( - color: Colors.red, - fontWeight: - FontWeight.w500, - fontSize: 16, - ), - ), - SizedBox(width: 5), - Text( - '-', - style: TextStyle( - color: Colors.grey - .withOpacity(1), - fontWeight: - FontWeight.w500, - fontSize: 16, - ), - ), - SizedBox(width: 5), - Text( - '${formatCurrency.format(variation.price.base)}', - style: TextStyle( - color: Colors.grey - .withOpacity(1), - fontWeight: - FontWeight.w400, - decoration: TextDecoration - .lineThrough, - fontSize: 16, + width: 220, + child: Text( + '${itemProduct.name}', + overflow: + TextOverflow.ellipsis, + maxLines: 1, + style: TextStyle( + color: Colors.black, + fontSize: 18, + fontWeight: + FontWeight.w400, + ), ), ), - ], - ), - SizedBox(height: 5), - Row( - children: [ - InkWell( - onTap: () { - deCrementQuantity( - indexCart); - }, - child: Container( - decoration: BoxDecoration( - border: Border.all( - color: - Colors.redAccent, - width: 0.5, + SizedBox(height: 5), + Row( + children: [ + Text('Phân loại:'), + Container( + height: + 15, // Adjust the height as needed + width: 150, + child: ListView.builder( + scrollDirection: + Axis.horizontal, + itemCount: variation + .attributes + .length, + itemBuilder: + (context, index) { + final attribute = + variation + .attributes[ + index]; + return Text( + ' ${attribute.v.toUpperCase()}${attribute.u ?? ''}', + ); + }, ), - color: Colors.white, - borderRadius: - BorderRadius - .circular(0), ), - child: Padding( - padding: EdgeInsets - .symmetric( - horizontal: 5, - vertical: 2), - child: Icon( - Icons.remove, + ], + ), + SizedBox(height: 5), + Row( + children: [ + Text( + '${formatCurrency.format(variation.price.special)}', + style: TextStyle( color: Colors.red, + fontWeight: + FontWeight.w500, + fontSize: 16, ), ), - ), - ), - Container( - padding: EdgeInsets.all(2), - decoration: BoxDecoration( - border: Border.all( - color: Colors.redAccent, - width: 0.5, + SizedBox(width: 5), + Text( + '-', + style: TextStyle( + color: Colors.grey + .withOpacity(1), + fontWeight: + FontWeight.w500, + fontSize: 16, + ), ), - color: Colors.white, - borderRadius: - BorderRadius.circular( - 0), - ), - child: Padding( - padding: - EdgeInsets.symmetric( - horizontal: 10, - vertical: 2.5), - child: Text( - '${itemCart.quantity.toString()}', + SizedBox(width: 5), + Text( + '${formatCurrency.format(variation.price.base)}', style: TextStyle( + color: Colors.grey + .withOpacity(1), + fontWeight: + FontWeight.w400, + decoration: + TextDecoration + .lineThrough, fontSize: 16, - color: Colors.black, ), ), - ), + ], ), - InkWell( - onTap: () { - inCrementQuantity( - indexCart); - }, - child: Container( - decoration: BoxDecoration( - border: Border.all( - color: - Colors.redAccent, - width: 0.5, + SizedBox(height: 5), + Row( + children: [ + InkWell( + onTap: () { + deCrementQuantity( + indexCart); + }, + child: Container( + decoration: + BoxDecoration( + border: Border.all( + color: Colors + .redAccent, + width: 0.5, + ), + color: Colors.white, + borderRadius: + BorderRadius + .circular( + 0), + ), + child: Padding( + padding: EdgeInsets + .symmetric( + horizontal: + 5, + vertical: + 2), + child: Icon( + Icons.remove, + color: Colors.red, + ), + ), ), - color: Colors.white, - borderRadius: - BorderRadius - .circular(0), ), - child: Padding( - padding: EdgeInsets - .symmetric( - horizontal: 5, - vertical: 2), - child: Icon( - Icons.add, - color: Colors.red, + Container( + padding: + EdgeInsets.all(2), + decoration: + BoxDecoration( + border: Border.all( + color: Colors + .redAccent, + width: 0.5, + ), + color: Colors.white, + borderRadius: + BorderRadius + .circular(0), + ), + child: Padding( + padding: EdgeInsets + .symmetric( + horizontal: + 10, + vertical: + 2.5), + child: Text( + '${itemCart.quantity.toString()}', + style: TextStyle( + fontSize: 16, + color: + Colors.black, + ), + ), ), ), - ), + InkWell( + onTap: () { + inCrementQuantity( + indexCart); + }, + child: Container( + decoration: + BoxDecoration( + border: Border.all( + color: Colors + .redAccent, + width: 0.5, + ), + color: Colors.white, + borderRadius: + BorderRadius + .circular( + 0), + ), + child: Padding( + padding: EdgeInsets + .symmetric( + horizontal: + 5, + vertical: + 2), + child: Icon( + Icons.add, + color: Colors.red, + ), + ), + ), + ), + ], ), ], ), ], - ), - ], - ); - } - return Container(); - }, - ), + ); + } + return Container(); + }, + ), + ), + ], ), - ], - ), - ), - ); - } - return Container(); - }, - ), + ), + ); + } + return Container(); + }, + ), + ); + }, ); + // Container( + // child: ListView.builder( + // shrinkWrap: true, + // physics: NeverScrollableScrollPhysics(), + // scrollDirection: Axis.vertical, + // itemCount: productProvider.length, + // itemBuilder: (context, indexProduct) { + // final itemProduct = productProvider[indexProduct]; + // if (itemCart.productId == itemProduct.id) { + // return Dismissible( + // key: Key(itemCart.productId), + // direction: DismissDirection.endToStart, + // onDismissed: (direction) { + // deleteCart(indexCart); + // }, + // background: Container( + // color: Colors.red, + // alignment: Alignment.centerRight, + // child: Center( + // child: Icon( + // Icons.delete, + // color: Colors.white, + // size: 40, + // ), + // ), + // ), + // child: Container( + // width: 400, + // padding: EdgeInsets.symmetric(vertical: 10), + // margin: EdgeInsets.symmetric(vertical: 5), + // decoration: BoxDecoration( + // color: Color.fromARGB(255, 240, 239, 239), + // borderRadius: BorderRadius.circular(10), + // ), + // child: Row( + // children: [ + // Padding( + // padding: EdgeInsets.symmetric(horizontal: 10), + // child: SizedBox( + // width: 10, + // child: Checkbox( + // activeColor: primaryColors, + // value: productSelected[indexCart], + // onChanged: (bool? value) { + // setState(() { + // productSelected[indexCart] = + // value ?? false; + // if (!value!) { + // selectAll = false; + // } else { + // selectAll = productSelected.every( + // (isSelected) => isSelected); + // } + // }); + // }, + // ), + // ), + // ), + // Expanded( + // child: ListView.builder( + // shrinkWrap: true, + // scrollDirection: Axis.vertical, + // physics: NeverScrollableScrollPhysics(), + // itemCount: itemProduct.variations.length, + // itemBuilder: (context, indexVariation) { + // final variation = + // itemProduct.variations[indexVariation]; + + // if (itemCart.sku == variation.sku) { + // return Row( + // children: [ + // Container( + // height: 120, + // width: 120, + // child: ListView.builder( + // scrollDirection: Axis.horizontal, + // itemCount: + // variation.images.length, + // itemBuilder: (context, index) { + // final image = + // variation.images[index]; + // if (image.isThumbnail == true) { + // return Image( + // image: NetworkImage( + // '${image.url}'), + // ); + // } else if (index == 0) { + // return Image( + // image: NetworkImage( + // '${image.url}'), + // ); + // } + // return Container(); + // }, + // ), + // ), + // SizedBox(width: 5), + // Column( + // crossAxisAlignment: + // CrossAxisAlignment.start, + // children: [ + // Container( + // width: 220, + // child: Text( + // '${itemProduct.name}', + // overflow: + // TextOverflow.ellipsis, + // maxLines: 1, + // style: TextStyle( + // color: Colors.black, + // fontSize: 18, + // fontWeight: FontWeight.w400, + // ), + // ), + // ), + // SizedBox(height: 5), + // Row( + // children: [ + // Text('Phân loại:'), + // Container( + // height: + // 15, // Adjust the height as needed + // width: 150, + // child: ListView.builder( + // scrollDirection: + // Axis.horizontal, + // itemCount: variation + // .attributes.length, + // itemBuilder: + // (context, index) { + // final attribute = + // variation + // .attributes[ + // index]; + // return Text( + // ' ${attribute.v.toUpperCase()}${attribute.u ?? ''}', + // ); + // }, + // ), + // ), + // ], + // ), + // SizedBox(height: 5), + // Row( + // children: [ + // Text( + // '${formatCurrency.format(variation.price.special)}', + // style: TextStyle( + // color: Colors.red, + // fontWeight: + // FontWeight.w500, + // fontSize: 16, + // ), + // ), + // SizedBox(width: 5), + // Text( + // '-', + // style: TextStyle( + // color: Colors.grey + // .withOpacity(1), + // fontWeight: + // FontWeight.w500, + // fontSize: 16, + // ), + // ), + // SizedBox(width: 5), + // Text( + // '${formatCurrency.format(variation.price.base)}', + // style: TextStyle( + // color: Colors.grey + // .withOpacity(1), + // fontWeight: + // FontWeight.w400, + // decoration: TextDecoration + // .lineThrough, + // fontSize: 16, + // ), + // ), + // ], + // ), + // SizedBox(height: 5), + // Row( + // children: [ + // InkWell( + // onTap: () { + // deCrementQuantity( + // indexCart); + // }, + // child: Container( + // decoration: BoxDecoration( + // border: Border.all( + // color: + // Colors.redAccent, + // width: 0.5, + // ), + // color: Colors.white, + // borderRadius: + // BorderRadius + // .circular(0), + // ), + // child: Padding( + // padding: EdgeInsets + // .symmetric( + // horizontal: 5, + // vertical: 2), + // child: Icon( + // Icons.remove, + // color: Colors.red, + // ), + // ), + // ), + // ), + // Container( + // padding: EdgeInsets.all(2), + // decoration: BoxDecoration( + // border: Border.all( + // color: Colors.redAccent, + // width: 0.5, + // ), + // color: Colors.white, + // borderRadius: + // BorderRadius.circular( + // 0), + // ), + // child: Padding( + // padding: + // EdgeInsets.symmetric( + // horizontal: 10, + // vertical: 2.5), + // child: Text( + // '${itemCart.quantity.toString()}', + // style: TextStyle( + // fontSize: 16, + // color: Colors.black, + // ), + // ), + // ), + // ), + // InkWell( + // onTap: () { + // inCrementQuantity( + // indexCart); + // }, + // child: Container( + // decoration: BoxDecoration( + // border: Border.all( + // color: + // Colors.redAccent, + // width: 0.5, + // ), + // color: Colors.white, + // borderRadius: + // BorderRadius + // .circular(0), + // ), + // child: Padding( + // padding: EdgeInsets + // .symmetric( + // horizontal: 5, + // vertical: 2), + // child: Icon( + // Icons.add, + // color: Colors.red, + // ), + // ), + // ), + // ), + // ], + // ), + // ], + // ), + // ], + // ); + // } + // return Container(); + // }, + // ), + // ), + // ], + // ), + // ), + // ); + // } + // return Container(); + // }, + // ), + // ); }, ), ), @@ -533,242 +865,28 @@ class _CartTapState extends State { ), ), Padding( - padding: EdgeInsets.all(10), + padding: EdgeInsets.all(15), child: ButtonSendrequest( - text: 'Thanh toán', + text: 'Mua hàng', submit: () { - showModalBottomSheet( - context: context, - isScrollControlled: true, - builder: (context) => OpenDialogAddreess( - productSelected: productSelected, - productCart: productCart.product, - ), - ); + + if (productSelected.contains(true)) { + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) => OpenDialogAddreess( + productSelected: productSelected, + productCart: productCart.product, + ), + ); + } else { + showSnackBarError(context, 'Bạn chưa chọn sản phẩm'); + } }, ), - ) + ), ], ), ); } - - openDiaologAddress() { - return showModalBottomSheet( - context: context, - builder: (context) { - List addressUser = - Provider.of(context, listen: false).user.address; - return Column( - children: [ - Expanded( - child: ListView.builder( - itemCount: addressUser.length, - itemBuilder: (context, index) { - return Column( - children: [ - Container( - decoration: BoxDecoration( - color: Colors.white, - border: Border( - bottom: BorderSide( - color: Colors.grey.withOpacity(0.5), - width: 1, - ), - ), - ), - padding: const EdgeInsets.only(top: 10, bottom: 10), - child: Row( - children: [ - Radio( - activeColor: primaryColors, - value: index, - groupValue: valueChecked, - onChanged: (val) { - setState( - () { - valueChecked = val!; - }, - ); - }, - ), - Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only( - left: 10.0, bottom: 5), - child: Row( - children: [ - Container( - constraints: BoxConstraints( - maxWidth: MediaQuery.of(context) - .size - .width * - 0.5), - child: Text( - addressUser[index].customerName, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ), - const SizedBox(width: 15), - const SizedBox( - height: 18, - child: VerticalDivider( - color: Colors.black, - thickness: 1, - ), - ), - SizedBox( - width: MediaQuery.of(context) - .size - .width * - 0.3, - child: Text( - addressUser[index].phoneNumbers, - style: const TextStyle( - color: Colors.grey, - fontSize: 16, - fontWeight: FontWeight.w500, - ), - ), - ) - ], - ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only( - left: 10.0, top: 5), - child: Text( - addressUser[index].detail, - style: const TextStyle( - color: Colors.grey, - fontSize: 14, - fontWeight: FontWeight.w500, - ), - ), - ), - ], - ), - Padding( - padding: const EdgeInsets.all(10.0), - child: Text( - '${addressUser[index].wardLevel.wardName}, ', - style: const TextStyle( - color: Colors.grey, - fontSize: 14, - fontWeight: FontWeight.w500, - ), - ), - ), - Padding( - padding: const EdgeInsets.only(left: 10.0), - child: Row( - children: [ - Text( - '${addressUser[index].districtLevel.district_name}, ', - style: const TextStyle( - color: Colors.grey, - fontSize: 14, - fontWeight: FontWeight.w500, - ), - ), - Text( - addressUser[index] - .provinceLevel - .province_name, - style: const TextStyle( - color: Colors.grey, - fontSize: 14, - fontWeight: FontWeight.w500, - ), - ), - ], - ), - ), - const SizedBox(height: 5), - ], - ), - const Spacer(), - TextButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: ((context) => ChangeAddress( - addressUser: addressUser[index], - index: index, - )), - ), - ); - }, - child: const Text( - 'Sửa', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w700, - color: primaryColors, - ), - ), - ), - ], - ), - ), - ], - ); - }, - ), - ), - InkWell( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const AddAddressTap())); - }, - child: Container( - padding: const EdgeInsets.only(top: 20, bottom: 20), - decoration: const BoxDecoration( - color: Colors.white, - ), - child: const Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - CupertinoIcons.add_circled, - size: 30, - color: primaryColors, - ), - SizedBox(width: 10), - Text( - 'Thêm Địa Chỉ Mới', - style: TextStyle( - color: primaryColors, - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - ], - ), - ), - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: ButtonSendrequest( - text: "Xác nhận", - submit: getReviewOder, - ), - ), - ], - ); - }); - } } diff --git a/lib/Pages/Tabs/confirm_order.dart b/lib/Pages/Tabs/confirm_order.dart index 151c328..f55a75e 100644 --- a/lib/Pages/Tabs/confirm_order.dart +++ b/lib/Pages/Tabs/confirm_order.dart @@ -2,12 +2,14 @@ import 'package:flutter/material.dart'; import 'package:my_app/API/api_order.dart'; +import 'package:my_app/Pages/Screens/main_screen.dart'; +import 'package:my_app/Providers/product_provider.dart'; import 'package:my_app/Providers/user_provider.dart'; import 'package:my_app/Widgets/Address/button_in_address.dart'; -import 'package:my_app/Widgets/Login/button.dart'; import 'package:my_app/models/address_model.dart'; import 'package:my_app/models/order_model.dart'; import 'package:my_app/utils/constant.dart'; +import 'package:my_app/utils/snackbar.dart'; import 'package:provider/provider.dart'; class ConfirmOrder extends StatefulWidget { @@ -25,6 +27,7 @@ class ConfirmOrder extends StatefulWidget { class _ConfirmOrderState extends State { int valueMethodPayment = 1; String? paymentMethod = 'COD'; + int getCartTotal() { int total = widget.orderResponse.totalPrice + widget.orderResponse.shipping.giaohangnhanh.serviceFee; @@ -47,354 +50,555 @@ class _ConfirmOrderState extends State { addressSelected: widget.orderResponse.addressSelected, product: widget.orderResponse.product, ); - } - // openDiaologCart() => showDialog( - // context: context, - // builder: (context) { - // return AlertDialog( - // title: const Text('Don hang cua ban'), - // content: SizedBox( - // width: double.maxFinite, - // child: ListView.builder( - // shrinkWrap: true, - // itemCount: widget.title.length, - // itemBuilder: ((context, index) { - // return Row( - // children: [ - // Image.asset( - // widget.image[index], - // width: 50, - // ), - // Text(widget.title[index]), - // ], - // ); - // })), - // ), - // actions: [ - // ElevatedButton( - // onPressed: () { - // Navigator.pop(context); - // }, - // child: const Text('Dong')), - // ], - // ); - // }); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => MainScreen(), + ), + ); + showSnackBarSuccess(context, 'Đặt hàng thành công'); + } - List addressUser = []; @override Widget build(BuildContext context) { - List addressUser = - Provider.of(context).user.address; + final ScrollController scrollController = ScrollController(); + return Scaffold( appBar: AppBar( - title: const Text( - "Xác nhận đơn hàng", - style: TextStyle(color: Colors.black), + title: Text( + "Thanh toán", + style: TextStyle( + fontSize: 22, + fontWeight: FontWeight.w500, + ), ), - centerTitle: true, + leading: BackButton(), backgroundColor: Colors.transparent, foregroundColor: primaryColors, elevation: 0, + centerTitle: true, ), - bottomNavigationBar: Container( - padding: const EdgeInsets.only(bottom: 10), - child: ButtonInAddress( - textInAddress: 'Thanh toán', - functionAddress: createOder, - ), - ), - body: SingleChildScrollView( - child: SafeArea( + body: SafeArea( + child: SingleChildScrollView( + controller: scrollController, child: Container( - color: const Color.fromARGB(255, 244, 243, 247), - padding: const EdgeInsets.all(20), + color: Colors.white, + padding: EdgeInsets.all(10), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const SizedBox(height: 10), - const Text( - "Thông tin nhận hàng", - style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600), + _buildShippingAddress(), + Divider(thickness: 1, color: Colors.black54), + _buildPaymentProduct(), + Divider(thickness: 1, color: Colors.black54), + _buildPaymentMethods(), + Divider(thickness: 1, color: Colors.black54), + _buildBill(), + ], + ), + ), + ), + ), + bottomNavigationBar: _buildBottomNavigationBar(), + ); + } + + Widget _buildShippingAddress() { + List addressUser = + Provider.of(context).user.address; + + return Padding( + padding: EdgeInsets.symmetric(vertical: 10), + child: Column( + children: [ + Row( + children: [ + Icon( + Icons.location_on, + color: primaryColors, + ), + SizedBox(width: 5), + Text( + "Địa chỉ nhận hàng", + style: TextStyle( + fontSize: 18, + color: Colors.black, + fontWeight: FontWeight.w600, ), - const SizedBox(height: 10), - Container( - width: MediaQuery.of(context).size.width, - height: 85, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(10), - boxShadow: const [ - BoxShadow( - color: Colors.black12, - blurRadius: 4, - spreadRadius: 2, - ), - ], - ), - child: Container( - padding: const EdgeInsets.only(left: 10, top: 10), - width: 300, - child: Row( + ), + ], + ), + SizedBox(height: 10), + Container( + padding: EdgeInsets.only(left: 30), + child: Row( + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + '${addressUser[widget.orderResponse.addressSelected].customerName}', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + ), + ), + SizedBox( + height: 18, + child: VerticalDivider( + color: Colors.black54, + thickness: 1, + ), + ), + Text( + '${addressUser[widget.orderResponse.addressSelected].phoneNumbers}', + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + SizedBox(height: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, + Text( + '${addressUser[widget.orderResponse.addressSelected].detail}', + style: TextStyle( + fontSize: 16, + color: Colors.black54, + fontWeight: FontWeight.w500, + ), + ), + SizedBox(height: 5), + Row( children: [ - Row( + Text( + '${addressUser[widget.orderResponse.addressSelected].wardLevel.wardName},', + style: TextStyle( + fontSize: 16, + color: Colors.black54, + fontWeight: FontWeight.w500, + ), + ), + Text( + '${addressUser[widget.orderResponse.addressSelected].districtLevel.district_name}, ', + style: TextStyle( + fontSize: 16, + color: Colors.black54, + fontWeight: FontWeight.w500, + ), + ), + Text( + '${addressUser[widget.orderResponse.addressSelected].provinceLevel.province_name}', + style: TextStyle( + fontSize: 16, + color: Colors.black54, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ], + ), + ], + ), + ], + ), + ), + ], + ), + ); + } + + Widget _buildPaymentProduct() { + List productWidgets = []; + + for (int i = 0; i < widget.orderResponse.product.length; i++) { + final product = widget.orderResponse.product[i]; + final productProvider = + Provider.of(context, listen: false).products; + productWidgets.add( + ListView.builder( + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + itemCount: productProvider.length, + itemBuilder: (context, index) { + final itemProduct = productProvider[index]; + if (product.productId == itemProduct.id) { + return Container( + width: 400, + padding: EdgeInsets.symmetric(vertical: 10), + margin: EdgeInsets.symmetric(vertical: 5), + // decoration: BoxDecoration( + // color: Color.fromARGB(255, 240, 239, 239), + // borderRadius: BorderRadius.circular(10), + // ), + child: Row( + children: [ + Expanded( + child: ListView.builder( + shrinkWrap: true, + scrollDirection: Axis.vertical, + physics: NeverScrollableScrollPhysics(), + itemCount: itemProduct.variations.length, + itemBuilder: (context, indexVariation) { + final variation = + itemProduct.variations[indexVariation]; + + if (product.sku == variation.sku) { + return Row( children: [ - Text( - addressUser[ - widget.orderResponse.addressSelected] - .customerName, - style: const TextStyle( - fontSize: 15, - fontWeight: FontWeight.w500, - ), - ), - const SizedBox( - height: 18, - child: VerticalDivider( - color: Colors.black, - thickness: 1, - ), - ), - Text( - addressUser[ - widget.orderResponse.addressSelected] - .phoneNumbers, - style: const TextStyle( - fontSize: 15, - fontWeight: FontWeight.w500, + Container( + height: 120, + width: 120, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: variation.images.length, + itemBuilder: (context, index) { + final image = variation.images[index]; + if (image.isThumbnail == true) { + return Image( + image: NetworkImage('${image.url}'), + ); + } else if (index == 0) { + return Image( + image: NetworkImage('${image.url}'), + ); + } + return Container(); + }, ), ), - ], - ), - const SizedBox(height: 10), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(addressUser[ - widget.orderResponse.addressSelected] - .detail), - Row( + SizedBox(width: 5), + Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ + Container( + width: 220, + child: Text( + '${itemProduct.name}', + overflow: TextOverflow.ellipsis, + maxLines: 1, + style: TextStyle( + color: Colors.black, + fontSize: 18, + fontWeight: FontWeight.w400, + ), + ), + ), + SizedBox(height: 5), + Row( + children: [ + Text( + 'Phân loại:', + style: TextStyle( + color: Colors.black, + fontSize: 14, + fontWeight: FontWeight.w400, + ), + ), + Container( + height: + 15, // Adjust the height as needed + width: 150, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: + variation.attributes.length, + itemBuilder: (context, index) { + final attribute = + variation.attributes[index]; + return Text( + ' ${attribute.v.toUpperCase()}${attribute.u ?? ''}', + style: TextStyle( + color: Colors.black, + fontSize: 14, + fontWeight: FontWeight.w400, + ), + ); + }, + ), + ), + ], + ), + SizedBox(height: 5), + Row( + children: [ + Text( + '${formatCurrency.format(variation.price.special)}', + style: TextStyle( + color: Colors.red, + fontWeight: FontWeight.w500, + fontSize: 16, + ), + ), + SizedBox(width: 5), + Text( + '-', + style: TextStyle( + color: Colors.grey.withOpacity(1), + fontWeight: FontWeight.w500, + fontSize: 16, + ), + ), + SizedBox(width: 5), + Text( + '${formatCurrency.format(variation.price.base)}', + style: TextStyle( + color: Colors.grey.withOpacity(1), + fontWeight: FontWeight.w400, + decoration: + TextDecoration.lineThrough, + fontSize: 16, + ), + ), + ], + ), + SizedBox(height: 5), Text( - "${addressUser[widget.orderResponse.addressSelected].wardLevel.wardName}, "), - Text( - "${addressUser[widget.orderResponse.addressSelected].districtLevel.district_name}, "), - Text( - "${addressUser[widget.orderResponse.addressSelected].provinceLevel.province_name},"), + 'Số lượng: ${product.quantity}', + style: TextStyle( + color: Colors.black, + fontSize: 14, + fontWeight: FontWeight.w400, + ), + ), + SizedBox(height: 5), ], ), ], - ), - ], - ), - ], + ); + } + return Container(); + }, + ), ), - ), + ], ), - const SizedBox(height: 30), - ButtonSendrequest( - text: 'Kiểm tra đơn hàng', - submit: () {}, + ); + } + return Container(); + }, + ), + ); + } + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: productWidgets, + ); + } + + Widget _buildPaymentMethods() { + return Container( + padding: EdgeInsets.all(10), + // decoration: BoxDecoration( + // color: Colors.white, + // borderRadius: BorderRadius.circular(10), + // boxShadow: [ + // BoxShadow( + // color: Color(0xFF475269).withOpacity(0.3), + // spreadRadius: 1, + // blurRadius: 5, + // ), + // ], + // ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Phương thức thanh toán', + style: TextStyle( + fontSize: 18, + color: Colors.black, + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 10), + Row( + children: [ + Text( + 'Thanh toán khi nhận hàng', + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w500, ), - const SizedBox(height: 30), - const Text( - 'Phương thức thanh toán', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), + ), + Spacer(), + Radio( + activeColor: primaryColors, + value: 1, + groupValue: valueMethodPayment, + onChanged: (check) { + setState(() { + valueMethodPayment = check!; + paymentMethod = 'COD'; + }); + }, + ), + ], + ), + Row( + children: [ + Text( + 'Thanh toán qua VNPAY', + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w500, ), - const SizedBox(height: 10), - Container( - padding: const EdgeInsets.all(15), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(10), - boxShadow: [ - BoxShadow( - color: const Color(0xFF475269).withOpacity(0.3), - spreadRadius: 1, - blurRadius: 5, - ), - ], - ), - child: Column( - children: [ - Row( - children: [ - const Text( - 'Thanh toán khi nhận hàng', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - ), - ), - const Spacer(), - Radio( - activeColor: primaryColors, - value: 1, - groupValue: valueMethodPayment, - onChanged: (check) { - setState(() { - valueMethodPayment = check!; - paymentMethod = 'COD'; - }); - }, - ), - ], - ), - Row( - children: [ - const Text( - 'Thanh toán qua VNPAY', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - ), - ), - const Spacer(), - Radio( - activeColor: primaryColors, - value: 2, - groupValue: valueMethodPayment, - onChanged: (check) { - setState(() { - valueMethodPayment = check!; - paymentMethod = 'VNPAY'; - }); - }, - ), - ], - ), - ], - ), + ), + Spacer(), + Radio( + activeColor: primaryColors, + value: 2, + groupValue: valueMethodPayment, + onChanged: (check) { + setState(() { + valueMethodPayment = check!; + paymentMethod = 'VNPAY'; + }); + }, + ), + ], + ), + ], + ), + ); + } + + Widget _buildBill() { + return Container( + padding: EdgeInsets.all(10), + // decoration: BoxDecoration( + // color: Colors.white, + // borderRadius: BorderRadius.circular(10), + // boxShadow: [ + // BoxShadow( + // color: const Color(0xFF475269).withOpacity(0.3), + // spreadRadius: 1, + // blurRadius: 5, + // ), + // ], + // ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Chi tiết hóa đơn", + style: TextStyle( + fontSize: 18, + color: Colors.black, + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Tổng số lượng", + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w500, ), - const SizedBox(height: 30), - Container( - padding: const EdgeInsets.all(15), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(10), - boxShadow: [ - BoxShadow( - color: const Color(0xFF475269).withOpacity(0.3), - spreadRadius: 1, - blurRadius: 5, - ), - ], - ), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - "Tổng số hàng", - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Color(0xFF475269), - ), - ), - Text( - getQuantity().toString(), - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Color(0xFF475269), - ), - ), - ], - ), - const Divider( - height: 30, - thickness: 0.5, - color: Color(0xFF475269), - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - "Tổng đơn hàng", - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Color(0xFF475269), - ), - ), - Text( - "${formatCurrency.format(widget.orderResponse.totalPrice)}", - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Color(0xFF475269), - ), - ), - ], - ), - const Divider( - height: 30, - thickness: 0.5, - color: Color(0xFF475269), - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - "Phí vận chuyển", - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Color(0xFF475269), - ), - ), - Text( - "${formatCurrency.format(widget.orderResponse.shipping.giaohangnhanh.total)}", - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Color(0xFF475269), - ), - ), - ], - ), - const Divider( - height: 30, - thickness: 0.5, - color: Color(0xFF475269), - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - "Tổng hóa đơn", - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Color(0xFF475269), - ), - ), - Text( - formatCurrency.format(getCartTotal()), - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: primaryColors, - ), - ), - ], - ), - ], - ), + ), + Text( + getQuantity().toString(), + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w500, ), - ], - ), + ), + ], ), - ), + SizedBox(height: 5), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Tổng tiền hàng", + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + ), + Text( + "${formatCurrency.format(widget.orderResponse.totalPrice)}", + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + SizedBox(height: 5), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + "Phí vận chuyển", + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + ), + Text( + "${formatCurrency.format(widget.orderResponse.shipping.giaohangnhanh.total)}", + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + SizedBox(height: 5), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + "Tổng thanh toán", + style: TextStyle( + fontSize: 20, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + ), + Text( + formatCurrency.format(getCartTotal()), + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: primaryColors, + ), + ), + ], + ), + ], + ), + ); + } + + Widget _buildBottomNavigationBar() { + return Container( + padding: EdgeInsets.all(10), + child: ButtonInAddress( + textInAddress: 'Đặt hàng', + functionAddress: createOder, ), ); } diff --git a/lib/Pages/Tabs/information_user.dart b/lib/Pages/Tabs/information_user.dart index beae117..afec704 100644 --- a/lib/Pages/Tabs/information_user.dart +++ b/lib/Pages/Tabs/information_user.dart @@ -7,7 +7,7 @@ import 'package:my_app/API/api_image.dart'; import 'package:my_app/API/api_profile.dart'; import 'package:my_app/Providers/user_provider.dart'; import 'package:my_app/Widgets/Login/button.dart'; -import 'package:my_app/models/user_models.dart'; +import 'package:my_app/models/user_model.dart'; import 'package:my_app/utils/constant.dart'; import 'package:my_app/utils/snackbar.dart'; import 'package:provider/provider.dart'; @@ -38,10 +38,10 @@ class _InformationUserState extends State { void initState() { super.initState(); ProfileUser().getProfileUser(context); - User user = Provider.of(context, listen: false).user; - fisrtNameController.text = user.firstName; - userNameController.text = user.userName; - lastNameController.text = user.lastName; + // User user = Provider.of(context, listen: false).user; + // fisrtNameController.text = user.firstName; + // userNameController.text = user.userName; + // lastNameController.text = user.lastName; } @override @@ -171,9 +171,10 @@ class _InformationUserState extends State { buildTextField('Id:', user.id), buildTextField('Email:', user.email), buildTextField('Tên tài khoản:', user.userName), + buildTextField('Được tạo lúc:', + formatTimestamp(user.createdAt.toString())), buildTextField( - 'Được tạo lúc:', formatTimestamp(user.createdAt)), - buildTextField('cập nhật ', formatTimestamp(user.updatedAt)), + 'cập nhật ', formatTimestamp(user.updatedAt.toString())), const SizedBox(height: 50), Padding( padding: const EdgeInsets.all(10.0), @@ -337,7 +338,7 @@ class _InformationUserState extends State { style: ElevatedButton.styleFrom(backgroundColor: primaryColors), child: const Text( 'Hoàn thành', - style: TextStyle(fontSize: 16), + style: TextStyle(fontSize: 16, color: Colors.white), ), ), ), @@ -369,7 +370,7 @@ class _InformationUserState extends State { ); checkavatar = false; } else { - showSnackBarError(context, 'loi roi'); + showSnackBarError(context, 'loi trong information'); } } @@ -379,6 +380,10 @@ class _InformationUserState extends State { String label, Function()? submit, ) { + User user = Provider.of(context, listen: false).user; + fisrtNameController.text = user.firstName; + userNameController.text = user.userName; + lastNameController.text = user.lastName; return Row( children: [ Expanded( @@ -394,17 +399,11 @@ class _InformationUserState extends State { label: Text(label), border: const OutlineInputBorder(), suffixIcon: TextButton( - onPressed: isButtonEnabled - ? () { - if (_formKey.currentState!.validate()) { - return; - } - } - : submit, - child: const Text( + onPressed: isButtonEnabled == true ? null : submit, + child: Text( 'Thay đổi', style: TextStyle( - color: primaryColors, + color: isButtonEnabled ? primaryColors : Colors.grey, ), )), ), diff --git a/lib/Pages/Tabs/notification_after_login_tab.dart b/lib/Pages/Tabs/notification_after_login_tab.dart index 69e79d0..388800c 100644 --- a/lib/Pages/Tabs/notification_after_login_tab.dart +++ b/lib/Pages/Tabs/notification_after_login_tab.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:my_app/API/api_notification.dart'; import 'package:my_app/models/notification_model.dart'; +import 'package:my_app/utils/constant.dart'; import 'package:socket_io_client/socket_io_client.dart' as IO; class NotificationAfterLoginTab extends StatefulWidget { @@ -73,74 +74,85 @@ class _NotificationAfterLoginTabState extends State { @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Center( - child: Text('Thông báo'), + return SafeArea( + child: Scaffold( + appBar: AppBar( + title: Text( + "Thông báo", + style: TextStyle( + fontSize: 22, + fontWeight: FontWeight.w500, + ), + ), + backgroundColor: primaryColors, + foregroundColor: Colors.white, + elevation: 0, + centerTitle: true, ), - ), - body: SingleChildScrollView( - child: Column( - children: [ - ListView.builder( - scrollDirection: Axis.vertical, - shrinkWrap: true, - physics: BouncingScrollPhysics(), - itemCount: notifications.data.length, - itemBuilder: (context, index) { - DataNotificationUser notification = notifications.data[index]; + body: SingleChildScrollView( + child: Column( + children: [ + ListView.builder( + scrollDirection: Axis.vertical, + shrinkWrap: true, + physics: BouncingScrollPhysics(), + itemCount: notifications.data.length, + itemBuilder: (context, index) { + DataNotificationUser notification = + notifications.data[index]; - return Column( - children: [ - Container( - width: MediaQuery.of(context).size.width, - child: ListTile( - onTap: () { - if (!notification.isRead()) { - markNotificationAsRead(notification.id); - } - ; - }, - leading: CircleAvatar( - backgroundColor: Colors.white, - backgroundImage: - AssetImage('assets/icons/profile.png'), - ), - title: Text( - notification.content, - style: TextStyle( - fontWeight: FontWeight.bold, - color: notification.isRead() - ? Colors.grey - : Colors.black), - ), - subtitle: Text( - notification.createdAt.toString(), - style: TextStyle( - fontWeight: FontWeight.bold, - color: notification.isRead() - ? Colors.grey - : Colors.black), + return Column( + children: [ + Container( + width: MediaQuery.of(context).size.width, + child: ListTile( + onTap: () { + if (!notification.isRead()) { + markNotificationAsRead(notification.id); + } + ; + }, + leading: CircleAvatar( + backgroundColor: Colors.white, + backgroundImage: + AssetImage('assets/icons/profile.png'), + ), + title: Text( + notification.content, + style: TextStyle( + fontWeight: FontWeight.bold, + color: notification.isRead() + ? Colors.grey + : Colors.black), + ), + subtitle: Text( + notification.createdAt.toString(), + style: TextStyle( + fontWeight: FontWeight.bold, + color: notification.isRead() + ? Colors.grey + : Colors.black), + ), + trailing: notification.isRead() + ? null + : Container( + width: 14, + height: 14, + decoration: BoxDecoration( + color: Colors.red, + shape: BoxShape.circle), + ), ), - trailing: notification.isRead() - ? null - : Container( - width: 14, - height: 14, - decoration: BoxDecoration( - color: Colors.red, - shape: BoxShape.circle), - ), ), - ), - Divider( - thickness: 0.5, - color: Colors.grey, - ) - ], - ); - }), - ], + Divider( + thickness: 0.5, + color: Colors.grey, + ) + ], + ); + }), + ], + ), ), ), ); diff --git a/lib/Pages/Tabs/order_detail.dart b/lib/Pages/Tabs/order_detail.dart index 0685065..a87af7d 100644 --- a/lib/Pages/Tabs/order_detail.dart +++ b/lib/Pages/Tabs/order_detail.dart @@ -1,51 +1,73 @@ // ignore_for_file: must_be_immutable +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; + import 'package:my_app/API/api_order.dart'; +import 'package:my_app/API/api_product.dart'; +import 'package:my_app/Pages/Tabs/product_detail.dart'; + +import 'package:intl/intl.dart'; +import 'package:my_app/Pages/Tabs/reason_cancelled_order.dart'; import 'package:my_app/Providers/product_provider.dart'; + import 'package:my_app/Widgets/Login/button.dart'; import 'package:my_app/models/order_model.dart'; import 'package:my_app/models/product_model.dart'; import 'package:my_app/utils/constant.dart'; -import 'package:provider/provider.dart'; + class OrderDetail extends StatefulWidget { - OrderUser orderUser; - OrderDetail({super.key, required this.orderUser}); + OrderUser orderDetail; + OrderDetail({super.key, required this.orderDetail}); @override State createState() => _OrderDetailState(); } class _OrderDetailState extends State { + String reaSonCancelled = ''; @override Widget build(BuildContext context) { - List productProvider = - Provider.of(context, listen: false).products; return Scaffold( appBar: AppBar( - title: const Text( - 'Đơn hàng của bạn', - style: TextStyle(color: Colors.black), + title: Text( + "Đơn hàng của bạn", + style: TextStyle( + fontSize: 22, + fontWeight: FontWeight.w500, + ), ), + leading: BackButton(), + backgroundColor: Colors.white, foregroundColor: primaryColors, elevation: 0, - backgroundColor: Colors.white, + centerTitle: true, ), - bottomNavigationBar: BuildButtonNavigationBar(), body: SingleChildScrollView( child: Container( - color: Colors.grey[300], + color: Colors.white, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ styleOderStatus(), + + Divider(thickness: 0.5), + _buildShippingAddressOrder(), + Divider(thickness: 0.5), + _buildProductOrder(), + Divider(thickness: 0.5), + __buildPaymentMethodAndSingleCode(), + Divider(thickness: 0.5), + _buildOrdersInvoice(), + Container( color: Colors.white, child: Padding( padding: const EdgeInsets.all(10), child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, children: [ Row( children: [ @@ -60,11 +82,29 @@ class _OrderDetailState extends State { ), ], ), - Column( - children: [ - Text(widget - .orderUser.shippingOrder.toAddress.addressName) - ], + Padding( + padding: const EdgeInsets.only(left: 25.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(widget.orderDetail.shippingOrder.toAddress + .customerName), + Text(widget.orderDetail.shippingOrder.toAddress + .phoneNumbers), + Text(widget + .orderDetail.shippingOrder.toAddress.detail), + Row( + children: [ + Text( + '${widget.orderDetail.shippingOrder.toAddress.wardLevel.wardName}, '), + Text( + '${widget.orderDetail.shippingOrder.toAddress.districtLevel.district_name}, '), + Text(widget.orderDetail.shippingOrder.toAddress + .provinceLevel.province_name), + ], + ), + ], + ), ) ], ), @@ -99,9 +139,9 @@ class _OrderDetailState extends State { shrinkWrap: true, scrollDirection: Axis.vertical, physics: NeverScrollableScrollPhysics(), - itemCount: widget.orderUser.product.length, + itemCount: widget.orderDetail.product.length, itemBuilder: (context, indexFirst) { - final itemCart = widget.orderUser.product[indexFirst]; + final itemCart = widget.orderDetail.product[indexFirst]; return Container( child: ListView.builder( shrinkWrap: true, @@ -358,7 +398,7 @@ class _OrderDetailState extends State { Text('Tạm tính'), Spacer(), Text(formatCurrency.format( - widget.orderUser.checkoutOrder.totalPrice)), + widget.orderDetail.checkoutOrder.totalPrice)), ], ), Row( @@ -366,7 +406,7 @@ class _OrderDetailState extends State { Text('Phí vận chuyển'), Spacer(), Text(formatCurrency.format( - widget.orderUser.checkoutOrder.shippingFee)), + widget.orderDetail.checkoutOrder.shippingFee)), ], ), Row( @@ -374,7 +414,7 @@ class _OrderDetailState extends State { Text('Giảm giá'), Spacer(), Text(formatCurrency.format(widget - .orderUser.checkoutOrder.totalApplyDiscount)), + .orderDetail.checkoutOrder.totalApplyDiscount)), ], ), Row( @@ -382,7 +422,7 @@ class _OrderDetailState extends State { Text('Voucher từ shop'), Spacer(), Text(formatCurrency.format(widget - .orderUser.checkoutOrder.totalApplyDiscount)), + .orderDetail.checkoutOrder.totalApplyDiscount)), ], ), Divider( @@ -398,7 +438,7 @@ class _OrderDetailState extends State { Spacer(), Text( formatCurrency.format( - widget.orderUser.checkoutOrder.totalPrice), + widget.orderDetail.checkoutOrder.totalPrice), style: TextStyle( fontSize: 16, fontWeight: FontWeight.w700, @@ -439,7 +479,7 @@ class _OrderDetailState extends State { ), ], ), - if (widget.orderUser.paymentOrder.method == 'COD') + if (widget.orderDetail.paymentOrder.method == 'COD') Padding( padding: const EdgeInsets.only(left: 30.0), child: Text('Thanh toán khi nhận hàng'), @@ -447,7 +487,7 @@ class _OrderDetailState extends State { else Padding( padding: const EdgeInsets.only(left: 30.0), - child: Text(widget.orderUser.paymentOrder.method), + child: Text(widget.orderDetail.paymentOrder.method), ), ]), ), @@ -469,7 +509,7 @@ class _OrderDetailState extends State { ), Spacer(), Text( - widget.orderUser.trackingCode, + widget.orderDetail.trackingCode, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w700), ), @@ -482,11 +522,11 @@ class _OrderDetailState extends State { children: [ Text('Ngày đặt đơn'), Spacer(), - Text(formatTimestamp(widget.orderUser.createdAt)), + Text(formatTimestamp(widget.orderDetail.createdAt)), ], ), ), - if (widget.orderUser.oderStatus == 'completed') + if (widget.orderDetail.oderStatus == 'completed') Padding( padding: const EdgeInsets.only( left: 10.0, right: 10, bottom: 10), @@ -494,7 +534,7 @@ class _OrderDetailState extends State { children: [ Text('Ngày nhận đơn'), Spacer(), - Text(formatTimestamp(widget.orderUser.updatedAt)), + Text(formatTimestamp(widget.orderDetail.updatedAt)), ], ), ) @@ -508,45 +548,68 @@ class _OrderDetailState extends State { ), ), ), + bottomNavigationBar: _buildButtonNavigationBar(), ); } Widget styleOderStatus() { - if (widget.orderUser.oderStatus == 'completed') { + if (widget.orderDetail.oderStatus == 'completed') { return Container( height: 100, width: MediaQuery.sizeOf(context).width, decoration: BoxDecoration(color: Color.fromARGB(255, 0, 197, 154)), child: Padding( - padding: const EdgeInsets.all(20.0), + padding: EdgeInsets.all(20.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text('Đơn hàng đã hoàn Thành', - style: TextStyle(color: Colors.white, fontSize: 18)), - Text('Cảm ơn bạn đã mua hàng tại Techcell', - style: TextStyle(color: Colors.white)) + Text( + 'Đơn hàng đã hoàn Thành', + style: TextStyle( + color: Colors.white, + fontSize: 18, + ), + ), + Text( + 'Cảm ơn bạn đã mua hàng tại Techcell', + style: TextStyle(color: Colors.white), + ) ], ), ), ); - } else if (widget.orderUser.oderStatus == 'pending') { + } else if (widget.orderDetail.oderStatus == 'pending') { return Container( height: 100, width: MediaQuery.sizeOf(context).width, decoration: BoxDecoration(color: Colors.yellow[800]), child: Padding( - padding: const EdgeInsets.all(20.0), + padding: EdgeInsets.all(20.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Đơn hàng đang chờ xử lý', + style: TextStyle(color: Colors.white), + ), + Text('Vui lòng chờ đợi', + style: TextStyle(color: Colors.white)), + Text('Cảm ơn bạn đã mua hàng tại Techcell', + style: TextStyle(color: Colors.white)) + ], + ), Text( - 'Đơn hàng đang chờ xử lý', + 'Vui lòng chờ đợi', style: TextStyle(color: Colors.white), ), - Text('Vui lòng chờ đợi', style: TextStyle(color: Colors.white)), - Text('Cảm ơn bạn đã mua hàng tại Techcell', - style: TextStyle(color: Colors.white)) + Text( + 'Cảm ơn bạn đã mua hàng tại Techcell', + style: TextStyle(color: Colors.white), + ), + Icon(CupertinoIcons.rectangle_paperclip) ], ), ), @@ -557,7 +620,7 @@ class _OrderDetailState extends State { width: MediaQuery.sizeOf(context).width, decoration: BoxDecoration(color: Colors.yellow[400]), child: Padding( - padding: const EdgeInsets.all(20.0), + padding: EdgeInsets.all(20.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -565,41 +628,551 @@ class _OrderDetailState extends State { 'Đơn hàng đang chờ xử lý', style: TextStyle(color: Colors.white), ), - Text('Vui lòng chờ đợi', style: TextStyle(color: Colors.white)), - Text('Cảm ơn bạn đã mua hàng tại Techcell', - style: TextStyle(color: Colors.white)) + Text( + 'Vui lòng chờ đợi', + style: TextStyle(color: Colors.white), + ), + Text( + 'Cảm ơn bạn đã mua hàng tại Techcell', + style: TextStyle(color: Colors.white), + ) ], ), ), ); } - BuildButtonNavigationBar() { - if (widget.orderUser.oderStatus == 'completed') { + Widget _buildShippingAddressOrder() { + return Padding( + padding: EdgeInsets.all(10), + child: Column( + children: [ + Row( + children: [ + Icon( + Icons.location_on, + color: primaryColors, + ), + SizedBox(width: 5), + Text( + "Địa chỉ nhận hàng", + style: TextStyle( + fontSize: 18, + color: Colors.black, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + SizedBox(height: 10), + Row( + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + widget.orderDetail.shippingOrder.toAddress.customerName, + ), + SizedBox( + height: 18, + child: VerticalDivider( + color: Colors.black54, + thickness: 1, + ), + ), + ], + ), + SizedBox(height: 10), + ], + ), + ], + ), + ], + ), + ); + } + + Widget _buildProductOrder() { + return Column( + children: [ + Padding( + padding: EdgeInsets.only(top: 10, left: 10), + child: Row( + children: [ + Image( + image: AssetImage( + 'assets/logos/favicon.ico', + ), + width: 20, + ), + SizedBox(width: 5), + Padding( + padding: EdgeInsets.only(top: 5), + child: Text( + 'TechCell', + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + ), + Divider(thickness: 0.5), + ListView.builder( + shrinkWrap: true, + scrollDirection: Axis.vertical, + physics: NeverScrollableScrollPhysics(), + itemCount: widget.orderDetail.product.length, + itemBuilder: (context, indexOrderDetail) { + final orderProduct = widget.orderDetail.product[indexOrderDetail]; + return FutureBuilder>( + future: ProductAPI().getAllProducts(), + builder: (context, snapshot) { + if ((snapshot.hasError) || (!snapshot.hasData)) { + return Padding( + padding: EdgeInsets.all(15), + child: Center( + child: CircularProgressIndicator(), + ), + ); + } + + List? products = snapshot.data; + return Padding( + padding: EdgeInsets.all(5), + child: ListView.builder( + shrinkWrap: true, + scrollDirection: Axis.vertical, + physics: NeverScrollableScrollPhysics(), + itemCount: products?.length, + itemBuilder: (context, indexProduct) { + final itemProduct = products?[indexProduct]; + if (orderProduct.productId == itemProduct!.id) { + return Container( + child: ListView.builder( + shrinkWrap: true, + scrollDirection: Axis.vertical, + physics: NeverScrollableScrollPhysics(), + itemCount: itemProduct.variations.length, + itemBuilder: (context, indexVariation) { + final variation = + itemProduct.variations[indexVariation]; + if (orderProduct.sku == variation.sku) { + return Row( + children: [ + InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ProductDetail( + productDetail: itemProduct), + ), + ); + }, + child: Container( + height: 120, + width: 120, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: variation.images.length, + itemBuilder: (context, index) { + final image = + variation.images[index]; + if (image.isThumbnail == true) { + return Image( + image: NetworkImage( + '${image.url}'), + ); + } else if (index == 0) { + return Image( + image: NetworkImage( + '${image.url}'), + ); + } + return Container(); + }, + ), + ), + ), + SizedBox(width: 5), + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Container( + width: 250, + child: Text( + '${itemProduct.name}', + overflow: TextOverflow.ellipsis, + maxLines: 1, + style: TextStyle( + color: Colors.black, + fontSize: 18, + fontWeight: FontWeight.w400, + ), + ), + ), + SizedBox(height: 5), + Row( + children: [ + Text('Phân loại:'), + Container( + height: + 15, // Adjust the height as needed + width: 150, + child: ListView.builder( + scrollDirection: + Axis.horizontal, + itemCount: + variation.attributes.length, + itemBuilder: (context, index) { + final attribute = variation + .attributes[index]; + return Text( + ' ${attribute.v.toUpperCase()}${attribute.u ?? ''}', + ); + }, + ), + ), + ], + ), + SizedBox(height: 5), + Row( + children: [ + Text( + '${formatCurrency.format(variation.price.special)}', + style: TextStyle( + color: Colors.red, + fontWeight: FontWeight.w500, + fontSize: 16, + ), + ), + SizedBox(width: 5), + Text( + '-', + style: TextStyle( + color: + Colors.grey.withOpacity(1), + fontWeight: FontWeight.w500, + fontSize: 16, + ), + ), + SizedBox(width: 5), + Text( + '${formatCurrency.format(variation.price.base)}', + style: TextStyle( + color: + Colors.grey.withOpacity(1), + fontWeight: FontWeight.w400, + decoration: + TextDecoration.lineThrough, + fontSize: 16, + ), + ), + ], + ), + SizedBox(height: 5), + ], + ), + ], + ); + } + return Container(); + }, + ), + ); + } + return Container(); + }, + ), + ); + }, + ); + }, + ), + ], + ); + } + + Widget __buildPaymentMethodAndSingleCode() { + return Padding( + padding: EdgeInsets.all(15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon( + Icons.payments_outlined, + color: primaryColors, + ), + SizedBox(width: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Phương thúc thanh toán', + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 5), + if (widget.orderDetail.paymentOrder.method == 'COD') + Text( + 'Thanh toán khi nhận hàng', + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w400, + ), + ) + else + Text(widget.orderDetail.paymentOrder.method) + ], + ), + ], + ), + ), + SizedBox(height: 10), + Container( + child: Row( + children: [ + Icon( + Icons.code_outlined, + color: primaryColors, + ), + SizedBox(width: 10), + Text( + 'Mã đơn hàng', + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w600, + ), + ), + Spacer(), + Text( + widget.orderDetail.trackingCode, + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w400, + ), + ), + ], + ), + ), + SizedBox(height: 10), + Container( + child: Row( + children: [ + Icon( + Icons.date_range, + color: primaryColors, + ), + SizedBox(width: 10), + Text( + 'Ngày đặt đơn', + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w600, + ), + ), + Spacer(), + Text( + '${formatTimestamp(widget.orderDetail.createdAt)}', + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w400, + ), + ), + ], + ), + ), + if (widget.orderDetail.oderStatus == 'completed') + Padding( + padding: EdgeInsets.only(left: 10.0, right: 10, bottom: 10), + child: Row( + children: [ + Text('Ngày nhận đơn'), + Spacer(), + Text( + '${formatTimestamp(widget.orderDetail.updatedAt)}', + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w400, + ), + ), + ], + ), + ) + else + Container(), + ], + ), + ); + } + + Widget _buildOrdersInvoice() { + int totalPrice = widget.orderDetail.checkoutOrder.totalPrice; + int shippingFee = widget.orderDetail.checkoutOrder.shippingFee; + int totalDiscount = widget.orderDetail.checkoutOrder.totalApplyDiscount; + + return Padding( + padding: EdgeInsets.all(15), + child: Column( + children: [ + Row( + children: [ + Text( + 'Tạm tính', + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w600, + ), + ), + Spacer(), + Text( + '${formatCurrency.format(totalPrice)}', + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w400, + ), + ), + ], + ), + SizedBox(height: 2), + Row( + children: [ + Text( + 'Phí vận chuyển', + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + ), + Spacer(), + Text( + '${formatCurrency.format(shippingFee)}', + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w400, + ), + ), + ], + ), + SizedBox(height: 2), + Row( + children: [ + Text( + 'Giảm giá', + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + ), + Spacer(), + Text( + '${formatCurrency.format(totalDiscount)}', + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w400, + ), + ), + ], + ), + SizedBox(height: 2), + Row( + children: [ + Text( + 'Voucher từ shop', + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + ), + Spacer(), + Text( + '${formatCurrency.format(widget.orderDetail.checkoutOrder.totalApplyDiscount)}', + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w400, + ), + ), + ], + ), + Divider(thickness: 1), + Padding( + padding: EdgeInsets.symmetric(vertical: 15), + child: Row( + children: [ + Text( + 'Thành tiền', + style: TextStyle( + fontSize: 20, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + ), + Spacer(), + Text( + '${formatCurrency.format(totalPrice + shippingFee - totalDiscount)}', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w700, + color: primaryColors, + ), + ), + ], + ), + ), + ], + ), + ); + } + + _buildButtonNavigationBar() { + if (widget.orderDetail.oderStatus == 'completed') { return Padding( - padding: const EdgeInsets.all(10.0), + padding: EdgeInsets.all(10.0), child: ButtonSendrequest(text: 'Mua lại', submit: () {})); - } else if (widget.orderUser.oderStatus == 'pending') { + } else if (widget.orderDetail.oderStatus == 'pending') { return Padding( - padding: const EdgeInsets.all(10.0), + padding: EdgeInsets.all(10.0), child: ButtonSendrequest( text: 'Hủy đơn hàng', submit: () { - OrderApi().cancelOrder(context, orderId: widget.orderUser.id); + Navigator.push( + context, + MaterialPageRoute( + builder: ((context) => ReaSonCancelledOrder( + orderId: widget.orderDetail.id, + )))); }), ); } else return null; } - - String formatTimestamp(String timestamp) { - // Parse the input timestamp - DateTime dateTime = DateTime.parse(timestamp); - - // Format the date and time - String formattedDate = - DateFormat('HH:mm || dd \'Tháng\' M, y').format(dateTime); - - return formattedDate; - } } diff --git a/lib/Pages/Tabs/order_user.dart b/lib/Pages/Tabs/order_user.dart index 15b0b90..f7d6b3a 100644 --- a/lib/Pages/Tabs/order_user.dart +++ b/lib/Pages/Tabs/order_user.dart @@ -21,6 +21,7 @@ class _OrderUserTapState extends State with SingleTickerProviderStateMixin { late TabController _tabController; ScrollController _scrollController = ScrollController(); + OrderResponse orderUser = OrderResponse( data: [], page: 1, @@ -28,6 +29,7 @@ class _OrderUserTapState extends State totalPage: 1, totalRecord: 1, ); + CartModel productCart = CartModel( id: '', userId: '', @@ -35,6 +37,7 @@ class _OrderUserTapState extends State product: [], cartState: '', ); + Map orderData = { 'pending': OrderResponse( page: 1, pageSize: 5, totalPage: 11, totalRecord: 11, data: []), @@ -47,6 +50,7 @@ class _OrderUserTapState extends State 'completed': OrderResponse( page: 1, pageSize: 5, totalPage: 11, totalRecord: 11, data: []), }; + Future fetchDataForOrders() async { for (var entry in orderData.entries) { try { @@ -105,17 +109,23 @@ class _OrderUserTapState extends State length: 5, child: Scaffold( appBar: AppBar( - title: const Text( - 'Đơn hàng của bạn', - style: TextStyle(color: Colors.black), + title: Text( + "Đơn hàng", + style: TextStyle( + fontSize: 22, + fontWeight: FontWeight.w500, + ), ), + leading: BackButton(), + backgroundColor: Colors.transparent, foregroundColor: primaryColors, elevation: 0, - backgroundColor: Colors.white, + centerTitle: true, bottom: TabBar( controller: _tabController, labelColor: primaryColors, - unselectedLabelColor: Colors.black.withOpacity(0.5), + unselectedLabelColor: Colors.black, + labelStyle: TextStyle(fontSize: 16), isScrollable: true, indicator: UnderlineTabIndicator( borderSide: BorderSide(width: 3, color: primaryColors), @@ -152,386 +162,263 @@ class _OrderUserTapState extends State } else { return SingleChildScrollView( child: Container( - color: const Color.fromARGB(255, 231, 231, 231), + color: Color.fromARGB(255, 240, 239, 239), child: Column( children: [ ListView.builder( - scrollDirection: Axis.vertical, - physics: BouncingScrollPhysics(), shrinkWrap: true, + scrollDirection: Axis.vertical, + physics: NeverScrollableScrollPhysics(), itemCount: orders.data.length, - itemBuilder: ((context, index) { - return Padding( - padding: const EdgeInsets.only(top: 8.0), - child: GestureDetector( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => OrderDetail( - orderUser: orders.data[index]))); - }, - child: Container( - padding: const EdgeInsets.all(10), - decoration: const BoxDecoration( - color: Colors.white, - ), - child: Column( - mainAxisSize: MainAxisSize.min, + itemBuilder: (context, index) { + final order = orders.data[index]; + return InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => OrderDetail(orderDetail: order), + ), + ); + }, + child: Container( + color: Colors.white, + padding: + EdgeInsets.symmetric(vertical: 15, horizontal: 8), + margin: EdgeInsets.symmetric(vertical: 2), + child: Column( + children: [ + Row( children: [ Row( children: [ - const Row( - children: [ - Icon(Icons.store), - Text('Techcell'), - ], + Image( + image: AssetImage( + 'assets/logos/favicon.ico', + ), + width: 20, ), - const Spacer(), - getOrderStatus( - orders.data[index].oderStatus, - _getStatusText( - orders.data[index].oderStatus)), + SizedBox(width: 2), + Text('Techcell'), ], ), - ListView.builder( - shrinkWrap: true, - scrollDirection: Axis.vertical, - physics: NeverScrollableScrollPhysics(), - itemCount: orders.data[index].product.length = - 1, - itemBuilder: (context, indexFirst) { - final itemCart = - orders.data[index].product[indexFirst]; - return Container( - child: ListView.builder( - shrinkWrap: true, - scrollDirection: Axis.vertical, - physics: NeverScrollableScrollPhysics(), - itemCount: productProvider.length, - itemBuilder: (context, indexSecond) { - final itemProduct = - productProvider[indexSecond]; - if (itemCart.productId == - itemProduct.id) { - return Container( - width: 400, - padding: EdgeInsets.symmetric( - vertical: 20), - margin: EdgeInsets.symmetric( - vertical: 5), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: - BorderRadius.circular(10), - ), - child: Row( - children: [ - Expanded( - child: ListView.builder( - shrinkWrap: true, - scrollDirection: - Axis.vertical, - physics: - NeverScrollableScrollPhysics(), - itemCount: itemProduct - .variations.length, - itemBuilder: - (context, indexThird) { - final variation = - itemProduct - .variations[ - indexThird]; - - if (itemCart.sku == - variation.sku) { - return Row( + Spacer(), + getOrderStatus(order.oderStatus, + _getStatusText(order.oderStatus)), + ], + ), + Padding( + padding: EdgeInsets.symmetric(vertical: 10), + child: ListView.builder( + shrinkWrap: true, + scrollDirection: Axis.vertical, + physics: NeverScrollableScrollPhysics(), + itemCount: order.product.length, + itemBuilder: (context, indexOrder) { + final orderProduct = order.product[indexOrder]; + if (indexOrder == 0) { + return ListView.builder( + shrinkWrap: true, + scrollDirection: Axis.vertical, + physics: NeverScrollableScrollPhysics(), + itemCount: productProvider.length, + itemBuilder: (context, indexProduct) { + final itemProduct = + productProvider[indexProduct]; + if (orderProduct.productId == + itemProduct.id) { + return Container( + child: ListView.builder( + shrinkWrap: true, + scrollDirection: Axis.vertical, + physics: + NeverScrollableScrollPhysics(), + itemCount: + itemProduct.variations.length, + itemBuilder: + (context, indexVariation) { + final variation = itemProduct + .variations[indexVariation]; + if (orderProduct.sku == + variation.sku) { + return Row( + children: [ + Container( + height: 120, + width: 120, + child: ListView.builder( + scrollDirection: + Axis.horizontal, + itemCount: variation + .images.length, + itemBuilder: + (context, index) { + final image = + variation.images[ + index]; + if (image + .isThumbnail == + true) { + return Image( + image: NetworkImage( + '${image.url}'), + ); + } else if (index == + 0) { + return Image( + image: NetworkImage( + '${image.url}'), + ); + } + return Container(); + }, + ), + ), + SizedBox(width: 5), + Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Container( + width: 250, + child: Text( + '${itemProduct.name}', + overflow: + TextOverflow + .ellipsis, + maxLines: 1, + style: TextStyle( + color: + Colors.black, + fontSize: 18, + fontWeight: + FontWeight + .w400, + ), + ), + ), + SizedBox(height: 5), + Row( children: [ + Text('Phân loại:'), Container( - height: 120, - width: 120, + height: + 15, // Adjust the height as needed + width: 150, child: ListView .builder( scrollDirection: Axis.horizontal, itemCount: variation - .images + .attributes .length, itemBuilder: (context, index) { - final image = + final attribute = variation - .images[ + .attributes[ index]; - if (image - .isThumbnail == - true) { - return Image( - image: NetworkImage( - '${image.url}'), - ); - } else if (index == - 0) { - return Image( - image: NetworkImage( - '${image.url}'), - ); - } - return Container(); + return Text( + ' ${attribute.v.toUpperCase()}${attribute.u ?? ''}', + ); }, ), ), - - // SizedBox(width: 10), - Column( - crossAxisAlignment: - CrossAxisAlignment - .start, - children: [ - Container( - width: 200, - child: Text( - '${itemProduct.name}', - overflow: - TextOverflow - .ellipsis, - maxLines: 2, - style: - TextStyle( - color: Colors - .black, - fontSize: - 18, - fontWeight: - FontWeight - .w400, - ), - ), - ), - SizedBox( - height: 5), - Row( - children: [ - Text( - 'Phân loại:'), - Container( - height: - 15, // Adjust the height as needed - width: - 150, - child: ListView - .builder( - scrollDirection: - Axis.horizontal, - itemCount: variation - .attributes - .length, - itemBuilder: - (context, - index) { - final attribute = - variation.attributes[index]; - return Text( - ' ${attribute.v.toUpperCase()}${attribute.u ?? ''}', - ); - }, - ), - ), - ], - ), - SizedBox( - height: 5), - if (variation - .price - .sale != - variation - .price - .base && - variation - .price - .sale != - 0) - Row( - children: [ - Text( - '${formatCurrency.format(variation.price.sale)}', - style: - TextStyle( - color: - Colors.red, - fontWeight: - FontWeight.w500, - fontSize: - 16, - ), - ), - SizedBox( - width: - 5), - Text( - '-', - style: - TextStyle( - color: Colors - .grey - .withOpacity(1), - fontWeight: - FontWeight.w500, - fontSize: - 16, - ), - ), - SizedBox( - width: - 5), - Text( - '${formatCurrency.format(variation.price.base)}', - style: - TextStyle( - color: Colors - .grey - .withOpacity(1), - fontWeight: - FontWeight.w400, - decoration: - TextDecoration.lineThrough, - fontSize: - 16, - ), - ), - ], - ) - else if (variation - .price - .special != - 0) - Row( - children: [ - Text( - '${formatCurrency.format(variation.price.special)}', - style: - TextStyle( - color: - Colors.red, - fontWeight: - FontWeight.w500, - fontSize: - 16, - ), - ), - SizedBox( - width: - 5), - Text( - '-', - style: - TextStyle( - color: Colors - .grey - .withOpacity(1), - fontWeight: - FontWeight.w500, - fontSize: - 16, - ), - ), - SizedBox( - width: - 5), - Text( - '${formatCurrency.format(variation.price.base)}', - style: - TextStyle( - color: Colors - .grey - .withOpacity(1), - fontWeight: - FontWeight.w400, - decoration: - TextDecoration.lineThrough, - fontSize: - 16, - ), - ), - ], - ) - else - Text( - '${formatCurrency.format(variation.price.base)}', - style: - TextStyle( - color: Colors - .red, - fontWeight: - FontWeight - .w500, - fontSize: - 16, - ), - ), - SizedBox( - height: 5), - Text( - 'Số lượng: ${itemCart.quantity.toString()}', - style: - TextStyle( - fontSize: - 16, - color: Colors - .black, - ), - ), - ], + ], + ), + SizedBox(height: 5), + Row( + children: [ + Text( + '${formatCurrency.format(variation.price.special)}', + style: TextStyle( + color: + Colors.red, + fontWeight: + FontWeight + .w500, + fontSize: 16, + ), + ), + SizedBox(width: 5), + Text( + '-', + style: TextStyle( + color: Colors + .grey + .withOpacity( + 1), + fontWeight: + FontWeight + .w500, + fontSize: 16, + ), + ), + SizedBox(width: 5), + Text( + '${formatCurrency.format(variation.price.base)}', + style: TextStyle( + color: Colors + .grey + .withOpacity( + 1), + fontWeight: + FontWeight + .w400, + decoration: + TextDecoration + .lineThrough, + fontSize: 16, + ), ), ], - ); - } - return Container(); - }, - ), - ), - ], - ), - ); - } - return Container(); - }, - ), + ), + SizedBox(height: 5), + ], + ), + ], + ); + } + return Container(); + }, + ), + ); + } + return Container(); + }, ); - }, - ), - const Divider( - thickness: 1, - ), - Row( - children: [ - Text( - "${orders.data[index].product.length.toString()} sản phẩm", - style: const TextStyle(color: Colors.grey), - ), - const Spacer(), - const Image( - image: AssetImage( - 'assets/logos/favicon.ico', - ), - width: 20, - ), - const SizedBox(width: 5), - const Text("Thành tiền: "), - Text( - ' ${formatCurrency.format(orders.data[index].checkoutOrder.totalPrice)}', - style: const TextStyle( - color: primaryColors, fontSize: 16), - ) - ], + } + return Container(); + }, + ), + ), + Divider(thickness: 1), + Row( + children: [ + Text( + "${order.product.length.toString()} sản phẩm", + style: TextStyle(color: Colors.grey), ), + Spacer(), + SizedBox(width: 5), + Text('Thành tiền: '), + Text( + '${formatCurrency.format(orders.data[index].checkoutOrder.totalPrice)}', + style: TextStyle( + color: primaryColors, + fontSize: 16, + ), + ) ], ), - )), + ], + ), + ), ); - }), + }, ), ], ), @@ -544,7 +431,7 @@ class _OrderUserTapState extends State return Row( children: [ Icon(Icons.local_shipping_outlined, color: color), - const SizedBox(width: 5), + SizedBox(width: 5), Text( text, style: TextStyle(fontSize: 15, color: color), @@ -568,13 +455,15 @@ class _OrderUserTapState extends State statusColor = Colors.transparent; break; } + return Container( - padding: const EdgeInsets.all(10), - child: Row( - children: [ - styleOrderStatus(statusColor, _getStatusText(status)), - ], - )); + padding: EdgeInsets.all(10), + child: Row( + children: [ + styleOrderStatus(statusColor, _getStatusText(status)), + ], + ), + ); } String _getStatusText(String status) { diff --git a/lib/Pages/Tabs/product_detail.dart b/lib/Pages/Tabs/product_detail.dart index cb46268..8fead2e 100644 --- a/lib/Pages/Tabs/product_detail.dart +++ b/lib/Pages/Tabs/product_detail.dart @@ -3,14 +3,15 @@ import 'package:carousel_slider/carousel_slider.dart'; import 'package:flutter/material.dart'; import 'package:my_app/Pages/Tabs/login_tap.dart'; -import 'package:my_app/Providers/user_provider.dart'; +import 'package:my_app/Providers/token_manager.dart'; import 'package:my_app/Widgets/HomeScreen/product_hot_sale.dart'; +import 'package:my_app/Widgets/HomeScreen/title_with_more_btn.dart'; import 'package:my_app/Widgets/ProductDetail/buy_now.dart'; import 'package:my_app/Widgets/ProductDetail/header_product.dart'; import 'package:my_app/Widgets/ProductDetail/add_to_store.dart'; import 'package:my_app/models/product_model.dart'; +import 'package:my_app/models/user_model.dart'; import 'package:my_app/utils/constant.dart'; -import 'package:provider/provider.dart'; import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; class ProductDetail extends StatefulWidget { @@ -484,13 +485,7 @@ class _ProductDetailState extends State { children: [ Padding( padding: EdgeInsets.symmetric(horizontal: 5, vertical: 15), - child: Text( - 'Gợi ý sản phẩm mua kèm:', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w700, - ), - ), + child: TitleWithMoreBtn(text: 'Sản phẩm nổi bật:'), ), ProductHotSale(), ], @@ -511,21 +506,35 @@ class _ProductDetailState extends State { showModalBottomSheet( isScrollControlled: true, context: context, - builder: (context) => Provider.of(context) - .user - .accessToken - .isEmpty - ? LoginTap() - : AddToStore( + builder: (context) => FutureBuilder( + future: TokenManager.getUserfromStorage(), + builder: (context, snapshoot) { + if (snapshoot.data == null) { + return LoginTap(); + } else { + return AddToStore( productId: widget.productDetail.id, variations: widget.productDetail.variations, - ), + ); + } + }, + ), + + // Provider.of(context) + // .user + // .accessToken + // .isEmpty + // ? LoginTap() + // : AddToStore( + // productId: widget.productDetail.id, + // variations: widget.productDetail.variations, + // ), ); }, style: ElevatedButton.styleFrom( backgroundColor: Colors.white, side: BorderSide( - width: 1, + width: 0.5, color: primaryColors, ), shape: RoundedRectangleBorder( diff --git a/lib/Pages/Tabs/reason_cancelled_order.dart b/lib/Pages/Tabs/reason_cancelled_order.dart new file mode 100644 index 0000000..8f87fc4 --- /dev/null +++ b/lib/Pages/Tabs/reason_cancelled_order.dart @@ -0,0 +1,212 @@ +// ignore_for_file: must_be_immutable + +import 'package:flutter/material.dart'; +import 'package:my_app/API/api_order.dart'; +import 'package:my_app/Widgets/Login/button.dart'; +import 'package:my_app/utils/constant.dart'; + +class ReaSonCancelledOrder extends StatefulWidget { + String orderId; + ReaSonCancelledOrder({super.key, required this.orderId}); + + @override + State createState() => _ReaSonCancelledOrderState(); +} + +class _ReaSonCancelledOrderState extends State { + String? currentOption; // Declare currentOption at the class level + final TextEditingController reaSonCancelledController = + TextEditingController(); + GlobalKey _formKey = GlobalKey(); + List reaSonCancelled = [ + 'Đặt nhầm sản phẩm', + 'Phí vận chuyển cao', + 'Đơn trùng', + 'Không muốn mua nữa', + 'Lý do khác' + ]; + + String sendReaSonStringtToSever = ''; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text( + 'Lý do hủy đơn hàng', + style: TextStyle(color: Colors.black), + ), + foregroundColor: primaryColors, + elevation: 0, + ), + body: Column( + children: [ + RadioListTile( + title: Text(reaSonCancelled[0]), + groupValue: currentOption, + value: reaSonCancelled[0], + onChanged: (newValue) { + setState(() { + currentOption = newValue.toString(); + }); + }, + activeColor: primaryColors, + ), + RadioListTile( + title: Text(reaSonCancelled[1]), + value: reaSonCancelled[1], + groupValue: currentOption, + onChanged: (newValue) { + setState(() { + currentOption = newValue.toString(); + }); + }, + activeColor: primaryColors, + ), + RadioListTile( + groupValue: currentOption, + title: Text(reaSonCancelled[2]), + value: reaSonCancelled[2], + onChanged: (newValue) { + setState(() { + currentOption = newValue.toString(); + }); + }, + activeColor: primaryColors, + ), + RadioListTile( + groupValue: currentOption, + title: Text(reaSonCancelled[3]), + value: reaSonCancelled[3], + onChanged: (newValue) { + setState(() { + currentOption = newValue.toString(); + }); + }, + activeColor: primaryColors, + ), + RadioListTile( + groupValue: currentOption, + title: Text(reaSonCancelled[4]), + value: reaSonCancelled[4], + onChanged: (newValue) { + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: Text('Lý do hủy đơn'), + content: Form( + key: _formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'Cho chúng tôi biết lý do bạn muốn hủy đơn để có thể cải thiện chất lượng dịch vụ'), + SizedBox(height: 10), + Container( + color: Colors.white, + child: Padding( + padding: + const EdgeInsets.only(left: 10.0, top: 5), + child: TextFormField( + controller: reaSonCancelledController, + decoration: InputDecoration( + border: InputBorder.none, + hintStyle: TextStyle( + color: Colors.grey.withOpacity(0.5), + ), + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Vui lòng nhập lý do hủy đơn'; + } + return null; + }, + onChanged: (value) { + setState(() { + currentOption = value; + }); + }, + ), + ), + ), + ], + ), + ), + actions: [ + Padding( + padding: const EdgeInsets.only(right: 15.0), + child: ElevatedButton( + onPressed: () { + if (_formKey.currentState!.validate()) { + Navigator.pop(context); + } + }, + style: ElevatedButton.styleFrom( + backgroundColor: primaryColors), + child: const Text( + 'Hoàn thành', + style: TextStyle(fontSize: 16, color: Colors.white), + ), + ), + ), + ], + ); + }, + ); + setState(() { + currentOption = newValue.toString(); + }); + }, + activeColor: primaryColors, + ), + Padding( + padding: const EdgeInsets.all(10.0), + child: Column(children: [ + if (currentOption == null) + ElevatedButton( + onPressed: () { + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: Text('Lỗi'), + content: Text('Vui lòng chọn lý do hủy đơn hàng.'), + actions: [ + ElevatedButton( + onPressed: () { + Navigator.pop(context); + }, + child: Text('OK'), + ), + ], + ); + }, + ); + }, + child: Text('Hủy đơn hàng', + style: + const TextStyle(fontSize: 20, color: Colors.white)), + style: ElevatedButton.styleFrom( + minimumSize: const Size.fromHeight(55), + backgroundColor: Colors.grey, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + ), + ) + else + ButtonSendrequest( + text: 'Hủy đơn hàng', + submit: () { + OrderApi().cancelOrder(context, + orderId: widget.orderId, + reaSonCancelled: currentOption!); + }) + ]), + ) + ], + ), + ); + } +} diff --git a/lib/Pages/Tabs/user_profile.dart b/lib/Pages/Tabs/user_profile.dart index 95d59e6..d857e60 100644 --- a/lib/Pages/Tabs/user_profile.dart +++ b/lib/Pages/Tabs/user_profile.dart @@ -7,7 +7,7 @@ import 'package:my_app/Providers/user_provider.dart'; import 'package:my_app/Widgets/Login/button.dart'; import 'package:my_app/Widgets/SettingScreen/setting_title.dart'; import 'package:my_app/models/setting.dart'; -import 'package:my_app/models/user_models.dart'; +import 'package:my_app/models/user_model.dart'; import 'package:my_app/utils/constant.dart'; import 'package:provider/provider.dart'; @@ -69,7 +69,7 @@ class _UserProfileState extends State { backgroundImage: user.avatar.url.isEmpty ? const AssetImage('assets/icons/profile.png') : NetworkImage(user.avatar.url) as ImageProvider, - backgroundColor: primaryColors, + backgroundColor: Colors.white, ), const SizedBox(width: 10), Column( @@ -104,11 +104,13 @@ class _UserProfileState extends State { borderRadius: BorderRadius.circular(20), ), child: Column( - children: List.generate( - settings.length, - (index) => SettingTitle( - settings: settings[index], - ))), + children: List.generate( + settings.length, + (index) => SettingTitle( + settings: settings[index], + ), + ), + ), ), const SizedBox(height: 30), Container( diff --git a/lib/Providers/token_manager.dart b/lib/Providers/token_manager.dart index 1cdd2d6..fab07e2 100644 --- a/lib/Providers/token_manager.dart +++ b/lib/Providers/token_manager.dart @@ -1,6 +1,6 @@ import 'dart:convert'; -import 'package:my_app/models/user_models.dart'; +import 'package:my_app/models/user_model.dart'; import 'package:shared_preferences/shared_preferences.dart'; class TokenManager { diff --git a/lib/Providers/user_provider.dart b/lib/Providers/user_provider.dart index 4cba1cd..055acea 100644 --- a/lib/Providers/user_provider.dart +++ b/lib/Providers/user_provider.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:my_app/models/user_models.dart'; +import 'package:my_app/models/user_model.dart'; import 'package:shared_preferences/shared_preferences.dart'; class UserProvider extends ChangeNotifier { diff --git a/lib/Widgets/Address/button_in_address.dart b/lib/Widgets/Address/button_in_address.dart index c3226f9..6111abc 100644 --- a/lib/Widgets/Address/button_in_address.dart +++ b/lib/Widgets/Address/button_in_address.dart @@ -14,15 +14,15 @@ class ButtonInAddress extends StatelessWidget { child: ElevatedButton( onPressed: functionAddress, style: ElevatedButton.styleFrom( - minimumSize: const Size.fromHeight(55), + minimumSize: Size.fromHeight(55), backgroundColor: primaryColors, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), + borderRadius: BorderRadius.circular(10), ), ), child: Text( textInAddress, - style: const TextStyle(fontSize: 20, color: Colors.white), + style: TextStyle(fontSize: 20, color: Colors.white), ), ), ); diff --git a/lib/Widgets/Cart/open_diaolog_address.dart b/lib/Widgets/Cart/open_diaolog_address.dart index 931d39d..f99196d 100644 --- a/lib/Widgets/Cart/open_diaolog_address.dart +++ b/lib/Widgets/Cart/open_diaolog_address.dart @@ -6,6 +6,7 @@ import 'package:my_app/Pages/Tabs/change_address.dart'; import 'package:my_app/Providers/user_provider.dart'; import 'package:my_app/Widgets/Login/button.dart'; import 'package:my_app/models/address_model.dart'; +import 'package:my_app/models/cart_model.dart'; import 'package:my_app/utils/constant.dart'; import 'package:provider/provider.dart'; @@ -13,9 +14,10 @@ class OpenDialogAddreess extends StatefulWidget { final productCart; final List productSelected; - const OpenDialogAddreess( - {Key? key, required this.productSelected, required this.productCart}) - : super(key: key); + const OpenDialogAddreess({ + required this.productSelected, + required this.productCart, + }); @override State createState() => _OpenDialogAddreessState(); @@ -25,224 +27,232 @@ class _OpenDialogAddreessState extends State { int valueChecked = 0; void getReviewOrder() { + List selectedProducts = []; + + for (int i = 0; i < widget.productCart.length; i++) { + if (i < widget.productSelected.length && widget.productSelected[i]) { + selectedProducts.add(widget.productCart[i]); + } + } + OrderApi().reviewOrder( context: context, addressSelected: valueChecked, - productSelected: (widget.productCart), + productSelected: selectedProducts, ); } @override Widget build(BuildContext context) { - List addressUser = - Provider.of(context, listen: false).user.address; return Container( - height: MediaQuery.of(context).size.height * 0.50, + color: Colors.white, + height: MediaQuery.of(context).size.height * 0.60, child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: ListView.builder( - itemCount: addressUser.length, - itemBuilder: (context, index) { - return Column( + Column( + children: [ + Padding( + padding: EdgeInsets.all(20), + child: Text( + 'Địa chỉ của tôi', + style: TextStyle( + color: primaryColors, + fontSize: 20, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + _buildMyAddress(), + _buildNewAddress(), + Padding( + padding: EdgeInsets.all(15), + child: ButtonSendrequest( + text: "Xác nhận", + submit: getReviewOrder, + ), + ), + ], + ), + ); + } + + Widget _buildMyAddress() { + List addressUser = + Provider.of(context, listen: false).user.address; + + return Expanded( + child: ListView.builder( + itemCount: addressUser.length, + itemBuilder: (context, index) { + final userAndAddress = addressUser[index]; + return Column( + children: [ + Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border( + bottom: BorderSide( + color: Colors.grey.withOpacity(0.5), + width: 1, + ), + ), + ), + padding: EdgeInsets.only(top: 10, bottom: 10), + child: Row( children: [ - Container( - decoration: BoxDecoration( - color: Colors.white, - border: Border( - bottom: BorderSide( - color: Colors.grey.withOpacity(0.5), - width: 1, - ), - ), - ), - padding: const EdgeInsets.only(top: 10, bottom: 10), - child: Row( - children: [ - Radio( - activeColor: primaryColors, - value: index, - groupValue: valueChecked, - onChanged: (val) { - setState( - () { - valueChecked = val!; - }, - ); - }, - ), - Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only( - left: 10.0, bottom: 5), - child: Row( - children: [ - Container( - constraints: BoxConstraints( - maxWidth: MediaQuery.of(context) - .size - .width * - 0.5), - child: Text( - addressUser[index].customerName, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ), - const SizedBox(width: 15), - const SizedBox( - height: 18, - child: VerticalDivider( - color: Colors.black, - thickness: 1, - ), - ), - SizedBox( - width: MediaQuery.of(context).size.width * - 0.3, - child: Text( - addressUser[index].phoneNumbers, - style: const TextStyle( - color: Colors.grey, - fontSize: 16, - fontWeight: FontWeight.w500, - ), - ), - ) - ], - ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only( - left: 10.0, top: 5), - child: Text( - addressUser[index].detail, - style: const TextStyle( - color: Colors.grey, - fontSize: 14, - fontWeight: FontWeight.w500, - ), - ), - ), - ], + Radio( + activeColor: primaryColors, + value: index, + groupValue: valueChecked, + onChanged: (val) { + setState( + () { + valueChecked = val!; + }, + ); + }, + ), + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + '${userAndAddress.customerName}', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + color: Colors.black, ), - Padding( - padding: const EdgeInsets.all(10.0), - child: Text( - '${addressUser[index].wardLevel.wardName}, ', - style: const TextStyle( - color: Colors.grey, - fontSize: 14, - fontWeight: FontWeight.w500, - ), - ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + SizedBox(width: 5), + Text( + '|', + style: TextStyle( + color: Colors.black54, + fontSize: 16, + fontWeight: FontWeight.w500, ), - Padding( - padding: const EdgeInsets.only(left: 10.0), - child: Row( - children: [ - Text( - '${addressUser[index].districtLevel.district_name}, ', - style: const TextStyle( - color: Colors.grey, - fontSize: 14, - fontWeight: FontWeight.w500, - ), - ), - Text( - addressUser[index] - .provinceLevel - .province_name, - style: const TextStyle( - color: Colors.grey, - fontSize: 14, - fontWeight: FontWeight.w500, - ), - ), - ], - ), + ), + SizedBox(width: 5), + Text( + '${userAndAddress.phoneNumbers}', + style: TextStyle( + color: Colors.black54, + fontSize: 16, + fontWeight: FontWeight.w500, ), - const SizedBox(height: 5), - ], + ), + ], + ), + SizedBox(height: 10), + Text( + '${userAndAddress.detail}', + style: TextStyle( + color: Colors.black54, + fontSize: 16, + fontWeight: FontWeight.w500, ), - const Spacer(), - TextButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: ((context) => ChangeAddress( - addressUser: addressUser[index], - index: index, - )), - ), - ); - }, - child: const Text( - 'Sửa', + ), + SizedBox(height: 10), + Row( + children: [ + Text( + '${userAndAddress.wardLevel.wardName}, ', style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w700, - color: primaryColors, + color: Colors.black54, + fontSize: 14, + fontWeight: FontWeight.w500, ), ), - ), - ], + Text( + '${userAndAddress.districtLevel.district_name}, ', + style: TextStyle( + color: Colors.black54, + fontSize: 14, + fontWeight: FontWeight.w500, + ), + ), + Text( + '${userAndAddress.provinceLevel.province_name}', + style: TextStyle( + color: Colors.black54, + fontSize: 14, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + SizedBox(height: 5), + ], + ), + Spacer(), + TextButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: ((context) => ChangeAddress( + addressUser: userAndAddress, + index: index, + ))), + ); + }, + child: Text( + 'Sửa', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w700, + color: primaryColors, + ), ), ), ], - ); - }, - ), - ), - InkWell( - onTap: () { - Navigator.push(context, - MaterialPageRoute(builder: (context) => AddAddressTap())); - }, - child: Container( - padding: const EdgeInsets.only(top: 20, bottom: 20), - decoration: const BoxDecoration( - color: Colors.white, - ), - child: const Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - CupertinoIcons.add_circled, - size: 30, - color: primaryColors, - ), - SizedBox(width: 10), - Text( - 'Thêm Địa Chỉ Mới', - style: TextStyle( - color: primaryColors, - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - ], + ), ), + ], + ); + }, + ), + ); + } + + Widget _buildNewAddress() { + return InkWell( + onTap: () { + Navigator.push( + context, MaterialPageRoute(builder: (context) => AddAddressTap())); + }, + child: Container( + padding: EdgeInsets.symmetric(vertical: 20), + decoration: BoxDecoration( + color: Colors.white, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + CupertinoIcons.add_circled, + size: 30, + color: primaryColors, ), - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: ButtonSendrequest( - text: "Xác nhận", - submit: getReviewOrder, + SizedBox(width: 10), + Text( + 'Thêm Địa Chỉ Mới', + style: TextStyle( + color: primaryColors, + fontSize: 18, + fontWeight: FontWeight.w600, + ), ), - ), - ], + ], + ), ), ); } diff --git a/lib/Widgets/HomeScreen/category.dart b/lib/Widgets/HomeScreen/category.dart index 69d3b41..1e9f12d 100644 --- a/lib/Widgets/HomeScreen/category.dart +++ b/lib/Widgets/HomeScreen/category.dart @@ -31,7 +31,8 @@ class _CategoryState extends State { future: ProductAPI().getAllProducts(), builder: (context, snapshot) { if ((snapshot.hasError) || (!snapshot.hasData)) { - return Container( + return Padding( + padding: EdgeInsets.all(15), child: Center( child: CircularProgressIndicator(), ), diff --git a/lib/Widgets/HomeScreen/product_hot_sale.dart b/lib/Widgets/HomeScreen/product_hot_sale.dart index 1c4f7c8..c391e05 100644 --- a/lib/Widgets/HomeScreen/product_hot_sale.dart +++ b/lib/Widgets/HomeScreen/product_hot_sale.dart @@ -32,10 +32,8 @@ class _ProductHotSaleState extends State { future: ProductAPI().getAllProducts(), builder: (context, snapshot) { if ((snapshot.hasError) || (!snapshot.hasData)) { - return Container( - child: Center( - child: CircularProgressIndicator(), - ), + return Center( + child: CircularProgressIndicator(), ); } diff --git a/lib/Widgets/Login/button.dart b/lib/Widgets/Login/button.dart index 9254b94..357128e 100644 --- a/lib/Widgets/Login/button.dart +++ b/lib/Widgets/Login/button.dart @@ -12,15 +12,15 @@ class ButtonSendrequest extends StatelessWidget { return ElevatedButton( onPressed: submit, style: ElevatedButton.styleFrom( - minimumSize: const Size.fromHeight(55), + minimumSize: Size.fromHeight(55), backgroundColor: primaryColors, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), + borderRadius: BorderRadius.circular(10), ), ), child: Text( text, - style: const TextStyle(fontSize: 20, color: Colors.white), + style: TextStyle(fontSize: 20, color: Colors.white), ), ); } diff --git a/lib/Widgets/ProductDetail/add_to_store.dart b/lib/Widgets/ProductDetail/add_to_store.dart index 832f11a..e89e866 100644 --- a/lib/Widgets/ProductDetail/add_to_store.dart +++ b/lib/Widgets/ProductDetail/add_to_store.dart @@ -2,8 +2,10 @@ import 'package:flutter/material.dart'; import 'package:my_app/API/api_cart.dart'; +import 'package:my_app/Pages/Screens/cart_screen.dart'; import 'package:my_app/models/product_model.dart'; import 'package:my_app/utils/constant.dart'; +import 'package:my_app/utils/snackbar.dart'; class AddToStore extends StatefulWidget { final productId; @@ -69,6 +71,13 @@ class _AddToStoreState extends State { sku: selectedSku.toString(), quantity: 1, ); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => CartScreen(), + ), + ); + showSnackBarSuccess(context, 'Thêm thành công'); } @override diff --git a/lib/Widgets/ProductHome/in_frame.dart b/lib/Widgets/ProductHome/in_frame.dart index abf7435..f63ee79 100644 --- a/lib/Widgets/ProductHome/in_frame.dart +++ b/lib/Widgets/ProductHome/in_frame.dart @@ -139,7 +139,7 @@ class _InFrameState extends State { ], ); } - return SizedBox(); + return Container(); }, ), ), diff --git a/lib/main.dart b/lib/main.dart index 87f4108..0691503 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:my_app/Pages/Screens/main_screen.dart'; import 'package:my_app/Providers/product_provider.dart'; import 'package:my_app/Providers/user_provider.dart'; +import 'package:my_app/utils/constant.dart'; import 'package:provider/provider.dart'; void main() async { @@ -24,7 +25,7 @@ class MyApp extends StatelessWidget { return MaterialApp( debugShowCheckedModeBanner: false, theme: ThemeData( - primaryColor: Color.fromARGB(255, 248, 119, 110), + primaryColor: primaryColors, visualDensity: VisualDensity.adaptivePlatformDensity, ), home: MainScreen(), diff --git a/lib/models/address_model.dart b/lib/models/address_model.dart index e08607f..6482e29 100644 --- a/lib/models/address_model.dart +++ b/lib/models/address_model.dart @@ -36,7 +36,7 @@ class AddressModel { districtLevel: DistrictLevel.fromJson(json["districtLevel"]), wardLevel: WardLevel.fromJson(json["wardLevel"]), detail: json["detail"], - isDefault: json["isDefault"], + isDefault: json["isDefault"] ?? true , ); Map toJson() => { diff --git a/lib/models/order_model.dart b/lib/models/order_model.dart index 3bd2402..52dcf01 100644 --- a/lib/models/order_model.dart +++ b/lib/models/order_model.dart @@ -146,24 +146,13 @@ class ShippingOrder { Map toMap() { return { - 'toAddress': toAddress.toJson(), + 'toAddress': toAddress.toMap(), }; } factory ShippingOrder.fromMap(Map map) { return ShippingOrder( - toAddress: map['shippingOrder'] != null - ? AddressModel.fromMap(map['shippingOrder']) - : AddressModel( - addressName: '', - customerName: '', - phoneNumbers: '', - provinceLevel: ProvinceLevel(province_id: 0, province_name: ''), - districtLevel: DistrictLevel(district_id: 0, district_name: ''), - wardLevel: WardLevel(wardCode: '', wardName: ''), - detail: '', - isDefault: true, - ), + toAddress: AddressModel.fromJson(map['toAddress'] ?? {}), ); } diff --git a/lib/models/user_models.dart b/lib/models/user_model.dart similarity index 99% rename from lib/models/user_models.dart rename to lib/models/user_model.dart index d99fd28..f387ddd 100644 --- a/lib/models/user_models.dart +++ b/lib/models/user_model.dart @@ -1,6 +1,5 @@ // ignore_for_file: public_member_api_docs, sort_constructors_first import 'dart:convert'; - import 'package:my_app/models/address_model.dart'; // ignore_for_file: non_constant_identifier_names diff --git a/lib/utils/constant.dart b/lib/utils/constant.dart index 8facd2e..c1a4962 100644 --- a/lib/utils/constant.dart +++ b/lib/utils/constant.dart @@ -12,3 +12,14 @@ extension MyExtension on String { return '${this[0].toUpperCase()}${this.substring(1).toLowerCase()}'; } } + +String formatTimestamp(String timestamp) { + // Parse the input timestamp + DateTime dateTime = DateTime.parse(timestamp); + + // Format the date and time + String formattedDate = + DateFormat('HH:mm || dd \'Tháng\' M, y').format(dateTime); + + return formattedDate; +} diff --git a/lib/utils/snackbar.dart b/lib/utils/snackbar.dart index b12058e..356bab3 100644 --- a/lib/utils/snackbar.dart +++ b/lib/utils/snackbar.dart @@ -1,94 +1,155 @@ import 'package:flutter/material.dart'; import 'dart:convert'; import 'package:http/http.dart' as http; +import 'package:my_app/utils/constant.dart'; void showSnackBarError(BuildContext context, String text) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Container( - padding: const EdgeInsets.all(8), - height: 100, - decoration: const BoxDecoration( - color: Colors.red, - borderRadius: BorderRadius.all( - Radius.circular(20), + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Container( + padding: EdgeInsets.all(10), + child: Row( + children: [ + Icon( + Icons.error_outline, + size: 30, + color: Colors.white, ), - ), - child: Row( - children: [ - const Icon( - Icons.error_outline, - size: 30, - color: Colors.white, - ), - const SizedBox(width: 20), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Thất bại', - style: TextStyle( - fontSize: 18, - color: Colors.white, - ), - ), - Text(text) - ], - ), - ), - ], - ), + SizedBox(width: 5), + Text( + text, + style: TextStyle(fontSize: 18), + ), + ], ), - showCloseIcon: true, - behavior: SnackBarBehavior.floating, - backgroundColor: const Color.fromARGB(255, 255, 239, 239), ), - ); + showCloseIcon: true, + closeIconColor: Colors.white, + behavior: SnackBarBehavior.floating, + backgroundColor: primaryColors, + ) + // SnackBar( + // content: Container( + // padding: const EdgeInsets.all(8), + // height: 100, + // decoration: const BoxDecoration( + // color: Colors.red, + // borderRadius: BorderRadius.all( + // Radius.circular(20), + // ), + // ), + // child: Row( + // children: [ + // const Icon( + // Icons.error_outline, + // size: 30, + // color: Colors.white, + // ), + // const SizedBox(width: 20), + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // const Text( + // 'Thất bại', + // style: TextStyle( + // fontSize: 18, + // color: Colors.white, + // ), + // ), + // Text(text) + // ], + // ), + // ), + // ], + // ), + // ), + // showCloseIcon: true, + // behavior: SnackBarBehavior.floating, + // backgroundColor: const Color.fromARGB(255, 255, 239, 239), + // ), + ); } void showSnackBarSuccess(BuildContext context, String text) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Container( - padding: const EdgeInsets.all(8), - height: 100, - decoration: const BoxDecoration( - color: Colors.green, - borderRadius: BorderRadius.all( - Radius.circular(20), - ), - ), + padding: EdgeInsets.all(10), child: Row( children: [ - const Icon( + Icon( Icons.check_circle, size: 30, color: Colors.white, ), - const SizedBox(width: 20), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Thành công', - style: TextStyle( - fontSize: 18, - color: Colors.white, - ), - ), - Text(text) - ], - ), + SizedBox(width: 5), + Text( + text, + style: TextStyle(fontSize: 18), ), ], ), ), showCloseIcon: true, + closeIconColor: Colors.white, behavior: SnackBarBehavior.floating, - backgroundColor: const Color.fromARGB(255, 255, 239, 239), + backgroundColor: Colors.green, ), + // SnackBar( + // content: Container( + // padding: EdgeInsets.all(8), + // height: 80, + // decoration: BoxDecoration( + // color: Colors.green, + // borderRadius: BorderRadius.all( + // Radius.circular(20), + // ), + // ), + // child: Row( + // children: [ + // Icon( + // Icons.check_circle, + // size: 30, + // color: Colors.white, + // ), + // SizedBox(width: 10), + // Expanded( + // child: Text( + // text, + // style: TextStyle( + // fontSize: 20, + // color: Colors.white, + // ), + // ), + // ), + // // Expanded( + // // child: Column( + // // crossAxisAlignment: CrossAxisAlignment.start, + // // children: [ + // // // const Text( + // // // 'Thành công', + // // // style: TextStyle( + // // // fontSize: 18, + // // // color: Colors.white, + // // // ), + // // // ), + // // Text( + // // text, + // // style: TextStyle( + // // fontSize: 18, + // // color: Colors.white, + // // ), + // // ) + // // ], + // // ), + // // ), + // ], + // ), + // ), + // showCloseIcon: true, + // behavior: SnackBarBehavior.floating, + // backgroundColor: Color.fromARGB(255, 255, 239, 239), + // ), ); } From 62c7c714d44902ede4755dba2d5423ccf306bf72 Mon Sep 17 00:00:00 2001 From: doann221 Date: Wed, 20 Mar 2024 19:53:43 +0700 Subject: [PATCH 3/4] merge again --- lib/Pages/Tabs/cart_tap.dart | 39 +++++----- lib/Pages/Tabs/order_detail.dart | 63 +++------------- pubspec.lock | 119 ++++++++++++++++++++----------- pubspec.yaml | 1 - 4 files changed, 109 insertions(+), 113 deletions(-) diff --git a/lib/Pages/Tabs/cart_tap.dart b/lib/Pages/Tabs/cart_tap.dart index 2c9934d..6be4e60 100644 --- a/lib/Pages/Tabs/cart_tap.dart +++ b/lib/Pages/Tabs/cart_tap.dart @@ -4,10 +4,6 @@ import 'package:my_app/API/api_product.dart'; import 'package:my_app/Pages/Tabs/product_detail.dart'; import 'package:my_app/Providers/product_provider.dart'; import 'package:my_app/Widgets/Cart/open_diaolog_address.dart'; -import 'package:my_app/Pages/Tabs/add_address._tap.dart'; -import 'package:my_app/Pages/Tabs/change_address.dart'; -import 'package:my_app/Providers/product_provider.dart'; -import 'package:my_app/Providers/user_provider.dart'; import 'package:my_app/Widgets/Login/button.dart'; import 'package:my_app/models/cart_model.dart'; import 'package:my_app/models/product_model.dart'; @@ -869,23 +865,30 @@ class _CartTapState extends State { child: ButtonSendrequest( text: 'Mua hàng', submit: () { - - if (productSelected.contains(true)) { - showModalBottomSheet( - context: context, - isScrollControlled: true, - builder: (context) => OpenDialogAddreess( - productSelected: productSelected, - productCart: productCart.product, - ), - ); - } else { - showSnackBarError(context, 'Bạn chưa chọn sản phẩm'); - } + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) => OpenDialogAddreess( + productSelected: productSelected, + productCart: productCart.product, + ), + ); }, ), - ), + + ) ], + + Padding( + padding: EdgeInsets.all(10), + child: ButtonSendrequest( + text: 'Thanh toán', + submit: openDiaologAddress, + ), + ) + ], + ), + ), ); } diff --git a/lib/Pages/Tabs/order_detail.dart b/lib/Pages/Tabs/order_detail.dart index a87af7d..3af647e 100644 --- a/lib/Pages/Tabs/order_detail.dart +++ b/lib/Pages/Tabs/order_detail.dart @@ -16,7 +16,6 @@ import 'package:my_app/models/order_model.dart'; import 'package:my_app/models/product_model.dart'; import 'package:my_app/utils/constant.dart'; - class OrderDetail extends StatefulWidget { OrderUser orderDetail; OrderDetail({super.key, required this.orderDetail}); @@ -51,7 +50,6 @@ class _OrderDetailState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ styleOderStatus(), - Divider(thickness: 0.5), _buildShippingAddressOrder(), Divider(thickness: 0.5), @@ -60,7 +58,6 @@ class _OrderDetailState extends State { __buildPaymentMethodAndSingleCode(), Divider(thickness: 0.5), _buildOrdersInvoice(), - Container( color: Colors.white, child: Padding( @@ -82,29 +79,11 @@ class _OrderDetailState extends State { ), ], ), - Padding( - padding: const EdgeInsets.only(left: 25.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(widget.orderDetail.shippingOrder.toAddress - .customerName), - Text(widget.orderDetail.shippingOrder.toAddress - .phoneNumbers), - Text(widget - .orderDetail.shippingOrder.toAddress.detail), - Row( - children: [ - Text( - '${widget.orderDetail.shippingOrder.toAddress.wardLevel.wardName}, '), - Text( - '${widget.orderDetail.shippingOrder.toAddress.districtLevel.district_name}, '), - Text(widget.orderDetail.shippingOrder.toAddress - .provinceLevel.province_name), - ], - ), - ], - ), + Column( + children: [ + Text(widget + .orderUser.shippingOrder.toAddress.addressName) + ], ) ], ), @@ -584,32 +563,17 @@ class _OrderDetailState extends State { width: MediaQuery.sizeOf(context).width, decoration: BoxDecoration(color: Colors.yellow[800]), child: Padding( - padding: EdgeInsets.all(20.0), + padding: const EdgeInsets.all(20.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Đơn hàng đang chờ xử lý', - style: TextStyle(color: Colors.white), - ), - Text('Vui lòng chờ đợi', - style: TextStyle(color: Colors.white)), - Text('Cảm ơn bạn đã mua hàng tại Techcell', - style: TextStyle(color: Colors.white)) - ], - ), Text( - 'Vui lòng chờ đợi', - style: TextStyle(color: Colors.white), - ), - Text( - 'Cảm ơn bạn đã mua hàng tại Techcell', + 'Đơn hàng đang chờ xử lý', style: TextStyle(color: Colors.white), ), - Icon(CupertinoIcons.rectangle_paperclip) + Text('Vui lòng chờ đợi', style: TextStyle(color: Colors.white)), + Text('Cảm ơn bạn đã mua hàng tại Techcell', + style: TextStyle(color: Colors.white)) ], ), ), @@ -1164,12 +1128,7 @@ class _OrderDetailState extends State { child: ButtonSendrequest( text: 'Hủy đơn hàng', submit: () { - Navigator.push( - context, - MaterialPageRoute( - builder: ((context) => ReaSonCancelledOrder( - orderId: widget.orderDetail.id, - )))); + OrderApi().cancelOrder(context, orderId: widget.orderUser.id); }), ); } else diff --git a/pubspec.lock b/pubspec.lock index 4c52032..a49add5 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,14 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a + url: "https://pub.dev" + source: hosted + version: "61.0.0" _flutterfire_internals: dependency: transitive description: @@ -8,7 +16,7 @@ packages: sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd" url: "https://pub.dev" source: hosted - version: "1.3.25" + version: "1.3.16" animated_bottom_navigation_bar: dependency: "direct main" description: @@ -16,15 +24,7 @@ packages: sha256: "2b04a2ae4b0742669e60ddf309467d6a354cefd2d0cd20f4737b1efaf9834cda" url: "https://pub.dev" source: hosted - version: "1.3.3" - args: - dependency: transitive - description: - name: args - sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 - url: "https://pub.dev" - source: hosted - version: "2.4.2" + version: "1.3.2" async: dependency: transitive description: @@ -117,15 +117,31 @@ packages: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + url: "https://pub.dev" + source: hosted + version: "1.17.2" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "3.1.1" cross_file: dependency: transitive description: name: cross_file - sha256: fedaadfa3a6996f75211d835aaeb8fede285dae94262485698afd832371b9a5e + sha256: "2f9d2cbccb76127ba28528cb3ae2c2326a122446a83de5a056aaa3880d3882c5" + url: "https://pub.dev" + source: hosted + version: "0.3.3+7" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab url: "https://pub.dev" source: hosted version: "0.3.3+8" @@ -408,14 +424,22 @@ packages: url: "https://pub.dev" source: hosted version: "4.6.6" + glob: + dependency: transitive + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" + source: hosted + version: "2.1.2" google_identity_services_web: dependency: transitive description: name: google_identity_services_web - sha256: "0c56c2c5d60d6dfaf9725f5ad4699f04749fb196ee5a70487a46ef184837ccf6" + sha256: "000b7a31e1fa17ee04b6c0553a2b2ea18f9f9352e4dcc0c9fcc785cf10f2484e" url: "https://pub.dev" source: hosted - version: "0.3.0+2" + version: "0.2.2" google_nav_bar: dependency: "direct main" description: @@ -428,10 +452,10 @@ packages: dependency: "direct main" description: name: google_sign_in - sha256: "0b8787cb9c1a68ad398e8010e8c8766bfa33556d2ab97c439fb4137756d7308f" + sha256: "8f8b94880f2753ccb796744259da529674e49b9af2e372abf6978c590c0ebfef" url: "https://pub.dev" source: hosted - version: "6.2.1" + version: "6.1.6" google_sign_in_android: dependency: transitive description: @@ -444,10 +468,10 @@ packages: dependency: transitive description: name: google_sign_in_ios - sha256: a7d653803468d30b82ceb47ea00fe86d23c56e63eb2e5c2248bb68e9df203217 + sha256: f3336d9e44d4d28063ac90271f6db5caf99f0480cb07281330e7a432edb95226 url: "https://pub.dev" source: hosted - version: "5.7.4" + version: "5.7.3" google_sign_in_platform_interface: dependency: transitive description: @@ -460,10 +484,11 @@ packages: dependency: transitive description: name: google_sign_in_web - sha256: a278ea2d01013faf341cbb093da880d0f2a552bbd1cb6ee90b5bebac9ba69d77 + sha256: "794f5494a945d6dd2654c52f979594ecd2558e5c82ce8272295ba371c93015e6" url: "https://pub.dev" source: hosted - version: "0.12.3+2" + + version: "0.12.2+1" html: dependency: transitive description: @@ -476,10 +501,10 @@ packages: dependency: "direct main" description: name: http - sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.1.0" http_parser: dependency: transitive description: @@ -628,18 +653,18 @@ packages: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.9.1" mime: dependency: transitive description: name: mime - sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e url: "https://pub.dev" source: hosted - version: "1.0.5" + version: "1.0.4" nested: dependency: transitive description: @@ -767,7 +792,16 @@ packages: sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c url: "https://pub.dev" source: hosted - version: "6.1.2" + version: "6.1.1" + + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" rxdart: dependency: transitive description: @@ -820,10 +854,10 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21" + sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.1" shared_preferences_windows: dependency: transitive description: @@ -897,18 +931,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.1" string_scanner: dependency: transitive description: @@ -937,10 +971,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.6.0" typed_data: dependency: transitive description: @@ -1113,7 +1147,7 @@ packages: dependency: transitive description: name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 url: "https://pub.dev" source: hosted version: "0.3.0" @@ -1148,15 +1182,16 @@ packages: sha256: "9bf168bccdf179ce90450b5f37e36fe263f591c9338828d6bf09b6f8d0f57f86" url: "https://pub.dev" source: hosted - version: "3.12.0" + version: "3.10.2" + version: "0.3.0" win32: dependency: transitive description: name: win32 - sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8" + sha256: b0f37db61ba2f2e9b7a78a1caece0052564d1bc70668156cf3a29d676fe4e574 url: "https://pub.dev" source: hosted - version: "5.2.0" + version: "5.1.1" xdg_directories: dependency: transitive description: @@ -1174,5 +1209,5 @@ packages: source: hosted version: "6.5.0" sdks: - dart: ">=3.2.3 <4.0.0" - flutter: ">=3.16.6" + dart: ">=3.2.0 <4.0.0" + flutter: ">=3.16.0" diff --git a/pubspec.yaml b/pubspec.yaml index 824fdd3..099a446 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -53,7 +53,6 @@ dependencies: socket_io_client: ^2.0.3+1 intl: ^0.19.0 flutter_widget_from_html: ^0.14.11 - dev_dependencies: From 60b9d974fbdf3894c6926e7079d4e44c75e5fcd2 Mon Sep 17 00:00:00 2001 From: doann221 Date: Wed, 27 Mar 2024 20:15:31 +0700 Subject: [PATCH 4/4] create splash screen change Icon app --- android/app/src/main/AndroidManifest.xml | 4 +- .../res/drawable-night-v21/background.png | Bin 0 -> 69 bytes .../drawable-night-v21/launch_background.xml | 6 + .../main/res/drawable-night/background.png | Bin 0 -> 69 bytes .../res/drawable-night/launch_background.xml | 6 + .../src/main/res/drawable-v21/background.png | Bin 0 -> 69 bytes .../res/drawable-v21/launch_background.xml | 12 +- .../app/src/main/res/drawable/background.png | Bin 0 -> 69 bytes .../main/res/drawable/launch_background.xml | 12 +- .../main/res/mipmap-hdpi/launcher_icon.png | Bin 0 -> 6450 bytes .../main/res/mipmap-mdpi/launcher_icon.png | Bin 0 -> 3433 bytes .../main/res/mipmap-xhdpi/launcher_icon.png | Bin 0 -> 9779 bytes .../main/res/mipmap-xxhdpi/launcher_icon.png | Bin 0 -> 17642 bytes .../main/res/mipmap-xxxhdpi/launcher_icon.png | Bin 0 -> 26443 bytes .../src/main/res/values-night-v31/styles.xml | 19 + .../app/src/main/res/values-night/styles.xml | 4 + .../app/src/main/res/values-v31/styles.xml | 19 + android/app/src/main/res/values/styles.xml | 4 + android/build.gradle | 22 +- assets/logos/app_icon_64.png | Bin 0 -> 5160 bytes .../Icon-App-1024x1024@1x.png | Bin 10932 -> 288371 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 295 -> 987 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 406 -> 2589 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 450 -> 4662 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 282 -> 1629 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 462 -> 4524 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 704 -> 8506 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 406 -> 2589 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 586 -> 7537 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 862 -> 13685 bytes .../AppIcon.appiconset/Icon-App-50x50@1x.png | Bin 0 -> 3566 bytes .../AppIcon.appiconset/Icon-App-50x50@2x.png | Bin 0 -> 10320 bytes .../AppIcon.appiconset/Icon-App-57x57@1x.png | Bin 0 -> 4295 bytes .../AppIcon.appiconset/Icon-App-57x57@2x.png | Bin 0 -> 12516 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 862 -> 13685 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 1674 -> 24043 bytes .../AppIcon.appiconset/Icon-App-72x72@1x.png | Bin 0 -> 6450 bytes .../AppIcon.appiconset/Icon-App-72x72@2x.png | Bin 0 -> 17642 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 762 -> 6918 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 1226 -> 18961 bytes .../Icon-App-83.5x83.5@2x.png | Bin 1418 -> 21704 bytes .../LaunchBackground.imageset/Contents.json | 22 + .../LaunchBackground.imageset/background.png | Bin 0 -> 69 bytes .../darkbackground.png | Bin 0 -> 69 bytes .../LaunchImage.imageset/Contents.json | 10 +- .../LaunchImage.imageset/LaunchImage.png | Bin 68 -> 69 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 68 -> 69 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 68 -> 69 bytes ios/Runner/Base.lproj/LaunchScreen.storyboard | 15 +- ios/Runner/Info.plist | 92 +-- lib/API/api_login.dart | 2 +- lib/API/api_notification.dart | 9 +- lib/API/api_sign_up.dart | 29 - lib/Pages/Screens/noti_screen.dart | 23 +- lib/Pages/Tabs/cart_tap.dart | 332 +--------- lib/Pages/Tabs/change_address.dart | 42 +- lib/Pages/Tabs/order_detail.dart | 571 +++--------------- lib/Pages/Tabs/product_detail.dart | 66 +- lib/Widgets/ProductDetail/add_to_store.dart | 1 + lib/Widgets/ProductHome/in_frame.dart | 55 +- lib/main.dart | 7 +- .../AppIcon.appiconset/Contents.json | 132 ++-- .../AppIcon.appiconset/app_icon_1024.png | Bin 59192 -> 288371 bytes .../AppIcon.appiconset/app_icon_128.png | Bin 4533 -> 14920 bytes .../AppIcon.appiconset/app_icon_16.png | Bin 520 -> 745 bytes .../AppIcon.appiconset/app_icon_256.png | Bin 10470 -> 39921 bytes .../AppIcon.appiconset/app_icon_32.png | Bin 1066 -> 1956 bytes .../AppIcon.appiconset/app_icon_512.png | Bin 23788 -> 107121 bytes .../AppIcon.appiconset/app_icon_64.png | Bin 2145 -> 5160 bytes pubspec.lock | 307 ++++++---- pubspec.yaml | 164 +++++ windows/runner/resources/app_icon.ico | Bin 33772 -> 3455 bytes 72 files changed, 823 insertions(+), 1164 deletions(-) create mode 100644 android/app/src/main/res/drawable-night-v21/background.png create mode 100644 android/app/src/main/res/drawable-night-v21/launch_background.xml create mode 100644 android/app/src/main/res/drawable-night/background.png create mode 100644 android/app/src/main/res/drawable-night/launch_background.xml create mode 100644 android/app/src/main/res/drawable-v21/background.png create mode 100644 android/app/src/main/res/drawable/background.png create mode 100644 android/app/src/main/res/mipmap-hdpi/launcher_icon.png create mode 100644 android/app/src/main/res/mipmap-mdpi/launcher_icon.png create mode 100644 android/app/src/main/res/mipmap-xhdpi/launcher_icon.png create mode 100644 android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png create mode 100644 android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png create mode 100644 android/app/src/main/res/values-night-v31/styles.xml create mode 100644 android/app/src/main/res/values-v31/styles.xml create mode 100644 assets/logos/app_icon_64.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png create mode 100644 ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json create mode 100644 ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png create mode 100644 ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index d2d3a99..4fa423e 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:icon="@mipmap/launcher_icon"> + + + + + diff --git a/android/app/src/main/res/drawable-night/background.png b/android/app/src/main/res/drawable-night/background.png new file mode 100644 index 0000000000000000000000000000000000000000..71e9c817e8c3531d8b353b9818aeece0e1e64971 GIT binary patch literal 69 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1SBVv2j2ryJf1F&Ar*|ti3tfno(Kc$izVN6 PfGh@2S3j3^P6 + + + + + diff --git a/android/app/src/main/res/drawable-v21/background.png b/android/app/src/main/res/drawable-v21/background.png new file mode 100644 index 0000000000000000000000000000000000000000..3107d37fa533216ce211fdcdd7c9b8633fab4cc4 GIT binary patch literal 69 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1SBVv2j2ryJf1F&Ar*|tKmY%?XJF%FW@0Ma R`v54;;OXk;vd$@?2>`rk4}t&y literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml index f74085f..f88598c 100644 --- a/android/app/src/main/res/drawable-v21/launch_background.xml +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -1,12 +1,6 @@ - - - - - + + + diff --git a/android/app/src/main/res/drawable/background.png b/android/app/src/main/res/drawable/background.png new file mode 100644 index 0000000000000000000000000000000000000000..3107d37fa533216ce211fdcdd7c9b8633fab4cc4 GIT binary patch literal 69 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1SBVv2j2ryJf1F&Ar*|tKmY%?XJF%FW@0Ma R`v54;;OXk;vd$@?2>`rk4}t&y literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml index 304732f..f88598c 100644 --- a/android/app/src/main/res/drawable/launch_background.xml +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -1,12 +1,6 @@ - - - - - + + + diff --git a/android/app/src/main/res/mipmap-hdpi/launcher_icon.png b/android/app/src/main/res/mipmap-hdpi/launcher_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..df741c4d613d48c3fcb31d52323953fbf0b4e02f GIT binary patch literal 6450 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 LNkvXXu0mjfWn!5x literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..857458196b536ee5c4c99ce0febd87a51ab8a890 GIT binary patch literal 9779 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 N002ovPDHLkV1l;Uw9Nnj literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..db0462a3a2880111e6f8d17a9c9f80346bcadb18 GIT binary patch literal 17642 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 + + + + + + diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml index 06952be..dbc9ea9 100644 --- a/android/app/src/main/res/values-night/styles.xml +++ b/android/app/src/main/res/values-night/styles.xml @@ -5,6 +5,10 @@ @drawable/launch_background + false + false + false + shortEdges + + + + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index cb1ef88..0d1fa8f 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -5,6 +5,10 @@ @drawable/launch_background + false + false + false + shortEdges