From bdcd88945d12ba7399bec322d5d29f6ee94e08ed Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Sat, 14 May 2022 16:14:57 +0700 Subject: [PATCH 01/49] Update gradle configs for build android --- android/app/build.gradle | 4 ++-- android/app/src/main/AndroidManifest.xml | 7 ++++--- android/build.gradle | 4 ++-- .../gradle/wrapper/gradle-wrapper.properties | 2 +- ios/Flutter/flutter_export_environment.sh | 11 +++++------ pubspec.lock | 17 ++++++++++++----- 6 files changed, 26 insertions(+), 19 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 8ef25fd0..231052c8 100755 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -32,7 +32,7 @@ if (keystorePropertiesFile.exists()) { } android { - compileSdkVersion 28 + compileSdkVersion 31 sourceSets { main.java.srcDirs += 'src/main/kotlin' @@ -46,7 +46,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.int2.ecommerce_int2" minSdkVersion 16 - targetSdkVersion 28 + targetSdkVersion 31 versionCode flutterVersionCode.toInteger() versionName flutterVersionName testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index fcdfbdc1..7945117d 100755 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -21,13 +21,14 @@ until Flutter renders its first frame. It can be removed if there is no splash screen (such as the default splash screen defined in @style/LaunchTheme). --> - + + diff --git a/android/build.gradle b/android/build.gradle index 3100ad2d..714549c2 100755 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,12 +1,12 @@ buildscript { - ext.kotlin_version = '1.3.50' + ext.kotlin_version = '1.6.10' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.0' + classpath 'com.android.tools.build:gradle:4.1.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 556d288e..a9282f15 100755 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip diff --git a/ios/Flutter/flutter_export_environment.sh b/ios/Flutter/flutter_export_environment.sh index 7f60bd78..c9bda9d4 100755 --- a/ios/Flutter/flutter_export_environment.sh +++ b/ios/Flutter/flutter_export_environment.sh @@ -1,14 +1,13 @@ #!/bin/sh # This is a generated file; do not edit or check into version control. -export "FLUTTER_ROOT=/Users/macbooki9/Documents/flutter" -export "FLUTTER_APPLICATION_PATH=/Users/macbooki9/Documents/personal/flutter_ecommerce_template" +export "FLUTTER_ROOT=D:\Flutter\flutter_windows_1.22.5-stable\flutter" +export "FLUTTER_APPLICATION_PATH=D:\Workspace\Flutter\do-an\flutter_ecommerce_template" export "COCOAPODS_PARALLEL_CODE_SIGN=true" -export "FLUTTER_TARGET=/Users/macbooki9/Documents/personal/flutter_ecommerce_template/lib/main.dart" +export "FLUTTER_TARGET=lib\main.dart" export "FLUTTER_BUILD_DIR=build" export "FLUTTER_BUILD_NAME=1.0.1" export "FLUTTER_BUILD_NUMBER=1.0.1" -export "DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==" export "DART_OBFUSCATION=false" -export "TRACK_WIDGET_CREATION=true" +export "TRACK_WIDGET_CREATION=false" export "TREE_SHAKE_ICONS=false" -export "PACKAGE_CONFIG=/Users/macbooki9/Documents/personal/flutter_ecommerce_template/.dart_tool/package_config.json" +export "PACKAGE_CONFIG=.packages" diff --git a/pubspec.lock b/pubspec.lock index 6f43fd5b..a6a35cbc 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -42,7 +42,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.8.1" + version: "2.8.2" boolean_selector: dependency: transitive description: @@ -119,7 +119,7 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0" charcode: dependency: transitive description: @@ -381,7 +381,14 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10" + version: "0.12.11" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.3" meta: dependency: transitive description: @@ -561,7 +568,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.2" + version: "0.4.8" timing: dependency: transitive description: @@ -589,7 +596,7 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" watcher: dependency: transitive description: From faef926e12e99e6540de4bf59ff5382f39dc11ee Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Mon, 16 May 2022 08:33:16 +0700 Subject: [PATCH 02/49] Add packages --- pubspec.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pubspec.yaml b/pubspec.yaml index 9f6e6bb9..9bd24cbe 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -34,6 +34,9 @@ dependencies: numberpicker: ^2.1.1 flare_splash_screen: ^4.0.0 flutter_svg: ^0.23.0+1 + get: ^4.6.3 + dio: ^4.0.6 + get_storage: ^2.0.3 dev_dependencies: From caf9a6e4aa139f18f96a437fb444f69a71ace4f5 Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Mon, 16 May 2022 10:00:17 +0700 Subject: [PATCH 03/49] Add base setup for Getx --- .flutter-plugins-dependencies | 1 + ios/Flutter/Flutter.podspec | 18 -- lib/app_properties.dart | 4 +- lib/data/provider/auth.provider.dart | 0 lib/data/repository/auth.repository.dart | 0 lib/interceptor/dio_interceptor.dart | 34 ++++ lib/main.dart | 17 +- lib/services/auth.service.dart | 23 +++ lib/services/network.service.dart | 203 +++++++++++++++++++++++ pubspec.lock | 116 ++++++++++++- pubspec.yaml | 3 +- 11 files changed, 393 insertions(+), 26 deletions(-) create mode 100644 .flutter-plugins-dependencies delete mode 100755 ios/Flutter/Flutter.podspec create mode 100644 lib/data/provider/auth.provider.dart create mode 100644 lib/data/repository/auth.repository.dart create mode 100644 lib/interceptor/dio_interceptor.dart create mode 100644 lib/services/auth.service.dart create mode 100644 lib/services/network.service.dart diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies new file mode 100644 index 00000000..0eccc216 --- /dev/null +++ b/.flutter-plugins-dependencies @@ -0,0 +1 @@ +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2022-05-16 09:54:21.342693","version":"2.10.4"} \ No newline at end of file diff --git a/ios/Flutter/Flutter.podspec b/ios/Flutter/Flutter.podspec deleted file mode 100755 index 5ca30416..00000000 --- a/ios/Flutter/Flutter.podspec +++ /dev/null @@ -1,18 +0,0 @@ -# -# NOTE: This podspec is NOT to be published. It is only used as a local source! -# - -Pod::Spec.new do |s| - s.name = 'Flutter' - s.version = '1.0.0' - s.summary = 'High-performance, high-fidelity mobile apps.' - s.description = <<-DESC -Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS. - DESC - s.homepage = 'https://flutter.io' - s.license = { :type => 'MIT' } - s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } - s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } - s.ios.deployment_target = '8.0' - s.vendored_frameworks = 'Flutter.framework' -end diff --git a/lib/app_properties.dart b/lib/app_properties.dart index 01cfbbf9..176d36b3 100755 --- a/lib/app_properties.dart +++ b/lib/app_properties.dart @@ -19,4 +19,6 @@ const List shadow = [ screenAwareSize(int size, BuildContext context) { double baseHeight = 640.0; return size * MediaQuery.of(context).size.height / baseHeight; -} \ No newline at end of file +} + +const String accessToken = "accessToken"; \ No newline at end of file diff --git a/lib/data/provider/auth.provider.dart b/lib/data/provider/auth.provider.dart new file mode 100644 index 00000000..e69de29b diff --git a/lib/data/repository/auth.repository.dart b/lib/data/repository/auth.repository.dart new file mode 100644 index 00000000..e69de29b diff --git a/lib/interceptor/dio_interceptor.dart b/lib/interceptor/dio_interceptor.dart new file mode 100644 index 00000000..f977588f --- /dev/null +++ b/lib/interceptor/dio_interceptor.dart @@ -0,0 +1,34 @@ +import 'dart:io'; +import 'package:dio/dio.dart'; +import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/services/auth.service.dart'; +import 'package:get_storage/get_storage.dart'; + +class DioInterceptors extends InterceptorsWrapper { + final _store = GetStorage(); + + final AuthService authService; + + DioInterceptors(this.authService); + + @override + Future onRequest( + RequestOptions options, RequestInterceptorHandler handler) async { + String? token = _store.read(accessToken); + if (token != null && token.isNotEmpty) { + options.headers.addAll({ + HttpHeaders.authorizationHeader: 'Bearer $token', + }); + } + + handler.next(options); + } + + @override + void onError(DioError err, ErrorInterceptorHandler handler) { + if (err.response?.statusCode == 401) { + authService.logout(); + } + super.onError(err, handler); + } +} diff --git a/lib/main.dart b/lib/main.dart index 42e4cfed..1f293a92 100755 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,16 +1,25 @@ - import 'package:ecommerce_int2/screens/splash_page.dart'; +import 'package:ecommerce_int2/services/auth.service.dart'; +import 'package:ecommerce_int2/services/network.service.dart'; import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +void main() { + initDependencies(); + runApp(MyApp()); +} - -void main() => runApp(MyApp()); +void initDependencies() { + Get + ..put(AuthService()) + ..put(NetWorkService(Get.find())); +} class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { - return MaterialApp( + return GetMaterialApp( title: 'eCommerce int2', debugShowCheckedModeBanner: false, theme: ThemeData( diff --git a/lib/services/auth.service.dart b/lib/services/auth.service.dart new file mode 100644 index 00000000..e91f6434 --- /dev/null +++ b/lib/services/auth.service.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; +import 'package:get_storage/get_storage.dart'; + +class AuthService extends GetxService { + + final store = GetStorage(); + + void verifyUser() { + + } + + void setAccessToken(String accessToken) { + + } + + void getAccessToken() { + + } + + void logout() { + + } +} \ No newline at end of file diff --git a/lib/services/network.service.dart b/lib/services/network.service.dart new file mode 100644 index 00000000..5b887d01 --- /dev/null +++ b/lib/services/network.service.dart @@ -0,0 +1,203 @@ +import 'package:dio/dio.dart'; +import 'package:ecommerce_int2/interceptor/dio_interceptor.dart'; +import 'package:ecommerce_int2/services/auth.service.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:path_provider/path_provider.dart'; + + +class HttpResponse { + HttpResponse({ + this.body, + this.headers, + this.request, + this.statusCode, + this.statusMessage, + this.extra, + }); + + T? body; + Headers? headers; + RequestOptions? request; + int? statusCode; + String? statusMessage; + Map? extra; +} + +class NetWorkService { + final AuthService authService; + late final Dio? _dio; + + NetWorkService(this.authService); + + Dio getDio() { + if(_dio == null) { + Dio _dio = Dio(); + _dio.interceptors.add(DioInterceptors(authService)); + } + return _dio!; + } + + String? getUriQueryParam(Uri uri, String key) { + final queryParams = uri.queryParametersAll.entries.toList(); + if (queryParams.any((_) => _.key == key)) { + return queryParams.firstWhere((_) => _.key == key).value.first; + } + return null; + } + + FormData mapToFormData(Map map) { + final formData = FormData.fromMap(map); + final FormData newData = FormData(); + + /// + formData.fields.forEach((element) { + newData.fields.add(MapEntry(element.key, element.value)); + }); + + /// + formData.files.forEach((element) { + if (element.key.contains('[') || element.key.contains(']')) { + final newKey = + element.key.replaceAllMapped(RegExp('(\[+[a-zA-Z]+\])'), (m) { + return '${m[0]}'.replaceAll('[', '.').replaceAll(']', ''); + }); + final newValue = element.value; + final newEntry = MapEntry(newKey, newValue); + newData.files.add(newEntry); + } else { + newData.files.add(element); + } + }); + return newData; + } + + Future get(String url, + {Map? queryParameters, Options? options}) async { + final Dio dio = getDio(); + debugPrint("--[GET]--: ${url}"); + final Response response = await dio.get( + url, + queryParameters: queryParameters, + options: options, + ); + return HttpResponse( + body: response.data, + headers: response.headers, + request: response.requestOptions, + statusCode: response.statusCode, + statusMessage: response.statusMessage, + extra: response.extra, + ); + } + + /// + /// Return the stored File path in the TemporaryDirectory + /// + Future downloadFile(String url, + {ProgressCallback? onReceiveProgress, + Map? queryParameters, + Options? options}) async { + final Dio dio = getDio(); + debugPrint("--[DOWNLOAD]--: ${url}"); + final tempDir = await getTemporaryDirectory(); + String filename = ''; + return await dio.download( + url, + (Headers headers) { + List tokens = headers.value('content-disposition')!.split(";"); + for (var i = 0; i < tokens.length; i++) { + if (tokens[i].contains('filename')) { + filename = tokens[i] + .substring(tokens[i].indexOf("=") + 1, tokens[i].length); + } + } + filename = Uri.decodeFull(filename).replaceAll("UTF-8''", ''); + return '${tempDir.path}/$filename'; + }, + onReceiveProgress: onReceiveProgress, + queryParameters: queryParameters, + options: options, + ).then((response) { + return '${tempDir.path}/$filename'; + }, onError: (e) { + throw e; + }); + } + + Future post(String url, + {data, + Map? queryParameters, + Options? options, + Map? formData}) async { + final Dio dio = getDio(); + debugPrint("--[POST]--: ${url}"); + if (formData != null) { + data = mapToFormData(formData); + } + final Response response = await dio.post( + url, + data: data, + queryParameters: queryParameters, + options: options, + ); + return HttpResponse( + body: response.data, + headers: response.headers, + request: response.requestOptions, + statusCode: response.statusCode, + statusMessage: response.statusMessage, + extra: response.extra, + ); + } + + Future put(String url, + {data, + Map? queryParameters, + Options? options, + Map? formData}) async { + final Dio dio = getDio(); + if (formData != null) { + data = mapToFormData(formData); + } + + debugPrint("--[PUT]--: ${url}"); + final Response response = await dio.put( + url, + data: data, + queryParameters: queryParameters, + options: options, + ); + return HttpResponse( + body: response.data, + headers: response.headers, + request: response.requestOptions, + statusCode: response.statusCode, + statusMessage: response.statusMessage, + extra: response.extra, + ); + } + + Future delete( + String url, { + data, + Map? queryParameters, + Options? options, + }) async { + final Dio dio = getDio(); + debugPrint("--[DELETE]--: ${url}"); + final Response response = await dio.delete( + url, + data: data, + queryParameters: queryParameters, + options: options, + ); + return HttpResponse( + body: response.data, + headers: response.headers, + request: response.requestOptions, + statusCode: response.statusCode, + statusMessage: response.statusMessage, + extra: response.extra, + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index a6a35cbc..ed258640 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -197,6 +197,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.1" + dio: + dependency: "direct main" + description: + name: dio + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.6" fake_async: dependency: transitive description: @@ -204,6 +211,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.1" file: dependency: transitive description: @@ -284,6 +298,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.2" + get: + dependency: "direct main" + description: + name: get + url: "https://pub.dartlang.org" + source: hosted + version: "4.6.1" + get_storage: + dependency: "direct main" + description: + name: get_storage + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3" glob: dependency: transitive description: @@ -445,6 +473,55 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.2.1" + path_provider: + dependency: "direct main" + description: + name: path_provider + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.10" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.14" + path_provider_ios: + dependency: transitive + description: + name: path_provider_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.9" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.6" + path_provider_macos: + dependency: transitive + description: + name: path_provider_macos + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.6" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.6" pedantic: dependency: transitive description: @@ -466,6 +543,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.0" + platform: + dependency: transitive + description: + name: platform + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2" pool: dependency: transitive description: @@ -473,6 +564,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.5.0" + process: + dependency: transitive + description: + name: process + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.4" pub_semver: dependency: transitive description: @@ -611,6 +709,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.dartlang.org" + source: hosted + version: "2.5.2" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.0+1" xml: dependency: transitive description: @@ -626,5 +738,5 @@ packages: source: hosted version: "3.1.0" sdks: - dart: ">=2.14.0 <3.0.0" - flutter: ">=1.24.0-7.0" + dart: ">=2.15.0 <3.0.0" + flutter: ">=2.8.1" diff --git a/pubspec.yaml b/pubspec.yaml index 9bd24cbe..9d903321 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -34,9 +34,10 @@ dependencies: numberpicker: ^2.1.1 flare_splash_screen: ^4.0.0 flutter_svg: ^0.23.0+1 - get: ^4.6.3 + get: 4.6.1 dio: ^4.0.6 get_storage: ^2.0.3 + path_provider: ^2.0.10 dev_dependencies: From 32b2db942a9c0e2aa8588d55aaac2e71af30f71c Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Tue, 17 May 2022 16:51:35 +0700 Subject: [PATCH 04/49] Add login and verify user when open app --- lib/data/models/login.result.dart | 18 ++++++++++ lib/data/models/login.result.g.dart | 22 ++++++++++++ lib/data/models/user.model.dart | 18 ++++++++++ lib/data/models/user.model.g.dart | 25 +++++++++++++ lib/data/provider/auth.provider.dart | 20 +++++++++++ lib/data/repository/auth.repository.dart | 31 ++++++++++++++++ lib/main.dart | 9 +++-- lib/screens/auth/welcome_back_page.dart | 27 +++++++------- lib/services/auth.service.dart | 46 +++++++++++++++++++----- 9 files changed, 191 insertions(+), 25 deletions(-) create mode 100644 lib/data/models/login.result.dart create mode 100644 lib/data/models/login.result.g.dart create mode 100644 lib/data/models/user.model.dart create mode 100644 lib/data/models/user.model.g.dart diff --git a/lib/data/models/login.result.dart b/lib/data/models/login.result.dart new file mode 100644 index 00000000..209ee4a1 --- /dev/null +++ b/lib/data/models/login.result.dart @@ -0,0 +1,18 @@ +import 'package:ecommerce_int2/data/models/user.model.dart'; +import 'package:json_annotation/json_annotation.dart'; +part 'login.result.g.dart'; + +@JsonSerializable(explicitToJson: true) +class LoginResult { + final String token; + final bool success; + final UserModel user; + + LoginResult(this.token, this.success, this.user); + + + factory LoginResult.fromJson(Map json) => + _$LoginResultFromJson(json); + + Map toJson() => _$LoginResultToJson(this); +} \ No newline at end of file diff --git a/lib/data/models/login.result.g.dart b/lib/data/models/login.result.g.dart new file mode 100644 index 00000000..df94b3cf --- /dev/null +++ b/lib/data/models/login.result.g.dart @@ -0,0 +1,22 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'login.result.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +LoginResult _$LoginResultFromJson(Map json) { + return LoginResult( + json['token'] as String, + json['success'] as bool, + UserModel.fromJson(json['user'] as Map), + ); +} + +Map _$LoginResultToJson(LoginResult instance) => + { + 'token': instance.token, + 'success': instance.success, + 'user': instance.user.toJson(), + }; diff --git a/lib/data/models/user.model.dart b/lib/data/models/user.model.dart new file mode 100644 index 00000000..8052d56b --- /dev/null +++ b/lib/data/models/user.model.dart @@ -0,0 +1,18 @@ +import 'package:json_annotation/json_annotation.dart'; +part 'user.model.g.dart'; + +@JsonSerializable() +class UserModel { + final String id; + final String firstName; + final String lastName; + final String email; + final String role; + + UserModel(this.id, this.firstName, this.lastName, this.email, this.role); + + factory UserModel.fromJson(Map json) => + _$UserModelFromJson(json); + + Map toJson() => _$UserModelToJson(this); +} diff --git a/lib/data/models/user.model.g.dart b/lib/data/models/user.model.g.dart new file mode 100644 index 00000000..41747ffa --- /dev/null +++ b/lib/data/models/user.model.g.dart @@ -0,0 +1,25 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'user.model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +UserModel _$UserModelFromJson(Map json) { + return UserModel( + json['id'] as String, + json['firstName'] as String, + json['lastName'] as String, + json['email'] as String, + json['role'] as String, + ); +} + +Map _$UserModelToJson(UserModel instance) => { + 'id': instance.id, + 'firstName': instance.firstName, + 'lastName': instance.lastName, + 'email': instance.email, + 'role': instance.role, + }; diff --git a/lib/data/provider/auth.provider.dart b/lib/data/provider/auth.provider.dart index e69de29b..2658c015 100644 --- a/lib/data/provider/auth.provider.dart +++ b/lib/data/provider/auth.provider.dart @@ -0,0 +1,20 @@ +import 'package:ecommerce_int2/data/models/login.result.dart'; +import 'package:ecommerce_int2/services/network.service.dart'; + +class AuthProvider { + final NetWorkService networkService; + + AuthProvider(this.networkService); + + final String loginUrl = 'https://ecommerce-api-dut.herokuapp.com/api/auth/login'; + final String userInfoUrl = 'https://ecommerce-api-dut.herokuapp.com/api/user'; + + Future login(String username, String password) { + return networkService.post(loginUrl, data: {"email": username, "password": password}); + } + + Future getUserInfo() { + return networkService.get(userInfoUrl); + } + +} \ No newline at end of file diff --git a/lib/data/repository/auth.repository.dart b/lib/data/repository/auth.repository.dart index e69de29b..2d9d16b7 100644 --- a/lib/data/repository/auth.repository.dart +++ b/lib/data/repository/auth.repository.dart @@ -0,0 +1,31 @@ +import 'dart:ffi'; + +import 'package:ecommerce_int2/data/models/login.result.dart'; +import 'package:ecommerce_int2/data/models/user.model.dart'; +import 'package:ecommerce_int2/data/provider/auth.provider.dart'; + +class AuthRepository { + final AuthProvider provider; + + AuthRepository(this.provider); + + Future login(String username, password) async { + final response = await provider.login(username, password); + if(response.statusCode != 200) { + throw Exception("Login failed"); + } + final result = LoginResult.fromJson(response.body); + return result; + } + + Future getUserInfo() async { + final response = await provider.getUserInfo(); + if(response.statusCode != 200) { + throw Exception("Login failed"); + } + final result = UserModel.fromJson(response.body); + return result; + } + + +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 1f293a92..dd1ce8be 100755 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,3 +1,5 @@ +import 'package:ecommerce_int2/data/provider/auth.provider.dart'; +import 'package:ecommerce_int2/data/repository/auth.repository.dart'; import 'package:ecommerce_int2/screens/splash_page.dart'; import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:ecommerce_int2/services/network.service.dart'; @@ -11,8 +13,11 @@ void main() { void initDependencies() { Get - ..put(AuthService()) - ..put(NetWorkService(Get.find())); + ..put(NetWorkService(Get.find())) + ..put(AuthProvider(Get.find())) + ..put(AuthRepository(Get.find())) + ..put(AuthService(Get.find())) + ; } class MyApp extends StatelessWidget { diff --git a/lib/screens/auth/welcome_back_page.dart b/lib/screens/auth/welcome_back_page.dart index 44ff3166..27c808e5 100755 --- a/lib/screens/auth/welcome_back_page.dart +++ b/lib/screens/auth/welcome_back_page.dart @@ -1,24 +1,25 @@ - import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:flutter/material.dart'; +import 'package:get/get.dart'; import 'register_page.dart'; -class WelcomeBackPage extends StatefulWidget { +class WelcomeBackPage extends StatefulWidget { @override _WelcomeBackPageState createState() => _WelcomeBackPageState(); } class _WelcomeBackPageState extends State { - TextEditingController email = - TextEditingController(text: 'example@email.com'); + TextEditingController email = TextEditingController(); - TextEditingController password = TextEditingController(text: '12345678'); + TextEditingController password = TextEditingController(); @override Widget build(BuildContext context) { + final controller = Get.find(); Widget welcomeBack = Text( - 'Welcome Back Roberto,', + 'Welcome Back', style: TextStyle( color: Colors.white, fontSize: 34.0, @@ -47,8 +48,7 @@ class _WelcomeBackPageState extends State { bottom: 40, child: InkWell( onTap: () { - Navigator.of(context) - .push(MaterialPageRoute(builder: (_) => RegisterPage())); + controller.login(email.text.trim(), password.text.trim()); }, child: Container( width: MediaQuery.of(context).size.width / 2, @@ -149,20 +149,17 @@ class _WelcomeBackPageState extends State { ); return Scaffold( - body: Stack( children: [ - Container( decoration: BoxDecoration( - image: DecorationImage(image: AssetImage('assets/background.jpg'), - fit: BoxFit.cover) - ), + image: DecorationImage( + image: AssetImage('assets/background.jpg'), + fit: BoxFit.cover)), ), Container( decoration: BoxDecoration( - color: transparentYellow, - + color: transparentYellow, ), ), Padding( diff --git a/lib/services/auth.service.dart b/lib/services/auth.service.dart index e91f6434..e7616ed8 100644 --- a/lib/services/auth.service.dart +++ b/lib/services/auth.service.dart @@ -1,23 +1,53 @@ +import 'package:ecommerce_int2/data/models/user.model.dart'; +import 'package:ecommerce_int2/data/repository/auth.repository.dart'; +import 'package:ecommerce_int2/screens/auth/welcome_back_page.dart'; +import 'package:ecommerce_int2/screens/main/main_page.dart'; +import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; class AuthService extends GetxService { + final AuthRepository repository; final store = GetStorage(); - void verifyUser() { - + @override + void onInit() { + verifyUser(); + super.onInit(); } - void setAccessToken(String accessToken) { + UserModel? userModel; - } + AuthService(this.repository); - void getAccessToken() { + void verifyUser() async { + try { + final res = await repository.getUserInfo(); + userModel = res; + Navigator.of(Get.context!) + .pushReplacement(MaterialPageRoute(builder: (_) => MainPage())); + } catch (e) { + Navigator.of(Get.context!).pushReplacement( + MaterialPageRoute(builder: (_) => WelcomeBackPage())); + } + } + Future login(String username, String password) async { + try { + final res = await repository.login(username, password); + userModel = res.user; + Navigator.of(Get.context!) + .pushReplacement(MaterialPageRoute(builder: (_) => MainPage())); + return true; + } catch (e) { + return false; + } } - void logout() { + void setAccessToken(String accessToken) {} - } -} \ No newline at end of file + void getAccessToken() {} + + void logout() {} +} From 068c2e8a5853afae8d3a0bd9dc1c8b5de99b1f0f Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Sat, 21 May 2022 17:06:51 +0700 Subject: [PATCH 05/49] Add auth service --- .flutter-plugins-dependencies | 2 +- lib/data/provider/auth.provider.dart | 28 ++++++++++++++-- lib/data/repository/auth.repository.dart | 21 ++++++++++-- lib/dependencies.dart | 15 +++++++++ lib/interceptor/dio_interceptor.dart | 7 ++-- lib/main.dart | 16 ++-------- lib/screens/auth/forgot_password_page.dart | 14 ++++---- lib/screens/auth/register_page.dart | 21 +++++++++--- lib/screens/auth/welcome_back_page.dart | 27 ++++++++++++++-- lib/services/auth.service.dart | 37 ++++++++++++++++++++-- lib/services/network.service.dart | 5 ++- 11 files changed, 149 insertions(+), 44 deletions(-) create mode 100644 lib/dependencies.dart diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 0eccc216..7d24b2f0 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2022-05-16 09:54:21.342693","version":"2.10.4"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2022-05-21 12:12:05.987807","version":"2.10.4"} \ No newline at end of file diff --git a/lib/data/provider/auth.provider.dart b/lib/data/provider/auth.provider.dart index 2658c015..756b9bc8 100644 --- a/lib/data/provider/auth.provider.dart +++ b/lib/data/provider/auth.provider.dart @@ -6,15 +6,37 @@ class AuthProvider { AuthProvider(this.networkService); - final String loginUrl = 'https://ecommerce-api-dut.herokuapp.com/api/auth/login'; + final String loginUrl = + 'https://ecommerce-api-dut.herokuapp.com/api/auth/login'; + final String registerUrl = + 'https://ecommerce-api-dut.herokuapp.com/api/auth/register'; + final String forgotUrl = + 'https://ecommerce-api-dut.herokuapp.com/api/auth/forgot'; final String userInfoUrl = 'https://ecommerce-api-dut.herokuapp.com/api/user'; Future login(String username, String password) { - return networkService.post(loginUrl, data: {"email": username, "password": password}); + return networkService + .post(loginUrl, data: {"email": username, "password": password}); } Future getUserInfo() { return networkService.get(userInfoUrl); } -} \ No newline at end of file + Future register( + String username, String password, String firstName, String lastName) { + return networkService.post(registerUrl, data: { + "email": username, + "password": password, + "firstName": firstName, + "lastName": lastName + }); + } + + Future forgotPassword( + String email) { + return networkService.post(forgotUrl, data: { + "email": email + }); + } +} diff --git a/lib/data/repository/auth.repository.dart b/lib/data/repository/auth.repository.dart index 2d9d16b7..0ac266e6 100644 --- a/lib/data/repository/auth.repository.dart +++ b/lib/data/repository/auth.repository.dart @@ -11,7 +11,7 @@ class AuthRepository { Future login(String username, password) async { final response = await provider.login(username, password); - if(response.statusCode != 200) { + if (response.statusCode != 200) { throw Exception("Login failed"); } final result = LoginResult.fromJson(response.body); @@ -20,12 +20,27 @@ class AuthRepository { Future getUserInfo() async { final response = await provider.getUserInfo(); - if(response.statusCode != 200) { + if (response.statusCode != 200) { throw Exception("Login failed"); } final result = UserModel.fromJson(response.body); return result; } + Future register(String username, String password, String firstName, + String lastName) async { + final response = + await provider.register(username, password, firstName, lastName); + if (response.statusCode != 200) { + throw Exception("Register failed"); + } + } -} \ No newline at end of file + Future forgotPassword(String email,) async { + final response = + await provider.forgotPassword(email); + if (response.statusCode != 200) { + throw Exception("Wrong email"); + } + } +} diff --git a/lib/dependencies.dart b/lib/dependencies.dart new file mode 100644 index 00000000..2a17a23a --- /dev/null +++ b/lib/dependencies.dart @@ -0,0 +1,15 @@ +import 'package:ecommerce_int2/data/provider/auth.provider.dart'; +import 'package:ecommerce_int2/data/repository/auth.repository.dart'; +import 'package:ecommerce_int2/services/auth.service.dart'; +import 'package:ecommerce_int2/services/network.service.dart'; +import 'package:get/get.dart'; + +class Dependency { + static void init() { + Get + ..put(NetWorkService()) + ..put(AuthProvider(Get.find())) + ..put(AuthRepository(Get.find())) + ..put(AuthService(Get.find())); + } +} diff --git a/lib/interceptor/dio_interceptor.dart b/lib/interceptor/dio_interceptor.dart index f977588f..f87cd478 100644 --- a/lib/interceptor/dio_interceptor.dart +++ b/lib/interceptor/dio_interceptor.dart @@ -2,14 +2,13 @@ import 'dart:io'; import 'package:dio/dio.dart'; import 'package:ecommerce_int2/app_properties.dart'; import 'package:ecommerce_int2/services/auth.service.dart'; +import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; class DioInterceptors extends InterceptorsWrapper { final _store = GetStorage(); - final AuthService authService; - - DioInterceptors(this.authService); + DioInterceptors(); @override Future onRequest( @@ -27,7 +26,7 @@ class DioInterceptors extends InterceptorsWrapper { @override void onError(DioError err, ErrorInterceptorHandler handler) { if (err.response?.statusCode == 401) { - authService.logout(); + Get.find().logout(); } super.onError(err, handler); } diff --git a/lib/main.dart b/lib/main.dart index dd1ce8be..7b0b9299 100755 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,25 +1,13 @@ -import 'package:ecommerce_int2/data/provider/auth.provider.dart'; -import 'package:ecommerce_int2/data/repository/auth.repository.dart'; +import 'package:ecommerce_int2/dependencies.dart'; import 'package:ecommerce_int2/screens/splash_page.dart'; -import 'package:ecommerce_int2/services/auth.service.dart'; -import 'package:ecommerce_int2/services/network.service.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; void main() { - initDependencies(); + Dependency.init(); runApp(MyApp()); } -void initDependencies() { - Get - ..put(NetWorkService(Get.find())) - ..put(AuthProvider(Get.find())) - ..put(AuthRepository(Get.find())) - ..put(AuthService(Get.find())) - ; -} - class MyApp extends StatelessWidget { // This widget is the root of your application. @override diff --git a/lib/screens/auth/forgot_password_page.dart b/lib/screens/auth/forgot_password_page.dart index da7f6a47..14e1c35d 100755 --- a/lib/screens/auth/forgot_password_page.dart +++ b/lib/screens/auth/forgot_password_page.dart @@ -1,8 +1,9 @@ import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:country_code_picker/country_code_picker.dart'; +import 'package:get/get.dart'; import 'confirm_otp_page.dart'; @@ -13,7 +14,7 @@ class ForgotPasswordPage extends StatefulWidget { } class _ForgotPasswordPageState extends State { - TextEditingController phoneNumber = TextEditingController(text: '46834683'); + TextEditingController email = TextEditingController(text: 'Your email'); GlobalKey prefixKey = GlobalKey(); double prefixWidth = 0; @@ -35,6 +36,7 @@ class _ForgotPasswordPageState extends State { @override Widget build(BuildContext context) { + final controller = Get.find(); Widget background = Container( decoration: BoxDecoration( image: DecorationImage( @@ -61,7 +63,7 @@ class _ForgotPasswordPageState extends State { Widget subTitle = Padding( padding: const EdgeInsets.only(right: 56.0), child: Text( - 'Enter your registered mobile number to get the OTP', + 'Enter your registered email', style: TextStyle( color: Colors.white, fontSize: 16.0, @@ -73,13 +75,13 @@ class _ForgotPasswordPageState extends State { bottom: 40, child: InkWell( onTap: () { - Navigator.of(context).push(MaterialPageRoute(builder:(_)=>ConfirmOtpPage())); + controller.forgetPassword(email.text.trim()); }, child: Container( width: MediaQuery.of(context).size.width / 2, height: 80, child: Center( - child: new Text("Send OTP", + child: new Text("Send Email", style: const TextStyle( color: const Color(0xfffefefe), fontWeight: FontWeight.w600, @@ -127,7 +129,7 @@ class _ForgotPasswordPageState extends State { child: Padding( padding: const EdgeInsets.only(top: 8.0), child: TextField( - controller: phoneNumber, + controller: email, style: TextStyle(fontSize: 16.0), keyboardType: TextInputType.phone, ), diff --git a/lib/screens/auth/register_page.dart b/lib/screens/auth/register_page.dart index 8eb312fa..3d6bc346 100755 --- a/lib/screens/auth/register_page.dart +++ b/lib/screens/auth/register_page.dart @@ -1,6 +1,8 @@ import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:flutter/material.dart'; +import 'package:get/get.dart'; import 'forgot_password_page.dart'; @@ -15,11 +17,13 @@ class _RegisterPageState extends State { TextEditingController password = TextEditingController(text: '12345678'); - TextEditingController cmfPassword = TextEditingController(text: '12345678'); + TextEditingController firstName = TextEditingController(text: 'First name'); + TextEditingController lastName = TextEditingController(text: 'Last name'); @override Widget build(BuildContext context) { + final controller = Get.find(); Widget title = Text( 'Glad To Meet You', style: TextStyle( @@ -50,8 +54,7 @@ class _RegisterPageState extends State { bottom: 40, child: InkWell( onTap: () { - Navigator.of(context) - .push(MaterialPageRoute(builder: (_) => ForgotPasswordPage())); + controller.register(email.text, password.text, "first name", "last Name"); }, child: Container( width: MediaQuery.of(context).size.width / 2, @@ -103,7 +106,7 @@ class _RegisterPageState extends State { Padding( padding: const EdgeInsets.only(top: 8.0), child: TextField( - controller: password, + controller: firstName, style: TextStyle(fontSize: 16.0), obscureText: true, ), @@ -111,7 +114,15 @@ class _RegisterPageState extends State { Padding( padding: const EdgeInsets.only(top: 8.0), child: TextField( - controller: cmfPassword, + controller: lastName, + style: TextStyle(fontSize: 16.0), + obscureText: true, + ), + ), + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: TextField( + controller: password, style: TextStyle(fontSize: 16.0), obscureText: true, ), diff --git a/lib/screens/auth/welcome_back_page.dart b/lib/screens/auth/welcome_back_page.dart index 27c808e5..0e274d05 100755 --- a/lib/screens/auth/welcome_back_page.dart +++ b/lib/screens/auth/welcome_back_page.dart @@ -1,4 +1,5 @@ import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/screens/auth/forgot_password_page.dart'; import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -134,7 +135,9 @@ class _WelcomeBackPageState extends State { ), ), InkWell( - onTap: () {}, + onTap: () { + Get.to(() => ForgotPasswordPage()); + }, child: Text( 'Reset password', style: TextStyle( @@ -148,6 +151,24 @@ class _WelcomeBackPageState extends State { ), ); + + Widget register = Padding( + padding: const EdgeInsets.only(bottom: 20), + child: InkWell( + onTap: () { + Get.to(() => RegisterPage()); + }, + child: Text( + 'Register new account', + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 14.0, + ), + ), + ), + ); + return Scaffold( body: Stack( children: [ @@ -174,7 +195,9 @@ class _WelcomeBackPageState extends State { Spacer(flex: 2), loginForm, Spacer(flex: 2), - forgotPassword + register, + Spacer(flex: 1), + forgotPassword, ], ), ) diff --git a/lib/services/auth.service.dart b/lib/services/auth.service.dart index e7616ed8..849f1fe9 100644 --- a/lib/services/auth.service.dart +++ b/lib/services/auth.service.dart @@ -1,3 +1,4 @@ +import 'package:ecommerce_int2/app_properties.dart'; import 'package:ecommerce_int2/data/models/user.model.dart'; import 'package:ecommerce_int2/data/repository/auth.repository.dart'; import 'package:ecommerce_int2/screens/auth/welcome_back_page.dart'; @@ -45,9 +46,39 @@ class AuthService extends GetxService { } } - void setAccessToken(String accessToken) {} + void setAccessToken(String token) { + store.write(accessToken, token); + } + + String getAccessToken() { + final String? token = store.read(accessToken); + if (token == null) throw Exception("Access token not available"); + return token; + } - void getAccessToken() {} + Future register(String username, String password, String firstName, + String lastName) async { + try { + repository.register(username, password, firstName, lastName); + } on Exception catch (e) { + Navigator.of(Get.context!).pushReplacement( + MaterialPageRoute(builder: (_) => WelcomeBackPage())); + } + } - void logout() {} + Future forgetPassword(String email) async { + try { + repository.forgotPassword(email); + } on Exception catch (e) { + } finally { + Navigator.of(Get.context!).pushReplacement( + MaterialPageRoute(builder: (_) => WelcomeBackPage())); + } + } + + void logout() { + store.remove(accessToken); + Navigator.of(Get.context!) + .pushReplacement(MaterialPageRoute(builder: (_) => WelcomeBackPage())); + } } diff --git a/lib/services/network.service.dart b/lib/services/network.service.dart index 5b887d01..9bcadcd3 100644 --- a/lib/services/network.service.dart +++ b/lib/services/network.service.dart @@ -24,15 +24,14 @@ class HttpResponse { } class NetWorkService { - final AuthService authService; late final Dio? _dio; - NetWorkService(this.authService); + NetWorkService(); Dio getDio() { if(_dio == null) { Dio _dio = Dio(); - _dio.interceptors.add(DioInterceptors(authService)); + _dio.interceptors.add(DioInterceptors()); } return _dio!; } From 350447a58a5ade838ddc7d346500b9348ed1042d Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Sat, 21 May 2022 17:24:46 +0700 Subject: [PATCH 06/49] Add reset password --- .flutter-plugins-dependencies | 2 +- lib/app_properties.dart | 3 ++- lib/data/models/user.model.dart | 13 +++++++------ lib/data/models/user.model.g.dart | 12 +++++++----- lib/data/provider/auth.provider.dart | 21 ++++++++++++++++----- lib/data/repository/auth.repository.dart | 8 ++++++++ lib/services/auth.service.dart | 7 +++++++ 7 files changed, 48 insertions(+), 18 deletions(-) diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 7d24b2f0..f7ec9eaf 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2022-05-21 12:12:05.987807","version":"2.10.4"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2022-05-21 17:10:51.919114","version":"2.10.4"} \ No newline at end of file diff --git a/lib/app_properties.dart b/lib/app_properties.dart index 176d36b3..bbaa741b 100755 --- a/lib/app_properties.dart +++ b/lib/app_properties.dart @@ -21,4 +21,5 @@ screenAwareSize(int size, BuildContext context) { return size * MediaQuery.of(context).size.height / baseHeight; } -const String accessToken = "accessToken"; \ No newline at end of file +const String accessToken = "accessToken"; +const String user = "user"; \ No newline at end of file diff --git a/lib/data/models/user.model.dart b/lib/data/models/user.model.dart index 8052d56b..490078db 100644 --- a/lib/data/models/user.model.dart +++ b/lib/data/models/user.model.dart @@ -3,13 +3,14 @@ part 'user.model.g.dart'; @JsonSerializable() class UserModel { - final String id; - final String firstName; - final String lastName; - final String email; - final String role; + final String? id; + final String? firstName; + final String? lastName; + final String? email; + final String? role; + final String? resetToken; - UserModel(this.id, this.firstName, this.lastName, this.email, this.role); + UserModel(this.id, this.firstName, this.lastName, this.email, this.role, this.resetToken); factory UserModel.fromJson(Map json) => _$UserModelFromJson(json); diff --git a/lib/data/models/user.model.g.dart b/lib/data/models/user.model.g.dart index 41747ffa..b880b3ca 100644 --- a/lib/data/models/user.model.g.dart +++ b/lib/data/models/user.model.g.dart @@ -8,11 +8,12 @@ part of 'user.model.dart'; UserModel _$UserModelFromJson(Map json) { return UserModel( - json['id'] as String, - json['firstName'] as String, - json['lastName'] as String, - json['email'] as String, - json['role'] as String, + json['id'] as String?, + json['firstName'] as String?, + json['lastName'] as String?, + json['email'] as String?, + json['role'] as String?, + json['resetToken'] as String?, ); } @@ -22,4 +23,5 @@ Map _$UserModelToJson(UserModel instance) => { 'lastName': instance.lastName, 'email': instance.email, 'role': instance.role, + 'resetToken': instance.resetToken, }; diff --git a/lib/data/provider/auth.provider.dart b/lib/data/provider/auth.provider.dart index 756b9bc8..557b1b52 100644 --- a/lib/data/provider/auth.provider.dart +++ b/lib/data/provider/auth.provider.dart @@ -1,9 +1,14 @@ +import 'package:ecommerce_int2/app_properties.dart'; import 'package:ecommerce_int2/data/models/login.result.dart'; +import 'package:ecommerce_int2/data/models/user.model.dart'; import 'package:ecommerce_int2/services/network.service.dart'; +import 'package:get_storage/get_storage.dart'; class AuthProvider { final NetWorkService networkService; + final GetStorage storage = GetStorage(); + AuthProvider(this.networkService); final String loginUrl = @@ -12,6 +17,7 @@ class AuthProvider { 'https://ecommerce-api-dut.herokuapp.com/api/auth/register'; final String forgotUrl = 'https://ecommerce-api-dut.herokuapp.com/api/auth/forgot'; + final String reset = 'https://ecommerce-api-dut.herokuapp.com/api/auth/reset'; final String userInfoUrl = 'https://ecommerce-api-dut.herokuapp.com/api/user'; Future login(String username, String password) { @@ -33,10 +39,15 @@ class AuthProvider { }); } - Future forgotPassword( - String email) { - return networkService.post(forgotUrl, data: { - "email": email - }); + Future forgotPassword(String email) { + return networkService.post(forgotUrl, data: {"email": email}); + } + + Future resetPassword(String password) { + final json = storage.read(user); + final u = UserModel.fromJson(json); + if (u.resetToken == null) throw Exception('Reset token is not available'); + return networkService + .post('$reset/${u.resetToken}', data: {"password": password}); } } diff --git a/lib/data/repository/auth.repository.dart b/lib/data/repository/auth.repository.dart index 0ac266e6..b05563c8 100644 --- a/lib/data/repository/auth.repository.dart +++ b/lib/data/repository/auth.repository.dart @@ -43,4 +43,12 @@ class AuthRepository { throw Exception("Wrong email"); } } + + Future resetPassword(String password) async { + final response = + await provider.forgotPassword(password); + if (response.statusCode != 200) { + throw Exception("Wrong email"); + } + } } diff --git a/lib/services/auth.service.dart b/lib/services/auth.service.dart index 849f1fe9..bfe39dd2 100644 --- a/lib/services/auth.service.dart +++ b/lib/services/auth.service.dart @@ -26,6 +26,7 @@ class AuthService extends GetxService { try { final res = await repository.getUserInfo(); userModel = res; + store.write(user, userModel!.toJson()); Navigator.of(Get.context!) .pushReplacement(MaterialPageRoute(builder: (_) => MainPage())); } catch (e) { @@ -81,4 +82,10 @@ class AuthService extends GetxService { Navigator.of(Get.context!) .pushReplacement(MaterialPageRoute(builder: (_) => WelcomeBackPage())); } + + void resetPassword(String password) { + try { + repository.resetPassword(password); + } catch (e) {} + } } From 782143dd009a3cce3a465e2323a22c9f10e7d80f Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Sat, 21 May 2022 17:28:59 +0700 Subject: [PATCH 07/49] Fix wrong behaviour --- lib/services/auth.service.dart | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/services/auth.service.dart b/lib/services/auth.service.dart index bfe39dd2..87a8260e 100644 --- a/lib/services/auth.service.dart +++ b/lib/services/auth.service.dart @@ -35,16 +35,14 @@ class AuthService extends GetxService { } } - Future login(String username, String password) async { + Future login(String username, String password) async { try { final res = await repository.login(username, password); + setAccessToken(res.token); userModel = res.user; Navigator.of(Get.context!) .pushReplacement(MaterialPageRoute(builder: (_) => MainPage())); - return true; - } catch (e) { - return false; - } + } catch (e) {} } void setAccessToken(String token) { From 2fba81d1ea1028ac718fbec6affd02d5d6ea8cd6 Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Sat, 21 May 2022 17:32:36 +0700 Subject: [PATCH 08/49] Get user info when login successfully --- lib/services/auth.service.dart | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/services/auth.service.dart b/lib/services/auth.service.dart index 87a8260e..7cdf20e8 100644 --- a/lib/services/auth.service.dart +++ b/lib/services/auth.service.dart @@ -14,7 +14,7 @@ class AuthService extends GetxService { @override void onInit() { - verifyUser(); + getUserInfo(); super.onInit(); } @@ -22,7 +22,7 @@ class AuthService extends GetxService { AuthService(this.repository); - void verifyUser() async { + void getUserInfo() async { try { final res = await repository.getUserInfo(); userModel = res; @@ -38,15 +38,15 @@ class AuthService extends GetxService { Future login(String username, String password) async { try { final res = await repository.login(username, password); - setAccessToken(res.token); - userModel = res.user; + await setAccessToken(res.token); + getUserInfo(); Navigator.of(Get.context!) .pushReplacement(MaterialPageRoute(builder: (_) => MainPage())); } catch (e) {} } - void setAccessToken(String token) { - store.write(accessToken, token); + Future setAccessToken(String token) async { + await store.write(accessToken, token); } String getAccessToken() { From d0d43dad078276a88c6997a7762a37b8bf116366 Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Sun, 22 May 2022 01:22:56 +0700 Subject: [PATCH 09/49] Add address page --- .flutter-plugins-dependencies | 2 +- lib/data/models/address.model.dart | 31 ++ lib/data/models/user.model.dart | 2 + lib/data/models/user.model.g.dart | 2 +- lib/data/provider/address.provider.dart | 32 ++ lib/data/repository/address.repository.dart | 35 +++ lib/data/repository/auth.repository.dart | 4 +- lib/dependencies.dart | 6 +- lib/interceptor/dio_interceptor.dart | 3 +- lib/main.dart | 4 +- lib/screens/address/add_address_page.dart | 276 ++++++++---------- lib/screens/address/address_form.dart | 87 +----- lib/screens/auth/forgot_password_page.dart | 3 - lib/screens/auth/register_page.dart | 5 +- lib/screens/profile_page.dart | 5 +- .../settings/change_password_page.dart | 9 +- lib/screens/settings/settings_page.dart | 7 +- lib/services/address.controller.dart | 48 +++ lib/services/auth.service.dart | 5 +- lib/services/network.service.dart | 14 +- 20 files changed, 321 insertions(+), 259 deletions(-) create mode 100644 lib/data/models/address.model.dart create mode 100644 lib/data/provider/address.provider.dart create mode 100644 lib/data/repository/address.repository.dart create mode 100644 lib/services/address.controller.dart diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index f7ec9eaf..9dc6b33b 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2022-05-21 17:10:51.919114","version":"2.10.4"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2022-05-21 23:33:06.517604","version":"2.10.4"} \ No newline at end of file diff --git a/lib/data/models/address.model.dart b/lib/data/models/address.model.dart new file mode 100644 index 00000000..62d9569a --- /dev/null +++ b/lib/data/models/address.model.dart @@ -0,0 +1,31 @@ +class Address { + String? id; + String? address; + String? city; + String? country; + String? zipCode; + bool? isDefault; + + Address( + {this.id, this.address, this.city, this.country, this.zipCode, this.isDefault = false}); + + Address.fromJson(Map json) { + id = json['_id']; + address = json['address']; + city = json['city']; + country = json['country']; + zipCode = json['zipCode']; + isDefault = json['isDefault'] ?? false; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['address'] = this.address; + data['city'] = this.city; + data['country'] = this.country; + data['zipCode'] = this.zipCode; + data['isDefault'] = this.isDefault; + return data; + } +} \ No newline at end of file diff --git a/lib/data/models/user.model.dart b/lib/data/models/user.model.dart index 490078db..d3d3b3b3 100644 --- a/lib/data/models/user.model.dart +++ b/lib/data/models/user.model.dart @@ -10,6 +10,8 @@ class UserModel { final String? role; final String? resetToken; + String get name => (firstName ?? '') + ' ' + (lastName ?? ''); + UserModel(this.id, this.firstName, this.lastName, this.email, this.role, this.resetToken); factory UserModel.fromJson(Map json) => diff --git a/lib/data/models/user.model.g.dart b/lib/data/models/user.model.g.dart index b880b3ca..641500ba 100644 --- a/lib/data/models/user.model.g.dart +++ b/lib/data/models/user.model.g.dart @@ -13,7 +13,7 @@ UserModel _$UserModelFromJson(Map json) { json['lastName'] as String?, json['email'] as String?, json['role'] as String?, - json['resetToken'] as String?, + json['resetPasswordToken'] as String?, ); } diff --git a/lib/data/provider/address.provider.dart b/lib/data/provider/address.provider.dart new file mode 100644 index 00000000..250cc698 --- /dev/null +++ b/lib/data/provider/address.provider.dart @@ -0,0 +1,32 @@ +import 'package:ecommerce_int2/data/models/address.model.dart'; +import 'package:ecommerce_int2/services/network.service.dart'; +import 'package:get_storage/get_storage.dart'; + +class AddressProvider { + final NetWorkService networkService; + + final GetStorage storage = GetStorage(); + + AddressProvider(this.networkService); + + final String getAddressUrl = + 'https://ecommerce-api-dut.herokuapp.com/api/address'; + final String addAddressUrl = + 'https://ecommerce-api-dut.herokuapp.com/api/address/add'; + + + Future getAllAddress() { + return networkService + .get(getAddressUrl); + } + + Future addAddress( + Address address) { + return networkService.post(addAddressUrl, data: address.toJson()); + } + + Future updateAddress( + Address address) { + return networkService.post('$addAddressUrl/${address.id}', data: address.toJson()); + } +} diff --git a/lib/data/repository/address.repository.dart b/lib/data/repository/address.repository.dart new file mode 100644 index 00000000..d3197008 --- /dev/null +++ b/lib/data/repository/address.repository.dart @@ -0,0 +1,35 @@ +import 'package:ecommerce_int2/data/models/address.model.dart'; +import 'package:ecommerce_int2/data/provider/address.provider.dart'; + +class AddressRepository { + final AddressProvider provider; + + AddressRepository(this.provider); + + Future> getAllAddress() async { + final response = await provider.getAllAddress(); + if (response.statusCode != 200) { + throw Exception("Get address failed"); + } + final result = (response.body['addresses'] as List).map((i) => + Address.fromJson(i)).toList(); + return result; + } + + + Future addAddress(Address address) async { + final response = + await provider.addAddress(address); + if (response.statusCode != 200) { + throw Exception("Add address failed"); + } + } + + Future updateAddress(Address address) async { + final response = + await provider.updateAddress(address); + if (response.statusCode != 200) { + throw Exception("Update address failed"); + } + } +} diff --git a/lib/data/repository/auth.repository.dart b/lib/data/repository/auth.repository.dart index b05563c8..c6158c56 100644 --- a/lib/data/repository/auth.repository.dart +++ b/lib/data/repository/auth.repository.dart @@ -1,5 +1,3 @@ -import 'dart:ffi'; - import 'package:ecommerce_int2/data/models/login.result.dart'; import 'package:ecommerce_int2/data/models/user.model.dart'; import 'package:ecommerce_int2/data/provider/auth.provider.dart'; @@ -23,7 +21,7 @@ class AuthRepository { if (response.statusCode != 200) { throw Exception("Login failed"); } - final result = UserModel.fromJson(response.body); + final result = UserModel.fromJson(response.body['user']); return result; } diff --git a/lib/dependencies.dart b/lib/dependencies.dart index 2a17a23a..24fa93fe 100644 --- a/lib/dependencies.dart +++ b/lib/dependencies.dart @@ -1,4 +1,6 @@ +import 'package:ecommerce_int2/data/provider/address.provider.dart'; import 'package:ecommerce_int2/data/provider/auth.provider.dart'; +import 'package:ecommerce_int2/data/repository/address.repository.dart'; import 'package:ecommerce_int2/data/repository/auth.repository.dart'; import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:ecommerce_int2/services/network.service.dart'; @@ -10,6 +12,8 @@ class Dependency { ..put(NetWorkService()) ..put(AuthProvider(Get.find())) ..put(AuthRepository(Get.find())) - ..put(AuthService(Get.find())); + ..put(AuthService(Get.find())) + ..put(AddressProvider(Get.find())) + ..put(AddressRepository(Get.find())); } } diff --git a/lib/interceptor/dio_interceptor.dart b/lib/interceptor/dio_interceptor.dart index f87cd478..166fff67 100644 --- a/lib/interceptor/dio_interceptor.dart +++ b/lib/interceptor/dio_interceptor.dart @@ -6,6 +6,7 @@ import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; class DioInterceptors extends InterceptorsWrapper { + final _store = GetStorage(); DioInterceptors(); @@ -16,7 +17,7 @@ class DioInterceptors extends InterceptorsWrapper { String? token = _store.read(accessToken); if (token != null && token.isNotEmpty) { options.headers.addAll({ - HttpHeaders.authorizationHeader: 'Bearer $token', + HttpHeaders.authorizationHeader: token, }); } diff --git a/lib/main.dart b/lib/main.dart index 7b0b9299..39b9d725 100755 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,8 +2,10 @@ import 'package:ecommerce_int2/dependencies.dart'; import 'package:ecommerce_int2/screens/splash_page.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:get_storage/get_storage.dart'; void main() { + GetStorage.init(); Dependency.init(); runApp(MyApp()); } @@ -13,7 +15,7 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return GetMaterialApp( - title: 'eCommerce int2', + title: 'E-commerce', debugShowCheckedModeBanner: false, theme: ThemeData( brightness: Brightness.light, diff --git a/lib/screens/address/add_address_page.dart b/lib/screens/address/add_address_page.dart index bd8760c0..7bac85e4 100755 --- a/lib/screens/address/add_address_page.dart +++ b/lib/screens/address/add_address_page.dart @@ -1,167 +1,135 @@ import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/data/repository/address.repository.dart'; import 'package:ecommerce_int2/screens/address/address_form.dart'; import 'package:ecommerce_int2/screens/select_card_page.dart'; +import 'package:ecommerce_int2/services/address.controller.dart'; import 'package:flutter/material.dart'; +import 'package:get/get.dart'; class AddAddressPage extends StatelessWidget { - @override - Widget build(BuildContext context) { - Widget finishButton = InkWell( - onTap:()=> Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => SelectCardPage())), - child: Container( - height: 80, - width: MediaQuery.of(context).size.width / 1.5, - decoration: BoxDecoration( - gradient: mainButton, - boxShadow: [ - BoxShadow( - color: Color.fromRGBO(0, 0, 0, 0.16), - offset: Offset(0, 5), - blurRadius: 10.0, - ) - ], - borderRadius: BorderRadius.circular(9.0)), - child: Center( - child: Text("Finish", - style: const TextStyle( - color: const Color(0xfffefefe), - fontWeight: FontWeight.w600, - fontStyle: FontStyle.normal, - fontSize: 20.0)), + final TextEditingController address = TextEditingController(); + final TextEditingController city = TextEditingController(); + + Widget buildFinishButton(AddressController controller) => InkWell( + onTap: () { + controller.updateCurrentAddress(address.text, city.text); + controller.submitAddress(); + Get.to(() => SelectCardPage()); + }, + child: Container( + height: 80, + width: Get.width / 1.5, + decoration: BoxDecoration( + gradient: mainButton, + boxShadow: [ + BoxShadow( + color: Color.fromRGBO(0, 0, 0, 0.16), + offset: Offset(0, 5), + blurRadius: 10.0, + ) + ], + borderRadius: BorderRadius.circular(9.0)), + child: Center( + child: Text("Finish", + style: const TextStyle( + color: const Color(0xfffefefe), + fontWeight: FontWeight.w600, + fontStyle: FontStyle.normal, + fontSize: 20.0)), + ), ), - ), - ); + ); - return Scaffold( - backgroundColor: Colors.grey[100], - appBar: AppBar( - backgroundColor: Colors.transparent, - elevation: 0.0, - iconTheme: IconThemeData(color: darkGrey), - title: Text( - 'Add Address', - style: const TextStyle( - color: darkGrey, - fontWeight: FontWeight.w500, - fontFamily: "Montserrat", - fontSize: 18.0), + @override + Widget build(BuildContext context) { + return GetBuilder( + init: AddressController(Get.find()), + builder: (controller) => Scaffold( + backgroundColor: Colors.grey[100], + appBar: AppBar( + backgroundColor: Colors.transparent, + elevation: 0.0, + iconTheme: IconThemeData(color: darkGrey), + title: Text( + 'Add Address', + style: const TextStyle( + color: darkGrey, + fontWeight: FontWeight.w500, + fontFamily: "Montserrat", + fontSize: 18.0), + ), ), - ), - body: LayoutBuilder( - builder: (_, viewportConstraints) => SingleChildScrollView( - child: ConstrainedBox( - constraints: - BoxConstraints(minHeight: viewportConstraints.maxHeight), - child: Container( - padding: EdgeInsets.only( - left: 16.0, - right: 16.0, - bottom: MediaQuery.of(context).padding.bottom == 0 - ? 20 - : MediaQuery.of(context).padding.bottom), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - mainAxisSize: MainAxisSize.min, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Card( - margin: EdgeInsets.symmetric(vertical: 8.0), - color: Colors.white, - elevation: 3, - child: SizedBox( - height: 100, - width: 80, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.all(4.0), - child: Image.asset( - 'assets/icons/address_home.png'), - ), - Text( - 'Add New Address', - style: TextStyle( - fontSize: 8, - color: darkGrey, - ), - textAlign: TextAlign.center, - ) - ], - ), - ))), - Card( - margin: EdgeInsets.symmetric(vertical: 8.0), - color: yellow, - elevation: 3, - child: SizedBox( - height: 80, - width: 100, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.all(4.0), - child: Image.asset( - 'assets/icons/address_home.png', - color: Colors.white, - height: 20, - ), - ), - Text( - 'Simon Philip,\nCity Oscarlad', - style: TextStyle( - fontSize: 8, - color: Colors.white, - ), - textAlign: TextAlign.center, - ) - ], - ), - ))), - Card( - margin: EdgeInsets.symmetric(vertical: 8.0), - color: yellow, - elevation: 3, - child: SizedBox( - height: 80, - width: 100, + body: LayoutBuilder( + builder: (_, viewportConstraints) => SingleChildScrollView( + child: ConstrainedBox( + constraints: + BoxConstraints(minHeight: viewportConstraints.maxHeight), + child: Container( + padding: EdgeInsets.only( + left: 16.0, + right: 16.0, + bottom: MediaQuery.of(context).padding.bottom == 0 + ? 20 + : MediaQuery.of(context).padding.bottom), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + mainAxisSize: MainAxisSize.min, + children: [ + Container( + height: 100, + child: ListView.builder( + scrollDirection: Axis.horizontal, + shrinkWrap: false, + itemCount: controller.addresses.length, + itemBuilder: (BuildContext context, int index) { + final e = controller.addresses[index]; + return GestureDetector( + onTap: () => controller.updateIndex(index), child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.all(4.0), - child: Image.asset( - 'assets/icons/address_work.png', - color: Colors.white, - height: 20), - ), - Text( - 'Workplace', - style: TextStyle( - fontSize: 8, - color: Colors.white, - ), - textAlign: TextAlign.center, - ) - ], - ), - ))) - ], - ), - AddAddressForm(), - Center(child: finishButton) - ], + padding: const EdgeInsets.only(right: 8.0), + child: Card( + margin: EdgeInsets.symmetric(vertical: 8.0), + color: index == controller.selectIndex + ? yellow + : Colors.white, + elevation: 3, + child: SizedBox( + height: 100, + width: 80, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Padding( + padding: + const EdgeInsets.all(4.0), + child: Image.asset( + 'assets/icons/address_home.png'), + ), + Text( + e.address ?? 'Add New Address', + style: TextStyle( + fontSize: 8, + color: darkGrey, + ), + textAlign: TextAlign.center, + ) + ], + ), + ))), + ), + ); + }), + ), + AddAddressForm( + address: controller.selectedAddress, + addr: address, + city: city), + Center(child: buildFinishButton(controller)) + ], + ), ), ), ), diff --git a/lib/screens/address/address_form.dart b/lib/screens/address/address_form.dart index 0268760d..4bce64f0 100755 --- a/lib/screens/address/address_form.dart +++ b/lib/screens/address/address_form.dart @@ -1,7 +1,18 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/data/models/address.model.dart'; import 'package:flutter/material.dart'; class AddAddressForm extends StatelessWidget { + final Address address; + + final TextEditingController addr; + final TextEditingController city; + + const AddAddressForm( + {Key? key, + required this.address, + required this.addr, + required this.city}) + : super(key: key); @override Widget build(BuildContext context) { return SizedBox( @@ -17,54 +28,11 @@ class AddAddressForm extends StatelessWidget { color: Colors.white, ), child: TextField( + controller: addr, decoration: InputDecoration( - border: InputBorder.none, hintText: 'Flat Number/House Number'), - ), - ), - Container( - padding: EdgeInsets.only(left: 16.0, top: 4.0, bottom: 4.0), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(5)), - color: Colors.white, - ), - child: TextField( - decoration: - InputDecoration(border: InputBorder.none, hintText: 'Street'), + border: InputBorder.none, hintText: address.address), ), ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.all(16.0), - child: Text( - 'Area', - style: TextStyle(fontSize: 12, color: darkGrey), - ), - ), - ClipRRect( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(5), topRight: Radius.circular(5)), - child: Container( - padding: EdgeInsets.only(left: 16.0, top: 4.0, bottom: 4.0), - decoration: BoxDecoration( - border: Border( - bottom: BorderSide(color: Colors.orange, width: 2)), - color: Colors.orange[100], - ), - child: TextField( - style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), - decoration: InputDecoration( - border: InputBorder.none, - hintText: 'Name on card', - hintStyle: - TextStyle(fontSize: 24, fontWeight: FontWeight.bold), - ), - ), - ), - ), - ], - ), Container( padding: EdgeInsets.only(left: 16.0, top: 4.0, bottom: 4.0), decoration: BoxDecoration( @@ -72,34 +40,11 @@ class AddAddressForm extends StatelessWidget { color: Colors.white, ), child: TextField( + controller: city, decoration: InputDecoration( - border: InputBorder.none, hintText: 'Name on card'), - ), - ), - ClipRRect( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(5), topRight: Radius.circular(5)), - child: Container( - padding: EdgeInsets.only(left: 16.0, top: 4.0, bottom: 4.0), - decoration: BoxDecoration( - border: Border(bottom: BorderSide(color: Colors.red, width: 1)), - color: Colors.white, - ), - child: TextField( - decoration: InputDecoration( - border: InputBorder.none, hintText: 'Postal code'), - ), + border: InputBorder.none, hintText: address.city), ), ), - Row( - children: [ - Checkbox( - value: true, - onChanged: (_) {}, - ), - Text('Add this to address bookmark') - ], - ) ], ), ); diff --git a/lib/screens/auth/forgot_password_page.dart b/lib/screens/auth/forgot_password_page.dart index 14e1c35d..9aefbdbc 100755 --- a/lib/screens/auth/forgot_password_page.dart +++ b/lib/screens/auth/forgot_password_page.dart @@ -1,4 +1,3 @@ - import 'package:ecommerce_int2/app_properties.dart'; import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:flutter/material.dart'; @@ -6,7 +5,6 @@ import 'package:country_code_picker/country_code_picker.dart'; import 'package:get/get.dart'; -import 'confirm_otp_page.dart'; class ForgotPasswordPage extends StatefulWidget { @override @@ -124,7 +122,6 @@ class _ForgotPasswordPageState extends State { child: Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ - prefix(), Flexible( child: Padding( padding: const EdgeInsets.only(top: 8.0), diff --git a/lib/screens/auth/register_page.dart b/lib/screens/auth/register_page.dart index 3d6bc346..ea053966 100755 --- a/lib/screens/auth/register_page.dart +++ b/lib/screens/auth/register_page.dart @@ -1,11 +1,8 @@ - import 'package:ecommerce_int2/app_properties.dart'; import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'forgot_password_page.dart'; - class RegisterPage extends StatefulWidget { @override _RegisterPageState createState() => _RegisterPageState(); @@ -81,7 +78,7 @@ class _RegisterPageState extends State { ); Widget registerForm = Container( - height: 300, + height: 350, child: Stack( children: [ Container( diff --git a/lib/screens/profile_page.dart b/lib/screens/profile_page.dart index ddea54bc..c8ec7ad4 100755 --- a/lib/screens/profile_page.dart +++ b/lib/screens/profile_page.dart @@ -4,11 +4,14 @@ import 'package:ecommerce_int2/screens/payment/payment_page.dart'; import 'package:ecommerce_int2/screens/settings/settings_page.dart'; import 'package:ecommerce_int2/screens/tracking_page.dart'; import 'package:ecommerce_int2/screens/wallet/wallet_page.dart'; +import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:flutter/material.dart'; +import 'package:get/get.dart'; class ProfilePage extends StatelessWidget { @override Widget build(BuildContext context) { + final controller = Get.find(); return Scaffold( backgroundColor: Color(0xffF9F9F9), body: SafeArea( @@ -26,7 +29,7 @@ class ProfilePage extends StatelessWidget { Padding( padding: const EdgeInsets.all(8.0), child: Text( - 'Rose Helbert', + controller.userModel!.name, style: TextStyle(fontWeight: FontWeight.bold), ), ), diff --git a/lib/screens/settings/change_password_page.dart b/lib/screens/settings/change_password_page.dart index 420841d4..f2ac932f 100755 --- a/lib/screens/settings/change_password_page.dart +++ b/lib/screens/settings/change_password_page.dart @@ -1,6 +1,7 @@ import 'package:ecommerce_int2/app_properties.dart'; -import 'package:flutter/cupertino.dart'; +import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:flutter/material.dart'; +import 'package:get/get.dart'; class ChangePasswordPage extends StatefulWidget { @override @@ -8,13 +9,15 @@ class ChangePasswordPage extends StatefulWidget { } class _ChangePasswordPageState extends State { + TextEditingController password = TextEditingController(); @override Widget build(BuildContext context) { + final controller = Get.find(); double width = MediaQuery.of(context).size.width; double bottomPadding = MediaQuery.of(context).padding.bottom; Widget changePasswordButton = InkWell( - onTap: () {}, + onTap: () {controller.resetPassword(password.text.trim());}, child: Container( height: 80, width: width / 1.5, @@ -45,7 +48,6 @@ class _ChangePasswordPageState extends State { iconTheme: IconThemeData( color: Colors.black, ), - brightness: Brightness.light, backgroundColor: Colors.transparent, title: Text( 'Settings', @@ -113,6 +115,7 @@ class _ChangePasswordPageState extends State { borderRadius: BorderRadius.all(Radius.circular(5))), child: TextField( + controller: password, decoration: InputDecoration( border: InputBorder.none, hintText: 'New Password', diff --git a/lib/screens/settings/settings_page.dart b/lib/screens/settings/settings_page.dart index 0105377f..c10d4c0d 100755 --- a/lib/screens/settings/settings_page.dart +++ b/lib/screens/settings/settings_page.dart @@ -1,11 +1,12 @@ import 'package:ecommerce_int2/app_properties.dart'; import 'package:ecommerce_int2/custom_background.dart'; -import 'package:ecommerce_int2/screens/auth/welcome_back_page.dart'; import 'package:ecommerce_int2/screens/settings/change_country.dart'; import 'package:ecommerce_int2/screens/settings/change_password_page.dart'; import 'package:ecommerce_int2/screens/settings/legal_about_page.dart'; import 'package:ecommerce_int2/screens/settings/notifications_settings_page.dart'; +import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:flutter/material.dart'; +import 'package:get/get.dart'; import 'change_language_page.dart'; @@ -19,7 +20,6 @@ class SettingsPage extends StatelessWidget { iconTheme: IconThemeData( color: Colors.black, ), - brightness: Brightness.light, backgroundColor: Colors.transparent, title: Text( 'Settings', @@ -96,8 +96,7 @@ class SettingsPage extends StatelessWidget { ListTile( title: Text('Sign out'), leading: Image.asset('assets/icons/sign_out.png'), - onTap: () => Navigator.of(context).push( - MaterialPageRoute(builder: (_) => WelcomeBackPage())), + onTap: () => Get.find().logout(), ), ], diff --git a/lib/services/address.controller.dart b/lib/services/address.controller.dart new file mode 100644 index 00000000..10a90f98 --- /dev/null +++ b/lib/services/address.controller.dart @@ -0,0 +1,48 @@ +import 'package:ecommerce_int2/data/models/address.model.dart'; +import 'package:ecommerce_int2/data/repository/address.repository.dart'; +import 'package:get/get.dart'; + +class AddressController extends GetxController { + final AddressRepository repository; + + AddressController(this.repository); + + List
addresses =
[Address()]; + + int selectIndex = 0; + + Address get selectedAddress => addresses[selectIndex]; + + @override + void onInit() { + getAllAddress(); + super.onInit(); + } + + void getAllAddress() async { + final List
res = await repository.getAllAddress(); + addresses.assignAll(res); + addresses.insert(0, Address()); + int index = addresses.indexWhere((element) => element.isDefault!); + if (index != -1) selectIndex = index; + update(); + } + + void updateIndex(int index) { + selectIndex = index; + update(); + } + + void updateCurrentAddress(String address, String city) { + if(address.isNotEmpty) selectedAddress.address = address; + if(city.isNotEmpty) selectedAddress.city = city; + } + + void submitAddress() { + if(selectedAddress.id == null) { + repository.addAddress(selectedAddress).then((value) => null, onError: (e) => null); + } else { + repository.updateAddress(selectedAddress).then((value) => null, onError: (e) => null); + } + } +} \ No newline at end of file diff --git a/lib/services/auth.service.dart b/lib/services/auth.service.dart index 7cdf20e8..19ca4948 100644 --- a/lib/services/auth.service.dart +++ b/lib/services/auth.service.dart @@ -42,7 +42,9 @@ class AuthService extends GetxService { getUserInfo(); Navigator.of(Get.context!) .pushReplacement(MaterialPageRoute(builder: (_) => MainPage())); - } catch (e) {} + } catch (e) { + print(e); + } } Future setAccessToken(String token) async { @@ -68,7 +70,6 @@ class AuthService extends GetxService { Future forgetPassword(String email) async { try { repository.forgotPassword(email); - } on Exception catch (e) { } finally { Navigator.of(Get.context!).pushReplacement( MaterialPageRoute(builder: (_) => WelcomeBackPage())); diff --git a/lib/services/network.service.dart b/lib/services/network.service.dart index 9bcadcd3..e821f477 100644 --- a/lib/services/network.service.dart +++ b/lib/services/network.service.dart @@ -1,10 +1,8 @@ import 'package:dio/dio.dart'; import 'package:ecommerce_int2/interceptor/dio_interceptor.dart'; -import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:flutter/cupertino.dart'; import 'package:path_provider/path_provider.dart'; - class HttpResponse { HttpResponse({ this.body, @@ -24,16 +22,14 @@ class HttpResponse { } class NetWorkService { - late final Dio? _dio; + Dio _dio = Dio(); - NetWorkService(); + NetWorkService() { + _dio.interceptors.add(DioInterceptors()); + } Dio getDio() { - if(_dio == null) { - Dio _dio = Dio(); - _dio.interceptors.add(DioInterceptors()); - } - return _dio!; + return _dio; } String? getUriQueryParam(Uri uri, String key) { From 342e4667d1b3953c587455faddb538d2902c5b4f Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Wed, 25 May 2022 10:34:11 +0700 Subject: [PATCH 10/49] Add product and category provider and repository --- lib/data/models/category.model.dart | 97 +++++++++++ lib/data/models/product.model.dart | 173 +++++++++++++++++++ lib/data/provider/category.provider.dart | 17 ++ lib/data/provider/product.provider.dart | 31 ++++ lib/data/repository/category.repository.dart | 18 ++ lib/data/repository/product.repository.dart | 27 +++ 6 files changed, 363 insertions(+) create mode 100644 lib/data/models/category.model.dart create mode 100644 lib/data/models/product.model.dart create mode 100644 lib/data/provider/category.provider.dart create mode 100644 lib/data/provider/product.provider.dart create mode 100644 lib/data/repository/category.repository.dart create mode 100644 lib/data/repository/product.repository.dart diff --git a/lib/data/models/category.model.dart b/lib/data/models/category.model.dart new file mode 100644 index 00000000..778b5229 --- /dev/null +++ b/lib/data/models/category.model.dart @@ -0,0 +1,97 @@ +class Category { + List? categories; + + Category({this.categories}); + + Category.fromJson(Map json) { + if (json['categories'] != null) { + categories = []; + json['categories'].forEach((v) { + categories!.add(new Categories.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + if (this.categories != null) { + data['categories'] = this.categories!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Categories { + String? categoryId; + String? categoryName; + List? subcategories; + + Categories({this.categoryId, this.categoryName, this.subcategories}); + + Categories.fromJson(Map json) { + categoryId = json['category_id']; + categoryName = json['category_name']; + if (json['subcategories'] != null) { + subcategories = []; + json['subcategories'].forEach((v) { + subcategories!.add(new Subcategories.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + data['category_id'] = this.categoryId; + data['category_name'] = this.categoryName; + if (this.subcategories != null) { + data['subcategories'] = + this.subcategories!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Subcategories { + String? sId; + String? name; + String? description; + bool? isActive; + String? category; + String? created; + String? slug; + int? iV; + + Subcategories( + {this.sId, + this.name, + this.description, + this.isActive, + this.category, + this.created, + this.slug, + this.iV}); + + Subcategories.fromJson(Map json) { + sId = json['_id']; + name = json['name']; + description = json['description']; + isActive = json['isActive']; + category = json['category']; + created = json['created']; + slug = json['slug']; + iV = json['__v']; + } + + Map toJson() { + final Map data = new Map(); + data['_id'] = this.sId; + data['name'] = this.name; + data['description'] = this.description; + data['isActive'] = this.isActive; + data['category'] = this.category; + data['created'] = this.created; + data['slug'] = this.slug; + data['__v'] = this.iV; + return data; + } +} diff --git a/lib/data/models/product.model.dart b/lib/data/models/product.model.dart new file mode 100644 index 00000000..93fdc064 --- /dev/null +++ b/lib/data/models/product.model.dart @@ -0,0 +1,173 @@ +class Product { + List? products; + int? page; + int? pages; + int? totalProducts; + + Product({this.products, this.page, this.pages, this.totalProducts}); + + Product.fromJson(Map json) { + if (json['products'] != null) { + products = []; + json['products'].forEach((v) { + products!.add(new Products.fromJson(v)); + }); + } + page = json['page']; + pages = json['pages']; + totalProducts = json['totalProducts']; + } + + Map toJson() { + final Map data = new Map(); + if (this.products != null) { + data['products'] = this.products!.map((v) => v.toJson()).toList(); + } + data['page'] = this.page; + data['pages'] = this.pages; + data['totalProducts'] = this.totalProducts; + return data; + } +} + +class Products { + String? sId; + String? name; + String? imageUrl; + String? imageKey; + String? description; + int? quantity; + int? price; + bool? isActive; + String? merchant; + String? category; + String? subcategory; + String? created; + String? slug; + int? iV; + int? totalRatings; + int? totalReviews; + int? averageRating; + + Products( + {this.sId, + this.name, + this.imageUrl, + this.imageKey, + this.description, + this.quantity, + this.price, + this.isActive, + this.merchant, + this.category, + this.subcategory, + this.created, + this.slug, + this.iV, + this.totalRatings, + this.totalReviews, + this.averageRating}); + + Products.fromJson(Map json) { + sId = json['_id']; + name = json['name']; + imageUrl = json['imageUrl']; + imageKey = json['imageKey']; + description = json['description']; + quantity = json['quantity']; + price = json['price']; + isActive = json['isActive']; + merchant = json['merchant']; + category = json['category']; + subcategory = json['subcategory']; + created = json['created']; + slug = json['slug']; + iV = json['__v']; + totalRatings = json['totalRatings']; + totalReviews = json['totalReviews']; + averageRating = json['averageRating']; + } + + Map toJson() { + final Map data = new Map(); + data['_id'] = this.sId; + data['name'] = this.name; + data['imageUrl'] = this.imageUrl; + data['imageKey'] = this.imageKey; + data['description'] = this.description; + data['quantity'] = this.quantity; + data['price'] = this.price; + data['isActive'] = this.isActive; + data['merchant'] = this.merchant; + data['category'] = this.category; + data['subcategory'] = this.subcategory; + data['created'] = this.created; + data['slug'] = this.slug; + data['__v'] = this.iV; + data['totalRatings'] = this.totalRatings; + data['totalReviews'] = this.totalReviews; + data['averageRating'] = this.averageRating; + return data; + } +} + +class ProductFilter { + SortOrder? sortOrder; + int? rating; + int? max; + int? min; + String? subcategory; + int? order; + int? pageNumber; + + ProductFilter( + {this.sortOrder, + this.rating, + this.max, + this.min, + this.subcategory, + this.order, + this.pageNumber}); + + ProductFilter.fromJson(Map json) { + sortOrder = json['sortOrder'] != null + ? new SortOrder.fromJson(json['sortOrder']) + : null; + rating = json['rating']; + max = json['max']; + min = json['min']; + subcategory = json['subcategory']; + order = json['order']; + pageNumber = json['pageNumber']; + } + + Map toJson() { + final Map data = new Map(); + if (this.sortOrder != null) { + data['sortOrder'] = this.sortOrder!.toJson(); + } + data['rating'] = this.rating; + data['max'] = this.max; + data['min'] = this.min; + data['subcategory'] = this.subcategory; + data['order'] = this.order; + data['pageNumber'] = this.pageNumber; + return data; + } +} + +class SortOrder { + int? iId; + + SortOrder({this.iId}); + + SortOrder.fromJson(Map json) { + iId = json['_id']; + } + + Map toJson() { + final Map data = new Map(); + data['_id'] = this.iId; + return data; + } +} diff --git a/lib/data/provider/category.provider.dart b/lib/data/provider/category.provider.dart new file mode 100644 index 00000000..52f3eab7 --- /dev/null +++ b/lib/data/provider/category.provider.dart @@ -0,0 +1,17 @@ +import 'package:ecommerce_int2/services/network.service.dart'; +import 'package:get_storage/get_storage.dart'; + +class CategoryProvider { + final NetWorkService networkService; + + final GetStorage storage = GetStorage(); + + CategoryProvider(this.networkService); + + final String getAllCaegories = + 'https://ecommerce-api-dut.herokuapp.com/api/category/list'; + + Future getCategories() { + return networkService.get(getAllCaegories); + } +} diff --git a/lib/data/provider/product.provider.dart b/lib/data/provider/product.provider.dart new file mode 100644 index 00000000..d4b209e1 --- /dev/null +++ b/lib/data/provider/product.provider.dart @@ -0,0 +1,31 @@ +import 'package:ecommerce_int2/data/models/address.model.dart'; +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/services/network.service.dart'; +import 'package:get_storage/get_storage.dart'; + +class ProductProvider { + final NetWorkService networkService; + + final GetStorage storage = GetStorage(); + + ProductProvider(this.networkService); + + final String getAllProductsUrl = + 'https://ecommerce-api-dut.herokuapp.com/api/category/list'; + + final String searchProductUrl = + 'https://ecommerce-api-dut.herokuapp.com/api/product/list/search/'; + + + Future getProducts( + ProductFilter filter) { + return networkService.post(getAllProductsUrl, data: filter.toJson()); + } + + Future searchProducts( + String keyword) { + return networkService.get("$searchProductUrl/$keyword"); + } + + +} diff --git a/lib/data/repository/category.repository.dart b/lib/data/repository/category.repository.dart new file mode 100644 index 00000000..139c3a9a --- /dev/null +++ b/lib/data/repository/category.repository.dart @@ -0,0 +1,18 @@ +import 'package:ecommerce_int2/data/models/category.model.dart'; +import 'package:ecommerce_int2/data/provider/category.provider.dart'; + +class CategoryRepository { + final CategoryProvider provider; + + CategoryRepository(this.provider); + + Future getAllCategories() async { + final response = await provider.getCategories(); + if (response.statusCode != 200) { + throw Exception("Get category failed"); + } + final result = Category.fromJson(response.body); + return result; + } + +} diff --git a/lib/data/repository/product.repository.dart b/lib/data/repository/product.repository.dart new file mode 100644 index 00000000..e73e4cda --- /dev/null +++ b/lib/data/repository/product.repository.dart @@ -0,0 +1,27 @@ +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/data/provider/product.provider.dart'; + +class ProductRepository { + final ProductProvider provider; + + ProductRepository(this.provider); + + Future getProducts(ProductFilter filter) async { + final response = await provider.getProducts(filter); + if (response.statusCode != 200) { + throw Exception("Get products failed"); + } + final result = Product.fromJson(response.body); + return result; + } + + Future searchProduct(String keyword) async { + final response = await provider.searchProducts(keyword); + if (response.statusCode != 200) { + throw Exception("Get products failed"); + } + final result = Product.fromJson(response.body); + return result; + } + +} From a33a2d5fe9ee3b18c76789536d78bcb2ad603178 Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Wed, 25 May 2022 10:44:22 +0700 Subject: [PATCH 11/49] Rename product and category model --- lib/data/models/category.model.dart | 18 +++++++++--------- lib/data/models/product.model.dart | 18 +++++++++--------- lib/data/repository/category.repository.dart | 4 ++-- lib/data/repository/product.repository.dart | 8 ++++---- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/lib/data/models/category.model.dart b/lib/data/models/category.model.dart index 778b5229..2443e202 100644 --- a/lib/data/models/category.model.dart +++ b/lib/data/models/category.model.dart @@ -1,13 +1,13 @@ -class Category { - List? categories; +class CategoryList { + List? categories; - Category({this.categories}); + CategoryList({this.categories}); - Category.fromJson(Map json) { + CategoryList.fromJson(Map json) { if (json['categories'] != null) { - categories = []; + categories = []; json['categories'].forEach((v) { - categories!.add(new Categories.fromJson(v)); + categories!.add(new Category.fromJson(v)); }); } } @@ -21,14 +21,14 @@ class Category { } } -class Categories { +class Category { String? categoryId; String? categoryName; List? subcategories; - Categories({this.categoryId, this.categoryName, this.subcategories}); + Category({this.categoryId, this.categoryName, this.subcategories}); - Categories.fromJson(Map json) { + Category.fromJson(Map json) { categoryId = json['category_id']; categoryName = json['category_name']; if (json['subcategories'] != null) { diff --git a/lib/data/models/product.model.dart b/lib/data/models/product.model.dart index 93fdc064..5f26cbf9 100644 --- a/lib/data/models/product.model.dart +++ b/lib/data/models/product.model.dart @@ -1,16 +1,16 @@ -class Product { - List? products; +class ProductList { + List? products; int? page; int? pages; int? totalProducts; - Product({this.products, this.page, this.pages, this.totalProducts}); + ProductList({this.products, this.page, this.pages, this.totalProducts}); - Product.fromJson(Map json) { + ProductList.fromJson(Map json) { if (json['products'] != null) { - products = []; + products = []; json['products'].forEach((v) { - products!.add(new Products.fromJson(v)); + products!.add(new Product.fromJson(v)); }); } page = json['page']; @@ -30,7 +30,7 @@ class Product { } } -class Products { +class Product { String? sId; String? name; String? imageUrl; @@ -49,7 +49,7 @@ class Products { int? totalReviews; int? averageRating; - Products( + Product( {this.sId, this.name, this.imageUrl, @@ -68,7 +68,7 @@ class Products { this.totalReviews, this.averageRating}); - Products.fromJson(Map json) { + Product.fromJson(Map json) { sId = json['_id']; name = json['name']; imageUrl = json['imageUrl']; diff --git a/lib/data/repository/category.repository.dart b/lib/data/repository/category.repository.dart index 139c3a9a..15cdd9b0 100644 --- a/lib/data/repository/category.repository.dart +++ b/lib/data/repository/category.repository.dart @@ -6,12 +6,12 @@ class CategoryRepository { CategoryRepository(this.provider); - Future getAllCategories() async { + Future getAllCategories() async { final response = await provider.getCategories(); if (response.statusCode != 200) { throw Exception("Get category failed"); } - final result = Category.fromJson(response.body); + final result = CategoryList.fromJson(response.body); return result; } diff --git a/lib/data/repository/product.repository.dart b/lib/data/repository/product.repository.dart index e73e4cda..76f620b1 100644 --- a/lib/data/repository/product.repository.dart +++ b/lib/data/repository/product.repository.dart @@ -6,21 +6,21 @@ class ProductRepository { ProductRepository(this.provider); - Future getProducts(ProductFilter filter) async { + Future getProducts(ProductFilter filter) async { final response = await provider.getProducts(filter); if (response.statusCode != 200) { throw Exception("Get products failed"); } - final result = Product.fromJson(response.body); + final result = ProductList.fromJson(response.body); return result; } - Future searchProduct(String keyword) async { + Future searchProduct(String keyword) async { final response = await provider.searchProducts(keyword); if (response.statusCode != 200) { throw Exception("Get products failed"); } - final result = Product.fromJson(response.body); + final result = ProductList.fromJson(response.body); return result; } From cfbff88ed34449a63c9f9072003635fd1534d9cd Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Wed, 25 May 2022 11:22:17 +0700 Subject: [PATCH 12/49] Implement category screen --- lib/data/models/category.model.dart | 12 +- lib/dependencies.dart | 11 +- lib/screens/category/category.controller.dart | 45 +++++ lib/screens/category/category_list_page.dart | 172 ++++++------------ .../category/sub_category.controller.dart | 34 ++++ .../category/sub_category_list_page.dart | 83 +++++++++ 6 files changed, 231 insertions(+), 126 deletions(-) create mode 100644 lib/screens/category/category.controller.dart create mode 100644 lib/screens/category/sub_category.controller.dart create mode 100644 lib/screens/category/sub_category_list_page.dart diff --git a/lib/data/models/category.model.dart b/lib/data/models/category.model.dart index 2443e202..7b1037e9 100644 --- a/lib/data/models/category.model.dart +++ b/lib/data/models/category.model.dart @@ -24,7 +24,7 @@ class CategoryList { class Category { String? categoryId; String? categoryName; - List? subcategories; + List? subcategories; Category({this.categoryId, this.categoryName, this.subcategories}); @@ -32,9 +32,9 @@ class Category { categoryId = json['category_id']; categoryName = json['category_name']; if (json['subcategories'] != null) { - subcategories = []; + subcategories = []; json['subcategories'].forEach((v) { - subcategories!.add(new Subcategories.fromJson(v)); + subcategories!.add(new SubCategory.fromJson(v)); }); } } @@ -51,7 +51,7 @@ class Category { } } -class Subcategories { +class SubCategory { String? sId; String? name; String? description; @@ -61,7 +61,7 @@ class Subcategories { String? slug; int? iV; - Subcategories( + SubCategory( {this.sId, this.name, this.description, @@ -71,7 +71,7 @@ class Subcategories { this.slug, this.iV}); - Subcategories.fromJson(Map json) { + SubCategory.fromJson(Map json) { sId = json['_id']; name = json['name']; description = json['description']; diff --git a/lib/dependencies.dart b/lib/dependencies.dart index 24fa93fe..acb3f273 100644 --- a/lib/dependencies.dart +++ b/lib/dependencies.dart @@ -1,7 +1,11 @@ import 'package:ecommerce_int2/data/provider/address.provider.dart'; import 'package:ecommerce_int2/data/provider/auth.provider.dart'; +import 'package:ecommerce_int2/data/provider/category.provider.dart'; +import 'package:ecommerce_int2/data/provider/product.provider.dart'; import 'package:ecommerce_int2/data/repository/address.repository.dart'; import 'package:ecommerce_int2/data/repository/auth.repository.dart'; +import 'package:ecommerce_int2/data/repository/category.repository.dart'; +import 'package:ecommerce_int2/data/repository/product.repository.dart'; import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:ecommerce_int2/services/network.service.dart'; import 'package:get/get.dart'; @@ -14,6 +18,11 @@ class Dependency { ..put(AuthRepository(Get.find())) ..put(AuthService(Get.find())) ..put(AddressProvider(Get.find())) - ..put(AddressRepository(Get.find())); + ..put(AddressRepository(Get.find())) + ..put(CategoryProvider(Get.find())) + ..put(CategoryRepository(Get.find())) + ..put(ProductProvider(Get.find())) + ..put(ProductRepository(Get.find())) + ; } } diff --git a/lib/screens/category/category.controller.dart b/lib/screens/category/category.controller.dart new file mode 100644 index 00000000..d0a6423f --- /dev/null +++ b/lib/screens/category/category.controller.dart @@ -0,0 +1,45 @@ +import 'package:ecommerce_int2/data/models/category.model.dart'; +import 'package:ecommerce_int2/data/repository/category.repository.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class CategoryController extends GetxController { + final CategoryRepository repository; + + CategoryController(this.repository); + + CategoryList categoryList = CategoryList(); + + TextEditingController searchController = TextEditingController(); + + List get list => categoryList.categories ?? []; + + List tempList = []; + + @override + void onInit() { + getCategoryList(); + super.onInit(); + } + + void getCategoryList() { + repository.getAllCategories().then((value) { + categoryList = value; + update(); + }, onError: (exeption) => print(exeption)); + } + + void onChanged(String value) { + if (value.isNotEmpty) { + list.forEach((category) { + if (category.categoryName!.toLowerCase().contains(value)) { + tempList.add(category); + } + }); + } else { + tempList.clear(); + tempList.addAll(list); + } + update(); + } +} diff --git a/lib/screens/category/category_list_page.dart b/lib/screens/category/category_list_page.dart index 140698a6..90dc953d 100755 --- a/lib/screens/category/category_list_page.dart +++ b/lib/screens/category/category_list_page.dart @@ -1,63 +1,13 @@ import 'package:ecommerce_int2/app_properties.dart'; -import 'package:ecommerce_int2/models/category.dart'; +import 'package:ecommerce_int2/data/repository/category.repository.dart'; +import 'package:ecommerce_int2/screens/category/category.controller.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; import 'components/staggered_category_card.dart'; -class CategoryListPage extends StatefulWidget { - @override - _CategoryListPageState createState() => _CategoryListPageState(); -} - -class _CategoryListPageState extends State { - List categories = [ - Category( - Color(0xffFCE183), - Color(0xffF68D7F), - 'Gadgets', - 'assets/jeans_5.png', - ), - Category( - Color(0xffF749A2), - Color(0xffFF7375), - 'Clothes', - 'assets/jeans_5.png', - ), - Category( - Color(0xff00E9DA), - Color(0xff5189EA), - 'Fashion', - 'assets/jeans_5.png', - ), - Category( - Color(0xffAF2D68), - Color(0xff632376), - 'Home', - 'assets/jeans_5.png', - ), - Category( - Color(0xff36E892), - Color(0xff33B2B9), - 'Beauty', - 'assets/jeans_5.png', - ), - Category( - Color(0xffF123C4), - Color(0xff668CEA), - 'Appliances', - 'assets/jeans_5.png', - ), - ]; - - List searchResults = []; - TextEditingController searchController = TextEditingController(); - - @override - void initState() { - super.initState(); - searchResults = categories; - } +class CategoryListPage extends StatelessWidget { @override Widget build(BuildContext context) { @@ -66,77 +16,61 @@ class _CategoryListPageState extends State { child: Container( margin: const EdgeInsets.only(top: kToolbarHeight), padding: EdgeInsets.symmetric(horizontal: 16.0), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Align( - alignment: Alignment(-1, 0), - child: Padding( - padding: EdgeInsets.symmetric(vertical: 16.0), - child: Text( - 'Category List', - style: TextStyle( - color: darkGrey, - fontSize: 22, - fontWeight: FontWeight.bold, + child: GetBuilder( + init: CategoryController(Get.find()), + builder: (controller) => Column( + mainAxisSize: MainAxisSize.min, + children: [ + Align( + alignment: Alignment(-1, 0), + child: Padding( + padding: EdgeInsets.symmetric(vertical: 16.0), + child: Text( + 'Category List', + style: TextStyle( + color: darkGrey, + fontSize: 22, + fontWeight: FontWeight.bold, + ), ), ), ), - ), - Container( - padding: EdgeInsets.only(left: 16.0), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(5)), - color: Colors.white, - ), - child: TextField( - controller: searchController, - decoration: InputDecoration( - border: InputBorder.none, - hintText: 'Search', - prefixIcon: SvgPicture.asset( - 'assets/icons/search_icon.svg', - fit: BoxFit.scaleDown, - )), - onChanged: (value) { - if (value.isNotEmpty) { - List tempList = []; - categories.forEach((category) { - if (category.category.toLowerCase().contains(value)) { - tempList.add(category); - } - }); - setState(() { - searchResults.clear(); - searchResults.addAll(tempList); - }); - return; - } else { - setState(() { - searchResults.clear(); - searchResults.addAll(categories); - }); - } - }, + Container( + padding: EdgeInsets.only(left: 16.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(5)), + color: Colors.white, + ), + child: TextField( + controller: controller.searchController, + decoration: InputDecoration( + border: InputBorder.none, + hintText: 'Search', + prefixIcon: SvgPicture.asset( + 'assets/icons/search_icon.svg', + fit: BoxFit.scaleDown, + )), + onChanged: (value) => controller.onChanged(value), + ), ), - ), - Flexible( - child: ListView.builder( - itemCount: searchResults.length, - itemBuilder: (_, index) => Padding( - padding: EdgeInsets.symmetric( - vertical: 16.0, - ), - child: StaggeredCardCard( - begin: searchResults[index].begin, - end: searchResults[index].end, - categoryName: searchResults[index].category, - assetPath: searchResults[index].image, + Flexible( + child: ListView.builder( + itemCount: controller.tempList.length, + itemBuilder: (_, index) => Padding( + padding: EdgeInsets.symmetric( + vertical: 16.0, + ), + child: StaggeredCardCard( + begin: const Color(0xffFCE183), + end: const Color(0xffF68D7F), + categoryName: controller.tempList[index].categoryName ?? "", + assetPath: 'assets/jeans_5.png', + ), ), ), - ), - ) - ], + ) + ], + ), ), ), ); diff --git a/lib/screens/category/sub_category.controller.dart b/lib/screens/category/sub_category.controller.dart new file mode 100644 index 00000000..97b0923e --- /dev/null +++ b/lib/screens/category/sub_category.controller.dart @@ -0,0 +1,34 @@ +import 'package:ecommerce_int2/data/models/category.model.dart'; +import 'package:ecommerce_int2/data/repository/category.repository.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class SubCategoryController extends GetxController { + + final CategoryRepository repository; + final Category category; + + SubCategoryController(this.repository, this.category); + + CategoryList categoryList = CategoryList(); + + TextEditingController searchController = TextEditingController(); + + List get list => category.subcategories ?? []; + + List tempList = []; + + void onChanged(String value) { + if (value.isNotEmpty) { + list.forEach((subCategory) { + if (subCategory.name!.toLowerCase().contains(value)) { + tempList.add(subCategory); + } + }); + } else { + tempList.clear(); + tempList.addAll(list); + } + update(); + } +} diff --git a/lib/screens/category/sub_category_list_page.dart b/lib/screens/category/sub_category_list_page.dart new file mode 100644 index 00000000..bf005c60 --- /dev/null +++ b/lib/screens/category/sub_category_list_page.dart @@ -0,0 +1,83 @@ +import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/data/models/category.model.dart'; +import 'package:ecommerce_int2/data/repository/category.repository.dart'; +import 'package:ecommerce_int2/screens/category/sub_category.controller.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + +import 'components/staggered_category_card.dart'; + +class SubCategoryListPage extends StatelessWidget { + + final Category category; + + const SubCategoryListPage({Key? key, required this.category}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Material( + color: Color(0xffF9F9F9), + child: Container( + margin: const EdgeInsets.only(top: kToolbarHeight), + padding: EdgeInsets.symmetric(horizontal: 16.0), + child: GetBuilder( + init: SubCategoryController(Get.find(), category), + builder: (controller) => Column( + mainAxisSize: MainAxisSize.min, + children: [ + Align( + alignment: Alignment(-1, 0), + child: Padding( + padding: EdgeInsets.symmetric(vertical: 16.0), + child: Text( + 'Sub Category List', + style: TextStyle( + color: darkGrey, + fontSize: 22, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + Container( + padding: EdgeInsets.only(left: 16.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(5)), + color: Colors.white, + ), + child: TextField( + controller: controller.searchController, + decoration: InputDecoration( + border: InputBorder.none, + hintText: 'Search', + prefixIcon: SvgPicture.asset( + 'assets/icons/search_icon.svg', + fit: BoxFit.scaleDown, + )), + onChanged: (value) => controller.onChanged(value), + ), + ), + Flexible( + child: ListView.builder( + itemCount: controller.tempList.length, + itemBuilder: (_, index) => Padding( + padding: EdgeInsets.symmetric( + vertical: 16.0, + ), + child: StaggeredCardCard( + begin: const Color(0xffFCE183), + end: const Color(0xffF68D7F), + categoryName: controller.tempList[index].name ?? "", + assetPath: 'assets/jeans_5.png', + ), + ), + ), + ) + ], + ), + ), + ), + ); + } +} From ef58e33b947206e22f3917dc576085e606f120da Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Sat, 28 May 2022 16:31:53 +0700 Subject: [PATCH 13/49] Update product and refactoring --- .flutter-plugins-dependencies | 2 +- lib/data/provider/auth.provider.dart | 2 +- lib/interceptor/dio_interceptor.dart | 2 +- lib/main.dart | 2 +- lib/models/product.dart | 14 +- lib/screens/address/add_address_page.dart | 2 +- lib/screens/auth/confirm_otp_page.dart | 2 +- lib/screens/auth/forgot_password_page.dart | 2 +- lib/screens/auth/register_page.dart | 2 +- lib/screens/auth/welcome_back_page.dart | 2 +- lib/screens/category/category.controller.dart | 1 + lib/screens/category/category_list_page.dart | 13 +- .../components/staggered_category_card.dart | 41 ++++-- .../category/sub_category.controller.dart | 6 + .../category/sub_category_list_page.dart | 14 +- lib/screens/faq_page.dart | 2 +- lib/screens/intro_page.dart | 2 +- lib/screens/main/components/product_list.dart | 14 +- .../main/components/recommended_list.dart | 28 ++-- lib/screens/main/main_page.dart | 132 +++++++++--------- lib/screens/notifications_page.dart | 2 +- lib/screens/payment/payment_page.dart | 2 +- lib/screens/payment/promo_item.dart | 12 +- lib/screens/payment/unpaid_page.dart | 2 +- lib/screens/payment_history_page.dart | 2 +- .../product/components/color_list.dart | 2 +- .../product/components/more_products.dart | 34 ++--- .../product/components/product_card.dart | 6 +- .../product/components/product_display.dart | 8 +- .../product/components/product_options.dart | 8 +- .../components/rating_bottomSheet.dart | 2 +- .../product/components/shop_bottomSheet.dart | 34 ++--- .../product/components/shop_product.dart | 8 +- lib/screens/product/product_page.dart | 10 +- lib/screens/product/view_product_page.dart | 16 +-- lib/screens/profile_page.dart | 2 +- lib/screens/rating/rating_dialog.dart | 2 +- lib/screens/rating/rating_page.dart | 2 +- lib/screens/request_money/receive_page.dart | 2 +- .../request_money/request_amount_page.dart | 2 +- lib/screens/request_money/request_page.dart | 4 +- .../search_products/search_controller.dart | 59 ++++++++ .../{ => search_products}/search_page.dart | 103 +++++++------- lib/screens/select_card_page.dart | 2 +- .../send_money/quick_send_amount_page.dart | 2 +- lib/screens/send_money/send_page.dart | 4 +- lib/screens/settings/change_country.dart | 2 +- .../settings/change_language_page.dart | 2 +- .../settings/change_password_page.dart | 2 +- lib/screens/settings/legal_about_page.dart | 2 +- .../settings/notifications_settings_page.dart | 2 +- lib/screens/settings/settings_page.dart | 4 +- lib/screens/shop/check_out_page.dart | 25 ++-- .../shop/components/shop_item_list.dart | 6 +- lib/screens/splash_page.dart | 2 +- lib/screens/tracking_page.dart | 2 +- lib/screens/wallet/wallet_page.dart | 4 +- lib/services/auth.service.dart | 2 +- lib/{ => utils}/api_service.dart | 2 +- lib/{ => utils}/app_properties.dart | 0 lib/{ => utils}/custom_background.dart | 2 +- lib/utils/debounce.dart | 17 +++ lib/{ => utils}/dependencies.dart | 0 pubspec.lock | 7 + pubspec.yaml | 1 + 65 files changed, 411 insertions(+), 290 deletions(-) create mode 100644 lib/screens/search_products/search_controller.dart rename lib/screens/{ => search_products}/search_page.dart (60%) mode change 100755 => 100644 rename lib/{ => utils}/api_service.dart (96%) mode change 100755 => 100644 rename lib/{ => utils}/app_properties.dart (100%) mode change 100755 => 100644 rename lib/{ => utils}/custom_background.dart (90%) mode change 100755 => 100644 create mode 100644 lib/utils/debounce.dart rename lib/{ => utils}/dependencies.dart (100%) diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 9dc6b33b..6c0e99bd 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2022-05-21 23:33:06.517604","version":"2.10.4"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2022-05-28 15:48:56.328295","version":"2.10.4"} \ No newline at end of file diff --git a/lib/data/provider/auth.provider.dart b/lib/data/provider/auth.provider.dart index 557b1b52..57a5e3e7 100644 --- a/lib/data/provider/auth.provider.dart +++ b/lib/data/provider/auth.provider.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/data/models/login.result.dart'; import 'package:ecommerce_int2/data/models/user.model.dart'; import 'package:ecommerce_int2/services/network.service.dart'; diff --git a/lib/interceptor/dio_interceptor.dart b/lib/interceptor/dio_interceptor.dart index 166fff67..c291f57a 100644 --- a/lib/interceptor/dio_interceptor.dart +++ b/lib/interceptor/dio_interceptor.dart @@ -1,6 +1,6 @@ import 'dart:io'; import 'package:dio/dio.dart'; -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; diff --git a/lib/main.dart b/lib/main.dart index 39b9d725..76199fc9 100755 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/dependencies.dart'; +import 'package:ecommerce_int2/utils/dependencies.dart'; import 'package:ecommerce_int2/screens/splash_page.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; diff --git a/lib/models/product.dart b/lib/models/product.dart index 4fa8c7df..30f05406 100755 --- a/lib/models/product.dart +++ b/lib/models/product.dart @@ -1,8 +1,8 @@ -class Product{ - String image; - String name; - String description; - double price; +// class Product{ +// String image; +// String name; +// String description; +// double price; - Product(this.image, this.name, this.description, this.price); -} \ No newline at end of file +// Product(this.image, this.name, this.description, this.price); +// } \ No newline at end of file diff --git a/lib/screens/address/add_address_page.dart b/lib/screens/address/add_address_page.dart index 7bac85e4..55a2d842 100755 --- a/lib/screens/address/add_address_page.dart +++ b/lib/screens/address/add_address_page.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/data/repository/address.repository.dart'; import 'package:ecommerce_int2/screens/address/address_form.dart'; import 'package:ecommerce_int2/screens/select_card_page.dart'; diff --git a/lib/screens/auth/confirm_otp_page.dart b/lib/screens/auth/confirm_otp_page.dart index ded6a0bc..cf671e13 100755 --- a/lib/screens/auth/confirm_otp_page.dart +++ b/lib/screens/auth/confirm_otp_page.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/intro_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; diff --git a/lib/screens/auth/forgot_password_page.dart b/lib/screens/auth/forgot_password_page.dart index 9aefbdbc..d54c157e 100755 --- a/lib/screens/auth/forgot_password_page.dart +++ b/lib/screens/auth/forgot_password_page.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:flutter/material.dart'; import 'package:country_code_picker/country_code_picker.dart'; diff --git a/lib/screens/auth/register_page.dart b/lib/screens/auth/register_page.dart index ea053966..e2de9dc2 100755 --- a/lib/screens/auth/register_page.dart +++ b/lib/screens/auth/register_page.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; diff --git a/lib/screens/auth/welcome_back_page.dart b/lib/screens/auth/welcome_back_page.dart index 0e274d05..9a2839be 100755 --- a/lib/screens/auth/welcome_back_page.dart +++ b/lib/screens/auth/welcome_back_page.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/auth/forgot_password_page.dart'; import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:flutter/material.dart'; diff --git a/lib/screens/category/category.controller.dart b/lib/screens/category/category.controller.dart index d0a6423f..2105774f 100644 --- a/lib/screens/category/category.controller.dart +++ b/lib/screens/category/category.controller.dart @@ -25,6 +25,7 @@ class CategoryController extends GetxController { void getCategoryList() { repository.getAllCategories().then((value) { categoryList = value; + tempList = categoryList.categories!; update(); }, onError: (exeption) => print(exeption)); } diff --git a/lib/screens/category/category_list_page.dart b/lib/screens/category/category_list_page.dart index 90dc953d..0efe6c54 100755 --- a/lib/screens/category/category_list_page.dart +++ b/lib/screens/category/category_list_page.dart @@ -1,6 +1,7 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/data/repository/category.repository.dart'; import 'package:ecommerce_int2/screens/category/category.controller.dart'; +import 'package:ecommerce_int2/screens/category/sub_category_list_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; @@ -8,7 +9,6 @@ import 'package:get/get.dart'; import 'components/staggered_category_card.dart'; class CategoryListPage extends StatelessWidget { - @override Widget build(BuildContext context) { return Material( @@ -62,9 +62,12 @@ class CategoryListPage extends StatelessWidget { ), child: StaggeredCardCard( begin: const Color(0xffFCE183), - end: const Color(0xffF68D7F), - categoryName: controller.tempList[index].categoryName ?? "", - assetPath: 'assets/jeans_5.png', + end: const Color(0xffF68D7F), + categoryName: + controller.tempList[index].categoryName ?? "", + assetPath: 'assets/jeans_5.png', + onViewMore: () => Get.to(SubCategoryListPage( + category: controller.tempList[index])), ), ), ), diff --git a/lib/screens/category/components/staggered_category_card.dart b/lib/screens/category/components/staggered_category_card.dart index 6deb245f..556f093c 100755 --- a/lib/screens/category/components/staggered_category_card.dart +++ b/lib/screens/category/components/staggered_category_card.dart @@ -5,6 +5,7 @@ class CategoryCard extends StatelessWidget { final Color end; final String categoryName; final String assetPath; + final Function onViewMore; CategoryCard({ required this.controller, @@ -12,6 +13,7 @@ class CategoryCard extends StatelessWidget { required this.end, required this.categoryName, required this.assetPath, + required this.onViewMore, }) : height = Tween(begin: 150, end: 250.0).animate( CurvedAnimation( parent: controller, @@ -56,12 +58,15 @@ class CategoryCard extends StatelessWidget { children: [ Align( alignment: Alignment(-1, 0), - child: Text( - categoryName, - style: TextStyle( - fontSize: 22, - color: Colors.white, - fontWeight: FontWeight.bold), + child: Container( + width: 150, + child: Text( + categoryName, + style: TextStyle( + fontSize: 22, + color: Colors.white, + fontWeight: FontWeight.bold), + ), )), Column( mainAxisAlignment: MainAxisAlignment.center, @@ -75,15 +80,18 @@ class CategoryCard extends StatelessWidget { assetPath, ), ), - Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(24))), - padding: - const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), - child: Text( - 'View more', - style: TextStyle(color: end, fontWeight: FontWeight.bold), + GestureDetector( + onTap: () => onViewMore(), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(24))), + padding: + const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), + child: Text( + 'View more', + style: TextStyle(color: end, fontWeight: FontWeight.bold), + ), ), ) ], @@ -107,12 +115,14 @@ class StaggeredCardCard extends StatefulWidget { final Color end; final String categoryName; final String assetPath; + final Function onViewMore; const StaggeredCardCard({ required this.begin, required this.end, required this.categoryName, required this.assetPath, + required this.onViewMore, }); @override @@ -168,6 +178,7 @@ class _StaggeredCardCardState extends State begin: widget.begin, end: widget.end, assetPath: widget.assetPath, + onViewMore: widget.onViewMore, ), ); } diff --git a/lib/screens/category/sub_category.controller.dart b/lib/screens/category/sub_category.controller.dart index 97b0923e..bfa23311 100644 --- a/lib/screens/category/sub_category.controller.dart +++ b/lib/screens/category/sub_category.controller.dart @@ -18,6 +18,12 @@ class SubCategoryController extends GetxController { List tempList = []; + @override + void onInit() { + tempList = list; + super.onInit(); + } + void onChanged(String value) { if (value.isNotEmpty) { list.forEach((subCategory) { diff --git a/lib/screens/category/sub_category_list_page.dart b/lib/screens/category/sub_category_list_page.dart index bf005c60..666647da 100644 --- a/lib/screens/category/sub_category_list_page.dart +++ b/lib/screens/category/sub_category_list_page.dart @@ -1,7 +1,9 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/data/models/category.model.dart'; import 'package:ecommerce_int2/data/repository/category.repository.dart'; import 'package:ecommerce_int2/screens/category/sub_category.controller.dart'; +import 'package:ecommerce_int2/screens/product/view_product_page.dart'; +import 'package:ecommerce_int2/screens/search_products/search_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; @@ -9,10 +11,10 @@ import 'package:get/get.dart'; import 'components/staggered_category_card.dart'; class SubCategoryListPage extends StatelessWidget { - final Category category; - const SubCategoryListPage({Key? key, required this.category}) : super(key: key); + const SubCategoryListPage({Key? key, required this.category}) + : super(key: key); @override Widget build(BuildContext context) { @@ -67,9 +69,11 @@ class SubCategoryListPage extends StatelessWidget { ), child: StaggeredCardCard( begin: const Color(0xffFCE183), - end: const Color(0xffF68D7F), + end: const Color(0xffF68D7F), categoryName: controller.tempList[index].name ?? "", - assetPath: 'assets/jeans_5.png', + assetPath: 'assets/jeans_5.png', + onViewMore: () => Get.to(SearchPage(), + arguments: controller.tempList[index].slug), ), ), ), diff --git a/lib/screens/faq_page.dart b/lib/screens/faq_page.dart index e62b6662..0268257f 100755 --- a/lib/screens/faq_page.dart +++ b/lib/screens/faq_page.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; diff --git a/lib/screens/intro_page.dart b/lib/screens/intro_page.dart index 5ab956af..fed6946f 100755 --- a/lib/screens/intro_page.dart +++ b/lib/screens/intro_page.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/main/main_page.dart'; import 'package:flutter/material.dart'; diff --git a/lib/screens/main/components/product_list.dart b/lib/screens/main/components/product_list.dart index cab0dc23..c6fb047f 100755 --- a/lib/screens/main/components/product_list.dart +++ b/lib/screens/main/components/product_list.dart @@ -1,15 +1,15 @@ import 'package:card_swiper/card_swiper.dart'; -import 'package:ecommerce_int2/app_properties.dart'; -import 'package:ecommerce_int2/models/product.dart'; +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/product/product_page.dart'; import 'package:flutter/material.dart'; -class ProductList extends StatelessWidget { +class ProductListView extends StatelessWidget { List products; final SwiperController swiperController = SwiperController(); - ProductList({required this.products}); + ProductListView({required this.products}); @override Widget build(BuildContext context) { @@ -135,7 +135,7 @@ class ProductCard extends StatelessWidget { child: Padding( padding: const EdgeInsets.all(8.0), child: Text( - product.name, + product.name ?? "", style: TextStyle(color: Colors.white, fontSize: 16.0), ), @@ -167,9 +167,9 @@ class ProductCard extends StatelessWidget { ), Positioned( child: Hero( - tag: product.image, + tag: product.imageUrl!, child: Image.asset( - product.image, + product.imageUrl!, height: height / 1.7, width: width / 1.4, fit: BoxFit.contain, diff --git a/lib/screens/main/components/recommended_list.dart b/lib/screens/main/components/recommended_list.dart index 939f2c9f..34a71731 100755 --- a/lib/screens/main/components/recommended_list.dart +++ b/lib/screens/main/components/recommended_list.dart @@ -1,21 +1,21 @@ -import 'package:ecommerce_int2/app_properties.dart'; -import 'package:ecommerce_int2/models/product.dart'; +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/product/product_page.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; import 'package:flutter/material.dart'; class RecommendedList extends StatelessWidget { List products = [ - Product('assets/bag_1.png', 'Bag', 'Beautiful bag', 2.33), - Product('assets/cap_5.png', 'Cap', 'Cap with beautiful design', 10), - Product('assets/jeans_1.png', 'Jeans', 'Jeans for you', 20), - Product('assets/womanshoe_3.png', 'Woman Shoes', - 'Shoes with special discount', 30), - Product('assets/bag_10.png', 'Bag Express', 'Bag for your shops', 40), - Product('assets/jeans_3.png', 'Jeans', 'Beautiful Jeans', 102.33), - Product('assets/ring_1.png', 'Silver Ring', 'Description', 52.33), - Product('assets/shoeman_7.png', 'Shoes', 'Description', 62.33), - Product('assets/headphone_9.png', 'Headphones', 'Description', 72.33), + // Product('assets/bag_1.png', 'Bag', 'Beautiful bag', 2.33), + // Product('assets/cap_5.png', 'Cap', 'Cap with beautiful design', 10), + // Product('assets/jeans_1.png', 'Jeans', 'Jeans for you', 20), + // Product('assets/womanshoe_3.png', 'Woman Shoes', + // 'Shoes with special discount', 30), + // Product('assets/bag_10.png', 'Bag Express', 'Bag for your shops', 40), + // Product('assets/jeans_3.png', 'Jeans', 'Beautiful Jeans', 102.33), + // Product('assets/ring_1.png', 'Silver Ring', 'Description', 52.33), + // Product('assets/shoeman_7.png', 'Shoes', 'Description', 62.33), + // Product('assets/headphone_9.png', 'Headphones', 'Description', 72.33), ]; @override @@ -71,8 +71,8 @@ class RecommendedList extends StatelessWidget { focalRadius: 0.1), ), child: Hero( - tag: products[index].image, - child: Image.asset(products[index].image))), + tag: products[index].imageUrl!, + child: Image.asset(products[index].imageUrl!))), ), ), staggeredTileBuilder: (int index) => diff --git a/lib/screens/main/main_page.dart b/lib/screens/main/main_page.dart index 1d58201c..544e4c71 100755 --- a/lib/screens/main/main_page.dart +++ b/lib/screens/main/main_page.dart @@ -1,15 +1,15 @@ -import 'package:ecommerce_int2/app_properties.dart'; -import 'package:ecommerce_int2/custom_background.dart'; -import 'package:ecommerce_int2/models/product.dart'; +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/screens/main/components/product_list.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; +import 'package:ecommerce_int2/utils/custom_background.dart'; import 'package:ecommerce_int2/screens/category/category_list_page.dart'; import 'package:ecommerce_int2/screens/notifications_page.dart'; import 'package:ecommerce_int2/screens/profile_page.dart'; -import 'package:ecommerce_int2/screens/search_page.dart'; +import 'package:ecommerce_int2/screens/search_products/search_page.dart'; import 'package:ecommerce_int2/screens/shop/check_out_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'components/custom_bottom_bar.dart'; -import 'components/product_list.dart'; import 'components/tab_view.dart'; class MainPage extends StatefulWidget { @@ -21,21 +21,21 @@ List timelines = ['Weekly featured', 'Best of June', 'Best of 2018']; String selectedTimeline = 'Weekly featured'; List products = [ - Product( - 'assets/headphones_2.png', - 'Skullcandy headset L325', - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - 102.99), - Product( - 'assets/headphones_3.png', - 'Skullcandy headset X25', - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - 55.99), - Product( - 'assets/headphones.png', - 'Blackzy PRO hedphones M003', - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - 152.99), + // Product( + // 'assets/headphones_2.png', + // 'Skullcandy headset L325', + // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', + // 102.99), + // Product( + // 'assets/headphones_3.png', + // 'Skullcandy headset X25', + // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', + // 55.99), + // Product( + // 'assets/headphones.png', + // 'Blackzy PRO hedphones M003', + // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', + // 152.99), ]; class _MainPageState extends State @@ -80,21 +80,21 @@ class _MainPageState extends State setState(() { selectedTimeline = timelines[0]; products = [ - Product( - 'assets/headphones_2.png', - 'Skullcandy headset L325', - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - 102.99), - Product( - 'assets/headphones_3.png', - 'Skullcandy headset X25', - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - 55.99), - Product( - 'assets/headphones.png', - 'Blackzy PRO hedphones M003', - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - 152.99), + // Product( + // 'assets/headphones_2.png', + // 'Skullcandy headset L325', + // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', + // 102.99), + // Product( + // 'assets/headphones_3.png', + // 'Skullcandy headset X25', + // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', + // 55.99), + // Product( + // 'assets/headphones.png', + // 'Blackzy PRO hedphones M003', + // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', + // 152.99), ]; }); }, @@ -112,21 +112,21 @@ class _MainPageState extends State setState(() { selectedTimeline = timelines[1]; products = [ - Product( - 'assets/bag_5.png', - 'Skullcandy headset L325', - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - 102.99), - Product( - 'assets/bag_6.png', - 'Skullcandy headset X25', - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - 55.99), - Product( - 'assets/bag_3.png', - 'Blackzy PRO hedphones M003', - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - 152.99), + // Product( + // 'assets/bag_5.png', + // 'Skullcandy headset L325', + // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', + // 102.99), + // Product( + // 'assets/bag_6.png', + // 'Skullcandy headset X25', + // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', + // 55.99), + // Product( + // 'assets/bag_3.png', + // 'Blackzy PRO hedphones M003', + // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', + // 152.99), ]; }); }, @@ -143,21 +143,21 @@ class _MainPageState extends State setState(() { selectedTimeline = timelines[2]; products = [ - Product( - 'assets/headphone_13.png', - 'Skullcandy headset L325', - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - 102.99), - Product( - 'assets/jeans_4.png', - 'Skullcandy headset X25', - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - 55.99), - Product( - 'assets/ring_7.png', - 'Blackzy PRO hedphones M003', - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - 152.99), + // Product( + // 'assets/headphone_13.png', + // 'Skullcandy headset L325', + // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', + // 102.99), + // Product( + // 'assets/jeans_4.png', + // 'Skullcandy headset X25', + // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', + // 55.99), + // Product( + // 'assets/ring_7.png', + // 'Blackzy PRO hedphones M003', + // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', + // 152.99), ]; }); }, @@ -210,7 +210,7 @@ class _MainPageState extends State child: topHeader, ), SliverToBoxAdapter( - child: ProductList( + child: ProductListView( products: products, ), ), diff --git a/lib/screens/notifications_page.dart b/lib/screens/notifications_page.dart index 0f5a3f8e..cb35d96b 100755 --- a/lib/screens/notifications_page.dart +++ b/lib/screens/notifications_page.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/rating/rating_page.dart'; import 'package:ecommerce_int2/screens/tracking_page.dart'; import 'package:flutter/material.dart'; diff --git a/lib/screens/payment/payment_page.dart b/lib/screens/payment/payment_page.dart index 49c30642..d610c47a 100755 --- a/lib/screens/payment/payment_page.dart +++ b/lib/screens/payment/payment_page.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/product/components/color_list.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; diff --git a/lib/screens/payment/promo_item.dart b/lib/screens/payment/promo_item.dart index 631243cc..a6615f4f 100755 --- a/lib/screens/payment/promo_item.dart +++ b/lib/screens/payment/promo_item.dart @@ -1,5 +1,5 @@ -import 'package:ecommerce_int2/app_properties.dart'; -import 'package:ecommerce_int2/models/product.dart'; +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/product/components/color_list.dart'; import 'package:ecommerce_int2/screens/product/components/shop_product.dart'; import 'package:flutter/material.dart'; @@ -131,10 +131,10 @@ class PromoItem extends StatelessWidget { top: 5, child: ShopProductDisplay( Product( - 'assets/headphones.png', - 'Boat roackerz 400 On-Ear Bluetooth Headphones', - 'description', - 45.3), + imageUrl: 'assets/headphones.png', + name: 'Boat roackerz 400 On-Ear Bluetooth Headphones', + description: 'description', + price: 45000), onPressed: () {}, ), ), diff --git a/lib/screens/payment/unpaid_page.dart b/lib/screens/payment/unpaid_page.dart index 74141a9f..014c3b6c 100755 --- a/lib/screens/payment/unpaid_page.dart +++ b/lib/screens/payment/unpaid_page.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/payment/promo_item.dart'; import 'package:flutter/material.dart'; diff --git a/lib/screens/payment_history_page.dart b/lib/screens/payment_history_page.dart index 5d28b846..c0d2d886 100755 --- a/lib/screens/payment_history_page.dart +++ b/lib/screens/payment_history_page.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/api_service.dart'; +import 'package:ecommerce_int2/utils/api_service.dart'; import 'package:ecommerce_int2/models/user.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; diff --git a/lib/screens/product/components/color_list.dart b/lib/screens/product/components/color_list.dart index 699cd4b8..6f6e9e1c 100755 --- a/lib/screens/product/components/color_list.dart +++ b/lib/screens/product/components/color_list.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:flutter/material.dart'; class ColorList extends StatefulWidget { diff --git a/lib/screens/product/components/more_products.dart b/lib/screens/product/components/more_products.dart index 5a6cb17c..0dc64795 100755 --- a/lib/screens/product/components/more_products.dart +++ b/lib/screens/product/components/more_products.dart @@ -1,25 +1,25 @@ -import 'package:ecommerce_int2/app_properties.dart'; -import 'package:ecommerce_int2/models/product.dart'; +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/product/components/product_card.dart'; import 'package:flutter/material.dart'; class MoreProducts extends StatelessWidget { final List products = [ - Product( - 'assets/headphones_2.png', - 'Skullcandy headset L325', - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - 102.99), - Product( - 'assets/headphones_3.png', - 'Skullcandy headset X25', - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - 55.99), - Product( - 'assets/headphones.png', - 'Blackzy PRO hedphones M003', - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - 152.99), + // Product( + // 'assets/headphones_2.png', + // 'Skullcandy headset L325', + // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', + // 102.99), + // Product( + // 'assets/headphones_3.png', + // 'Skullcandy headset X25', + // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', + // 55.99), + // Product( + // 'assets/headphones.png', + // 'Blackzy PRO hedphones M003', + // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', + // 152.99), ]; @override diff --git a/lib/screens/product/components/product_card.dart b/lib/screens/product/components/product_card.dart index e4d0e1c3..5f77ef3b 100755 --- a/lib/screens/product/components/product_card.dart +++ b/lib/screens/product/components/product_card.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/models/product.dart'; +import 'package:ecommerce_int2/data/models/product.model.dart'; import 'package:flutter/material.dart'; class ProductCard extends StatelessWidget { @@ -26,7 +26,7 @@ class ProductCard extends StatelessWidget { width: MediaQuery.of(context).size.width / 2 - 64, height: MediaQuery.of(context).size.width / 2 - 64, child: Image.asset( - product.image, + product.imageUrl!, ), ), ), @@ -42,7 +42,7 @@ class ProductCard extends StatelessWidget { topLeft: Radius.circular(10), bottomLeft: Radius.circular(10))), child: Text( - product.name, + product.name ?? "Product", textAlign: TextAlign.right, style: TextStyle( fontSize: 12.0, diff --git a/lib/screens/product/components/product_display.dart b/lib/screens/product/components/product_display.dart index 2bb9492b..27020c8d 100755 --- a/lib/screens/product/components/product_display.dart +++ b/lib/screens/product/components/product_display.dart @@ -1,5 +1,5 @@ -import 'package:ecommerce_int2/app_properties.dart'; -import 'package:ecommerce_int2/models/product.dart'; +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/rating/rating_page.dart'; import 'package:flutter/material.dart'; @@ -65,9 +65,9 @@ class ProductDisplay extends StatelessWidget { ), child: Container( child: Hero( - tag: product.image, + tag: product.imageUrl!, child: Image.asset( - product.image, + product.imageUrl!, fit: BoxFit.contain, height: 230, width: 230, diff --git a/lib/screens/product/components/product_options.dart b/lib/screens/product/components/product_options.dart index a1ac9570..06bf3137 100755 --- a/lib/screens/product/components/product_options.dart +++ b/lib/screens/product/components/product_options.dart @@ -1,5 +1,5 @@ -import 'package:ecommerce_int2/app_properties.dart'; -import 'package:ecommerce_int2/models/product.dart'; +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/shop/check_out_page.dart'; import 'package:flutter/material.dart'; @@ -22,7 +22,7 @@ class ProductOption extends StatelessWidget { Positioned( left: 16.0, child: Image.asset( - product.image, + product.imageUrl!, height: 200, width: 200, ), @@ -38,7 +38,7 @@ class ProductOption extends StatelessWidget { children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 24.0), - child: Text(product.name, + child: Text(product.name ?? '', textAlign: TextAlign.right, style: TextStyle( fontWeight: FontWeight.bold, diff --git a/lib/screens/product/components/rating_bottomSheet.dart b/lib/screens/product/components/rating_bottomSheet.dart index 3a66cf54..6d5824ae 100755 --- a/lib/screens/product/components/rating_bottomSheet.dart +++ b/lib/screens/product/components/rating_bottomSheet.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:flutter/material.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; diff --git a/lib/screens/product/components/shop_bottomSheet.dart b/lib/screens/product/components/shop_bottomSheet.dart index ba8fcd04..7d0792b1 100755 --- a/lib/screens/product/components/shop_bottomSheet.dart +++ b/lib/screens/product/components/shop_bottomSheet.dart @@ -1,5 +1,5 @@ -import 'package:ecommerce_int2/app_properties.dart'; -import 'package:ecommerce_int2/models/product.dart'; +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/shop/check_out_page.dart'; import 'package:flutter/material.dart'; @@ -12,21 +12,21 @@ class ShopBottomSheet extends StatefulWidget { class _ShopBottomSheetState extends State { List products = [ - Product( - 'assets/headphones.png', - 'Boat roackerz 400 On-Ear Bluetooth Headphones', - 'description', - 45.3), - Product( - 'assets/headphones_2.png', - 'Boat roackerz 100 On-Ear Bluetooth Headphones', - 'description', - 22.3), - Product( - 'assets/headphones_3.png', - 'Boat roackerz 300 On-Ear Bluetooth Headphones', - 'description', - 58.3) + // Product( + // 'assets/headphones.png', + // 'Boat roackerz 400 On-Ear Bluetooth Headphones', + // 'description', + // 45.3), + // Product( + // 'assets/headphones_2.png', + // 'Boat roackerz 100 On-Ear Bluetooth Headphones', + // 'description', + // 22.3), + // Product( + // 'assets/headphones_3.png', + // 'Boat roackerz 300 On-Ear Bluetooth Headphones', + // 'description', + // 58.3) ]; @override diff --git a/lib/screens/product/components/shop_product.dart b/lib/screens/product/components/shop_product.dart index ae0c95ac..6f953979 100755 --- a/lib/screens/product/components/shop_product.dart +++ b/lib/screens/product/components/shop_product.dart @@ -1,5 +1,5 @@ -import 'package:ecommerce_int2/app_properties.dart'; -import 'package:ecommerce_int2/models/product.dart'; +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:flutter/material.dart'; class ShopProduct extends StatelessWidget { @@ -25,7 +25,7 @@ class ShopProduct extends StatelessWidget { Padding( padding: const EdgeInsets.all(8.0), child: Text( - product.name, + product.name ?? '', textAlign: TextAlign.center, style: TextStyle( color: darkGrey, @@ -73,7 +73,7 @@ class ShopProductDisplay extends StatelessWidget { height: 80, width: 80, child: Image.asset( - '${product.image}', + product.imageUrl!, fit: BoxFit.contain, )), ), diff --git a/lib/screens/product/product_page.dart b/lib/screens/product/product_page.dart index 193c7e54..f531d6bf 100755 --- a/lib/screens/product/product_page.dart +++ b/lib/screens/product/product_page.dart @@ -1,6 +1,6 @@ -import 'package:ecommerce_int2/app_properties.dart'; -import 'package:ecommerce_int2/models/product.dart'; -import 'package:ecommerce_int2/screens/search_page.dart'; +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; +import 'package:ecommerce_int2/screens/search_products/search_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -95,7 +95,7 @@ class _ProductPageState extends State { Padding( padding: const EdgeInsets.only(left: 20.0, right: 16.0), child: Text( - product.name, + product.name ?? "", style: const TextStyle( color: const Color(0xFFFEFEFE), fontWeight: FontWeight.w600, @@ -136,7 +136,7 @@ class _ProductPageState extends State { Padding( padding: EdgeInsets.only(left: 20.0, right: 40.0, bottom: 130), - child: new Text(product.description, + child: new Text(product.description ?? "", style: const TextStyle( color: const Color(0xfefefefe), fontWeight: FontWeight.w800, diff --git a/lib/screens/product/view_product_page.dart b/lib/screens/product/view_product_page.dart index 4bbdd652..154ae3cb 100755 --- a/lib/screens/product/view_product_page.dart +++ b/lib/screens/product/view_product_page.dart @@ -1,10 +1,10 @@ -import 'package:ecommerce_int2/models/product.dart'; import 'package:ecommerce_int2/screens/product/components/rating_bottomSheet.dart'; -import 'package:ecommerce_int2/screens/search_page.dart'; +import 'package:ecommerce_int2/screens/search_products/search_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import '../../app_properties.dart'; +import '../../data/models/product.model.dart'; +import '../../utils/app_properties.dart'; import 'components/color_list.dart'; import 'components/more_products.dart'; import 'components/product_options.dart'; @@ -59,7 +59,7 @@ class _ViewProductPageState extends State { Widget description = Padding( padding: const EdgeInsets.all(24.0), child: Text( - widget.product.description, + widget.product.description ?? 'description', maxLines: 5, semanticsLabel: '...', overflow: TextOverflow.ellipsis, @@ -98,10 +98,10 @@ class _ViewProductPageState extends State { width: MediaQuery.of(context).size.width, child: Column( children: [ - ProductOption( - _scaffoldKey, - product: widget.product, - ), + // ProductOption( + // _scaffoldKey, + // product: widget.product, + // ), description, Padding( padding: const EdgeInsets.all(24.0), diff --git a/lib/screens/profile_page.dart b/lib/screens/profile_page.dart index c8ec7ad4..703de6cf 100755 --- a/lib/screens/profile_page.dart +++ b/lib/screens/profile_page.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/faq_page.dart'; import 'package:ecommerce_int2/screens/payment/payment_page.dart'; import 'package:ecommerce_int2/screens/settings/settings_page.dart'; diff --git a/lib/screens/rating/rating_dialog.dart b/lib/screens/rating/rating_dialog.dart index d0eab80f..02f385cc 100755 --- a/lib/screens/rating/rating_dialog.dart +++ b/lib/screens/rating/rating_dialog.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/shop/check_out_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; diff --git a/lib/screens/rating/rating_page.dart b/lib/screens/rating/rating_page.dart index 08b6ef19..8684ef6f 100755 --- a/lib/screens/rating/rating_page.dart +++ b/lib/screens/rating/rating_page.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:flutter/material.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; diff --git a/lib/screens/request_money/receive_page.dart b/lib/screens/request_money/receive_page.dart index 3b5458ad..49acc8c3 100755 --- a/lib/screens/request_money/receive_page.dart +++ b/lib/screens/request_money/receive_page.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/models/user.dart'; import 'package:flutter/material.dart'; import 'dart:math' as math; diff --git a/lib/screens/request_money/request_amount_page.dart b/lib/screens/request_money/request_amount_page.dart index 2210a2b6..1151fed6 100755 --- a/lib/screens/request_money/request_amount_page.dart +++ b/lib/screens/request_money/request_amount_page.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/models/user.dart'; import 'package:ecommerce_int2/screens/request_money/receive_page.dart'; import 'package:flutter/material.dart'; diff --git a/lib/screens/request_money/request_page.dart b/lib/screens/request_money/request_page.dart index 0ef51e57..23c1695a 100755 --- a/lib/screens/request_money/request_page.dart +++ b/lib/screens/request_money/request_page.dart @@ -1,11 +1,11 @@ -import 'package:ecommerce_int2/api_service.dart'; +import 'package:ecommerce_int2/utils/api_service.dart'; import 'package:ecommerce_int2/models/user.dart'; import 'package:ecommerce_int2/screens/request_money/request_amount_page.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import '../../app_properties.dart'; +import '../../utils/app_properties.dart'; class RequestPage extends StatefulWidget { @override diff --git a/lib/screens/search_products/search_controller.dart b/lib/screens/search_products/search_controller.dart new file mode 100644 index 00000000..81c11e63 --- /dev/null +++ b/lib/screens/search_products/search_controller.dart @@ -0,0 +1,59 @@ +import 'package:ecommerce_int2/data/models/category.model.dart'; +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/data/repository/product.repository.dart'; +import 'package:ecommerce_int2/utils/debounce.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; + +class SearchProductController extends GetxController { + final ProductRepository repository; + + SearchProductController(this.repository); + + TextEditingController searchController = TextEditingController(); + +RefreshController refreshController = + RefreshController(initialRefresh: false); + int currentPage = 1; + + ProductFilter filter = ProductFilter(sortOrder: SortOrder(iId: -1)); + + final Debounce debounce = Debounce(milliseconds: 2000); + + List list = []; + + @override + void onInit() { + super.onInit(); + } + + void getProduct() async { + final res = await repository.getProducts(filter); + list.addAll(res.products!); + refreshController.loadComplete(); + update(); + } + + void onRefresh() { + list.clear(); + currentPage = 1; + filter.pageNumber = 1; + getProduct(); + } + + void onLoadMore() { + ++ currentPage; + filter.pageNumber = currentPage; + getProduct(); + } + + void onChanged(String value) { + debounce.run(() { + if (value.isNotEmpty) { + getProduct(); + update(); + } + }); + } +} diff --git a/lib/screens/search_page.dart b/lib/screens/search_products/search_page.dart old mode 100755 new mode 100644 similarity index 60% rename from lib/screens/search_page.dart rename to lib/screens/search_products/search_page.dart index ae34f571..18734294 --- a/lib/screens/search_page.dart +++ b/lib/screens/search_products/search_page.dart @@ -1,8 +1,12 @@ -import 'package:ecommerce_int2/app_properties.dart'; -import 'package:ecommerce_int2/models/product.dart'; +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/data/repository/product.repository.dart'; +import 'package:ecommerce_int2/screens/search_products/search_controller.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/product/view_product_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:rubber/rubber.dart'; class SearchPage extends StatefulWidget { @@ -17,21 +21,21 @@ class _SearchPageState extends State String selectedPrice = ""; List products = [ - Product( - 'assets/headphones_2.png', - 'Skullcandy headset L325', - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - 102.99), - Product( - 'assets/headphones_3.png', - 'Skullcandy headset X25', - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - 55.99), - Product( - 'assets/headphones.png', - 'Blackzy PRO hedphones M003', - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - 152.99), + // Product( + // 'assets/headphones_2.png', + // 'Skullcandy headset L325', + // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', + // 102.99), + // Product( + // 'assets/headphones_3.png', + // 'Skullcandy headset X25', + // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', + // 55.99), + // Product( + // 'assets/headphones.png', + // 'Blackzy PRO hedphones M003', + // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', + // 152.99), ]; List timeFilter = [ @@ -83,7 +87,7 @@ class _SearchPageState extends State _controller.expand(); } - Widget _getLowerLayer() { + Widget _getLowerLayer(SearchProductController controller) { return Container( margin: const EdgeInsets.only(top: kToolbarHeight), child: Column( @@ -116,7 +120,7 @@ class _SearchPageState extends State if (value.isNotEmpty) { List tempList = []; products.forEach((product) { - if (product.name.toLowerCase().contains(value)) { + if (product.name!.toLowerCase().contains(value)) { tempList.add(product); } }); @@ -156,18 +160,26 @@ class _SearchPageState extends State Flexible( child: Container( color: Colors.orange[50], - child: ListView.builder( - itemCount: searchResults.length, - itemBuilder: (_, index) => Padding( - padding: EdgeInsets.symmetric(horizontal: 16.0), - child: ListTile( - onTap: () => - Navigator.of(context).push(MaterialPageRoute( - builder: (_) => ViewProductPage( - product: searchResults[index], - ))), - title: Text(searchResults[index].name), - ))), + child: SmartRefresher( + enablePullDown: true, + enablePullUp: true, + controller: controller.refreshController, + onLoading: controller.onLoadMore, + onRefresh: controller.onRefresh, + header: WaterDropHeader(), + child: ListView.builder( + itemCount: controller.list.length, + itemBuilder: (_, index) => Padding( + padding: EdgeInsets.symmetric(horizontal: 16.0), + child: ListTile( + onTap: () => + Navigator.of(context).push(MaterialPageRoute( + builder: (_) => ViewProductPage( + product: controller.list[index], + ))), + title: Text(controller.list[index].name ?? ''), + ))), + ), ), ) ], @@ -175,7 +187,7 @@ class _SearchPageState extends State ); } - Widget _getUpperLayer() { + Widget _getUpperLayer(SearchProductController controller) { return Container( decoration: BoxDecoration( boxShadow: [ @@ -321,24 +333,15 @@ class _SearchPageState extends State top: true, bottom: false, child: Scaffold( -// bottomSheet: ClipRRect( -// borderRadius: BorderRadius.only( -// topRight: Radius.circular(25), topLeft: Radius.circular(25)), -// child: BottomSheet( -// onClosing: () {}, -// builder: (_) => Container( -// padding: EdgeInsets.all(16.0), -// child: Row( -// mainAxisAlignment: MainAxisAlignment.center, -// children: [Text('Filters')]), -// color: Colors.white, -// width: MediaQuery.of(context).size.height, -// )), -// ), - body: RubberBottomSheet( - lowerLayer: _getLowerLayer(), // The underlying page (Widget) - upperLayer: _getUpperLayer(), // The bottomsheet content (Widget) - animationController: _controller, // The one we created earlier + body: GetBuilder( + init: SearchProductController(Get.find()), + builder: (controller) => RubberBottomSheet( + lowerLayer: + _getLowerLayer(controller), // The underlying page (Widget) + upperLayer: + _getUpperLayer(controller), // The bottomsheet content (Widget) + animationController: _controller, // The one we created earlier + ), )), ), ); diff --git a/lib/screens/select_card_page.dart b/lib/screens/select_card_page.dart index 0216b4f2..65f7f66c 100755 --- a/lib/screens/select_card_page.dart +++ b/lib/screens/select_card_page.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:flutter/material.dart'; import 'dart:math' as math; diff --git a/lib/screens/send_money/quick_send_amount_page.dart b/lib/screens/send_money/quick_send_amount_page.dart index b58ce663..fef3c26e 100755 --- a/lib/screens/send_money/quick_send_amount_page.dart +++ b/lib/screens/send_money/quick_send_amount_page.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/models/user.dart'; import 'package:ecommerce_int2/screens/request_money/receive_page.dart'; import 'package:flutter/material.dart'; diff --git a/lib/screens/send_money/send_page.dart b/lib/screens/send_money/send_page.dart index e153cb13..abd23393 100755 --- a/lib/screens/send_money/send_page.dart +++ b/lib/screens/send_money/send_page.dart @@ -1,11 +1,11 @@ -import 'package:ecommerce_int2/api_service.dart'; +import 'package:ecommerce_int2/utils/api_service.dart'; import 'package:ecommerce_int2/models/user.dart'; import 'package:ecommerce_int2/screens/send_money/quick_send_amount_page.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import '../../app_properties.dart'; +import '../../utils/app_properties.dart'; class SendPage extends StatefulWidget { @override diff --git a/lib/screens/settings/change_country.dart b/lib/screens/settings/change_country.dart index f5c73dc5..ab26033d 100755 --- a/lib/screens/settings/change_country.dart +++ b/lib/screens/settings/change_country.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:flutter/material.dart'; class ChangeCountryPage extends StatefulWidget { diff --git a/lib/screens/settings/change_language_page.dart b/lib/screens/settings/change_language_page.dart index 1ae518e4..1fc4cd05 100755 --- a/lib/screens/settings/change_language_page.dart +++ b/lib/screens/settings/change_language_page.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:flutter/material.dart'; class ChangeLanguagePage extends StatefulWidget { diff --git a/lib/screens/settings/change_password_page.dart b/lib/screens/settings/change_password_page.dart index f2ac932f..7da4b017 100755 --- a/lib/screens/settings/change_password_page.dart +++ b/lib/screens/settings/change_password_page.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; diff --git a/lib/screens/settings/legal_about_page.dart b/lib/screens/settings/legal_about_page.dart index 9b2bf0c7..abbfe13c 100755 --- a/lib/screens/settings/legal_about_page.dart +++ b/lib/screens/settings/legal_about_page.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; diff --git a/lib/screens/settings/notifications_settings_page.dart b/lib/screens/settings/notifications_settings_page.dart index 3fd668aa..ddc6386a 100755 --- a/lib/screens/settings/notifications_settings_page.dart +++ b/lib/screens/settings/notifications_settings_page.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; diff --git a/lib/screens/settings/settings_page.dart b/lib/screens/settings/settings_page.dart index c10d4c0d..db3f0210 100755 --- a/lib/screens/settings/settings_page.dart +++ b/lib/screens/settings/settings_page.dart @@ -1,5 +1,5 @@ -import 'package:ecommerce_int2/app_properties.dart'; -import 'package:ecommerce_int2/custom_background.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; +import 'package:ecommerce_int2/utils/custom_background.dart'; import 'package:ecommerce_int2/screens/settings/change_country.dart'; import 'package:ecommerce_int2/screens/settings/change_password_page.dart'; import 'package:ecommerce_int2/screens/settings/legal_about_page.dart'; diff --git a/lib/screens/shop/check_out_page.dart b/lib/screens/shop/check_out_page.dart index 9a2d4d28..4896b16e 100755 --- a/lib/screens/shop/check_out_page.dart +++ b/lib/screens/shop/check_out_page.dart @@ -1,6 +1,6 @@ import 'package:card_swiper/card_swiper.dart'; -import 'package:ecommerce_int2/app_properties.dart'; -import 'package:ecommerce_int2/models/product.dart'; +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/address/add_address_page.dart'; import 'package:ecommerce_int2/screens/payment/unpaid_page.dart'; import 'package:flutter/material.dart'; @@ -17,12 +17,21 @@ class _CheckOutPageState extends State { SwiperController swiperController = SwiperController(); List products = [ - Product('assets/headphones.png', - 'Boat roackerz 400 On-Ear Bluetooth Headphones', 'description', 45.3), - Product('assets/headphones_2.png', - 'Boat roackerz 100 On-Ear Bluetooth Headphones', 'description', 22.3), - Product('assets/headphones_3.png', - 'Boat roackerz 300 On-Ear Bluetooth Headphones', 'description', 58.3) + Product( + imageUrl: 'assets/headphones.png', + name: 'Boat roackerz 400 On-Ear Bluetooth Headphones', + description: 'description', + price: 45000), + Product( + imageUrl: 'assets/headphones_2.png', + name: 'Boat roackerz 100 On-Ear Bluetooth Headphones', + description: 'description', + price: 22000), + Product( + imageUrl: 'assets/headphones_3.png', + name: 'Boat roackerz 300 On-Ear Bluetooth Headphones', + description: 'description', + price: 58000) ]; @override diff --git a/lib/screens/shop/components/shop_item_list.dart b/lib/screens/shop/components/shop_item_list.dart index 2358eb22..cfc82679 100755 --- a/lib/screens/shop/components/shop_item_list.dart +++ b/lib/screens/shop/components/shop_item_list.dart @@ -1,5 +1,5 @@ -import 'package:ecommerce_int2/app_properties.dart'; -import 'package:ecommerce_int2/models/product.dart'; +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/product/components/color_list.dart'; import 'package:ecommerce_int2/screens/product/components/shop_product.dart'; import 'package:flutter/material.dart'; @@ -46,7 +46,7 @@ class _ShopItemListState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - widget.product.name, + widget.product.name ?? 'Product', textAlign: TextAlign.right, style: TextStyle( fontWeight: FontWeight.bold, diff --git a/lib/screens/splash_page.dart b/lib/screens/splash_page.dart index 4420ceb6..04f906db 100755 --- a/lib/screens/splash_page.dart +++ b/lib/screens/splash_page.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/auth/welcome_back_page.dart'; import 'package:flutter/material.dart'; diff --git a/lib/screens/tracking_page.dart b/lib/screens/tracking_page.dart index 9d12c96e..aa14efaf 100755 --- a/lib/screens/tracking_page.dart +++ b/lib/screens/tracking_page.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; diff --git a/lib/screens/wallet/wallet_page.dart b/lib/screens/wallet/wallet_page.dart index b776669c..31db5476 100755 --- a/lib/screens/wallet/wallet_page.dart +++ b/lib/screens/wallet/wallet_page.dart @@ -1,5 +1,5 @@ -import 'package:ecommerce_int2/api_service.dart'; -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/api_service.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/models/user.dart'; import 'package:ecommerce_int2/screens/payment_history_page.dart'; import 'package:ecommerce_int2/screens/request_money/request_amount_page.dart'; diff --git a/lib/services/auth.service.dart b/lib/services/auth.service.dart index 19ca4948..e2e8c98c 100644 --- a/lib/services/auth.service.dart +++ b/lib/services/auth.service.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/data/models/user.model.dart'; import 'package:ecommerce_int2/data/repository/auth.repository.dart'; import 'package:ecommerce_int2/screens/auth/welcome_back_page.dart'; diff --git a/lib/api_service.dart b/lib/utils/api_service.dart old mode 100755 new mode 100644 similarity index 96% rename from lib/api_service.dart rename to lib/utils/api_service.dart index ba39f20a..4311f8b9 --- a/lib/api_service.dart +++ b/lib/utils/api_service.dart @@ -2,7 +2,7 @@ import 'dart:convert'; import 'package:http/http.dart' as http; -import 'models/user.dart'; +import '../models/user.dart'; class ApiService { static String url(int nrResults) { diff --git a/lib/app_properties.dart b/lib/utils/app_properties.dart old mode 100755 new mode 100644 similarity index 100% rename from lib/app_properties.dart rename to lib/utils/app_properties.dart diff --git a/lib/custom_background.dart b/lib/utils/custom_background.dart old mode 100755 new mode 100644 similarity index 90% rename from lib/custom_background.dart rename to lib/utils/custom_background.dart index 1bf1b50b..00934f7b --- a/lib/custom_background.dart +++ b/lib/utils/custom_background.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/app_properties.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:flutter/material.dart'; class MainBackground extends CustomPainter { diff --git a/lib/utils/debounce.dart b/lib/utils/debounce.dart new file mode 100644 index 00000000..d0fa2276 --- /dev/null +++ b/lib/utils/debounce.dart @@ -0,0 +1,17 @@ +import 'package:flutter/foundation.dart'; +import 'dart:async'; + +class Debounce { + final int milliseconds; + Timer? _timer; + + Debounce({required this.milliseconds}); + + run(VoidCallback action) { + if (_timer != null) { + _timer!.cancel(); + } + + _timer = Timer(Duration(milliseconds: milliseconds), action); + } +} diff --git a/lib/dependencies.dart b/lib/utils/dependencies.dart similarity index 100% rename from lib/dependencies.dart rename to lib/utils/dependencies.dart diff --git a/pubspec.lock b/pubspec.lock index ed258640..60d34c19 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -585,6 +585,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.0" + pull_to_refresh: + dependency: "direct main" + description: + name: pull_to_refresh + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" rubber: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 9d903321..d3344f8e 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -38,6 +38,7 @@ dependencies: dio: ^4.0.6 get_storage: ^2.0.3 path_provider: ^2.0.10 + pull_to_refresh: ^2.0.0 dev_dependencies: From d620a97ad784cf746e51db08123f990ba4875cfb Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Sat, 28 May 2022 21:53:31 +0700 Subject: [PATCH 14/49] Add search product and product detail --- .flutter-plugins-dependencies | 2 +- lib/data/provider/product.provider.dart | 2 +- .../product/components/more_products.dart | 6 +- .../product/components/product_card.dart | 92 ++++----- .../product/components/product_display.dart | 82 ++++---- lib/screens/product/product_page.dart | 177 ++++++++---------- lib/screens/product/view_product_page.dart | 36 +--- .../search_products/search_controller.dart | 31 ++- lib/screens/search_products/search_page.dart | 84 +++------ 9 files changed, 213 insertions(+), 299 deletions(-) diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 6c0e99bd..23822fa7 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2022-05-28 15:48:56.328295","version":"2.10.4"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2022-05-28 20:47:18.103651","version":"2.10.4"} \ No newline at end of file diff --git a/lib/data/provider/product.provider.dart b/lib/data/provider/product.provider.dart index d4b209e1..2ecadfc5 100644 --- a/lib/data/provider/product.provider.dart +++ b/lib/data/provider/product.provider.dart @@ -11,7 +11,7 @@ class ProductProvider { ProductProvider(this.networkService); final String getAllProductsUrl = - 'https://ecommerce-api-dut.herokuapp.com/api/category/list'; + 'https://ecommerce-api-dut.herokuapp.com/api/product/list'; final String searchProductUrl = 'https://ecommerce-api-dut.herokuapp.com/api/product/list/search/'; diff --git a/lib/screens/product/components/more_products.dart b/lib/screens/product/components/more_products.dart index 0dc64795..7dc6d7fa 100755 --- a/lib/screens/product/components/more_products.dart +++ b/lib/screens/product/components/more_products.dart @@ -1,4 +1,5 @@ import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/screens/product/product_page.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/product/components/product_card.dart'; import 'package:flutter/material.dart'; @@ -49,7 +50,10 @@ class MoreProducts extends StatelessWidget { : index == 4 ? EdgeInsets.only(right: 24.0, left: 8.0) : EdgeInsets.symmetric(horizontal: 8.0), - child: ProductCard(products[index])); + child: ProductCard(products[index], () => Navigator.of(context).push(MaterialPageRoute( + builder: (_) => ProductPage( + product: products[index], + ))),), ); }, scrollDirection: Axis.horizontal, ), diff --git a/lib/screens/product/components/product_card.dart b/lib/screens/product/components/product_card.dart index 5f77ef3b..22b000fe 100755 --- a/lib/screens/product/components/product_card.dart +++ b/lib/screens/product/components/product_card.dart @@ -3,55 +3,57 @@ import 'package:flutter/material.dart'; class ProductCard extends StatelessWidget { final Product product; + final Function onTap; - ProductCard(this.product); + ProductCard(this.product, this.onTap); @override Widget build(BuildContext context) { - return InkWell( - onTap: null, - child: Container( - height: 250, - width: MediaQuery.of(context).size.width / 2 - 29, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(10)), - color: Color(0xfffbd085).withOpacity(0.46)), - child: Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Align( - alignment: Alignment.topCenter, - child: Container( - padding: EdgeInsets.all(16.0), - width: MediaQuery.of(context).size.width / 2 - 64, - height: MediaQuery.of(context).size.width / 2 - 64, - child: Image.asset( - product.imageUrl!, + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Card( + child: InkWell( + onTap: () => onTap(), + child: Container( + height: 200, + width: MediaQuery.of(context).size.width / 2 - 29, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(10)), + color: Color(0xfffbd085).withOpacity(0.46)), + child: Row( + children: [ + Align( + alignment: Alignment.topCenter, + child: Container( + padding: EdgeInsets.all(16.0), + width: 180, + height: 180, + child: Image.network( + product.imageUrl!, + ), + ), ), - ), - ), - Flexible( - child: Align( - alignment: Alignment(1, 0.5), - child: Container( - margin: const EdgeInsets.only(left: 16.0), - padding: const EdgeInsets.all(8.0), - decoration: BoxDecoration( - color: Color(0xffe0450a).withOpacity(0.51), - borderRadius: BorderRadius.only( - topLeft: Radius.circular(10), - bottomLeft: Radius.circular(10))), - child: Text( - product.name ?? "Product", - textAlign: TextAlign.right, - style: TextStyle( - fontSize: 12.0, - color: Colors.white, - ), - )), - ), - ) - ], - ))); + Flexible( + child: Container( + margin: const EdgeInsets.only(left: 16.0), + padding: const EdgeInsets.all(8.0), + decoration: BoxDecoration( + color: Color(0xffe0450a).withOpacity(0.51), + borderRadius: BorderRadius.only( + topLeft: Radius.circular(10), + bottomLeft: Radius.circular(10))), + child: Text( + product.name ?? "Product", + textAlign: TextAlign.right, + style: TextStyle( + fontSize: 12.0, + color: Colors.white, + ), + )), + ) + ], + ))), + ), + ); } } diff --git a/lib/screens/product/components/product_display.dart b/lib/screens/product/components/product_display.dart index 27020c8d..02d1d91b 100755 --- a/lib/screens/product/components/product_display.dart +++ b/lib/screens/product/components/product_display.dart @@ -1,6 +1,5 @@ import 'package:ecommerce_int2/data/models/product.model.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; -import 'package:ecommerce_int2/screens/rating/rating_page.dart'; import 'package:flutter/material.dart'; class ProductDisplay extends StatelessWidget { @@ -11,11 +10,39 @@ class ProductDisplay extends StatelessWidget { }); @override Widget build(BuildContext context) { - return Stack( + return Column( children: [ - Positioned( - top: 30.0, - right: 0, + Align( + alignment: Alignment(-1, 0), + child: Padding( + padding: const EdgeInsets.only(right: 20.0, left: 20.0), + child: Container( + height: screenAwareSize(220, context), + child: Stack( + children: [ + Padding( + padding: const EdgeInsets.only( + bottom: 18.0, + ), + child: Container( + child: Hero( + tag: product.imageUrl!, + child: Image.network( + product.imageUrl!, + fit: BoxFit.contain, + height: 230, + width: 230, + ), + ), + ), + ) + ], + ), + ), + ), + ), + Align( + alignment: Alignment.centerRight, child: Container( width: MediaQuery.of(context).size.width / 1.5, height: 85, @@ -43,7 +70,7 @@ class ProductDisplay extends StatelessWidget { fontFamily: "Montserrat", fontSize: 36.0)), TextSpan( - text: '.58', + text: 'VND', style: const TextStyle( color: const Color(0xFFFFFFFF), fontWeight: FontWeight.w400, @@ -51,49 +78,6 @@ class ProductDisplay extends StatelessWidget { fontSize: 18.0)) ])), ))), - Align( - alignment: Alignment(-1, 0), - child: Padding( - padding: const EdgeInsets.only(right: 20.0, left: 20.0), - child: Container( - height: screenAwareSize(220, context), - child: Stack( - children: [ - Padding( - padding: const EdgeInsets.only( - bottom: 18.0, - ), - child: Container( - child: Hero( - tag: product.imageUrl!, - child: Image.asset( - product.imageUrl!, - fit: BoxFit.contain, - height: 230, - width: 230, - ), - ), - ), - ) - ], - ), - ), - ), - ), - Positioned( - left: 20.0, - bottom: 0.0, - child: RawMaterialButton( - onPressed: () => Navigator.of(context) - .push(MaterialPageRoute(builder: (_) => RatingPage())), - constraints: const BoxConstraints(minWidth: 45, minHeight: 45), - child: - Icon(Icons.favorite, color: Color.fromRGBO(255, 137, 147, 1)), - elevation: 0.0, - shape: CircleBorder(), - fillColor: Color.fromRGBO(255, 255, 255, 0.4), - ), - ) ], ); } diff --git a/lib/screens/product/product_page.dart b/lib/screens/product/product_page.dart index f531d6bf..fe2dfa3e 100755 --- a/lib/screens/product/product_page.dart +++ b/lib/screens/product/product_page.dart @@ -45,7 +45,7 @@ class _ProductPageState extends State { ], borderRadius: BorderRadius.circular(9.0)), child: Center( - child: Text("View Product", + child: Text('Add to Cart', style: const TextStyle( color: const Color(0xfffefefe), fontWeight: FontWeight.w600, @@ -61,111 +61,92 @@ class _ProductPageState extends State { backgroundColor: Colors.transparent, elevation: 0.0, iconTheme: IconThemeData(color: darkGrey), - actions: [ - IconButton( - icon: new SvgPicture.asset( - 'assets/icons/search_icon.svg', - fit: BoxFit.scaleDown, - ), - onPressed: () => Navigator.of(context) - .push(MaterialPageRoute(builder: (_) => SearchPage())), - ) - ], title: Text( - 'Headphones', + widget.product.name ?? 'Product', style: const TextStyle( color: darkGrey, fontWeight: FontWeight.w500, fontSize: 18.0), ), ), - body: Stack( - children: [ - SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - height: 80.0, - ), - ProductDisplay( - product: product, - ), - SizedBox( - height: 16.0, - ), - Padding( - padding: const EdgeInsets.only(left: 20.0, right: 16.0), - child: Text( - product.name ?? "", + body: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ProductDisplay( + product: product, + ), + SizedBox( + height: 16.0, + ), + Padding( + padding: const EdgeInsets.only(left: 20.0, right: 16.0), + child: Text( + product.name ?? "", + style: const TextStyle( + color: const Color(0xFFFEFEFE), + fontWeight: FontWeight.w600, + fontSize: 20.0), + ), + ), + SizedBox( + height: 24.0, + ), + Padding( + padding: const EdgeInsets.only(left: 20.0), + child: Row( + children: [ + Container( + width: 90, + height: 40, + decoration: BoxDecoration( + color: Color.fromRGBO(253, 192, 84, 1), + borderRadius: BorderRadius.circular(4.0), + border: Border.all(color: Color(0xFFFFFFFF), width: 0.5), + ), + child: Center( + child: new Text("Details", + style: const TextStyle( + color: const Color(0xeefefefe), + fontWeight: FontWeight.w300, + fontStyle: FontStyle.normal, + fontSize: 12.0)), + ), + ) + ], + ), + ), + SizedBox( + height: 16.0, + ), + Padding( + padding: EdgeInsets.only(left: 20.0, right: 40.0, bottom: 20), + child: new Text(product.description ?? "", style: const TextStyle( - color: const Color(0xFFFEFEFE), - fontWeight: FontWeight.w600, - fontSize: 20.0), - ), - ), - SizedBox( - height: 24.0, - ), - Padding( - padding: const EdgeInsets.only(left: 20.0), - child: Row( - children: [ - Container( - width: 90, - height: 40, - decoration: BoxDecoration( - color: Color.fromRGBO(253, 192, 84, 1), - borderRadius: BorderRadius.circular(4.0), - border: - Border.all(color: Color(0xFFFFFFFF), width: 0.5), - ), - child: Center( - child: new Text("Details", - style: const TextStyle( - color: const Color(0xeefefefe), - fontWeight: FontWeight.w300, - fontStyle: FontStyle.normal, - fontSize: 12.0)), - ), - ) + color: const Color(0xfefefefe), + fontWeight: FontWeight.w800, + fontFamily: "NunitoSans", + fontStyle: FontStyle.normal, + fontSize: 16.0))), + Align( + alignment: Alignment.bottomCenter, + child: Container( + padding: EdgeInsets.only( + top: 8.0, bottom: bottomPadding != 20 ? 20 : bottomPadding), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + Color.fromRGBO(255, 255, 255, 0), + Color.fromRGBO(253, 192, 84, 0.5), + Color.fromRGBO(253, 192, 84, 1), ], - ), - ), - SizedBox( - height: 16.0, - ), - Padding( - padding: - EdgeInsets.only(left: 20.0, right: 40.0, bottom: 130), - child: new Text(product.description ?? "", - style: const TextStyle( - color: const Color(0xfefefefe), - fontWeight: FontWeight.w800, - fontFamily: "NunitoSans", - fontStyle: FontStyle.normal, - fontSize: 16.0))) - ], + begin: FractionalOffset.topCenter, + end: FractionalOffset.bottomCenter)), + width: width, + height: 120, + child: Center(child: viewProductButton), + ), ), - ), - Align( - alignment: Alignment.bottomCenter, - child: Container( - padding: EdgeInsets.only( - top: 8.0, bottom: bottomPadding != 20 ? 20 : bottomPadding), - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - Color.fromRGBO(255, 255, 255, 0), - Color.fromRGBO(253, 192, 84, 0.5), - Color.fromRGBO(253, 192, 84, 1), - ], - begin: FractionalOffset.topCenter, - end: FractionalOffset.bottomCenter)), - width: width, - height: 120, - child: Center(child: viewProductButton), - ), - ), - ], + ], + ), ), ); } diff --git a/lib/screens/product/view_product_page.dart b/lib/screens/product/view_product_page.dart index 154ae3cb..813949a1 100755 --- a/lib/screens/product/view_product_page.dart +++ b/lib/screens/product/view_product_page.dart @@ -7,7 +7,6 @@ import '../../data/models/product.model.dart'; import '../../utils/app_properties.dart'; import 'components/color_list.dart'; import 'components/more_products.dart'; -import 'components/product_options.dart'; class ViewProductPage extends StatefulWidget { final Product product; @@ -85,7 +84,7 @@ class _ViewProductPageState extends State { ) ], title: Text( - 'Headphones', + widget.product.name ?? 'Product', style: const TextStyle( color: darkGrey, fontWeight: FontWeight.w500, @@ -103,39 +102,6 @@ class _ViewProductPageState extends State { // product: widget.product, // ), description, - Padding( - padding: const EdgeInsets.all(24.0), - child: Row(mainAxisSize: MainAxisSize.min, children: [ - Flexible( - child: ColorList([ - Colors.red, - Colors.blue, - Colors.purple, - Colors.green, - Colors.yellow - ]), - ), - RawMaterialButton( - onPressed: () { - showModalBottomSheet( - context: context, - builder: (context) { - return RatingBottomSheet(); - }, - //elevation: 0, - //backgroundColor: Colors.transparent - ); - }, - constraints: - const BoxConstraints(minWidth: 45, minHeight: 45), - child: Icon(Icons.favorite, - color: Color.fromRGBO(255, 137, 147, 1)), - elevation: 0.0, - shape: CircleBorder(), - fillColor: Color.fromRGBO(255, 255, 255, 0.4), - ), - ]), - ), MoreProducts() ], ), diff --git a/lib/screens/search_products/search_controller.dart b/lib/screens/search_products/search_controller.dart index 81c11e63..1dad5d3d 100644 --- a/lib/screens/search_products/search_controller.dart +++ b/lib/screens/search_products/search_controller.dart @@ -13,11 +13,20 @@ class SearchProductController extends GetxController { TextEditingController searchController = TextEditingController(); -RefreshController refreshController = + RefreshController refreshController = RefreshController(initialRefresh: false); int currentPage = 1; - ProductFilter filter = ProductFilter(sortOrder: SortOrder(iId: -1)); + int total = 0; + + ProductFilter filter = ProductFilter( + sortOrder: SortOrder(iId: -1), + pageNumber: 1, + rating: 0, + min: 1, + max: 500000, + subcategory: '', + order: 0); final Debounce debounce = Debounce(milliseconds: 2000); @@ -25,27 +34,31 @@ RefreshController refreshController = @override void onInit() { + getProduct(); super.onInit(); } - void getProduct() async { + Future getProduct() async { final res = await repository.getProducts(filter); + total = res.totalProducts ?? 0; list.addAll(res.products!); - refreshController.loadComplete(); update(); } - void onRefresh() { + void onRefresh() async { list.clear(); currentPage = 1; filter.pageNumber = 1; - getProduct(); + await getProduct(); + refreshController.refreshCompleted(); } - void onLoadMore() { - ++ currentPage; + void onLoadMore() async { + if(list.length == total) return; + ++currentPage; filter.pageNumber = currentPage; - getProduct(); + await getProduct(); + refreshController.loadComplete(); } void onChanged(String value) { diff --git a/lib/screens/search_products/search_page.dart b/lib/screens/search_products/search_page.dart index 18734294..818684a9 100644 --- a/lib/screens/search_products/search_page.dart +++ b/lib/screens/search_products/search_page.dart @@ -1,5 +1,7 @@ import 'package:ecommerce_int2/data/models/product.model.dart'; import 'package:ecommerce_int2/data/repository/product.repository.dart'; +import 'package:ecommerce_int2/screens/product/components/product_card.dart'; +import 'package:ecommerce_int2/screens/product/product_page.dart'; import 'package:ecommerce_int2/screens/search_products/search_controller.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/product/view_product_page.dart'; @@ -20,24 +22,6 @@ class _SearchPageState extends State String selectedCategory = ""; String selectedPrice = ""; - List products = [ - // Product( - // 'assets/headphones_2.png', - // 'Skullcandy headset L325', - // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - // 102.99), - // Product( - // 'assets/headphones_3.png', - // 'Skullcandy headset X25', - // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - // 55.99), - // Product( - // 'assets/headphones.png', - // 'Blackzy PRO hedphones M003', - // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - // 152.99), - ]; - List timeFilter = [ 'Brand', 'New', @@ -116,26 +100,7 @@ class _SearchPageState extends State Border(bottom: BorderSide(color: Colors.orange, width: 1))), child: TextField( controller: searchController, - onChanged: (value) { - if (value.isNotEmpty) { - List tempList = []; - products.forEach((product) { - if (product.name!.toLowerCase().contains(value)) { - tempList.add(product); - } - }); - setState(() { - searchResults.clear(); - searchResults.addAll(tempList); - }); - return; - } else { - setState(() { - searchResults.clear(); - searchResults.addAll(products); - }); - } - }, + onChanged: (value) => controller.onChanged(value), cursorColor: darkGrey, decoration: InputDecoration( contentPadding: EdgeInsets.zero, @@ -158,30 +123,29 @@ class _SearchPageState extends State ), ), Flexible( - child: Container( - color: Colors.orange[50], - child: SmartRefresher( - enablePullDown: true, - enablePullUp: true, - controller: controller.refreshController, - onLoading: controller.onLoadMore, - onRefresh: controller.onRefresh, - header: WaterDropHeader(), - child: ListView.builder( - itemCount: controller.list.length, - itemBuilder: (_, index) => Padding( - padding: EdgeInsets.symmetric(horizontal: 16.0), - child: ListTile( - onTap: () => - Navigator.of(context).push(MaterialPageRoute( - builder: (_) => ViewProductPage( - product: controller.list[index], - ))), - title: Text(controller.list[index].name ?? ''), - ))), + child: Container( + color: Colors.orange[50], + child: SmartRefresher( + enablePullDown: true, + enablePullUp: true, + controller: controller.refreshController, + onLoading: controller.onLoadMore, + onRefresh: controller.onRefresh, + header: WaterDropHeader(), + child: ListView.builder( + itemCount: controller.list.length, + itemBuilder: (_, index) => Padding( + padding: EdgeInsets.symmetric(horizontal: 16.0), + child: ProductCard( + controller.list[index], + () => Navigator.of(context).push(MaterialPageRoute( + builder: (_) => ProductPage( + product: controller.list[index], + ))), + )), ), ), - ) + )) ], ), ); From ae9bb9564439d511181ded7c9dc621aef69b824e Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Sat, 28 May 2022 23:01:42 +0700 Subject: [PATCH 15/49] Refactor home view --- lib/data/models/product.model.dart | 2 + lib/screens/address/add_address_page.dart | 2 +- .../address}/address.controller.dart | 0 lib/screens/main/main_page.dart | 130 ++++-------------- 4 files changed, 33 insertions(+), 101 deletions(-) rename lib/{services => screens/address}/address.controller.dart (100%) diff --git a/lib/data/models/product.model.dart b/lib/data/models/product.model.dart index 5f26cbf9..94e3a5cd 100644 --- a/lib/data/models/product.model.dart +++ b/lib/data/models/product.model.dart @@ -4,6 +4,8 @@ class ProductList { int? pages; int? totalProducts; + List get random => [products!.first, products!.last, products![1]]; + ProductList({this.products, this.page, this.pages, this.totalProducts}); ProductList.fromJson(Map json) { diff --git a/lib/screens/address/add_address_page.dart b/lib/screens/address/add_address_page.dart index 55a2d842..a1e918a2 100755 --- a/lib/screens/address/add_address_page.dart +++ b/lib/screens/address/add_address_page.dart @@ -2,7 +2,7 @@ import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/data/repository/address.repository.dart'; import 'package:ecommerce_int2/screens/address/address_form.dart'; import 'package:ecommerce_int2/screens/select_card_page.dart'; -import 'package:ecommerce_int2/services/address.controller.dart'; +import 'package:ecommerce_int2/screens/address/address.controller.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; diff --git a/lib/services/address.controller.dart b/lib/screens/address/address.controller.dart similarity index 100% rename from lib/services/address.controller.dart rename to lib/screens/address/address.controller.dart diff --git a/lib/screens/main/main_page.dart b/lib/screens/main/main_page.dart index 544e4c71..21995296 100755 --- a/lib/screens/main/main_page.dart +++ b/lib/screens/main/main_page.dart @@ -71,104 +71,37 @@ class _MainPageState extends State Widget topHeader = Padding( padding: const EdgeInsets.only(left: 16.0, right: 16.0, bottom: 4.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - Flexible( - child: InkWell( - onTap: () { - setState(() { - selectedTimeline = timelines[0]; - products = [ - // Product( - // 'assets/headphones_2.png', - // 'Skullcandy headset L325', - // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - // 102.99), - // Product( - // 'assets/headphones_3.png', - // 'Skullcandy headset X25', - // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - // 55.99), - // Product( - // 'assets/headphones.png', - // 'Blackzy PRO hedphones M003', - // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - // 152.99), - ]; - }); - }, - child: Text( - timelines[0], - style: TextStyle( - fontSize: timelines[0] == selectedTimeline ? 20 : 14, - color: darkGrey), - ), - ), - ), - Flexible( - child: InkWell( - onTap: () { - setState(() { - selectedTimeline = timelines[1]; - products = [ - // Product( - // 'assets/bag_5.png', - // 'Skullcandy headset L325', - // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - // 102.99), - // Product( - // 'assets/bag_6.png', - // 'Skullcandy headset X25', - // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - // 55.99), - // Product( - // 'assets/bag_3.png', - // 'Blackzy PRO hedphones M003', - // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - // 152.99), - ]; - }); - }, - child: Text(timelines[1], - textAlign: TextAlign.center, - style: TextStyle( - fontSize: timelines[1] == selectedTimeline ? 20 : 14, - color: darkGrey)), - ), + child: Flexible( + child: InkWell( + onTap: () { + setState(() { + selectedTimeline = timelines[0]; + products = [ + // Product( + // 'assets/headphones_2.png', + // 'Skullcandy headset L325', + // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', + // 102.99), + // Product( + // 'assets/headphones_3.png', + // 'Skullcandy headset X25', + // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', + // 55.99), + // Product( + // 'assets/headphones.png', + // 'Blackzy PRO hedphones M003', + // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', + // 152.99), + ]; + }); + }, + child: Text( + timelines[0], + style: TextStyle( + fontSize: timelines[0] == selectedTimeline ? 20 : 14, + color: darkGrey), ), - Flexible( - child: InkWell( - onTap: () { - setState(() { - selectedTimeline = timelines[2]; - products = [ - // Product( - // 'assets/headphone_13.png', - // 'Skullcandy headset L325', - // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - // 102.99), - // Product( - // 'assets/jeans_4.png', - // 'Skullcandy headset X25', - // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - // 55.99), - // Product( - // 'assets/ring_7.png', - // 'Blackzy PRO hedphones M003', - // 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ut labore et dolore magna aliqua. Nec nam aliquam sem et tortor consequat id porta nibh. Orci porta non pulvinar neque laoreet suspendisse. Id nibh tortor id aliquet. Dui sapien eget mi proin. Viverra vitae congue eu consequat ac felis donec. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Vulputate mi sit amet mauris commodo quis imperdiet. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Sit amet cursus sit amet dictum sit amet justo. Mattis pellentesque id nibh tortor. Sed blandit libero volutpat sed cras ornare arcu dui. Fermentum et sollicitudin ac orci phasellus. Ipsum nunc aliquet bibendum enim facilisis gravida. Viverra suspendisse potenti nullam ac tortor. Dapibus ultrices in iaculis nunc sed. Nisi porta lorem mollis aliquam ut porttitor leo a. Phasellus egestas tellus rutrum tellus pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Eros in cursus turpis massa. Eget mauris pharetra et ultrices neque.', - // 152.99), - ]; - }); - }, - child: Text(timelines[2], - textAlign: TextAlign.right, - style: TextStyle( - fontSize: timelines[2] == selectedTimeline ? 20 : 14, - color: darkGrey)), - ), - ), - ], + ), )); Widget tabBar = TabBar( @@ -203,9 +136,6 @@ class _MainPageState extends State (BuildContext context, bool innerBoxIsScrolled) { // These are the slivers that show up in the "outer" scroll view. return [ - SliverToBoxAdapter( - child: appBar, - ), SliverToBoxAdapter( child: topHeader, ), From 048f4396aa03865e6e8dba4c23f3e9cce1986686 Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Sat, 28 May 2022 23:15:48 +0700 Subject: [PATCH 16/49] Update profile screen --- lib/screens/profile_page.dart | 62 +++++++++++++++++------------------ 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/lib/screens/profile_page.dart b/lib/screens/profile_page.dart index 703de6cf..3dd96602 100755 --- a/lib/screens/profile_page.dart +++ b/lib/screens/profile_page.dart @@ -54,21 +54,21 @@ class ProfilePage extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - IconButton( - icon: Image.asset('assets/icons/wallet.png'), - onPressed:()=> Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => WalletPage())), - ), - Text( - 'Wallet', - style: TextStyle(fontWeight: FontWeight.bold), - ) - ], - ), + // Column( + // mainAxisAlignment: MainAxisAlignment.center, + // children: [ + // IconButton( + // icon: Image.asset('assets/icons/wallet.png'), + // onPressed:()=> Navigator.of(context).push( + // MaterialPageRoute( + // builder: (_) => WalletPage())), + // ), + // Text( + // 'Wallet', + // style: TextStyle(fontWeight: FontWeight.bold), + // ) + // ], + // ), Column( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -78,26 +78,26 @@ class ProfilePage extends StatelessWidget { MaterialPageRoute(builder: (_) => TrackingPage())), ), Text( - 'Shipped', - style: TextStyle(fontWeight: FontWeight.bold), - ) - ], - ), - Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - IconButton( - icon: Image.asset('assets/icons/card.png'), - onPressed:()=> Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => PaymentPage())), - ), - Text( - 'Payment', + 'Orders', style: TextStyle(fontWeight: FontWeight.bold), ) ], ), + // Column( + // mainAxisAlignment: MainAxisAlignment.center, + // children: [ + // IconButton( + // icon: Image.asset('assets/icons/card.png'), + // onPressed:()=> Navigator.of(context).push( + // MaterialPageRoute( + // builder: (_) => PaymentPage())), + // ), + // Text( + // 'Payment', + // style: TextStyle(fontWeight: FontWeight.bold), + // ) + // ], + // ), Column( mainAxisAlignment: MainAxisAlignment.center, children: [ From 1a5051ad1cd9cc24b29096f09e06f008093bd575 Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Sat, 28 May 2022 23:16:57 +0700 Subject: [PATCH 17/49] Update splash screen --- lib/screens/splash_page.dart | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/lib/screens/splash_page.dart b/lib/screens/splash_page.dart index 04f906db..dde8322b 100755 --- a/lib/screens/splash_page.dart +++ b/lib/screens/splash_page.dart @@ -53,19 +53,6 @@ class _SplashScreenState extends State opacity: opacity.value, child: new Image.asset('assets/logo.png')), ), - Padding( - padding: const EdgeInsets.all(8.0), - child: RichText( - text: TextSpan( - style: TextStyle(color: Colors.black), - children: [ - TextSpan(text: 'Powered by '), - TextSpan( - text: 'int2.io', - style: TextStyle(fontWeight: FontWeight.bold)) - ]), - ), - ) ], ), ), From 2ba883f472feb9b35420b7c968e7bf74ceb67ce2 Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Sun, 29 May 2022 00:00:07 +0700 Subject: [PATCH 18/49] Add provider and repository for cart --- lib/data/models/product.model.dart | 138 +++++++++++++++++++++++ lib/data/provider/cart.provider.dart | 40 +++++++ lib/data/repository/cart.repository.dart | 42 +++++++ lib/screens/shop/cart.controller.dart | 3 + 4 files changed, 223 insertions(+) create mode 100644 lib/data/provider/cart.provider.dart create mode 100644 lib/data/repository/cart.repository.dart create mode 100644 lib/screens/shop/cart.controller.dart diff --git a/lib/data/models/product.model.dart b/lib/data/models/product.model.dart index 94e3a5cd..bda712e9 100644 --- a/lib/data/models/product.model.dart +++ b/lib/data/models/product.model.dart @@ -173,3 +173,141 @@ class SortOrder { return data; } } + +class AddProductParam { + List? products; + + AddProductParam({this.products}); + + AddProductParam.fromJson(Map json) { + if (json['products'] != null) { + products = []; + json['products'].forEach((v) { + products!.add(new ProductParam.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + if (this.products != null) { + data['products'] = this.products!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class ProductParam { + String? product; + int? quantity; + int? price; + String? merchant; + + ProductParam({this.product, this.quantity, this.price, this.merchant}); + + ProductParam.fromJson(Map json) { + product = json['product']; + quantity = json['quantity']; + price = json['price']; + merchant = json['merchant']; + } + + Map toJson() { + final Map data = new Map(); + data['product'] = this.product; + data['quantity'] = this.quantity; + data['price'] = this.price; + data['merchant'] = this.merchant; + return data; + } +} + +class Cart { + int? total; + String? sId; + List? products; + String? user; + String? merchant; + String? created; + int? iV; + bool? isOrdered; + + Cart( + {this.total, + this.sId, + this.products, + this.user, + this.merchant, + this.created, + this.iV, + this.isOrdered}); + + Cart.fromJson(Map json) { + total = json['total']; + sId = json['_id']; + if (json['products'] != null) { + products = []; + json['products'].forEach((v) { + products!.add(new ProductResponse.fromJson(v)); + }); + } + user = json['user']; + merchant = json['merchant']; + created = json['created']; + iV = json['__v']; + isOrdered = json['isOrdered']; + } + + Map toJson() { + final Map data = new Map(); + data['total'] = this.total; + data['_id'] = this.sId; + if (this.products != null) { + data['products'] = this.products!.map((v) => v.toJson()).toList(); + } + data['user'] = this.user; + data['merchant'] = this.merchant; + data['created'] = this.created; + data['__v'] = this.iV; + data['isOrdered'] = this.isOrdered; + return data; + } +} + +class ProductResponse { + String? product; + int? quantity; + int? purchasePrice; + int? totalPrice; + String? merchant; + String? sId; + + ProductResponse( + {this.product, + this.quantity, + this.purchasePrice, + this.totalPrice, + this.merchant, + this.sId}); + + ProductResponse.fromJson(Map json) { + product = json['product']; + quantity = json['quantity']; + purchasePrice = json['purchasePrice']; + totalPrice = json['totalPrice']; + merchant = json['merchant']; + sId = json['_id']; + } + + Map toJson() { + final Map data = new Map(); + data['product'] = this.product; + data['quantity'] = this.quantity; + data['purchasePrice'] = this.purchasePrice; + data['totalPrice'] = this.totalPrice; + data['merchant'] = this.merchant; + data['_id'] = this.sId; + return data; + } +} + diff --git a/lib/data/provider/cart.provider.dart b/lib/data/provider/cart.provider.dart new file mode 100644 index 00000000..b363f243 --- /dev/null +++ b/lib/data/provider/cart.provider.dart @@ -0,0 +1,40 @@ +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/services/network.service.dart'; +import 'package:get_storage/get_storage.dart'; + +class CartProvider { + final NetWorkService networkService; + + final GetStorage storage = GetStorage(); + + CartProvider(this.networkService); + + final String getAllCartUrl = + 'https://ecommerce-api-dut.herokuapp.com/api/cart'; + + final String addProductToCartUrl = + 'https://ecommerce-api-dut.herokuapp.com/api/cart/add'; + + final String modifyProductToCartUrl = + 'https://ecommerce-api-dut.herokuapp.com/api/cart/modify'; + + final String deleteProductFromCartUrl = + 'https://ecommerce-api-dut.herokuapp.com/api/cart/modify'; + + Future getCarts() { + return networkService.get(getAllCartUrl); + } + + Future addProduct(AddProductParam param) { + return networkService.post(addProductToCartUrl, data: param.toJson()); + } + + Future modifyProduct(String productId, int before, int after) { + return networkService.put('$addProductToCartUrl/$productId', + data: {"previousQuantity": before, "currentQuantity": after}); + } + + Future deleteProduct(String productId) { + return networkService.delete('$deleteProductFromCartUrl/$productId'); + } +} diff --git a/lib/data/repository/cart.repository.dart b/lib/data/repository/cart.repository.dart new file mode 100644 index 00000000..58fbcf83 --- /dev/null +++ b/lib/data/repository/cart.repository.dart @@ -0,0 +1,42 @@ +import 'package:ecommerce_int2/data/models/address.model.dart'; +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/data/provider/address.provider.dart'; +import 'package:ecommerce_int2/data/provider/cart.provider.dart'; + +class CartRepository { + final CartProvider provider; + + CartRepository(this.provider); + + Future> getCarts() async { + final response = await provider.getCarts(); + if (response.statusCode != 200) { + throw Exception("Get cart failed"); + } + final result = (response.body['addresses'] as List) + .map((i) => Address.fromJson(i)) + .toList(); + return result; + } + + Future addProduct(AddProductParam param) async { + final response = await provider.addProduct(param); + if (response.statusCode != 200) { + throw Exception("Add product failed"); + } + } + + Future deleteProduct(String productID) async { + final response = await provider.deleteProduct(productID); + if (response.statusCode != 200) { + throw Exception("Delete product failed"); + } + } + + Future modifyProduct(String productId, int before, int after) async { + final response = await provider.modifyProduct(productId, before, after); + if (response.statusCode != 200) { + throw Exception("Update product failed"); + } + } +} diff --git a/lib/screens/shop/cart.controller.dart b/lib/screens/shop/cart.controller.dart new file mode 100644 index 00000000..7d64a1b5 --- /dev/null +++ b/lib/screens/shop/cart.controller.dart @@ -0,0 +1,3 @@ +class CartController{ + +} \ No newline at end of file From 686cb807b558208237f455eabd90b8391748f9d7 Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Sun, 29 May 2022 00:40:22 +0700 Subject: [PATCH 19/49] Update cart flow --- lib/screens/address/add_address_page.dart | 4 +- lib/screens/address/address_form.dart | 4 +- lib/screens/main/components/tab_view.dart | 38 ++-- lib/screens/shop/cart.controller.dart | 47 +++- lib/screens/shop/check_out_page.dart | 200 +++++++++--------- lib/screens/shop/components/credit_card.dart | 42 +--- .../shop/components/shop_item_list.dart | 2 +- lib/utils/dependencies.dart | 4 + 8 files changed, 176 insertions(+), 165 deletions(-) diff --git a/lib/screens/address/add_address_page.dart b/lib/screens/address/add_address_page.dart index a1e918a2..ea55b446 100755 --- a/lib/screens/address/add_address_page.dart +++ b/lib/screens/address/add_address_page.dart @@ -72,7 +72,6 @@ class AddAddressPage extends StatelessWidget { ? 20 : MediaQuery.of(context).padding.bottom), child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisSize: MainAxisSize.min, children: [ Container( @@ -123,10 +122,13 @@ class AddAddressPage extends StatelessWidget { ); }), ), + const SizedBox(height: 16), AddAddressForm( address: controller.selectedAddress, addr: address, city: city), + const SizedBox(height: 16), + Center(child: buildFinishButton(controller)) ], ), diff --git a/lib/screens/address/address_form.dart b/lib/screens/address/address_form.dart index 4bce64f0..08e8d811 100755 --- a/lib/screens/address/address_form.dart +++ b/lib/screens/address/address_form.dart @@ -15,8 +15,7 @@ class AddAddressForm extends StatelessWidget { : super(key: key); @override Widget build(BuildContext context) { - return SizedBox( - height: 500, + return Flexible( child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, crossAxisAlignment: CrossAxisAlignment.start, @@ -33,6 +32,7 @@ class AddAddressForm extends StatelessWidget { border: InputBorder.none, hintText: address.address), ), ), + const SizedBox(height: 16,), Container( padding: EdgeInsets.only(left: 16.0, top: 4.0, bottom: 4.0), decoration: BoxDecoration( diff --git a/lib/screens/main/components/tab_view.dart b/lib/screens/main/components/tab_view.dart index c9a2446e..8b5694c9 100755 --- a/lib/screens/main/components/tab_view.dart +++ b/lib/screens/main/components/tab_view.dart @@ -56,26 +56,24 @@ class TabView extends StatelessWidget { physics: NeverScrollableScrollPhysics(), controller: tabController, children: [ - Container( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - margin: EdgeInsets.all(8.0), - height: MediaQuery.of(context).size.height / 9, - width: MediaQuery.of(context).size.width, - child: ListView.builder( - scrollDirection: Axis.horizontal, - itemCount: categories.length, - itemBuilder: (_, index) => CategoryCard( - category: categories[index], - ))), - SizedBox( - height: 16.0, - ), - Flexible(child: RecommendedList()), - ], - ), + Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + margin: EdgeInsets.all(8.0), + height: MediaQuery.of(context).size.height / 9, + width: MediaQuery.of(context).size.width, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: categories.length, + itemBuilder: (_, index) => CategoryCard( + category: categories[index], + ))), + SizedBox( + height: 16.0, + ), + Flexible(child: RecommendedList()), + ], ), Column(children: [ SizedBox( diff --git a/lib/screens/shop/cart.controller.dart b/lib/screens/shop/cart.controller.dart index 7d64a1b5..ed79eec4 100644 --- a/lib/screens/shop/cart.controller.dart +++ b/lib/screens/shop/cart.controller.dart @@ -1,3 +1,44 @@ -class CartController{ - -} \ No newline at end of file +import 'package:card_swiper/card_swiper.dart'; +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/data/repository/cart.repository.dart'; +import 'package:get/get.dart'; + +class CartController extends GetxController { + final CartRepository repository; + + final SwiperController swiperController = SwiperController(); + + CartController(this.repository); + + List products = [ + Product( + imageUrl: 'assets/headphones.png', + name: 'Boat roackerz 400 On-Ear Bluetooth Headphones', + description: 'description', + price: 45000), + Product( + imageUrl: 'assets/headphones_2.png', + name: 'Boat roackerz 100 On-Ear Bluetooth Headphones', + description: 'description', + price: 22000), + Product( + imageUrl: 'assets/headphones_3.png', + name: 'Boat roackerz 300 On-Ear Bluetooth Headphones', + description: 'description', + price: 58000) + ]; + + String get total { + int result = 0; + products.forEach((element) { + result += element.price!; + }); + return '$result VND'; + } + + void remove(Product product) { + repository.deleteProduct(product.sId!); + products.remove(product); + update(); + } +} diff --git a/lib/screens/shop/check_out_page.dart b/lib/screens/shop/check_out_page.dart index 4896b16e..fa75f668 100755 --- a/lib/screens/shop/check_out_page.dart +++ b/lib/screens/shop/check_out_page.dart @@ -1,39 +1,17 @@ import 'package:card_swiper/card_swiper.dart'; import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/data/repository/cart.repository.dart'; +import 'package:ecommerce_int2/screens/shop/cart.controller.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/address/add_address_page.dart'; import 'package:ecommerce_int2/screens/payment/unpaid_page.dart'; import 'package:flutter/material.dart'; +import 'package:get/get.dart'; import 'components/credit_card.dart'; import 'components/shop_item_list.dart'; -class CheckOutPage extends StatefulWidget { - @override - _CheckOutPageState createState() => _CheckOutPageState(); -} - -class _CheckOutPageState extends State { - SwiperController swiperController = SwiperController(); - - List products = [ - Product( - imageUrl: 'assets/headphones.png', - name: 'Boat roackerz 400 On-Ear Bluetooth Headphones', - description: 'description', - price: 45000), - Product( - imageUrl: 'assets/headphones_2.png', - name: 'Boat roackerz 100 On-Ear Bluetooth Headphones', - description: 'description', - price: 22000), - Product( - imageUrl: 'assets/headphones_3.png', - name: 'Boat roackerz 300 On-Ear Bluetooth Headphones', - description: 'description', - price: 58000) - ]; - +class CheckOutPage extends StatelessWidget { @override Widget build(BuildContext context) { Widget checkOutButton = InkWell( @@ -69,13 +47,6 @@ class _CheckOutPageState extends State { backgroundColor: Colors.transparent, elevation: 0.0, iconTheme: IconThemeData(color: darkGrey), - actions: [ - IconButton( - icon: Image.asset('assets/icons/denied_wallet.png'), - onPressed: () => Navigator.of(context) - .push(MaterialPageRoute(builder: (_) => UnpaidPage())), - ) - ], title: Text( 'Checkout', style: TextStyle( @@ -87,83 +58,102 @@ class _CheckOutPageState extends State { physics: ClampingScrollPhysics(), child: ConstrainedBox( constraints: BoxConstraints(minHeight: constraints.maxHeight), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - padding: EdgeInsets.symmetric(horizontal: 32.0), - height: 48.0, - color: yellow, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Subtotal', - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 16), - ), - Text( - products.length.toString() + ' items', - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 16), - ) - ], + child: GetBuilder( + init: CartController(Get.find()), + builder: (controller) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: EdgeInsets.symmetric(horizontal: 32.0), + height: 48.0, + color: yellow, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Subtotal', + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 16), + ), + Text( + controller.products.length.toString() + ' items', + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 16), + ) + ], + ), ), - ), - SizedBox( - height: 300, - child: Scrollbar( - child: ListView.builder( - itemBuilder: (_, index) => ShopItemList( - products[index], - onRemove: () { - setState(() { - products.remove(products[index]); - }); - }, - ), - itemCount: products.length, + ...controller.products.map( + (product) => ShopItemList( + product, + onRemove: () => controller.remove(product), ), ), - ), - Padding( - padding: const EdgeInsets.all(16.0), - child: Text( - 'Payment', - style: TextStyle( - fontSize: 20, - color: darkGrey, - fontWeight: FontWeight.bold), + Container( + padding: EdgeInsets.symmetric(horizontal: 32.0), + height: 48.0, + color: yellow, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Total', + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 16), + ), + Text( + controller.total, + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 16), + ) + ], + ), ), - ), - SizedBox( - height: 250, - child: Swiper( - itemCount: 2, - itemBuilder: (_, index) { - return CreditCard(); - }, - scale: 0.8, - controller: swiperController, - viewportFraction: 0.6, - loop: false, - fade: 0.7, + Padding( + padding: const EdgeInsets.all(16.0), + child: Text( + 'Payment', + style: TextStyle( + fontSize: 20, + color: darkGrey, + fontWeight: FontWeight.bold), + ), + ), + SizedBox( + height: 50, + child: Swiper( + itemCount: 2, + itemBuilder: (_, index) { + return CreditCard( + text: index == 0 ? 'CASH \$\$\$' : 'PAYPAL', + ); + }, + scale: 0.8, + controller: controller.swiperController, + viewportFraction: 0.6, + loop: false, + fade: 0.7, + ), ), - ), - SizedBox(height: 24), - Center( - child: Padding( - padding: EdgeInsets.only( - bottom: MediaQuery.of(context).padding.bottom == 0 - ? 20 - : MediaQuery.of(context).padding.bottom), - child: checkOutButton, - )) - ], + SizedBox(height: 24), + Center( + child: Padding( + padding: EdgeInsets.only( + bottom: MediaQuery.of(context).padding.bottom == 0 + ? 20 + : MediaQuery.of(context).padding.bottom), + child: checkOutButton, + )) + ], + ), ), ), ), diff --git a/lib/screens/shop/components/credit_card.dart b/lib/screens/shop/components/credit_card.dart index 0ac1e6cd..47ca4ec2 100755 --- a/lib/screens/shop/components/credit_card.dart +++ b/lib/screens/shop/components/credit_card.dart @@ -1,47 +1,23 @@ import 'package:flutter/material.dart'; class CreditCard extends StatelessWidget { + final String text; + + const CreditCard({Key? key,required this.text}) : super(key: key); @override Widget build(BuildContext context) { return Container( - height: 200, + height: 50, width: 250, padding: EdgeInsets.all(16.0), decoration: BoxDecoration( color: Colors.deepPurple[700], borderRadius: BorderRadius.all(Radius.circular(10))), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - Text( - 'CREDIT CARD', - style: TextStyle(color: Colors.white), - ), - Container( - height: 25, - width: 40, - color: Colors.white, - ), - Text( - 'xxxx - xxxx - xxxx - 4951', - style: TextStyle(color: Colors.white), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Name', - style: TextStyle(color: Colors.grey), - ), - Text( - 'GEORGE W BUSH', - style: TextStyle(color: Colors.white), - ), - ], - ) - ], + child: Center( + child: Text( + text, + style: TextStyle(color: Colors.white), + ), ), ); } diff --git a/lib/screens/shop/components/shop_item_list.dart b/lib/screens/shop/components/shop_item_list.dart index cfc82679..f4a61a9a 100755 --- a/lib/screens/shop/components/shop_item_list.dart +++ b/lib/screens/shop/components/shop_item_list.dart @@ -21,7 +21,7 @@ class _ShopItemListState extends State { @override Widget build(BuildContext context) { return Container( - margin: EdgeInsets.only(top: 20), + margin: EdgeInsets.symmetric(vertical: 10), height: 130, child: Stack( children: [ diff --git a/lib/utils/dependencies.dart b/lib/utils/dependencies.dart index acb3f273..0c136478 100644 --- a/lib/utils/dependencies.dart +++ b/lib/utils/dependencies.dart @@ -1,9 +1,11 @@ import 'package:ecommerce_int2/data/provider/address.provider.dart'; import 'package:ecommerce_int2/data/provider/auth.provider.dart'; +import 'package:ecommerce_int2/data/provider/cart.provider.dart'; import 'package:ecommerce_int2/data/provider/category.provider.dart'; import 'package:ecommerce_int2/data/provider/product.provider.dart'; import 'package:ecommerce_int2/data/repository/address.repository.dart'; import 'package:ecommerce_int2/data/repository/auth.repository.dart'; +import 'package:ecommerce_int2/data/repository/cart.repository.dart'; import 'package:ecommerce_int2/data/repository/category.repository.dart'; import 'package:ecommerce_int2/data/repository/product.repository.dart'; import 'package:ecommerce_int2/services/auth.service.dart'; @@ -23,6 +25,8 @@ class Dependency { ..put(CategoryRepository(Get.find())) ..put(ProductProvider(Get.find())) ..put(ProductRepository(Get.find())) + ..put(CartProvider(Get.find())) + ..put(CartRepository(Get.find())) ; } } From d648256b94c3a3f1762193d3f473f5b9d370a7ec Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Sun, 29 May 2022 09:12:41 +0700 Subject: [PATCH 20/49] Add product to cart, add loading --- .flutter-plugins-dependencies | 2 +- lib/data/models/category.model.dart | 33 +++---- lib/data/models/login.result.dart | 4 +- lib/data/models/login.result.g.dart | 4 +- lib/interceptor/dio_interceptor.dart | 2 +- lib/screens/category/category.controller.dart | 27 ++++-- lib/screens/category/category_list_page.dart | 4 +- .../category/sub_category_list_page.dart | 27 +++--- .../product/components/shop_product.dart | 2 +- lib/screens/product/product_page.dart | 23 ++--- lib/screens/search_products/search_page.dart | 2 +- lib/screens/shop/cart.controller.dart | 24 ++--- lib/services/auth.service.dart | 11 ++- lib/utils/dependencies.dart | 2 + lib/utils/message_dialog.dart | 90 +++++++++++++++++++ 15 files changed, 177 insertions(+), 80 deletions(-) create mode 100644 lib/utils/message_dialog.dart diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 23822fa7..3b28c1ce 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2022-05-28 20:47:18.103651","version":"2.10.4"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2022-05-29 08:23:17.010544","version":"2.10.4"} \ No newline at end of file diff --git a/lib/data/models/category.model.dart b/lib/data/models/category.model.dart index 7b1037e9..3b1816f6 100644 --- a/lib/data/models/category.model.dart +++ b/lib/data/models/category.model.dart @@ -1,36 +1,38 @@ class CategoryList { - List? categories; + List? data; - CategoryList({this.categories}); + CategoryList({this.data}); CategoryList.fromJson(Map json) { - if (json['categories'] != null) { - categories = []; - json['categories'].forEach((v) { - categories!.add(new Category.fromJson(v)); + if (json['data'] != null) { + data = []; + json['data'].forEach((v) { + data!.add(new Category.fromJson(v)); }); } } Map toJson() { final Map data = new Map(); - if (this.categories != null) { - data['categories'] = this.categories!.map((v) => v.toJson()).toList(); + if (this.data != null) { + data['data'] = this.data!.map((v) => v.toJson()).toList(); } return data; } } class Category { - String? categoryId; - String? categoryName; + String? id; + String? name; + String? description; List? subcategories; - Category({this.categoryId, this.categoryName, this.subcategories}); + Category({this.id, this.name, this.description, this.subcategories}); Category.fromJson(Map json) { - categoryId = json['category_id']; - categoryName = json['category_name']; + id = json['_id']; + name = json['name']; + description = json['description']; if (json['subcategories'] != null) { subcategories = []; json['subcategories'].forEach((v) { @@ -41,8 +43,9 @@ class Category { Map toJson() { final Map data = new Map(); - data['category_id'] = this.categoryId; - data['category_name'] = this.categoryName; + data['_id'] = this.id; + data['name'] = this.name; + data['description'] = this.description; if (this.subcategories != null) { data['subcategories'] = this.subcategories!.map((v) => v.toJson()).toList(); diff --git a/lib/data/models/login.result.dart b/lib/data/models/login.result.dart index 209ee4a1..523f9122 100644 --- a/lib/data/models/login.result.dart +++ b/lib/data/models/login.result.dart @@ -6,9 +6,9 @@ part 'login.result.g.dart'; class LoginResult { final String token; final bool success; - final UserModel user; + final UserModel data; - LoginResult(this.token, this.success, this.user); + LoginResult(this.token, this.success, this.data); factory LoginResult.fromJson(Map json) => diff --git a/lib/data/models/login.result.g.dart b/lib/data/models/login.result.g.dart index df94b3cf..5b149d6a 100644 --- a/lib/data/models/login.result.g.dart +++ b/lib/data/models/login.result.g.dart @@ -10,7 +10,7 @@ LoginResult _$LoginResultFromJson(Map json) { return LoginResult( json['token'] as String, json['success'] as bool, - UserModel.fromJson(json['user'] as Map), + UserModel.fromJson(json['data'] as Map), ); } @@ -18,5 +18,5 @@ Map _$LoginResultToJson(LoginResult instance) => { 'token': instance.token, 'success': instance.success, - 'user': instance.user.toJson(), + 'data': instance.data.toJson(), }; diff --git a/lib/interceptor/dio_interceptor.dart b/lib/interceptor/dio_interceptor.dart index c291f57a..641f5a2b 100644 --- a/lib/interceptor/dio_interceptor.dart +++ b/lib/interceptor/dio_interceptor.dart @@ -17,7 +17,7 @@ class DioInterceptors extends InterceptorsWrapper { String? token = _store.read(accessToken); if (token != null && token.isNotEmpty) { options.headers.addAll({ - HttpHeaders.authorizationHeader: token, + HttpHeaders.authorizationHeader: 'Bearer $token', }); } diff --git a/lib/screens/category/category.controller.dart b/lib/screens/category/category.controller.dart index 2105774f..bc4196c3 100644 --- a/lib/screens/category/category.controller.dart +++ b/lib/screens/category/category.controller.dart @@ -1,5 +1,6 @@ import 'package:ecommerce_int2/data/models/category.model.dart'; import 'package:ecommerce_int2/data/repository/category.repository.dart'; +import 'package:ecommerce_int2/utils/message_dialog.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -12,28 +13,40 @@ class CategoryController extends GetxController { TextEditingController searchController = TextEditingController(); - List get list => categoryList.categories ?? []; + List get list => categoryList.data ?? []; List tempList = []; @override void onInit() { - getCategoryList(); + // getCategoryList(); super.onInit(); } - void getCategoryList() { - repository.getAllCategories().then((value) { + @override + void onReady() { + getCategoryList(); + super.onReady(); + } + + void getCategoryList() async { + MessageDialog.showLoading(); + try { + final value = await repository.getAllCategories(); categoryList = value; - tempList = categoryList.categories!; + tempList = categoryList.data!; update(); - }, onError: (exeption) => print(exeption)); + } on Exception catch (e) { + print(e); + } finally { + MessageDialog.hideLoading(); + } } void onChanged(String value) { if (value.isNotEmpty) { list.forEach((category) { - if (category.categoryName!.toLowerCase().contains(value)) { + if (category.name!.toLowerCase().contains(value)) { tempList.add(category); } }); diff --git a/lib/screens/category/category_list_page.dart b/lib/screens/category/category_list_page.dart index 0efe6c54..f06896a1 100755 --- a/lib/screens/category/category_list_page.dart +++ b/lib/screens/category/category_list_page.dart @@ -14,7 +14,7 @@ class CategoryListPage extends StatelessWidget { return Material( color: Color(0xffF9F9F9), child: Container( - margin: const EdgeInsets.only(top: kToolbarHeight), + margin: const EdgeInsets.only(top: 16), padding: EdgeInsets.symmetric(horizontal: 16.0), child: GetBuilder( init: CategoryController(Get.find()), @@ -64,7 +64,7 @@ class CategoryListPage extends StatelessWidget { begin: const Color(0xffFCE183), end: const Color(0xffF68D7F), categoryName: - controller.tempList[index].categoryName ?? "", + controller.tempList[index].name ?? "", assetPath: 'assets/jeans_5.png', onViewMore: () => Get.to(SubCategoryListPage( category: controller.tempList[index])), diff --git a/lib/screens/category/sub_category_list_page.dart b/lib/screens/category/sub_category_list_page.dart index 666647da..c9ba9cea 100644 --- a/lib/screens/category/sub_category_list_page.dart +++ b/lib/screens/category/sub_category_list_page.dart @@ -2,7 +2,6 @@ import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/data/models/category.model.dart'; import 'package:ecommerce_int2/data/repository/category.repository.dart'; import 'package:ecommerce_int2/screens/category/sub_category.controller.dart'; -import 'package:ecommerce_int2/screens/product/view_product_page.dart'; import 'package:ecommerce_int2/screens/search_products/search_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -21,26 +20,28 @@ class SubCategoryListPage extends StatelessWidget { return Material( color: Color(0xffF9F9F9), child: Container( - margin: const EdgeInsets.only(top: kToolbarHeight), + margin: const EdgeInsets.only(top: 16), padding: EdgeInsets.symmetric(horizontal: 16.0), child: GetBuilder( init: SubCategoryController(Get.find(), category), builder: (controller) => Column( mainAxisSize: MainAxisSize.min, children: [ - Align( - alignment: Alignment(-1, 0), - child: Padding( - padding: EdgeInsets.symmetric(vertical: 16.0), - child: Text( - 'Sub Category List', - style: TextStyle( - color: darkGrey, - fontSize: 22, - fontWeight: FontWeight.bold, + Row( + children: [ + BackButton(onPressed: () => Get.back(),), + Padding( + padding: EdgeInsets.symmetric(vertical: 16.0), + child: Text( + 'Sub Category List', + style: TextStyle( + color: darkGrey, + fontSize: 22, + fontWeight: FontWeight.bold, + ), ), ), - ), + ], ), Container( padding: EdgeInsets.only(left: 16.0), diff --git a/lib/screens/product/components/shop_product.dart b/lib/screens/product/components/shop_product.dart index 6f953979..9002e44e 100755 --- a/lib/screens/product/components/shop_product.dart +++ b/lib/screens/product/components/shop_product.dart @@ -72,7 +72,7 @@ class ShopProductDisplay extends StatelessWidget { child: SizedBox( height: 80, width: 80, - child: Image.asset( + child: Image.network( product.imageUrl!, fit: BoxFit.contain, )), diff --git a/lib/screens/product/product_page.dart b/lib/screens/product/product_page.dart index fe2dfa3e..1b770a2b 100755 --- a/lib/screens/product/product_page.dart +++ b/lib/screens/product/product_page.dart @@ -1,36 +1,25 @@ import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/screens/shop/cart.controller.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; -import 'package:ecommerce_int2/screens/search_products/search_page.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; import 'components/product_display.dart'; -import 'view_product_page.dart'; -class ProductPage extends StatefulWidget { +class ProductPage extends StatelessWidget { final Product product; ProductPage({required this.product}); - @override - _ProductPageState createState() => _ProductPageState(product); -} - -class _ProductPageState extends State { - final Product product; - - _ProductPageState(this.product); @override Widget build(BuildContext context) { + final controller = Get.find(); double width = MediaQuery.of(context).size.width; double bottomPadding = MediaQuery.of(context).padding.bottom; Widget viewProductButton = InkWell( - onTap: () => Navigator.of(context).push(MaterialPageRoute( - builder: (_) => ViewProductPage( - product: product, - ))), + onTap: () => controller.addProduct(product), child: Container( height: 80, width: width / 1.5, @@ -62,7 +51,7 @@ class _ProductPageState extends State { elevation: 0.0, iconTheme: IconThemeData(color: darkGrey), title: Text( - widget.product.name ?? 'Product', + product.name ?? 'Product', style: const TextStyle( color: darkGrey, fontWeight: FontWeight.w500, fontSize: 18.0), ), diff --git a/lib/screens/search_products/search_page.dart b/lib/screens/search_products/search_page.dart index 818684a9..3259bd28 100644 --- a/lib/screens/search_products/search_page.dart +++ b/lib/screens/search_products/search_page.dart @@ -73,7 +73,7 @@ class _SearchPageState extends State Widget _getLowerLayer(SearchProductController controller) { return Container( - margin: const EdgeInsets.only(top: kToolbarHeight), + margin: const EdgeInsets.only(top: 16), child: Column( children: [ Padding( diff --git a/lib/screens/shop/cart.controller.dart b/lib/screens/shop/cart.controller.dart index ed79eec4..7db8828c 100644 --- a/lib/screens/shop/cart.controller.dart +++ b/lib/screens/shop/cart.controller.dart @@ -1,6 +1,7 @@ import 'package:card_swiper/card_swiper.dart'; import 'package:ecommerce_int2/data/models/product.model.dart'; import 'package:ecommerce_int2/data/repository/cart.repository.dart'; +import 'package:ecommerce_int2/utils/message_dialog.dart'; import 'package:get/get.dart'; class CartController extends GetxController { @@ -11,21 +12,7 @@ class CartController extends GetxController { CartController(this.repository); List products = [ - Product( - imageUrl: 'assets/headphones.png', - name: 'Boat roackerz 400 On-Ear Bluetooth Headphones', - description: 'description', - price: 45000), - Product( - imageUrl: 'assets/headphones_2.png', - name: 'Boat roackerz 100 On-Ear Bluetooth Headphones', - description: 'description', - price: 22000), - Product( - imageUrl: 'assets/headphones_3.png', - name: 'Boat roackerz 300 On-Ear Bluetooth Headphones', - description: 'description', - price: 58000) + ]; String get total { @@ -41,4 +28,11 @@ class CartController extends GetxController { products.remove(product); update(); } + + void addProduct(Product product) { + MessageDialog.showToast("Added product to cart"); + // repository.addProduct(param); + products.add(product); + update(); + } } diff --git a/lib/services/auth.service.dart b/lib/services/auth.service.dart index e2e8c98c..3bc0a296 100644 --- a/lib/services/auth.service.dart +++ b/lib/services/auth.service.dart @@ -3,6 +3,7 @@ import 'package:ecommerce_int2/data/models/user.model.dart'; import 'package:ecommerce_int2/data/repository/auth.repository.dart'; import 'package:ecommerce_int2/screens/auth/welcome_back_page.dart'; import 'package:ecommerce_int2/screens/main/main_page.dart'; +import 'package:ecommerce_int2/utils/message_dialog.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; @@ -12,15 +13,17 @@ class AuthService extends GetxService { final store = GetStorage(); + UserModel? userModel; + + AuthService(this.repository); + @override void onInit() { + // login('manmaihuu@gmail.com', '123456A'); getUserInfo(); super.onInit(); } - UserModel? userModel; - - AuthService(this.repository); void getUserInfo() async { try { @@ -37,7 +40,9 @@ class AuthService extends GetxService { Future login(String username, String password) async { try { + MessageDialog.showLoading(); final res = await repository.login(username, password); + MessageDialog.hideLoading(); await setAccessToken(res.token); getUserInfo(); Navigator.of(Get.context!) diff --git a/lib/utils/dependencies.dart b/lib/utils/dependencies.dart index 0c136478..f7dd82e7 100644 --- a/lib/utils/dependencies.dart +++ b/lib/utils/dependencies.dart @@ -8,6 +8,7 @@ import 'package:ecommerce_int2/data/repository/auth.repository.dart'; import 'package:ecommerce_int2/data/repository/cart.repository.dart'; import 'package:ecommerce_int2/data/repository/category.repository.dart'; import 'package:ecommerce_int2/data/repository/product.repository.dart'; +import 'package:ecommerce_int2/screens/shop/cart.controller.dart'; import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:ecommerce_int2/services/network.service.dart'; import 'package:get/get.dart'; @@ -27,6 +28,7 @@ class Dependency { ..put(ProductRepository(Get.find())) ..put(CartProvider(Get.find())) ..put(CartRepository(Get.find())) + ..put(CartController(Get.find()), permanent: true) ; } } diff --git a/lib/utils/message_dialog.dart b/lib/utils/message_dialog.dart new file mode 100644 index 00000000..be0e84ef --- /dev/null +++ b/lib/utils/message_dialog.dart @@ -0,0 +1,90 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class MessageDialog { + static void hideLoading() { + if (Get.isDialogOpen!) { + Get.back(); + } + } + + static void showToast(String text) { + Get.showSnackbar(GetSnackBar( + messageText: Text(text), + )); + } + + static void showConfirmDialog({ + required String content, + }) { + Get.generalDialog( + barrierDismissible: false, + barrierColor: const Color.fromRGBO(0, 0, 0, 0.3), + transitionDuration: Duration.zero, + pageBuilder: (context, _, __) { + return AlertDialog( + backgroundColor: Colors.white, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(10), + ), + ), + content: SizedBox( + height: 65, + width: Get.width, + child: Center( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + //todo: Change the loading indicator + const CircularProgressIndicator(), + const SizedBox(width: 16), + Text( + content, + ), + ], + ), + ), + ), + buttonPadding: EdgeInsets.zero, + ); + }, + ); + } + + static void showLoading() { + Get.generalDialog( + barrierDismissible: false, + barrierColor: const Color.fromRGBO(0, 0, 0, 0.3), + transitionDuration: Duration.zero, + pageBuilder: (context, _, __) { + return AlertDialog( + backgroundColor: Colors.white, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(10), + ), + ), + content: SizedBox( + height: 65, + width: Get.width, + child: Center( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + //todo: Change the loading indicator + const CircularProgressIndicator(), + const SizedBox(width: 16), + Text( + 'Processing...', + ), + ], + ), + ), + ), + buttonPadding: EdgeInsets.zero, + ); + }, + ); + } +} From a3086d0cc0463f29a51b0db5af02b871d16e16fd Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Wed, 1 Jun 2022 15:51:50 +0700 Subject: [PATCH 21/49] Update purchase flow --- .flutter-plugins-dependencies | 2 +- lib/data/models/order.model.dart | 190 ++++++++++++++++++ lib/data/provider/auth.provider.dart | 1 - lib/data/provider/cart.provider.dart | 15 +- lib/data/provider/order.provider.dart | 34 ++++ lib/data/provider/product.provider.dart | 1 - lib/data/repository/cart.repository.dart | 16 +- lib/data/repository/order.repository.dart | 38 ++++ lib/screens/address/add_address_page.dart | 5 +- lib/screens/address/address.controller.dart | 29 ++- lib/screens/auth/confirm_otp_page.dart | 1 - lib/screens/category/category.controller.dart | 4 +- lib/screens/category/category_list_page.dart | 101 +++++----- .../category/sub_category_list_page.dart | 103 +++++----- lib/screens/shop/cart.controller.dart | 37 +++- lib/screens/shop/check_out_page.dart | 7 +- lib/utils/dependencies.dart | 4 + 17 files changed, 458 insertions(+), 130 deletions(-) create mode 100644 lib/data/models/order.model.dart create mode 100644 lib/data/provider/order.provider.dart create mode 100644 lib/data/repository/order.repository.dart diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 3b28c1ce..ebe32000 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2022-05-29 08:23:17.010544","version":"2.10.4"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2022-06-01 15:20:23.532298","version":"2.10.4"} \ No newline at end of file diff --git a/lib/data/models/order.model.dart b/lib/data/models/order.model.dart new file mode 100644 index 00000000..f78be6a3 --- /dev/null +++ b/lib/data/models/order.model.dart @@ -0,0 +1,190 @@ +class OrderResponse { + bool? success; + String? message; + Order? order; + + OrderResponse({this.success, this.message, this.order}); + + OrderResponse.fromJson(Map json) { + success = json['success']; + message = json['message']; + order = json['order'] != null ? new Order.fromJson(json['order']) : null; + } + + Map toJson() { + final Map data = new Map(); + data['success'] = this.success; + data['message'] = this.message; + if (this.order != null) { + data['order'] = this.order!.toJson(); + } + return data; + } +} + +class Order { + String? cart; + String? user; + String? merchant; + String? payment; + String? otherAddress; + String? phoneNumber; + String? status; + String? paymentStatus; + String? sId; + String? created; + int? iV; + + Order( + {this.cart, + this.user, + this.merchant, + this.payment, + this.otherAddress, + this.phoneNumber, + this.status, + this.paymentStatus, + this.sId, + this.created, + this.iV}); + + Order.fromJson(Map json) { + cart = json['cart']; + user = json['user']; + merchant = json['merchant']; + payment = json['payment']; + otherAddress = json['otherAddress']; + phoneNumber = json['phoneNumber']; + status = json['status']; + paymentStatus = json['paymentStatus']; + sId = json['_id']; + created = json['created']; + iV = json['__v']; + } + + Map toJson() { + final Map data = new Map(); + data['cart'] = this.cart; + data['user'] = this.user; + data['merchant'] = this.merchant; + data['payment'] = this.payment; + data['otherAddress'] = this.otherAddress; + data['phoneNumber'] = this.phoneNumber; + data['status'] = this.status; + data['paymentStatus'] = this.paymentStatus; + data['_id'] = this.sId; + data['created'] = this.created; + data['__v'] = this.iV; + return data; + } +} + +class CompleteOrderParam { + String? address; + String? otherAddress; + String? phoneNumber; + String? payment; + + CompleteOrderParam( + {this.address, this.otherAddress, this.phoneNumber, this.payment}); + + CompleteOrderParam.fromJson(Map json) { + address = json['address']; + otherAddress = json['otherAddress']; + phoneNumber = json['phoneNumber']; + payment = json['payment']; + } + + Map toJson() { + final Map data = new Map(); + data['address'] = this.address; + data['otherAddress'] = this.otherAddress; + data['phoneNumber'] = this.phoneNumber; + data['payment'] = this.payment; + return data; + } +} + +class CompleteOrderResponse { + bool? success; + String? message; + OrderDoc? orderDoc; + + CompleteOrderResponse({this.success, this.message, this.orderDoc}); + + CompleteOrderResponse.fromJson(Map json) { + success = json['success']; + message = json['message']; + orderDoc = json['orderDoc'] != null + ? new OrderDoc.fromJson(json['orderDoc']) + : null; + } + + Map toJson() { + final Map data = new Map(); + data['success'] = this.success; + data['message'] = this.message; + if (this.orderDoc != null) { + data['orderDoc'] = this.orderDoc!.toJson(); + } + return data; + } +} + +class OrderDoc { + String? sId; + String? cart; + String? user; + String? merchant; + String? payment; + String? otherAddress; + String? phoneNumber; + String? status; + String? paymentStatus; + String? created; + int? iV; + + OrderDoc( + {this.sId, + this.cart, + this.user, + this.merchant, + this.payment, + this.otherAddress, + this.phoneNumber, + this.status, + this.paymentStatus, + this.created, + this.iV}); + + OrderDoc.fromJson(Map json) { + sId = json['_id']; + cart = json['cart']; + user = json['user']; + merchant = json['merchant']; + payment = json['payment']; + otherAddress = json['otherAddress']; + phoneNumber = json['phoneNumber']; + status = json['status']; + paymentStatus = json['paymentStatus']; + created = json['created']; + iV = json['__v']; + } + + Map toJson() { + final Map data = new Map(); + data['_id'] = this.sId; + data['cart'] = this.cart; + data['user'] = this.user; + data['merchant'] = this.merchant; + data['payment'] = this.payment; + data['otherAddress'] = this.otherAddress; + data['phoneNumber'] = this.phoneNumber; + data['status'] = this.status; + data['paymentStatus'] = this.paymentStatus; + data['created'] = this.created; + data['__v'] = this.iV; + return data; + } +} + diff --git a/lib/data/provider/auth.provider.dart b/lib/data/provider/auth.provider.dart index 57a5e3e7..b793d8eb 100644 --- a/lib/data/provider/auth.provider.dart +++ b/lib/data/provider/auth.provider.dart @@ -1,5 +1,4 @@ import 'package:ecommerce_int2/utils/app_properties.dart'; -import 'package:ecommerce_int2/data/models/login.result.dart'; import 'package:ecommerce_int2/data/models/user.model.dart'; import 'package:ecommerce_int2/services/network.service.dart'; import 'package:get_storage/get_storage.dart'; diff --git a/lib/data/provider/cart.provider.dart b/lib/data/provider/cart.provider.dart index b363f243..7e6ff69f 100644 --- a/lib/data/provider/cart.provider.dart +++ b/lib/data/provider/cart.provider.dart @@ -19,7 +19,9 @@ class CartProvider { 'https://ecommerce-api-dut.herokuapp.com/api/cart/modify'; final String deleteProductFromCartUrl = - 'https://ecommerce-api-dut.herokuapp.com/api/cart/modify'; + 'https://ecommerce-api-dut.herokuapp.com/api/cart/delete'; + + Future getCarts() { return networkService.get(getAllCartUrl); @@ -29,12 +31,15 @@ class CartProvider { return networkService.post(addProductToCartUrl, data: param.toJson()); } - Future modifyProduct(String productId, int before, int after) { - return networkService.put('$addProductToCartUrl/$productId', + Future modifyProduct( + String cartId, String productId, int before, int after) { + return networkService.put('$addProductToCartUrl/$cartId/$productId', data: {"previousQuantity": before, "currentQuantity": after}); } - Future deleteProduct(String productId) { - return networkService.delete('$deleteProductFromCartUrl/$productId'); + Future deleteProduct(String cartId, String productId) { + return networkService + .delete('$deleteProductFromCartUrl/$cartId/$productId'); } + } diff --git a/lib/data/provider/order.provider.dart b/lib/data/provider/order.provider.dart new file mode 100644 index 00000000..e7abfbd4 --- /dev/null +++ b/lib/data/provider/order.provider.dart @@ -0,0 +1,34 @@ +import 'package:ecommerce_int2/data/models/order.model.dart'; +import 'package:ecommerce_int2/services/network.service.dart'; +import 'package:get_storage/get_storage.dart'; + +class OrderProvider { + final NetWorkService networkService; + + final GetStorage storage = GetStorage(); + + OrderProvider(this.networkService); + + final String completeOrderUrl = + 'https://ecommerce-api-dut.herokuapp.com/api/order/'; + + final String checkOutCartUrl = + 'https://ecommerce-api-dut.herokuapp.com/api/order/add'; + + + Future checkOut(String cartId) { + return networkService.post(checkOutCartUrl, + data: {"cart": cartId, "merchant": "626e237ef4224ee4107039b9"}); + } + + Future completeOrder( + CompleteOrderParam param) { + return networkService.put(completeOrderUrl, data: param.toJson()); + } + + Future makePayment( + String orderId) { + return networkService.post('$completeOrderUrl/$orderId/pay'); + } + +} diff --git a/lib/data/provider/product.provider.dart b/lib/data/provider/product.provider.dart index 2ecadfc5..e3d1b707 100644 --- a/lib/data/provider/product.provider.dart +++ b/lib/data/provider/product.provider.dart @@ -1,4 +1,3 @@ -import 'package:ecommerce_int2/data/models/address.model.dart'; import 'package:ecommerce_int2/data/models/product.model.dart'; import 'package:ecommerce_int2/services/network.service.dart'; import 'package:get_storage/get_storage.dart'; diff --git a/lib/data/repository/cart.repository.dart b/lib/data/repository/cart.repository.dart index 58fbcf83..eb757915 100644 --- a/lib/data/repository/cart.repository.dart +++ b/lib/data/repository/cart.repository.dart @@ -1,6 +1,5 @@ import 'package:ecommerce_int2/data/models/address.model.dart'; import 'package:ecommerce_int2/data/models/product.model.dart'; -import 'package:ecommerce_int2/data/provider/address.provider.dart'; import 'package:ecommerce_int2/data/provider/cart.provider.dart'; class CartRepository { @@ -19,24 +18,29 @@ class CartRepository { return result; } - Future addProduct(AddProductParam param) async { + Future addProduct(AddProductParam param) async { final response = await provider.addProduct(param); if (response.statusCode != 200) { throw Exception("Add product failed"); } + return response.body['_id']; } - Future deleteProduct(String productID) async { - final response = await provider.deleteProduct(productID); + Future deleteProduct(String cartId, String productID) async { + final response = await provider.deleteProduct(cartId, productID); if (response.statusCode != 200) { throw Exception("Delete product failed"); } } - Future modifyProduct(String productId, int before, int after) async { - final response = await provider.modifyProduct(productId, before, after); + Future modifyProduct( + String cartId, String productId, int before, int after) async { + final response = + await provider.modifyProduct(cartId, productId, before, after); if (response.statusCode != 200) { throw Exception("Update product failed"); } } + + } diff --git a/lib/data/repository/order.repository.dart b/lib/data/repository/order.repository.dart new file mode 100644 index 00000000..6d0ed885 --- /dev/null +++ b/lib/data/repository/order.repository.dart @@ -0,0 +1,38 @@ +import 'package:ecommerce_int2/data/models/order.model.dart'; +import 'package:ecommerce_int2/data/provider/order.provider.dart'; + +class OrderRepository { + final OrderProvider provider; + + OrderRepository(this.provider); + + Future completeOrder(CompleteOrderParam param) async { + final response = await provider.completeOrder(param); + if (response.statusCode != 200) { + throw Exception("Complete order failed"); + } + final result = CompleteOrderResponse.fromJson(response.body); + return result.orderDoc!.sId!; + } + + Future makePayment(String orderId) async { + final response = await provider.makePayment(orderId); + if (response.statusCode != 200) { + throw Exception("Make payment failed"); + } + // final result = CompleteOrderResponse.fromJson(response.body); + return 'href'; + } + + Future checkOut( + String cartId) async { + final response = + await provider.checkOut(cartId); + if (response.statusCode != 200) { + throw Exception("Check out cart failed"); + } + + final result = OrderResponse.fromJson(response.body); + return result.order!; + } +} diff --git a/lib/screens/address/add_address_page.dart b/lib/screens/address/add_address_page.dart index ea55b446..b1c0a9a1 100755 --- a/lib/screens/address/add_address_page.dart +++ b/lib/screens/address/add_address_page.dart @@ -1,3 +1,4 @@ +import 'package:ecommerce_int2/data/repository/order.repository.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/data/repository/address.repository.dart'; import 'package:ecommerce_int2/screens/address/address_form.dart'; @@ -43,7 +44,8 @@ class AddAddressPage extends StatelessWidget { @override Widget build(BuildContext context) { return GetBuilder( - init: AddressController(Get.find()), + init: AddressController( + Get.find(), Get.find()), builder: (controller) => Scaffold( backgroundColor: Colors.grey[100], appBar: AppBar( @@ -128,7 +130,6 @@ class AddAddressPage extends StatelessWidget { addr: address, city: city), const SizedBox(height: 16), - Center(child: buildFinishButton(controller)) ], ), diff --git a/lib/screens/address/address.controller.dart b/lib/screens/address/address.controller.dart index 10a90f98..30386e0e 100644 --- a/lib/screens/address/address.controller.dart +++ b/lib/screens/address/address.controller.dart @@ -1,11 +1,18 @@ import 'package:ecommerce_int2/data/models/address.model.dart'; +import 'package:ecommerce_int2/data/models/order.model.dart'; import 'package:ecommerce_int2/data/repository/address.repository.dart'; +import 'package:ecommerce_int2/data/repository/order.repository.dart'; +import 'package:ecommerce_int2/screens/tracking_page.dart'; +import 'package:ecommerce_int2/utils/message_dialog.dart'; import 'package:get/get.dart'; class AddressController extends GetxController { final AddressRepository repository; + final OrderRepository orderRepository; - AddressController(this.repository); + AddressController(this.repository, this.orderRepository); + + String? cartId; List
addresses =
[Address()]; @@ -15,10 +22,18 @@ class AddressController extends GetxController { @override void onInit() { + getArgument(); getAllAddress(); super.onInit(); } + void getArgument() { + final arg = Get.arguments; + if (arg != null && arg is String) { + cartId = arg; + } + } + void getAllAddress() async { final List
res = await repository.getAllAddress(); addresses.assignAll(res); @@ -45,4 +60,16 @@ class AddressController extends GetxController { repository.updateAddress(selectedAddress).then((value) => null, onError: (e) => null); } } + + void checkOut() async { + try { + MessageDialog.showLoading(); + final Order order = await orderRepository.checkOut(cartId!); + MessageDialog.hideLoading(); + Get.to(TrackingPage()); + } on Exception catch (e) { + MessageDialog.hideLoading(); + print(e); + } + } } \ No newline at end of file diff --git a/lib/screens/auth/confirm_otp_page.dart b/lib/screens/auth/confirm_otp_page.dart index cf671e13..12618944 100755 --- a/lib/screens/auth/confirm_otp_page.dart +++ b/lib/screens/auth/confirm_otp_page.dart @@ -1,7 +1,6 @@ import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/intro_page.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:pin_code_text_field/pin_code_text_field.dart'; class ConfirmOtpPage extends StatefulWidget { diff --git a/lib/screens/category/category.controller.dart b/lib/screens/category/category.controller.dart index bc4196c3..2403d34b 100644 --- a/lib/screens/category/category.controller.dart +++ b/lib/screens/category/category.controller.dart @@ -34,7 +34,8 @@ class CategoryController extends GetxController { try { final value = await repository.getAllCategories(); categoryList = value; - tempList = categoryList.data!; + final temp = CategoryList.fromJson(value.toJson()); + tempList = temp.data!; update(); } on Exception catch (e) { print(e); @@ -45,6 +46,7 @@ class CategoryController extends GetxController { void onChanged(String value) { if (value.isNotEmpty) { + tempList.clear(); list.forEach((category) { if (category.name!.toLowerCase().contains(value)) { tempList.add(category); diff --git a/lib/screens/category/category_list_page.dart b/lib/screens/category/category_list_page.dart index f06896a1..a096325d 100755 --- a/lib/screens/category/category_list_page.dart +++ b/lib/screens/category/category_list_page.dart @@ -18,61 +18,64 @@ class CategoryListPage extends StatelessWidget { padding: EdgeInsets.symmetric(horizontal: 16.0), child: GetBuilder( init: CategoryController(Get.find()), - builder: (controller) => Column( - mainAxisSize: MainAxisSize.min, - children: [ - Align( - alignment: Alignment(-1, 0), - child: Padding( - padding: EdgeInsets.symmetric(vertical: 16.0), - child: Text( - 'Category List', - style: TextStyle( - color: darkGrey, - fontSize: 22, - fontWeight: FontWeight.bold, + builder: (controller) => SafeArea( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox(height: 16,), + Align( + alignment: Alignment(-1, 0), + child: Padding( + padding: EdgeInsets.symmetric(vertical: 16.0), + child: Text( + 'Category List', + style: TextStyle( + color: darkGrey, + fontSize: 22, + fontWeight: FontWeight.bold, + ), ), ), ), - ), - Container( - padding: EdgeInsets.only(left: 16.0), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(5)), - color: Colors.white, - ), - child: TextField( - controller: controller.searchController, - decoration: InputDecoration( - border: InputBorder.none, - hintText: 'Search', - prefixIcon: SvgPicture.asset( - 'assets/icons/search_icon.svg', - fit: BoxFit.scaleDown, - )), - onChanged: (value) => controller.onChanged(value), + Container( + padding: EdgeInsets.only(left: 16.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(5)), + color: Colors.white, + ), + child: TextField( + controller: controller.searchController, + decoration: InputDecoration( + border: InputBorder.none, + hintText: 'Search', + prefixIcon: SvgPicture.asset( + 'assets/icons/search_icon.svg', + fit: BoxFit.scaleDown, + )), + onChanged: (value) => controller.onChanged(value), + ), ), - ), - Flexible( - child: ListView.builder( - itemCount: controller.tempList.length, - itemBuilder: (_, index) => Padding( - padding: EdgeInsets.symmetric( - vertical: 16.0, - ), - child: StaggeredCardCard( - begin: const Color(0xffFCE183), - end: const Color(0xffF68D7F), - categoryName: - controller.tempList[index].name ?? "", - assetPath: 'assets/jeans_5.png', - onViewMore: () => Get.to(SubCategoryListPage( - category: controller.tempList[index])), + Flexible( + child: ListView.builder( + itemCount: controller.tempList.length, + itemBuilder: (_, index) => Padding( + padding: EdgeInsets.symmetric( + vertical: 16.0, + ), + child: StaggeredCardCard( + begin: const Color(0xffFCE183), + end: const Color(0xffF68D7F), + categoryName: + controller.tempList[index].name ?? "", + assetPath: 'assets/jeans_5.png', + onViewMore: () => Get.to(SubCategoryListPage( + category: controller.tempList[index])), + ), ), ), - ), - ) - ], + ) + ], + ), ), ), ), diff --git a/lib/screens/category/sub_category_list_page.dart b/lib/screens/category/sub_category_list_page.dart index c9ba9cea..b918c15f 100644 --- a/lib/screens/category/sub_category_list_page.dart +++ b/lib/screens/category/sub_category_list_page.dart @@ -24,62 +24,65 @@ class SubCategoryListPage extends StatelessWidget { padding: EdgeInsets.symmetric(horizontal: 16.0), child: GetBuilder( init: SubCategoryController(Get.find(), category), - builder: (controller) => Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - children: [ - BackButton(onPressed: () => Get.back(),), - Padding( - padding: EdgeInsets.symmetric(vertical: 16.0), - child: Text( - 'Sub Category List', - style: TextStyle( - color: darkGrey, - fontSize: 22, - fontWeight: FontWeight.bold, + builder: (controller) => SafeArea( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox(height: 16,), + Row( + children: [ + BackButton(onPressed: () => Get.back(),), + Padding( + padding: EdgeInsets.symmetric(vertical: 16.0), + child: Text( + 'Sub Category List', + style: TextStyle( + color: darkGrey, + fontSize: 22, + fontWeight: FontWeight.bold, + ), ), ), - ), - ], - ), - Container( - padding: EdgeInsets.only(left: 16.0), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(5)), - color: Colors.white, + ], ), - child: TextField( - controller: controller.searchController, - decoration: InputDecoration( - border: InputBorder.none, - hintText: 'Search', - prefixIcon: SvgPicture.asset( - 'assets/icons/search_icon.svg', - fit: BoxFit.scaleDown, - )), - onChanged: (value) => controller.onChanged(value), + Container( + padding: EdgeInsets.only(left: 16.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(5)), + color: Colors.white, + ), + child: TextField( + controller: controller.searchController, + decoration: InputDecoration( + border: InputBorder.none, + hintText: 'Search', + prefixIcon: SvgPicture.asset( + 'assets/icons/search_icon.svg', + fit: BoxFit.scaleDown, + )), + onChanged: (value) => controller.onChanged(value), + ), ), - ), - Flexible( - child: ListView.builder( - itemCount: controller.tempList.length, - itemBuilder: (_, index) => Padding( - padding: EdgeInsets.symmetric( - vertical: 16.0, - ), - child: StaggeredCardCard( - begin: const Color(0xffFCE183), - end: const Color(0xffF68D7F), - categoryName: controller.tempList[index].name ?? "", - assetPath: 'assets/jeans_5.png', - onViewMore: () => Get.to(SearchPage(), - arguments: controller.tempList[index].slug), + Flexible( + child: ListView.builder( + itemCount: controller.tempList.length, + itemBuilder: (_, index) => Padding( + padding: EdgeInsets.symmetric( + vertical: 16.0, + ), + child: StaggeredCardCard( + begin: const Color(0xffFCE183), + end: const Color(0xffF68D7F), + categoryName: controller.tempList[index].name ?? "", + assetPath: 'assets/jeans_5.png', + onViewMore: () => Get.to(SearchPage(), + arguments: controller.tempList[index].slug), + ), ), ), - ), - ) - ], + ) + ], + ), ), ), ), diff --git a/lib/screens/shop/cart.controller.dart b/lib/screens/shop/cart.controller.dart index 7db8828c..b523ed3d 100644 --- a/lib/screens/shop/cart.controller.dart +++ b/lib/screens/shop/cart.controller.dart @@ -1,6 +1,7 @@ import 'package:card_swiper/card_swiper.dart'; import 'package:ecommerce_int2/data/models/product.model.dart'; import 'package:ecommerce_int2/data/repository/cart.repository.dart'; +import 'package:ecommerce_int2/screens/address/add_address_page.dart'; import 'package:ecommerce_int2/utils/message_dialog.dart'; import 'package:get/get.dart'; @@ -11,9 +12,9 @@ class CartController extends GetxController { CartController(this.repository); - List products = [ + String? id; - ]; + List products = []; String get total { int result = 0; @@ -24,15 +25,35 @@ class CartController extends GetxController { } void remove(Product product) { - repository.deleteProduct(product.sId!); + if (id == null) { + MessageDialog.showToast("There is something wrong!!"); + return; + } + repository.deleteProduct(id!, product.sId!); products.remove(product); update(); } - void addProduct(Product product) { - MessageDialog.showToast("Added product to cart"); - // repository.addProduct(param); - products.add(product); - update(); + void addProduct(Product product, {int? quantity}) async { + try { + AddProductParam param = AddProductParam(products: [ + ProductParam( + product: product.sId, + price: product.price, + merchant: product.merchant, + quantity: quantity) + ]); + // final String cartId = await repository.addProduct(param); + MessageDialog.showToast("Added product to cart"); + // id = cartId; + products.add(product); + update(); + } on Exception catch (e) { + print(e); + } + } + + void checkOut() async { + Get.to(AddAddressPage(), arguments: id); } } diff --git a/lib/screens/shop/check_out_page.dart b/lib/screens/shop/check_out_page.dart index fa75f668..b5d6c00d 100755 --- a/lib/screens/shop/check_out_page.dart +++ b/lib/screens/shop/check_out_page.dart @@ -14,9 +14,8 @@ import 'components/shop_item_list.dart'; class CheckOutPage extends StatelessWidget { @override Widget build(BuildContext context) { - Widget checkOutButton = InkWell( - onTap: () => Navigator.of(context) - .push(MaterialPageRoute(builder: (_) => AddAddressPage())), + Widget checkOutButton(CartController controller) => InkWell( + onTap: () => controller.checkOut(), child: Container( height: 80, width: MediaQuery.of(context).size.width / 1.5, @@ -150,7 +149,7 @@ class CheckOutPage extends StatelessWidget { bottom: MediaQuery.of(context).padding.bottom == 0 ? 20 : MediaQuery.of(context).padding.bottom), - child: checkOutButton, + child: checkOutButton(controller), )) ], ), diff --git a/lib/utils/dependencies.dart b/lib/utils/dependencies.dart index f7dd82e7..b0c3ecaa 100644 --- a/lib/utils/dependencies.dart +++ b/lib/utils/dependencies.dart @@ -2,11 +2,13 @@ import 'package:ecommerce_int2/data/provider/address.provider.dart'; import 'package:ecommerce_int2/data/provider/auth.provider.dart'; import 'package:ecommerce_int2/data/provider/cart.provider.dart'; import 'package:ecommerce_int2/data/provider/category.provider.dart'; +import 'package:ecommerce_int2/data/provider/order.provider.dart'; import 'package:ecommerce_int2/data/provider/product.provider.dart'; import 'package:ecommerce_int2/data/repository/address.repository.dart'; import 'package:ecommerce_int2/data/repository/auth.repository.dart'; import 'package:ecommerce_int2/data/repository/cart.repository.dart'; import 'package:ecommerce_int2/data/repository/category.repository.dart'; +import 'package:ecommerce_int2/data/repository/order.repository.dart'; import 'package:ecommerce_int2/data/repository/product.repository.dart'; import 'package:ecommerce_int2/screens/shop/cart.controller.dart'; import 'package:ecommerce_int2/services/auth.service.dart'; @@ -29,6 +31,8 @@ class Dependency { ..put(CartProvider(Get.find())) ..put(CartRepository(Get.find())) ..put(CartController(Get.find()), permanent: true) + ..put(OrderProvider(Get.find())) + ..put(OrderRepository(Get.find())) ; } } From d56f188ba7c8233771f58207e9716f7ea6aab0c9 Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Thu, 2 Jun 2022 16:29:25 +0700 Subject: [PATCH 22/49] Fix product get issue --- lib/data/models/address.model.dart | 9 ++++++-- lib/data/repository/product.repository.dart | 2 +- .../category/sub_category.controller.dart | 14 +++++++++---- .../search_products/search_controller.dart | 21 ++++++++++++------- 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/lib/data/models/address.model.dart b/lib/data/models/address.model.dart index 62d9569a..a3430b88 100644 --- a/lib/data/models/address.model.dart +++ b/lib/data/models/address.model.dart @@ -7,7 +7,12 @@ class Address { bool? isDefault; Address( - {this.id, this.address, this.city, this.country, this.zipCode, this.isDefault = false}); + {this.id, + this.address, + this.city, + this.country = "Viet Name", + this.zipCode = "+84", + this.isDefault = false}); Address.fromJson(Map json) { id = json['_id']; @@ -28,4 +33,4 @@ class Address { data['isDefault'] = this.isDefault; return data; } -} \ No newline at end of file +} diff --git a/lib/data/repository/product.repository.dart b/lib/data/repository/product.repository.dart index 76f620b1..46ea2a82 100644 --- a/lib/data/repository/product.repository.dart +++ b/lib/data/repository/product.repository.dart @@ -11,7 +11,7 @@ class ProductRepository { if (response.statusCode != 200) { throw Exception("Get products failed"); } - final result = ProductList.fromJson(response.body); + final result = ProductList.fromJson(response.body['data']); return result; } diff --git a/lib/screens/category/sub_category.controller.dart b/lib/screens/category/sub_category.controller.dart index bfa23311..3c037c1e 100644 --- a/lib/screens/category/sub_category.controller.dart +++ b/lib/screens/category/sub_category.controller.dart @@ -10,8 +10,6 @@ class SubCategoryController extends GetxController { SubCategoryController(this.repository, this.category); - CategoryList categoryList = CategoryList(); - TextEditingController searchController = TextEditingController(); List get list => category.subcategories ?? []; @@ -20,11 +18,20 @@ class SubCategoryController extends GetxController { @override void onInit() { - tempList = list; + super.onInit(); } + @override + void onReady() { + final temp = Category.fromJson(category.toJson()); + tempList = temp.subcategories!; + update(); + super.onReady(); + } + void onChanged(String value) { + tempList.clear(); if (value.isNotEmpty) { list.forEach((subCategory) { if (subCategory.name!.toLowerCase().contains(value)) { @@ -32,7 +39,6 @@ class SubCategoryController extends GetxController { } }); } else { - tempList.clear(); tempList.addAll(list); } update(); diff --git a/lib/screens/search_products/search_controller.dart b/lib/screens/search_products/search_controller.dart index 1dad5d3d..e26d8135 100644 --- a/lib/screens/search_products/search_controller.dart +++ b/lib/screens/search_products/search_controller.dart @@ -20,13 +20,15 @@ class SearchProductController extends GetxController { int total = 0; ProductFilter filter = ProductFilter( - sortOrder: SortOrder(iId: -1), + sortOrder: SortOrder(price: 1), pageNumber: 1, rating: 0, min: 1, max: 500000, - subcategory: '', - order: 0); + // subcategory: '', + // name: '', + // merchant: '', + order: 2); final Debounce debounce = Debounce(milliseconds: 2000); @@ -39,10 +41,14 @@ class SearchProductController extends GetxController { } Future getProduct() async { - final res = await repository.getProducts(filter); - total = res.totalProducts ?? 0; - list.addAll(res.products!); - update(); + try { + final res = await repository.getProducts(filter); + total = res.totalProducts ?? 0; + list.addAll(res.products!); + update(); + } on Exception catch (e) { + print(e); + } } void onRefresh() async { @@ -64,6 +70,7 @@ class SearchProductController extends GetxController { void onChanged(String value) { debounce.run(() { if (value.isNotEmpty) { + filter.name = value; getProduct(); update(); } From 4301c0fcb5870f73e503ec177b00070023237cf4 Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Thu, 2 Jun 2022 16:30:00 +0700 Subject: [PATCH 23/49] Fix address issues --- lib/data/models/product.model.dart | 14 ++++++++++---- lib/data/repository/address.repository.dart | 2 +- lib/screens/address/address.controller.dart | 18 +++++++++++------- lib/screens/address/address_form.dart | 6 ++++-- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/lib/data/models/product.model.dart b/lib/data/models/product.model.dart index bda712e9..d727ed28 100644 --- a/lib/data/models/product.model.dart +++ b/lib/data/models/product.model.dart @@ -119,6 +119,8 @@ class ProductFilter { int? max; int? min; String? subcategory; + String? name; + String? merchant; int? order; int? pageNumber; @@ -128,6 +130,8 @@ class ProductFilter { this.max, this.min, this.subcategory, + this.name, + this.merchant, this.order, this.pageNumber}); @@ -152,6 +156,8 @@ class ProductFilter { data['max'] = this.max; data['min'] = this.min; data['subcategory'] = this.subcategory; + data['name'] = this.name ?? ''; + data['merchant'] = this.merchant; data['order'] = this.order; data['pageNumber'] = this.pageNumber; return data; @@ -159,17 +165,17 @@ class ProductFilter { } class SortOrder { - int? iId; + int? price; - SortOrder({this.iId}); + SortOrder({this.price}); SortOrder.fromJson(Map json) { - iId = json['_id']; + price = json['_id']; } Map toJson() { final Map data = new Map(); - data['_id'] = this.iId; + data['price'] = this.price; return data; } } diff --git a/lib/data/repository/address.repository.dart b/lib/data/repository/address.repository.dart index d3197008..d4284fd2 100644 --- a/lib/data/repository/address.repository.dart +++ b/lib/data/repository/address.repository.dart @@ -11,7 +11,7 @@ class AddressRepository { if (response.statusCode != 200) { throw Exception("Get address failed"); } - final result = (response.body['addresses'] as List).map((i) => + final result = (response.body['data'] as List).map((i) => Address.fromJson(i)).toList(); return result; } diff --git a/lib/screens/address/address.controller.dart b/lib/screens/address/address.controller.dart index 30386e0e..eb788b21 100644 --- a/lib/screens/address/address.controller.dart +++ b/lib/screens/address/address.controller.dart @@ -49,19 +49,23 @@ class AddressController extends GetxController { } void updateCurrentAddress(String address, String city) { - if(address.isNotEmpty) selectedAddress.address = address; - if(city.isNotEmpty) selectedAddress.city = city; + if (address.isNotEmpty) selectedAddress.address = address; + if (city.isNotEmpty) selectedAddress.city = city; } void submitAddress() { - if(selectedAddress.id == null) { - repository.addAddress(selectedAddress).then((value) => null, onError: (e) => null); + if (selectedAddress.id == null) { + repository + .addAddress(selectedAddress) + .then((value) => null, onError: (e) => null); } else { - repository.updateAddress(selectedAddress).then((value) => null, onError: (e) => null); + repository + .updateAddress(selectedAddress) + .then((value) => null, onError: (e) => null); } } - void checkOut() async { + void checkOut() async { try { MessageDialog.showLoading(); final Order order = await orderRepository.checkOut(cartId!); @@ -72,4 +76,4 @@ class AddressController extends GetxController { print(e); } } -} \ No newline at end of file +} diff --git a/lib/screens/address/address_form.dart b/lib/screens/address/address_form.dart index 08e8d811..7d387552 100755 --- a/lib/screens/address/address_form.dart +++ b/lib/screens/address/address_form.dart @@ -20,8 +20,9 @@ class AddAddressForm extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceAround, crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text("Address"), Container( - padding: EdgeInsets.only(left: 16.0, top: 4.0, bottom: 4.0), + padding: EdgeInsets.only(left: 16.0, top: 8.0, bottom: 4.0), decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(5)), color: Colors.white, @@ -33,8 +34,9 @@ class AddAddressForm extends StatelessWidget { ), ), const SizedBox(height: 16,), + Text("City"), Container( - padding: EdgeInsets.only(left: 16.0, top: 4.0, bottom: 4.0), + padding: EdgeInsets.only(left: 16.0, top: 8.0, bottom: 4.0), decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(5)), color: Colors.white, From afb283d962dc7ca2f9c39ca42220b6f1b906b94c Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Fri, 3 Jun 2022 10:36:08 +0700 Subject: [PATCH 24/49] Check out cart to order --- lib/data/models/cart.model.dart | 83 ++++++++++++++++++++++ lib/data/models/product.model.dart | 90 ------------------------ lib/data/provider/cart.provider.dart | 7 +- lib/data/repository/cart.repository.dart | 16 +++-- lib/screens/shop/cart.controller.dart | 30 +++++--- 5 files changed, 119 insertions(+), 107 deletions(-) create mode 100644 lib/data/models/cart.model.dart diff --git a/lib/data/models/cart.model.dart b/lib/data/models/cart.model.dart new file mode 100644 index 00000000..eb84b23f --- /dev/null +++ b/lib/data/models/cart.model.dart @@ -0,0 +1,83 @@ +import 'package:ecommerce_int2/data/models/product.model.dart'; + +class CartResponse { + bool? success; + String? message; + List? data; + + CartResponse({this.success, this.message, this.data}); + + CartResponse.fromJson(Map json) { + success = json['success']; + message = json['message']; + if (json['data'] != null) { + data = []; + json['data'].forEach((v) { + data!.add(new CartModel.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + data['success'] = this.success; + data['message'] = this.message; + if (this.data != null) { + data['data'] = this.data!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class CartModel { + String? sId; + List? products; + String? user; + String? merchant; + int? total; + bool? isOrdered; + String? created; + int? iV; + + CartModel( + {this.sId, + this.products, + this.user, + this.merchant, + this.total, + this.isOrdered, + this.created, + this.iV}); + + CartModel.fromJson(Map json) { + sId = json['_id']; + if (json['products'] != null) { + products = []; + json['products'].forEach((v) { + products!.add(new Product.fromJson(v)); + }); + } + user = json['user']; + merchant = json['merchant']; + total = json['total']; + isOrdered = json['isOrdered']; + created = json['created']; + iV = json['__v']; + } + + Map toJson() { + final Map data = new Map(); + data['_id'] = this.sId; + if (this.products != null) { + data['products'] = this.products!.map((v) => v.toJson()).toList(); + } + data['user'] = this.user; + data['merchant'] = this.merchant; + data['total'] = this.total; + data['isOrdered'] = this.isOrdered; + data['created'] = this.created; + data['__v'] = this.iV; + return data; + } +} + diff --git a/lib/data/models/product.model.dart b/lib/data/models/product.model.dart index d727ed28..0dadbe59 100644 --- a/lib/data/models/product.model.dart +++ b/lib/data/models/product.model.dart @@ -227,93 +227,3 @@ class ProductParam { return data; } } - -class Cart { - int? total; - String? sId; - List? products; - String? user; - String? merchant; - String? created; - int? iV; - bool? isOrdered; - - Cart( - {this.total, - this.sId, - this.products, - this.user, - this.merchant, - this.created, - this.iV, - this.isOrdered}); - - Cart.fromJson(Map json) { - total = json['total']; - sId = json['_id']; - if (json['products'] != null) { - products = []; - json['products'].forEach((v) { - products!.add(new ProductResponse.fromJson(v)); - }); - } - user = json['user']; - merchant = json['merchant']; - created = json['created']; - iV = json['__v']; - isOrdered = json['isOrdered']; - } - - Map toJson() { - final Map data = new Map(); - data['total'] = this.total; - data['_id'] = this.sId; - if (this.products != null) { - data['products'] = this.products!.map((v) => v.toJson()).toList(); - } - data['user'] = this.user; - data['merchant'] = this.merchant; - data['created'] = this.created; - data['__v'] = this.iV; - data['isOrdered'] = this.isOrdered; - return data; - } -} - -class ProductResponse { - String? product; - int? quantity; - int? purchasePrice; - int? totalPrice; - String? merchant; - String? sId; - - ProductResponse( - {this.product, - this.quantity, - this.purchasePrice, - this.totalPrice, - this.merchant, - this.sId}); - - ProductResponse.fromJson(Map json) { - product = json['product']; - quantity = json['quantity']; - purchasePrice = json['purchasePrice']; - totalPrice = json['totalPrice']; - merchant = json['merchant']; - sId = json['_id']; - } - - Map toJson() { - final Map data = new Map(); - data['product'] = this.product; - data['quantity'] = this.quantity; - data['purchasePrice'] = this.purchasePrice; - data['totalPrice'] = this.totalPrice; - data['merchant'] = this.merchant; - data['_id'] = this.sId; - return data; - } -} - diff --git a/lib/data/provider/cart.provider.dart b/lib/data/provider/cart.provider.dart index 7e6ff69f..102fd93a 100644 --- a/lib/data/provider/cart.provider.dart +++ b/lib/data/provider/cart.provider.dart @@ -21,7 +21,8 @@ class CartProvider { final String deleteProductFromCartUrl = 'https://ecommerce-api-dut.herokuapp.com/api/cart/delete'; - + final String checkOutCartUrl = + 'https://ecommerce-api-dut.herokuapp.com/api/order/add'; Future getCarts() { return networkService.get(getAllCartUrl); @@ -42,4 +43,8 @@ class CartProvider { .delete('$deleteProductFromCartUrl/$cartId/$productId'); } + Future checkoutCart(String cartId, String merchant) { + return networkService + .post(checkOutCartUrl, data: {"cart": cartId, "merchant": merchant}); + } } diff --git a/lib/data/repository/cart.repository.dart b/lib/data/repository/cart.repository.dart index eb757915..023557c0 100644 --- a/lib/data/repository/cart.repository.dart +++ b/lib/data/repository/cart.repository.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/data/models/address.model.dart'; +import 'package:ecommerce_int2/data/models/cart.model.dart'; import 'package:ecommerce_int2/data/models/product.model.dart'; import 'package:ecommerce_int2/data/provider/cart.provider.dart'; @@ -7,15 +7,13 @@ class CartRepository { CartRepository(this.provider); - Future> getCarts() async { + Future> getCarts() async { final response = await provider.getCarts(); if (response.statusCode != 200) { throw Exception("Get cart failed"); } - final result = (response.body['addresses'] as List) - .map((i) => Address.fromJson(i)) - .toList(); - return result; + final result = CartResponse.fromJson(response.body); + return result.data ?? []; } Future addProduct(AddProductParam param) async { @@ -42,5 +40,9 @@ class CartRepository { } } - + Future checkOutCart(List carts) async { + for(CartModel cart in carts) { + await provider.checkoutCart(cart.sId!, cart.merchant!); + } + } } diff --git a/lib/screens/shop/cart.controller.dart b/lib/screens/shop/cart.controller.dart index b523ed3d..17a75e9d 100644 --- a/lib/screens/shop/cart.controller.dart +++ b/lib/screens/shop/cart.controller.dart @@ -1,4 +1,5 @@ import 'package:card_swiper/card_swiper.dart'; +import 'package:ecommerce_int2/data/models/cart.model.dart'; import 'package:ecommerce_int2/data/models/product.model.dart'; import 'package:ecommerce_int2/data/repository/cart.repository.dart'; import 'package:ecommerce_int2/screens/address/add_address_page.dart'; @@ -12,10 +13,10 @@ class CartController extends GetxController { CartController(this.repository); - String? id; - List products = []; + List? carts; + String get total { int result = 0; products.forEach((element) { @@ -24,13 +25,19 @@ class CartController extends GetxController { return '$result VND'; } + void getCart() { + repository.getCarts().then((value) => carts = value); + } + void remove(Product product) { - if (id == null) { + CartModel? cart = carts! + .firstWhereOrNull((element) => element.products!.contains(product)); + if (cart == null) { MessageDialog.showToast("There is something wrong!!"); return; } - repository.deleteProduct(id!, product.sId!); - products.remove(product); + repository.deleteProduct(cart.sId!, product.sId!); + cart.products!.remove(product); update(); } @@ -43,10 +50,14 @@ class CartController extends GetxController { merchant: product.merchant, quantity: quantity) ]); - // final String cartId = await repository.addProduct(param); + final String cartId = await repository.addProduct(param); MessageDialog.showToast("Added product to cart"); - // id = cartId; - products.add(product); + int index = carts!.indexWhere((element) => element.sId == cartId); + if (index != -1) { + carts![index].products!.add(product); + } else { + carts!.add(CartModel(sId: cartId, products: [product])); + } update(); } on Exception catch (e) { print(e); @@ -54,6 +65,7 @@ class CartController extends GetxController { } void checkOut() async { - Get.to(AddAddressPage(), arguments: id); + repository.checkOutCart(carts!); + Get.to(AddAddressPage()); } } From f68bb55bd282d96b43e92dc43613222c32b8f394 Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Fri, 3 Jun 2022 11:41:37 +0700 Subject: [PATCH 25/49] Complete order flow --- lib/data/models/order.model.dart | 4 ++-- lib/data/provider/order.provider.dart | 4 ++-- lib/data/repository/cart.repository.dart | 9 +++++++-- lib/data/repository/order.repository.dart | 4 ++-- lib/screens/address/add_address_page.dart | 3 ++- lib/screens/address/address.controller.dart | 21 ++++++++++++++++----- lib/screens/shop/cart.controller.dart | 4 ++-- 7 files changed, 33 insertions(+), 16 deletions(-) diff --git a/lib/data/models/order.model.dart b/lib/data/models/order.model.dart index f78be6a3..0578b1c1 100644 --- a/lib/data/models/order.model.dart +++ b/lib/data/models/order.model.dart @@ -8,7 +8,7 @@ class OrderResponse { OrderResponse.fromJson(Map json) { success = json['success']; message = json['message']; - order = json['order'] != null ? new Order.fromJson(json['order']) : null; + order = json['data'] != null ? new Order.fromJson(json['data']) : null; } Map toJson() { @@ -16,7 +16,7 @@ class OrderResponse { data['success'] = this.success; data['message'] = this.message; if (this.order != null) { - data['order'] = this.order!.toJson(); + data['data'] = this.order!.toJson(); } return data; } diff --git a/lib/data/provider/order.provider.dart b/lib/data/provider/order.provider.dart index e7abfbd4..05d0d6a7 100644 --- a/lib/data/provider/order.provider.dart +++ b/lib/data/provider/order.provider.dart @@ -21,9 +21,9 @@ class OrderProvider { data: {"cart": cartId, "merchant": "626e237ef4224ee4107039b9"}); } - Future completeOrder( + Future completeOrder( String orderId, CompleteOrderParam param) { - return networkService.put(completeOrderUrl, data: param.toJson()); + return networkService.put('$completeOrderUrl/$orderId/', data: param.toJson()); } Future makePayment( diff --git a/lib/data/repository/cart.repository.dart b/lib/data/repository/cart.repository.dart index 023557c0..c995a7e6 100644 --- a/lib/data/repository/cart.repository.dart +++ b/lib/data/repository/cart.repository.dart @@ -1,4 +1,5 @@ import 'package:ecommerce_int2/data/models/cart.model.dart'; +import 'package:ecommerce_int2/data/models/order.model.dart'; import 'package:ecommerce_int2/data/models/product.model.dart'; import 'package:ecommerce_int2/data/provider/cart.provider.dart'; @@ -40,9 +41,13 @@ class CartRepository { } } - Future checkOutCart(List carts) async { + Future> checkOutCart(List carts) async { + List orderIds = []; for(CartModel cart in carts) { - await provider.checkoutCart(cart.sId!, cart.merchant!); + final response = await provider.checkoutCart(cart.sId!, cart.merchant!); + OrderResponse order = OrderResponse.fromJson(response.body); + orderIds.add(order.order!.sId!); } + return orderIds; } } diff --git a/lib/data/repository/order.repository.dart b/lib/data/repository/order.repository.dart index 6d0ed885..5a5bf0ac 100644 --- a/lib/data/repository/order.repository.dart +++ b/lib/data/repository/order.repository.dart @@ -6,8 +6,8 @@ class OrderRepository { OrderRepository(this.provider); - Future completeOrder(CompleteOrderParam param) async { - final response = await provider.completeOrder(param); + Future completeOrder(String orderId, CompleteOrderParam param) async { + final response = await provider.completeOrder(orderId, param); if (response.statusCode != 200) { throw Exception("Complete order failed"); } diff --git a/lib/screens/address/add_address_page.dart b/lib/screens/address/add_address_page.dart index b1c0a9a1..bd3d3a3f 100755 --- a/lib/screens/address/add_address_page.dart +++ b/lib/screens/address/add_address_page.dart @@ -1,4 +1,5 @@ import 'package:ecommerce_int2/data/repository/order.repository.dart'; +import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/data/repository/address.repository.dart'; import 'package:ecommerce_int2/screens/address/address_form.dart'; @@ -45,7 +46,7 @@ class AddAddressPage extends StatelessWidget { Widget build(BuildContext context) { return GetBuilder( init: AddressController( - Get.find(), Get.find()), + Get.find(), Get.find(), Get.find()), builder: (controller) => Scaffold( backgroundColor: Colors.grey[100], appBar: AppBar( diff --git a/lib/screens/address/address.controller.dart b/lib/screens/address/address.controller.dart index eb788b21..53114042 100644 --- a/lib/screens/address/address.controller.dart +++ b/lib/screens/address/address.controller.dart @@ -3,16 +3,18 @@ import 'package:ecommerce_int2/data/models/order.model.dart'; import 'package:ecommerce_int2/data/repository/address.repository.dart'; import 'package:ecommerce_int2/data/repository/order.repository.dart'; import 'package:ecommerce_int2/screens/tracking_page.dart'; +import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:ecommerce_int2/utils/message_dialog.dart'; import 'package:get/get.dart'; class AddressController extends GetxController { final AddressRepository repository; final OrderRepository orderRepository; + final AuthService authService; - AddressController(this.repository, this.orderRepository); + AddressController(this.repository, this.orderRepository, this.authService); - String? cartId; + List? orderIds; List
addresses =
[Address()]; @@ -29,8 +31,8 @@ class AddressController extends GetxController { void getArgument() { final arg = Get.arguments; - if (arg != null && arg is String) { - cartId = arg; + if (arg != null && arg is List) { + orderIds = arg; } } @@ -66,9 +68,18 @@ class AddressController extends GetxController { } void checkOut() async { + if (orderIds == null) { + Get.back(); + return; + } try { MessageDialog.showLoading(); - final Order order = await orderRepository.checkOut(cartId!); + for (String order in orderIds!) { + await orderRepository.completeOrder(order, CompleteOrderParam( + address: selectedAddress.id, + phoneNumber: authService.userModel!.email, + payment: 'CASH')); + } MessageDialog.hideLoading(); Get.to(TrackingPage()); } on Exception catch (e) { diff --git a/lib/screens/shop/cart.controller.dart b/lib/screens/shop/cart.controller.dart index 17a75e9d..00b95162 100644 --- a/lib/screens/shop/cart.controller.dart +++ b/lib/screens/shop/cart.controller.dart @@ -65,7 +65,7 @@ class CartController extends GetxController { } void checkOut() async { - repository.checkOutCart(carts!); - Get.to(AddAddressPage()); + final List orderIds = await repository.checkOutCart(carts!); + Get.to(AddAddressPage(), arguments: orderIds); } } From 9cda5889661e74f4635cde2e115e0119515dbe66 Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Fri, 3 Jun 2022 16:53:12 +0700 Subject: [PATCH 26/49] Add make payment to order --- lib/data/models/order.model.dart | 199 ++++++++++++++++++ lib/data/provider/order.provider.dart | 27 ++- lib/data/repository/order.repository.dart | 28 ++- lib/screens/address/address.controller.dart | 2 +- lib/screens/notifications_page.dart | 2 +- lib/screens/profile_page.dart | 2 +- lib/screens/tracking/order.controller.dart | 31 +++ .../tracking/order_detail.controller.dart | 38 ++++ lib/screens/{ => tracking}/tracking_page.dart | 0 9 files changed, 312 insertions(+), 17 deletions(-) create mode 100644 lib/screens/tracking/order.controller.dart create mode 100644 lib/screens/tracking/order_detail.controller.dart rename lib/screens/{ => tracking}/tracking_page.dart (100%) mode change 100755 => 100644 diff --git a/lib/data/models/order.model.dart b/lib/data/models/order.model.dart index 0578b1c1..c51acb83 100644 --- a/lib/data/models/order.model.dart +++ b/lib/data/models/order.model.dart @@ -188,3 +188,202 @@ class OrderDoc { } } +class AllOrderResponse { + bool? success; + List? orders; + + AllOrderResponse({this.success, this.orders}); + + AllOrderResponse.fromJson(Map json) { + success = json['success']; + if (json['orders'] != null) { + orders = []; + json['orders'].forEach((v) { + orders!.add(new Order.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + data['success'] = this.success; + if (this.orders != null) { + data['orders'] = this.orders!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class DetailOrderResponse { + bool? success; + OrderDocDetail? orderDoc; + + DetailOrderResponse({this.success, this.orderDoc}); + + DetailOrderResponse.fromJson(Map json) { + success = json['success']; + orderDoc = json['orderDoc'] != null + ? new OrderDocDetail.fromJson(json['orderDoc']) + : null; + } + + Map toJson() { + final Map data = new Map(); + data['success'] = this.success; + if (this.orderDoc != null) { + data['orderDoc'] = this.orderDoc!.toJson(); + } + return data; + } +} + +class OrderDocDetail { + String? sId; + Cart? cart; + String? user; + String? merchant; + String? payment; + String? phoneNumber; + String? status; + String? paymentStatus; + String? created; + int? iV; + String? address; + + OrderDocDetail( + {this.sId, + this.cart, + this.user, + this.merchant, + this.payment, + this.phoneNumber, + this.status, + this.paymentStatus, + this.created, + this.iV, + this.address}); + + OrderDocDetail.fromJson(Map json) { + sId = json['_id']; + cart = json['cart'] != null ? new Cart.fromJson(json['cart']) : null; + user = json['user']; + merchant = json['merchant']; + payment = json['payment']; + phoneNumber = json['phoneNumber']; + status = json['status']; + paymentStatus = json['paymentStatus']; + created = json['created']; + iV = json['__v']; + address = json['address']; + } + + Map toJson() { + final Map data = new Map(); + data['_id'] = this.sId; + if (this.cart != null) { + data['cart'] = this.cart!.toJson(); + } + data['user'] = this.user; + data['merchant'] = this.merchant; + data['payment'] = this.payment; + data['phoneNumber'] = this.phoneNumber; + data['status'] = this.status; + data['paymentStatus'] = this.paymentStatus; + data['created'] = this.created; + data['__v'] = this.iV; + data['address'] = this.address; + return data; + } +} + +class Cart { + String? sId; + List? products; + int? total; + + Cart({this.sId, this.products, this.total}); + + Cart.fromJson(Map json) { + sId = json['_id']; + if (json['products'] != null) { + products = []; + json['products'].forEach((v) { + products!.add(new Products.fromJson(v)); + }); + } + total = json['total']; + } + + Map toJson() { + final Map data = new Map(); + data['_id'] = this.sId; + if (this.products != null) { + data['products'] = this.products!.map((v) => v.toJson()).toList(); + } + data['total'] = this.total; + return data; + } +} + +class Products { + Product? product; + int? quantity; + int? purchasePrice; + int? totalPrice; + String? merchant; + String? sId; + + Products( + {this.product, + this.quantity, + this.purchasePrice, + this.totalPrice, + this.merchant, + this.sId}); + + Products.fromJson(Map json) { + product = + json['product'] != null ? new Product.fromJson(json['product']) : null; + quantity = json['quantity']; + purchasePrice = json['purchasePrice']; + totalPrice = json['totalPrice']; + merchant = json['merchant']; + sId = json['_id']; + } + + Map toJson() { + final Map data = new Map(); + if (this.product != null) { + data['product'] = this.product!.toJson(); + } + data['quantity'] = this.quantity; + data['purchasePrice'] = this.purchasePrice; + data['totalPrice'] = this.totalPrice; + data['merchant'] = this.merchant; + data['_id'] = this.sId; + return data; + } +} + +class Product { + String? sId; + String? name; + String? imageUrl; + + Product({this.sId, this.name, this.imageUrl}); + + Product.fromJson(Map json) { + sId = json['_id']; + name = json['name']; + imageUrl = json['imageUrl']; + } + + Map toJson() { + final Map data = new Map(); + data['_id'] = this.sId; + data['name'] = this.name; + data['imageUrl'] = this.imageUrl; + return data; + } +} + diff --git a/lib/data/provider/order.provider.dart b/lib/data/provider/order.provider.dart index 05d0d6a7..cdace98f 100644 --- a/lib/data/provider/order.provider.dart +++ b/lib/data/provider/order.provider.dart @@ -9,26 +9,39 @@ class OrderProvider { OrderProvider(this.networkService); + final String orderUrl = 'https://ecommerce-api-dut.herokuapp.com/api/order'; + final String completeOrderUrl = 'https://ecommerce-api-dut.herokuapp.com/api/order/'; - final String checkOutCartUrl = + final String checkOutCartUrl = 'https://ecommerce-api-dut.herokuapp.com/api/order/add'; + final String cancleOrderUrl = + 'https://ecommerce-api-dut.herokuapp.com/api/order'; + + Future getAllOrders() { + return networkService.get(orderUrl); + } - Future checkOut(String cartId) { return networkService.post(checkOutCartUrl, data: {"cart": cartId, "merchant": "626e237ef4224ee4107039b9"}); } - Future completeOrder( String orderId, - CompleteOrderParam param) { - return networkService.put('$completeOrderUrl/$orderId/', data: param.toJson()); + Future completeOrder(String orderId, CompleteOrderParam param) { + return networkService.put('$completeOrderUrl/$orderId/', + data: param.toJson()); } - Future makePayment( - String orderId) { + Future makePayment(String orderId) { return networkService.post('$completeOrderUrl/$orderId/pay'); } + Future cancleOrder(String orderId) { + return networkService.delete('$cancleOrder/$orderId/cancel'); + } + + Future getOrderDetail(String orderId) { + return networkService.delete('$orderUrl/$orderId'); + } } diff --git a/lib/data/repository/order.repository.dart b/lib/data/repository/order.repository.dart index 5a5bf0ac..d852f7c8 100644 --- a/lib/data/repository/order.repository.dart +++ b/lib/data/repository/order.repository.dart @@ -6,6 +6,15 @@ class OrderRepository { OrderRepository(this.provider); + Future> getAllOrders() async { + final response = await provider.getAllOrders(); + if (response.statusCode != 200) { + throw Exception("Complete order failed"); + } + final result = AllOrderResponse.fromJson(response.body); + return result.orders ?? []; + } + Future completeOrder(String orderId, CompleteOrderParam param) async { final response = await provider.completeOrder(orderId, param); if (response.statusCode != 200) { @@ -24,15 +33,20 @@ class OrderRepository { return 'href'; } - Future checkOut( - String cartId) async { - final response = - await provider.checkOut(cartId); + Future cancleOrder(String orderId) async { + final response = await provider.cancleOrder(orderId); if (response.statusCode != 200) { - throw Exception("Check out cart failed"); + throw Exception("Cancel order failed"); } + return; + } - final result = OrderResponse.fromJson(response.body); - return result.order!; + Future getOrderDetail(String orderId) async { + final response = await provider.getOrderDetail(orderId); + if (response.statusCode != 200) { + throw Exception("Cancel order failed"); + } + final res = DetailOrderResponse.fromJson(response.body); + return res.orderDoc!; } } diff --git a/lib/screens/address/address.controller.dart b/lib/screens/address/address.controller.dart index 53114042..5d640429 100644 --- a/lib/screens/address/address.controller.dart +++ b/lib/screens/address/address.controller.dart @@ -2,7 +2,7 @@ import 'package:ecommerce_int2/data/models/address.model.dart'; import 'package:ecommerce_int2/data/models/order.model.dart'; import 'package:ecommerce_int2/data/repository/address.repository.dart'; import 'package:ecommerce_int2/data/repository/order.repository.dart'; -import 'package:ecommerce_int2/screens/tracking_page.dart'; +import 'package:ecommerce_int2/screens/tracking/tracking_page.dart'; import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:ecommerce_int2/utils/message_dialog.dart'; import 'package:get/get.dart'; diff --git a/lib/screens/notifications_page.dart b/lib/screens/notifications_page.dart index cb35d96b..7602ad12 100755 --- a/lib/screens/notifications_page.dart +++ b/lib/screens/notifications_page.dart @@ -1,6 +1,6 @@ import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/rating/rating_page.dart'; -import 'package:ecommerce_int2/screens/tracking_page.dart'; +import 'package:ecommerce_int2/screens/tracking/tracking_page.dart'; import 'package:flutter/material.dart'; class NotificationsPage extends StatelessWidget { diff --git a/lib/screens/profile_page.dart b/lib/screens/profile_page.dart index 3dd96602..337a4f39 100755 --- a/lib/screens/profile_page.dart +++ b/lib/screens/profile_page.dart @@ -2,7 +2,7 @@ import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/faq_page.dart'; import 'package:ecommerce_int2/screens/payment/payment_page.dart'; import 'package:ecommerce_int2/screens/settings/settings_page.dart'; -import 'package:ecommerce_int2/screens/tracking_page.dart'; +import 'package:ecommerce_int2/screens/tracking/tracking_page.dart'; import 'package:ecommerce_int2/screens/wallet/wallet_page.dart'; import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:flutter/material.dart'; diff --git a/lib/screens/tracking/order.controller.dart b/lib/screens/tracking/order.controller.dart new file mode 100644 index 00000000..e2626743 --- /dev/null +++ b/lib/screens/tracking/order.controller.dart @@ -0,0 +1,31 @@ +import 'package:card_swiper/card_swiper.dart'; +import 'package:ecommerce_int2/data/models/order.model.dart'; +import 'package:ecommerce_int2/data/repository/order.repository.dart'; +import 'package:ecommerce_int2/utils/message_dialog.dart'; +import 'package:get/get.dart'; + +class OrderController extends GetxController { + final OrderRepository repository; + + final SwiperController swiperController = SwiperController(); + + OrderController(this.repository); + + List orders = []; + + @override + void onInit() { + getAllOrders(); + super.onInit(); + } + + void getAllOrders() { + repository.getAllOrders().then((value) => orders = value); + } + + void remove(Order order) { + orders.remove(order); + update(); + } + +} diff --git a/lib/screens/tracking/order_detail.controller.dart b/lib/screens/tracking/order_detail.controller.dart new file mode 100644 index 00000000..56f639c1 --- /dev/null +++ b/lib/screens/tracking/order_detail.controller.dart @@ -0,0 +1,38 @@ +import 'package:card_swiper/card_swiper.dart'; +import 'package:ecommerce_int2/data/models/order.model.dart'; +import 'package:ecommerce_int2/data/repository/order.repository.dart'; +import 'package:ecommerce_int2/screens/tracking/order.controller.dart'; +import 'package:ecommerce_int2/utils/message_dialog.dart'; +import 'package:get/get.dart'; + +class OrderDetailController extends GetxController { + final OrderRepository repository; + + final OrderController orderController; + + final String orderDetail; + + OrderDetailController(this.repository, this.orderDetail, this.orderController); + + OrderDocDetail? detail; + + + void getOrder() { + repository.getOrderDetail(orderDetail).then((value) => detail = value); + } + + void remove(Order order) { + repository.cancleOrder(order.sId!); + orderController.remove(order); + Get.back(); + } + + void makePayment(Order order) async { + MessageDialog.showLoading(); + await repository.makePayment(order.sId!); + await repository.getOrderDetail(orderDetail).then((value) => detail = value); + orderController.getAllOrders(); + MessageDialog.hideLoading(); + } + +} diff --git a/lib/screens/tracking_page.dart b/lib/screens/tracking/tracking_page.dart old mode 100755 new mode 100644 similarity index 100% rename from lib/screens/tracking_page.dart rename to lib/screens/tracking/tracking_page.dart From 43893a462082500789e56aa7ddeba471edc3e6ea Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Sat, 4 Jun 2022 17:09:42 +0700 Subject: [PATCH 27/49] Complete order flow --- lib/data/models/order.model.dart | 10 +++++----- lib/data/models/product.model.dart | 8 ++++++++ lib/screens/address/add_address_page.dart | 1 - lib/screens/address/address.controller.dart | 1 + .../product/components/shop_product.dart | 2 +- lib/screens/shop/cart.controller.dart | 19 ++++++++++++++++--- lib/screens/shop/check_out_page.dart | 3 +++ .../shop/components/shop_item_list.dart | 2 +- 8 files changed, 35 insertions(+), 11 deletions(-) diff --git a/lib/data/models/order.model.dart b/lib/data/models/order.model.dart index c51acb83..d33e8eed 100644 --- a/lib/data/models/order.model.dart +++ b/lib/data/models/order.model.dart @@ -8,7 +8,7 @@ class OrderResponse { OrderResponse.fromJson(Map json) { success = json['success']; message = json['message']; - order = json['data'] != null ? new Order.fromJson(json['data']) : null; + order = json['order'] != null ? new Order.fromJson(json['order']) : null; } Map toJson() { @@ -16,7 +16,7 @@ class OrderResponse { data['success'] = this.success; data['message'] = this.message; if (this.order != null) { - data['data'] = this.order!.toJson(); + data['order'] = this.order!.toJson(); } return data; } @@ -115,8 +115,8 @@ class CompleteOrderResponse { CompleteOrderResponse.fromJson(Map json) { success = json['success']; message = json['message']; - orderDoc = json['orderDoc'] != null - ? new OrderDoc.fromJson(json['orderDoc']) + orderDoc = json['data'] != null + ? new OrderDoc.fromJson(json['data']) : null; } @@ -125,7 +125,7 @@ class CompleteOrderResponse { data['success'] = this.success; data['message'] = this.message; if (this.orderDoc != null) { - data['orderDoc'] = this.orderDoc!.toJson(); + data['data'] = this.orderDoc!.toJson(); } return data; } diff --git a/lib/data/models/product.model.dart b/lib/data/models/product.model.dart index 0dadbe59..6b6810e6 100644 --- a/lib/data/models/product.model.dart +++ b/lib/data/models/product.model.dart @@ -40,6 +40,8 @@ class Product { String? description; int? quantity; int? price; + int? purchasePrice; + int? totalPrice; bool? isActive; String? merchant; String? category; @@ -59,6 +61,8 @@ class Product { this.description, this.quantity, this.price, + this.purchasePrice, + this.totalPrice, this.isActive, this.merchant, this.category, @@ -78,6 +82,8 @@ class Product { description = json['description']; quantity = json['quantity']; price = json['price']; + purchasePrice = json['purchasePrice']; + totalPrice = json['totalPrice']; isActive = json['isActive']; merchant = json['merchant']; category = json['category']; @@ -99,6 +105,8 @@ class Product { data['description'] = this.description; data['quantity'] = this.quantity; data['price'] = this.price; + data['purchasePrice'] = this.purchasePrice; + data['totalPrice'] = this.totalPrice; data['isActive'] = this.isActive; data['merchant'] = this.merchant; data['category'] = this.category; diff --git a/lib/screens/address/add_address_page.dart b/lib/screens/address/add_address_page.dart index bd3d3a3f..b3e8d699 100755 --- a/lib/screens/address/add_address_page.dart +++ b/lib/screens/address/add_address_page.dart @@ -16,7 +16,6 @@ class AddAddressPage extends StatelessWidget { onTap: () { controller.updateCurrentAddress(address.text, city.text); controller.submitAddress(); - Get.to(() => SelectCardPage()); }, child: Container( height: 80, diff --git a/lib/screens/address/address.controller.dart b/lib/screens/address/address.controller.dart index 5d640429..50bb5f82 100644 --- a/lib/screens/address/address.controller.dart +++ b/lib/screens/address/address.controller.dart @@ -65,6 +65,7 @@ class AddressController extends GetxController { .updateAddress(selectedAddress) .then((value) => null, onError: (e) => null); } + checkOut(); } void checkOut() async { diff --git a/lib/screens/product/components/shop_product.dart b/lib/screens/product/components/shop_product.dart index 9002e44e..c8b82eaa 100755 --- a/lib/screens/product/components/shop_product.dart +++ b/lib/screens/product/components/shop_product.dart @@ -73,7 +73,7 @@ class ShopProductDisplay extends StatelessWidget { height: 80, width: 80, child: Image.network( - product.imageUrl!, + product.imageUrl ?? '', fit: BoxFit.contain, )), ), diff --git a/lib/screens/shop/cart.controller.dart b/lib/screens/shop/cart.controller.dart index 00b95162..757fd746 100644 --- a/lib/screens/shop/cart.controller.dart +++ b/lib/screens/shop/cart.controller.dart @@ -13,20 +13,33 @@ class CartController extends GetxController { CartController(this.repository); - List products = []; + List get products { + if(carts == null) return []; + List products = []; + for(CartModel cart in carts!) { + products.addAll(cart.products!); + } + return products; + } List? carts; + @override + onInit() { + super.onInit(); + } + String get total { int result = 0; products.forEach((element) { - result += element.price!; + result += element.totalPrice ?? 0; }); return '$result VND'; } - void getCart() { + Future getCart() async { repository.getCarts().then((value) => carts = value); + update(); } void remove(Product product) { diff --git a/lib/screens/shop/check_out_page.dart b/lib/screens/shop/check_out_page.dart index b5d6c00d..3b5105b9 100755 --- a/lib/screens/shop/check_out_page.dart +++ b/lib/screens/shop/check_out_page.dart @@ -59,6 +59,9 @@ class CheckOutPage extends StatelessWidget { constraints: BoxConstraints(minHeight: constraints.maxHeight), child: GetBuilder( init: CartController(Get.find()), + initState: (state) { + Get.find().getCart(); + }, builder: (controller) => Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/lib/screens/shop/components/shop_item_list.dart b/lib/screens/shop/components/shop_item_list.dart index f4a61a9a..3781717d 100755 --- a/lib/screens/shop/components/shop_item_list.dart +++ b/lib/screens/shop/components/shop_item_list.dart @@ -66,7 +66,7 @@ class _ShopItemListState extends State { children: [ ColorOption(Colors.red), Text( - '\$${widget.product.price}', + '\$${widget.product.price ?? widget.product.purchasePrice ?? 0}', textAlign: TextAlign.center, style: TextStyle( color: darkGrey, From 34758b2cffa8b966322436d062e968259f73efd2 Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Sun, 5 Jun 2022 10:54:52 +0700 Subject: [PATCH 28/49] Update your order page --- lib/data/models/order.model.dart | 116 ++---------- lib/data/models/product.model.dart | 6 +- lib/data/provider/order.provider.dart | 2 +- lib/screens/main/components/product_list.dart | 6 +- lib/screens/tracking/order.controller.dart | 21 ++- .../tracking/order_detail.controller.dart | 37 ++-- lib/screens/tracking/order_detail.view.dart | 141 +++++++++++++++ lib/screens/tracking/tracking_page.dart | 168 +++++++----------- 8 files changed, 265 insertions(+), 232 deletions(-) create mode 100644 lib/screens/tracking/order_detail.view.dart diff --git a/lib/data/models/order.model.dart b/lib/data/models/order.model.dart index d33e8eed..f5fc9872 100644 --- a/lib/data/models/order.model.dart +++ b/lib/data/models/order.model.dart @@ -1,3 +1,5 @@ +import 'package:ecommerce_int2/data/models/cart.model.dart'; + class OrderResponse { bool? success; String? message; @@ -196,9 +198,9 @@ class AllOrderResponse { AllOrderResponse.fromJson(Map json) { success = json['success']; - if (json['orders'] != null) { + if (json['data'] != null) { orders = []; - json['orders'].forEach((v) { + json['data'].forEach((v) { orders!.add(new Order.fromJson(v)); }); } @@ -208,7 +210,7 @@ class AllOrderResponse { final Map data = new Map(); data['success'] = this.success; if (this.orders != null) { - data['orders'] = this.orders!.map((v) => v.toJson()).toList(); + data['data'] = this.orders!.map((v) => v.toJson()).toList(); } return data; } @@ -222,8 +224,8 @@ class DetailOrderResponse { DetailOrderResponse.fromJson(Map json) { success = json['success']; - orderDoc = json['orderDoc'] != null - ? new OrderDocDetail.fromJson(json['orderDoc']) + orderDoc = json['data'] != null + ? new OrderDocDetail.fromJson(json['data']) : null; } @@ -231,7 +233,7 @@ class DetailOrderResponse { final Map data = new Map(); data['success'] = this.success; if (this.orderDoc != null) { - data['orderDoc'] = this.orderDoc!.toJson(); + data['data'] = this.orderDoc!.toJson(); } return data; } @@ -239,7 +241,7 @@ class DetailOrderResponse { class OrderDocDetail { String? sId; - Cart? cart; + CartModel? cart; String? user; String? merchant; String? payment; @@ -250,6 +252,8 @@ class OrderDocDetail { int? iV; String? address; + bool get isPayWithCash => payment == 'CASH'; + OrderDocDetail( {this.sId, this.cart, @@ -265,8 +269,8 @@ class OrderDocDetail { OrderDocDetail.fromJson(Map json) { sId = json['_id']; - cart = json['cart'] != null ? new Cart.fromJson(json['cart']) : null; - user = json['user']; + cart = json['cart'] != null ? new CartModel.fromJson(json['cart']) : null; + user = json['user']['_id']; merchant = json['merchant']; payment = json['payment']; phoneNumber = json['phoneNumber']; @@ -294,96 +298,4 @@ class OrderDocDetail { data['address'] = this.address; return data; } -} - -class Cart { - String? sId; - List? products; - int? total; - - Cart({this.sId, this.products, this.total}); - - Cart.fromJson(Map json) { - sId = json['_id']; - if (json['products'] != null) { - products = []; - json['products'].forEach((v) { - products!.add(new Products.fromJson(v)); - }); - } - total = json['total']; - } - - Map toJson() { - final Map data = new Map(); - data['_id'] = this.sId; - if (this.products != null) { - data['products'] = this.products!.map((v) => v.toJson()).toList(); - } - data['total'] = this.total; - return data; - } -} - -class Products { - Product? product; - int? quantity; - int? purchasePrice; - int? totalPrice; - String? merchant; - String? sId; - - Products( - {this.product, - this.quantity, - this.purchasePrice, - this.totalPrice, - this.merchant, - this.sId}); - - Products.fromJson(Map json) { - product = - json['product'] != null ? new Product.fromJson(json['product']) : null; - quantity = json['quantity']; - purchasePrice = json['purchasePrice']; - totalPrice = json['totalPrice']; - merchant = json['merchant']; - sId = json['_id']; - } - - Map toJson() { - final Map data = new Map(); - if (this.product != null) { - data['product'] = this.product!.toJson(); - } - data['quantity'] = this.quantity; - data['purchasePrice'] = this.purchasePrice; - data['totalPrice'] = this.totalPrice; - data['merchant'] = this.merchant; - data['_id'] = this.sId; - return data; - } -} - -class Product { - String? sId; - String? name; - String? imageUrl; - - Product({this.sId, this.name, this.imageUrl}); - - Product.fromJson(Map json) { - sId = json['_id']; - name = json['name']; - imageUrl = json['imageUrl']; - } - - Map toJson() { - final Map data = new Map(); - data['_id'] = this.sId; - data['name'] = this.name; - data['imageUrl'] = this.imageUrl; - return data; - } -} - +} \ No newline at end of file diff --git a/lib/data/models/product.model.dart b/lib/data/models/product.model.dart index 6b6810e6..50ec2fcf 100644 --- a/lib/data/models/product.model.dart +++ b/lib/data/models/product.model.dart @@ -75,9 +75,9 @@ class Product { this.averageRating}); Product.fromJson(Map json) { - sId = json['_id']; - name = json['name']; - imageUrl = json['imageUrl']; + sId = json['_id'] ?? json['product']['_id']; + name = json['name'] ?? json['product']['name']; + imageUrl = json['imageUrl'] ?? json['product']['imageUrl']; imageKey = json['imageKey']; description = json['description']; quantity = json['quantity']; diff --git a/lib/data/provider/order.provider.dart b/lib/data/provider/order.provider.dart index cdace98f..bdf218c9 100644 --- a/lib/data/provider/order.provider.dart +++ b/lib/data/provider/order.provider.dart @@ -42,6 +42,6 @@ class OrderProvider { } Future getOrderDetail(String orderId) { - return networkService.delete('$orderUrl/$orderId'); + return networkService.get('$orderUrl/$orderId'); } } diff --git a/lib/screens/main/components/product_list.dart b/lib/screens/main/components/product_list.dart index c6fb047f..87f4265c 100755 --- a/lib/screens/main/components/product_list.dart +++ b/lib/screens/main/components/product_list.dart @@ -112,7 +112,7 @@ class ProductCard extends StatelessWidget { child: Stack( children: [ Container( - margin: const EdgeInsets.only(left: 30), + margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), height: height, width: width, decoration: BoxDecoration( @@ -152,7 +152,7 @@ class ProductCard extends StatelessWidget { color: Color.fromRGBO(224, 69, 10, 1), ), child: Text( - '\$${product.price}', + '\$${product.price ?? product.purchasePrice ?? 0}', style: TextStyle( color: Colors.white, fontSize: 18, @@ -168,7 +168,7 @@ class ProductCard extends StatelessWidget { Positioned( child: Hero( tag: product.imageUrl!, - child: Image.asset( + child: Image.network( product.imageUrl!, height: height / 1.7, width: width / 1.4, diff --git a/lib/screens/tracking/order.controller.dart b/lib/screens/tracking/order.controller.dart index e2626743..e93d4b84 100644 --- a/lib/screens/tracking/order.controller.dart +++ b/lib/screens/tracking/order.controller.dart @@ -1,6 +1,7 @@ import 'package:card_swiper/card_swiper.dart'; import 'package:ecommerce_int2/data/models/order.model.dart'; import 'package:ecommerce_int2/data/repository/order.repository.dart'; +import 'package:ecommerce_int2/screens/tracking/order_detail.view.dart'; import 'package:ecommerce_int2/utils/message_dialog.dart'; import 'package:get/get.dart'; @@ -14,18 +15,26 @@ class OrderController extends GetxController { List orders = []; @override - void onInit() { + void onReady() { getAllOrders(); - super.onInit(); + super.onReady(); } void getAllOrders() { - repository.getAllOrders().then((value) => orders = value); + MessageDialog.showLoading(); + repository.getAllOrders().then((value) { + orders = value; + update(); + MessageDialog.hideLoading(); + }); } - void remove(Order order) { - orders.remove(order); - update(); + void getOrderDetail(Order order) { + Get.to(() => OrderDetail(orderId: order.sId!)); } + void remove(String orderId) { + orders.removeWhere((element) => element.sId == orderId); + update(); + } } diff --git a/lib/screens/tracking/order_detail.controller.dart b/lib/screens/tracking/order_detail.controller.dart index 56f639c1..0a9fedf2 100644 --- a/lib/screens/tracking/order_detail.controller.dart +++ b/lib/screens/tracking/order_detail.controller.dart @@ -1,4 +1,3 @@ -import 'package:card_swiper/card_swiper.dart'; import 'package:ecommerce_int2/data/models/order.model.dart'; import 'package:ecommerce_int2/data/repository/order.repository.dart'; import 'package:ecommerce_int2/screens/tracking/order.controller.dart'; @@ -12,27 +11,43 @@ class OrderDetailController extends GetxController { final String orderDetail; - OrderDetailController(this.repository, this.orderDetail, this.orderController); + OrderDetailController( + this.repository, this.orderDetail, this.orderController); OrderDocDetail? detail; + @override + void onReady() { + getOrder(); + super.onReady(); + } void getOrder() { - repository.getOrderDetail(orderDetail).then((value) => detail = value); + MessageDialog.showLoading(); + repository.getOrderDetail(orderDetail).then((value) { + detail = value; + MessageDialog.hideLoading(); + update(); + }); } - void remove(Order order) { - repository.cancleOrder(order.sId!); - orderController.remove(order); + void remove(String orderId) { + repository.cancleOrder(orderId); + orderController.remove(orderId); Get.back(); } - void makePayment(Order order) async { + void makePayment(String orderId) async { MessageDialog.showLoading(); - await repository.makePayment(order.sId!); - await repository.getOrderDetail(orderDetail).then((value) => detail = value); - orderController.getAllOrders(); + try { + await repository.makePayment(orderId); + await repository + .getOrderDetail(orderDetail) + .then((value) => detail = value); + orderController.getAllOrders(); + } on Exception catch (e) { + MessageDialog.showToast(e.toString()); + } MessageDialog.hideLoading(); } - } diff --git a/lib/screens/tracking/order_detail.view.dart b/lib/screens/tracking/order_detail.view.dart new file mode 100644 index 00000000..7bbf2efd --- /dev/null +++ b/lib/screens/tracking/order_detail.view.dart @@ -0,0 +1,141 @@ +import 'package:ecommerce_int2/data/repository/order.repository.dart'; +import 'package:ecommerce_int2/screens/main/components/product_list.dart'; +import 'package:ecommerce_int2/screens/tracking/order.controller.dart'; +import 'package:ecommerce_int2/screens/tracking/order_detail.controller.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:intl/intl.dart'; + +class OrderDetail extends StatelessWidget { + final String orderId; + + const OrderDetail({Key? key, required this.orderId}) : super(key: key); + + @override + Widget build(BuildContext context) { + return GetBuilder( + init: OrderDetailController( + Get.find(), orderId, Get.find()), + builder: (controller) => Container( + decoration: BoxDecoration( + color: Colors.grey[100], + image: DecorationImage( + image: AssetImage('assets/Group 444.png'), + fit: BoxFit.contain)), + child: Container( + color: Colors.white54, + child: Scaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + elevation: 0.0, + brightness: Brightness.light, + iconTheme: IconThemeData(color: Colors.grey), + title: Text( + orderId, + style: TextStyle( + color: darkGrey, + fontSize: 22, + fontWeight: FontWeight.bold, + ), + ), + leading: SizedBox(), + actions: [CloseButton()], + ), + body: SafeArea( + child: LayoutBuilder( + builder: (_, constraints) => SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + maxHeight: constraints.maxHeight - 48, + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: controller.detail != null + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 24), + Text( + 'Deliver status: ${controller.detail?.status ?? ''}'), + Text( + 'Payment status: ${controller.detail?.paymentStatus ?? ''}'), + Text( + 'Merchant: ${controller.detail?.merchant ?? ''}'), + Text( + 'Date: ${controller.detail?.created ?? ''}'), + Text('Products'), + const SizedBox(height: 16), + ...controller.detail!.cart!.products! + .map((product) => ProductCard( + product: product, + height: 130, + width: Get.width)) + .toList(), + if (controller.detail!.isPayWithCash) + GestureDetector( + onTap: (() => controller.makePayment(orderId)), + child: Center( + child: Container( + height: 40, + width: + MediaQuery.of(context).size.width / + 1.5, + decoration: BoxDecoration( + gradient: mainButton, + boxShadow: [ + BoxShadow( + color: Color.fromRGBO( + 0, 0, 0, 0.16), + offset: Offset(0, 5), + blurRadius: 10.0, + ) + ], + borderRadius: + BorderRadius.circular(9.0)), + child: Center( + child: Text("Pay with PayPal", + style: const TextStyle( + color: + const Color(0xfffefefe), + fontWeight: FontWeight.w600, + fontStyle: FontStyle.normal, + fontSize: 20.0)), + ), + ), + ), + ) + ], + ) + : SizedBox.shrink(), + ), + ), + ), + ), + ), + )), + ), + ), + ); + } +} + +class Location { + String city; + DateTime date; + bool showHour; + bool isHere; + bool passed; + + Location(this.city, this.date, + {this.showHour = false, this.isHere = false, this.passed = false}); + + String getDate() { + if (showHour) { + return DateFormat("K:mm aaa, d MMMM y").format(date); + } else { + return DateFormat('d MMMM y').format(date); + } + } +} diff --git a/lib/screens/tracking/tracking_page.dart b/lib/screens/tracking/tracking_page.dart index aa14efaf..506af33c 100644 --- a/lib/screens/tracking/tracking_page.dart +++ b/lib/screens/tracking/tracking_page.dart @@ -1,5 +1,8 @@ +import 'package:ecommerce_int2/data/repository/order.repository.dart'; +import 'package:ecommerce_int2/screens/tracking/order.controller.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:flutter/material.dart'; +import 'package:get/get.dart'; import 'package:intl/intl.dart'; class TrackingPage extends StatefulWidget { @@ -31,119 +34,72 @@ class _TrackingPageState extends State { @override Widget build(BuildContext context) { - return Container( - decoration: BoxDecoration( - color: Colors.grey[100], - image: DecorationImage( - image: AssetImage('assets/Group 444.png'), fit: BoxFit.contain)), - child: Container( - color: Colors.white54, - child: Scaffold( - appBar: AppBar( - backgroundColor: Colors.transparent, - elevation: 0.0, - brightness: Brightness.light, - iconTheme: IconThemeData(color: Colors.grey), - title: Text( - 'Shipped', - style: TextStyle( - color: darkGrey, - fontSize: 22, - fontWeight: FontWeight.bold, + return GetBuilder( + init: OrderController(Get.find()), + builder: (controller) => Container( + decoration: BoxDecoration( + color: Colors.grey[100], + image: DecorationImage( + image: AssetImage('assets/Group 444.png'), + fit: BoxFit.contain)), + child: Container( + color: Colors.white54, + child: Scaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + elevation: 0.0, + brightness: Brightness.light, + iconTheme: IconThemeData(color: Colors.grey), + title: Text( + 'Your orders', + style: TextStyle( + color: darkGrey, + fontSize: 22, + fontWeight: FontWeight.bold, + ), ), + leading: SizedBox(), + actions: [CloseButton()], ), - leading: SizedBox(), - actions: [CloseButton()], - ), - body: SafeArea( - child: LayoutBuilder( - builder: (_, constraints) => Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - margin: const EdgeInsets.symmetric(horizontal: 16.0), - padding: const EdgeInsets.symmetric(horizontal: 16.0), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(5))), - child: DropdownButtonHideUnderline( - child: DropdownButton( - items: [ - 'Boat Headphones Bass boost 100v', - 'Boat Headphones Bass boost 200v', - 'Boat Headphones Bass boost 300v', - 'Boat Headphones Bass boost 400v', - 'Boat Headphones Bass boost 500v', - 'Boat Headphones Bass double boosting 600v' - ].map((val) { - return DropdownMenuItem( - value: val, - child: Container( - color: Colors.white, - child: Align( - alignment: Alignment.centerLeft, - child: Text( - val, - maxLines: 2, - semanticsLabel: '...', - overflow: TextOverflow.ellipsis, - ))), - ); - }).toList(), - onChanged: (newValue) { - setState(() { - selectedProduct = newValue as String; - }); - }, - value: selectedProduct, - isExpanded: true, - icon: Icon(Icons.keyboard_arrow_down), - elevation: 0, - ), + body: SafeArea( + child: LayoutBuilder( + builder: (_, constraints) => SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + maxHeight: constraints.maxHeight - 48, ), - ), - SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - maxHeight: constraints.maxHeight - 48, - ), - child: Theme( - data: ThemeData( - primaryColor: yellow, fontFamily: 'Montserrat'), - child: Stepper( -// physics: NeverScrollableScrollPhysics(), - steps: [ - ...locations - .map( - (location) => Step( - isActive: - location.isHere || location.passed, - title: Text(location.city), - subtitle: Text(location.getDate()), - content: Align( - child: Image.asset( - 'assets/icons/truck.png'), - alignment: Alignment.centerLeft, + child: Column( + // physics: NeverScrollableScrollPhysics(), + children: [ + ...controller.orders + .map((order) => GestureDetector( + onTap: (() => controller.getOrderDetail(order)), + child: Container( + width: Get.width, + child: Card( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column(children: [ + Text('Order Id: ${order.sId ?? 'Order'}'), + Text('Deliver status: ${order.status ?? ''}'), + Text('Payment status: ${order.paymentStatus ?? ''}'), + Text('Merchant: ${order.merchant ?? ''}'), + Text('Date: ${order.created ?? ''}') + ], + crossAxisAlignment: CrossAxisAlignment.start, + ), + ), ), - state: location.passed - ? StepState.complete - : location.isHere - ? StepState.editing - : StepState.indexed, - ), - ) - .toList() - ], - currentStep: locations.indexOf( - locations.firstWhere((loc) => loc.isHere)), - ), - ), + ), + )) + .toList() + ], ), ), - ], + ), ), - ), - )), + )), + ), ), ); } From aa0c6ae5498a46ff180ab4ed2be9b00f59ccd963 Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Tue, 7 Jun 2022 11:12:30 +0700 Subject: [PATCH 29/49] Integrate webview to pay with paypal --- lib/data/models/order.model.dart | 2 + lib/data/models/payment.model.dart | 163 ++++++++++++++++++ lib/data/repository/order.repository.dart | 5 +- .../tracking/order_detail.controller.dart | 4 +- lib/screens/tracking/order_detail.view.dart | 33 ++++ lib/utils/webview.dart | 28 +++ pubspec.yaml | 1 + 7 files changed, 233 insertions(+), 3 deletions(-) create mode 100644 lib/data/models/payment.model.dart create mode 100644 lib/utils/webview.dart diff --git a/lib/data/models/order.model.dart b/lib/data/models/order.model.dart index f5fc9872..2d1a8f56 100644 --- a/lib/data/models/order.model.dart +++ b/lib/data/models/order.model.dart @@ -254,6 +254,8 @@ class OrderDocDetail { bool get isPayWithCash => payment == 'CASH'; + bool get canCancel => status == 'NOT_PROCESS'; + OrderDocDetail( {this.sId, this.cart, diff --git a/lib/data/models/payment.model.dart b/lib/data/models/payment.model.dart new file mode 100644 index 00000000..b4cf7ac8 --- /dev/null +++ b/lib/data/models/payment.model.dart @@ -0,0 +1,163 @@ +class PaymentResponse { + bool? success; + String? message; + Data? data; + + PaymentResponse({this.success, this.message, this.data}); + + PaymentResponse.fromJson(Map json) { + success = json['success']; + message = json['message']; + data = json['data'] != null ? new Data.fromJson(json['data']) : null; + } + + Map toJson() { + final Map data = new Map(); + data['success'] = this.success; + data['message'] = this.message; + if (this.data != null) { + data['data'] = this.data!.toJson(); + } + return data; + } +} + +class Data { + String? id; + String? intent; + String? state; + Payer? payer; + List? transactions; + String? createTime; + List? links; + int? httpStatusCode; + + Data( + {this.id, + this.intent, + this.state, + this.payer, + this.transactions, + this.createTime, + this.links, + this.httpStatusCode}); + + Data.fromJson(Map json) { + id = json['id']; + intent = json['intent']; + state = json['state']; + payer = json['payer'] != null ? new Payer.fromJson(json['payer']) : null; + if (json['transactions'] != null) { + transactions = []; + json['transactions'].forEach((v) { + transactions!.add(new Transactions.fromJson(v)); + }); + } + createTime = json['create_time']; + if (json['links'] != null) { + links = []; + json['links'].forEach((v) { + links!.add(new Links.fromJson(v)); + }); + } + httpStatusCode = json['httpStatusCode']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['intent'] = this.intent; + data['state'] = this.state; + if (this.payer != null) { + data['payer'] = this.payer!.toJson(); + } + if (this.transactions != null) { + data['transactions'] = this.transactions!.map((v) => v.toJson()).toList(); + } + data['create_time'] = this.createTime; + if (this.links != null) { + data['links'] = this.links!.map((v) => v.toJson()).toList(); + } + data['httpStatusCode'] = this.httpStatusCode; + return data; + } +} + +class Payer { + String? paymentMethod; + + Payer({this.paymentMethod}); + + Payer.fromJson(Map json) { + paymentMethod = json['payment_method']; + } + + Map toJson() { + final Map data = new Map(); + data['payment_method'] = this.paymentMethod; + return data; + } +} + +class Transactions { + Amount? amount; + String? description; + + Transactions({this.amount, this.description}); + + Transactions.fromJson(Map json) { + amount = + json['amount'] != null ? new Amount.fromJson(json['amount']) : null; + description = json['description']; + } + + Map toJson() { + final Map data = new Map(); + if (this.amount != null) { + data['amount'] = this.amount!.toJson(); + } + data['description'] = this.description; + return data; + } +} + +class Amount { + String? total; + String? currency; + + Amount({this.total, this.currency}); + + Amount.fromJson(Map json) { + total = json['total']; + currency = json['currency']; + } + + Map toJson() { + final Map data = new Map(); + data['total'] = this.total; + data['currency'] = this.currency; + return data; + } +} + +class Links { + String? href; + String? rel; + String? method; + + Links({this.href, this.rel, this.method}); + + Links.fromJson(Map json) { + href = json['href']; + rel = json['rel']; + method = json['method']; + } + + Map toJson() { + final Map data = new Map(); + data['href'] = this.href; + data['rel'] = this.rel; + data['method'] = this.method; + return data; + } +} diff --git a/lib/data/repository/order.repository.dart b/lib/data/repository/order.repository.dart index d852f7c8..efaa6448 100644 --- a/lib/data/repository/order.repository.dart +++ b/lib/data/repository/order.repository.dart @@ -1,4 +1,5 @@ import 'package:ecommerce_int2/data/models/order.model.dart'; +import 'package:ecommerce_int2/data/models/payment.model.dart'; import 'package:ecommerce_int2/data/provider/order.provider.dart'; class OrderRepository { @@ -29,8 +30,8 @@ class OrderRepository { if (response.statusCode != 200) { throw Exception("Make payment failed"); } - // final result = CompleteOrderResponse.fromJson(response.body); - return 'href'; + final result = PaymentResponse.fromJson(response.body); + return result.data!.links?.firstWhere((element) => element.rel == 'approval_url').href ?? ''; } Future cancleOrder(String orderId) async { diff --git a/lib/screens/tracking/order_detail.controller.dart b/lib/screens/tracking/order_detail.controller.dart index 0a9fedf2..ea930bf1 100644 --- a/lib/screens/tracking/order_detail.controller.dart +++ b/lib/screens/tracking/order_detail.controller.dart @@ -2,6 +2,7 @@ import 'package:ecommerce_int2/data/models/order.model.dart'; import 'package:ecommerce_int2/data/repository/order.repository.dart'; import 'package:ecommerce_int2/screens/tracking/order.controller.dart'; import 'package:ecommerce_int2/utils/message_dialog.dart'; +import 'package:ecommerce_int2/utils/webview.dart'; import 'package:get/get.dart'; class OrderDetailController extends GetxController { @@ -40,7 +41,8 @@ class OrderDetailController extends GetxController { void makePayment(String orderId) async { MessageDialog.showLoading(); try { - await repository.makePayment(orderId); + final String href = await repository.makePayment(orderId); + await Get.to(() => WebViewExample(url: href)); await repository .getOrderDetail(orderDetail) .then((value) => detail = value); diff --git a/lib/screens/tracking/order_detail.view.dart b/lib/screens/tracking/order_detail.view.dart index 7bbf2efd..665cf0e6 100644 --- a/lib/screens/tracking/order_detail.view.dart +++ b/lib/screens/tracking/order_detail.view.dart @@ -73,6 +73,39 @@ class OrderDetail extends StatelessWidget { height: 130, width: Get.width)) .toList(), + if (controller.detail!.canCancel) + GestureDetector( + onTap: (() => controller.remove(orderId)), + child: Center( + child: Container( + height: 40, + width: + MediaQuery.of(context).size.width / + 1.5, + decoration: BoxDecoration( + gradient: mainButton, + boxShadow: [ + BoxShadow( + color: Color.fromRGBO( + 0, 0, 0, 0.16), + offset: Offset(0, 5), + blurRadius: 10.0, + ) + ], + borderRadius: + BorderRadius.circular(9.0)), + child: Center( + child: Text("Cancle Order", + style: const TextStyle( + color: + const Color(0xfffefefe), + fontWeight: FontWeight.w600, + fontStyle: FontStyle.normal, + fontSize: 20.0)), + ), + ), + ), + ), if (controller.detail!.isPayWithCash) GestureDetector( onTap: (() => controller.makePayment(orderId)), diff --git a/lib/utils/webview.dart b/lib/utils/webview.dart new file mode 100644 index 00000000..2ef1ae1e --- /dev/null +++ b/lib/utils/webview.dart @@ -0,0 +1,28 @@ +import 'dart:io'; + + import 'package:flutter/material.dart'; +import 'package:webview_flutter/webview_flutter.dart'; + + class WebViewExample extends StatefulWidget { + final String url; + + const WebViewExample({Key? key,required this.url}) : super(key: key); + @override + WebViewExampleState createState() => WebViewExampleState(); + } + + class WebViewExampleState extends State { + @override + void initState() { + super.initState(); + // Enable virtual display. + if (Platform.isAndroid) WebView.platform = AndroidWebView(); + } + + @override + Widget build(BuildContext context) { + return WebView( + initialUrl: widget.url, + ); + } + } \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index d3344f8e..f3dfb46e 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -39,6 +39,7 @@ dependencies: get_storage: ^2.0.3 path_provider: ^2.0.10 pull_to_refresh: ^2.0.0 + webview_flutter: ^3.0.4 dev_dependencies: From d864b4faa87ab49af232318cf803824c62eee027 Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Tue, 7 Jun 2022 16:24:27 +0700 Subject: [PATCH 30/49] Add cart button for search and product detail --- lib/screens/product/view_product_page.dart | 4 +++- lib/screens/search_products/search_page.dart | 7 +++++-- lib/screens/shop/check_out_page.dart | 2 -- lib/utils/cart_button.widget.dart | 18 ++++++++++++++++++ 4 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 lib/utils/cart_button.widget.dart diff --git a/lib/screens/product/view_product_page.dart b/lib/screens/product/view_product_page.dart index 813949a1..83483485 100755 --- a/lib/screens/product/view_product_page.dart +++ b/lib/screens/product/view_product_page.dart @@ -1,5 +1,6 @@ import 'package:ecommerce_int2/screens/product/components/rating_bottomSheet.dart'; import 'package:ecommerce_int2/screens/search_products/search_page.dart'; +import 'package:ecommerce_int2/utils/cart_button.widget.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -81,7 +82,8 @@ class _ViewProductPageState extends State { ), onPressed: () => Navigator.of(context) .push(MaterialPageRoute(builder: (_) => SearchPage())), - ) + ), + CartButton() ], title: Text( widget.product.name ?? 'Product', diff --git a/lib/screens/search_products/search_page.dart b/lib/screens/search_products/search_page.dart index 3259bd28..ce7d2a40 100644 --- a/lib/screens/search_products/search_page.dart +++ b/lib/screens/search_products/search_page.dart @@ -5,6 +5,7 @@ import 'package:ecommerce_int2/screens/product/product_page.dart'; import 'package:ecommerce_int2/screens/search_products/search_controller.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/product/view_product_page.dart'; +import 'package:ecommerce_int2/utils/cart_button.widget.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; @@ -79,8 +80,9 @@ class _SearchPageState extends State Padding( padding: EdgeInsets.symmetric(horizontal: 16.0), child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.start, children: [ + BackButton(), Text( 'Search', style: TextStyle( @@ -89,7 +91,8 @@ class _SearchPageState extends State fontWeight: FontWeight.bold, ), ), - CloseButton() + Spacer(), + CartButton(), ], ), ), diff --git a/lib/screens/shop/check_out_page.dart b/lib/screens/shop/check_out_page.dart index 3b5105b9..23dbb043 100755 --- a/lib/screens/shop/check_out_page.dart +++ b/lib/screens/shop/check_out_page.dart @@ -3,8 +3,6 @@ import 'package:ecommerce_int2/data/models/product.model.dart'; import 'package:ecommerce_int2/data/repository/cart.repository.dart'; import 'package:ecommerce_int2/screens/shop/cart.controller.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; -import 'package:ecommerce_int2/screens/address/add_address_page.dart'; -import 'package:ecommerce_int2/screens/payment/unpaid_page.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; diff --git a/lib/utils/cart_button.widget.dart b/lib/utils/cart_button.widget.dart new file mode 100644 index 00000000..15986870 --- /dev/null +++ b/lib/utils/cart_button.widget.dart @@ -0,0 +1,18 @@ +import 'package:ecommerce_int2/screens/shop/check_out_page.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + +class CartButton extends StatelessWidget { + const CartButton({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return IconButton( + icon: SvgPicture.asset('assets/icons/cart_icon.svg'), + onPressed: () { + Get.to(() => CheckOutPage()); + }, + ); + } +} \ No newline at end of file From ef82edea15c3ab1f8066754bc2e8bd676ecdc672 Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Thu, 9 Jun 2022 16:34:26 +0700 Subject: [PATCH 31/49] Update search --- .../search_products/search_controller.dart | 18 +++++++++++------- lib/screens/search_products/search_page.dart | 12 ++++-------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/screens/search_products/search_controller.dart b/lib/screens/search_products/search_controller.dart index e26d8135..3e71ab01 100644 --- a/lib/screens/search_products/search_controller.dart +++ b/lib/screens/search_products/search_controller.dart @@ -1,4 +1,3 @@ -import 'package:ecommerce_int2/data/models/category.model.dart'; import 'package:ecommerce_int2/data/models/product.model.dart'; import 'package:ecommerce_int2/data/repository/product.repository.dart'; import 'package:ecommerce_int2/utils/debounce.dart'; @@ -40,6 +39,13 @@ class SearchProductController extends GetxController { super.onInit(); } + void getArgument() { + final dynamic subCategory = Get.arguments; + if (subCategory != null && subCategory is String) { + filter.subcategory = subCategory; + } + } + Future getProduct() async { try { final res = await repository.getProducts(filter); @@ -60,7 +66,7 @@ class SearchProductController extends GetxController { } void onLoadMore() async { - if(list.length == total) return; + if (list.length == total) return; ++currentPage; filter.pageNumber = currentPage; await getProduct(); @@ -69,11 +75,9 @@ class SearchProductController extends GetxController { void onChanged(String value) { debounce.run(() { - if (value.isNotEmpty) { - filter.name = value; - getProduct(); - update(); - } + filter.name = value; + getProduct(); + update(); }); } } diff --git a/lib/screens/search_products/search_page.dart b/lib/screens/search_products/search_page.dart index 3259bd28..8cff98e5 100644 --- a/lib/screens/search_products/search_page.dart +++ b/lib/screens/search_products/search_page.dart @@ -1,10 +1,11 @@ +// ignore_for_file: deprecated_member_use + import 'package:ecommerce_int2/data/models/product.model.dart'; import 'package:ecommerce_int2/data/repository/product.repository.dart'; import 'package:ecommerce_int2/screens/product/components/product_card.dart'; import 'package:ecommerce_int2/screens/product/product_page.dart'; import 'package:ecommerce_int2/screens/search_products/search_controller.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; -import 'package:ecommerce_int2/screens/product/view_product_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; @@ -47,7 +48,6 @@ class _SearchPageState extends State List searchResults = []; - TextEditingController searchController = TextEditingController(); late RubberAnimationController _controller; @@ -67,10 +67,6 @@ class _SearchPageState extends State super.dispose(); } - void _expand() { - _controller.expand(); - } - Widget _getLowerLayer(SearchProductController controller) { return Container( margin: const EdgeInsets.only(top: 16), @@ -99,7 +95,7 @@ class _SearchPageState extends State border: Border(bottom: BorderSide(color: Colors.orange, width: 1))), child: TextField( - controller: searchController, + controller: controller.searchController, onChanged: (value) => controller.onChanged(value), cursorColor: darkGrey, decoration: InputDecoration( @@ -111,7 +107,7 @@ class _SearchPageState extends State ), suffix: FlatButton( onPressed: () { - searchController.clear(); + controller.searchController.clear(); searchResults.clear(); }, child: Text( From 67e5cfd2ad74396e2f06725b3f965438d02303b9 Mon Sep 17 00:00:00 2001 From: manmaihuu Date: Thu, 9 Jun 2022 16:37:52 +0700 Subject: [PATCH 32/49] Update UI for product_card --- .../product/components/product_card.dart | 52 +++++++++++++------ lib/screens/shop/check_out_page.dart | 3 -- 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/lib/screens/product/components/product_card.dart b/lib/screens/product/components/product_card.dart index 22b000fe..2c2879dd 100755 --- a/lib/screens/product/components/product_card.dart +++ b/lib/screens/product/components/product_card.dart @@ -15,22 +15,16 @@ class ProductCard extends StatelessWidget { child: InkWell( onTap: () => onTap(), child: Container( - height: 200, width: MediaQuery.of(context).size.width / 2 - 29, decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(10)), color: Color(0xfffbd085).withOpacity(0.46)), child: Row( children: [ - Align( - alignment: Alignment.topCenter, - child: Container( - padding: EdgeInsets.all(16.0), - width: 180, - height: 180, - child: Image.network( - product.imageUrl!, - ), + Container( + padding: EdgeInsets.all(16.0), + child: Image.network( + product.imageUrl!, ), ), Flexible( @@ -42,13 +36,37 @@ class ProductCard extends StatelessWidget { borderRadius: BorderRadius.only( topLeft: Radius.circular(10), bottomLeft: Radius.circular(10))), - child: Text( - product.name ?? "Product", - textAlign: TextAlign.right, - style: TextStyle( - fontSize: 12.0, - color: Colors.white, - ), + child: Column( + children: [ + Text( + product.name ?? "Product", + textAlign: TextAlign.right, + style: TextStyle( + fontSize: 12.0, + color: Colors.white, + ), + ), + Text( + product.merchant ?? "Merchant", + textAlign: TextAlign.right, + style: TextStyle( + fontSize: 12.0, + color: Colors.white, + ), + ), + Text( + 'VND' + + (product.purchasePrice ?? + product.price ?? + 0) + .toString(), + textAlign: TextAlign.right, + style: TextStyle( + fontSize: 12.0, + color: Colors.white, + ), + ) + ], )), ) ], diff --git a/lib/screens/shop/check_out_page.dart b/lib/screens/shop/check_out_page.dart index 3b5105b9..027e17d5 100755 --- a/lib/screens/shop/check_out_page.dart +++ b/lib/screens/shop/check_out_page.dart @@ -1,10 +1,7 @@ import 'package:card_swiper/card_swiper.dart'; -import 'package:ecommerce_int2/data/models/product.model.dart'; import 'package:ecommerce_int2/data/repository/cart.repository.dart'; import 'package:ecommerce_int2/screens/shop/cart.controller.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; -import 'package:ecommerce_int2/screens/address/add_address_page.dart'; -import 'package:ecommerce_int2/screens/payment/unpaid_page.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; From cc2a764620d53afb7f5a14e211af4f03f4705457 Mon Sep 17 00:00:00 2001 From: manmaihuu <103487985+pdax-manmai@users.noreply.github.com> Date: Tue, 14 Jun 2022 16:30:19 +0700 Subject: [PATCH 33/49] Add item for home views --- .flutter-plugins-dependencies | 2 +- android/app/build.gradle | 2 +- lib/screens/address/add_address_page.dart | 1 - lib/screens/auth/confirm_otp_page.dart | 214 ---------------- .../category/sub_category.controller.dart | 1 - lib/screens/intro_page.dart | 229 ------------------ .../main/components/recommended_list.dart | 20 +- lib/screens/main/components/tab_view.dart | 199 ++++++++------- lib/screens/main/home.controller.dart | 79 ++++++ lib/screens/main/main_page.dart | 69 +++--- .../product/components/product_card.dart | 2 + lib/screens/product/view_product_page.dart | 2 - pubspec.lock | 28 +++ 13 files changed, 252 insertions(+), 596 deletions(-) delete mode 100755 lib/screens/auth/confirm_otp_page.dart delete mode 100755 lib/screens/intro_page.dart create mode 100644 lib/screens/main/home.controller.dart diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index ebe32000..8318f62a 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2022-06-01 15:20:23.532298","version":"2.10.4"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]},{"name":"webview_flutter_wkwebview","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_wkwebview-2.7.5\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]},{"name":"webview_flutter_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_android-2.8.10\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2022-06-14 14:44:17.351912","version":"2.10.4"} \ No newline at end of file diff --git a/android/app/build.gradle b/android/app/build.gradle index 231052c8..65a2a263 100755 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -45,7 +45,7 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.int2.ecommerce_int2" - minSdkVersion 16 + minSdkVersion 19 targetSdkVersion 31 versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/lib/screens/address/add_address_page.dart b/lib/screens/address/add_address_page.dart index b3e8d699..1683cb64 100755 --- a/lib/screens/address/add_address_page.dart +++ b/lib/screens/address/add_address_page.dart @@ -3,7 +3,6 @@ import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/data/repository/address.repository.dart'; import 'package:ecommerce_int2/screens/address/address_form.dart'; -import 'package:ecommerce_int2/screens/select_card_page.dart'; import 'package:ecommerce_int2/screens/address/address.controller.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; diff --git a/lib/screens/auth/confirm_otp_page.dart b/lib/screens/auth/confirm_otp_page.dart deleted file mode 100755 index 12618944..00000000 --- a/lib/screens/auth/confirm_otp_page.dart +++ /dev/null @@ -1,214 +0,0 @@ -import 'package:ecommerce_int2/utils/app_properties.dart'; -import 'package:ecommerce_int2/screens/intro_page.dart'; -import 'package:flutter/material.dart'; -import 'package:pin_code_text_field/pin_code_text_field.dart'; - -class ConfirmOtpPage extends StatefulWidget { - @override - _ConfirmOtpPageState createState() => _ConfirmOtpPageState(); -} - -class _ConfirmOtpPageState extends State { - TextEditingController otp1 = TextEditingController(text: '1'); - TextEditingController otp2 = TextEditingController(text: '2'); - TextEditingController otp3 = TextEditingController(text: '3'); - TextEditingController otp4 = TextEditingController(text: '4'); - TextEditingController otp5 = TextEditingController(text: '5'); - - Widget otpBox(TextEditingController otpController) { - return Container( - height: 48, - width: 48, - decoration: BoxDecoration( - color: Color.fromRGBO(255, 255, 255, 0.8), - borderRadius: BorderRadius.all(Radius.circular(10))), - child: Center( - child: SizedBox( - width: 9, - child: Padding( - padding: const EdgeInsets.only(top: 8.0), - child: TextField( - controller: otpController, - decoration: InputDecoration( - border: InputBorder.none, contentPadding: EdgeInsets.zero), - style: TextStyle(fontSize: 16.0), - keyboardType: TextInputType.phone, - ), - ), - ), - ), - ); - } - - @override - Widget build(BuildContext context) { - Widget title = Text( - 'Confirm your OTP', - style: TextStyle( - color: Colors.white, - fontSize: 34.0, - fontWeight: FontWeight.bold, - shadows: [ - BoxShadow( - color: Color.fromRGBO(0, 0, 0, 0.15), - offset: Offset(0, 5), - blurRadius: 10.0, - ) - ]), - ); - - Widget subTitle = Padding( - padding: const EdgeInsets.only(right: 56.0), - child: Text( - 'Please wait, we are confirming your OTP', - style: TextStyle( - color: Colors.white, - fontSize: 16.0, - ), - )); - - Widget verifyButton = Center( - child: InkWell( - onTap: () { - Navigator.of(context) - .push(MaterialPageRoute(builder: (_) => IntroPage())); - }, - child: Container( - width: MediaQuery.of(context).size.width / 2, - height: 80, - child: Center( - child: new Text("Verify", - style: const TextStyle( - color: const Color(0xfffefefe), - fontWeight: FontWeight.w600, - fontStyle: FontStyle.normal, - fontSize: 20.0))), - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - Color.fromRGBO(236, 60, 3, 1), - Color.fromRGBO(234, 60, 3, 1), - Color.fromRGBO(216, 78, 16, 1), - ], - begin: FractionalOffset.topCenter, - end: FractionalOffset.bottomCenter), - boxShadow: [ - BoxShadow( - color: Color.fromRGBO(0, 0, 0, 0.16), - offset: Offset(0, 5), - blurRadius: 10.0, - ) - ], - borderRadius: BorderRadius.circular(9.0)), - ), - ), - ); - - Widget otpCode = Container( - padding: const EdgeInsets.only(right: 28.0), - height: 190, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - otpBox(otp1), - otpBox(otp2), - otpBox(otp3), - otpBox(otp4), - otpBox(otp5) - ], - ), - ); - - Widget resendText = Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - "Resend again after ", - style: TextStyle( - fontStyle: FontStyle.italic, - color: Color.fromRGBO(255, 255, 255, 0.5), - fontSize: 14.0, - ), - ), - InkWell( - onTap: () {}, - child: Text( - '0:39', - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 14.0, - ), - ), - ), - ], - ); - - return GestureDetector( - onTap: () => FocusScope.of(context).requestFocus(new FocusNode()), - child: Container( - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage('assets/background.jpg'), fit: BoxFit.cover)), - child: Container( - decoration: BoxDecoration(color: transparentYellow), - child: Scaffold( - appBar: AppBar( - backgroundColor: Colors.transparent, - elevation: 0.0, - ), - body: Stack( - children: [ - Padding( - padding: const EdgeInsets.only(left: 28.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Spacer(flex: 3), - title, - Spacer(), - subTitle, - Spacer(flex: 1), - Padding( - padding: const EdgeInsets.only(right: 28.0), - child: Center( - child: PinCodeTextField( - controller: new TextEditingController(), - highlightColor: Colors.white, - highlightAnimation: true, - highlightAnimationBeginColor: Colors.white, - highlightAnimationEndColor: Theme.of(context).primaryColor, - pinTextAnimatedSwitcherDuration: Duration(milliseconds: 500), - wrapAlignment: WrapAlignment.center, - hasTextBorderColor: Colors.transparent, - highlightPinBoxColor: Colors.white, - autofocus: true, - pinBoxHeight: 60, - pinBoxWidth: 60, - pinBoxRadius: 5, - defaultBorderColor: Colors.transparent, - pinBoxColor: Color.fromRGBO(255, 255, 255, 0.8), - maxLength: 4, - ), - ), - ), - Spacer(flex: 1), -// otpCode, - Padding( - padding: const EdgeInsets.only(right: 28.0), - child: verifyButton, - ), - Spacer(flex: 2), - resendText, - Spacer() - ], - ), - ) - ], - ), - ), - ), - ), - ); - } -} diff --git a/lib/screens/category/sub_category.controller.dart b/lib/screens/category/sub_category.controller.dart index 3c037c1e..c2a14a98 100644 --- a/lib/screens/category/sub_category.controller.dart +++ b/lib/screens/category/sub_category.controller.dart @@ -18,7 +18,6 @@ class SubCategoryController extends GetxController { @override void onInit() { - super.onInit(); } diff --git a/lib/screens/intro_page.dart b/lib/screens/intro_page.dart deleted file mode 100755 index fed6946f..00000000 --- a/lib/screens/intro_page.dart +++ /dev/null @@ -1,229 +0,0 @@ -import 'package:ecommerce_int2/utils/app_properties.dart'; -import 'package:ecommerce_int2/screens/main/main_page.dart'; -import 'package:flutter/material.dart'; - -class IntroPage extends StatefulWidget { - @override - _IntroPageState createState() => _IntroPageState(); -} - -class _IntroPageState extends State { - PageController controller = PageController(); - int pageIndex = 0; - - @override - Widget build(BuildContext context) { - return Material( - child: Container( -// width: MediaQuery.of(context).size.width, - decoration: BoxDecoration( - color: Colors.grey[100], - image: DecorationImage(image: AssetImage('assets/background.png'))), - child: Stack( - children: [ - PageView( - onPageChanged: (value) { - setState(() { - pageIndex = value; - }); - }, - controller: controller, - children: [ - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Center( - child: Image.asset( - 'assets/firstScreen.png', - height: 200, - width: 200, - ), - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 32), - child: Text( - 'Get Any Thing Online', - textAlign: TextAlign.right, - style: TextStyle( - fontWeight: FontWeight.bold, fontSize: 16), - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32, vertical: 16.0), - child: Text( - 'You can buy anything ranging from digital products to hardware within few clicks.', - textAlign: TextAlign.right, - style: TextStyle(color: Colors.grey, fontSize: 12.0), - ), - ), - ], - ), - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Center( - child: Image.asset( - 'assets/secondScreen.png', - height: 200, - width: 200, - ), - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 32), - child: Text( - 'Shipping to anywhere ', - textAlign: TextAlign.right, - style: TextStyle( - fontWeight: FontWeight.bold, fontSize: 16), - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32, vertical: 16.0), - child: Text( - 'We will ship to anywhere in the world, With 30 day 100% money back policy.', - textAlign: TextAlign.right, - style: TextStyle(color: Colors.grey, fontSize: 12.0), - ), - ), - ], - ), - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Center( - child: Image.asset( - 'assets/thirdScreen.png', - height: 200, - width: 200, - ), - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 32), - child: Text( - 'On-time delivery', - textAlign: TextAlign.right, - style: TextStyle( - fontWeight: FontWeight.bold, fontSize: 16), - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32, vertical: 16.0), - child: Text( - 'You can track your product with our powerful tracking service.', - textAlign: TextAlign.right, - style: TextStyle(color: Colors.grey, fontSize: 12.0), - ), - ), - ], - ), - ], - ), - Positioned( - bottom: 16.0, - child: SizedBox( - width: MediaQuery.of(context).size.width, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - margin: EdgeInsets.all(8.0), - height: 12, - width: 12, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all(color: Colors.black, width: 2), - color: pageIndex == 0 ? yellow : Colors.white), - ), - Container( - margin: EdgeInsets.all(8.0), - height: 12, - width: 12, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all(color: Colors.black, width: 2), - color: pageIndex == 1 ? yellow : Colors.white), - ), - Container( - margin: EdgeInsets.all(8.0), - height: 12, - width: 12, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all(color: Colors.black, width: 2), - color: pageIndex == 2 ? yellow : Colors.white), - ) - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - Opacity( - opacity: pageIndex != 2 ? 1.0 : 0.0, - child: FlatButton( - splashColor: Colors.transparent, - child: Text( - 'SKIP', - style: TextStyle( - color: Colors.black, - fontWeight: FontWeight.bold, - fontSize: 16), - ), - onPressed: () { - Navigator.of(context).pushReplacement( - MaterialPageRoute( - builder: (context) => MainPage())); - }, - ), - ), - pageIndex != 2 - ? FlatButton( - splashColor: Colors.transparent, - child: Text( - 'NEXT', - style: TextStyle( - color: Colors.black, - fontWeight: FontWeight.bold, - fontSize: 16), - ), - onPressed: () { - if (!(controller.page == 2.0)) - controller.nextPage( - duration: Duration(milliseconds: 200), - curve: Curves.linear); - }, - ) - : FlatButton( - splashColor: Colors.transparent, - child: Text( - 'FINISH', - style: TextStyle( - color: Colors.black, - fontWeight: FontWeight.bold, - fontSize: 16), - ), - onPressed: () { - Navigator.of(context).pushReplacement( - MaterialPageRoute( - builder: (context) => MainPage())); - }, - ) - ], - ), - ], - ), - ), - ) - ], - ), - ), - ); - } -} diff --git a/lib/screens/main/components/recommended_list.dart b/lib/screens/main/components/recommended_list.dart index 34a71731..2f8f4bd0 100755 --- a/lib/screens/main/components/recommended_list.dart +++ b/lib/screens/main/components/recommended_list.dart @@ -5,18 +5,10 @@ import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; import 'package:flutter/material.dart'; class RecommendedList extends StatelessWidget { - List products = [ - // Product('assets/bag_1.png', 'Bag', 'Beautiful bag', 2.33), - // Product('assets/cap_5.png', 'Cap', 'Cap with beautiful design', 10), - // Product('assets/jeans_1.png', 'Jeans', 'Jeans for you', 20), - // Product('assets/womanshoe_3.png', 'Woman Shoes', - // 'Shoes with special discount', 30), - // Product('assets/bag_10.png', 'Bag Express', 'Bag for your shops', 40), - // Product('assets/jeans_3.png', 'Jeans', 'Beautiful Jeans', 102.33), - // Product('assets/ring_1.png', 'Silver Ring', 'Description', 52.33), - // Product('assets/shoeman_7.png', 'Shoes', 'Description', 62.33), - // Product('assets/headphone_9.png', 'Headphones', 'Description', 72.33), - ]; + final List products; + + const RecommendedList({Key? key,required this.products}) : super(key: key); + @override Widget build(BuildContext context) { @@ -71,8 +63,8 @@ class RecommendedList extends StatelessWidget { focalRadius: 0.1), ), child: Hero( - tag: products[index].imageUrl!, - child: Image.asset(products[index].imageUrl!))), + tag: products[index].sId!, + child: Image.network(products[index].imageUrl!))), ), ), staggeredTileBuilder: (int index) => diff --git a/lib/screens/main/components/tab_view.dart b/lib/screens/main/components/tab_view.dart index 8b5694c9..5bc928b2 100755 --- a/lib/screens/main/components/tab_view.dart +++ b/lib/screens/main/components/tab_view.dart @@ -1,104 +1,103 @@ -import 'package:ecommerce_int2/models/category.dart'; -import 'package:flutter/material.dart'; -import 'category_card.dart'; -import 'recommended_list.dart'; +// import 'package:ecommerce_int2/models/category.dart'; +// import 'package:flutter/material.dart'; +// import 'category_card.dart'; +// import 'recommended_list.dart'; -class TabView extends StatelessWidget { - List categories = [ - Category( - Color(0xffFCE183), - Color(0xffF68D7F), - 'Gadgets', - 'assets/jeans_5.png', - ), - Category( - Color(0xffF749A2), - Color(0xffFF7375), - 'Clothes', - 'assets/jeans_5.png', - ), - Category( - Color(0xff00E9DA), - Color(0xff5189EA), - 'Fashion', - 'assets/jeans_5.png', - ), - Category( - Color(0xffAF2D68), - Color(0xff632376), - 'Home', - 'assets/jeans_5.png', - ), - Category( - Color(0xff36E892), - Color(0xff33B2B9), - 'Beauty', - 'assets/jeans_5.png', - ), - Category( - Color(0xffF123C4), - Color(0xff668CEA), - 'Appliances', - 'assets/jeans_5.png', - ), - ]; +// class TabView extends StatelessWidget { +// List categories = [ +// Category( +// Color(0xffFCE183), +// Color(0xffF68D7F), +// 'Gadgets', +// 'assets/jeans_5.png', +// ), +// Category( +// Color(0xffF749A2), +// Color(0xffFF7375), +// 'Clothes', +// 'assets/jeans_5.png', +// ), +// Category( +// Color(0xff00E9DA), +// Color(0xff5189EA), +// 'Fashion', +// 'assets/jeans_5.png', +// ), +// Category( +// Color(0xffAF2D68), +// Color(0xff632376), +// 'Home', +// 'assets/jeans_5.png', +// ), +// Category( +// Color(0xff36E892), +// Color(0xff33B2B9), +// 'Beauty', +// 'assets/jeans_5.png', +// ), +// Category( +// Color(0xffF123C4), +// Color(0xff668CEA), +// 'Appliances', +// 'assets/jeans_5.png', +// ), +// ]; - final TabController tabController; +// final TabController tabController; - TabView({ - required this.tabController, - }); +// TabView({ +// required this.tabController, +// }); - @override - Widget build(BuildContext context) { - print(MediaQuery.of(context).size.height / 9); - return TabBarView( - physics: NeverScrollableScrollPhysics(), - controller: tabController, - children: [ - Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - margin: EdgeInsets.all(8.0), - height: MediaQuery.of(context).size.height / 9, - width: MediaQuery.of(context).size.width, - child: ListView.builder( - scrollDirection: Axis.horizontal, - itemCount: categories.length, - itemBuilder: (_, index) => CategoryCard( - category: categories[index], - ))), - SizedBox( - height: 16.0, - ), - Flexible(child: RecommendedList()), - ], - ), - Column(children: [ - SizedBox( - height: 16.0, - ), - Flexible(child: RecommendedList()) - ]), - Column(children: [ - SizedBox( - height: 16.0, - ), - Flexible(child: RecommendedList()) - ]), - Column(children: [ - SizedBox( - height: 16.0, - ), - Flexible(child: RecommendedList()) - ]), - Column(children: [ - SizedBox( - height: 16.0, - ), - Flexible(child: RecommendedList()) - ]), - ]); - } -} +// @override +// Widget build(BuildContext context) { +// return TabBarView( +// physics: NeverScrollableScrollPhysics(), +// controller: tabController, +// children: [ +// Column( +// mainAxisSize: MainAxisSize.min, +// children: [ +// Container( +// margin: EdgeInsets.all(8.0), +// height: MediaQuery.of(context).size.height / 9, +// width: MediaQuery.of(context).size.width, +// child: ListView.builder( +// scrollDirection: Axis.horizontal, +// itemCount: categories.length, +// itemBuilder: (_, index) => CategoryCard( +// category: categories[index], +// ))), +// SizedBox( +// height: 16.0, +// ), +// Flexible(child: RecommendedList()), +// ], +// ), +// Column(children: [ +// SizedBox( +// height: 16.0, +// ), +// Flexible(child: RecommendedList()) +// ]), +// Column(children: [ +// SizedBox( +// height: 16.0, +// ), +// Flexible(child: RecommendedList()) +// ]), +// Column(children: [ +// SizedBox( +// height: 16.0, +// ), +// Flexible(child: RecommendedList()) +// ]), +// Column(children: [ +// SizedBox( +// height: 16.0, +// ), +// Flexible(child: RecommendedList()) +// ]), +// ]); +// } +// } diff --git a/lib/screens/main/home.controller.dart b/lib/screens/main/home.controller.dart new file mode 100644 index 00000000..f73de49a --- /dev/null +++ b/lib/screens/main/home.controller.dart @@ -0,0 +1,79 @@ +import 'package:ecommerce_int2/data/models/category.model.dart'; +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/data/repository/product.repository.dart'; +import 'package:ecommerce_int2/utils/debounce.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; + +class HomeController extends GetxController { + final ProductRepository repository; + + HomeController(this.repository); + + TextEditingController searchController = TextEditingController(); + + RefreshController refreshController = + RefreshController(initialRefresh: false); + int currentPage = 1; + + int total = 0; + + ProductFilter filter = ProductFilter( + sortOrder: SortOrder(price: 1), + pageNumber: 1, + rating: 0, + min: 1, + max: 500000, + // subcategory: '', + // name: '', + // merchant: '', + order: 2); + + final Debounce debounce = Debounce(milliseconds: 2000); + + List list = []; + + @override + void onInit() { + getProduct(); + super.onInit(); + } + + Future getProduct() async { + try { + final res = await repository.getProducts(filter); + total = res.totalProducts ?? 0; + list.addAll(res.products!); + update(); + } on Exception catch (e) { + print(e); + } + } + + void onRefresh() async { + list.clear(); + currentPage = 1; + filter.pageNumber = 1; + await getProduct(); + refreshController.refreshCompleted(); + } + + void onLoadMore() async { + if(list.length == total) return; + ++currentPage; + filter.pageNumber = currentPage; + await getProduct(); + refreshController.loadComplete(); + } + + void onChanged(String value) { + debounce.run(() { + if (value.isNotEmpty) { + filter.name = value; + getProduct(); + update(); + } + }); + } +} diff --git a/lib/screens/main/main_page.dart b/lib/screens/main/main_page.dart index 21995296..4af411b8 100755 --- a/lib/screens/main/main_page.dart +++ b/lib/screens/main/main_page.dart @@ -1,5 +1,7 @@ import 'package:ecommerce_int2/data/models/product.model.dart'; import 'package:ecommerce_int2/screens/main/components/product_list.dart'; +import 'package:ecommerce_int2/screens/main/components/recommended_list.dart'; +import 'package:ecommerce_int2/screens/main/home.controller.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/utils/custom_background.dart'; import 'package:ecommerce_int2/screens/category/category_list_page.dart'; @@ -9,6 +11,7 @@ import 'package:ecommerce_int2/screens/search_products/search_page.dart'; import 'package:ecommerce_int2/screens/shop/check_out_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:get/get.dart'; import 'components/custom_bottom_bar.dart'; import 'components/tab_view.dart'; @@ -124,40 +127,40 @@ class _MainPageState extends State return Scaffold( bottomNavigationBar: CustomBottomBar(controller: bottomTabController), - body: CustomPaint( - painter: MainBackground(), - child: TabBarView( - controller: bottomTabController, - physics: NeverScrollableScrollPhysics(), - children: [ - SafeArea( - child: NestedScrollView( - headerSliverBuilder: - (BuildContext context, bool innerBoxIsScrolled) { - // These are the slivers that show up in the "outer" scroll view. - return [ - SliverToBoxAdapter( - child: topHeader, - ), - SliverToBoxAdapter( - child: ProductListView( - products: products, - ), - ), - SliverToBoxAdapter( - child: tabBar, - ) - ]; - }, - body: TabView( - tabController: tabController, - ), + body: GetBuilder( + init: HomeController(Get.find()), + builder: (controller) => CustomPaint( + painter: MainBackground(), + child: TabBarView( + controller: bottomTabController, + physics: NeverScrollableScrollPhysics(), + children: [ + SafeArea( + child: NestedScrollView( + headerSliverBuilder: + (BuildContext context, bool innerBoxIsScrolled) { + // These are the slivers that show up in the "outer" scroll view. + return [ + SliverToBoxAdapter( + child: appBar, + ), + SliverToBoxAdapter( + child: topHeader, + ), + SliverToBoxAdapter( + child: ProductListView( + products: controller.list.getRange(0, 3).toList(), + ), + ), + ]; + }, + body: RecommendedList(products: controller.list)), ), - ), - CategoryListPage(), - CheckOutPage(), - ProfilePage() - ], + CategoryListPage(), + CheckOutPage(), + ProfilePage() + ], + ), ), ), ); diff --git a/lib/screens/product/components/product_card.dart b/lib/screens/product/components/product_card.dart index 2c2879dd..d93f7703 100755 --- a/lib/screens/product/components/product_card.dart +++ b/lib/screens/product/components/product_card.dart @@ -25,6 +25,8 @@ class ProductCard extends StatelessWidget { padding: EdgeInsets.all(16.0), child: Image.network( product.imageUrl!, + width: 200, + height: 200, ), ), Flexible( diff --git a/lib/screens/product/view_product_page.dart b/lib/screens/product/view_product_page.dart index 813949a1..9fc26d32 100755 --- a/lib/screens/product/view_product_page.dart +++ b/lib/screens/product/view_product_page.dart @@ -1,11 +1,9 @@ -import 'package:ecommerce_int2/screens/product/components/rating_bottomSheet.dart'; import 'package:ecommerce_int2/screens/search_products/search_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import '../../data/models/product.model.dart'; import '../../utils/app_properties.dart'; -import 'components/color_list.dart'; import 'components/more_products.dart'; class ViewProductPage extends StatefulWidget { diff --git a/pubspec.lock b/pubspec.lock index 60d34c19..e00dce4f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -716,6 +716,34 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + webview_flutter: + dependency: "direct main" + description: + name: webview_flutter + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.4" + webview_flutter_android: + dependency: transitive + description: + name: webview_flutter_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.8.10" + webview_flutter_platform_interface: + dependency: transitive + description: + name: webview_flutter_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.9.1" + webview_flutter_wkwebview: + dependency: transitive + description: + name: webview_flutter_wkwebview + url: "https://pub.dartlang.org" + source: hosted + version: "2.7.5" win32: dependency: transitive description: From 22ec2e95e8c1799b2019b6e38ae15f276e5c11b1 Mon Sep 17 00:00:00 2001 From: manmaihuu <103487985+pdax-manmai@users.noreply.github.com> Date: Wed, 15 Jun 2022 00:18:23 +0700 Subject: [PATCH 34/49] Fix some isssues --- .flutter-plugins-dependencies | 2 +- lib/data/models/cart.model.dart | 5 +- lib/data/repository/cart.repository.dart | 2 +- lib/screens/main/main_page.dart | 65 ++++++++++--------- lib/screens/product/product_page.dart | 38 +++-------- lib/screens/shop/cart.controller.dart | 14 ++-- .../shop/components/shop_item_list.dart | 50 +++++++------- lib/screens/tracking/order_detail.view.dart | 17 +++-- lib/screens/tracking/tracking_page.dart | 52 +++++++-------- lib/utils/dependencies.dart | 2 + lib/utils/webview.dart | 6 +- 11 files changed, 123 insertions(+), 130 deletions(-) diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 8318f62a..1e9978c2 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]},{"name":"webview_flutter_wkwebview","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_wkwebview-2.7.5\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]},{"name":"webview_flutter_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_android-2.8.10\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2022-06-14 14:44:17.351912","version":"2.10.4"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]},{"name":"webview_flutter_wkwebview","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_wkwebview-2.7.5\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]},{"name":"webview_flutter_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_android-2.8.10\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2022-06-14 23:54:07.072332","version":"2.10.4"} \ No newline at end of file diff --git a/lib/data/models/cart.model.dart b/lib/data/models/cart.model.dart index eb84b23f..d17da25f 100644 --- a/lib/data/models/cart.model.dart +++ b/lib/data/models/cart.model.dart @@ -58,7 +58,9 @@ class CartModel { }); } user = json['user']; - merchant = json['merchant']; + merchant = json['merchant'] ?? (json['merchant'] == null + ? null + : json['merchant']['_id'] ); total = json['total']; isOrdered = json['isOrdered']; created = json['created']; @@ -80,4 +82,3 @@ class CartModel { return data; } } - diff --git a/lib/data/repository/cart.repository.dart b/lib/data/repository/cart.repository.dart index c995a7e6..9e1f26eb 100644 --- a/lib/data/repository/cart.repository.dart +++ b/lib/data/repository/cart.repository.dart @@ -22,7 +22,7 @@ class CartRepository { if (response.statusCode != 200) { throw Exception("Add product failed"); } - return response.body['_id']; + return response.body['_id'] ?? ''; } Future deleteProduct(String cartId, String productID) async { diff --git a/lib/screens/main/main_page.dart b/lib/screens/main/main_page.dart index 4af411b8..d81454d5 100755 --- a/lib/screens/main/main_page.dart +++ b/lib/screens/main/main_page.dart @@ -131,36 +131,41 @@ class _MainPageState extends State init: HomeController(Get.find()), builder: (controller) => CustomPaint( painter: MainBackground(), - child: TabBarView( - controller: bottomTabController, - physics: NeverScrollableScrollPhysics(), - children: [ - SafeArea( - child: NestedScrollView( - headerSliverBuilder: - (BuildContext context, bool innerBoxIsScrolled) { - // These are the slivers that show up in the "outer" scroll view. - return [ - SliverToBoxAdapter( - child: appBar, - ), - SliverToBoxAdapter( - child: topHeader, - ), - SliverToBoxAdapter( - child: ProductListView( - products: controller.list.getRange(0, 3).toList(), - ), - ), - ]; - }, - body: RecommendedList(products: controller.list)), - ), - CategoryListPage(), - CheckOutPage(), - ProfilePage() - ], - ), + child: controller.list.isEmpty + ? Center( + child: CircularProgressIndicator.adaptive(), + ) + : TabBarView( + controller: bottomTabController, + physics: NeverScrollableScrollPhysics(), + children: [ + SafeArea( + child: NestedScrollView( + headerSliverBuilder: + (BuildContext context, bool innerBoxIsScrolled) { + // These are the slivers that show up in the "outer" scroll view. + return [ + SliverToBoxAdapter( + child: appBar, + ), + SliverToBoxAdapter( + child: topHeader, + ), + SliverToBoxAdapter( + child: ProductListView( + products: + controller.list.getRange(0, 3).toList(), + ), + ), + ]; + }, + body: RecommendedList(products: controller.list)), + ), + CategoryListPage(), + CheckOutPage(), + ProfilePage() + ], + ), ), ), ); diff --git a/lib/screens/product/product_page.dart b/lib/screens/product/product_page.dart index 1b770a2b..80b7d83a 100755 --- a/lib/screens/product/product_page.dart +++ b/lib/screens/product/product_page.dart @@ -1,6 +1,9 @@ import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/screens/main/components/product_list.dart'; +import 'package:ecommerce_int2/screens/search_products/search_controller.dart'; import 'package:ecommerce_int2/screens/shop/cart.controller.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; +import 'package:ecommerce_int2/utils/cart_button.widget.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -11,7 +14,6 @@ class ProductPage extends StatelessWidget { ProductPage({required this.product}); - @override Widget build(BuildContext context) { final controller = Get.find(); @@ -55,6 +57,7 @@ class ProductPage extends StatelessWidget { style: const TextStyle( color: darkGrey, fontWeight: FontWeight.w500, fontSize: 18.0), ), + actions: [CartButton()], ), body: SingleChildScrollView( child: Column( @@ -79,33 +82,6 @@ class ProductPage extends StatelessWidget { SizedBox( height: 24.0, ), - Padding( - padding: const EdgeInsets.only(left: 20.0), - child: Row( - children: [ - Container( - width: 90, - height: 40, - decoration: BoxDecoration( - color: Color.fromRGBO(253, 192, 84, 1), - borderRadius: BorderRadius.circular(4.0), - border: Border.all(color: Color(0xFFFFFFFF), width: 0.5), - ), - child: Center( - child: new Text("Details", - style: const TextStyle( - color: const Color(0xeefefefe), - fontWeight: FontWeight.w300, - fontStyle: FontStyle.normal, - fontSize: 12.0)), - ), - ) - ], - ), - ), - SizedBox( - height: 16.0, - ), Padding( padding: EdgeInsets.only(left: 20.0, right: 40.0, bottom: 20), child: new Text(product.description ?? "", @@ -134,6 +110,12 @@ class ProductPage extends StatelessWidget { child: Center(child: viewProductButton), ), ), + Text('Merchant ${ product.merchant}'), + ProductListView( + products: Get.find() + .list + .where((element) => element.merchant == product.merchant) + .toList()) ], ), ), diff --git a/lib/screens/shop/cart.controller.dart b/lib/screens/shop/cart.controller.dart index 757fd746..45ad3f44 100644 --- a/lib/screens/shop/cart.controller.dart +++ b/lib/screens/shop/cart.controller.dart @@ -14,9 +14,9 @@ class CartController extends GetxController { CartController(this.repository); List get products { - if(carts == null) return []; + if (carts == null) return []; List products = []; - for(CartModel cart in carts!) { + for (CartModel cart in carts!) { products.addAll(cart.products!); } return products; @@ -37,9 +37,11 @@ class CartController extends GetxController { return '$result VND'; } - Future getCart() async { - repository.getCarts().then((value) => carts = value); - update(); + Future getCart() async { + repository.getCarts().then((value) { + carts = value; + update(); + }); } void remove(Product product) { @@ -79,6 +81,6 @@ class CartController extends GetxController { void checkOut() async { final List orderIds = await repository.checkOutCart(carts!); - Get.to(AddAddressPage(), arguments: orderIds); + Get.to(() => AddAddressPage(), arguments: orderIds); } } diff --git a/lib/screens/shop/components/shop_item_list.dart b/lib/screens/shop/components/shop_item_list.dart index 3781717d..65a7d35b 100755 --- a/lib/screens/shop/components/shop_item_list.dart +++ b/lib/screens/shop/components/shop_item_list.dart @@ -45,36 +45,38 @@ class _ShopItemListState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - widget.product.name ?? 'Product', - textAlign: TextAlign.right, - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 12, - color: darkGrey, - ), - ), Align( alignment: Alignment.centerRight, child: Container( width: 160, padding: const EdgeInsets.only( left: 32.0, top: 8.0, bottom: 8.0), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - ColorOption(Colors.red), - Text( - '\$${widget.product.price ?? widget.product.purchasePrice ?? 0}', - textAlign: TextAlign.center, - style: TextStyle( - color: darkGrey, - fontWeight: FontWeight.bold, - fontSize: 18.0), - ) - ], - ), + child: Column(children: [ + Text( + widget.product.name ?? 'Product', + textAlign: TextAlign.right, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18, + color: darkGrey, + ), + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + ColorOption(Colors.red), + Text( + '\$${widget.product.price ?? widget.product.purchasePrice ?? 0}', + textAlign: TextAlign.center, + style: TextStyle( + color: darkGrey, + fontWeight: FontWeight.bold, + fontSize: 18.0), + ) + ], + ), + ]), ), ) ], diff --git a/lib/screens/tracking/order_detail.view.dart b/lib/screens/tracking/order_detail.view.dart index 665cf0e6..614fdabf 100644 --- a/lib/screens/tracking/order_detail.view.dart +++ b/lib/screens/tracking/order_detail.view.dart @@ -73,9 +73,10 @@ class OrderDetail extends StatelessWidget { height: 130, width: Get.width)) .toList(), - if (controller.detail!.canCancel) + const SizedBox(height: 16), + if (controller.detail!.isPayWithCash) GestureDetector( - onTap: (() => controller.remove(orderId)), + onTap: (() => controller.makePayment(orderId)), child: Center( child: Container( height: 40, @@ -95,7 +96,7 @@ class OrderDetail extends StatelessWidget { borderRadius: BorderRadius.circular(9.0)), child: Center( - child: Text("Cancle Order", + child: Text("Pay with PayPal", style: const TextStyle( color: const Color(0xfffefefe), @@ -106,9 +107,10 @@ class OrderDetail extends StatelessWidget { ), ), ), - if (controller.detail!.isPayWithCash) + const SizedBox(height: 16), + if (controller.detail!.canCancel) GestureDetector( - onTap: (() => controller.makePayment(orderId)), + onTap: (() => controller.remove(orderId)), child: Center( child: Container( height: 40, @@ -128,7 +130,7 @@ class OrderDetail extends StatelessWidget { borderRadius: BorderRadius.circular(9.0)), child: Center( - child: Text("Pay with PayPal", + child: Text("Cancle Order", style: const TextStyle( color: const Color(0xfffefefe), @@ -138,10 +140,11 @@ class OrderDetail extends StatelessWidget { ), ), ), - ) + ), ], ) : SizedBox.shrink(), + ), ), ), diff --git a/lib/screens/tracking/tracking_page.dart b/lib/screens/tracking/tracking_page.dart index 506af33c..77c5e3d2 100644 --- a/lib/screens/tracking/tracking_page.dart +++ b/lib/screens/tracking/tracking_page.dart @@ -64,37 +64,31 @@ class _TrackingPageState extends State { body: SafeArea( child: LayoutBuilder( builder: (_, constraints) => SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - maxHeight: constraints.maxHeight - 48, - ), - child: Column( - // physics: NeverScrollableScrollPhysics(), - children: [ - ...controller.orders - .map((order) => GestureDetector( - onTap: (() => controller.getOrderDetail(order)), - child: Container( - width: Get.width, - child: Card( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column(children: [ - Text('Order Id: ${order.sId ?? 'Order'}'), - Text('Deliver status: ${order.status ?? ''}'), - Text('Payment status: ${order.paymentStatus ?? ''}'), - Text('Merchant: ${order.merchant ?? ''}'), - Text('Date: ${order.created ?? ''}') - ], - crossAxisAlignment: CrossAxisAlignment.start, - ), + child: Column( + children: [ + ...controller.orders.reversed + .map((order) => GestureDetector( + onTap: (() => controller.getOrderDetail(order)), + child: Container( + width: Get.width, + child: Card( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column(children: [ + Text('Order Id: ${order.sId ?? 'Order'}'), + Text('Deliver status: ${order.status ?? ''}'), + Text('Payment status: ${order.paymentStatus ?? ''}'), + Text('Merchant: ${order.merchant ?? ''}'), + Text('Date: ${order.created ?? ''}') + ], + crossAxisAlignment: CrossAxisAlignment.start, ), ), - ), - )) - .toList() - ], - ), + ), + ), + )) + .toList() + ], ), ), ), diff --git a/lib/utils/dependencies.dart b/lib/utils/dependencies.dart index b0c3ecaa..8473d016 100644 --- a/lib/utils/dependencies.dart +++ b/lib/utils/dependencies.dart @@ -10,6 +10,7 @@ import 'package:ecommerce_int2/data/repository/cart.repository.dart'; import 'package:ecommerce_int2/data/repository/category.repository.dart'; import 'package:ecommerce_int2/data/repository/order.repository.dart'; import 'package:ecommerce_int2/data/repository/product.repository.dart'; +import 'package:ecommerce_int2/screens/search_products/search_controller.dart'; import 'package:ecommerce_int2/screens/shop/cart.controller.dart'; import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:ecommerce_int2/services/network.service.dart'; @@ -33,6 +34,7 @@ class Dependency { ..put(CartController(Get.find()), permanent: true) ..put(OrderProvider(Get.find())) ..put(OrderRepository(Get.find())) + ..put(SearchProductController(Get.find())) ; } } diff --git a/lib/utils/webview.dart b/lib/utils/webview.dart index 2ef1ae1e..d32473de 100644 --- a/lib/utils/webview.dart +++ b/lib/utils/webview.dart @@ -21,8 +21,10 @@ import 'package:webview_flutter/webview_flutter.dart'; @override Widget build(BuildContext context) { - return WebView( - initialUrl: widget.url, + return SafeArea( + child: WebView( + initialUrl: widget.url, + ), ); } } \ No newline at end of file From 0e9ca53b0857b193b670521ca36ffcb3adb5d4ae Mon Sep 17 00:00:00 2001 From: manmaihuu <103487985+pdax-manmai@users.noreply.github.com> Date: Thu, 16 Jun 2022 15:35:52 +0700 Subject: [PATCH 35/49] Fix bugs --- .flutter-plugins-dependencies | 2 +- lib/data/models/cart.model.dart | 5 +- lib/screens/main/components/product_list.dart | 102 ++++++++---------- lib/screens/shop/cart.controller.dart | 4 +- 4 files changed, 53 insertions(+), 60 deletions(-) diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 1e9978c2..3c5e4f40 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]},{"name":"webview_flutter_wkwebview","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_wkwebview-2.7.5\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]},{"name":"webview_flutter_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_android-2.8.10\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2022-06-14 23:54:07.072332","version":"2.10.4"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]},{"name":"webview_flutter_wkwebview","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_wkwebview-2.7.5\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]},{"name":"webview_flutter_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_android-2.8.10\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2022-06-16 15:24:57.459862","version":"2.10.4"} \ No newline at end of file diff --git a/lib/data/models/cart.model.dart b/lib/data/models/cart.model.dart index d17da25f..369d5383 100644 --- a/lib/data/models/cart.model.dart +++ b/lib/data/models/cart.model.dart @@ -58,9 +58,8 @@ class CartModel { }); } user = json['user']; - merchant = json['merchant'] ?? (json['merchant'] == null - ? null - : json['merchant']['_id'] ); + merchant = json['merchant'] != null ? + (json['merchant'] is String? ? json['merchant'] : json['merchant']['_id']) : ''; total = json['total']; isOrdered = json['isOrdered']; created = json['created']; diff --git a/lib/screens/main/components/product_list.dart b/lib/screens/main/components/product_list.dart index 87f4265c..a59e1220 100755 --- a/lib/screens/main/components/product_list.dart +++ b/lib/screens/main/components/product_list.dart @@ -3,6 +3,7 @@ import 'package:ecommerce_int2/data/models/product.model.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/product/product_page.dart'; import 'package:flutter/material.dart'; +import 'package:get/get.dart'; class ProductListView extends StatelessWidget { List products; @@ -109,55 +110,57 @@ class ProductCard extends StatelessWidget { return InkWell( onTap: () => Navigator.of(context).push( MaterialPageRoute(builder: (_) => ProductPage(product: product))), - child: Stack( - children: [ - Container( - margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - height: height, - width: width, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(24)), - color: mediumYellow, + child: Container( + margin: const EdgeInsets.symmetric( vertical: 8), + height: height, + width: Get.width, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(8)), + color: mediumYellow, + ), + child: Row(children: [ + Hero( + tag: product.sId!, + child: Image.network( + product.imageUrl!, + height: 130, + width: 130, + fit: BoxFit.contain, + ), + ), + Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - IconButton( - icon: Icon(Icons.favorite_border), - onPressed: () {}, - color: Colors.white, - ), Column( children: [ - Align( - alignment: Alignment.topLeft, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - product.name ?? "", - style: - TextStyle(color: Colors.white, fontSize: 16.0), - ), - )), - Align( - alignment: Alignment.topRight, - child: Container( - margin: const EdgeInsets.only(bottom: 12.0), - padding: const EdgeInsets.fromLTRB(8.0, 4.0, 12.0, 4.0), - decoration: BoxDecoration( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(10), - bottomLeft: Radius.circular(10)), - color: Color.fromRGBO(224, 69, 10, 1), - ), - child: Text( - '\$${product.price ?? product.purchasePrice ?? 0}', - style: TextStyle( - color: Colors.white, - fontSize: 18, - fontWeight: FontWeight.bold), - ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + product.name ?? "", + style: TextStyle( + color: Colors.white, fontSize: 16.0), + ), + ), + Container( + margin: const EdgeInsets.only(bottom: 12.0), + padding: + const EdgeInsets.fromLTRB(8.0, 4.0, 12.0, 4.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(10), + bottomLeft: Radius.circular(10)), + color: Color.fromRGBO(224, 69, 10, 1), + ), + child: Text( + '\$${product.price ?? product.purchasePrice ?? 0}', + style: TextStyle( + color: Colors.white, + fontSize: 18, + fontWeight: FontWeight.bold), ), ), ], @@ -165,18 +168,7 @@ class ProductCard extends StatelessWidget { ], ), ), - Positioned( - child: Hero( - tag: product.imageUrl!, - child: Image.network( - product.imageUrl!, - height: height / 1.7, - width: width / 1.4, - fit: BoxFit.contain, - ), - ), - ), - ], + ]), ), ); } diff --git a/lib/screens/shop/cart.controller.dart b/lib/screens/shop/cart.controller.dart index 45ad3f44..64179768 100644 --- a/lib/screens/shop/cart.controller.dart +++ b/lib/screens/shop/cart.controller.dart @@ -32,7 +32,7 @@ class CartController extends GetxController { String get total { int result = 0; products.forEach((element) { - result += element.totalPrice ?? 0; + result += element.price ?? element.purchasePrice ?? 0; }); return '$result VND'; } @@ -80,7 +80,9 @@ class CartController extends GetxController { } void checkOut() async { + MessageDialog.showLoading(); final List orderIds = await repository.checkOutCart(carts!); + MessageDialog.hideLoading(); Get.to(() => AddAddressPage(), arguments: orderIds); } } From bbbd53450b7b22feef29613c49d819a73741c096 Mon Sep 17 00:00:00 2001 From: manmaihuu <103487985+pdax-manmai@users.noreply.github.com> Date: Thu, 16 Jun 2022 16:09:27 +0700 Subject: [PATCH 36/49] Add merchant page --- .flutter-plugins-dependencies | 2 +- .../merchant/components/credit_card.dart | 24 ++++ .../merchant/components/shop_item_list.dart | 122 ++++++++++++++++ lib/screens/merchant/merchant.controller.dart | 99 +++++++++++++ lib/screens/merchant/merchant.view.dart | 136 ++++++++++++++++++ lib/screens/product/product_page.dart | 12 +- 6 files changed, 393 insertions(+), 2 deletions(-) create mode 100644 lib/screens/merchant/components/credit_card.dart create mode 100644 lib/screens/merchant/components/shop_item_list.dart create mode 100644 lib/screens/merchant/merchant.controller.dart create mode 100644 lib/screens/merchant/merchant.view.dart diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 3c5e4f40..0ed29738 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]},{"name":"webview_flutter_wkwebview","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_wkwebview-2.7.5\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]},{"name":"webview_flutter_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_android-2.8.10\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2022-06-16 15:24:57.459862","version":"2.10.4"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]},{"name":"webview_flutter_wkwebview","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_wkwebview-2.7.5\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]},{"name":"webview_flutter_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_android-2.8.10\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2022-06-16 16:07:07.680593","version":"2.10.4"} \ No newline at end of file diff --git a/lib/screens/merchant/components/credit_card.dart b/lib/screens/merchant/components/credit_card.dart new file mode 100644 index 00000000..47ca4ec2 --- /dev/null +++ b/lib/screens/merchant/components/credit_card.dart @@ -0,0 +1,24 @@ +import 'package:flutter/material.dart'; + +class CreditCard extends StatelessWidget { + final String text; + + const CreditCard({Key? key,required this.text}) : super(key: key); + @override + Widget build(BuildContext context) { + return Container( + height: 50, + width: 250, + padding: EdgeInsets.all(16.0), + decoration: BoxDecoration( + color: Colors.deepPurple[700], + borderRadius: BorderRadius.all(Radius.circular(10))), + child: Center( + child: Text( + text, + style: TextStyle(color: Colors.white), + ), + ), + ); + } +} diff --git a/lib/screens/merchant/components/shop_item_list.dart b/lib/screens/merchant/components/shop_item_list.dart new file mode 100644 index 00000000..65a7d35b --- /dev/null +++ b/lib/screens/merchant/components/shop_item_list.dart @@ -0,0 +1,122 @@ +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; +import 'package:ecommerce_int2/screens/product/components/color_list.dart'; +import 'package:ecommerce_int2/screens/product/components/shop_product.dart'; +import 'package:flutter/material.dart'; +import 'package:numberpicker/numberpicker.dart'; + +class ShopItemList extends StatefulWidget { + final Product product; + final VoidCallback onRemove; + + ShopItemList(this.product, {required this.onRemove}); + + @override + _ShopItemListState createState() => _ShopItemListState(); +} + +class _ShopItemListState extends State { + int quantity = 1; + + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.symmetric(vertical: 10), + height: 130, + child: Stack( + children: [ + Align( + alignment: Alignment(0, 0.8), + child: Container( + height: 100, + margin: EdgeInsets.symmetric(horizontal: 16.0), + decoration: BoxDecoration( + color: Colors.white, + boxShadow: shadow, + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(10), + bottomRight: Radius.circular(10))), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Container( + padding: EdgeInsets.only(top: 12.0, right: 12.0), + width: 200, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Align( + alignment: Alignment.centerRight, + child: Container( + width: 160, + padding: const EdgeInsets.only( + left: 32.0, top: 8.0, bottom: 8.0), + child: Column(children: [ + Text( + widget.product.name ?? 'Product', + textAlign: TextAlign.right, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18, + color: darkGrey, + ), + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + ColorOption(Colors.red), + Text( + '\$${widget.product.price ?? widget.product.purchasePrice ?? 0}', + textAlign: TextAlign.center, + style: TextStyle( + color: darkGrey, + fontWeight: FontWeight.bold, + fontSize: 18.0), + ) + ], + ), + ]), + ), + ) + ], + ), + ), + Theme( + data: ThemeData( + accentColor: Colors.black, + textTheme: TextTheme( + headline6: TextStyle( + fontFamily: 'Montserrat', + fontSize: 14, + color: Colors.black, + fontWeight: FontWeight.bold), + bodyText1: TextStyle( + fontFamily: 'Montserrat', + fontSize: 12, + color: Colors.grey[400], + ), + )), + child: NumberPicker( + value: quantity, + minValue: 1, + maxValue: 10, + onChanged: (value) { + setState(() { + quantity = value; + }); + }, + )) + ])), + ), + Positioned( + top: 5, + child: ShopProductDisplay( + widget.product, + onPressed: widget.onRemove, + )), + ], + ), + ); + } +} diff --git a/lib/screens/merchant/merchant.controller.dart b/lib/screens/merchant/merchant.controller.dart new file mode 100644 index 00000000..045ec837 --- /dev/null +++ b/lib/screens/merchant/merchant.controller.dart @@ -0,0 +1,99 @@ +import 'package:card_swiper/card_swiper.dart'; +import 'package:ecommerce_int2/data/models/cart.model.dart'; +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/data/repository/cart.repository.dart'; +import 'package:ecommerce_int2/screens/address/add_address_page.dart'; +import 'package:ecommerce_int2/screens/search_products/search_controller.dart'; +import 'package:ecommerce_int2/utils/message_dialog.dart'; +import 'package:get/get.dart'; + +class MerchantController extends GetxController { + final CartRepository repository; + + final SwiperController swiperController = SwiperController(); + + MerchantController(this.repository); + + List get products { + return Get.find() + .list + .where((element) => element.merchant == merchant) + .toList(); + } + + List? carts; + String? merchantId; + + String get merchant => merchantId ?? 'Merchant'; + String get des => 'A shop sellling high quality assets'; + + @override + onInit() { + getArg(); + super.onInit(); + } + + void getArg() { + final arg = Get.arguments; + if (arg != null && arg is String) { + merchantId = arg; + } + } + + String get total { + int result = 0; + products.forEach((element) { + result += element.price ?? element.purchasePrice ?? 0; + }); + return '$result VND'; + } + + Future getCart() async { + repository.getCarts().then((value) { + carts = value; + update(); + }); + } + + void remove(Product product) { + CartModel? cart = carts! + .firstWhereOrNull((element) => element.products!.contains(product)); + if (cart == null) { + MessageDialog.showToast("There is something wrong!!"); + return; + } + repository.deleteProduct(cart.sId!, product.sId!); + cart.products!.remove(product); + update(); + } + + void addProduct(Product product, {int? quantity}) async { + try { + AddProductParam param = AddProductParam(products: [ + ProductParam( + product: product.sId, + price: product.price, + merchant: product.merchant, + quantity: quantity) + ]); + final String cartId = await repository.addProduct(param); + MessageDialog.showToast("Added product to cart"); + int index = carts!.indexWhere((element) => element.sId == cartId); + if (index != -1) { + carts![index].products!.add(product); + } else { + carts!.add(CartModel(sId: cartId, products: [product])); + } + update(); + } on Exception catch (e) { + print(e); + } + } + + void checkOut() async { + MessageDialog.showLoading(); + final List orderIds = await repository.checkOutCart(carts!); + MessageDialog.hideLoading(); + Get.to(() => AddAddressPage(), arguments: orderIds); + } +} diff --git a/lib/screens/merchant/merchant.view.dart b/lib/screens/merchant/merchant.view.dart new file mode 100644 index 00000000..30988db5 --- /dev/null +++ b/lib/screens/merchant/merchant.view.dart @@ -0,0 +1,136 @@ +import 'package:ecommerce_int2/data/repository/cart.repository.dart'; +import 'package:ecommerce_int2/screens/merchant/merchant.controller.dart'; +import 'package:ecommerce_int2/screens/product/product_page.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; +import 'package:get/get.dart'; + +class MerchantPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + backgroundColor: Colors.transparent, + elevation: 0.0, + iconTheme: IconThemeData(color: darkGrey), + title: Text( + 'Merchant', + style: TextStyle( + color: darkGrey, fontWeight: FontWeight.w500, fontSize: 18.0), + ), + ), + body: GetBuilder( + init: MerchantController(Get.find()), + builder: (controller) => SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), + color: yellow, + width: Get.width, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + controller.merchant, + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 16), + ), + const SizedBox(height: 40), + Text( + controller.des, + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 16), + ) + ], + ), + ), + Expanded( + child: StaggeredGridView.countBuilder( + physics: NeverScrollableScrollPhysics(), + padding: EdgeInsets.zero, + crossAxisCount: 4, + itemCount: controller.products.length, + itemBuilder: (BuildContext context, int index) => + new ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(5.0)), + child: InkWell( + onTap: () => Navigator.of(context).push(MaterialPageRoute( + builder: (_) => ProductPage( + product: controller.products[index]))), + child: Container( + decoration: BoxDecoration( + gradient: RadialGradient( + colors: [ + Colors.grey.withOpacity(0.3), + Colors.grey.withOpacity(0.7), + ], + center: Alignment(0, 0), + radius: 0.6, + focal: Alignment(0, 0), + focalRadius: 0.1), + ), + child: Hero( + tag: controller.products[index].sId!, + child: Image.network( + controller.products[index].imageUrl!))), + ), + ), + staggeredTileBuilder: (int index) => + StaggeredTile.count(2, index.isEven ? 3 : 2), + mainAxisSpacing: 4.0, + crossAxisSpacing: 4.0, + ), + ), + SizedBox(height: 24), + ], + ), + ), + ), + ); + } +} + +class Scroll extends CustomPainter { + @override + void paint(Canvas canvas, Size size) { + // TODO: implement paint + + LinearGradient grT = LinearGradient( + colors: [Colors.transparent, Colors.black26], + begin: Alignment.topCenter, + end: Alignment.bottomCenter); + LinearGradient grB = LinearGradient( + colors: [Colors.transparent, Colors.black26], + begin: Alignment.bottomCenter, + end: Alignment.topCenter); + + canvas.drawRect( + Rect.fromLTRB(0, 0, size.width, 30), + Paint() + ..shader = grT.createShader(Rect.fromLTRB(0, 0, size.width, 30))); + + canvas.drawRect(Rect.fromLTRB(0, 30, size.width, size.height - 40), + Paint()..color = Color.fromRGBO(50, 50, 50, 0.4)); + + canvas.drawRect( + Rect.fromLTRB(0, size.height - 40, size.width, size.height), + Paint() + ..shader = grB.createShader( + Rect.fromLTRB(0, size.height - 40, size.width, size.height))); + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) { + // TODO: implement shouldRepaint + return false; + } +} diff --git a/lib/screens/product/product_page.dart b/lib/screens/product/product_page.dart index 80b7d83a..f2949220 100755 --- a/lib/screens/product/product_page.dart +++ b/lib/screens/product/product_page.dart @@ -1,5 +1,6 @@ import 'package:ecommerce_int2/data/models/product.model.dart'; import 'package:ecommerce_int2/screens/main/components/product_list.dart'; +import 'package:ecommerce_int2/screens/merchant/merchant.view.dart'; import 'package:ecommerce_int2/screens/search_products/search_controller.dart'; import 'package:ecommerce_int2/screens/shop/cart.controller.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; @@ -110,7 +111,16 @@ class ProductPage extends StatelessWidget { child: Center(child: viewProductButton), ), ), - Text('Merchant ${ product.merchant}'), + GestureDetector( + onTap: () => Get.to(() => MerchantPage(), arguments: product.merchant), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Text( + '${product.merchant ?? 'Merchant'}', + style: TextStyle(fontSize: 18), + ), + ), + ), ProductListView( products: Get.find() .list From 0c0c1e63dcb2f09523a2e0abb4017c14345472f2 Mon Sep 17 00:00:00 2001 From: manmaihuu <103487985+pdax-manmai@users.noreply.github.com> Date: Thu, 16 Jun 2022 16:23:21 +0700 Subject: [PATCH 37/49] Fix bug in merchant view --- lib/screens/merchant/merchant.view.dart | 129 ++++++++++++------------ 1 file changed, 63 insertions(+), 66 deletions(-) diff --git a/lib/screens/merchant/merchant.view.dart b/lib/screens/merchant/merchant.view.dart index 30988db5..13c28586 100644 --- a/lib/screens/merchant/merchant.view.dart +++ b/lib/screens/merchant/merchant.view.dart @@ -23,76 +23,73 @@ class MerchantPage extends StatelessWidget { ), body: GetBuilder( init: MerchantController(Get.find()), - builder: (controller) => SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), - color: yellow, - width: Get.width, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - controller.merchant, - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 16), - ), - const SizedBox(height: 40), - Text( - controller.des, - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 16), - ) - ], - ), + builder: (controller) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), + color: yellow, + width: Get.width, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + controller.merchant, + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 16), + ), + const SizedBox(height: 40), + Text( + controller.des, + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 16), + ) + ], ), - Expanded( - child: StaggeredGridView.countBuilder( - physics: NeverScrollableScrollPhysics(), - padding: EdgeInsets.zero, - crossAxisCount: 4, - itemCount: controller.products.length, - itemBuilder: (BuildContext context, int index) => - new ClipRRect( - borderRadius: BorderRadius.all(Radius.circular(5.0)), - child: InkWell( - onTap: () => Navigator.of(context).push(MaterialPageRoute( - builder: (_) => ProductPage( - product: controller.products[index]))), - child: Container( - decoration: BoxDecoration( - gradient: RadialGradient( - colors: [ - Colors.grey.withOpacity(0.3), - Colors.grey.withOpacity(0.7), - ], - center: Alignment(0, 0), - radius: 0.6, - focal: Alignment(0, 0), - focalRadius: 0.1), - ), - child: Hero( - tag: controller.products[index].sId!, - child: Image.network( - controller.products[index].imageUrl!))), - ), + ), + Expanded( + child: StaggeredGridView.countBuilder( + padding: EdgeInsets.zero, + crossAxisCount: 4, + itemCount: controller.products.length, + itemBuilder: (BuildContext context, int index) => + new ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(5.0)), + child: InkWell( + onTap: () => Navigator.of(context).push(MaterialPageRoute( + builder: (_) => ProductPage( + product: controller.products[index]))), + child: Container( + decoration: BoxDecoration( + gradient: RadialGradient( + colors: [ + Colors.grey.withOpacity(0.3), + Colors.grey.withOpacity(0.7), + ], + center: Alignment(0, 0), + radius: 0.6, + focal: Alignment(0, 0), + focalRadius: 0.1), + ), + child: Hero( + tag: controller.products[index].sId!, + child: Image.network( + controller.products[index].imageUrl!))), ), - staggeredTileBuilder: (int index) => - StaggeredTile.count(2, index.isEven ? 3 : 2), - mainAxisSpacing: 4.0, - crossAxisSpacing: 4.0, ), + staggeredTileBuilder: (int index) => + StaggeredTile.count(2, index.isEven ? 3 : 2), + mainAxisSpacing: 4.0, + crossAxisSpacing: 4.0, ), - SizedBox(height: 24), - ], - ), + ), + SizedBox(height: 24), + ], ), ), ); From 106a61e867f748456d6a44b44a6c42a1fbe66fec Mon Sep 17 00:00:00 2001 From: manmaihuu <103487985+pdax-manmai@users.noreply.github.com> Date: Thu, 16 Jun 2022 16:51:04 +0700 Subject: [PATCH 38/49] Update UI for order list and order detail view --- lib/data/models/order.model.dart | 29 ++++++-- lib/screens/tracking/order_detail.view.dart | 73 +++++++++++++-------- lib/screens/tracking/row_text.widget.dart | 50 ++++++++++++++ lib/screens/tracking/tracking_page.dart | 47 +++++++++---- 4 files changed, 149 insertions(+), 50 deletions(-) create mode 100644 lib/screens/tracking/row_text.widget.dart diff --git a/lib/data/models/order.model.dart b/lib/data/models/order.model.dart index 2d1a8f56..768db48f 100644 --- a/lib/data/models/order.model.dart +++ b/lib/data/models/order.model.dart @@ -1,4 +1,5 @@ import 'package:ecommerce_int2/data/models/cart.model.dart'; +import 'package:intl/intl.dart'; class OrderResponse { bool? success; @@ -37,6 +38,14 @@ class Order { String? created; int? iV; + String get createdDate { + if (created == null) return ''; + final date = DateTime.tryParse(created!); + if (date == null) return ''; + final res = DateFormat("yyyy-MM-dd HH:mm:ss aa").format(date); + return res; + } + Order( {this.cart, this.user, @@ -117,9 +126,8 @@ class CompleteOrderResponse { CompleteOrderResponse.fromJson(Map json) { success = json['success']; message = json['message']; - orderDoc = json['data'] != null - ? new OrderDoc.fromJson(json['data']) - : null; + orderDoc = + json['data'] != null ? new OrderDoc.fromJson(json['data']) : null; } Map toJson() { @@ -224,9 +232,8 @@ class DetailOrderResponse { DetailOrderResponse.fromJson(Map json) { success = json['success']; - orderDoc = json['data'] != null - ? new OrderDocDetail.fromJson(json['data']) - : null; + orderDoc = + json['data'] != null ? new OrderDocDetail.fromJson(json['data']) : null; } Map toJson() { @@ -252,6 +259,14 @@ class OrderDocDetail { int? iV; String? address; + String get createdDate { + if (created == null) return ''; + final date = DateTime.tryParse(created!); + if (date == null) return ''; + final res = DateFormat("yyyy-MM-dd HH:mm:ss aa").format(date); + return res; + } + bool get isPayWithCash => payment == 'CASH'; bool get canCancel => status == 'NOT_PROCESS'; @@ -300,4 +315,4 @@ class OrderDocDetail { data['address'] = this.address; return data; } -} \ No newline at end of file +} diff --git a/lib/screens/tracking/order_detail.view.dart b/lib/screens/tracking/order_detail.view.dart index 614fdabf..eeb6dac6 100644 --- a/lib/screens/tracking/order_detail.view.dart +++ b/lib/screens/tracking/order_detail.view.dart @@ -2,6 +2,7 @@ import 'package:ecommerce_int2/data/repository/order.repository.dart'; import 'package:ecommerce_int2/screens/main/components/product_list.dart'; import 'package:ecommerce_int2/screens/tracking/order.controller.dart'; import 'package:ecommerce_int2/screens/tracking/order_detail.controller.dart'; +import 'package:ecommerce_int2/screens/tracking/row_text.widget.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -57,15 +58,22 @@ class OrderDetail extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 24), - Text( - 'Deliver status: ${controller.detail?.status ?? ''}'), - Text( - 'Payment status: ${controller.detail?.paymentStatus ?? ''}'), - Text( - 'Merchant: ${controller.detail?.merchant ?? ''}'), - Text( - 'Date: ${controller.detail?.created ?? ''}'), - Text('Products'), + RowTextWidget( + text1: 'Deliver status', + text2: + ' ${controller.detail?.status ?? ''}'), + RowTextWidget( + text1: 'Payment status', + text2: + '${controller.detail?.paymentStatus ?? ''}'), + RowTextWidget( + text1: 'Merchant', + text2: + '${controller.detail?.merchant ?? ''}'), + RowTextWidget( + text1: 'Date', + text2: + '${controller.detail?.createdDate ?? ''}'), const SizedBox(height: 16), ...controller.detail!.cart!.products! .map((product) => ProductCard( @@ -73,16 +81,18 @@ class OrderDetail extends StatelessWidget { height: 130, width: Get.width)) .toList(), - const SizedBox(height: 16), + const SizedBox(height: 16), if (controller.detail!.isPayWithCash) GestureDetector( - onTap: (() => controller.makePayment(orderId)), + onTap: (() => + controller.makePayment(orderId)), child: Center( child: Container( height: 40, - width: - MediaQuery.of(context).size.width / - 1.5, + width: MediaQuery.of(context) + .size + .width / + 1.5, decoration: BoxDecoration( gradient: mainButton, boxShadow: [ @@ -98,25 +108,29 @@ class OrderDetail extends StatelessWidget { child: Center( child: Text("Pay with PayPal", style: const TextStyle( - color: - const Color(0xfffefefe), - fontWeight: FontWeight.w600, - fontStyle: FontStyle.normal, + color: const Color( + 0xfffefefe), + fontWeight: + FontWeight.w600, + fontStyle: + FontStyle.normal, fontSize: 20.0)), ), ), ), ), - const SizedBox(height: 16), - if (controller.detail!.canCancel) + const SizedBox(height: 16), + if (controller.detail!.canCancel) GestureDetector( - onTap: (() => controller.remove(orderId)), + onTap: (() => + controller.remove(orderId)), child: Center( child: Container( height: 40, - width: - MediaQuery.of(context).size.width / - 1.5, + width: MediaQuery.of(context) + .size + .width / + 1.5, decoration: BoxDecoration( gradient: mainButton, boxShadow: [ @@ -132,10 +146,12 @@ class OrderDetail extends StatelessWidget { child: Center( child: Text("Cancle Order", style: const TextStyle( - color: - const Color(0xfffefefe), - fontWeight: FontWeight.w600, - fontStyle: FontStyle.normal, + color: const Color( + 0xfffefefe), + fontWeight: + FontWeight.w600, + fontStyle: + FontStyle.normal, fontSize: 20.0)), ), ), @@ -144,7 +160,6 @@ class OrderDetail extends StatelessWidget { ], ) : SizedBox.shrink(), - ), ), ), diff --git a/lib/screens/tracking/row_text.widget.dart b/lib/screens/tracking/row_text.widget.dart new file mode 100644 index 00000000..3b6afed0 --- /dev/null +++ b/lib/screens/tracking/row_text.widget.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +// ignore: must_be_immutable +class RowTextWidget extends StatelessWidget { + RowTextWidget( + {required this.text1, + required this.text2, + Key? key, + this.isBold = false, + this.isHighlight = false}) + : super(key: key); + final String text1; + final String text2; + bool isBold; + final bool isHighlight; + + @override + Widget build(BuildContext context) { + TextStyle subHeader = TextStyle(fontSize: 14); + final style = !isBold + ? subHeader.copyWith(color: const Color(0xFF292B30)) + : subHeader.copyWith( + color: const Color(0xFF292B30), fontWeight: FontWeight.w700); + var textStyle = style; + if (isHighlight) { + textStyle = style.copyWith(fontSize: 16); + } + return SizedBox( + height: 56, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(text1, style: textStyle), + const SizedBox(width: 12), + Container( + constraints: BoxConstraints(maxWidth: Get.width * 0.5), + child: Text( + text2, + style: textStyle, + overflow: TextOverflow.ellipsis, + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/screens/tracking/tracking_page.dart b/lib/screens/tracking/tracking_page.dart index 77c5e3d2..26c44b78 100644 --- a/lib/screens/tracking/tracking_page.dart +++ b/lib/screens/tracking/tracking_page.dart @@ -1,5 +1,6 @@ import 'package:ecommerce_int2/data/repository/order.repository.dart'; import 'package:ecommerce_int2/screens/tracking/order.controller.dart'; +import 'package:ecommerce_int2/screens/tracking/row_text.widget.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -68,25 +69,43 @@ class _TrackingPageState extends State { children: [ ...controller.orders.reversed .map((order) => GestureDetector( - onTap: (() => controller.getOrderDetail(order)), - child: Container( - width: Get.width, - child: Card( + onTap: (() => + controller.getOrderDetail(order)), + child: Container( + width: Get.width, + child: Card( child: Padding( padding: const EdgeInsets.all(8.0), - child: Column(children: [ - Text('Order Id: ${order.sId ?? 'Order'}'), - Text('Deliver status: ${order.status ?? ''}'), - Text('Payment status: ${order.paymentStatus ?? ''}'), - Text('Merchant: ${order.merchant ?? ''}'), - Text('Date: ${order.created ?? ''}') - ], - crossAxisAlignment: CrossAxisAlignment.start, + child: Column( + children: [ + RowTextWidget( + text1: 'Order Id', + text2: + '${order.sId ?? 'Order'}'), + RowTextWidget( + text1: 'Deliver status', + text2: + ' ${order.status ?? ''}'), + RowTextWidget( + text1: 'Payment status', + text2: + '${order.paymentStatus ?? ''}'), + RowTextWidget( + text1: 'Merchant', + text2: + '${order.merchant ?? ''}'), + RowTextWidget( + text1: 'Date', + text2: + '${order.createdDate}'), + ], + crossAxisAlignment: + CrossAxisAlignment.start, ), ), ), - ), - )) + ), + )) .toList() ], ), From 0b01e7af89810b103146f2b559e3d348b886322c Mon Sep 17 00:00:00 2001 From: manmaihuu <103487985+pdax-manmai@users.noreply.github.com> Date: Sun, 19 Jun 2022 10:33:13 +0700 Subject: [PATCH 39/49] Fix flow app --- lib/screens/search_products/search_page.dart | 1 - lib/screens/settings/legal_about_page.dart | 3 --- 2 files changed, 4 deletions(-) diff --git a/lib/screens/search_products/search_page.dart b/lib/screens/search_products/search_page.dart index 7ad1c312..f99ddc9e 100644 --- a/lib/screens/search_products/search_page.dart +++ b/lib/screens/search_products/search_page.dart @@ -6,7 +6,6 @@ import 'package:ecommerce_int2/screens/product/components/product_card.dart'; import 'package:ecommerce_int2/screens/product/product_page.dart'; import 'package:ecommerce_int2/screens/search_products/search_controller.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; -import 'package:ecommerce_int2/screens/product/view_product_page.dart'; import 'package:ecommerce_int2/utils/cart_button.widget.dart'; import 'package:flutter/material.dart'; diff --git a/lib/screens/settings/legal_about_page.dart b/lib/screens/settings/legal_about_page.dart index abbfe13c..a9667abe 100755 --- a/lib/screens/settings/legal_about_page.dart +++ b/lib/screens/settings/legal_about_page.dart @@ -1,7 +1,4 @@ -import 'dart:io'; - import 'package:ecommerce_int2/utils/app_properties.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class LegalAboutPage extends StatefulWidget { From fce6c57a6fd194b946f07f2ad951632609e303ef Mon Sep 17 00:00:00 2001 From: manmaihuu <103487985+pdax-manmai@users.noreply.github.com> Date: Sun, 19 Jun 2022 10:33:31 +0700 Subject: [PATCH 40/49] Refactor code --- .flutter-plugins-dependencies | 2 +- lib/data/models/order.model.dart | 6 +- lib/data/provider/category.provider.dart | 2 +- lib/data/provider/order.provider.dart | 8 + lib/data/repository/cart.repository.dart | 2 +- lib/data/repository/order.repository.dart | 6 + lib/screens/address/address.controller.dart | 25 +++- lib/screens/auth/forgot_password_page.dart | 8 - lib/screens/category/category_list_page.dart | 2 +- .../components/staggered_category_card.dart | 1 - .../category/sub_category_list_page.dart | 2 +- lib/screens/faq_page.dart | 2 - lib/screens/main/components/product_list.dart | 1 + lib/screens/main/home.controller.dart | 1 - lib/screens/main/main_page.dart | 19 --- .../merchant/components/shop_item_list.dart | 1 - lib/screens/merchant/merchant.view.dart | 2 - lib/screens/profile_page.dart | 2 - lib/screens/request_money/receive_page.dart | 1 - .../request_money/request_amount_page.dart | 2 - lib/screens/request_money/request_page.dart | 1 - lib/screens/shop/cart.controller.dart | 5 + lib/screens/shop/check_out_page.dart | 3 + .../shop/components/shop_item_list.dart | 2 +- .../tracking/order_detail.controller.dart | 13 ++ lib/screens/tracking/order_detail.view.dart | 139 ++++++++---------- lib/screens/tracking/tracking_page.dart | 57 +------ lib/services/network.service.dart | 10 +- 28 files changed, 136 insertions(+), 189 deletions(-) diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 0ed29738..d41e520d 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]},{"name":"webview_flutter_wkwebview","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_wkwebview-2.7.5\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]},{"name":"webview_flutter_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_android-2.8.10\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2022-06-16 16:07:07.680593","version":"2.10.4"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]},{"name":"webview_flutter_wkwebview","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_wkwebview-2.7.5\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]},{"name":"webview_flutter_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_android-2.8.10\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2022-06-19 09:22:24.112163","version":"2.10.4"} \ No newline at end of file diff --git a/lib/data/models/order.model.dart b/lib/data/models/order.model.dart index 768db48f..99c9dd16 100644 --- a/lib/data/models/order.model.dart +++ b/lib/data/models/order.model.dart @@ -11,7 +11,7 @@ class OrderResponse { OrderResponse.fromJson(Map json) { success = json['success']; message = json['message']; - order = json['order'] != null ? new Order.fromJson(json['order']) : null; + order = json['data'] != null ? new Order.fromJson(json['data']) : null; } Map toJson() { @@ -19,7 +19,7 @@ class OrderResponse { data['success'] = this.success; data['message'] = this.message; if (this.order != null) { - data['order'] = this.order!.toJson(); + data['data'] = this.order!.toJson(); } return data; } @@ -60,7 +60,7 @@ class Order { this.iV}); Order.fromJson(Map json) { - cart = json['cart']; + cart = json['cart']['_id']; user = json['user']; merchant = json['merchant']; payment = json['payment']; diff --git a/lib/data/provider/category.provider.dart b/lib/data/provider/category.provider.dart index 52f3eab7..7bdd9d4d 100644 --- a/lib/data/provider/category.provider.dart +++ b/lib/data/provider/category.provider.dart @@ -9,7 +9,7 @@ class CategoryProvider { CategoryProvider(this.networkService); final String getAllCaegories = - 'https://ecommerce-api-dut.herokuapp.com/api/category/list'; + 'https://ecommerce-api-dut.herokuapp.com/api/category'; Future getCategories() { return networkService.get(getAllCaegories); diff --git a/lib/data/provider/order.provider.dart b/lib/data/provider/order.provider.dart index bdf218c9..316af00c 100644 --- a/lib/data/provider/order.provider.dart +++ b/lib/data/provider/order.provider.dart @@ -19,6 +19,9 @@ class OrderProvider { final String cancleOrderUrl = 'https://ecommerce-api-dut.herokuapp.com/api/order'; + final String confirmReceivedUrl = + 'https://ecommerce-api-dut.herokuapp.com/api/order'; + Future getAllOrders() { return networkService.get(orderUrl); } @@ -44,4 +47,9 @@ class OrderProvider { Future getOrderDetail(String orderId) { return networkService.get('$orderUrl/$orderId'); } + + Future confirmReceived(String orderId) { + return networkService.put('$confirmReceivedUrl/$orderId/status', + data: {"status": "RECEIVED"}); + } } diff --git a/lib/data/repository/cart.repository.dart b/lib/data/repository/cart.repository.dart index 9e1f26eb..a065fd39 100644 --- a/lib/data/repository/cart.repository.dart +++ b/lib/data/repository/cart.repository.dart @@ -46,7 +46,7 @@ class CartRepository { for(CartModel cart in carts) { final response = await provider.checkoutCart(cart.sId!, cart.merchant!); OrderResponse order = OrderResponse.fromJson(response.body); - orderIds.add(order.order!.sId!); + orderIds.add(order. order!.sId!); } return orderIds; } diff --git a/lib/data/repository/order.repository.dart b/lib/data/repository/order.repository.dart index efaa6448..607be7ff 100644 --- a/lib/data/repository/order.repository.dart +++ b/lib/data/repository/order.repository.dart @@ -50,4 +50,10 @@ class OrderRepository { final res = DetailOrderResponse.fromJson(response.body); return res.orderDoc!; } + Future confirmReceived(String orderId) async { + final response = await provider.confirmReceived(orderId); + if (response.statusCode != 200) { + throw Exception("Confirm order failed"); + } + } } diff --git a/lib/screens/address/address.controller.dart b/lib/screens/address/address.controller.dart index 50bb5f82..4ecc5c55 100644 --- a/lib/screens/address/address.controller.dart +++ b/lib/screens/address/address.controller.dart @@ -25,10 +25,16 @@ class AddressController extends GetxController { @override void onInit() { getArgument(); - getAllAddress(); super.onInit(); } + @override + void onReady() { + getAllAddress(); + + super.onReady(); + } + void getArgument() { final arg = Get.arguments; if (arg != null && arg is List) { @@ -37,11 +43,14 @@ class AddressController extends GetxController { } void getAllAddress() async { + MessageDialog.showLoading(); final List
res = await repository.getAllAddress(); addresses.assignAll(res); addresses.insert(0, Address()); int index = addresses.indexWhere((element) => element.isDefault!); if (index != -1) selectIndex = index; + MessageDialog.hideLoading(); + update(); } @@ -65,7 +74,7 @@ class AddressController extends GetxController { .updateAddress(selectedAddress) .then((value) => null, onError: (e) => null); } - checkOut(); + checkOut(); } void checkOut() async { @@ -76,13 +85,15 @@ class AddressController extends GetxController { try { MessageDialog.showLoading(); for (String order in orderIds!) { - await orderRepository.completeOrder(order, CompleteOrderParam( - address: selectedAddress.id, - phoneNumber: authService.userModel!.email, - payment: 'CASH')); + await orderRepository.completeOrder( + order, + CompleteOrderParam( + address: selectedAddress.id, + phoneNumber: authService.userModel!.email, + payment: 'CASH')); } MessageDialog.hideLoading(); - Get.to(TrackingPage()); + Get.offAll(() => TrackingPage()); } on Exception catch (e) { MessageDialog.hideLoading(); print(e); diff --git a/lib/screens/auth/forgot_password_page.dart b/lib/screens/auth/forgot_password_page.dart index d54c157e..adef55b9 100755 --- a/lib/screens/auth/forgot_password_page.dart +++ b/lib/screens/auth/forgot_password_page.dart @@ -35,14 +35,6 @@ class _ForgotPasswordPageState extends State { @override Widget build(BuildContext context) { final controller = Get.find(); - Widget background = Container( - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage('assets/background.jpg'), fit: BoxFit.cover), - ), - foregroundDecoration: BoxDecoration(color: transparentYellow), - ); - Widget title = Text( 'Forgot your Password?', style: TextStyle( diff --git a/lib/screens/category/category_list_page.dart b/lib/screens/category/category_list_page.dart index a096325d..d0ee46b7 100755 --- a/lib/screens/category/category_list_page.dart +++ b/lib/screens/category/category_list_page.dart @@ -68,7 +68,7 @@ class CategoryListPage extends StatelessWidget { categoryName: controller.tempList[index].name ?? "", assetPath: 'assets/jeans_5.png', - onViewMore: () => Get.to(SubCategoryListPage( + onViewMore: () => Get.to(() => SubCategoryListPage( category: controller.tempList[index])), ), ), diff --git a/lib/screens/category/components/staggered_category_card.dart b/lib/screens/category/components/staggered_category_card.dart index 556f093c..0515060f 100755 --- a/lib/screens/category/components/staggered_category_card.dart +++ b/lib/screens/category/components/staggered_category_card.dart @@ -160,7 +160,6 @@ class _StaggeredCardCardState extends State @override Widget build(BuildContext context) { - var timeDilation = 10.0; // 1.0 is normal animation speed. return GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { diff --git a/lib/screens/category/sub_category_list_page.dart b/lib/screens/category/sub_category_list_page.dart index b918c15f..b2613315 100644 --- a/lib/screens/category/sub_category_list_page.dart +++ b/lib/screens/category/sub_category_list_page.dart @@ -75,7 +75,7 @@ class SubCategoryListPage extends StatelessWidget { end: const Color(0xffF68D7F), categoryName: controller.tempList[index].name ?? "", assetPath: 'assets/jeans_5.png', - onViewMore: () => Get.to(SearchPage(), + onViewMore: () => Get.to(() => SearchPage(), arguments: controller.tempList[index].slug), ), ), diff --git a/lib/screens/faq_page.dart b/lib/screens/faq_page.dart index 0268257f..1ef1e78f 100755 --- a/lib/screens/faq_page.dart +++ b/lib/screens/faq_page.dart @@ -1,5 +1,4 @@ import 'package:ecommerce_int2/utils/app_properties.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class FaqPage extends StatefulWidget { @@ -43,7 +42,6 @@ class _FaqPageState extends State { iconTheme: IconThemeData( color: Colors.black, ), - brightness: Brightness.light, backgroundColor: Colors.transparent, title: Text( 'Settings', diff --git a/lib/screens/main/components/product_list.dart b/lib/screens/main/components/product_list.dart index a59e1220..1aced475 100755 --- a/lib/screens/main/components/product_list.dart +++ b/lib/screens/main/components/product_list.dart @@ -5,6 +5,7 @@ import 'package:ecommerce_int2/screens/product/product_page.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +// ignore: must_be_immutable class ProductListView extends StatelessWidget { List products; diff --git a/lib/screens/main/home.controller.dart b/lib/screens/main/home.controller.dart index f73de49a..18d276ea 100644 --- a/lib/screens/main/home.controller.dart +++ b/lib/screens/main/home.controller.dart @@ -1,4 +1,3 @@ -import 'package:ecommerce_int2/data/models/category.model.dart'; import 'package:ecommerce_int2/data/models/product.model.dart'; import 'package:ecommerce_int2/data/repository/product.repository.dart'; import 'package:ecommerce_int2/utils/debounce.dart'; diff --git a/lib/screens/main/main_page.dart b/lib/screens/main/main_page.dart index d81454d5..4cb372f3 100755 --- a/lib/screens/main/main_page.dart +++ b/lib/screens/main/main_page.dart @@ -13,7 +13,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:get/get.dart'; import 'components/custom_bottom_bar.dart'; -import 'components/tab_view.dart'; class MainPage extends StatefulWidget { @override @@ -107,24 +106,6 @@ class _MainPageState extends State ), )); - Widget tabBar = TabBar( - tabs: [ - Tab(text: 'Trending'), - Tab(text: 'Sports'), - Tab(text: 'Headsets'), - Tab(text: 'Wireless'), - Tab(text: 'Bluetooth'), - ], - labelStyle: TextStyle(fontSize: 16.0), - unselectedLabelStyle: TextStyle( - fontSize: 14.0, - ), - labelColor: darkGrey, - unselectedLabelColor: Color.fromRGBO(0, 0, 0, 0.5), - isScrollable: true, - controller: tabController, - ); - return Scaffold( bottomNavigationBar: CustomBottomBar(controller: bottomTabController), body: GetBuilder( diff --git a/lib/screens/merchant/components/shop_item_list.dart b/lib/screens/merchant/components/shop_item_list.dart index 65a7d35b..fbb420dc 100644 --- a/lib/screens/merchant/components/shop_item_list.dart +++ b/lib/screens/merchant/components/shop_item_list.dart @@ -84,7 +84,6 @@ class _ShopItemListState extends State { ), Theme( data: ThemeData( - accentColor: Colors.black, textTheme: TextTheme( headline6: TextStyle( fontFamily: 'Montserrat', diff --git a/lib/screens/merchant/merchant.view.dart b/lib/screens/merchant/merchant.view.dart index 13c28586..d8e10de5 100644 --- a/lib/screens/merchant/merchant.view.dart +++ b/lib/screens/merchant/merchant.view.dart @@ -99,7 +99,6 @@ class MerchantPage extends StatelessWidget { class Scroll extends CustomPainter { @override void paint(Canvas canvas, Size size) { - // TODO: implement paint LinearGradient grT = LinearGradient( colors: [Colors.transparent, Colors.black26], @@ -127,7 +126,6 @@ class Scroll extends CustomPainter { @override bool shouldRepaint(CustomPainter oldDelegate) { - // TODO: implement shouldRepaint return false; } } diff --git a/lib/screens/profile_page.dart b/lib/screens/profile_page.dart index 337a4f39..20405836 100755 --- a/lib/screens/profile_page.dart +++ b/lib/screens/profile_page.dart @@ -1,9 +1,7 @@ import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/faq_page.dart'; -import 'package:ecommerce_int2/screens/payment/payment_page.dart'; import 'package:ecommerce_int2/screens/settings/settings_page.dart'; import 'package:ecommerce_int2/screens/tracking/tracking_page.dart'; -import 'package:ecommerce_int2/screens/wallet/wallet_page.dart'; import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; diff --git a/lib/screens/request_money/receive_page.dart b/lib/screens/request_money/receive_page.dart index 49acc8c3..690c107b 100755 --- a/lib/screens/request_money/receive_page.dart +++ b/lib/screens/request_money/receive_page.dart @@ -16,7 +16,6 @@ class ReceivePaymentPage extends StatelessWidget { iconTheme: IconThemeData( color: Colors.black, ), - brightness: Brightness.light, backgroundColor: Colors.transparent, title: Text( 'Receive Payment', diff --git a/lib/screens/request_money/request_amount_page.dart b/lib/screens/request_money/request_amount_page.dart index 1151fed6..1ada1ea5 100755 --- a/lib/screens/request_money/request_amount_page.dart +++ b/lib/screens/request_money/request_amount_page.dart @@ -10,7 +10,6 @@ class RequestAmountPage extends StatelessWidget { @override Widget build(BuildContext context) { - double width = MediaQuery.of(context).size.width; Widget viewProductButton = InkWell( onTap: () {}, child: Container( @@ -72,7 +71,6 @@ class RequestAmountPage extends StatelessWidget { iconTheme: IconThemeData( color: Colors.black, ), - brightness: Brightness.light, backgroundColor: Colors.transparent, title: Text( 'Request Amount', diff --git a/lib/screens/request_money/request_page.dart b/lib/screens/request_money/request_page.dart index 23c1695a..7c2f1751 100755 --- a/lib/screens/request_money/request_page.dart +++ b/lib/screens/request_money/request_page.dart @@ -45,7 +45,6 @@ class _RequestPageState extends State { iconTheme: IconThemeData( color: Colors.black, ), - brightness: Brightness.light, backgroundColor: Colors.transparent, title: Text( 'Request Amount', diff --git a/lib/screens/shop/cart.controller.dart b/lib/screens/shop/cart.controller.dart index 64179768..add1f9e9 100644 --- a/lib/screens/shop/cart.controller.dart +++ b/lib/screens/shop/cart.controller.dart @@ -13,6 +13,8 @@ class CartController extends GetxController { CartController(this.repository); + bool isLoadingCart = false; + List get products { if (carts == null) return []; List products = []; @@ -38,8 +40,11 @@ class CartController extends GetxController { } Future getCart() async { + isLoadingCart = true; + update(); repository.getCarts().then((value) { carts = value; + isLoadingCart = false; update(); }); } diff --git a/lib/screens/shop/check_out_page.dart b/lib/screens/shop/check_out_page.dart index 027e17d5..7291cb9e 100755 --- a/lib/screens/shop/check_out_page.dart +++ b/lib/screens/shop/check_out_page.dart @@ -86,6 +86,9 @@ class CheckOutPage extends StatelessWidget { ], ), ), + if(controller.isLoadingCart) + Container(height: 100, child: Center(child: CircularProgressIndicator.adaptive()),), + if(!controller.isLoadingCart) ...controller.products.map( (product) => ShopItemList( product, diff --git a/lib/screens/shop/components/shop_item_list.dart b/lib/screens/shop/components/shop_item_list.dart index 65a7d35b..5e4c8ab0 100755 --- a/lib/screens/shop/components/shop_item_list.dart +++ b/lib/screens/shop/components/shop_item_list.dart @@ -28,7 +28,7 @@ class _ShopItemListState extends State { Align( alignment: Alignment(0, 0.8), child: Container( - height: 100, + height: 120, margin: EdgeInsets.symmetric(horizontal: 16.0), decoration: BoxDecoration( color: Colors.white, diff --git a/lib/screens/tracking/order_detail.controller.dart b/lib/screens/tracking/order_detail.controller.dart index ea930bf1..cbdb0586 100644 --- a/lib/screens/tracking/order_detail.controller.dart +++ b/lib/screens/tracking/order_detail.controller.dart @@ -52,4 +52,17 @@ class OrderDetailController extends GetxController { } MessageDialog.hideLoading(); } + + void confirmOrder(String orderId) async { + MessageDialog.showLoading(); + try { + await repository.confirmReceived(orderId); + orderController.getAllOrders(); + MessageDialog.hideLoading(); + Get.back(); + } on Exception catch (e) { + MessageDialog.hideLoading(); + MessageDialog.showToast(e.toString()); + } + } } diff --git a/lib/screens/tracking/order_detail.view.dart b/lib/screens/tracking/order_detail.view.dart index eeb6dac6..6a01f21d 100644 --- a/lib/screens/tracking/order_detail.view.dart +++ b/lib/screens/tracking/order_detail.view.dart @@ -1,5 +1,6 @@ import 'package:ecommerce_int2/data/repository/order.repository.dart'; import 'package:ecommerce_int2/screens/main/components/product_list.dart'; +import 'package:ecommerce_int2/screens/profile_page.dart'; import 'package:ecommerce_int2/screens/tracking/order.controller.dart'; import 'package:ecommerce_int2/screens/tracking/order_detail.controller.dart'; import 'package:ecommerce_int2/screens/tracking/row_text.widget.dart'; @@ -40,8 +41,7 @@ class OrderDetail extends StatelessWidget { fontWeight: FontWeight.bold, ), ), - leading: SizedBox(), - actions: [CloseButton()], + leading: BackButton(), ), body: SafeArea( child: LayoutBuilder( @@ -82,81 +82,24 @@ class OrderDetail extends StatelessWidget { width: Get.width)) .toList(), const SizedBox(height: 16), - if (controller.detail!.isPayWithCash) - GestureDetector( - onTap: (() => - controller.makePayment(orderId)), - child: Center( - child: Container( - height: 40, - width: MediaQuery.of(context) - .size - .width / - 1.5, - decoration: BoxDecoration( - gradient: mainButton, - boxShadow: [ - BoxShadow( - color: Color.fromRGBO( - 0, 0, 0, 0.16), - offset: Offset(0, 5), - blurRadius: 10.0, - ) - ], - borderRadius: - BorderRadius.circular(9.0)), - child: Center( - child: Text("Pay with PayPal", - style: const TextStyle( - color: const Color( - 0xfffefefe), - fontWeight: - FontWeight.w600, - fontStyle: - FontStyle.normal, - fontSize: 20.0)), - ), - ), - ), - ), - const SizedBox(height: 16), - if (controller.detail!.canCancel) - GestureDetector( - onTap: (() => - controller.remove(orderId)), - child: Center( - child: Container( - height: 40, - width: MediaQuery.of(context) - .size - .width / - 1.5, - decoration: BoxDecoration( - gradient: mainButton, - boxShadow: [ - BoxShadow( - color: Color.fromRGBO( - 0, 0, 0, 0.16), - offset: Offset(0, 5), - blurRadius: 10.0, - ) - ], - borderRadius: - BorderRadius.circular(9.0)), - child: Center( - child: Text("Cancle Order", - style: const TextStyle( - color: const Color( - 0xfffefefe), - fontWeight: - FontWeight.w600, - fontStyle: - FontStyle.normal, - fontSize: 20.0)), - ), - ), - ), - ), + if (!controller.detail!.isPayWithCash) + Button( + title: 'Pay with Paypal', + onTap: () => + controller.makePayment(orderId)), + Button( + title: 'Cancle Order', + onTap: () => controller.remove(orderId), + ), + Button( + title: 'Confirm Received', + onTap: () => + controller.confirmOrder(orderId), + ), + if (controller.detail?.status == 'RECEIVED') + Button( + title: 'Add review', + onTap: () => print('add review')) ], ) : SizedBox.shrink(), @@ -172,6 +115,48 @@ class OrderDetail extends StatelessWidget { } } +class Button extends StatelessWidget { + const Button({Key? key, required this.onTap, required this.title}) + : super(key: key); + + final String title; + final Function onTap; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: GestureDetector( + onTap: (() => onTap()), + child: Center( + child: Container( + height: 40, + width: MediaQuery.of(context).size.width / 1.5, + decoration: BoxDecoration( + gradient: mainButton, + boxShadow: [ + BoxShadow( + color: Color.fromRGBO(0, 0, 0, 0.16), + offset: Offset(0, 5), + blurRadius: 10.0, + ) + ], + borderRadius: BorderRadius.circular(9.0)), + child: Center( + child: Text(title, + style: const TextStyle( + color: const Color(0xfffefefe), + fontWeight: FontWeight.w600, + fontStyle: FontStyle.normal, + fontSize: 20.0)), + ), + ), + ), + ), + ); + } +} + class Location { String city; DateTime date; diff --git a/lib/screens/tracking/tracking_page.dart b/lib/screens/tracking/tracking_page.dart index 26c44b78..1c09a463 100644 --- a/lib/screens/tracking/tracking_page.dart +++ b/lib/screens/tracking/tracking_page.dart @@ -1,38 +1,12 @@ import 'package:ecommerce_int2/data/repository/order.repository.dart'; +import 'package:ecommerce_int2/screens/profile_page.dart'; import 'package:ecommerce_int2/screens/tracking/order.controller.dart'; import 'package:ecommerce_int2/screens/tracking/row_text.widget.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:intl/intl.dart'; - -class TrackingPage extends StatefulWidget { - @override - _TrackingPageState createState() => _TrackingPageState(); -} - -class _TrackingPageState extends State { - final List locations = [ - Location('Kolkata Facility', DateTime(2019, 6, 5, 5, 23, 4), - showHour: false, isHere: false, passed: true), - Location('Hyderabad Facility', DateTime(2019, 6, 6, 5, 23, 4), - showHour: false, isHere: false, passed: true), - Location( - 'Chennai Facility', - DateTime(2019, 6, 9, 5, 23, 4), - showHour: false, - isHere: true, - ), - Location( - 'Kerala Facility', - DateTime(2019, 6, 10, 5, 23, 4), - showHour: true, - isHere: false, - ), - ]; - - String selectedProduct = 'Boat Headphones Bass boost 100v'; +class TrackingPage extends StatelessWidget { @override Widget build(BuildContext context) { return GetBuilder( @@ -59,8 +33,9 @@ class _TrackingPageState extends State { fontWeight: FontWeight.bold, ), ), - leading: SizedBox(), - actions: [CloseButton()], + leading: BackButton( + onPressed: () => Get.offAll(() => ProfilePage()), + ), ), body: SafeArea( child: LayoutBuilder( @@ -96,8 +71,7 @@ class _TrackingPageState extends State { '${order.merchant ?? ''}'), RowTextWidget( text1: 'Date', - text2: - '${order.createdDate}'), + text2: '${order.createdDate}'), ], crossAxisAlignment: CrossAxisAlignment.start, @@ -117,22 +91,3 @@ class _TrackingPageState extends State { ); } } - -class Location { - String city; - DateTime date; - bool showHour; - bool isHere; - bool passed; - - Location(this.city, this.date, - {this.showHour = false, this.isHere = false, this.passed = false}); - - String getDate() { - if (showHour) { - return DateFormat("K:mm aaa, d MMMM y").format(date); - } else { - return DateFormat('d MMMM y').format(date); - } - } -} diff --git a/lib/services/network.service.dart b/lib/services/network.service.dart index e821f477..a52b2d43 100644 --- a/lib/services/network.service.dart +++ b/lib/services/network.service.dart @@ -69,7 +69,7 @@ class NetWorkService { Future get(String url, {Map? queryParameters, Options? options}) async { final Dio dio = getDio(); - debugPrint("--[GET]--: ${url}"); + debugPrint("--[GET]--: $url"); final Response response = await dio.get( url, queryParameters: queryParameters, @@ -93,7 +93,7 @@ class NetWorkService { Map? queryParameters, Options? options}) async { final Dio dio = getDio(); - debugPrint("--[DOWNLOAD]--: ${url}"); + debugPrint("--[DOWNLOAD]--: $url"); final tempDir = await getTemporaryDirectory(); String filename = ''; return await dio.download( @@ -125,7 +125,7 @@ class NetWorkService { Options? options, Map? formData}) async { final Dio dio = getDio(); - debugPrint("--[POST]--: ${url}"); + debugPrint("--[POST]--: $url"); if (formData != null) { data = mapToFormData(formData); } @@ -155,7 +155,7 @@ class NetWorkService { data = mapToFormData(formData); } - debugPrint("--[PUT]--: ${url}"); + debugPrint("--[PUT]--: $url"); final Response response = await dio.put( url, data: data, @@ -179,7 +179,7 @@ class NetWorkService { Options? options, }) async { final Dio dio = getDio(); - debugPrint("--[DELETE]--: ${url}"); + debugPrint("--[DELETE]--: $url"); final Response response = await dio.delete( url, data: data, From c9f54ec03fa89f03db0135919b5efab2c3d5be64 Mon Sep 17 00:00:00 2001 From: manmaihuu <103487985+pdax-manmai@users.noreply.github.com> Date: Tue, 21 Jun 2022 10:41:05 +0700 Subject: [PATCH 41/49] Update UI for product_card --- .flutter-plugins-dependencies | 2 +- lib/data/models/order.model.dart | 6 +- lib/screens/address/add_address_page.dart | 32 +++++-- lib/screens/address/address.controller.dart | 28 ++++-- lib/screens/address/address_form.dart | 29 +++++- .../main/components/recommended_list.dart | 2 +- lib/screens/main/main_page.dart | 7 +- lib/screens/product/product_page.dart | 2 +- lib/screens/profile_page.dart | 3 +- lib/screens/shop/cart.controller.dart | 5 +- lib/screens/shop/check_out_page.dart | 88 ++++++++----------- .../shop/components/shop_item_list.dart | 7 +- lib/screens/tracking/order.controller.dart | 9 ++ lib/screens/tracking/order_detail.view.dart | 12 +-- lib/screens/tracking/tracking_page.dart | 6 +- 15 files changed, 139 insertions(+), 99 deletions(-) diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index d41e520d..b00ece6c 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]},{"name":"webview_flutter_wkwebview","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_wkwebview-2.7.5\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]},{"name":"webview_flutter_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_android-2.8.10\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2022-06-19 09:22:24.112163","version":"2.10.4"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]},{"name":"webview_flutter_wkwebview","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_wkwebview-2.7.5\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]},{"name":"webview_flutter_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_android-2.8.10\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2022-06-21 09:01:59.958819","version":"2.10.4"} \ No newline at end of file diff --git a/lib/data/models/order.model.dart b/lib/data/models/order.model.dart index 99c9dd16..d6008e92 100644 --- a/lib/data/models/order.model.dart +++ b/lib/data/models/order.model.dart @@ -60,7 +60,7 @@ class Order { this.iV}); Order.fromJson(Map json) { - cart = json['cart']['_id']; + cart = json['cart'] is String ? json['cart']: json['cart']['_id']; user = json['user']; merchant = json['merchant']; payment = json['payment']; @@ -267,9 +267,9 @@ class OrderDocDetail { return res; } - bool get isPayWithCash => payment == 'CASH'; + bool get isPayWithCash => payment == 'CASH' && canCancel; - bool get canCancel => status == 'NOT_PROCESS'; + bool get canCancel => !(status == 'CANCLED' || status == 'RECEIVED') ; OrderDocDetail( {this.sId, diff --git a/lib/screens/address/add_address_page.dart b/lib/screens/address/add_address_page.dart index 1683cb64..464f7333 100755 --- a/lib/screens/address/add_address_page.dart +++ b/lib/screens/address/add_address_page.dart @@ -1,4 +1,6 @@ +import 'package:card_swiper/card_swiper.dart'; import 'package:ecommerce_int2/data/repository/order.repository.dart'; +import 'package:ecommerce_int2/screens/shop/components/credit_card.dart'; import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/data/repository/address.repository.dart'; @@ -8,12 +10,11 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; class AddAddressPage extends StatelessWidget { - final TextEditingController address = TextEditingController(); - final TextEditingController city = TextEditingController(); + Widget buildFinishButton(AddressController controller) => InkWell( onTap: () { - controller.updateCurrentAddress(address.text, city.text); + controller.updateCurrentAddress(); controller.submitAddress(); }, child: Container( @@ -126,9 +127,30 @@ class AddAddressPage extends StatelessWidget { const SizedBox(height: 16), AddAddressForm( address: controller.selectedAddress, - addr: address, - city: city), + addr: controller.address, + phone: controller.phone, + city: controller.city), const SizedBox(height: 16), + if(controller.orderIds != null) + Padding( + padding: const EdgeInsets.all(16.0), + child: SizedBox( + height: 50, + child: Swiper( + itemCount: 2, + itemBuilder: (_, index) { + return CreditCard( + text: index == 0 ? 'CASH \$\$\$' : 'PAYPAL', + ); + }, + scale: 0.8, + controller: controller.swiperController, + viewportFraction: 0.6, + loop: false, + fade: 0.7, + ), + ), + ), Center(child: buildFinishButton(controller)) ], ), diff --git a/lib/screens/address/address.controller.dart b/lib/screens/address/address.controller.dart index 4ecc5c55..4336fd1f 100644 --- a/lib/screens/address/address.controller.dart +++ b/lib/screens/address/address.controller.dart @@ -1,10 +1,13 @@ +import 'package:card_swiper/card_swiper.dart'; import 'package:ecommerce_int2/data/models/address.model.dart'; import 'package:ecommerce_int2/data/models/order.model.dart'; import 'package:ecommerce_int2/data/repository/address.repository.dart'; import 'package:ecommerce_int2/data/repository/order.repository.dart'; +import 'package:ecommerce_int2/screens/payment/payment_page.dart'; import 'package:ecommerce_int2/screens/tracking/tracking_page.dart'; import 'package:ecommerce_int2/services/auth.service.dart'; import 'package:ecommerce_int2/utils/message_dialog.dart'; +import 'package:flutter/material.dart'; import 'package:get/get.dart'; class AddressController extends GetxController { @@ -12,6 +15,12 @@ class AddressController extends GetxController { final OrderRepository orderRepository; final AuthService authService; + final TextEditingController address = TextEditingController(); + final TextEditingController city = TextEditingController(); + final TextEditingController phone = TextEditingController(); + + final SwiperController swiperController = SwiperController(); + AddressController(this.repository, this.orderRepository, this.authService); List? orderIds; @@ -31,7 +40,9 @@ class AddressController extends GetxController { @override void onReady() { getAllAddress(); - + address.text = selectedAddress.address ?? ""; + city.text = selectedAddress.city ?? ""; + phone.text = authService.userModel!.email ?? ""; super.onReady(); } @@ -59,9 +70,9 @@ class AddressController extends GetxController { update(); } - void updateCurrentAddress(String address, String city) { - if (address.isNotEmpty) selectedAddress.address = address; - if (city.isNotEmpty) selectedAddress.city = city; + void updateCurrentAddress() { + if (address.text.isNotEmpty) selectedAddress.address = address.text; + if (city.text.isNotEmpty) selectedAddress.city = city.text; } void submitAddress() { @@ -88,12 +99,15 @@ class AddressController extends GetxController { await orderRepository.completeOrder( order, CompleteOrderParam( - address: selectedAddress.id, + address: '${selectedAddress.address}, ${selectedAddress.city}', phoneNumber: authService.userModel!.email, - payment: 'CASH')); + payment: swiperController.index == 0 ? 'CASH' : 'PAYPAL')); } MessageDialog.hideLoading(); - Get.offAll(() => TrackingPage()); + if (swiperController.index == 0) + Get.offAll(() => TrackingPage(), arguments: true); + else + Get.to(() => PaymentPage()); } on Exception catch (e) { MessageDialog.hideLoading(); print(e); diff --git a/lib/screens/address/address_form.dart b/lib/screens/address/address_form.dart index 7d387552..b1226522 100755 --- a/lib/screens/address/address_form.dart +++ b/lib/screens/address/address_form.dart @@ -6,11 +6,13 @@ class AddAddressForm extends StatelessWidget { final TextEditingController addr; final TextEditingController city; + final TextEditingController phone; const AddAddressForm( {Key? key, required this.address, required this.addr, + required this.phone, required this.city}) : super(key: key); @override @@ -20,7 +22,10 @@ class AddAddressForm extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceAround, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Address"), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text("Address"), + ), Container( padding: EdgeInsets.only(left: 16.0, top: 8.0, bottom: 4.0), decoration: BoxDecoration( @@ -33,8 +38,26 @@ class AddAddressForm extends StatelessWidget { border: InputBorder.none, hintText: address.address), ), ), - const SizedBox(height: 16,), - Text("City"), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text("City"), + ), + Container( + padding: EdgeInsets.only(left: 16.0, top: 8.0, bottom: 4.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(5)), + color: Colors.white, + ), + child: TextField( + controller: city, + decoration: InputDecoration( + border: InputBorder.none, hintText: address.city), + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text("Phone number"), + ), Container( padding: EdgeInsets.only(left: 16.0, top: 8.0, bottom: 4.0), decoration: BoxDecoration( diff --git a/lib/screens/main/components/recommended_list.dart b/lib/screens/main/components/recommended_list.dart index 2f8f4bd0..1b65cec2 100755 --- a/lib/screens/main/components/recommended_list.dart +++ b/lib/screens/main/components/recommended_list.dart @@ -63,7 +63,7 @@ class RecommendedList extends StatelessWidget { focalRadius: 0.1), ), child: Hero( - tag: products[index].sId!, + tag: UniqueKey(), child: Image.network(products[index].imageUrl!))), ), ), diff --git a/lib/screens/main/main_page.dart b/lib/screens/main/main_page.dart index 4cb372f3..22ee4099 100755 --- a/lib/screens/main/main_page.dart +++ b/lib/screens/main/main_page.dart @@ -5,7 +5,6 @@ import 'package:ecommerce_int2/screens/main/home.controller.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/utils/custom_background.dart'; import 'package:ecommerce_int2/screens/category/category_list_page.dart'; -import 'package:ecommerce_int2/screens/notifications_page.dart'; import 'package:ecommerce_int2/screens/profile_page.dart'; import 'package:ecommerce_int2/screens/search_products/search_page.dart'; import 'package:ecommerce_int2/screens/shop/check_out_page.dart'; @@ -57,12 +56,8 @@ class _MainPageState extends State Widget appBar = Container( height: kToolbarHeight + MediaQuery.of(context).padding.top, child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.end, children: [ - IconButton( - onPressed: () => Navigator.of(context) - .push(MaterialPageRoute(builder: (_) => NotificationsPage())), - icon: Icon(Icons.notifications)), IconButton( onPressed: () => Navigator.of(context) .push(MaterialPageRoute(builder: (_) => SearchPage())), diff --git a/lib/screens/product/product_page.dart b/lib/screens/product/product_page.dart index f2949220..1e840156 100755 --- a/lib/screens/product/product_page.dart +++ b/lib/screens/product/product_page.dart @@ -116,7 +116,7 @@ class ProductPage extends StatelessWidget { child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Text( - '${product.merchant ?? 'Merchant'}', + 'More product', style: TextStyle(fontSize: 18), ), ), diff --git a/lib/screens/profile_page.dart b/lib/screens/profile_page.dart index 20405836..f515d700 100755 --- a/lib/screens/profile_page.dart +++ b/lib/screens/profile_page.dart @@ -72,8 +72,7 @@ class ProfilePage extends StatelessWidget { children: [ IconButton( icon: Image.asset('assets/icons/truck.png'), - onPressed: () => Navigator.of(context).push( - MaterialPageRoute(builder: (_) => TrackingPage())), + onPressed: () => Get.to(() => TrackingPage()), ), Text( 'Orders', diff --git a/lib/screens/shop/cart.controller.dart b/lib/screens/shop/cart.controller.dart index add1f9e9..77038bd8 100644 --- a/lib/screens/shop/cart.controller.dart +++ b/lib/screens/shop/cart.controller.dart @@ -1,4 +1,3 @@ -import 'package:card_swiper/card_swiper.dart'; import 'package:ecommerce_int2/data/models/cart.model.dart'; import 'package:ecommerce_int2/data/models/product.model.dart'; import 'package:ecommerce_int2/data/repository/cart.repository.dart'; @@ -9,7 +8,6 @@ import 'package:get/get.dart'; class CartController extends GetxController { final CartRepository repository; - final SwiperController swiperController = SwiperController(); CartController(this.repository); @@ -34,7 +32,8 @@ class CartController extends GetxController { String get total { int result = 0; products.forEach((element) { - result += element.price ?? element.purchasePrice ?? 0; + result += (element.price ?? element.purchasePrice ?? 0) * + (element.quantity ?? 1); }); return '$result VND'; } diff --git a/lib/screens/shop/check_out_page.dart b/lib/screens/shop/check_out_page.dart index 7291cb9e..77ec9c64 100755 --- a/lib/screens/shop/check_out_page.dart +++ b/lib/screens/shop/check_out_page.dart @@ -1,41 +1,39 @@ -import 'package:card_swiper/card_swiper.dart'; import 'package:ecommerce_int2/data/repository/cart.repository.dart'; import 'package:ecommerce_int2/screens/shop/cart.controller.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'components/credit_card.dart'; import 'components/shop_item_list.dart'; class CheckOutPage extends StatelessWidget { @override Widget build(BuildContext context) { Widget checkOutButton(CartController controller) => InkWell( - onTap: () => controller.checkOut(), - child: Container( - height: 80, - width: MediaQuery.of(context).size.width / 1.5, - decoration: BoxDecoration( - gradient: mainButton, - boxShadow: [ - BoxShadow( - color: Color.fromRGBO(0, 0, 0, 0.16), - offset: Offset(0, 5), - blurRadius: 10.0, - ) - ], - borderRadius: BorderRadius.circular(9.0)), - child: Center( - child: Text("Check Out", - style: const TextStyle( - color: const Color(0xfffefefe), - fontWeight: FontWeight.w600, - fontStyle: FontStyle.normal, - fontSize: 20.0)), - ), - ), - ); + onTap: () => controller.checkOut(), + child: Container( + height: 80, + width: MediaQuery.of(context).size.width / 1.5, + decoration: BoxDecoration( + gradient: mainButton, + boxShadow: [ + BoxShadow( + color: Color.fromRGBO(0, 0, 0, 0.16), + offset: Offset(0, 5), + blurRadius: 10.0, + ) + ], + borderRadius: BorderRadius.circular(9.0)), + child: Center( + child: Text("Check Out", + style: const TextStyle( + color: const Color(0xfffefefe), + fontWeight: FontWeight.w600, + fontStyle: FontStyle.normal, + fontSize: 20.0)), + ), + ), + ); return Scaffold( backgroundColor: Colors.white, @@ -57,7 +55,7 @@ class CheckOutPage extends StatelessWidget { child: GetBuilder( init: CartController(Get.find()), initState: (state) { - Get.find().getCart(); + Get.find().getCart(); }, builder: (controller) => Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -86,15 +84,19 @@ class CheckOutPage extends StatelessWidget { ], ), ), - if(controller.isLoadingCart) - Container(height: 100, child: Center(child: CircularProgressIndicator.adaptive()),), - if(!controller.isLoadingCart) - ...controller.products.map( - (product) => ShopItemList( - product, - onRemove: () => controller.remove(product), + if (controller.isLoadingCart) + Container( + height: 100, + child: + Center(child: CircularProgressIndicator.adaptive()), + ), + if (!controller.isLoadingCart) + ...controller.products.map( + (product) => ShopItemList( + product, + onRemove: () => controller.remove(product), + ), ), - ), Container( padding: EdgeInsets.symmetric(horizontal: 32.0), height: 48.0, @@ -129,22 +131,6 @@ class CheckOutPage extends StatelessWidget { fontWeight: FontWeight.bold), ), ), - SizedBox( - height: 50, - child: Swiper( - itemCount: 2, - itemBuilder: (_, index) { - return CreditCard( - text: index == 0 ? 'CASH \$\$\$' : 'PAYPAL', - ); - }, - scale: 0.8, - controller: controller.swiperController, - viewportFraction: 0.6, - loop: false, - fade: 0.7, - ), - ), SizedBox(height: 24), Center( child: Padding( diff --git a/lib/screens/shop/components/shop_item_list.dart b/lib/screens/shop/components/shop_item_list.dart index 5e4c8ab0..9998e003 100755 --- a/lib/screens/shop/components/shop_item_list.dart +++ b/lib/screens/shop/components/shop_item_list.dart @@ -16,8 +16,6 @@ class ShopItemList extends StatefulWidget { } class _ShopItemListState extends State { - int quantity = 1; - @override Widget build(BuildContext context) { return Container( @@ -84,7 +82,6 @@ class _ShopItemListState extends State { ), Theme( data: ThemeData( - accentColor: Colors.black, textTheme: TextTheme( headline6: TextStyle( fontFamily: 'Montserrat', @@ -98,12 +95,12 @@ class _ShopItemListState extends State { ), )), child: NumberPicker( - value: quantity, + value: widget.product.quantity ?? 1, minValue: 1, maxValue: 10, onChanged: (value) { setState(() { - quantity = value; + widget.product.quantity = value; }); }, )) diff --git a/lib/screens/tracking/order.controller.dart b/lib/screens/tracking/order.controller.dart index e93d4b84..c948ad1c 100644 --- a/lib/screens/tracking/order.controller.dart +++ b/lib/screens/tracking/order.controller.dart @@ -1,6 +1,7 @@ import 'package:card_swiper/card_swiper.dart'; import 'package:ecommerce_int2/data/models/order.model.dart'; import 'package:ecommerce_int2/data/repository/order.repository.dart'; +import 'package:ecommerce_int2/screens/main/main_page.dart'; import 'package:ecommerce_int2/screens/tracking/order_detail.view.dart'; import 'package:ecommerce_int2/utils/message_dialog.dart'; import 'package:get/get.dart'; @@ -20,6 +21,14 @@ class OrderController extends GetxController { super.onReady(); } + void onBack() { + if(Get.arguments != null && Get.arguments == true) { + Get.offAll(() => MainPage()); + } else { + Get.back(); + } + } + void getAllOrders() { MessageDialog.showLoading(); repository.getAllOrders().then((value) { diff --git a/lib/screens/tracking/order_detail.view.dart b/lib/screens/tracking/order_detail.view.dart index 6a01f21d..5848e6f6 100644 --- a/lib/screens/tracking/order_detail.view.dart +++ b/lib/screens/tracking/order_detail.view.dart @@ -1,6 +1,5 @@ import 'package:ecommerce_int2/data/repository/order.repository.dart'; import 'package:ecommerce_int2/screens/main/components/product_list.dart'; -import 'package:ecommerce_int2/screens/profile_page.dart'; import 'package:ecommerce_int2/screens/tracking/order.controller.dart'; import 'package:ecommerce_int2/screens/tracking/order_detail.controller.dart'; import 'package:ecommerce_int2/screens/tracking/row_text.widget.dart'; @@ -31,7 +30,6 @@ class OrderDetail extends StatelessWidget { appBar: AppBar( backgroundColor: Colors.transparent, elevation: 0.0, - brightness: Brightness.light, iconTheme: IconThemeData(color: Colors.grey), title: Text( orderId, @@ -87,10 +85,12 @@ class OrderDetail extends StatelessWidget { title: 'Pay with Paypal', onTap: () => controller.makePayment(orderId)), - Button( - title: 'Cancle Order', - onTap: () => controller.remove(orderId), - ), + if (controller.detail!.canCancel) + Button( + title: 'Cancle Order', + onTap: () => controller.remove(orderId), + ), + if (!controller.detail!.canCancel) Button( title: 'Confirm Received', onTap: () => diff --git a/lib/screens/tracking/tracking_page.dart b/lib/screens/tracking/tracking_page.dart index 1c09a463..5f14bfa3 100644 --- a/lib/screens/tracking/tracking_page.dart +++ b/lib/screens/tracking/tracking_page.dart @@ -1,5 +1,4 @@ import 'package:ecommerce_int2/data/repository/order.repository.dart'; -import 'package:ecommerce_int2/screens/profile_page.dart'; import 'package:ecommerce_int2/screens/tracking/order.controller.dart'; import 'package:ecommerce_int2/screens/tracking/row_text.widget.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; @@ -23,7 +22,6 @@ class TrackingPage extends StatelessWidget { appBar: AppBar( backgroundColor: Colors.transparent, elevation: 0.0, - brightness: Brightness.light, iconTheme: IconThemeData(color: Colors.grey), title: Text( 'Your orders', @@ -33,9 +31,7 @@ class TrackingPage extends StatelessWidget { fontWeight: FontWeight.bold, ), ), - leading: BackButton( - onPressed: () => Get.offAll(() => ProfilePage()), - ), + leading: BackButton(onPressed: () => controller.onBack()), ), body: SafeArea( child: LayoutBuilder( From f90d1047c3aa7f78926552ae136759b5828e6b91 Mon Sep 17 00:00:00 2001 From: manmaihuu <103487985+pdax-manmai@users.noreply.github.com> Date: Tue, 21 Jun 2022 17:11:00 +0700 Subject: [PATCH 42/49] Fix address --- .flutter-plugins-dependencies | 2 +- lib/screens/address/address.controller.dart | 8 ++++---- lib/screens/address/address_form.dart | 2 +- lib/screens/shop/cart.controller.dart | 18 +++++++++++++++++- lib/screens/shop/check_out_page.dart | 1 + .../shop/components/shop_item_list.dart | 7 +++---- 6 files changed, 27 insertions(+), 11 deletions(-) diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index b00ece6c..659fb090 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]},{"name":"webview_flutter_wkwebview","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_wkwebview-2.7.5\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]},{"name":"webview_flutter_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_android-2.8.10\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2022-06-21 09:01:59.958819","version":"2.10.4"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]},{"name":"webview_flutter_wkwebview","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_wkwebview-2.7.5\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]},{"name":"webview_flutter_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_android-2.8.10\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2022-06-21 16:32:14.833834","version":"2.10.4"} \ No newline at end of file diff --git a/lib/screens/address/address.controller.dart b/lib/screens/address/address.controller.dart index 4336fd1f..d943bb0a 100644 --- a/lib/screens/address/address.controller.dart +++ b/lib/screens/address/address.controller.dart @@ -40,9 +40,7 @@ class AddressController extends GetxController { @override void onReady() { getAllAddress(); - address.text = selectedAddress.address ?? ""; - city.text = selectedAddress.city ?? ""; - phone.text = authService.userModel!.email ?? ""; + super.onReady(); } @@ -60,8 +58,10 @@ class AddressController extends GetxController { addresses.insert(0, Address()); int index = addresses.indexWhere((element) => element.isDefault!); if (index != -1) selectIndex = index; + address.text = selectedAddress.address ?? ""; + city.text = selectedAddress.city ?? ""; + phone.text = authService.userModel!.email ?? ""; MessageDialog.hideLoading(); - update(); } diff --git a/lib/screens/address/address_form.dart b/lib/screens/address/address_form.dart index b1226522..c980c5bb 100755 --- a/lib/screens/address/address_form.dart +++ b/lib/screens/address/address_form.dart @@ -65,7 +65,7 @@ class AddAddressForm extends StatelessWidget { color: Colors.white, ), child: TextField( - controller: city, + controller: phone, decoration: InputDecoration( border: InputBorder.none, hintText: address.city), ), diff --git a/lib/screens/shop/cart.controller.dart b/lib/screens/shop/cart.controller.dart index 77038bd8..3dc7f049 100644 --- a/lib/screens/shop/cart.controller.dart +++ b/lib/screens/shop/cart.controller.dart @@ -8,7 +8,6 @@ import 'package:get/get.dart'; class CartController extends GetxController { final CartRepository repository; - CartController(this.repository); bool isLoadingCart = false; @@ -89,4 +88,21 @@ class CartController extends GetxController { MessageDialog.hideLoading(); Get.to(() => AddAddressPage(), arguments: orderIds); } + + void onChangeQuantity(String id, int quantity) { + try { + final product = products.firstWhere((element) => element.sId == id); + repository.modifyProduct( + carts! + .firstWhere((element) => element.products!.contains(product)) + .sId!, + product.sId!, + product.quantity!, + quantity); + product.quantity = quantity; + update(); + } on Exception catch (e) { + print(e.toString()); + } + } } diff --git a/lib/screens/shop/check_out_page.dart b/lib/screens/shop/check_out_page.dart index 77ec9c64..e48af09e 100755 --- a/lib/screens/shop/check_out_page.dart +++ b/lib/screens/shop/check_out_page.dart @@ -94,6 +94,7 @@ class CheckOutPage extends StatelessWidget { ...controller.products.map( (product) => ShopItemList( product, + onChange: (a, b) => controller.onChangeQuantity(a, b), onRemove: () => controller.remove(product), ), ), diff --git a/lib/screens/shop/components/shop_item_list.dart b/lib/screens/shop/components/shop_item_list.dart index 9998e003..7c00cbb6 100755 --- a/lib/screens/shop/components/shop_item_list.dart +++ b/lib/screens/shop/components/shop_item_list.dart @@ -8,8 +8,9 @@ import 'package:numberpicker/numberpicker.dart'; class ShopItemList extends StatefulWidget { final Product product; final VoidCallback onRemove; + final Function(String, int) onChange; - ShopItemList(this.product, {required this.onRemove}); + ShopItemList(this.product, {required this.onRemove,required this.onChange}); @override _ShopItemListState createState() => _ShopItemListState(); @@ -99,9 +100,7 @@ class _ShopItemListState extends State { minValue: 1, maxValue: 10, onChanged: (value) { - setState(() { - widget.product.quantity = value; - }); + widget.onChange( widget.product.sId!, value); }, )) ])), From 3d0e2099e8775a80a7c418b2c7c7949a6bd4057e Mon Sep 17 00:00:00 2001 From: manmaihuu <103487985+pdax-manmai@users.noreply.github.com> Date: Tue, 21 Jun 2022 17:16:10 +0700 Subject: [PATCH 43/49] Fix address --- lib/screens/address/address.controller.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/screens/address/address.controller.dart b/lib/screens/address/address.controller.dart index d943bb0a..0b2f267b 100644 --- a/lib/screens/address/address.controller.dart +++ b/lib/screens/address/address.controller.dart @@ -67,6 +67,8 @@ class AddressController extends GetxController { void updateIndex(int index) { selectIndex = index; + address.text = selectedAddress.address ?? ""; + city.text = selectedAddress.city ?? ""; update(); } From 86318c790e8596e3a719466cf97ba5850528f42b Mon Sep 17 00:00:00 2001 From: manmaihuu <103487985+pdax-manmai@users.noreply.github.com> Date: Wed, 22 Jun 2022 11:44:58 +0700 Subject: [PATCH 44/49] Add review and merchant --- .flutter-plugins-dependencies | 2 +- lib/data/models/merchant.model.dart | 157 +++++++++ lib/data/models/order.model.dart | 198 +++++++++++ lib/data/models/review.dart | 110 ++++++ lib/data/provider/cart.provider.dart | 2 +- lib/data/provider/merchant.provider.dart | 20 ++ lib/data/provider/order.provider.dart | 8 +- lib/data/provider/review.provider.dart | 30 ++ lib/data/repository/merchant.repository.dart | 17 + lib/data/repository/review.repository.dart | 26 ++ lib/screens/main/components/product_list.dart | 29 +- lib/screens/merchant/merchant.controller.dart | 84 +---- lib/screens/merchant/merchant.view.dart | 65 ++-- lib/screens/notifications_page.dart | 22 -- lib/screens/product/product_page.dart | 4 +- lib/screens/rating/rating_dialog.dart | 168 ++++----- lib/screens/rating/rating_page.dart | 327 +++++------------- lib/screens/rating/review.controller.dart | 48 +++ lib/screens/tracking/order_detail.view.dart | 5 +- lib/utils/dependencies.dart | 8 + lib/utils/message_dialog.dart | 1 + 21 files changed, 871 insertions(+), 460 deletions(-) create mode 100644 lib/data/models/merchant.model.dart create mode 100644 lib/data/models/review.dart create mode 100644 lib/data/provider/merchant.provider.dart create mode 100644 lib/data/provider/review.provider.dart create mode 100644 lib/data/repository/merchant.repository.dart create mode 100644 lib/data/repository/review.repository.dart create mode 100644 lib/screens/rating/review.controller.dart diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 659fb090..eb65f3e5 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]},{"name":"webview_flutter_wkwebview","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_wkwebview-2.7.5\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]},{"name":"webview_flutter_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_android-2.8.10\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2022-06-21 16:32:14.833834","version":"2.10.4"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]},{"name":"webview_flutter_wkwebview","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_wkwebview-2.7.5\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]},{"name":"webview_flutter_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_android-2.8.10\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2022-06-22 10:08:31.555869","version":"2.10.4"} \ No newline at end of file diff --git a/lib/data/models/merchant.model.dart b/lib/data/models/merchant.model.dart new file mode 100644 index 00000000..05f68179 --- /dev/null +++ b/lib/data/models/merchant.model.dart @@ -0,0 +1,157 @@ +import 'package:ecommerce_int2/data/models/product.model.dart'; + +class MerchantResponse { + bool? success; + MerchantData? data; + + MerchantResponse({this.success, this.data}); + + MerchantResponse.fromJson(Map json) { + success = json['success']; + data = json['data'] != null ? new MerchantData.fromJson(json['data']) : null; + } + + Map toJson() { + final Map data = new Map(); + data['success'] = this.success; + if (this.data != null) { + data['data'] = this.data!.toJson(); + } + return data; + } +} + +class MerchantData { + Merchant? merchant; + List? products; + int? page; + int? pages; + int? totalProducts; + + MerchantData( + {this.merchant, + this.products, + this.page, + this.pages, + this.totalProducts}); + + MerchantData.fromJson(Map json) { + merchant = json['merchant'] != null + ? new Merchant.fromJson(json['merchant']) + : null; + if (json['products'] != null) { + products = []; + json['products'].forEach((v) { + products!.add(new Product.fromJson(v)); + }); + } + page = json['page']; + pages = json['pages']; + totalProducts = json['totalProducts']; + } + + Map toJson() { + final Map data = new Map(); + if (this.merchant != null) { + data['merchant'] = this.merchant!.toJson(); + } + if (this.products != null) { + data['products'] = this.products!.map((v) => v.toJson()).toList(); + } + data['page'] = this.page; + data['pages'] = this.pages; + data['totalProducts'] = this.totalProducts; + return data; + } +} + +class Merchant { + String? sId; + String? name; + String? email; + String? phoneNumber; + List? categories; + String? business; + bool? isActive; + String? status; + String? created; + String? slug; + int? iV; + + Merchant( + {this.sId, + this.name, + this.email, + this.phoneNumber, + this.categories, + this.business, + this.isActive, + this.status, + this.created, + this.slug, + this.iV}); + + Merchant.fromJson(Map json) { + sId = json['_id']; + name = json['name']; + email = json['email']; + phoneNumber = json['phoneNumber']; + if (json['categories'] != null) { + categories = []; + json['categories'].forEach((v) { + categories!.add(new Categories.fromJson(v)); + }); + } + business = json['business']; + isActive = json['isActive']; + status = json['status']; + created = json['created']; + slug = json['slug']; + iV = json['__v']; + } + + Map toJson() { + final Map data = new Map(); + data['_id'] = this.sId; + data['name'] = this.name; + data['email'] = this.email; + data['phoneNumber'] = this.phoneNumber; + if (this.categories != null) { + data['categories'] = this.categories!.map((v) => v.toJson()).toList(); + } + data['business'] = this.business; + data['isActive'] = this.isActive; + data['status'] = this.status; + data['created'] = this.created; + data['slug'] = this.slug; + data['__v'] = this.iV; + return data; + } +} + +class Categories { + String? sId; + String? name; + String? slug; + String? image; + + Categories({this.sId, this.name, this.slug, this.image}); + + Categories.fromJson(Map json) { + sId = json['_id']; + name = json['name']; + slug = json['slug']; + image = json['image']; + } + + Map toJson() { + final Map data = new Map(); + data['_id'] = this.sId; + data['name'] = this.name; + data['slug'] = this.slug; + data['image'] = this.image; + return data; + } +} + + diff --git a/lib/data/models/order.model.dart b/lib/data/models/order.model.dart index d6008e92..14d5b4b4 100644 --- a/lib/data/models/order.model.dart +++ b/lib/data/models/order.model.dart @@ -316,3 +316,201 @@ class OrderDocDetail { return data; } } + +class OrderProceed { + bool? success; + Data? data; + + OrderProceed({this.success, this.data}); + + OrderProceed.fromJson(Map json) { + success = json['success']; + data = json['data'] != null ? new Data.fromJson(json['data']) : null; + } + + Map toJson() { + final Map data = new Map(); + data['success'] = this.success; + if (this.data != null) { + data['data'] = this.data!.toJson(); + } + return data; + } +} + +class Data { + Order? order; + Payment? payment; + + Data({this.order, this.payment}); + + Data.fromJson(Map json) { + order = json['order'] != null ? new Order.fromJson(json['order']) : null; + payment = + json['payment'] != null ? new Payment.fromJson(json['payment']) : null; + } + + Map toJson() { + final Map data = new Map(); + if (this.order != null) { + data['order'] = this.order!.toJson(); + } + if (this.payment != null) { + data['payment'] = this.payment!.toJson(); + } + return data; + } +} + + +class Payment { + String? id; + String? intent; + String? state; + Payer? payer; + List? transactions; + String? createTime; + List? links; + int? httpStatusCode; + + Payment( + {this.id, + this.intent, + this.state, + this.payer, + this.transactions, + this.createTime, + this.links, + this.httpStatusCode}); + + Payment.fromJson(Map json) { + id = json['id']; + intent = json['intent']; + state = json['state']; + payer = json['payer'] != null ? new Payer.fromJson(json['payer']) : null; + if (json['transactions'] != null) { + transactions = []; + json['transactions'].forEach((v) { + transactions!.add(new Transactions.fromJson(v)); + }); + } + createTime = json['create_time']; + if (json['links'] != null) { + links = []; + json['links'].forEach((v) { + links!.add(new Links.fromJson(v)); + }); + } + httpStatusCode = json['httpStatusCode']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['intent'] = this.intent; + data['state'] = this.state; + if (this.payer != null) { + data['payer'] = this.payer!.toJson(); + } + if (this.transactions != null) { + data['transactions'] = this.transactions!.map((v) => v.toJson()).toList(); + } + data['create_time'] = this.createTime; + if (this.links != null) { + data['links'] = this.links!.map((v) => v.toJson()).toList(); + } + data['httpStatusCode'] = this.httpStatusCode; + return data; + } +} + +class Payer { + String? paymentMethod; + + Payer({this.paymentMethod}); + + Payer.fromJson(Map json) { + paymentMethod = json['payment_method']; + } + + Map toJson() { + final Map data = new Map(); + data['payment_method'] = this.paymentMethod; + return data; + } +} + +class Transactions { + Amount? amount; + String? description; + List? relatedResources; + + Transactions({this.amount, this.description, this.relatedResources}); + + Transactions.fromJson(Map json) { + amount = + json['amount'] != null ? new Amount.fromJson(json['amount']) : null; + description = json['description']; + if (json['related_resources'] != null) { + relatedResources = []; + json['related_resources'].forEach((v) { + relatedResources!.add(v); + }); + } + } + + Map toJson() { + final Map data = new Map(); + if (this.amount != null) { + data['amount'] = this.amount!.toJson(); + } + data['description'] = this.description; + if (this.relatedResources != null) { + data['related_resources'] = + this.relatedResources!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Amount { + String? total; + String? currency; + + Amount({this.total, this.currency}); + + Amount.fromJson(Map json) { + total = json['total']; + currency = json['currency']; + } + + Map toJson() { + final Map data = new Map(); + data['total'] = this.total; + data['currency'] = this.currency; + return data; + } +} + +class Links { + String? href; + String? rel; + String? method; + + Links({this.href, this.rel, this.method}); + + Links.fromJson(Map json) { + href = json['href']; + rel = json['rel']; + method = json['method']; + } + + Map toJson() { + final Map data = new Map(); + data['href'] = this.href; + data['rel'] = this.rel; + data['method'] = this.method; + return data; + } +} + diff --git a/lib/data/models/review.dart b/lib/data/models/review.dart new file mode 100644 index 00000000..cf4d8b94 --- /dev/null +++ b/lib/data/models/review.dart @@ -0,0 +1,110 @@ +class ReviewResponse { + bool? success; + List? data; + + ReviewResponse({this.success, this.data}); + + ReviewResponse.fromJson(Map json) { + success = json['success']; + if (json['data'] != null) { + data = []; + json['data'].forEach((v) { + data!.add(new Review.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + data['success'] = this.success; + if (this.data != null) { + data['data'] = this.data!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Review { + String? sId; + String? product; + User? user; + int? rating; + String? review; + String? created; + int? iV; + + Review( + {this.sId, + this.product, + this.user, + this.rating, + this.review, + this.created, + this.iV}); + + Review.fromJson(Map json) { + sId = json['_id']; + product = json['product']; + user = json['user'] != null ? new User.fromJson(json['user']) : null; + rating = json['rating']; + review = json['review']; + created = json['created']; + iV = json['__v']; + } + + Map toJson() { + final Map data = new Map(); + data['_id'] = this.sId; + data['product'] = this.product; + if (this.user != null) { + data['user'] = this.user!.toJson(); + } + data['rating'] = this.rating; + data['review'] = this.review; + data['created'] = this.created; + data['__v'] = this.iV; + return data; + } +} + +class User { + String? sId; + String? firstName; + + User({this.sId, this.firstName}); + + User.fromJson(Map json) { + sId = json['_id']; + firstName = json['firstName']; + } + + Map toJson() { + final Map data = new Map(); + data['_id'] = this.sId; + data['firstName'] = this.firstName; + return data; + } +} + +class ReviewParam { + String? product; + int? rating; + String? review; + + ReviewParam({this.product, this.rating, this.review}); + + ReviewParam.fromJson(Map json) { + product = json['product']; + rating = json['rating']; + review = json['review']; + } + + Map toJson() { + final Map data = new Map(); + data['product'] = this.product; + data['rating'] = this.rating; + data['review'] = this.review; + return data; + } +} + diff --git a/lib/data/provider/cart.provider.dart b/lib/data/provider/cart.provider.dart index 102fd93a..c9167365 100644 --- a/lib/data/provider/cart.provider.dart +++ b/lib/data/provider/cart.provider.dart @@ -22,7 +22,7 @@ class CartProvider { 'https://ecommerce-api-dut.herokuapp.com/api/cart/delete'; final String checkOutCartUrl = - 'https://ecommerce-api-dut.herokuapp.com/api/order/add'; + 'https://ecommerce-api-dut.herokuapp.com/api/order/proceed'; Future getCarts() { return networkService.get(getAllCartUrl); diff --git a/lib/data/provider/merchant.provider.dart b/lib/data/provider/merchant.provider.dart new file mode 100644 index 00000000..3b2b426b --- /dev/null +++ b/lib/data/provider/merchant.provider.dart @@ -0,0 +1,20 @@ +import 'package:ecommerce_int2/services/network.service.dart'; +import 'package:get_storage/get_storage.dart'; + +class MerchantProvider { + final NetWorkService networkService; + + final GetStorage storage = GetStorage(); + + MerchantProvider(this.networkService); + + final String getMerchantInfoUrl = + 'https://ecommerce-api-dut.herokuapp.com/api/merchant'; + + Future getMerchantInfo( + String keyword) { + return networkService.get("$getMerchantInfoUrl/$keyword"); + } + + +} diff --git a/lib/data/provider/order.provider.dart b/lib/data/provider/order.provider.dart index 316af00c..d822e788 100644 --- a/lib/data/provider/order.provider.dart +++ b/lib/data/provider/order.provider.dart @@ -15,7 +15,8 @@ class OrderProvider { 'https://ecommerce-api-dut.herokuapp.com/api/order/'; final String checkOutCartUrl = - 'https://ecommerce-api-dut.herokuapp.com/api/order/add'; + 'https://ecommerce-api-dut.herokuapp.com/api/order/proceed'; + final String cancleOrderUrl = 'https://ecommerce-api-dut.herokuapp.com/api/order'; @@ -26,11 +27,6 @@ class OrderProvider { return networkService.get(orderUrl); } - Future checkOut(String cartId) { - return networkService.post(checkOutCartUrl, - data: {"cart": cartId, "merchant": "626e237ef4224ee4107039b9"}); - } - Future completeOrder(String orderId, CompleteOrderParam param) { return networkService.put('$completeOrderUrl/$orderId/', data: param.toJson()); diff --git a/lib/data/provider/review.provider.dart b/lib/data/provider/review.provider.dart new file mode 100644 index 00000000..2cf5f019 --- /dev/null +++ b/lib/data/provider/review.provider.dart @@ -0,0 +1,30 @@ +import 'package:ecommerce_int2/data/models/review.dart'; +import 'package:ecommerce_int2/services/network.service.dart'; +import 'package:get_storage/get_storage.dart'; + +class ReviewProvider { + final NetWorkService networkService; + + final GetStorage storage = GetStorage(); + + ReviewProvider(this.networkService); + + final String addReviewUrl = + 'https://ecommerce-api-dut.herokuapp.com/api/review/add'; + + final String getRevAboutProductUrl = + 'https://ecommerce-api-dut.herokuapp.com/api/review'; + + + Future addReview( + ReviewParam filter) { + return networkService.post(addReviewUrl, data: filter.toJson()); + } + + Future getReviewProduct( + String keyword) { + return networkService.get("$getRevAboutProductUrl/$keyword"); + } + + +} diff --git a/lib/data/repository/merchant.repository.dart b/lib/data/repository/merchant.repository.dart new file mode 100644 index 00000000..4270d6a1 --- /dev/null +++ b/lib/data/repository/merchant.repository.dart @@ -0,0 +1,17 @@ +import 'package:ecommerce_int2/data/models/merchant.model.dart'; +import 'package:ecommerce_int2/data/provider/merchant.provider.dart'; + +class MerchantRepository { + final MerchantProvider provider; + + MerchantRepository(this.provider); + + Future getMerchantInfo(String merchant) async { + final response = await provider.getMerchantInfo(merchant); + if (response.statusCode != 200) { + throw Exception("Get merchant failed"); + } + final result = MerchantResponse.fromJson(response.body); + return result.data!; + } +} diff --git a/lib/data/repository/review.repository.dart b/lib/data/repository/review.repository.dart new file mode 100644 index 00000000..febc0a54 --- /dev/null +++ b/lib/data/repository/review.repository.dart @@ -0,0 +1,26 @@ +import 'package:ecommerce_int2/data/models/review.dart'; +import 'package:ecommerce_int2/data/provider/review.provider.dart'; + +class ReviewRepository { + final ReviewProvider provider; + + ReviewRepository(this.provider); + + Future addReview(ReviewParam filter) async { + final response = await provider.addReview(filter); + if (response.statusCode != 200) { + throw Exception("Add review failed"); + } + return; + } + + Future> getReviewProduct(String keyword) async { + final response = await provider.getReviewProduct(keyword); + if (response.statusCode != 200) { + throw Exception("Get products failed"); + } + final result = ReviewResponse.fromJson(response.body); + return result.data ?? []; + } + +} diff --git a/lib/screens/main/components/product_list.dart b/lib/screens/main/components/product_list.dart index 1aced475..2c167620 100755 --- a/lib/screens/main/components/product_list.dart +++ b/lib/screens/main/components/product_list.dart @@ -1,5 +1,7 @@ import 'package:card_swiper/card_swiper.dart'; import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/screens/rating/rating_dialog.dart'; +import 'package:ecommerce_int2/screens/tracking/order_detail.view.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/product/product_page.dart'; import 'package:flutter/material.dart'; @@ -99,11 +101,13 @@ class ProductCard extends StatelessWidget { final Product product; final double height; final double width; + final bool hasReceived; const ProductCard({ required this.product, required this.height, required this.width, + this.hasReceived = false, }); @override @@ -112,7 +116,7 @@ class ProductCard extends StatelessWidget { onTap: () => Navigator.of(context).push( MaterialPageRoute(builder: (_) => ProductPage(product: product))), child: Container( - margin: const EdgeInsets.symmetric( vertical: 8), + margin: const EdgeInsets.symmetric(vertical: 8), height: height, width: Get.width, decoration: BoxDecoration( @@ -127,7 +131,6 @@ class ProductCard extends StatelessWidget { height: 130, width: 130, fit: BoxFit.contain, - ), ), Expanded( @@ -142,14 +145,12 @@ class ProductCard extends StatelessWidget { padding: const EdgeInsets.all(8.0), child: Text( product.name ?? "", - style: TextStyle( - color: Colors.white, fontSize: 16.0), + style: TextStyle(color: Colors.white, fontSize: 16.0), ), ), Container( margin: const EdgeInsets.only(bottom: 12.0), - padding: - const EdgeInsets.fromLTRB(8.0, 4.0, 12.0, 4.0), + padding: const EdgeInsets.fromLTRB(8.0, 4.0, 12.0, 4.0), decoration: BoxDecoration( borderRadius: BorderRadius.only( topLeft: Radius.circular(10), @@ -164,6 +165,22 @@ class ProductCard extends StatelessWidget { fontWeight: FontWeight.bold), ), ), + if (hasReceived) + Button( + title: 'Add review', + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return Dialog( + shape: BeveledRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(10))), + child: RatingDialog(product: product), + ); + }, + ); + }) ], ) ], diff --git a/lib/screens/merchant/merchant.controller.dart b/lib/screens/merchant/merchant.controller.dart index 045ec837..c4759e08 100644 --- a/lib/screens/merchant/merchant.controller.dart +++ b/lib/screens/merchant/merchant.controller.dart @@ -1,31 +1,29 @@ import 'package:card_swiper/card_swiper.dart'; -import 'package:ecommerce_int2/data/models/cart.model.dart'; +import 'package:ecommerce_int2/data/models/merchant.model.dart'; import 'package:ecommerce_int2/data/models/product.model.dart'; -import 'package:ecommerce_int2/data/repository/cart.repository.dart'; -import 'package:ecommerce_int2/screens/address/add_address_page.dart'; -import 'package:ecommerce_int2/screens/search_products/search_controller.dart'; +import 'package:ecommerce_int2/data/repository/merchant.repository.dart'; import 'package:ecommerce_int2/utils/message_dialog.dart'; import 'package:get/get.dart'; class MerchantController extends GetxController { - final CartRepository repository; + final MerchantRepository merchantRepository; final SwiperController swiperController = SwiperController(); - MerchantController(this.repository); + MerchantController(this.merchantRepository); List get products { - return Get.find() - .list - .where((element) => element.merchant == merchant) - .toList(); + return data?.products ?? []; } - List? carts; String? merchantId; + MerchantData? data; - String get merchant => merchantId ?? 'Merchant'; - String get des => 'A shop sellling high quality assets'; + String get merchant => data?.merchant?.name ?? 'Merchant'; + String get des => + data?.merchant?.business ?? 'A shop sellling high quality assets'; + String get email => data?.merchant?.email ?? ''; + String get phone => data?.merchant?.phoneNumber ?? ''; @override onInit() { @@ -40,60 +38,16 @@ class MerchantController extends GetxController { } } - String get total { - int result = 0; - products.forEach((element) { - result += element.price ?? element.purchasePrice ?? 0; - }); - return '$result VND'; - } - - Future getCart() async { - repository.getCarts().then((value) { - carts = value; - update(); - }); - } - - void remove(Product product) { - CartModel? cart = carts! - .firstWhereOrNull((element) => element.products!.contains(product)); - if (cart == null) { - MessageDialog.showToast("There is something wrong!!"); + void getInfo() async { + if (merchantId == null) { + MessageDialog.showConfirmDialog( + content: "Error loading", + ); return; } - repository.deleteProduct(cart.sId!, product.sId!); - cart.products!.remove(product); - update(); - } - - void addProduct(Product product, {int? quantity}) async { - try { - AddProductParam param = AddProductParam(products: [ - ProductParam( - product: product.sId, - price: product.price, - merchant: product.merchant, - quantity: quantity) - ]); - final String cartId = await repository.addProduct(param); - MessageDialog.showToast("Added product to cart"); - int index = carts!.indexWhere((element) => element.sId == cartId); - if (index != -1) { - carts![index].products!.add(product); - } else { - carts!.add(CartModel(sId: cartId, products: [product])); - } - update(); - } on Exception catch (e) { - print(e); - } - } - void checkOut() async { - MessageDialog.showLoading(); - final List orderIds = await repository.checkOutCart(carts!); - MessageDialog.hideLoading(); - Get.to(() => AddAddressPage(), arguments: orderIds); + final res = await merchantRepository.getMerchantInfo(merchantId!); + data = res; + update(); } } diff --git a/lib/screens/merchant/merchant.view.dart b/lib/screens/merchant/merchant.view.dart index d8e10de5..7466ea69 100644 --- a/lib/screens/merchant/merchant.view.dart +++ b/lib/screens/merchant/merchant.view.dart @@ -1,4 +1,4 @@ -import 'package:ecommerce_int2/data/repository/cart.repository.dart'; +import 'package:ecommerce_int2/data/repository/merchant.repository.dart'; import 'package:ecommerce_int2/screens/merchant/merchant.controller.dart'; import 'package:ecommerce_int2/screens/product/product_page.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; @@ -22,7 +22,7 @@ class MerchantPage extends StatelessWidget { ), ), body: GetBuilder( - init: MerchantController(Get.find()), + init: MerchantController(Get.find()), builder: (controller) => Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -34,21 +34,46 @@ class MerchantPage extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - controller.merchant, - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 16), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + controller.merchant, + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 16), + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + controller.des, + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 16), + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + controller.email, + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 16), + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + controller.phone, + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 16), + ), ), - const SizedBox(height: 40), - Text( - controller.des, - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 16), - ) ], ), ), @@ -57,13 +82,12 @@ class MerchantPage extends StatelessWidget { padding: EdgeInsets.zero, crossAxisCount: 4, itemCount: controller.products.length, - itemBuilder: (BuildContext context, int index) => - new ClipRRect( + itemBuilder: (BuildContext context, int index) => new ClipRRect( borderRadius: BorderRadius.all(Radius.circular(5.0)), child: InkWell( onTap: () => Navigator.of(context).push(MaterialPageRoute( - builder: (_) => ProductPage( - product: controller.products[index]))), + builder: (_) => + ProductPage(product: controller.products[index]))), child: Container( decoration: BoxDecoration( gradient: RadialGradient( @@ -99,7 +123,6 @@ class MerchantPage extends StatelessWidget { class Scroll extends CustomPainter { @override void paint(Canvas canvas, Size size) { - LinearGradient grT = LinearGradient( colors: [Colors.transparent, Colors.black26], begin: Alignment.topCenter, diff --git a/lib/screens/notifications_page.dart b/lib/screens/notifications_page.dart index 7602ad12..a3da004a 100755 --- a/lib/screens/notifications_page.dart +++ b/lib/screens/notifications_page.dart @@ -1,5 +1,4 @@ import 'package:ecommerce_int2/utils/app_properties.dart'; -import 'package:ecommerce_int2/screens/rating/rating_page.dart'; import 'package:ecommerce_int2/screens/tracking/tracking_page.dart'; import 'package:flutter/material.dart'; @@ -262,27 +261,6 @@ class NotificationsPage extends StatelessWidget { ) ]), ), - InkWell( - onTap: () => Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => RatingPage())), - child: Container( - padding: const EdgeInsets.all(14.0), - decoration: BoxDecoration( - color: yellow, - borderRadius: BorderRadius.only( - bottomRight: Radius.circular(5.0), - bottomLeft: Radius.circular(5.0))), - child: Align( - alignment: Alignment.centerRight, - child: Text( - 'Share your feedback', - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 10), - ))), - ) ], ), ), diff --git a/lib/screens/product/product_page.dart b/lib/screens/product/product_page.dart index 1e840156..963e0d18 100755 --- a/lib/screens/product/product_page.dart +++ b/lib/screens/product/product_page.dart @@ -1,6 +1,7 @@ import 'package:ecommerce_int2/data/models/product.model.dart'; import 'package:ecommerce_int2/screens/main/components/product_list.dart'; import 'package:ecommerce_int2/screens/merchant/merchant.view.dart'; +import 'package:ecommerce_int2/screens/rating/rating_page.dart'; import 'package:ecommerce_int2/screens/search_products/search_controller.dart'; import 'package:ecommerce_int2/screens/shop/cart.controller.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; @@ -111,6 +112,7 @@ class ProductPage extends StatelessWidget { child: Center(child: viewProductButton), ), ), + Ratings(product: product), GestureDetector( onTap: () => Get.to(() => MerchantPage(), arguments: product.merchant), child: Padding( @@ -124,7 +126,7 @@ class ProductPage extends StatelessWidget { ProductListView( products: Get.find() .list - .where((element) => element.merchant == product.merchant) + .where((element) => element.subcategory == product.subcategory) .toList()) ], ), diff --git a/lib/screens/rating/rating_dialog.dart b/lib/screens/rating/rating_dialog.dart index 02f385cc..2adf60d9 100755 --- a/lib/screens/rating/rating_dialog.dart +++ b/lib/screens/rating/rating_dialog.dart @@ -1,107 +1,87 @@ -import 'package:ecommerce_int2/utils/app_properties.dart'; -import 'package:ecommerce_int2/screens/shop/check_out_page.dart'; +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/data/repository/review.repository.dart'; +import 'package:ecommerce_int2/screens/rating/review.controller.dart'; import 'package:flutter/material.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; +import 'package:get/get.dart'; class RatingDialog extends StatelessWidget { + final Product product; + + const RatingDialog({Key? key, required this.product}) : super(key: key); @override Widget build(BuildContext context) { - double width = MediaQuery.of(context).size.width; - - Widget payNow = InkWell( - onTap: () async { - Navigator.of(context).pop(); - Navigator.of(context) - .push(MaterialPageRoute(builder: (_) => CheckOutPage())); - }, - child: Container( - height: 60, - width: width / 1.5, - decoration: BoxDecoration( - gradient: mainButton, - boxShadow: [ - BoxShadow( - color: Color.fromRGBO(0, 0, 0, 0.16), - offset: Offset(0, 5), - blurRadius: 10.0, - ) - ], - borderRadius: BorderRadius.circular(9.0)), - child: Center( - child: Text("Pay Now", - style: const TextStyle( - color: const Color(0xfffefefe), - fontWeight: FontWeight.w600, - fontStyle: FontStyle.normal, - fontSize: 20.0)), - ), - ), - ); - return SingleChildScrollView( - physics: ClampingScrollPhysics(), - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(10)), - color: Colors.grey[50]), - padding: EdgeInsets.all(24.0), - child: Column(mainAxisSize: MainAxisSize.min, children: [ - Text( - 'Thank You!', - style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), - ), - Padding( - padding: const EdgeInsets.symmetric(vertical: 16.0), - child: RichText( - text: TextSpan( - style: - TextStyle(fontFamily: 'Montserrat', color: Colors.grey), - children: [ - TextSpan( - text: 'You rated ', - ), - TextSpan( - text: 'Boat Rockerz 350 On-Ear Bluetooth Headphones', - style: TextStyle( - fontWeight: FontWeight.bold, - color: Colors.grey[600])) - ]), + return GetBuilder( + init: ReviewController(Get.find(), product.sId!), + tag: product.sId!, + global: false, + builder: (controller) => SingleChildScrollView( + physics: ClampingScrollPhysics(), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(10)), + color: Colors.grey[50]), + padding: EdgeInsets.all(24.0), + child: Column(mainAxisSize: MainAxisSize.min, children: [ + Text( + 'Thank You!', + style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), ), - ), - RatingBar( - itemSize: 32, - allowHalfRating: false, - initialRating: 1, - itemPadding: EdgeInsets.symmetric(horizontal: 4.0), - onRatingUpdate: (value) {}, - ratingWidget: RatingWidget( - empty: Icon(Icons.favorite_border, - color: Color(0xffFF8993), size: 20), - full: Icon( - Icons.favorite, - color: Color(0xffFF8993), - size: 20, + Padding( + padding: const EdgeInsets.symmetric(vertical: 16.0), + child: RichText( + text: TextSpan( + style: TextStyle( + fontFamily: 'Montserrat', color: Colors.grey), + children: [ + TextSpan( + text: 'You rated ', + ), + TextSpan( + text: product.name, + style: TextStyle( + fontWeight: FontWeight.bold, + color: Colors.grey[600])) + ]), ), - half: SizedBox(), ), - ), - Container( - margin: EdgeInsets.symmetric(vertical: 16.0), - padding: EdgeInsets.all(16.0), - decoration: BoxDecoration( - color: Colors.grey[200], - borderRadius: BorderRadius.all(Radius.circular(5))), - child: TextField( - controller: TextEditingController(), - decoration: InputDecoration( - border: InputBorder.none, - contentPadding: EdgeInsets.zero, - hintText: 'Say something about the product.'), - style: TextStyle(fontSize: 12, color: Colors.grey[600]), - maxLength: 200, - )), - payNow - ])), + RatingBar( + itemSize: 32, + allowHalfRating: false, + initialRating: 1, + itemPadding: EdgeInsets.symmetric(horizontal: 4.0), + onRatingUpdate: (value) { + controller.updateRating(value.toInt()); + }, + ratingWidget: RatingWidget( + empty: Icon(Icons.favorite_border, + color: Color(0xffFF8993), size: 20), + full: Icon( + Icons.favorite, + color: Color(0xffFF8993), + size: 20, + ), + half: SizedBox(), + ), + ), + Container( + margin: EdgeInsets.symmetric(vertical: 16.0), + padding: EdgeInsets.all(16.0), + decoration: BoxDecoration( + color: Colors.grey[200], + borderRadius: BorderRadius.all(Radius.circular(5))), + child: TextField( + controller: controller.textEditingController, + decoration: InputDecoration( + border: InputBorder.none, + contentPadding: EdgeInsets.zero, + hintText: 'Say something about the product.'), + style: TextStyle(fontSize: 12, color: Colors.grey[600]), + maxLength: 200, + )), + ])), + ), ); } } diff --git a/lib/screens/rating/rating_page.dart b/lib/screens/rating/rating_page.dart index 8684ef6f..b28902f2 100755 --- a/lib/screens/rating/rating_page.dart +++ b/lib/screens/rating/rating_page.dart @@ -1,262 +1,111 @@ -import 'package:ecommerce_int2/utils/app_properties.dart'; +import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:ecommerce_int2/data/repository/review.repository.dart'; +import 'package:ecommerce_int2/screens/rating/review.controller.dart'; import 'package:flutter/material.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; -import 'package:ecommerce_int2/screens/rating/rating_dialog.dart'; +import 'package:get/get.dart'; -class RatingPage extends StatefulWidget { - @override - _RatingPageState createState() => _RatingPageState(); -} - -class _RatingPageState extends State { - double rating = 0.0; - List ratings = [2, 1, 5, 2, 4, 3]; +class Ratings extends StatelessWidget { + const Ratings({Key? key, required this.product}) : super(key: key); + final Product product; @override Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Colors.grey[100], - appBar: AppBar( - backgroundColor: Colors.transparent, - iconTheme: IconThemeData(color: Colors.black), - elevation: 0.0, - actions: [ - IconButton( - icon: Image.asset('assets/icons/comment.png'), - onPressed: () { - showDialog( - context: context, - builder: (BuildContext context) { - return Dialog( - shape: BeveledRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(10))), - child: RatingDialog(), - ); - }, - ); - }, - color: Colors.black, - ), - ], - ), - body: SafeArea( - child: LayoutBuilder( - builder: (b, constraints) => Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints(minHeight: constraints.maxHeight), - child: Column( - children: [ - Column( - children: [ - Container( + return GetBuilder( + init: ReviewController(Get.find(), product.sId!), + tag: product.sId!, + global: false, + builder: (controller) => controller.reviewList.isEmpty + ? SizedBox.shrink() + : Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + ...controller.reviewList + .map((val) => Container( + margin: const EdgeInsets.symmetric(vertical: 4.0), padding: const EdgeInsets.all(8.0), - height: 92, - width: 92, decoration: BoxDecoration( - color: yellow, - shape: BoxShape.circle, - boxShadow: shadow, - border: Border.all( - width: 8.0, color: Colors.white)), - child: Image.asset('assets/headphones.png'), - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 72.0, vertical: 16.0), - child: Text( - 'Boat Rockerz 350 On-Ear Bluetooth Headphones', - style: TextStyle(fontWeight: FontWeight.bold), - textAlign: TextAlign.center, - ), - ) - ], - ), - Divider(), - Padding( - padding: const EdgeInsets.symmetric(vertical: 40), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.only(right: 16.0), - child: Text( - '4.8', - style: TextStyle(fontSize: 48), - ), - ), - Column( + color: Colors.white, + borderRadius: + BorderRadius.all(Radius.circular(5.0))), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - RatingBar( -// borderColor: Color(0xffFF8993), -// fillColor: Color(0xffFF8993), - ignoreGestures: true, - itemSize: 20, - allowHalfRating: true, - initialRating: 1, - itemPadding: - EdgeInsets.symmetric(horizontal: 4.0), - ratingWidget: RatingWidget( - empty: Icon(Icons.favorite_border, - color: Color(0xffFF8993), size: 20), - full: Icon( - Icons.favorite, - color: Color(0xffFF8993), - size: 20, - ), - half: SizedBox(), + Padding( + padding: const EdgeInsets.only(right: 16.0), + child: CircleAvatar( + maxRadius: 14, + backgroundImage: + AssetImage('assets/background.jpg'), ), - onRatingUpdate: (value) { - setState(() { - rating = value; - }); - print(value); - }, ), - Padding( - padding: const EdgeInsets.only(top: 4.0), - child: Text('from 25 people'), - ) - ], - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.only(bottom: 16.0), - child: Align( - alignment: Alignment(-1, 0), - child: Text('Recent Reviews')), - ), - Column( - children: [ - ...ratings - .map((val) => Container( - margin: - const EdgeInsets.symmetric(vertical: 4.0), - padding: const EdgeInsets.all(8.0), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all( - Radius.circular(5.0))), - child: Row( + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + val.user?.firstName ?? "Anonymous", + style: TextStyle( + fontWeight: FontWeight.bold), + ), + Text( + '10 am, Via iOS', + style: TextStyle( + color: Colors.grey, + fontSize: 10.0), + ) + ], + ), Padding( - padding: - const EdgeInsets.only(right: 16.0), - child: CircleAvatar( - maxRadius: 14, - backgroundImage: AssetImage( - 'assets/background.jpg'), + padding: const EdgeInsets.symmetric( + vertical: 8.0), + child: RatingBar( + ignoreGestures: true, + itemSize: 20, + allowHalfRating: true, + initialRating: + (val.rating ?? 5).toDouble(), + itemPadding: EdgeInsets.symmetric( + horizontal: 4.0), + ratingWidget: RatingWidget( + empty: Icon(Icons.favorite_border, + color: Color(0xffFF8993), + size: 20), + full: Icon( + Icons.favorite, + color: Color(0xffFF8993), + size: 20, + ), + half: SizedBox(), + ), + onRatingUpdate: (value) { + print(value); + }, ), ), - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment - .spaceBetween, - children: [ - Text( - 'Billy Holand', - style: TextStyle( - fontWeight: - FontWeight.bold), - ), - Text( - '10 am, Via iOS', - style: TextStyle( - color: Colors.grey, - fontSize: 10.0), - ) - ], - ), - Padding( - padding: - const EdgeInsets.symmetric( - vertical: 8.0), - child: RatingBar( - ignoreGestures: true, - itemSize: 20, - allowHalfRating: true, - initialRating: val.toDouble(), - itemPadding: - EdgeInsets.symmetric( - horizontal: 4.0), - ratingWidget: RatingWidget( - empty: Icon( - Icons.favorite_border, - color: Color(0xffFF8993), - size: 20), - full: Icon( - Icons.favorite, - color: Color(0xffFF8993), - size: 20, - ), - half: SizedBox(), - ), - onRatingUpdate: (value) { - setState(() { - rating = value; - }); - print(value); - }, - ), - ), - Text( - 'Not as I expected! ... I`m really sad', - style: TextStyle( - color: Colors.grey, - ), - ), - Padding( - padding: - const EdgeInsets.symmetric( - vertical: 16.0), - child: Row( - mainAxisAlignment: - MainAxisAlignment - .spaceBetween, - children: [ - Text( - '21 likes', - style: TextStyle( - color: Colors.grey[400], - fontSize: 10.0), - ), - Text( - '1 Comment', - style: TextStyle( - color: Colors.blue, - fontWeight: - FontWeight.bold, - fontSize: 10.0), - ) - ], - ), - ) - ], + Text( + val.review ?? "Review is hidden", + style: TextStyle( + color: Colors.grey, ), - ) + ), + const SizedBox(height: 12) ], - ))) - .toList() - ], - ) - ], - ), + ), + ) + ], + ))) + .toList() + ], ), - ), - ), - ), - )); + )); } } diff --git a/lib/screens/rating/review.controller.dart b/lib/screens/rating/review.controller.dart new file mode 100644 index 00000000..239ec337 --- /dev/null +++ b/lib/screens/rating/review.controller.dart @@ -0,0 +1,48 @@ +import 'package:ecommerce_int2/data/models/review.dart'; +import 'package:ecommerce_int2/data/repository/review.repository.dart'; +import 'package:ecommerce_int2/utils/message_dialog.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:get/get.dart'; + +class ReviewController extends GetxController { + final ReviewRepository repository; + final String productId; + + final TextEditingController textEditingController = TextEditingController(); + + ReviewController(this.repository, this.productId); + + ReviewParam param = ReviewParam(rating: 5); + + @override + onInit() { + getReview(); + super.onInit(); + } + + void updateRating(int value) { + param.rating = value; + } + + void addReview() async { + try { + ReviewParam param = ReviewParam( + product: productId, review: textEditingController.text.trim()); + await repository.addReview(param); + MessageDialog.showToast("Thank you for your review"); + Get.back(); + } on Exception catch (e) { + print(e); + } + } + + List? reviews; + + List get reviewList => reviews ?? []; + + void getReview() async { + final res = await repository.getReviewProduct(productId); + reviews = res; + update(); + } +} diff --git a/lib/screens/tracking/order_detail.view.dart b/lib/screens/tracking/order_detail.view.dart index 5848e6f6..5a854326 100644 --- a/lib/screens/tracking/order_detail.view.dart +++ b/lib/screens/tracking/order_detail.view.dart @@ -77,6 +77,7 @@ class OrderDetail extends StatelessWidget { .map((product) => ProductCard( product: product, height: 130, + hasReceived: controller.detail?.status == 'RECEIVED', width: Get.width)) .toList(), const SizedBox(height: 16), @@ -96,10 +97,6 @@ class OrderDetail extends StatelessWidget { onTap: () => controller.confirmOrder(orderId), ), - if (controller.detail?.status == 'RECEIVED') - Button( - title: 'Add review', - onTap: () => print('add review')) ], ) : SizedBox.shrink(), diff --git a/lib/utils/dependencies.dart b/lib/utils/dependencies.dart index 8473d016..89662d76 100644 --- a/lib/utils/dependencies.dart +++ b/lib/utils/dependencies.dart @@ -2,14 +2,18 @@ import 'package:ecommerce_int2/data/provider/address.provider.dart'; import 'package:ecommerce_int2/data/provider/auth.provider.dart'; import 'package:ecommerce_int2/data/provider/cart.provider.dart'; import 'package:ecommerce_int2/data/provider/category.provider.dart'; +import 'package:ecommerce_int2/data/provider/merchant.provider.dart'; import 'package:ecommerce_int2/data/provider/order.provider.dart'; import 'package:ecommerce_int2/data/provider/product.provider.dart'; +import 'package:ecommerce_int2/data/provider/review.provider.dart'; import 'package:ecommerce_int2/data/repository/address.repository.dart'; import 'package:ecommerce_int2/data/repository/auth.repository.dart'; import 'package:ecommerce_int2/data/repository/cart.repository.dart'; import 'package:ecommerce_int2/data/repository/category.repository.dart'; +import 'package:ecommerce_int2/data/repository/merchant.repository.dart'; import 'package:ecommerce_int2/data/repository/order.repository.dart'; import 'package:ecommerce_int2/data/repository/product.repository.dart'; +import 'package:ecommerce_int2/data/repository/review.repository.dart'; import 'package:ecommerce_int2/screens/search_products/search_controller.dart'; import 'package:ecommerce_int2/screens/shop/cart.controller.dart'; import 'package:ecommerce_int2/services/auth.service.dart'; @@ -34,6 +38,10 @@ class Dependency { ..put(CartController(Get.find()), permanent: true) ..put(OrderProvider(Get.find())) ..put(OrderRepository(Get.find())) + ..put(MerchantProvider(Get.find())) + ..put(MerchantRepository(Get.find())) + ..put(ReviewProvider(Get.find())) + ..put(ReviewRepository(Get.find())) ..put(SearchProductController(Get.find())) ; } diff --git a/lib/utils/message_dialog.dart b/lib/utils/message_dialog.dart index be0e84ef..c760b331 100644 --- a/lib/utils/message_dialog.dart +++ b/lib/utils/message_dialog.dart @@ -10,6 +10,7 @@ class MessageDialog { static void showToast(String text) { Get.showSnackbar(GetSnackBar( + backgroundColor: Colors.white, messageText: Text(text), )); } From a89788482a407465dd95f7d9432a9e0e478056dd Mon Sep 17 00:00:00 2001 From: manmaihuu <103487985+pdax-manmai@users.noreply.github.com> Date: Wed, 22 Jun 2022 15:03:49 +0700 Subject: [PATCH 45/49] Add payment for cart --- .flutter-plugins-dependencies | 2 +- lib/data/repository/cart.repository.dart | 8 +- lib/screens/address/add_address_page.dart | 2 +- lib/screens/address/address.controller.dart | 12 +- lib/screens/payment/payment.controller.dart | 52 +++ lib/screens/payment/payment_page.dart | 378 ++++---------------- lib/screens/shop/cart.controller.dart | 3 +- lib/screens/tracking/tracking_page.dart | 9 +- 8 files changed, 134 insertions(+), 332 deletions(-) create mode 100644 lib/screens/payment/payment.controller.dart diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index eb65f3e5..ce1e38e0 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]},{"name":"webview_flutter_wkwebview","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_wkwebview-2.7.5\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]},{"name":"webview_flutter_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_android-2.8.10\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2022-06-22 10:08:31.555869","version":"2.10.4"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]},{"name":"webview_flutter_wkwebview","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_wkwebview-2.7.5\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]},{"name":"webview_flutter_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_android-2.8.10\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2022-06-22 14:17:13.739521","version":"2.10.4"} \ No newline at end of file diff --git a/lib/data/repository/cart.repository.dart b/lib/data/repository/cart.repository.dart index a065fd39..f5de1288 100644 --- a/lib/data/repository/cart.repository.dart +++ b/lib/data/repository/cart.repository.dart @@ -41,12 +41,12 @@ class CartRepository { } } - Future> checkOutCart(List carts) async { - List orderIds = []; + Future> checkOutCart(List carts) async { + List orderIds = []; for(CartModel cart in carts) { final response = await provider.checkoutCart(cart.sId!, cart.merchant!); - OrderResponse order = OrderResponse.fromJson(response.body); - orderIds.add(order. order!.sId!); + OrderProceed order = OrderProceed.fromJson(response.body); + orderIds.add(order); } return orderIds; } diff --git a/lib/screens/address/add_address_page.dart b/lib/screens/address/add_address_page.dart index 464f7333..fd884787 100755 --- a/lib/screens/address/add_address_page.dart +++ b/lib/screens/address/add_address_page.dart @@ -140,7 +140,7 @@ class AddAddressPage extends StatelessWidget { itemCount: 2, itemBuilder: (_, index) { return CreditCard( - text: index == 0 ? 'CASH \$\$\$' : 'PAYPAL', + text: index == 0 ? 'CASH' : 'PAYPAL', ); }, scale: 0.8, diff --git a/lib/screens/address/address.controller.dart b/lib/screens/address/address.controller.dart index 0b2f267b..d1a183ec 100644 --- a/lib/screens/address/address.controller.dart +++ b/lib/screens/address/address.controller.dart @@ -23,7 +23,7 @@ class AddressController extends GetxController { AddressController(this.repository, this.orderRepository, this.authService); - List? orderIds; + List? orderIds; List
addresses =
[Address()]; @@ -46,7 +46,7 @@ class AddressController extends GetxController { void getArgument() { final arg = Get.arguments; - if (arg != null && arg is List) { + if (arg != null && arg is List) { orderIds = arg; } } @@ -95,11 +95,15 @@ class AddressController extends GetxController { Get.back(); return; } + if( swiperController.index == 1) { + final done = await Get.to(() => PaymentPage()); + if(!done) return; + } try { MessageDialog.showLoading(); - for (String order in orderIds!) { + for (OrderProceed order in orderIds!) { await orderRepository.completeOrder( - order, + order.data!.order!.sId! , CompleteOrderParam( address: '${selectedAddress.address}, ${selectedAddress.city}', phoneNumber: authService.userModel!.email, diff --git a/lib/screens/payment/payment.controller.dart b/lib/screens/payment/payment.controller.dart new file mode 100644 index 00000000..61ad2e84 --- /dev/null +++ b/lib/screens/payment/payment.controller.dart @@ -0,0 +1,52 @@ +import 'package:ecommerce_int2/data/models/order.model.dart'; +import 'package:ecommerce_int2/data/repository/order.repository.dart'; +import 'package:ecommerce_int2/utils/message_dialog.dart'; +import 'package:ecommerce_int2/utils/webview.dart'; +import 'package:get/get.dart'; + +class PaymentController extends GetxController { + final OrderRepository repository; + + List? orders; + + PaymentController(this.repository); + + OrderDocDetail? detail; + + @override + void onReady() { + super.onReady(); + } + + void getArg() { + final arg = Get.arguments; + if (arg != null && arg is List) { + orders = arg; + } + } + + + void makePayment(OrderProceed order) async { + MessageDialog.showLoading(); + try { + await Get.to(() => WebViewExample( + url: order.data!.payment!.links! + .firstWhere( + (element) => element.method!.toUpperCase() == 'REDIRECT') + .href!)); + final res = await repository.getOrderDetail(order.data!.order!.sId!); + if (res.paymentStatus == "PAID") orders!.remove(order); + if (orders!.isEmpty) { + onBack(); + } + update(); + } on Exception catch (e) { + MessageDialog.showToast(e.toString()); + } + MessageDialog.hideLoading(); + } + + void onBack() { + Get.back(result: orders!.isEmpty); + } +} diff --git a/lib/screens/payment/payment_page.dart b/lib/screens/payment/payment_page.dart index d610c47a..4f965f42 100755 --- a/lib/screens/payment/payment_page.dart +++ b/lib/screens/payment/payment_page.dart @@ -1,331 +1,79 @@ +import 'package:ecommerce_int2/data/repository/order.repository.dart'; +import 'package:ecommerce_int2/screens/payment/payment.controller.dart'; +import 'package:ecommerce_int2/screens/tracking/row_text.widget.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; -import 'package:ecommerce_int2/screens/product/components/color_list.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'dart:math' as math; - -class PaymentPage extends StatefulWidget { - @override - _PaymentPageState createState() => _PaymentPageState(); -} - -class _PaymentPageState extends State { - Color active = Colors.red; - TextEditingController cardNumber = TextEditingController(); - TextEditingController year = TextEditingController(); - TextEditingController month = TextEditingController(); - TextEditingController cvc = TextEditingController(); - TextEditingController cardHolder = TextEditingController(); - - ScrollController scrollController = ScrollController(); - - @override - void initState() { - super.initState(); - scrollController.addListener(() { - if (scrollController.position.userScrollDirection.index == 1) { - FocusScope.of(context).requestFocus(FocusNode()); - } - }); - } - - String convertCardNumber(String src, String divider) { - String newStr = ''; - int step = 4; - for (int i = 0; i < src.length; i += step) { - newStr += src.substring(i, math.min(i + step, src.length)); - if (i + step < src.length) newStr += divider; - } - return newStr; - } - - String convertMonthYear(String month, String year) { - if (month.isNotEmpty) - return month + '/' + year; - else - return ''; - } +import 'package:get/get.dart'; +class PaymentPage extends StatelessWidget { @override Widget build(BuildContext context) { - Widget addThisCard = InkWell( -// onTap: () => Navigator.of(context) -// .push(MaterialPageRoute(builder: (_) => ViewProductPage())), - child: Container( - height: 80, - width: MediaQuery.of(context).size.width / 1.5, + return GetBuilder( + init: PaymentController(Get.find()), + builder: (controller) => Container( decoration: BoxDecoration( - gradient: mainButton, - boxShadow: [ - BoxShadow( - color: Color.fromRGBO(0, 0, 0, 0.16), - offset: Offset(0, 5), - blurRadius: 10.0, - ) - ], - borderRadius: BorderRadius.circular(9.0)), - child: Center( - child: Text("Add This Card", - style: const TextStyle( - color: const Color(0xfffefefe), - fontWeight: FontWeight.w600, - fontStyle: FontStyle.normal, - fontSize: 20.0)), - ), - ), - ); - - return Scaffold( - backgroundColor: Colors.white, - body: LayoutBuilder( - builder: (_, constraints) => GestureDetector( - onPanDown: (val) {}, - behavior: HitTestBehavior.opaque, - child: SingleChildScrollView( - controller: scrollController, - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, + color: Colors.grey[100], + image: DecorationImage( + image: AssetImage('assets/Group 444.png'), + fit: BoxFit.contain)), + child: Container( + color: Colors.white54, + child: Scaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + elevation: 0.0, + iconTheme: IconThemeData(color: Colors.grey), + title: Text( + 'Your payment', + style: TextStyle( + color: darkGrey, + fontSize: 22, + fontWeight: FontWeight.bold, + ), + ), + leading: BackButton(onPressed: () => controller.onBack()), ), - child: Container( - margin: const EdgeInsets.only(top: kToolbarHeight), - padding: EdgeInsets.symmetric(horizontal: 16.0), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Payment', - style: TextStyle( - color: darkGrey, - fontSize: 22, - fontWeight: FontWeight.bold, - ), - ), - CloseButton() - ], - ), - Container( - height: 200, - width: MediaQuery.of(context).size.width, - padding: EdgeInsets.all(32.0), - decoration: BoxDecoration( - color: active, - borderRadius: BorderRadius.all(Radius.circular(10))), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'CREDIT CARD', - style: TextStyle(color: Colors.white), - ), - SizedBox(height: 16.0), - Row( - children: [ - Container( - height: 25, - width: 40, - color: Colors.white, - ), - Flexible( - child: Center( - child: Text( - convertCardNumber( - cardNumber.text, '-'), - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 18.0)))), - ], - ), - Spacer(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(convertMonthYear(month.text, year.text), - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold)), - Text(cvc.text, - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold)) - ], - ), - Spacer(), - Text(cardHolder.text, - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 18.0)) - ], - ), - ), - Padding( - padding: const EdgeInsets.all(16.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Colors.red, - Colors.blue, - Colors.purple[700], - Colors.green[700], - Colors.lightBlueAccent - ] - .map((c) => InkWell( - onTap: () { - setState(() { - active = c ?? Colors.red; - }); - }, - child: Transform.scale( + body: SafeArea( + child: LayoutBuilder( + builder: (_, constraints) => SingleChildScrollView( + child: Column( + children: [ + ...controller.orders!.reversed + .map((order) => GestureDetector( + onTap: (() => controller.makePayment(order)), + child: Container( + width: Get.width, + child: Card( child: Padding( padding: const EdgeInsets.all(8.0), - child: ColorOption(c ?? Colors.red), + child: Column( + children: [ + RowTextWidget( + text1: 'ID', + text2: + '${order.data!.order!.sId}'), + RowTextWidget( + text1: 'Deliver status', + text2: + ' ${order.data!.payment!.transactions!.fold(0, (previousValue, element) => (previousValue as int) + (element.amount?.total as int? ?? 0))}'), + RowTextWidget( + text1: 'Merchant', + text2: + '${order.data?.order?.merchant ?? ''}'), + ], + crossAxisAlignment: + CrossAxisAlignment.start, + ), ), - scale: active == c ? 1.2 : 1), - )) - .toList(), - ), - ), - Container( - padding: EdgeInsets.all(16.0), - height: 250, - width: MediaQuery.of(context).size.width, - decoration: BoxDecoration( - color: Colors.white, - boxShadow: shadow, - borderRadius: BorderRadius.only( - bottomRight: Radius.circular(10), - bottomLeft: Radius.circular(10))), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - Container( - padding: EdgeInsets.only(left: 16.0), - decoration: BoxDecoration( - borderRadius: - BorderRadius.all(Radius.circular(5)), - color: Colors.grey[200], - ), - child: TextField( - inputFormatters: [ - LengthLimitingTextInputFormatter(16) - ], - controller: cardNumber, - onChanged: (val) { - setState(() {}); - }, - decoration: InputDecoration( - border: InputBorder.none, - hintText: 'Card Number'), - ), - ), - Row( - children: [ - Flexible( - child: Container( - padding: EdgeInsets.only(left: 16.0), - decoration: BoxDecoration( - borderRadius: - BorderRadius.all(Radius.circular(5)), - color: Colors.grey[200], - ), - child: TextField( - inputFormatters: [ - LengthLimitingTextInputFormatter(2) - ], - controller: month, - decoration: InputDecoration( - border: InputBorder.none, - hintText: 'Month'), - onChanged: (val) { - setState(() {}); - }, + ), ), - ), - ), - SizedBox( - width: 8.0, - ), - Flexible( - child: Container( - padding: EdgeInsets.only(left: 16.0), - decoration: BoxDecoration( - borderRadius: - BorderRadius.all(Radius.circular(5)), - color: Colors.grey[200], - ), - child: TextField( - inputFormatters: [ - LengthLimitingTextInputFormatter(2) - ], - controller: year, - decoration: InputDecoration( - border: InputBorder.none, - hintText: 'Year'), - onChanged: (val) { - setState(() {}); - }, - ), - ), - ), - SizedBox( - width: 8.0, - ), - Flexible( - child: Container( - padding: EdgeInsets.only(left: 16.0), - decoration: BoxDecoration( - borderRadius: - BorderRadius.all(Radius.circular(5)), - color: Colors.grey[200], - ), - child: TextField( - controller: cvc, - decoration: InputDecoration( - border: InputBorder.none, - hintText: 'CVC'), - onChanged: (val) { - setState(() {}); - }, - ), - ), - ) - ], - ), - Container( - padding: EdgeInsets.only(left: 16.0), - decoration: BoxDecoration( - borderRadius: - BorderRadius.all(Radius.circular(5)), - color: Colors.grey[200], - ), - child: TextField( - controller: cardHolder, - decoration: InputDecoration( - border: InputBorder.none, - hintText: 'Name on card'), - onChanged: (val) { - setState(() {}); - }, - ), - ), - ], - ), + )) + .toList() + ], ), - SizedBox(height: 24.0), - Center( - child: Padding( - padding: EdgeInsets.only(bottom: 20), - child: addThisCard, - )) - ], + ), ), - ), - ), - ), + )), ), ), ); diff --git a/lib/screens/shop/cart.controller.dart b/lib/screens/shop/cart.controller.dart index 3dc7f049..41b5a860 100644 --- a/lib/screens/shop/cart.controller.dart +++ b/lib/screens/shop/cart.controller.dart @@ -1,4 +1,5 @@ import 'package:ecommerce_int2/data/models/cart.model.dart'; +import 'package:ecommerce_int2/data/models/order.model.dart'; import 'package:ecommerce_int2/data/models/product.model.dart'; import 'package:ecommerce_int2/data/repository/cart.repository.dart'; import 'package:ecommerce_int2/screens/address/add_address_page.dart'; @@ -84,7 +85,7 @@ class CartController extends GetxController { void checkOut() async { MessageDialog.showLoading(); - final List orderIds = await repository.checkOutCart(carts!); + final List orderIds = await repository.checkOutCart(carts!); MessageDialog.hideLoading(); Get.to(() => AddAddressPage(), arguments: orderIds); } diff --git a/lib/screens/tracking/tracking_page.dart b/lib/screens/tracking/tracking_page.dart index 5f14bfa3..06fb7813 100644 --- a/lib/screens/tracking/tracking_page.dart +++ b/lib/screens/tracking/tracking_page.dart @@ -50,9 +50,8 @@ class TrackingPage extends StatelessWidget { child: Column( children: [ RowTextWidget( - text1: 'Order Id', - text2: - '${order.sId ?? 'Order'}'), + text1: 'Date', + text2: '${order.createdDate}'), RowTextWidget( text1: 'Deliver status', text2: @@ -65,9 +64,7 @@ class TrackingPage extends StatelessWidget { text1: 'Merchant', text2: '${order.merchant ?? ''}'), - RowTextWidget( - text1: 'Date', - text2: '${order.createdDate}'), + ], crossAxisAlignment: CrossAxisAlignment.start, From 0db861585f364e836016ec1992df00c816d6ce41 Mon Sep 17 00:00:00 2001 From: manmaihuu <103487985+pdax-manmai@users.noreply.github.com> Date: Thu, 23 Jun 2022 14:38:05 +0700 Subject: [PATCH 46/49] Fix bugs --- .flutter-plugins-dependencies | 2 +- lib/data/models/order.model.dart | 5 +- lib/data/provider/order.provider.dart | 7 +- lib/data/repository/order.repository.dart | 8 + lib/screens/address/add_address_page.dart | 3 + lib/screens/address/address.controller.dart | 17 +- .../category/sub_category_list_page.dart | 14 +- lib/screens/main/components/product_list.dart | 98 +++---- lib/screens/payment/payment.controller.dart | 13 +- lib/screens/payment/payment_page.dart | 4 +- lib/screens/product/product_page.dart | 2 +- lib/screens/rating/rating_dialog.dart | 29 +- .../search_products/search_controller.dart | 1 + lib/screens/search_products/search_page.dart | 253 +++--------------- lib/screens/shop/cart.controller.dart | 8 +- lib/screens/shop/check_out_page.dart | 10 - lib/screens/tracking/order_detail.view.dart | 11 +- lib/utils/webview.dart | 53 ++-- 18 files changed, 191 insertions(+), 347 deletions(-) diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index ce1e38e0..8d0c2ed4 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]},{"name":"webview_flutter_wkwebview","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_wkwebview-2.7.5\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]},{"name":"webview_flutter_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_android-2.8.10\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2022-06-22 14:17:13.739521","version":"2.10.4"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]},{"name":"webview_flutter_wkwebview","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_wkwebview-2.7.5\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]},{"name":"webview_flutter_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_android-2.8.10\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2022-06-23 14:08:41.383944","version":"2.10.4"} \ No newline at end of file diff --git a/lib/data/models/order.model.dart b/lib/data/models/order.model.dart index 14d5b4b4..9a80233c 100644 --- a/lib/data/models/order.model.dart +++ b/lib/data/models/order.model.dart @@ -42,7 +42,7 @@ class Order { if (created == null) return ''; final date = DateTime.tryParse(created!); if (date == null) return ''; - final res = DateFormat("yyyy-MM-dd HH:mm:ss aa").format(date); + final res = DateFormat("yyyy-MM-dd HH:mm:ss aa").format(date.toLocal()); return res; } @@ -268,8 +268,9 @@ class OrderDocDetail { } bool get isPayWithCash => payment == 'CASH' && canCancel; + bool get canConfirmReceive => status == 'DELIVERING'; - bool get canCancel => !(status == 'CANCLED' || status == 'RECEIVED') ; + bool get canCancel => !(status == 'CANCELLED' || status == 'RECEIVED') ; OrderDocDetail( {this.sId, diff --git a/lib/data/provider/order.provider.dart b/lib/data/provider/order.provider.dart index d822e788..730f5897 100644 --- a/lib/data/provider/order.provider.dart +++ b/lib/data/provider/order.provider.dart @@ -37,7 +37,7 @@ class OrderProvider { } Future cancleOrder(String orderId) { - return networkService.delete('$cancleOrder/$orderId/cancel'); + return networkService.delete('$cancleOrderUrl/$orderId/cancel'); } Future getOrderDetail(String orderId) { @@ -48,4 +48,9 @@ class OrderProvider { return networkService.put('$confirmReceivedUrl/$orderId/status', data: {"status": "RECEIVED"}); } + + Future payOrder(String orderId) { + return networkService.put('$confirmReceivedUrl/$orderId/status', + data: {"paymentStatus": "PAID"}); + } } diff --git a/lib/data/repository/order.repository.dart b/lib/data/repository/order.repository.dart index 607be7ff..333c8302 100644 --- a/lib/data/repository/order.repository.dart +++ b/lib/data/repository/order.repository.dart @@ -50,10 +50,18 @@ class OrderRepository { final res = DetailOrderResponse.fromJson(response.body); return res.orderDoc!; } + Future confirmReceived(String orderId) async { final response = await provider.confirmReceived(orderId); if (response.statusCode != 200) { throw Exception("Confirm order failed"); } } + + Future payOrder(String orderId) async { + final response = await provider.payOrder(orderId); + if (response.statusCode != 200) { + throw Exception("Confirm order failed"); + } + } } diff --git a/lib/screens/address/add_address_page.dart b/lib/screens/address/add_address_page.dart index fd884787..e1b8be3f 100755 --- a/lib/screens/address/add_address_page.dart +++ b/lib/screens/address/add_address_page.dart @@ -145,6 +145,9 @@ class AddAddressPage extends StatelessWidget { }, scale: 0.8, controller: controller.swiperController, + onIndexChanged: (value) { + controller.swiperIndex = value; + }, viewportFraction: 0.6, loop: false, fade: 0.7, diff --git a/lib/screens/address/address.controller.dart b/lib/screens/address/address.controller.dart index d1a183ec..de980396 100644 --- a/lib/screens/address/address.controller.dart +++ b/lib/screens/address/address.controller.dart @@ -29,6 +29,8 @@ class AddressController extends GetxController { int selectIndex = 0; + int swiperIndex = 0; + Address get selectedAddress => addresses[selectIndex]; @override @@ -95,25 +97,22 @@ class AddressController extends GetxController { Get.back(); return; } - if( swiperController.index == 1) { - final done = await Get.to(() => PaymentPage()); - if(!done) return; + if (swiperIndex == 1) { + final done = await Get.to(() => PaymentPage(), arguments: orderIds); + if (!done) return; } try { MessageDialog.showLoading(); for (OrderProceed order in orderIds!) { await orderRepository.completeOrder( - order.data!.order!.sId! , + order.data!.order!.sId!, CompleteOrderParam( address: '${selectedAddress.address}, ${selectedAddress.city}', phoneNumber: authService.userModel!.email, - payment: swiperController.index == 0 ? 'CASH' : 'PAYPAL')); + payment: swiperIndex == 0 ? 'CASH' : 'PAYPAL')); } MessageDialog.hideLoading(); - if (swiperController.index == 0) - Get.offAll(() => TrackingPage(), arguments: true); - else - Get.to(() => PaymentPage()); + Get.offAll(() => TrackingPage(), arguments: true); } on Exception catch (e) { MessageDialog.hideLoading(); print(e); diff --git a/lib/screens/category/sub_category_list_page.dart b/lib/screens/category/sub_category_list_page.dart index b2613315..b00dd3ad 100644 --- a/lib/screens/category/sub_category_list_page.dart +++ b/lib/screens/category/sub_category_list_page.dart @@ -28,10 +28,14 @@ class SubCategoryListPage extends StatelessWidget { child: Column( mainAxisSize: MainAxisSize.min, children: [ - const SizedBox(height: 16,), + const SizedBox( + height: 16, + ), Row( children: [ - BackButton(onPressed: () => Get.back(),), + BackButton( + onPressed: () => Get.back(), + ), Padding( padding: EdgeInsets.symmetric(vertical: 16.0), child: Text( @@ -75,8 +79,10 @@ class SubCategoryListPage extends StatelessWidget { end: const Color(0xffF68D7F), categoryName: controller.tempList[index].name ?? "", assetPath: 'assets/jeans_5.png', - onViewMore: () => Get.to(() => SearchPage(), - arguments: controller.tempList[index].slug), + onViewMore: () => Get.to( + () => SearchPage( + subCategory: controller.tempList[index].slug), + ), ), ), ), diff --git a/lib/screens/main/components/product_list.dart b/lib/screens/main/components/product_list.dart index 2c167620..b6e91393 100755 --- a/lib/screens/main/components/product_list.dart +++ b/lib/screens/main/components/product_list.dart @@ -1,7 +1,6 @@ import 'package:card_swiper/card_swiper.dart'; import 'package:ecommerce_int2/data/models/product.model.dart'; import 'package:ecommerce_int2/screens/rating/rating_dialog.dart'; -import 'package:ecommerce_int2/screens/tracking/order_detail.view.dart'; import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:ecommerce_int2/screens/product/product_page.dart'; import 'package:flutter/material.dart'; @@ -134,56 +133,57 @@ class ProductCard extends StatelessWidget { ), ), Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - product.name ?? "", - style: TextStyle(color: Colors.white, fontSize: 16.0), - ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + product.name ?? "", + style: TextStyle(color: Colors.white, fontSize: 16.0), + ), + Container( + padding: const EdgeInsets.fromLTRB(8.0, 4.0, 12.0, 4.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(10), + bottomLeft: Radius.circular(10)), + color: Color.fromRGBO(224, 69, 10, 1), ), - Container( - margin: const EdgeInsets.only(bottom: 12.0), - padding: const EdgeInsets.fromLTRB(8.0, 4.0, 12.0, 4.0), - decoration: BoxDecoration( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(10), - bottomLeft: Radius.circular(10)), - color: Color.fromRGBO(224, 69, 10, 1), - ), - child: Text( - '\$${product.price ?? product.purchasePrice ?? 0}', - style: TextStyle( - color: Colors.white, - fontSize: 18, - fontWeight: FontWeight.bold), - ), + child: Text( + '\$${product.price ?? product.purchasePrice ?? 0}', + style: TextStyle( + color: Colors.white, + fontSize: 18, + fontWeight: FontWeight.bold), ), - if (hasReceived) - Button( - title: 'Add review', - onTap: () { - showDialog( - context: context, - builder: (BuildContext context) { - return Dialog( - shape: BeveledRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(10))), - child: RatingDialog(product: product), - ); - }, - ); - }) - ], - ) - ], + ), + if (hasReceived) + Align( + alignment: Alignment.centerRight, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: GestureDetector( + child: Text('Add review', style: TextStyle(color: Colors.white),), + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return Dialog( + shape: BeveledRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(10))), + child: RatingDialog(product: product), + ); + }, + ); + }), + ), + ) + ], + ), ), ), ]), diff --git a/lib/screens/payment/payment.controller.dart b/lib/screens/payment/payment.controller.dart index 61ad2e84..8affcf36 100644 --- a/lib/screens/payment/payment.controller.dart +++ b/lib/screens/payment/payment.controller.dart @@ -14,8 +14,9 @@ class PaymentController extends GetxController { OrderDocDetail? detail; @override - void onReady() { - super.onReady(); + void onInit() { + getArg(); + super.onInit(); } void getArg() { @@ -25,10 +26,10 @@ class PaymentController extends GetxController { } } - void makePayment(OrderProceed order) async { MessageDialog.showLoading(); try { + repository.payOrder(order.data!.order!.sId!); await Get.to(() => WebViewExample( url: order.data!.payment!.links! .firstWhere( @@ -36,14 +37,14 @@ class PaymentController extends GetxController { .href!)); final res = await repository.getOrderDetail(order.data!.order!.sId!); if (res.paymentStatus == "PAID") orders!.remove(order); - if (orders!.isEmpty) { - onBack(); - } update(); } on Exception catch (e) { MessageDialog.showToast(e.toString()); } MessageDialog.hideLoading(); + if (orders!.isEmpty) { + onBack(); + } } void onBack() { diff --git a/lib/screens/payment/payment_page.dart b/lib/screens/payment/payment_page.dart index 4f965f42..4dee5cf3 100755 --- a/lib/screens/payment/payment_page.dart +++ b/lib/screens/payment/payment_page.dart @@ -53,9 +53,9 @@ class PaymentPage extends StatelessWidget { text2: '${order.data!.order!.sId}'), RowTextWidget( - text1: 'Deliver status', + text1: 'Total', text2: - ' ${order.data!.payment!.transactions!.fold(0, (previousValue, element) => (previousValue as int) + (element.amount?.total as int? ?? 0))}'), + ' ${order.data!.payment!.transactions!.fold(0, (previousValue, element) => (previousValue as int) + (int.tryParse(element.amount!.total!) ?? 0))}'), RowTextWidget( text1: 'Merchant', text2: diff --git a/lib/screens/product/product_page.dart b/lib/screens/product/product_page.dart index 963e0d18..b29f8460 100755 --- a/lib/screens/product/product_page.dart +++ b/lib/screens/product/product_page.dart @@ -23,7 +23,7 @@ class ProductPage extends StatelessWidget { double bottomPadding = MediaQuery.of(context).padding.bottom; Widget viewProductButton = InkWell( - onTap: () => controller.addProduct(product), + onTap: () => controller.addProduct(product, quantity: 1), child: Container( height: 80, width: width / 1.5, diff --git a/lib/screens/rating/rating_dialog.dart b/lib/screens/rating/rating_dialog.dart index 2adf60d9..87a4284b 100755 --- a/lib/screens/rating/rating_dialog.dart +++ b/lib/screens/rating/rating_dialog.dart @@ -1,6 +1,7 @@ import 'package:ecommerce_int2/data/models/product.model.dart'; import 'package:ecommerce_int2/data/repository/review.repository.dart'; import 'package:ecommerce_int2/screens/rating/review.controller.dart'; +import 'package:ecommerce_int2/utils/app_properties.dart'; import 'package:flutter/material.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; import 'package:get/get.dart'; @@ -11,7 +12,6 @@ class RatingDialog extends StatelessWidget { const RatingDialog({Key? key, required this.product}) : super(key: key); @override Widget build(BuildContext context) { - return GetBuilder( init: ReviewController(Get.find(), product.sId!), tag: product.sId!, @@ -80,6 +80,33 @@ class RatingDialog extends StatelessWidget { style: TextStyle(fontSize: 12, color: Colors.grey[600]), maxLength: 200, )), + InkWell( + onTap: () async { + controller.addReview(); + }, + child: Container( + height: 60, + width: Get.width / 1.5, + decoration: BoxDecoration( + gradient: mainButton, + boxShadow: [ + BoxShadow( + color: Color.fromRGBO(0, 0, 0, 0.16), + offset: Offset(0, 5), + blurRadius: 10.0, + ) + ], + borderRadius: BorderRadius.circular(9.0)), + child: Center( + child: Text("Add review", + style: const TextStyle( + color: const Color(0xfffefefe), + fontWeight: FontWeight.w600, + fontStyle: FontStyle.normal, + fontSize: 20.0)), + ), + ), + ) ])), ), ); diff --git a/lib/screens/search_products/search_controller.dart b/lib/screens/search_products/search_controller.dart index 3e71ab01..d2d83dd7 100644 --- a/lib/screens/search_products/search_controller.dart +++ b/lib/screens/search_products/search_controller.dart @@ -35,6 +35,7 @@ class SearchProductController extends GetxController { @override void onInit() { + getArgument(); getProduct(); super.onInit(); } diff --git a/lib/screens/search_products/search_page.dart b/lib/screens/search_products/search_page.dart index f99ddc9e..fca7d323 100644 --- a/lib/screens/search_products/search_page.dart +++ b/lib/screens/search_products/search_page.dart @@ -1,7 +1,5 @@ // ignore_for_file: deprecated_member_use -import 'package:ecommerce_int2/data/models/product.model.dart'; -import 'package:ecommerce_int2/data/repository/product.repository.dart'; import 'package:ecommerce_int2/screens/product/components/product_card.dart'; import 'package:ecommerce_int2/screens/product/product_page.dart'; import 'package:ecommerce_int2/screens/search_products/search_controller.dart'; @@ -12,62 +10,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; -import 'package:rubber/rubber.dart'; -class SearchPage extends StatefulWidget { - @override - _SearchPageState createState() => _SearchPageState(); -} - -class _SearchPageState extends State - with SingleTickerProviderStateMixin { - String selectedPeriod = ""; - String selectedCategory = ""; - String selectedPrice = ""; - - List timeFilter = [ - 'Brand', - 'New', - 'Latest', - 'Trending', - 'Discount', - ]; - - List categoryFilter = [ - 'Skull Candy', - 'Boat', - 'JBL', - 'Micromax', - 'Seg', - ]; - - List priceFilter = [ - '\$50-200', - '\$200-400', - '\$400-800', - '\$800-1000', - ]; - - List searchResults = []; - - - late RubberAnimationController _controller; - - @override - void initState() { - _controller = RubberAnimationController( - vsync: this, - halfBoundValue: AnimationControllerValue(percentage: 0.4), - upperBoundValue: AnimationControllerValue(percentage: 0.4), - lowerBoundValue: AnimationControllerValue(pixel: 50), - duration: Duration(milliseconds: 200)); - super.initState(); - } +// ignore: must_be_immutable +class SearchPage extends GetView { + String? subCategory; - @override - void dispose() { - super.dispose(); - } + SearchPage({this.subCategory}); Widget _getLowerLayer(SearchProductController controller) { return Container( @@ -112,7 +60,6 @@ class _SearchPageState extends State suffix: FlatButton( onPressed: () { controller.searchController.clear(); - searchResults.clear(); }, child: Text( 'Clear', @@ -123,166 +70,27 @@ class _SearchPageState extends State ), ), Flexible( - child: Container( - color: Colors.orange[50], - child: SmartRefresher( - enablePullDown: true, - enablePullUp: true, - controller: controller.refreshController, - onLoading: controller.onLoadMore, - onRefresh: controller.onRefresh, - header: WaterDropHeader(), - child: ListView.builder( - itemCount: controller.list.length, - itemBuilder: (_, index) => Padding( - padding: EdgeInsets.symmetric(horizontal: 16.0), - child: ProductCard( - controller.list[index], - () => Navigator.of(context).push(MaterialPageRoute( - builder: (_) => ProductPage( - product: controller.list[index], - ))), - )), + child: Container( + color: Colors.orange[50], + child: SmartRefresher( + enablePullDown: true, + enablePullUp: true, + controller: controller.refreshController, + onLoading: controller.onLoadMore, + onRefresh: controller.onRefresh, + header: WaterDropHeader(), + child: ListView.builder( + itemCount: controller.list.length, + itemBuilder: (_, index) => Padding( + padding: EdgeInsets.symmetric(horizontal: 16.0), + child: ProductCard( + controller.list[index], + () => Get.to(() => ProductPage( + product: controller.list[index], + ))), + )), ), ), - )) - ], - ), - ); - } - - Widget _getUpperLayer(SearchProductController controller) { - return Container( - decoration: BoxDecoration( - boxShadow: [ - BoxShadow( - color: Color.fromRGBO(0, 0, 0, 0.05), - offset: Offset(0, -3), - blurRadius: 10) - ], - borderRadius: BorderRadius.only( - topRight: Radius.circular(24), topLeft: Radius.circular(24)), - color: Colors.white), - child: ListView( - physics: NeverScrollableScrollPhysics(), -// controller: _scrollController, - children: [ - Align( - alignment: Alignment.center, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - 'Filters', - style: TextStyle(color: Colors.grey[300]), - ), - ), - ), - Align( - alignment: Alignment.centerLeft, - child: Padding( - padding: - const EdgeInsets.only(left: 32.0, top: 16.0, bottom: 16.0), - child: Text( - 'Sort By', - style: TextStyle(fontWeight: FontWeight.bold), - ), - ), - ), - Container( - height: 50, - child: ListView.builder( - itemBuilder: (_, index) => Center( - child: Padding( - padding: EdgeInsets.symmetric( - horizontal: 8.0, - ), - child: InkWell( - onTap: () { - setState(() { - selectedPeriod = timeFilter[index]; - }); - }, - child: Container( - padding: EdgeInsets.symmetric( - vertical: 4.0, horizontal: 20.0), - decoration: selectedPeriod == timeFilter[index] - ? BoxDecoration( - color: Color(0xffFDB846), - borderRadius: - BorderRadius.all(Radius.circular(45))) - : BoxDecoration(), - child: Text( - timeFilter[index], - style: TextStyle(fontSize: 16.0), - ))), - )), - itemCount: timeFilter.length, - scrollDirection: Axis.horizontal, - ), - ), - Container( - height: 50, - child: ListView.builder( - itemBuilder: (_, index) => Center( - child: Padding( - padding: EdgeInsets.symmetric( - horizontal: 8.0, - ), - child: InkWell( - onTap: () { - setState(() { - selectedCategory = categoryFilter[index]; - }); - }, - child: Container( - padding: EdgeInsets.symmetric( - vertical: 4.0, horizontal: 20.0), - decoration: selectedCategory == categoryFilter[index] - ? BoxDecoration( - color: Color(0xffFDB846), - borderRadius: - BorderRadius.all(Radius.circular(45))) - : BoxDecoration(), - child: Text( - categoryFilter[index], - style: TextStyle(fontSize: 16.0), - ))), - )), - itemCount: categoryFilter.length, - scrollDirection: Axis.horizontal, - ), - ), - Container( - height: 50, - child: ListView.builder( - itemBuilder: (_, index) => Center( - child: Padding( - padding: EdgeInsets.symmetric( - horizontal: 8.0, - ), - child: InkWell( - onTap: () { - setState(() { - selectedPrice = priceFilter[index]; - }); - }, - child: Container( - padding: EdgeInsets.symmetric( - vertical: 4.0, horizontal: 20.0), - decoration: selectedPrice == priceFilter[index] - ? BoxDecoration( - color: Color(0xffFDB846), - borderRadius: - BorderRadius.all(Radius.circular(45))) - : BoxDecoration(), - child: Text( - priceFilter[index], - style: TextStyle(fontSize: 16.0), - ))), - )), - itemCount: priceFilter.length, - scrollDirection: Axis.horizontal, - ), ) ], ), @@ -298,14 +106,13 @@ class _SearchPageState extends State bottom: false, child: Scaffold( body: GetBuilder( - init: SearchProductController(Get.find()), - builder: (controller) => RubberBottomSheet( - lowerLayer: - _getLowerLayer(controller), // The underlying page (Widget) - upperLayer: - _getUpperLayer(controller), // The bottomsheet content (Widget) - animationController: _controller, // The one we created earlier - ), + init: controller, + initState: (state) { + controller.filter.subcategory = subCategory; + controller.filter.name = ''; + controller.onRefresh(); + }, + builder: (controller) => _getLowerLayer(controller), )), ), ); diff --git a/lib/screens/shop/cart.controller.dart b/lib/screens/shop/cart.controller.dart index 41b5a860..cd231e50 100644 --- a/lib/screens/shop/cart.controller.dart +++ b/lib/screens/shop/cart.controller.dart @@ -69,14 +69,8 @@ class CartController extends GetxController { merchant: product.merchant, quantity: quantity) ]); - final String cartId = await repository.addProduct(param); + await repository.addProduct(param); MessageDialog.showToast("Added product to cart"); - int index = carts!.indexWhere((element) => element.sId == cartId); - if (index != -1) { - carts![index].products!.add(product); - } else { - carts!.add(CartModel(sId: cartId, products: [product])); - } update(); } on Exception catch (e) { print(e); diff --git a/lib/screens/shop/check_out_page.dart b/lib/screens/shop/check_out_page.dart index e48af09e..85a452d2 100755 --- a/lib/screens/shop/check_out_page.dart +++ b/lib/screens/shop/check_out_page.dart @@ -122,16 +122,6 @@ class CheckOutPage extends StatelessWidget { ], ), ), - Padding( - padding: const EdgeInsets.all(16.0), - child: Text( - 'Payment', - style: TextStyle( - fontSize: 20, - color: darkGrey, - fontWeight: FontWeight.bold), - ), - ), SizedBox(height: 24), Center( child: Padding( diff --git a/lib/screens/tracking/order_detail.view.dart b/lib/screens/tracking/order_detail.view.dart index 5a854326..728bc3ca 100644 --- a/lib/screens/tracking/order_detail.view.dart +++ b/lib/screens/tracking/order_detail.view.dart @@ -81,18 +81,13 @@ class OrderDetail extends StatelessWidget { width: Get.width)) .toList(), const SizedBox(height: 16), - if (!controller.detail!.isPayWithCash) - Button( - title: 'Pay with Paypal', - onTap: () => - controller.makePayment(orderId)), if (controller.detail!.canCancel) Button( - title: 'Cancle Order', + title: 'Cancel Order', onTap: () => controller.remove(orderId), ), - if (!controller.detail!.canCancel) - Button( + if (controller.detail!.canConfirmReceive) + Button( title: 'Confirm Received', onTap: () => controller.confirmOrder(orderId), diff --git a/lib/utils/webview.dart b/lib/utils/webview.dart index d32473de..ceacfebf 100644 --- a/lib/utils/webview.dart +++ b/lib/utils/webview.dart @@ -1,30 +1,37 @@ import 'dart:io'; - import 'package:flutter/material.dart'; +import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; - class WebViewExample extends StatefulWidget { - final String url; +class WebViewExample extends StatefulWidget { + final String url; - const WebViewExample({Key? key,required this.url}) : super(key: key); - @override - WebViewExampleState createState() => WebViewExampleState(); - } + const WebViewExample({Key? key, required this.url}) : super(key: key); + @override + WebViewExampleState createState() => WebViewExampleState(); +} - class WebViewExampleState extends State { - @override - void initState() { - super.initState(); - // Enable virtual display. - if (Platform.isAndroid) WebView.platform = AndroidWebView(); - } +class WebViewExampleState extends State { + @override + void initState() { + super.initState(); + // Enable virtual display. + if (Platform.isAndroid) WebView.platform = AndroidWebView(); + } - @override - Widget build(BuildContext context) { - return SafeArea( - child: WebView( - initialUrl: widget.url, - ), - ); - } - } \ No newline at end of file + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text("Paypal"), + leading: BackButton(), + ), + body: SafeArea( + child: WebView( + javascriptMode: JavascriptMode.unrestricted, + initialUrl: widget.url, + ), + ), + ); + } +} From b2c87a19dba925df584094042dcda7b0006e4915 Mon Sep 17 00:00:00 2001 From: manmaihuu <103487985+pdax-manmai@users.noreply.github.com> Date: Thu, 23 Jun 2022 16:01:04 +0700 Subject: [PATCH 47/49] Fix bugs --- .flutter-plugins-dependencies | 2 +- lib/data/models/product.model.dart | 1 - lib/data/models/review.dart | 10 +++++ lib/data/repository/review.repository.dart | 1 - lib/main.dart | 30 +++++++++----- lib/screens/merchant/merchant.controller.dart | 21 ++++++++-- .../product/components/product_card.dart | 40 +++++++++++++------ lib/screens/product/product_page.dart | 7 ++-- lib/screens/rating/rating_page.dart | 10 ++++- .../search_products/search_controller.dart | 23 ++++++++++- lib/screens/search_products/search_page.dart | 5 ++- lib/utils/message_dialog.dart | 5 +-- 12 files changed, 118 insertions(+), 37 deletions(-) diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 8d0c2ed4..2e95ca9b 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]},{"name":"webview_flutter_wkwebview","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_wkwebview-2.7.5\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]},{"name":"webview_flutter_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_android-2.8.10\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2022-06-23 14:08:41.383944","version":"2.10.4"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_ios","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.9\\\\","dependencies":[]},{"name":"webview_flutter_wkwebview","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_wkwebview-2.7.5\\\\","dependencies":[]}],"android":[{"name":"path_provider_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.14\\\\","dependencies":[]},{"name":"webview_flutter_android","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\webview_flutter_android-2.8.10\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.6\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"D:\\\\Flutter\\\\flutter_windows_1.22.5-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.6\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2022-06-23 15:27:58.328689","version":"2.10.4"} \ No newline at end of file diff --git a/lib/data/models/product.model.dart b/lib/data/models/product.model.dart index 50ec2fcf..e62f33d2 100644 --- a/lib/data/models/product.model.dart +++ b/lib/data/models/product.model.dart @@ -93,7 +93,6 @@ class Product { iV = json['__v']; totalRatings = json['totalRatings']; totalReviews = json['totalReviews']; - averageRating = json['averageRating']; } Map toJson() { diff --git a/lib/data/models/review.dart b/lib/data/models/review.dart index cf4d8b94..689181ec 100644 --- a/lib/data/models/review.dart +++ b/lib/data/models/review.dart @@ -1,3 +1,5 @@ +import 'package:intl/intl.dart'; + class ReviewResponse { bool? success; List? data; @@ -33,6 +35,14 @@ class Review { String? created; int? iV; + String get createdDate { + if (created == null) return ''; + final date = DateTime.tryParse(created!); + if (date == null) return ''; + final res = DateFormat("yyyy-MM-dd HH:mm:ss aa").format(date); + return res; + } + Review( {this.sId, this.product, diff --git a/lib/data/repository/review.repository.dart b/lib/data/repository/review.repository.dart index febc0a54..1ec726d4 100644 --- a/lib/data/repository/review.repository.dart +++ b/lib/data/repository/review.repository.dart @@ -22,5 +22,4 @@ class ReviewRepository { final result = ReviewResponse.fromJson(response.body); return result.data ?? []; } - } diff --git a/lib/main.dart b/lib/main.dart index 76199fc9..1f72b393 100755 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,6 +3,7 @@ import 'package:ecommerce_int2/screens/splash_page.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; void main() { GetStorage.init(); @@ -14,16 +15,27 @@ class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { - return GetMaterialApp( - title: 'E-commerce', - debugShowCheckedModeBanner: false, - theme: ThemeData( - brightness: Brightness.light, - canvasColor: Colors.transparent, - primarySwatch: Colors.blue, - fontFamily: "Montserrat", + return RefreshConfiguration( + headerBuilder: () => WaterDropHeader(), // Configure the default header indicator. If you have the same header indicator for each page, you need to set this + footerBuilder: () => ClassicFooter(), // Configure default bottom indicator + headerTriggerDistance: 80.0, // header trigger refresh trigger distance + maxOverScrollExtent :100, //The maximum dragging range of the head. Set this property if a rush out of the view area occurs + maxUnderScrollExtent:100, // Maximum dragging range at the bottom + enableScrollWhenRefreshCompleted: true, //This property is incompatible with PageView and TabBarView. If you need TabBarView to slide left and right, you need to set it to true. + enableLoadingWhenFailed : true, //In the case of load failure, users can still trigger more loads by gesture pull-up. + hideFooterWhenNotFull: false, // Disable pull-up to load more functionality when Viewport is less than one screen + enableBallisticLoad: true, + child: GetMaterialApp( + title: 'E-commerce', + debugShowCheckedModeBanner: false, + theme: ThemeData( + brightness: Brightness.light, + canvasColor: Colors.transparent, + primarySwatch: Colors.blue, + fontFamily: "Montserrat", + ), + home: SplashScreen(), ), - home: SplashScreen(), ); } } diff --git a/lib/screens/merchant/merchant.controller.dart b/lib/screens/merchant/merchant.controller.dart index c4759e08..d1d62557 100644 --- a/lib/screens/merchant/merchant.controller.dart +++ b/lib/screens/merchant/merchant.controller.dart @@ -31,6 +31,12 @@ class MerchantController extends GetxController { super.onInit(); } + @override + void onReady() { + getInfo(); + super.onReady(); + } + void getArg() { final arg = Get.arguments; if (arg != null && arg is String) { @@ -46,8 +52,17 @@ class MerchantController extends GetxController { return; } - final res = await merchantRepository.getMerchantInfo(merchantId!); - data = res; - update(); + try { + MessageDialog.showLoading(); + final res = await merchantRepository.getMerchantInfo(merchantId!); + data = res; + update(); + MessageDialog.hideLoading(); + } on Exception catch (e) { + MessageDialog.hideLoading(); + MessageDialog.showConfirmDialog( + content: "Error loading", + ); + } } } diff --git a/lib/screens/product/components/product_card.dart b/lib/screens/product/components/product_card.dart index d93f7703..3fb54709 100755 --- a/lib/screens/product/components/product_card.dart +++ b/lib/screens/product/components/product_card.dart @@ -1,4 +1,5 @@ import 'package:ecommerce_int2/data/models/product.model.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class ProductCard extends StatelessWidget { @@ -20,6 +21,7 @@ class ProductCard extends StatelessWidget { borderRadius: BorderRadius.all(Radius.circular(10)), color: Color(0xfffbd085).withOpacity(0.46)), child: Row( + crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( padding: EdgeInsets.all(16.0), @@ -29,9 +31,9 @@ class ProductCard extends StatelessWidget { height: 200, ), ), - Flexible( + Expanded( child: Container( - margin: const EdgeInsets.only(left: 16.0), + margin: const EdgeInsets.only(left: 16.0, top: 16), padding: const EdgeInsets.all(8.0), decoration: BoxDecoration( color: Color(0xffe0450a).withOpacity(0.51), @@ -39,35 +41,49 @@ class ProductCard extends StatelessWidget { topLeft: Radius.circular(10), bottomLeft: Radius.circular(10))), child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( product.name ?? "Product", textAlign: TextAlign.right, style: TextStyle( - fontSize: 12.0, + fontSize: 22.0, color: Colors.white, ), ), + const SizedBox(height: 16), Text( - product.merchant ?? "Merchant", + '\$ ' + + (product.purchasePrice ?? + product.price ?? + 0) + .toString(), textAlign: TextAlign.right, style: TextStyle( - fontSize: 12.0, + fontSize: 18.0, color: Colors.white, ), ), + Divider(), + const SizedBox(height: 8), Text( - 'VND' + - (product.purchasePrice ?? - product.price ?? - 0) - .toString(), + '${product.totalRatings ?? 0} ratings', textAlign: TextAlign.right, style: TextStyle( - fontSize: 12.0, + fontSize: 13.0, color: Colors.white, ), - ) + ), + const SizedBox(height: 8), + Text( + '${product.totalReviews ?? 0} reviews', + textAlign: TextAlign.right, + style: TextStyle( + fontSize: 13.0, + color: Colors.white, + ), + ), ], )), ) diff --git a/lib/screens/product/product_page.dart b/lib/screens/product/product_page.dart index b29f8460..3249d617 100755 --- a/lib/screens/product/product_page.dart +++ b/lib/screens/product/product_page.dart @@ -25,7 +25,7 @@ class ProductPage extends StatelessWidget { Widget viewProductButton = InkWell( onTap: () => controller.addProduct(product, quantity: 1), child: Container( - height: 80, + height: 60, width: width / 1.5, decoration: BoxDecoration( gradient: mainButton, @@ -81,8 +81,8 @@ class ProductPage extends StatelessWidget { fontSize: 20.0), ), ), - SizedBox( - height: 24.0, + const SizedBox( + height: 24.0 ), Padding( padding: EdgeInsets.only(left: 20.0, right: 40.0, bottom: 20), @@ -123,6 +123,7 @@ class ProductPage extends StatelessWidget { ), ), ), + const SizedBox(height: 8), ProductListView( products: Get.find() .list diff --git a/lib/screens/rating/rating_page.dart b/lib/screens/rating/rating_page.dart index b28902f2..de29ce5e 100755 --- a/lib/screens/rating/rating_page.dart +++ b/lib/screens/rating/rating_page.dart @@ -21,7 +21,15 @@ class Ratings extends StatelessWidget { : Padding( padding: const EdgeInsets.all(8.0), child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + "Reviews:", + style: TextStyle(fontSize: 18), + ), + ), ...controller.reviewList .map((val) => Container( margin: const EdgeInsets.symmetric(vertical: 4.0), @@ -57,7 +65,7 @@ class Ratings extends StatelessWidget { fontWeight: FontWeight.bold), ), Text( - '10 am, Via iOS', + val.createdDate, style: TextStyle( color: Colors.grey, fontSize: 10.0), diff --git a/lib/screens/search_products/search_controller.dart b/lib/screens/search_products/search_controller.dart index d2d83dd7..571cb3ef 100644 --- a/lib/screens/search_products/search_controller.dart +++ b/lib/screens/search_products/search_controller.dart @@ -33,6 +33,8 @@ class SearchProductController extends GetxController { List list = []; + ScrollController scrollController = ScrollController(); + @override void onInit() { getArgument(); @@ -40,6 +42,25 @@ class SearchProductController extends GetxController { super.onInit(); } + void onClear() { + searchController.clear(); + onRefresh(); + update(); + } + + @override + void onReady() { + scrollController.addListener(() { + if (scrollController.position.pixels < + scrollController.position.maxScrollExtent - 100) { + // debounce.run(() { + // onLoadMore(); + // }); + } + }); + super.onReady(); + } + void getArgument() { final dynamic subCategory = Get.arguments; if (subCategory != null && subCategory is String) { @@ -77,7 +98,7 @@ class SearchProductController extends GetxController { void onChanged(String value) { debounce.run(() { filter.name = value; - getProduct(); + onRefresh(); update(); }); } diff --git a/lib/screens/search_products/search_page.dart b/lib/screens/search_products/search_page.dart index fca7d323..5a9575f7 100644 --- a/lib/screens/search_products/search_page.dart +++ b/lib/screens/search_products/search_page.dart @@ -59,7 +59,7 @@ class SearchPage extends GetView { ), suffix: FlatButton( onPressed: () { - controller.searchController.clear(); + controller.onClear(); }, child: Text( 'Clear', @@ -69,7 +69,7 @@ class SearchPage extends GetView { ), ), ), - Flexible( + Expanded( child: Container( color: Colors.orange[50], child: SmartRefresher( @@ -80,6 +80,7 @@ class SearchPage extends GetView { onRefresh: controller.onRefresh, header: WaterDropHeader(), child: ListView.builder( + controller: controller.scrollController, itemCount: controller.list.length, itemBuilder: (_, index) => Padding( padding: EdgeInsets.symmetric(horizontal: 16.0), diff --git a/lib/utils/message_dialog.dart b/lib/utils/message_dialog.dart index c760b331..14ace041 100644 --- a/lib/utils/message_dialog.dart +++ b/lib/utils/message_dialog.dart @@ -11,6 +11,7 @@ class MessageDialog { static void showToast(String text) { Get.showSnackbar(GetSnackBar( backgroundColor: Colors.white, + duration: Duration(seconds: 1), messageText: Text(text), )); } @@ -37,8 +38,6 @@ class MessageDialog { child: Row( mainAxisSize: MainAxisSize.min, children: [ - //todo: Change the loading indicator - const CircularProgressIndicator(), const SizedBox(width: 16), Text( content, @@ -77,7 +76,7 @@ class MessageDialog { const CircularProgressIndicator(), const SizedBox(width: 16), Text( - 'Processing...', + 'Loading...', ), ], ), From dad7f34bed63a6dd179329d7a7e94ac4a4e7824b Mon Sep 17 00:00:00 2001 From: manmaihuu <103487985+pdax-manmai@users.noreply.github.com> Date: Thu, 23 Jun 2022 16:42:39 +0700 Subject: [PATCH 48/49] Update tab orders --- lib/screens/tracking/order.controller.dart | 16 +- lib/screens/tracking/tracking_page.dart | 163 +++++++++++++-------- 2 files changed, 113 insertions(+), 66 deletions(-) diff --git a/lib/screens/tracking/order.controller.dart b/lib/screens/tracking/order.controller.dart index c948ad1c..b3c9f171 100644 --- a/lib/screens/tracking/order.controller.dart +++ b/lib/screens/tracking/order.controller.dart @@ -1,4 +1,3 @@ -import 'package:card_swiper/card_swiper.dart'; import 'package:ecommerce_int2/data/models/order.model.dart'; import 'package:ecommerce_int2/data/repository/order.repository.dart'; import 'package:ecommerce_int2/screens/main/main_page.dart'; @@ -9,12 +8,21 @@ import 'package:get/get.dart'; class OrderController extends GetxController { final OrderRepository repository; - final SwiperController swiperController = SwiperController(); - OrderController(this.repository); List orders = []; + List get notProcessList => + orders.where((element) => element.status == 'NOT_PROCESSED').toList(); + List get processingList => + orders.where((element) => element.status == 'PROCESSING').toList(); + List get cancelledList => + orders.where((element) => element.status == 'CANCELLED').toList(); + List get deliveringList => + orders.where((element) => element.status == 'DELIVERING').toList(); + List get receivedList => + orders.where((element) => element.status == 'RECEIVED').toList(); + @override void onReady() { getAllOrders(); @@ -22,7 +30,7 @@ class OrderController extends GetxController { } void onBack() { - if(Get.arguments != null && Get.arguments == true) { + if (Get.arguments != null && Get.arguments == true) { Get.offAll(() => MainPage()); } else { Get.back(); diff --git a/lib/screens/tracking/tracking_page.dart b/lib/screens/tracking/tracking_page.dart index 06fb7813..de2537d2 100644 --- a/lib/screens/tracking/tracking_page.dart +++ b/lib/screens/tracking/tracking_page.dart @@ -1,3 +1,4 @@ +import 'package:ecommerce_int2/data/models/order.model.dart'; import 'package:ecommerce_int2/data/repository/order.repository.dart'; import 'package:ecommerce_int2/screens/tracking/order.controller.dart'; import 'package:ecommerce_int2/screens/tracking/row_text.widget.dart'; @@ -9,76 +10,114 @@ class TrackingPage extends StatelessWidget { @override Widget build(BuildContext context) { return GetBuilder( - init: OrderController(Get.find()), - builder: (controller) => Container( - decoration: BoxDecoration( - color: Colors.grey[100], - image: DecorationImage( - image: AssetImage('assets/Group 444.png'), - fit: BoxFit.contain)), - child: Container( - color: Colors.white54, - child: Scaffold( - appBar: AppBar( - backgroundColor: Colors.transparent, - elevation: 0.0, - iconTheme: IconThemeData(color: Colors.grey), - title: Text( - 'Your orders', - style: TextStyle( - color: darkGrey, - fontSize: 22, - fontWeight: FontWeight.bold, + init: OrderController(Get.find()), + builder: (controller) => Container( + decoration: BoxDecoration( + color: Colors.grey[100], + image: DecorationImage( + image: AssetImage('assets/Group 444.png'), + fit: BoxFit.contain)), + child: Container( + color: Colors.white54, + child: MaterialApp( + home: DefaultTabController( + length: 5, + child: Scaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + elevation: 0.0, + iconTheme: IconThemeData(color: Colors.grey), + title: Text( + 'Your orders', + style: TextStyle( + color: darkGrey, + fontSize: 22, + fontWeight: FontWeight.bold, + ), + ), + leading: + BackButton(onPressed: () => controller.onBack()), + bottom: TabBar( + labelColor: Colors.black, + isScrollable: true, + tabs: [ + Tab(child: Text('Not processing')), + Tab(child: Text('Processing')), + Tab(child: Text('Delivering')), + Tab(child: Text('Cancel')), + Tab(child: Text('Received')), + ], + ), + ), + body: TabBarView( + children: [ + Body(orders: controller.notProcessList), + Body(orders: controller.processingList), + Body(orders: controller.deliveringList), + Body(orders: controller.cancelledList), + Body(orders: controller.receivedList), + ], + ), + ), ), ), - leading: BackButton(onPressed: () => controller.onBack()), ), - body: SafeArea( - child: LayoutBuilder( - builder: (_, constraints) => SingleChildScrollView( - child: Column( - children: [ - ...controller.orders.reversed - .map((order) => GestureDetector( - onTap: (() => - controller.getOrderDetail(order)), - child: Container( - width: Get.width, - child: Card( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - children: [ - RowTextWidget( - text1: 'Date', - text2: '${order.createdDate}'), - RowTextWidget( - text1: 'Deliver status', - text2: - ' ${order.status ?? ''}'), - RowTextWidget( - text1: 'Payment status', - text2: - '${order.paymentStatus ?? ''}'), - RowTextWidget( - text1: 'Merchant', - text2: - '${order.merchant ?? ''}'), + )); + } +} - ], - crossAxisAlignment: - CrossAxisAlignment.start, - ), +class Body extends StatelessWidget { + const Body({Key? key, required this.orders}) : super(key: key); + + final List orders; + @override + Widget build(BuildContext context) { + return GetBuilder( + builder: (controller) => SafeArea( + child: LayoutBuilder( + builder: (_, constraints) => SingleChildScrollView( + child: orders.isEmpty + ? Padding( + padding: const EdgeInsets.all(18.0), + child: Center(child: Text('Empty')), + ) + : Column( + children: [ + ...orders + .map((order) => GestureDetector( + onTap: (() => controller.getOrderDetail(order)), + child: Container( + width: Get.width, + child: Card( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + RowTextWidget( + text1: 'Date', + text2: '${order.createdDate}'), + RowTextWidget( + text1: 'Deliver status', + text2: ' ${order.status ?? ''}'), + RowTextWidget( + text1: 'Payment status', + text2: + '${order.paymentStatus ?? ''}'), + RowTextWidget( + text1: 'Merchant', + text2: '${order.merchant ?? ''}'), + ], + crossAxisAlignment: + CrossAxisAlignment.start, ), ), ), - )) - .toList() - ], - ), + ), + )) + .toList() + ], ), - ), - )), + ), ), ), ); From 90a9a446c2d38cd853547d858fab82995b6c50c9 Mon Sep 17 00:00:00 2001 From: manmaihuu <103487985+pdax-manmai@users.noreply.github.com> Date: Thu, 23 Jun 2022 16:45:07 +0700 Subject: [PATCH 49/49] Update category view --- lib/screens/category/category_list_page.dart | 2 -- lib/screens/category/sub_category_list_page.dart | 4 ---- 2 files changed, 6 deletions(-) diff --git a/lib/screens/category/category_list_page.dart b/lib/screens/category/category_list_page.dart index d0ee46b7..a15bacbf 100755 --- a/lib/screens/category/category_list_page.dart +++ b/lib/screens/category/category_list_page.dart @@ -14,7 +14,6 @@ class CategoryListPage extends StatelessWidget { return Material( color: Color(0xffF9F9F9), child: Container( - margin: const EdgeInsets.only(top: 16), padding: EdgeInsets.symmetric(horizontal: 16.0), child: GetBuilder( init: CategoryController(Get.find()), @@ -22,7 +21,6 @@ class CategoryListPage extends StatelessWidget { child: Column( mainAxisSize: MainAxisSize.min, children: [ - const SizedBox(height: 16,), Align( alignment: Alignment(-1, 0), child: Padding( diff --git a/lib/screens/category/sub_category_list_page.dart b/lib/screens/category/sub_category_list_page.dart index b00dd3ad..1e32a69e 100644 --- a/lib/screens/category/sub_category_list_page.dart +++ b/lib/screens/category/sub_category_list_page.dart @@ -20,7 +20,6 @@ class SubCategoryListPage extends StatelessWidget { return Material( color: Color(0xffF9F9F9), child: Container( - margin: const EdgeInsets.only(top: 16), padding: EdgeInsets.symmetric(horizontal: 16.0), child: GetBuilder( init: SubCategoryController(Get.find(), category), @@ -28,9 +27,6 @@ class SubCategoryListPage extends StatelessWidget { child: Column( mainAxisSize: MainAxisSize.min, children: [ - const SizedBox( - height: 16, - ), Row( children: [ BackButton(