diff --git a/lib/logic/server_api.dart b/lib/logic/server_api.dart new file mode 100644 index 0000000..c0b24a2 --- /dev/null +++ b/lib/logic/server_api.dart @@ -0,0 +1,217 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:dio/adapter.dart'; +import 'package:dio/dio.dart'; + +import 'package:selfprivacy/models/courier.dart'; +import 'package:selfprivacy/models/order.dart'; +import 'package:selfprivacy/models/item.dart'; + +class ApiResponse { + ApiResponse({ + required this.statusCode, + required this.data, + this.errorMessage, + }); + final int statusCode; + final String? errorMessage; + final D data; + + bool get isSuccess => statusCode >= 200 && statusCode < 300; +} + +class ServerApi { + Future getClient() async { + final Dio dio = Dio(await options); + (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = + (final HttpClient client) { + client.badCertificateCallback = + (final X509Certificate cert, final String host, final int port) => + true; + return client; + }; + + dio.interceptors.add( + InterceptorsWrapper( + onError: (final DioError e, final ErrorInterceptorHandler handler) { + print(e.requestOptions.path); + print(e.requestOptions.data); + + print(e.message); + print(e.response); + + return handler.next(e); + }, + ), + ); + return dio; + } + + BaseOptions get options => + BaseOptions( + baseUrl: 'http://10.100.0.6:8888/api/v1', + connectTimeout: 10000, + receiveTimeout: 10000, + ); + + ValidateStatus? validateStatus; + + void close(final Dio client) { + client.close(); + validateStatus = null; + } + + Future>> getItems() async { + final Dio client = await getClient(); + final Response response = await client.get('/items'); + final List items = (response.data as List) + .map((final dynamic e) => Item.fromJson(e as Map)) + .toList(); + return ApiResponse>( + statusCode: response.statusCode ?? 0, + data: items, + ); + } + + // Create an item + Future> createItem(final Item item) async { + final Dio client = await getClient(); + final Response response = await client.post('/items', data: item.toJson(),); + final Item createdItem = Item.fromJson(response.data as Map); + return ApiResponse( + statusCode: response.statusCode ?? 0, + data: createdItem, + ); + } + + // Update an item + Future> updateItem(final Item item) async { + final Dio client = await getClient(); + final Response response = await client.put('/items/${item.id}', data: { + 'title': item.title, + 'description': item.description, + 'price': item.price, + },); + final Item updatedItem = Item.fromJson(response.data as Map); + return ApiResponse( + statusCode: response.statusCode ?? 0, + data: updatedItem, + ); + } + + // Delete an item + Future> deleteItem(final Item item) async { + final Dio client = await getClient(); + final Response response = await client.delete('/items/${item.id}'); + final Item deletedItem = Item.fromJson(response.data as Map); + return ApiResponse( + statusCode: response.statusCode ?? 0, + data: deletedItem, + ); + } + + // Get a single item + Future> getItem(final int id) async { + final Dio client = await getClient(); + final Response response = await client.get('/items/$id'); + final Item item = Item.fromJson(response.data as Map); + return ApiResponse( + statusCode: response.statusCode ?? 0, + data: item, + ); + } + + // Get all couriers + Future>> getCouriers() async { + final Dio client = await getClient(); + final Response response = await client.get('/couriers'); + final List couriers = (response.data as List) + .map((final dynamic e) => Courier.fromJson(e as Map)) + .toList(); + return ApiResponse>( + statusCode: response.statusCode ?? 0, + data: couriers, + ); + } + + // Add a courier + Future> addCourier(final Courier courier) async { + final Dio client = await getClient(); + final Response response = await client.post('/couriers', data: courier.toJson(),); + final Courier createdCourier = Courier.fromJson(response.data as Map); + return ApiResponse( + statusCode: response.statusCode ?? 0, + data: createdCourier, + ); + } + + // Update a courier + Future> updateCourier(final Courier courier) async { + final Dio client = await getClient(); + final Response response = await client.put('/couriers/${courier.id}', data: courier.toJson(),); + final Courier updatedCourier = Courier.fromJson(response.data as Map); + return ApiResponse( + statusCode: response.statusCode ?? 0, + data: updatedCourier, + ); + } + + // Get a single courier + Future> getCourier(final int id) async { + final Dio client = await getClient(); + final Response response = await client.get('/couriers/$id'); + final Courier courier = Courier.fromJson(response.data as Map); + return ApiResponse( + statusCode: response.statusCode ?? 0, + data: courier, + ); + } + + // Get all orders + Future>> getOrders() async { + final Dio client = await getClient(); + final Response response = await client.get('/orders'); + final List orders = (response.data as List) + .map((final dynamic e) => Order.fromJson(e as Map)) + .toList(); + return ApiResponse>( + statusCode: response.statusCode ?? 0, + data: orders, + ); + } + + // Get a single order + Future> getOrder(final int id) async { + final Dio client = await getClient(); + final Response response = await client.get('/orders/$id'); + final Order order = Order.fromJson(response.data as Map); + return ApiResponse( + statusCode: response.statusCode ?? 0, + data: order, + ); + } + + // Create an order + Future> createOrder(final Order order) async { + final Dio client = await getClient(); + final Response response = await client.post('/orders', data: order.toJsonAsNew()); + final Order createdOrder = Order.fromJson(response.data as Map); + return ApiResponse( + statusCode: response.statusCode ?? 0, + data: createdOrder, + ); + } + + // Update an order + Future> updateOrder(final Order order) async { + final Dio client = await getClient(); + final Response response = await client.put('/orders/${order.id}', data: order.toJson()); + final Order updatedOrder = Order.fromJson(response.data as Map); + return ApiResponse( + statusCode: response.statusCode ?? 0, + data: updatedOrder, + ); + } +} diff --git a/lib/models/courier.dart b/lib/models/courier.dart index 92ceead..ebd9e9c 100644 --- a/lib/models/courier.dart +++ b/lib/models/courier.dart @@ -1,4 +1,13 @@ -class Courier { +import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'courier.g.dart'; + +@JsonSerializable() +class Courier extends Equatable { + factory Courier.fromJson(final Map json) => + _$CourierFromJson(json); + Courier({ required this.name, required this.surname, @@ -10,4 +19,15 @@ class Courier { final String surname; final String phone; final int id; + + // tojson + Map toJson() => _$CourierToJson(this); + + @override + List get props => [ + name, + surname, + phone, + id, + ]; } diff --git a/lib/models/courier.g.dart b/lib/models/courier.g.dart new file mode 100644 index 0000000..70699ba --- /dev/null +++ b/lib/models/courier.g.dart @@ -0,0 +1,21 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'courier.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +Courier _$CourierFromJson(Map json) => Courier( + name: json['name'] as String, + surname: json['surname'] as String, + id: json['id'] as int, + phone: json['phone'] as String, + ); + +Map _$CourierToJson(Courier instance) => { + 'name': instance.name, + 'surname': instance.surname, + 'phone': instance.phone, + 'id': instance.id, + }; diff --git a/lib/models/item.dart b/lib/models/item.dart index 50e47a3..c0ea7ff 100644 --- a/lib/models/item.dart +++ b/lib/models/item.dart @@ -1,13 +1,35 @@ -class Item { +import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'item.g.dart'; + +@JsonSerializable() +class Item extends Equatable { + factory Item.fromJson(final Map json) => + _$ItemFromJson(json); Item({ required this.title, - required this.description, required this.id, - required this.price, + this.description, + this.price, + this.quantity, }); final String title; - final String description; - final int price; + final String? description; + final int? price; final int id; + final int? quantity; + + // tojson + Map toJson() => _$ItemToJson(this); + + @override + List get props => [ + title, + description, + price, + id, + quantity, + ]; } diff --git a/lib/models/item.g.dart b/lib/models/item.g.dart new file mode 100644 index 0000000..9c0ee7a --- /dev/null +++ b/lib/models/item.g.dart @@ -0,0 +1,23 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'item.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +Item _$ItemFromJson(Map json) => Item( + title: json['title'] as String, + id: json['id'] as int, + description: json['description'] as String?, + price: json['price'] as int?, + quantity: json['quantity'] as int?, + ); + +Map _$ItemToJson(Item instance) => { + 'title': instance.title, + 'description': instance.description, + 'price': instance.price, + 'id': instance.id, + 'quantity': instance.quantity, + }; diff --git a/lib/models/order.dart b/lib/models/order.dart index 5842c81..b443809 100644 --- a/lib/models/order.dart +++ b/lib/models/order.dart @@ -1,6 +1,13 @@ +import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; import 'package:selfprivacy/models/item.dart'; +part 'order.g.dart'; + +@JsonSerializable() class Order { + factory Order.fromJson(final Map json) => + _$OrderFromJson(json); Order({ required this.title, required this.description, @@ -17,9 +24,13 @@ class Order { final String title; final String description; + @JsonKey(name: 'customer_name') final String customerName; + @JsonKey(name: 'customer_phone') final String customerPhone; + @JsonKey(name: 'order_date') final String orderDate; + @JsonKey(name: 'delivery_date') final String deliveryDate; final String address; final String status; @@ -27,4 +38,27 @@ class Order { final int courierId; final List items; + + // tojson + Map toJson() => _$OrderToJson(this); + Map toJsonAsNew() { + final Map data = _$OrderToJson(this); + // To "order_in" goes everything except items + data['order_in'] = { + 'title': data['title'], + 'description': data['description'], + 'customer_name': data['customer_name'], + 'customer_phone': data['customer_phone'], + 'order_date': data['order_date'], + 'delivery_date': data['delivery_date'], + 'address': data['address'], + 'status': data['status'], + 'courier_id': data['courier_id'], + }; + // To "order_items" goes only items + data['order_items'] = data['items']; + // Remove items from data + data.remove('items'); + return data; + } } diff --git a/lib/models/order.g.dart b/lib/models/order.g.dart new file mode 100644 index 0000000..cf3db0e --- /dev/null +++ b/lib/models/order.g.dart @@ -0,0 +1,37 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'order.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +Order _$OrderFromJson(Map json) => Order( + title: json['title'] as String, + description: json['description'] as String, + id: json['id'] as int, + customerName: json['customer_name'] as String, + customerPhone: json['customer_phone'] as String, + orderDate: json['order_date'] as String, + deliveryDate: json['delivery_date'] as String, + address: json['address'] as String, + status: json['status'] as String, + courierId: json['courierId'] as int, + items: (json['items'] as List) + .map((e) => Item.fromJson(e as Map)) + .toList(), + ); + +Map _$OrderToJson(Order instance) => { + 'title': instance.title, + 'description': instance.description, + 'customer_name': instance.customerName, + 'customer_phone': instance.customerPhone, + 'order_date': instance.orderDate, + 'delivery_date': instance.deliveryDate, + 'address': instance.address, + 'status': instance.status, + 'id': instance.id, + 'courierId': instance.courierId, + 'items': instance.items, + };