From 576f687d2109bac86b15edb126112afa018639f6 Mon Sep 17 00:00:00 2001 From: efrilm Date: Sat, 2 Aug 2025 23:10:48 +0700 Subject: [PATCH] feat: sync auth to new api --- lib/core/constants/variables.dart | 2 +- lib/core/network/dio_client.dart | 22 ++++ .../datasources/auth_remote_datasource.dart | 75 +++++++----- .../models/response/auth_response_model.dart | 108 +++++++++--------- .../home/bloc/order/order_bloc.dart | 6 +- pubspec.lock | 32 ++++++ pubspec.yaml | 2 + 7 files changed, 162 insertions(+), 85 deletions(-) create mode 100644 lib/core/network/dio_client.dart diff --git a/lib/core/constants/variables.dart b/lib/core/constants/variables.dart index d0717c9..b9ffc2b 100644 --- a/lib/core/constants/variables.dart +++ b/lib/core/constants/variables.dart @@ -2,5 +2,5 @@ class Variables { static const String appName = 'POS Kasir Resto App'; static const String apiVersion = 'v1'; // static const String baseUrl = 'http://192.168.1.202:8000'; - static const String baseUrl = 'https://pos-app-tablet.enaklo.co.id'; + static const String baseUrl = 'https://enaklo-pos-be.altru.id'; } diff --git a/lib/core/network/dio_client.dart b/lib/core/network/dio_client.dart new file mode 100644 index 0000000..986e5dd --- /dev/null +++ b/lib/core/network/dio_client.dart @@ -0,0 +1,22 @@ +// lib/core/network/dio_client.dart +import 'package:awesome_dio_interceptor/awesome_dio_interceptor.dart'; +import 'package:dio/dio.dart'; + +class DioClient { + static final Dio _dio = Dio(BaseOptions( + connectTimeout: const Duration(seconds: 10), + receiveTimeout: const Duration(seconds: 10), + headers: { + 'Accept': 'application/json', + }, + )) + ..interceptors.add( + AwesomeDioInterceptor( + logRequestTimeout: true, + logRequestHeaders: true, + logResponseHeaders: true, + ), + ); + + static Dio get instance => _dio; +} diff --git a/lib/data/datasources/auth_remote_datasource.dart b/lib/data/datasources/auth_remote_datasource.dart index 5f34461..81c93a1 100644 --- a/lib/data/datasources/auth_remote_datasource.dart +++ b/lib/data/datasources/auth_remote_datasource.dart @@ -1,44 +1,67 @@ +import 'dart:developer'; + import 'package:dartz/dartz.dart'; +import 'package:dio/dio.dart'; import 'package:enaklo_pos/core/constants/variables.dart'; +import 'package:enaklo_pos/core/network/dio_client.dart'; import 'package:enaklo_pos/data/datasources/auth_local_datasource.dart'; import 'package:enaklo_pos/data/models/response/auth_response_model.dart'; -import 'package:http/http.dart' as http; class AuthRemoteDatasource { + final Dio dio = DioClient.instance; Future> login( String email, String password) async { - final url = Uri.parse('${Variables.baseUrl}/api/login'); - final response = await http.post( - url, - body: { - 'email': email, - 'password': password, - }, - ); + final url = '${Variables.baseUrl}/api/v1/auth/login'; + log(url); - if (response.statusCode == 200) { - return Right(AuthResponseModel.fromJson(response.body)); - } else { - return const Left('Failed to login'); + try { + final response = await dio.post( + url, + data: { + 'email': email, + 'password': password, + }, + ); + + if (response.statusCode == 200) { + return Right(AuthResponseModel.fromMap(response.data)); + } else { + return const Left('Failed to login'); + } + } on DioException catch (e) { + log("Dio error: ${e.message}"); + return Left(e.response?.data['message'] ?? 'Login gagal'); + } catch (e) { + log("Unexpected error: $e"); + return const Left('Unexpected error occurred'); } } //logout Future> logout() async { - final authData = await AuthLocalDataSource().getAuthData(); - final url = Uri.parse('${Variables.baseUrl}/api/logout'); - final response = await http.post( - url, - headers: { - 'Authorization': 'Bearer ${authData.token}', - 'Accept': 'application/json', - }, - ); + try { + final authData = await AuthLocalDataSource().getAuthData(); + final url = '${Variables.baseUrl}/api/v1/auth/logout'; - if (response.statusCode == 200) { - return const Right(true); - } else { - return const Left('Failed to logout'); + final response = await dio.post( + url, + options: Options( + headers: { + 'Authorization': 'Bearer ${authData.token}', + 'Accept': 'application/json', + }, + ), + ); + + if (response.statusCode == 200) { + return const Right(true); + } else { + return const Left('Failed to logout'); + } + } on DioException catch (e) { + return Left(e.response?.data['message'] ?? 'Logout gagal'); + } catch (e) { + return const Left('Unexpected error occurred'); } } } diff --git a/lib/data/models/response/auth_response_model.dart b/lib/data/models/response/auth_response_model.dart index 56eb5f6..ef7a840 100644 --- a/lib/data/models/response/auth_response_model.dart +++ b/lib/data/models/response/auth_response_model.dart @@ -1,85 +1,83 @@ import 'dart:convert'; class AuthResponseModel { - final String? status; - final String? token; - final User? user; + final String? token; + final User? user; - AuthResponseModel({ - this.status, - this.token, - this.user, - }); + AuthResponseModel({ + this.token, + this.user, + }); - factory AuthResponseModel.fromJson(String str) => AuthResponseModel.fromMap(json.decode(str)); + factory AuthResponseModel.fromJson(String str) => + AuthResponseModel.fromMap(json.decode(str)); - String toJson() => json.encode(toMap()); + String toJson() => json.encode(toMap()); - factory AuthResponseModel.fromMap(Map json) => AuthResponseModel( - status: json["status"], + factory AuthResponseModel.fromMap(Map json) => + AuthResponseModel( token: json["token"], user: json["user"] == null ? null : User.fromMap(json["user"]), - ); + ); - Map toMap() => { - "status": status, + Map toMap() => { "token": token, "user": user?.toMap(), - }; + }; } class User { - final int? id; - final String? name; - final String? email; - final DateTime? emailVerifiedAt; - final dynamic twoFactorSecret; - final dynamic twoFactorRecoveryCodes; - final dynamic twoFactorConfirmedAt; - final DateTime? createdAt; - final DateTime? updatedAt; - final String? role; + final String? id; + final String? organizationId; + final String? outletId; + final String? name; + final String? email; + final String? role; + final bool? isActive; + final DateTime? createdAt; + final DateTime? updatedAt; - User({ - this.id, - this.name, - this.email, - this.emailVerifiedAt, - this.twoFactorSecret, - this.twoFactorRecoveryCodes, - this.twoFactorConfirmedAt, - this.createdAt, - this.updatedAt, - this.role, - }); + User({ + this.id, + this.organizationId, + this.outletId, + this.name, + this.role, + this.isActive, + this.email, + this.createdAt, + this.updatedAt, + }); - factory User.fromJson(String str) => User.fromMap(json.decode(str)); + factory User.fromJson(String str) => User.fromMap(json.decode(str)); - String toJson() => json.encode(toMap()); + String toJson() => json.encode(toMap()); - factory User.fromMap(Map json) => User( + factory User.fromMap(Map json) => User( id: json["id"], + organizationId: json["organization_id"], + outletId: json["outlet_id"], name: json["name"], email: json["email"], - emailVerifiedAt: json["email_verified_at"] == null ? null : DateTime.parse(json["email_verified_at"]), - twoFactorSecret: json["two_factor_secret"], - twoFactorRecoveryCodes: json["two_factor_recovery_codes"], - twoFactorConfirmedAt: json["two_factor_confirmed_at"], - createdAt: json["created_at"] == null ? null : DateTime.parse(json["created_at"]), - updatedAt: json["updated_at"] == null ? null : DateTime.parse(json["updated_at"]), role: json["role"], - ); + isActive: json["is_active"], + createdAt: json["created_at"] == null + ? null + : DateTime.parse(json["created_at"]), + updatedAt: json["updated_at"] == null + ? null + : DateTime.parse(json["updated_at"]), + ); - Map toMap() => { + Map toMap() => { "id": id, + "organization_id": organizationId, + "outlet_id": outletId, "name": name, "email": email, - "email_verified_at": emailVerifiedAt?.toIso8601String(), - "two_factor_secret": twoFactorSecret, - "two_factor_recovery_codes": twoFactorRecoveryCodes, - "two_factor_confirmed_at": twoFactorConfirmedAt, + "role": role, + "is_active": isActive, "created_at": createdAt?.toIso8601String(), "updated_at": updatedAt?.toIso8601String(), - "role": role, - }; + }; } diff --git a/lib/presentation/home/bloc/order/order_bloc.dart b/lib/presentation/home/bloc/order/order_bloc.dart index 9a303bc..76f6b54 100644 --- a/lib/presentation/home/bloc/order/order_bloc.dart +++ b/lib/presentation/home/bloc/order/order_bloc.dart @@ -52,7 +52,7 @@ class OrderBloc extends Bloc { total: event.totalPriceFinal, paymentMethod: event.paymentMethod, totalItem: totalItem, - idKasir: userData.user?.id ?? 1, + idKasir: int.parse(userData.user!.id ?? "0"), namaKasir: userData.user?.name ?? 'Kasir A', transactionTime: DateTime.now().toIso8601String(), customerName: event.customerName, @@ -66,11 +66,11 @@ class OrderBloc extends Bloc { log("Start 2"); //check state online or offline - + log("🔄 About to call API to save order..."); log("📤 Order data being sent to API: ${dataInput.toServerMap()}"); log("🌐 OrderRemoteDatasource instance: $orderRemoteDatasource"); - + bool value = false; try { value = await orderRemoteDatasource.saveOrder(dataInput); diff --git a/pubspec.lock b/pubspec.lock index ebf70b6..74de381 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -46,6 +46,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.13.0" + awesome_dio_interceptor: + dependency: "direct main" + description: + name: awesome_dio_interceptor + sha256: "4aef4adfdd9d8fda159870277b898a97986c6624baaf42f8a986d3130860d007" + url: "https://pub.dev" + source: hosted + version: "1.3.0" barcode: dependency: transitive description: @@ -222,6 +230,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.0" + colorize: + dependency: transitive + description: + name: colorize + sha256: "584746cd6ba1cba0633b6720f494fe6f9601c4170f0666c1579d2aa2a61071ba" + url: "https://pub.dev" + source: hosted + version: "3.0.0" connectivity_plus: dependency: "direct main" description: @@ -326,6 +342,22 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.2" + dio: + dependency: "direct main" + description: + name: dio + sha256: "253a18bbd4851fecba42f7343a1df3a9a4c1d31a2c1b37e221086b4fa8c8dbc9" + url: "https://pub.dev" + source: hosted + version: "5.8.0+1" + dio_web_adapter: + dependency: transitive + description: + name: dio_web_adapter + sha256: "7586e476d70caecaf1686d21eee7247ea43ef5c345eab9e0cc3583ff13378d78" + url: "https://pub.dev" + source: hosted + version: "2.1.1" esc_pos_utils_plus: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index fb43fdb..3ee70f3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -59,6 +59,8 @@ dependencies: widgets_to_image: ^1.0.0 flutter_esc_pos_network: ^1.0.3 flutter_screenutil: ^5.9.3 + dio: ^5.8.0+1 + awesome_dio_interceptor: ^1.3.0 # imin_printer: ^0.6.10 dev_dependencies: