Compare commits

..
19 Commits
Author SHA1 Message Date
Efril 5d73f82017 fix payment struck 2026-01-13 23:41:56 +07:00
aefril 1d52f22f5f Merge pull request 'dev' (#1) from dev into main
Reviewed-on: #1
2025-08-13 17:19:46 +00:00
efrilm f87309af3f feat: update 2025-08-14 00:16:42 +07:00
efrilm 96d0b91984 feat: succes payment 2025-08-14 00:12:49 +07:00
efrilm e20dc53fb8 feat: profit loss widget 2025-08-13 23:27:52 +07:00
efrilm c09822b470 feat: success save order 2025-08-13 23:08:12 +07:00
efrilm 6a9a26f71c fix: success save order 2025-08-13 23:00:11 +07:00
efrilm b0006ee6bc fix: order and add to order 2025-08-13 22:52:37 +07:00
efrilm b34428965e fix: bug 2025-08-13 22:11:24 +07:00
efrilm 670a0b6414 feat: update split bill 2025-08-08 23:04:35 +07:00
efrilm b7ab9c6939 feat: update logo 2025-08-08 19:44:00 +07:00
efrilm 6b5af82307 feat: table 2025-08-08 14:59:49 +07:00
efrilm 2848678cdc fix: amount 2025-08-08 14:39:56 +07:00
efrilm f05347c90d feat: transfer table 2025-08-08 14:22:12 +07:00
efrilm 94725964ea fix: change position table 2025-08-08 13:45:03 +07:00
efrilm 2eceb0bc0c feat: update 2025-08-08 10:53:46 +07:00
efrilm e19d788f47 feat: update order detail 2025-08-08 10:29:17 +07:00
efrilm 3a07d2e7cc feat: fix payment 2025-08-08 00:12:10 +07:00
efrilm 2c8b1333d8 feat: order response model 2025-08-07 23:59:01 +07:00
81 changed files with 2722 additions and 869 deletions
+1 -1
View File
@@ -45,7 +45,7 @@ android {
applicationId "com.appscale.pos" applicationId "com.appscale.pos"
// You can update the following values to match your application needs. // You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion 21 minSdkVersion flutter.minSdkVersion
targetSdkVersion 35 targetSdkVersion 35
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()
versionName flutterVersionName versionName flutterVersionName
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 983 B

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 320 B

After

Width:  |  Height:  |  Size: 666 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 804 B

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 492 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 804 B

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 15 KiB

+4 -4
View File
@@ -3,15 +3,15 @@
flutter_launcher_icons: flutter_launcher_icons:
android: "launcher_icon" android: "launcher_icon"
ios: true ios: true
image_path: "assets/logo/ic_launcher.png" image_path: "assets/logo/logo.png"
remove_alpha_ios: true remove_alpha_ios: true
min_sdk_android: 21 # android min sdk min:16, default 21 min_sdk_android: 21 # android min sdk min:16, default 21
adaptive_icon_background: "#ffffff" adaptive_icon_background: "#ffffff"
adaptive_icon_foreground: "assets/logo/ic_launcher.png" adaptive_icon_foreground: "assets/logo/logo.png"
web: web:
generate: true generate: true
image_path: "assets/logo/ic_launcher.png" image_path: "assets/logo/logo.png"
windows: windows:
generate: true generate: true
image_path: "assets/logo/ic_launcher.png" image_path: "assets/logo/logo.png"
icon_size: 48 icon_size: 48
+4 -17
View File
@@ -304,12 +304,8 @@ class $AssetsImagesGen {
class $AssetsLogoGen { class $AssetsLogoGen {
const $AssetsLogoGen(); const $AssetsLogoGen();
/// File path: assets/logo/ic_launcher.png /// File path: assets/logo/logo.png
AssetGenImage get icLauncher => AssetGenImage get logo => const AssetGenImage('assets/logo/logo.png');
const AssetGenImage('assets/logo/ic_launcher.png');
/// File path: assets/logo/logo.jpeg
AssetGenImage get logo => const AssetGenImage('assets/logo/logo.jpeg');
/// File path: assets/logo/logo2.png /// File path: assets/logo/logo2.png
AssetGenImage get logo2 => const AssetGenImage('assets/logo/logo2.png'); AssetGenImage get logo2 => const AssetGenImage('assets/logo/logo2.png');
@@ -334,17 +330,8 @@ class $AssetsLogoGen {
AssetGenImage get mylogo => const AssetGenImage('assets/logo/mylogo.png'); AssetGenImage get mylogo => const AssetGenImage('assets/logo/mylogo.png');
/// List of all assets /// List of all assets
List<AssetGenImage> get values => [ List<AssetGenImage> get values =>
icLauncher, [logo, logo2, logo3, logo4, logo5, logo6, logoAppIcon, mylogo];
logo,
logo2,
logo3,
logo4,
logo5,
logo6,
logoAppIcon,
mylogo
];
} }
class Assets { class Assets {
+3 -1
View File
@@ -865,7 +865,9 @@ class PrintDataoutputs {
? '------------------------------------------------' ? '------------------------------------------------'
: '--------------------------------', : '--------------------------------',
styles: const PosStyles(bold: false, align: PosAlign.center)); styles: const PosStyles(bold: false, align: PosAlign.center));
for (final product in (order.orderItems ?? <OrderItem>[])) { for (final product
in (order.orderItems?.where((item) => item.status != 'cancelled') ??
<OrderItem>[])) {
bytes += generator.row([ bytes += generator.row([
PosColumn( PosColumn(
text: '${product.quantity} x ${product.productName}', text: '${product.quantity} x ${product.productName}',
@@ -405,7 +405,7 @@ class OrderRemoteDatasource {
} }
} }
Future<Either<String, OrderDetailResponseModel>> addToOrder({ Future<Either<String, bool>> addToOrder({
required String orderId, required String orderId,
required List<OrderItemRequest> orderItems, required List<OrderItemRequest> orderItems,
}) async { }) async {
@@ -429,8 +429,7 @@ class OrderRemoteDatasource {
); );
if (response.statusCode == 200) { if (response.statusCode == 200) {
final data = OrderDetailResponseModel.fromMap(response.data); return Right(true);
return Right(data);
} else { } else {
return const Left('Gagal menambahkan pesanan pesanan'); return const Left('Gagal menambahkan pesanan pesanan');
} }
@@ -442,7 +441,7 @@ class OrderRemoteDatasource {
return Left(errorMessage); return Left(errorMessage);
} catch (e) { } catch (e) {
log("đź’Ą Unexpected error: $e"); log("đź’Ą Unexpected error: $e");
return const Left('Terjadi kesalahan tak terduga'); return const Left('Terjadi kesalahan, coba lagi nanti.');
} }
} }
@@ -55,7 +55,7 @@ class TableRemoteDataSource {
Future<Either<String, TableResponseModel>> getTable({ Future<Either<String, TableResponseModel>> getTable({
int page = 1, int page = 1,
int limit = 10, int limit = 50,
String? status, String? status,
}) async { }) async {
try { try {
@@ -131,4 +131,40 @@ class TableRemoteDataSource {
return const Left('Unexpected error occurred'); return const Left('Unexpected error occurred');
} }
} }
Future<Either<String, bool>> transferTable({
required String fromTableId,
required String toTableId,
}) async {
try {
final authData = await AuthLocalDataSource().getAuthData();
final url = '${Variables.baseUrl}/api/v1/tables/transfer';
final response = await dio.put(
url,
data: {
"from_table": fromTableId,
"to_table": toTableId,
},
options: Options(
headers: {
'Authorization': 'Bearer ${authData.token}',
'Accept': 'application/json',
},
),
);
if (response.statusCode == 200 || response.statusCode == 201) {
return Right(true);
} else {
return const Left('Failed to create table');
}
} on DioException catch (e) {
log("Dio error: ${e.message}");
return Left(e.response?.data['message'] ?? 'Gagal membuat table');
} catch (e) {
log("Unexpected error: $e");
return const Left('Unexpected error occurred');
}
}
} }
+4 -1
View File
@@ -100,10 +100,13 @@ class PaymentSplitBillRequest {
Map<String, dynamic> data = { Map<String, dynamic> data = {
'order_id': orderId, 'order_id': orderId,
'payment_method_id': paymentMethodId, 'payment_method_id': paymentMethodId,
'customer_id': customerId,
'type': type, 'type': type,
}; };
if (customerId.isNotEmpty) {
data['customer_id'] = customerId;
}
if (type == "AMOUNT") { if (type == "AMOUNT") {
data['amount'] = amount; data['amount'] = amount;
} }
@@ -59,11 +59,17 @@ class DashboardAnalyticData {
dateFrom: map['date_from'], dateFrom: map['date_from'],
dateTo: map['date_to'], dateTo: map['date_to'],
overview: DashboardOverview.fromMap(map['overview']), overview: DashboardOverview.fromMap(map['overview']),
topProducts: List<TopProduct>.from( topProducts: map['top_products'] == null
? []
: List<TopProduct>.from(
map['top_products']?.map((x) => TopProduct.fromMap(x))), map['top_products']?.map((x) => TopProduct.fromMap(x))),
paymentMethods: List<PaymentMethodAnalytic>.from(map['payment_methods'] paymentMethods: map['payment_methods'] == null
? []
: List<PaymentMethodAnalytic>.from(map['payment_methods']
?.map((x) => PaymentMethodAnalytic.fromMap(x))), ?.map((x) => PaymentMethodAnalytic.fromMap(x))),
recentSales: List<RecentSale>.from( recentSales: map['recent_sales'] == null
? []
: List<RecentSale>.from(
map['recent_sales']?.map((x) => RecentSale.fromMap(x))), map['recent_sales']?.map((x) => RecentSale.fromMap(x))),
); );
+268 -144
View File
@@ -1,35 +1,5 @@
import 'dart:convert'; import 'dart:convert';
class OrderResponseModel {
final bool? success;
final OrderData? data;
final dynamic errors;
OrderResponseModel({
this.success,
this.data,
this.errors,
});
factory OrderResponseModel.fromJson(String str) =>
OrderResponseModel.fromMap(json.decode(str));
String toJson() => json.encode(toMap());
factory OrderResponseModel.fromMap(Map<String, dynamic> json) =>
OrderResponseModel(
success: json["success"],
data: json["data"] == null ? null : OrderData.fromMap(json["data"]),
errors: json["errors"],
);
Map<String, dynamic> toMap() => {
"success": success,
"data": data?.toMap(),
"errors": errors,
};
}
class OrderDetailResponseModel { class OrderDetailResponseModel {
final bool? success; final bool? success;
final Order? data; final Order? data;
@@ -60,40 +30,77 @@ class OrderDetailResponseModel {
}; };
} }
class OrderResponseModel {
final bool? success;
final OrderData? data;
OrderResponseModel({
this.success,
this.data,
});
factory OrderResponseModel.fromJson(String str) =>
OrderResponseModel.fromMap(json.decode(str));
String toJson() => json.encode(toMap());
factory OrderResponseModel.fromMap(Map<String, dynamic> map) {
return OrderResponseModel(
success: map['success'] ?? false,
data: OrderData.fromMap(map['data']),
);
}
Map<String, dynamic> toMap() {
return {
'success': success,
'data': data?.toMap(),
};
}
}
class OrderData { class OrderData {
final List<Order>? orders; final List<Order>? orders;
final List<Payment>? payments;
final int? totalCount; final int? totalCount;
final int? page; final int? page;
final int? limit; final int? limit;
final int? totalPages; final int? totalPages;
OrderData({ OrderData({
this.orders, required this.orders,
this.totalCount, required this.payments,
this.page, required this.totalCount,
this.limit, required this.page,
this.totalPages, required this.limit,
required this.totalPages,
}); });
factory OrderData.fromMap(Map<String, dynamic> json) => OrderData( factory OrderData.fromMap(Map<String, dynamic> map) {
orders: json["orders"] == null return OrderData(
orders: map["orders"] == null
? [] ? []
: List<Order>.from(json["orders"].map((x) => Order.fromMap(x))), : List<Order>.from(map['orders']?.map((x) => Order.fromMap(x))),
totalCount: json["total_count"], payments: map["payments"] == null
page: json["page"], ? []
limit: json["limit"], : List<Payment>.from(map['payments']?.map((x) => Payment.fromMap(x))),
totalPages: json["total_pages"], totalCount: map['total_count'],
page: map['page'],
limit: map['limit'],
totalPages: map['total_pages'],
); );
}
Map<String, dynamic> toMap() => { Map<String, dynamic> toMap() {
"orders": orders == null return {
? [] 'orders': orders?.map((x) => x.toMap()).toList(),
: List<dynamic>.from(orders!.map((x) => x.toMap())), 'payments': payments?.map((x) => x.toMap()).toList(),
"total_count": totalCount, 'total_count': totalCount,
"page": page, 'page': page,
"limit": limit, 'limit': limit,
"total_pages": totalPages, 'total_pages': totalPages,
}; };
}
} }
class Order { class Order {
@@ -108,12 +115,21 @@ class Order {
final int? taxAmount; final int? taxAmount;
final int? discountAmount; final int? discountAmount;
final int? totalAmount; final int? totalAmount;
final int? totalCost;
final int? remainingAmount;
final String? paymentStatus;
final int? refundAmount;
final bool? isVoid;
final bool? isRefund;
final String? notes; final String? notes;
final Map<String, dynamic>? metadata; final Map<String, dynamic>? metadata;
final DateTime? createdAt; final DateTime? createdAt;
final DateTime? updatedAt; final DateTime? updatedAt;
final List<OrderItem>? orderItems; final List<OrderItem>? orderItems;
final bool? isRefund; final List<Payment>? payments;
final int? totalPaid;
final int? paymentCount;
final String? splitType;
Order({ Order({
this.id, this.id,
@@ -127,79 +143,108 @@ class Order {
this.taxAmount, this.taxAmount,
this.discountAmount, this.discountAmount,
this.totalAmount, this.totalAmount,
this.totalCost,
this.remainingAmount,
this.paymentStatus,
this.refundAmount,
this.isVoid,
this.isRefund,
this.notes, this.notes,
this.metadata, this.metadata,
this.createdAt, this.createdAt,
this.updatedAt, this.updatedAt,
this.orderItems, this.orderItems,
this.isRefund, this.payments,
this.totalPaid,
this.paymentCount,
this.splitType,
}); });
factory Order.fromMap(Map<String, dynamic> json) => Order( factory Order.fromMap(Map<String, dynamic> map) {
id: json["id"], return Order(
orderNumber: json["order_number"], id: map['id'],
outletId: json["outlet_id"], orderNumber: map['order_number'],
userId: json["user_id"], outletId: map['outlet_id'],
tableNumber: json["table_number"], userId: map['user_id'],
orderType: json["order_type"], tableNumber: map['table_number'],
status: json["status"], orderType: map['order_type'],
subtotal: json["subtotal"], status: map['status'],
taxAmount: json["tax_amount"], subtotal: map['subtotal'],
discountAmount: json["discount_amount"], taxAmount: map['tax_amount'],
totalAmount: json["total_amount"], discountAmount: map['discount_amount'],
notes: json["notes"], totalAmount: map['total_amount'],
metadata: json["metadata"] ?? {}, totalCost: map['total_cost'],
isRefund: json["is_refund"], remainingAmount: map['remaining_amount'],
createdAt: json["created_at"] == null paymentStatus: map['payment_status'],
? null refundAmount: map['refund_amount'],
: DateTime.parse(json["created_at"]), isVoid: map['is_void'],
updatedAt: json["updated_at"] == null isRefund: map['is_refund'],
? null notes: map['notes'],
: DateTime.parse(json["updated_at"]), metadata: map['metadata'] ?? {},
orderItems: json["order_items"] == null createdAt: DateTime.parse(map['created_at']),
updatedAt: DateTime.parse(map['updated_at']),
orderItems: map["order_items"] == null
? [] ? []
: List<OrderItem>.from( : List<OrderItem>.from(
json["order_items"].map((x) => OrderItem.fromMap(x))), map['order_items'].map((x) => OrderItem.fromMap(x))),
); payments: map["payments"] == null
Map<String, dynamic> toMap() => {
"id": id,
"order_number": orderNumber,
"outlet_id": outletId,
"user_id": userId,
"table_number": tableNumber,
"order_type": orderType,
"status": status,
"subtotal": subtotal,
"tax_amount": taxAmount,
"discount_amount": discountAmount,
"total_amount": totalAmount,
"notes": notes,
"metadata": metadata,
"created_at": createdAt?.toIso8601String(),
"updated_at": updatedAt?.toIso8601String(),
"is_refund": isRefund,
"order_items": orderItems == null
? [] ? []
: List<dynamic>.from(orderItems!.map((x) => x.toMap())), : List<Payment>.from(map['payments'].map((x) => Payment.fromMap(x))),
totalPaid: map['total_paid'],
paymentCount: map['payment_count'],
splitType: map['split_type'] ?? "",
);
}
Map<String, dynamic> toMap() {
return {
'id': id,
'order_number': orderNumber,
'outlet_id': outletId,
'user_id': userId,
'table_number': tableNumber,
'order_type': orderType,
'status': status,
'subtotal': subtotal,
'tax_amount': taxAmount,
'discount_amount': discountAmount,
'total_amount': totalAmount,
'total_cost': totalCost,
'remaining_amount': remainingAmount,
'payment_status': paymentStatus,
'refund_amount': refundAmount,
'is_void': isVoid,
'is_refund': isRefund,
'notes': notes,
'metadata': metadata,
'created_at': createdAt?.toIso8601String(),
'updated_at': updatedAt?.toIso8601String(),
'order_items': orderItems?.map((x) => x.toMap()).toList(),
'payments': payments?.map((x) => x.toMap()).toList(),
'total_paid': totalPaid,
'payment_count': paymentCount,
'split_type': splitType,
}; };
}
} }
class OrderItem { class OrderItem {
final String? id; String? id;
final String? orderId; String? orderId;
final String? productId; String? productId;
final String? productName; String? productName;
final String? productVariantId; String? productVariantId;
final String? productVariantName; String? productVariantName;
final int? quantity; int? quantity;
final int? unitPrice; int? unitPrice;
final int? totalPrice; int? totalPrice;
final List<dynamic>? modifiers; List<dynamic>? modifiers;
final String? notes; String? notes;
final String? status; String? status;
final DateTime? createdAt; DateTime? createdAt;
final DateTime? updatedAt; DateTime? updatedAt;
String? printerType;
int? paidQuantity;
OrderItem({ OrderItem({
this.id, this.id,
@@ -216,43 +261,122 @@ class OrderItem {
this.status, this.status,
this.createdAt, this.createdAt,
this.updatedAt, this.updatedAt,
this.printerType,
this.paidQuantity,
}); });
factory OrderItem.fromMap(Map<String, dynamic> json) => OrderItem( factory OrderItem.fromMap(Map<String, dynamic> map) {
id: json["id"], return OrderItem(
orderId: json["order_id"], id: map['id'],
productId: json["product_id"], orderId: map['order_id'],
productName: json["product_name"], productId: map['product_id'],
productVariantId: json["product_variant_id"], productName: map['product_name'],
productVariantName: json["product_variant_name"], productVariantId: map['product_variant_id'],
quantity: json["quantity"], productVariantName: map['product_variant_name'],
unitPrice: json["unit_price"], quantity: map['quantity'],
totalPrice: json["total_price"], unitPrice: map['unit_price'],
modifiers: json["modifiers"] ?? [], totalPrice: map['total_price'],
notes: json["notes"], modifiers:
status: json["status"], map['modifiers'] == null ? [] : List<dynamic>.from(map['modifiers']),
createdAt: json["created_at"] == null notes: map['notes'],
? null status: map['status'],
: DateTime.parse(json["created_at"]), createdAt: DateTime.parse(map['created_at']),
updatedAt: json["updated_at"] == null updatedAt: DateTime.parse(map['updated_at']),
? null printerType: map['printer_type'],
: DateTime.parse(json["updated_at"]), paidQuantity: map['paid_quantity'],
); );
}
Map<String, dynamic> toMap() => { Map<String, dynamic> toMap() {
"id": id, return {
"order_id": orderId, 'id': id,
"product_id": productId, 'order_id': orderId,
"product_name": productName, 'product_id': productId,
"product_variant_id": productVariantId, 'product_name': productName,
"product_variant_name": productVariantName, 'product_variant_id': productVariantId,
"quantity": quantity, 'product_variant_name': productVariantName,
"unit_price": unitPrice, 'quantity': quantity,
"total_price": totalPrice, 'unit_price': unitPrice,
"modifiers": modifiers, 'total_price': totalPrice,
"notes": notes, 'modifiers': modifiers,
"status": status, 'notes': notes,
"created_at": createdAt?.toIso8601String(), 'status': status,
"updated_at": updatedAt?.toIso8601String(), 'created_at': createdAt?.toIso8601String(),
'updated_at': updatedAt?.toIso8601String(),
'printer_type': printerType,
'paid_quantity': paidQuantity,
}; };
}
}
class Payment {
final String? id;
final String? orderId;
final String? paymentMethodId;
final String? paymentMethodName;
final String? paymentMethodType;
final int? amount;
final String? status;
final int? splitNumber;
final int? splitTotal;
final String? splitDescription;
final int? refundAmount;
final Map<String, dynamic>? metadata;
final DateTime? createdAt;
final DateTime? updatedAt;
Payment({
this.id,
this.orderId,
this.paymentMethodId,
this.paymentMethodName,
this.paymentMethodType,
this.amount,
this.status,
this.splitNumber,
this.splitTotal,
this.splitDescription,
this.refundAmount,
this.metadata,
this.createdAt,
this.updatedAt,
});
factory Payment.fromMap(Map<String, dynamic> map) {
return Payment(
id: map['id'],
orderId: map['order_id'],
paymentMethodId: map['payment_method_id'],
paymentMethodName: map['payment_method_name'],
paymentMethodType: map['payment_method_type'],
amount: map['amount'],
status: map['status'],
splitNumber: map['split_number'],
splitTotal: map['split_total'],
splitDescription: map['split_description'],
refundAmount: map['refund_amount'],
metadata: map['metadata'] ?? {},
createdAt: DateTime.parse(map['created_at']),
updatedAt: DateTime.parse(map['updated_at']),
);
}
Map<String, dynamic> toMap() {
return {
'id': id,
'order_id': orderId,
'payment_method_id': paymentMethodId,
'payment_method_name': paymentMethodName,
'payment_method_type': paymentMethodType,
'amount': amount,
'status': status,
'split_number': splitNumber,
'split_total': splitTotal,
'split_description': splitDescription,
'refund_amount': refundAmount,
'metadata': metadata,
'created_at': createdAt?.toIso8601String(),
'updated_at': updatedAt?.toIso8601String(),
};
}
} }
@@ -64,8 +64,11 @@ class PaymentMethodAnalyticData {
dateTo: DateTime.parse(map['date_to']), dateTo: DateTime.parse(map['date_to']),
groupBy: map['group_by'], groupBy: map['group_by'],
summary: PaymentSummary.fromMap(map['summary']), summary: PaymentSummary.fromMap(map['summary']),
data: List<PaymentMethodAnalyticItem>.from( data: map['data'] == null
map['data']?.map((x) => PaymentMethodAnalyticItem.fromMap(x)) ?? [], ? []
: List<PaymentMethodAnalyticItem>.from(
map['data']?.map((x) => PaymentMethodAnalyticItem.fromMap(x)) ??
[],
), ),
); );
} }
@@ -52,7 +52,9 @@ class ProductAnalyticData {
outletId: map['outlet_id'], outletId: map['outlet_id'],
dateFrom: DateTime.parse(map['date_from']), dateFrom: DateTime.parse(map['date_from']),
dateTo: DateTime.parse(map['date_to']), dateTo: DateTime.parse(map['date_to']),
data: List<ProductAnalyticItem>.from( data: map['data'] == null
? []
: List<ProductAnalyticItem>.from(
map['data'].map((x) => ProductAnalyticItem.fromMap(x)), map['data'].map((x) => ProductAnalyticItem.fromMap(x)),
), ),
); );
@@ -72,9 +72,13 @@ class ProfitLossData {
dateTo: map['date_to'], dateTo: map['date_to'],
groupBy: map['group_by'], groupBy: map['group_by'],
summary: ProfitLossSummary.fromMap(map['summary']), summary: ProfitLossSummary.fromMap(map['summary']),
data: List<ProfitLossItem>.from( data: map['data'] == null
? []
: List<ProfitLossItem>.from(
map['data'].map((x) => ProfitLossItem.fromMap(x))), map['data'].map((x) => ProfitLossItem.fromMap(x))),
productData: List<ProfitLossProduct>.from( productData: map['product_data'] == null
? []
: List<ProfitLossProduct>.from(
map['product_data'].map((x) => ProfitLossProduct.fromMap(x))), map['product_data'].map((x) => ProfitLossProduct.fromMap(x))),
); );
} }
+4
View File
@@ -21,6 +21,7 @@ import 'package:enaklo_pos/presentation/sales/blocs/order_loader/order_loader_bl
import 'package:enaklo_pos/presentation/sales/blocs/payment_form/payment_form_bloc.dart'; import 'package:enaklo_pos/presentation/sales/blocs/payment_form/payment_form_bloc.dart';
import 'package:enaklo_pos/presentation/setting/bloc/get_printer_ticket/get_printer_ticket_bloc.dart'; import 'package:enaklo_pos/presentation/setting/bloc/get_printer_ticket/get_printer_ticket_bloc.dart';
import 'package:enaklo_pos/presentation/setting/bloc/upload_file/upload_file_bloc.dart'; import 'package:enaklo_pos/presentation/setting/bloc/upload_file/upload_file_bloc.dart';
import 'package:enaklo_pos/presentation/table/blocs/transfer_table/transfer_table_bloc.dart';
import 'package:enaklo_pos/presentation/void/bloc/void_order_bloc.dart'; import 'package:enaklo_pos/presentation/void/bloc/void_order_bloc.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:enaklo_pos/data/datasources/auth_local_datasource.dart'; import 'package:enaklo_pos/data/datasources/auth_local_datasource.dart';
@@ -284,6 +285,9 @@ class _MyAppState extends State<MyApp> {
BlocProvider( BlocProvider(
create: (context) => GetPrinterTicketBloc(), create: (context) => GetPrinterTicketBloc(),
), ),
BlocProvider(
create: (context) => TransferTableBloc(TableRemoteDataSource()),
),
], ],
child: MaterialApp( child: MaterialApp(
navigatorKey: AuthInterceptor.navigatorKey, navigatorKey: AuthInterceptor.navigatorKey,
@@ -77,8 +77,8 @@ class OrderFormBloc extends Bloc<OrderFormEvent, OrderFormState> {
customerName: event.customerName, customerName: event.customerName,
notes: '', notes: '',
orderType: event.orderType.name, orderType: event.orderType.name,
tableId: event.table.id, tableId: event.table?.id ?? "",
tableNumber: event.table.tableName, tableNumber: event.table?.tableName ?? "",
outletId: userData.user?.outletId, outletId: userData.user?.outletId,
customerId: event.customer?.id ?? '', customerId: event.customer?.id ?? '',
orderItems: event.items orderItems: event.items
@@ -131,11 +131,11 @@ class OrderFormBloc extends Bloc<OrderFormEvent, OrderFormState> {
result.fold( result.fold(
(error) => emit(_Error(error)), (error) => emit(_Error(error)),
(success) => emit(_Success(success.data!)), (success) => emit(_SuccessMsg()),
); );
} catch (e) { } catch (e) {
log("Error in AddOrderItemsBloc: $e"); log("Error in AddOrderItemsBloc: $e");
emit(_Error("Failed to add order items: $e")); emit(_Error("Ada kesalahan. Coba lagi nanti"));
} }
}, },
); );
@@ -27,7 +27,7 @@ mixin _$OrderFormEvent {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod) PaymentMethod paymentMethod)
createWithPayment, createWithPayment,
required TResult Function(List<ProductQuantity> items, String orderId) required TResult Function(List<ProductQuantity> items, String orderId)
@@ -53,7 +53,7 @@ mixin _$OrderFormEvent {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod)? PaymentMethod paymentMethod)?
createWithPayment, createWithPayment,
TResult? Function(List<ProductQuantity> items, String orderId)? addToOrder, TResult? Function(List<ProductQuantity> items, String orderId)? addToOrder,
@@ -76,7 +76,7 @@ mixin _$OrderFormEvent {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod)? PaymentMethod paymentMethod)?
createWithPayment, createWithPayment,
TResult Function(List<ProductQuantity> items, String orderId)? addToOrder, TResult Function(List<ProductQuantity> items, String orderId)? addToOrder,
@@ -226,7 +226,7 @@ class _$StartedImpl implements _Started {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod) PaymentMethod paymentMethod)
createWithPayment, createWithPayment,
required TResult Function(List<ProductQuantity> items, String orderId) required TResult Function(List<ProductQuantity> items, String orderId)
@@ -255,7 +255,7 @@ class _$StartedImpl implements _Started {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod)? PaymentMethod paymentMethod)?
createWithPayment, createWithPayment,
TResult? Function(List<ProductQuantity> items, String orderId)? addToOrder, TResult? Function(List<ProductQuantity> items, String orderId)? addToOrder,
@@ -281,7 +281,7 @@ class _$StartedImpl implements _Started {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod)? PaymentMethod paymentMethod)?
createWithPayment, createWithPayment,
TResult Function(List<ProductQuantity> items, String orderId)? addToOrder, TResult Function(List<ProductQuantity> items, String orderId)? addToOrder,
@@ -496,7 +496,7 @@ class _$CreateImpl implements _Create {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod) PaymentMethod paymentMethod)
createWithPayment, createWithPayment,
required TResult Function(List<ProductQuantity> items, String orderId) required TResult Function(List<ProductQuantity> items, String orderId)
@@ -525,7 +525,7 @@ class _$CreateImpl implements _Create {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod)? PaymentMethod paymentMethod)?
createWithPayment, createWithPayment,
TResult? Function(List<ProductQuantity> items, String orderId)? addToOrder, TResult? Function(List<ProductQuantity> items, String orderId)? addToOrder,
@@ -551,7 +551,7 @@ class _$CreateImpl implements _Create {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod)? PaymentMethod paymentMethod)?
createWithPayment, createWithPayment,
TResult Function(List<ProductQuantity> items, String orderId)? addToOrder, TResult Function(List<ProductQuantity> items, String orderId)? addToOrder,
@@ -652,7 +652,7 @@ abstract class _$$CreateWithPaymentMethodImplCopyWith<$Res> {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod}); PaymentMethod paymentMethod});
} }
@@ -674,7 +674,7 @@ class __$$CreateWithPaymentMethodImplCopyWithImpl<$Res>
Object? customerName = null, Object? customerName = null,
Object? customer = freezed, Object? customer = freezed,
Object? orderType = null, Object? orderType = null,
Object? table = null, Object? table = freezed,
Object? paymentMethod = null, Object? paymentMethod = null,
}) { }) {
return _then(_$CreateWithPaymentMethodImpl( return _then(_$CreateWithPaymentMethodImpl(
@@ -694,10 +694,10 @@ class __$$CreateWithPaymentMethodImplCopyWithImpl<$Res>
? _value.orderType ? _value.orderType
: orderType // ignore: cast_nullable_to_non_nullable : orderType // ignore: cast_nullable_to_non_nullable
as OrderType, as OrderType,
table: null == table table: freezed == table
? _value.table ? _value.table
: table // ignore: cast_nullable_to_non_nullable : table // ignore: cast_nullable_to_non_nullable
as TableModel, as TableModel?,
paymentMethod: null == paymentMethod paymentMethod: null == paymentMethod
? _value.paymentMethod ? _value.paymentMethod
: paymentMethod // ignore: cast_nullable_to_non_nullable : paymentMethod // ignore: cast_nullable_to_non_nullable
@@ -733,7 +733,7 @@ class _$CreateWithPaymentMethodImpl implements _CreateWithPaymentMethod {
@override @override
final OrderType orderType; final OrderType orderType;
@override @override
final TableModel table; final TableModel? table;
@override @override
final PaymentMethod paymentMethod; final PaymentMethod paymentMethod;
@@ -790,7 +790,7 @@ class _$CreateWithPaymentMethodImpl implements _CreateWithPaymentMethod {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod) PaymentMethod paymentMethod)
createWithPayment, createWithPayment,
required TResult Function(List<ProductQuantity> items, String orderId) required TResult Function(List<ProductQuantity> items, String orderId)
@@ -820,7 +820,7 @@ class _$CreateWithPaymentMethodImpl implements _CreateWithPaymentMethod {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod)? PaymentMethod paymentMethod)?
createWithPayment, createWithPayment,
TResult? Function(List<ProductQuantity> items, String orderId)? addToOrder, TResult? Function(List<ProductQuantity> items, String orderId)? addToOrder,
@@ -847,7 +847,7 @@ class _$CreateWithPaymentMethodImpl implements _CreateWithPaymentMethod {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod)? PaymentMethod paymentMethod)?
createWithPayment, createWithPayment,
TResult Function(List<ProductQuantity> items, String orderId)? addToOrder, TResult Function(List<ProductQuantity> items, String orderId)? addToOrder,
@@ -922,7 +922,7 @@ abstract class _CreateWithPaymentMethod implements OrderFormEvent {
required final String customerName, required final String customerName,
required final Customer? customer, required final Customer? customer,
required final OrderType orderType, required final OrderType orderType,
required final TableModel table, required final TableModel? table,
required final PaymentMethod paymentMethod}) = required final PaymentMethod paymentMethod}) =
_$CreateWithPaymentMethodImpl; _$CreateWithPaymentMethodImpl;
@@ -930,7 +930,7 @@ abstract class _CreateWithPaymentMethod implements OrderFormEvent {
String get customerName; String get customerName;
Customer? get customer; Customer? get customer;
OrderType get orderType; OrderType get orderType;
TableModel get table; TableModel? get table;
PaymentMethod get paymentMethod; PaymentMethod get paymentMethod;
/// Create a copy of OrderFormEvent /// Create a copy of OrderFormEvent
@@ -1034,7 +1034,7 @@ class _$AddToOrderImpl implements _AddToOrder {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod) PaymentMethod paymentMethod)
createWithPayment, createWithPayment,
required TResult Function(List<ProductQuantity> items, String orderId) required TResult Function(List<ProductQuantity> items, String orderId)
@@ -1063,7 +1063,7 @@ class _$AddToOrderImpl implements _AddToOrder {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod)? PaymentMethod paymentMethod)?
createWithPayment, createWithPayment,
TResult? Function(List<ProductQuantity> items, String orderId)? addToOrder, TResult? Function(List<ProductQuantity> items, String orderId)? addToOrder,
@@ -1089,7 +1089,7 @@ class _$AddToOrderImpl implements _AddToOrder {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod)? PaymentMethod paymentMethod)?
createWithPayment, createWithPayment,
TResult Function(List<ProductQuantity> items, String orderId)? addToOrder, TResult Function(List<ProductQuantity> items, String orderId)? addToOrder,
@@ -1276,7 +1276,7 @@ class _$RefundImpl implements _Refund {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod) PaymentMethod paymentMethod)
createWithPayment, createWithPayment,
required TResult Function(List<ProductQuantity> items, String orderId) required TResult Function(List<ProductQuantity> items, String orderId)
@@ -1305,7 +1305,7 @@ class _$RefundImpl implements _Refund {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod)? PaymentMethod paymentMethod)?
createWithPayment, createWithPayment,
TResult? Function(List<ProductQuantity> items, String orderId)? addToOrder, TResult? Function(List<ProductQuantity> items, String orderId)? addToOrder,
@@ -1331,7 +1331,7 @@ class _$RefundImpl implements _Refund {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod)? PaymentMethod paymentMethod)?
createWithPayment, createWithPayment,
TResult Function(List<ProductQuantity> items, String orderId)? addToOrder, TResult Function(List<ProductQuantity> items, String orderId)? addToOrder,
@@ -1520,7 +1520,7 @@ class _$VoidOrderImpl implements _VoidOrder {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod) PaymentMethod paymentMethod)
createWithPayment, createWithPayment,
required TResult Function(List<ProductQuantity> items, String orderId) required TResult Function(List<ProductQuantity> items, String orderId)
@@ -1549,7 +1549,7 @@ class _$VoidOrderImpl implements _VoidOrder {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod)? PaymentMethod paymentMethod)?
createWithPayment, createWithPayment,
TResult? Function(List<ProductQuantity> items, String orderId)? addToOrder, TResult? Function(List<ProductQuantity> items, String orderId)? addToOrder,
@@ -1575,7 +1575,7 @@ class _$VoidOrderImpl implements _VoidOrder {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod)? PaymentMethod paymentMethod)?
createWithPayment, createWithPayment,
TResult Function(List<ProductQuantity> items, String orderId)? addToOrder, TResult Function(List<ProductQuantity> items, String orderId)? addToOrder,
@@ -1737,7 +1737,7 @@ class _$ToggleItemImpl implements _ToggleItem {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod) PaymentMethod paymentMethod)
createWithPayment, createWithPayment,
required TResult Function(List<ProductQuantity> items, String orderId) required TResult Function(List<ProductQuantity> items, String orderId)
@@ -1766,7 +1766,7 @@ class _$ToggleItemImpl implements _ToggleItem {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod)? PaymentMethod paymentMethod)?
createWithPayment, createWithPayment,
TResult? Function(List<ProductQuantity> items, String orderId)? addToOrder, TResult? Function(List<ProductQuantity> items, String orderId)? addToOrder,
@@ -1792,7 +1792,7 @@ class _$ToggleItemImpl implements _ToggleItem {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod)? PaymentMethod paymentMethod)?
createWithPayment, createWithPayment,
TResult Function(List<ProductQuantity> items, String orderId)? addToOrder, TResult Function(List<ProductQuantity> items, String orderId)? addToOrder,
@@ -1951,7 +1951,7 @@ class _$ToggleSelectAllImpl implements _ToggleSelectAll {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod) PaymentMethod paymentMethod)
createWithPayment, createWithPayment,
required TResult Function(List<ProductQuantity> items, String orderId) required TResult Function(List<ProductQuantity> items, String orderId)
@@ -1980,7 +1980,7 @@ class _$ToggleSelectAllImpl implements _ToggleSelectAll {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod)? PaymentMethod paymentMethod)?
createWithPayment, createWithPayment,
TResult? Function(List<ProductQuantity> items, String orderId)? addToOrder, TResult? Function(List<ProductQuantity> items, String orderId)? addToOrder,
@@ -2006,7 +2006,7 @@ class _$ToggleSelectAllImpl implements _ToggleSelectAll {
String customerName, String customerName,
Customer? customer, Customer? customer,
OrderType orderType, OrderType orderType,
TableModel table, TableModel? table,
PaymentMethod paymentMethod)? PaymentMethod paymentMethod)?
createWithPayment, createWithPayment,
TResult Function(List<ProductQuantity> items, String orderId)? addToOrder, TResult Function(List<ProductQuantity> items, String orderId)? addToOrder,
@@ -15,7 +15,7 @@ class OrderFormEvent with _$OrderFormEvent {
required String customerName, required String customerName,
required Customer? customer, required Customer? customer,
required OrderType orderType, required OrderType orderType,
required TableModel table, required TableModel? table,
required PaymentMethod paymentMethod, required PaymentMethod paymentMethod,
}) = _CreateWithPaymentMethod; }) = _CreateWithPaymentMethod;
const factory OrderFormEvent.addToOrder({ const factory OrderFormEvent.addToOrder({
@@ -289,7 +289,7 @@ class _PaymentAddOrderDialogState extends State<PaymentAddOrderDialog> {
listener: (context, state) { listener: (context, state) {
state.maybeWhen( state.maybeWhen(
orElse: () {}, orElse: () {},
success: (data) { successMsg: () {
context.pop(); context.pop();
context.pushReplacement( context.pushReplacement(
SuccessSaveOrderPage( SuccessSaveOrderPage(
@@ -45,7 +45,6 @@ class OrderRequestModel {
Map<String, dynamic> data = { Map<String, dynamic> data = {
"outlet_id": outletId, "outlet_id": outletId,
"table_number": tableNumber, "table_number": tableNumber,
"table_id": tableId,
"order_type": orderType, "order_type": orderType,
"notes": notes, "notes": notes,
"order_items": orderItems == null "order_items": orderItems == null
@@ -58,6 +57,10 @@ class OrderRequestModel {
data["customer_id"] = customerId; data["customer_id"] = customerId;
} }
if (tableId != null && tableId != "") {
data["table_id"] = tableId;
}
return data; return data;
} }
} }
@@ -355,7 +355,10 @@ class _ConfirmPaymentPageState extends State<ConfirmPaymentPage> {
(previousValue, element) => (previousValue, element) =>
previousValue + previousValue +
(element.product.price! * (element.product.price! *
element.quantity), element.quantity) +
(element.variant
?.priceModifier ??
0),
)); ));
return Text( return Text(
price.currencyFormatRp, price.currencyFormatRp,
@@ -500,7 +503,9 @@ class _ConfirmPaymentPageState extends State<ConfirmPaymentPage> {
(previousValue, element) => (previousValue, element) =>
previousValue + previousValue +
(element.product.price! * (element.product.price! *
element.quantity), element.quantity) +
(element.variant?.priceModifier ??
0),
), ),
); );
@@ -1065,12 +1070,15 @@ class _ConfirmPaymentPageState extends State<ConfirmPaymentPage> {
} }
context.read<OrderFormBloc>().add( context.read<OrderFormBloc>().add(
OrderFormEvent.create( OrderFormEvent
.createWithPayment(
items: items, items: items,
customerName: customerName:
customerController customerController
.text, .text,
orderType: orderType, orderType: orderType,
paymentMethod:
selectedPaymentMethod!,
table: widget.table, table: widget.table,
customer: customer:
selectedCustomer, selectedCustomer,
+4 -2
View File
@@ -429,8 +429,10 @@ class _HomePageState extends State<HomePage> {
} }
return products return products
.map((e) => .map((e) =>
e.product.price! * (e.product.price! *
e.quantity) e.quantity) +
(e.variant?.priceModifier ??
0))
.reduce((value, element) => .reduce((value, element) =>
value + element); value + element);
}); });
@@ -372,7 +372,8 @@ class _PaymentPageState extends State<PaymentPage> {
success: (data) { success: (data) {
context.pushReplacement(SuccessPaymentPage( context.pushReplacement(SuccessPaymentPage(
productQuantity: widget.order.orderItems productQuantity: widget.order.orderItems
?.map( ?.where((item) => item.status == "pending")
.map(
(item) => ProductQuantity( (item) => ProductQuantity(
product: Product( product: Product(
name: item.productName, name: item.productName,
@@ -1,6 +1,8 @@
import 'package:enaklo_pos/core/components/spaces.dart'; import 'package:enaklo_pos/core/components/spaces.dart';
import 'package:enaklo_pos/core/constants/colors.dart'; import 'package:enaklo_pos/core/constants/colors.dart';
import 'package:enaklo_pos/core/extensions/build_context_ext.dart';
import 'package:enaklo_pos/core/extensions/int_ext.dart'; import 'package:enaklo_pos/core/extensions/int_ext.dart';
import 'package:enaklo_pos/presentation/home/pages/dashboard_page.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class RefundSuccessDialog extends StatelessWidget { class RefundSuccessDialog extends StatelessWidget {
@@ -102,8 +104,7 @@ class RefundSuccessDialog extends StatelessWidget {
Expanded( Expanded(
child: ElevatedButton( child: ElevatedButton(
onPressed: () { onPressed: () {
Navigator.pop(context); context.push(DashboardPage());
Navigator.pop(context);
}, },
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: AppColors.primary, backgroundColor: AppColors.primary,
@@ -172,12 +172,17 @@ class ProfitLossWidget extends StatelessWidget {
break; break;
} }
if (previous == 0) return '+0.0%'; // Handle division by zero and invalid values
if (previous == 0 || previous.isNaN || previous.isInfinite) return '+0.0%';
if (current.isNaN || current.isInfinite) return '+0.0%';
final trendPercentage = ((current - previous) / previous) * 100; final trendPercentage = ((current - previous) / previous) * 100;
final sign = trendPercentage >= 0 ? '+' : '';
return '$sign${trendPercentage.toStringAsFixed(1)}%'; // Check if trendPercentage is valid
if (trendPercentage.isNaN || trendPercentage.isInfinite) return '+0.0%';
final sign = trendPercentage >= 0 ? '+' : '';
return '$sign${trendPercentage.round()}%';
} }
Widget _buildSummaryCards() { Widget _buildSummaryCards() {
@@ -201,8 +206,7 @@ class ProfitLossWidget extends StatelessWidget {
{ {
'title': 'Laba Kotor', 'title': 'Laba Kotor',
'value': _formatCurrency(data.summary.grossProfit), 'value': _formatCurrency(data.summary.grossProfit),
'subtitle': 'subtitle': '${_safeRound(data.summary.grossProfitMargin)}% margin',
'${data.summary.grossProfitMargin.toStringAsFixed(1)}% margin',
'icon': Icons.trending_up, 'icon': Icons.trending_up,
'color': AppColorProfitLoss.primary, 'color': AppColorProfitLoss.primary,
'trend': _calculateTrend('grossProfit'), 'trend': _calculateTrend('grossProfit'),
@@ -210,8 +214,7 @@ class ProfitLossWidget extends StatelessWidget {
{ {
'title': 'Laba Bersih', 'title': 'Laba Bersih',
'value': _formatCurrency(data.summary.netProfit), 'value': _formatCurrency(data.summary.netProfit),
'subtitle': 'subtitle': '${_safeRound(data.summary.netProfitMargin)}% margin',
'${data.summary.netProfitMargin.toStringAsFixed(1)}% margin',
'icon': Icons.account_balance, 'icon': Icons.account_balance,
'color': AppColorProfitLoss.info, 'color': AppColorProfitLoss.info,
'trend': _calculateTrend('netProfit'), 'trend': _calculateTrend('netProfit'),
@@ -360,13 +363,17 @@ class ProfitLossWidget extends StatelessWidget {
showTitles: true, showTitles: true,
reservedSize: 50, reservedSize: 50,
getTitlesWidget: (value, meta) { getTitlesWidget: (value, meta) {
final kValue = (value / 1000);
if (kValue.isFinite) {
return Text( return Text(
'${(value / 1000).toInt()}K', '${kValue.toInt()}K',
style: TextStyle( style: TextStyle(
color: Colors.grey[600], color: Colors.grey[600],
fontSize: 10, fontSize: 10,
), ),
); );
}
return const SizedBox();
}, },
), ),
), ),
@@ -402,8 +409,9 @@ class ProfitLossWidget extends StatelessWidget {
// Garis Pendapatan // Garis Pendapatan
LineChartBarData( LineChartBarData(
spots: data.data.asMap().entries.map((entry) { spots: data.data.asMap().entries.map((entry) {
final revenue = entry.value.revenue.toDouble();
return FlSpot( return FlSpot(
entry.key.toDouble(), entry.value.revenue.toDouble()); entry.key.toDouble(), revenue.isFinite ? revenue : 0);
}).toList(), }).toList(),
isCurved: true, isCurved: true,
color: AppColorProfitLoss.info, color: AppColorProfitLoss.info,
@@ -412,8 +420,9 @@ class ProfitLossWidget extends StatelessWidget {
// Garis Biaya // Garis Biaya
LineChartBarData( LineChartBarData(
spots: data.data.asMap().entries.map((entry) { spots: data.data.asMap().entries.map((entry) {
final cost = entry.value.cost.toDouble();
return FlSpot( return FlSpot(
entry.key.toDouble(), entry.value.cost.toDouble()); entry.key.toDouble(), cost.isFinite ? cost : 0);
}).toList(), }).toList(),
isCurved: true, isCurved: true,
color: AppColorProfitLoss.danger, color: AppColorProfitLoss.danger,
@@ -422,8 +431,9 @@ class ProfitLossWidget extends StatelessWidget {
// Garis Laba Bersih // Garis Laba Bersih
LineChartBarData( LineChartBarData(
spots: data.data.asMap().entries.map((entry) { spots: data.data.asMap().entries.map((entry) {
final netProfit = entry.value.netProfit.toDouble();
return FlSpot(entry.key.toDouble(), return FlSpot(entry.key.toDouble(),
entry.value.netProfit.toDouble()); netProfit.isFinite ? netProfit : 0);
}).toList(), }).toList(),
isCurved: true, isCurved: true,
color: AppColorProfitLoss.success, color: AppColorProfitLoss.success,
@@ -506,9 +516,10 @@ class ProfitLossWidget extends StatelessWidget {
} }
Widget _buildProductItem(ProfitLossProduct product) { Widget _buildProductItem(ProfitLossProduct product) {
final profitColor = product.grossProfitMargin >= 35 final profitMargin = _safeDouble(product.grossProfitMargin);
final profitColor = profitMargin >= 35
? AppColorProfitLoss.success ? AppColorProfitLoss.success
: product.grossProfitMargin >= 25 : profitMargin >= 25
? AppColorProfitLoss.warning ? AppColorProfitLoss.warning
: AppColorProfitLoss.danger; : AppColorProfitLoss.danger;
@@ -572,7 +583,7 @@ class ProfitLossWidget extends StatelessWidget {
borderRadius: BorderRadius.circular(6), borderRadius: BorderRadius.circular(6),
), ),
child: Text( child: Text(
'${product.grossProfitMargin.toStringAsFixed(1)}%', '${_safeRound(profitMargin)}%',
style: TextStyle( style: TextStyle(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@@ -710,13 +721,17 @@ class ProfitLossWidget extends StatelessWidget {
startDegreeOffset: -90, startDegreeOffset: -90,
sections: breakdownData.asMap().entries.map((entry) { sections: breakdownData.asMap().entries.map((entry) {
final item = entry.value; final item = entry.value;
final grossProfit = data.summary.grossProfit;
final value = item['value'] as int;
// Handle division by zero
final percentage = final percentage =
(item['value'] as int) / data.summary.grossProfit * 100; grossProfit > 0 ? (value / grossProfit * 100) : 0.0;
return PieChartSectionData( return PieChartSectionData(
color: item['color'] as Color, color: item['color'] as Color,
value: (item['value'] as int).toDouble(), value: value.toDouble(),
title: '${percentage.toStringAsFixed(1)}%', title: '${_safeRound(percentage)}%',
radius: 40, radius: 40,
titleStyle: const TextStyle( titleStyle: const TextStyle(
fontSize: 10, fontSize: 10,
@@ -799,7 +814,7 @@ class ProfitLossWidget extends StatelessWidget {
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
Text( Text(
'${(data.summary.profitabilityRatio * 100).toStringAsFixed(1)}%', '${_safeRound(data.summary.profitabilityRatio)}%',
style: const TextStyle( style: const TextStyle(
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@@ -848,9 +863,7 @@ class ProfitLossWidget extends StatelessWidget {
Expanded( Expanded(
child: _buildMetricCard( child: _buildMetricCard(
'Nilai Rata-rata Pesanan', 'Nilai Rata-rata Pesanan',
_formatCurrency( _formatCurrency(_safeCalculateAverageOrder()),
(data.summary.totalRevenue / data.summary.totalOrders)
.round()),
'Per transaksi', 'Per transaksi',
Icons.shopping_cart_outlined, Icons.shopping_cart_outlined,
AppColorProfitLoss.info, AppColorProfitLoss.info,
@@ -870,7 +883,7 @@ class ProfitLossWidget extends StatelessWidget {
Expanded( Expanded(
child: _buildMetricCard( child: _buildMetricCard(
'Rasio Biaya', 'Rasio Biaya',
'${((data.summary.totalCost / data.summary.totalRevenue) * 100).toStringAsFixed(1)}%', '${_safeCalculateCostRatio()}%',
'Dari total pendapatan', 'Dari total pendapatan',
Icons.pie_chart, Icons.pie_chart,
AppColorProfitLoss.danger, AppColorProfitLoss.danger,
@@ -1026,7 +1039,7 @@ class ProfitLossWidget extends StatelessWidget {
borderRadius: BorderRadius.circular(4), borderRadius: BorderRadius.circular(4),
), ),
child: Text( child: Text(
'${item.netProfitMargin.toStringAsFixed(1)}%', '${_safeRound(item.netProfitMargin)}%',
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontSize: 10, fontSize: 10,
@@ -1093,6 +1106,31 @@ class ProfitLossWidget extends StatelessWidget {
); );
} }
// Helper methods for safe calculations
int _safeRound(double value) {
if (value.isNaN || value.isInfinite) return 0;
return value.round();
}
double _safeDouble(double value) {
if (value.isNaN || value.isInfinite) return 0.0;
return value;
}
int _safeCalculateAverageOrder() {
if (data.summary.totalOrders == 0) return 0;
final average = data.summary.totalRevenue / data.summary.totalOrders;
if (average.isNaN || average.isInfinite) return 0;
return average.round();
}
int _safeCalculateCostRatio() {
if (data.summary.totalRevenue == 0) return 0;
final ratio = (data.summary.totalCost / data.summary.totalRevenue) * 100;
if (ratio.isNaN || ratio.isInfinite) return 0;
return ratio.round();
}
IconData _getProductIcon(String category) { IconData _getProductIcon(String category) {
switch (category.toLowerCase()) { switch (category.toLowerCase()) {
case 'coffee': case 'coffee':
@@ -1110,8 +1148,9 @@ class ProfitLossWidget extends StatelessWidget {
} }
Color _getMarginColor(double margin) { Color _getMarginColor(double margin) {
if (margin >= 25) return AppColorProfitLoss.success; final safeMargin = _safeDouble(margin);
if (margin >= 15) return AppColorProfitLoss.warning; if (safeMargin >= 25) return AppColorProfitLoss.success;
if (safeMargin >= 15) return AppColorProfitLoss.warning;
return AppColorProfitLoss.danger; return AppColorProfitLoss.danger;
} }
@@ -1126,7 +1165,7 @@ class ProfitLossWidget extends StatelessWidget {
String _formatCurrencyShort(int amount) { String _formatCurrencyShort(int amount) {
if (amount >= 1000000) { if (amount >= 1000000) {
return 'Rp ${(amount / 1000000).toStringAsFixed(1)}M'; return 'Rp ${(amount / 1000000).round()}M';
} else if (amount >= 1000) { } else if (amount >= 1000) {
return 'Rp ${(amount / 1000).toStringAsFixed(0)}K'; return 'Rp ${(amount / 1000).toStringAsFixed(0)}K';
} }
+20 -20
View File
@@ -6,9 +6,9 @@ import 'package:enaklo_pos/presentation/home/bloc/order_form/order_form_bloc.dar
import 'package:enaklo_pos/presentation/payment/pages/payment_page.dart'; import 'package:enaklo_pos/presentation/payment/pages/payment_page.dart';
import 'package:enaklo_pos/presentation/refund/pages/refund_page.dart'; import 'package:enaklo_pos/presentation/refund/pages/refund_page.dart';
import 'package:enaklo_pos/presentation/sales/blocs/order_loader/order_loader_bloc.dart'; import 'package:enaklo_pos/presentation/sales/blocs/order_loader/order_loader_bloc.dart';
import 'package:enaklo_pos/presentation/sales/widgets/sales_payment_summary.dart';
import 'package:enaklo_pos/presentation/split_bill/pages/split_bill_page.dart'; import 'package:enaklo_pos/presentation/split_bill/pages/split_bill_page.dart';
import 'package:enaklo_pos/presentation/void/pages/void_page.dart'; import 'package:enaklo_pos/presentation/void/pages/void_page.dart';
import 'package:enaklo_pos/presentation/sales/widgets/sales_detail.dart';
import 'package:enaklo_pos/presentation/sales/widgets/sales_list_order.dart'; import 'package:enaklo_pos/presentation/sales/widgets/sales_list_order.dart';
import 'package:enaklo_pos/presentation/sales/widgets/sales_order_information.dart'; import 'package:enaklo_pos/presentation/sales/widgets/sales_order_information.dart';
import 'package:enaklo_pos/presentation/sales/widgets/sales_payment.dart'; import 'package:enaklo_pos/presentation/sales/widgets/sales_payment.dart';
@@ -259,35 +259,35 @@ class _SalesPageState extends State<SalesPage> {
), ),
Expanded( Expanded(
child: SingleChildScrollView( child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: Column( child: Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Expanded( // Order Header
child: SalesOrderInformation( SalesOrderInformation(
order: orderDetail, order: orderDetail,
), ),
), // Order Items
SpaceWidth(16), SalesListOrder(order: orderDetail),
Expanded( const SpaceHeight(16),
child: SalesDetail(
order: orderDetail, // Payment Summary
), SalesPaymentSummary(order: orderDetail),
), const SpaceHeight(16),
// Payment Information
if (orderDetail?.payments != null &&
orderDetail?.payments!.isNotEmpty ==
true) ...[
SalesPayment(order: orderDetail),
const SpaceHeight(20),
], ],
),
SalesListOrder(
order: orderDetail,
),
SalesPayment(
order: orderDetail,
),
], ],
), ),
), ),
) ),
),
], ],
), ),
), ),
+79 -18
View File
@@ -58,6 +58,24 @@ class SalesCard extends StatelessWidget {
), ),
), ),
), ),
if (order.isVoid == true)
Container(
padding:
const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: Colors.red.withOpacity(0.15),
borderRadius: BorderRadius.circular(16),
),
child: Text(
'Void',
style: TextStyle(
color: Colors.red,
fontWeight: FontWeight.w600,
fontSize: 10,
letterSpacing: 0.5,
),
),
),
], ],
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
@@ -98,23 +116,7 @@ class SalesCard extends StatelessWidget {
], ],
), ),
), ),
Container( _buildStatus(),
padding:
const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: Colors.green.withOpacity(0.15),
borderRadius: BorderRadius.circular(16),
),
child: Text(
(order.status ?? "").toUpperCase(),
style: TextStyle(
color: Colors.green,
fontWeight: FontWeight.w600,
fontSize: 12,
letterSpacing: 0.5,
),
),
),
], ],
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
@@ -122,7 +124,10 @@ class SalesCard extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Text(
(order.totalAmount ?? 0).currencyFormatRpV2, order.status == 'pending'
? ((order.totalAmount ?? 0) - (order.totalPaid ?? 0))
.currencyFormatRpV2
: (order.totalAmount ?? 0).currencyFormatRpV2,
style: TextStyle( style: TextStyle(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@@ -142,4 +147,60 @@ class SalesCard extends StatelessWidget {
), ),
); );
} }
Widget _buildStatus() {
switch (order.status) {
case 'pending':
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: Colors.amber.withOpacity(0.15),
borderRadius: BorderRadius.circular(16),
),
child: Text(
(order.status ?? "").toUpperCase(),
style: TextStyle(
color: Colors.amber,
fontWeight: FontWeight.w600,
fontSize: 12,
letterSpacing: 0.5,
),
),
);
case 'completed':
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: Colors.green.withOpacity(0.15),
borderRadius: BorderRadius.circular(16),
),
child: Text(
(order.status ?? "").toUpperCase(),
style: TextStyle(
color: Colors.green,
fontWeight: FontWeight.w600,
fontSize: 12,
letterSpacing: 0.5,
),
),
);
default:
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.15),
borderRadius: BorderRadius.circular(16),
),
child: Text(
(order.status ?? "").toUpperCase(),
style: TextStyle(
color: Colors.grey,
fontWeight: FontWeight.w600,
fontSize: 12,
letterSpacing: 0.5,
),
),
);
}
}
} }
@@ -1,71 +0,0 @@
import 'package:enaklo_pos/core/constants/colors.dart';
import 'package:enaklo_pos/core/extensions/date_time_ext.dart';
import 'package:enaklo_pos/data/models/response/order_response_model.dart';
import 'package:flutter/material.dart';
class SalesDetail extends StatelessWidget {
final Order? order;
const SalesDetail({super.key, this.order});
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: AppColors.white,
borderRadius: BorderRadius.circular(8),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Detail',
style: TextStyle(
color: AppColors.black,
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
_item(
title: 'Pelanggan',
value: order?.metadata?['customer_name'] ?? "-",
),
_item(
title: 'Waktu',
value: (order?.createdAt ?? DateTime.now()).toFormattedDate3(),
),
_item(
title: 'Status',
value: order?.status ?? "-",
),
],
),
);
}
Padding _item({
required String title,
required String value,
}) {
return Padding(
padding: const EdgeInsets.only(top: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
title,
style: const TextStyle(
fontSize: 14,
),
),
Text(
value,
style: const TextStyle(
fontSize: 14,
),
),
],
),
);
}
}
@@ -63,27 +63,6 @@ class SalesListOrder extends StatelessWidget {
), ),
child: Row( child: Row(
children: [ children: [
Container(
decoration: BoxDecoration(
color: AppColors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: isAllSelected ? AppColors.primary : Colors.grey.shade300,
width: 2,
),
),
child: Checkbox(
value: isAllSelected,
activeColor: AppColors.primary,
checkColor: AppColors.white,
onChanged: (val) {
context
.read<OrderFormBloc>()
.add(OrderFormEvent.toggleSelectAll(val ?? false));
},
),
),
const SizedBox(width: 12),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -179,28 +158,6 @@ class SalesListOrder extends StatelessWidget {
Row( Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Container(
decoration: BoxDecoration(
color: AppColors.white,
borderRadius: BorderRadius.circular(6),
border: Border.all(
color:
isSelected ? AppColors.primary : Colors.grey.shade300,
width: 1.5,
),
),
child: Checkbox(
value: isSelected,
activeColor: AppColors.primary,
checkColor: AppColors.white,
onChanged: (_) {
context
.read<OrderFormBloc>()
.add(OrderFormEvent.toggleItem(product));
},
),
),
const SizedBox(width: 12),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -314,6 +271,57 @@ class SalesListOrder extends StatelessWidget {
), ),
], ],
), ),
if (order?.splitType == 'ITEM' && order?.status == 'pending') ...[
SpaceHeight(6),
Align(
alignment: Alignment.centerRight,
child: Container(
padding:
const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(
color: AppColors.primary.withOpacity(0.2),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: AppColors.primary),
),
child: RichText(
text: TextSpan(
children: [
TextSpan(
text: '${product.paidQuantity} ',
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: AppColors.primary,
),
),
TextSpan(
text: 'dari ',
style: const TextStyle(
fontSize: 12,
color: AppColors.primary,
),
),
TextSpan(
text: '${product.quantity} ',
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: AppColors.primary,
),
),
TextSpan(
text: 'kuantiti telah dibayar.',
style: const TextStyle(
fontSize: 12,
color: AppColors.primary,
),
),
],
),
),
),
)
],
], ],
), ),
), ),
@@ -328,8 +336,8 @@ class SalesListOrder extends StatelessWidget {
switch (status) { switch (status) {
case "pending": case "pending":
backgroundColor = Colors.orange.withOpacity(0.1); backgroundColor = Colors.white;
textColor = Colors.orange.shade700; textColor = Colors.white;
displayText = "Pending"; displayText = "Pending";
icon = Icons.access_time; icon = Icons.access_time;
break; break;
@@ -1,3 +1,4 @@
import 'package:enaklo_pos/core/components/spaces.dart';
import 'package:enaklo_pos/core/constants/colors.dart'; import 'package:enaklo_pos/core/constants/colors.dart';
import 'package:enaklo_pos/core/extensions/date_time_ext.dart'; import 'package:enaklo_pos/core/extensions/date_time_ext.dart';
import 'package:enaklo_pos/data/models/response/order_response_model.dart'; import 'package:enaklo_pos/data/models/response/order_response_model.dart';
@@ -10,66 +11,121 @@ class SalesOrderInformation extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
width: double.infinity,
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
decoration: BoxDecoration( decoration: BoxDecoration(
color: AppColors.white, color: AppColors.primary,
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Text(
'Informasi Pesanan', order?.orderNumber ?? "",
style: TextStyle( style: const TextStyle(
color: AppColors.black, color: Colors.white,
fontSize: 16, fontSize: 18,
fontWeight: FontWeight.w600, fontWeight: FontWeight.bold,
), ),
), ),
_item( _buildStatus(),
title: 'No. Order', ],
value: "${order?.orderNumber}",
), ),
_item( const SizedBox(height: 8),
title: 'Tanggal', Row(
value: (order?.createdAt ?? DateTime.now()).toFormattedDate2(), children: [
if (order?.orderType == 'dineIn') ...[
_buildRowItem(Icons.table_restaurant_outlined,
'Meja ${order?.tableNumber}'),
const SizedBox(width: 16),
],
_buildRowItem(Icons.restaurant_outlined, '${order?.orderType}'),
],
), ),
_item( const SizedBox(height: 8),
title: 'No. Meja', Text(
value: order?.tableNumber ?? "-", 'Pelanggan: ${order?.metadata?['customer_name'] ?? ""}',
style: const TextStyle(color: Colors.white, fontSize: 14),
), ),
_item( Text(
title: 'Jenis Order', 'Dibuat: ${order?.createdAt?.toFormattedDate3() ?? ""}',
value: order?.orderType ?? "-", style: const TextStyle(color: Colors.white70, fontSize: 12),
), ),
], ],
), ),
); );
} }
Padding _item({ Row _buildRowItem(IconData icon, String title) {
required String title, return Row(
required String value,
}) {
return Padding(
padding: const EdgeInsets.only(top: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Icon(
icon,
color: Colors.white70,
size: 16,
),
const SpaceWidth(4),
Text( Text(
title, title,
style: const TextStyle( style: const TextStyle(color: Colors.white70, fontSize: 14),
fontSize: 14,
),
),
Text(
value,
style: const TextStyle(
fontSize: 14,
),
), ),
], ],
);
}
Container _buildStatus() {
switch (order?.status) {
case 'pending':
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
decoration: BoxDecoration(
color: Colors.orange,
borderRadius: BorderRadius.circular(12),
),
child: Text(
(order?.status ?? "").toUpperCase(),
style: TextStyle(
color: Colors.white,
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
);
case 'completed':
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
decoration: BoxDecoration(
color: Colors.greenAccent,
borderRadius: BorderRadius.circular(12),
),
child: Text(
(order?.status ?? "").toUpperCase(),
style: TextStyle(
color: Colors.white,
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
);
default:
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
decoration: BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.circular(12),
),
child: Text(
(order?.status ?? "").toUpperCase(),
style: TextStyle(
color: Colors.white,
fontSize: 12,
fontWeight: FontWeight.bold,
),
), ),
); );
} }
}
} }
+143 -66
View File
@@ -1,7 +1,7 @@
import 'package:enaklo_pos/core/components/dashed_divider.dart';
import 'package:enaklo_pos/core/components/spaces.dart'; import 'package:enaklo_pos/core/components/spaces.dart';
import 'package:enaklo_pos/core/constants/colors.dart'; import 'package:enaklo_pos/core/constants/colors.dart';
import 'package:enaklo_pos/core/extensions/int_ext.dart'; import 'package:enaklo_pos/core/extensions/int_ext.dart';
import 'package:enaklo_pos/core/extensions/string_ext.dart';
import 'package:enaklo_pos/data/models/response/order_response_model.dart'; import 'package:enaklo_pos/data/models/response/order_response_model.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -12,88 +12,165 @@ class SalesPayment extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
width: double.infinity,
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
margin: const EdgeInsets.only(top: 16),
decoration: BoxDecoration( decoration: BoxDecoration(
color: AppColors.white, color: Colors.white,
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Text(
'Informasi Pesanan', 'Informasi Pembayaran',
style: TextStyle( style: TextStyle(
color: AppColors.black,
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w600, fontWeight: FontWeight.bold,
),
),
SpaceHeight(12),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Subtotal ${order?.orderItems?.length} Produk',
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
Text(
(order?.subtotal)?.currencyFormatRp ?? "0",
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
],
),
SpaceHeight(12),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Pajak',
style: const TextStyle(
fontSize: 16,
),
),
Text(
(order?.taxAmount)?.currencyFormatRp ?? "0",
style: const TextStyle(
fontSize: 16,
),
),
],
),
SpaceHeight(12),
DashedDivider(
color: AppColors.stroke,
),
SpaceHeight(12),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Total',
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w700,
),
),
Text(
(order?.totalAmount)?.currencyFormatRp ?? "0",
style: const TextStyle(
color: AppColors.primary, color: AppColors.primary,
fontSize: 18, ),
fontWeight: FontWeight.w700, ),
_buildPaymentStatus(),
],
),
const SpaceHeight(12),
...List.generate(
order?.payments?.length ?? 0,
(index) => Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: _buildPaymentItem(order?.payments?[index] ?? Payment()),
),
),
const SpaceHeight(4),
const Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Jumlah yang Dibayar',
style: TextStyle(color: Colors.grey.shade700),
),
Text(
(order?.totalPaid ?? 0).currencyFormatRpV2,
style: TextStyle(fontWeight: FontWeight.w500),
),
],
),
if (((order?.totalAmount ?? 0) - (order?.totalPaid ?? 0)) != 0) ...[
const SpaceHeight(4),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Sisa Tagihan',
style: TextStyle(
color: Colors.red.shade700,
fontWeight: FontWeight.w500,
),
),
Text(
((order?.totalAmount ?? 0) - (order?.totalPaid ?? 0))
.currencyFormatRpV2,
style: TextStyle(
color: Colors.red.shade700,
fontWeight: FontWeight.w500,
), ),
), ),
], ],
), ),
], ],
],
), ),
); );
} }
Container _buildPaymentStatus() {
switch (order?.paymentStatus) {
case 'completed':
return Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: AppColors.green.withOpacity(0.2),
borderRadius: BorderRadius.circular(4),
),
child: Text(
(order?.paymentStatus ?? "").toTitleCase(),
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.bold,
color: AppColors.green,
),
),
);
default:
return Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: Colors.amber.shade100,
borderRadius: BorderRadius.circular(4),
),
child: Text(
(order?.paymentStatus ?? "").toTitleCase(),
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.bold,
color: Colors.amber.shade800,
),
),
);
}
}
Row _buildPaymentItem(Payment payment) {
return Row(
children: [
Container(
width: 32,
height: 32,
decoration: BoxDecoration(
color: Colors.green.shade100,
borderRadius: BorderRadius.circular(4),
),
child: Icon(
Icons.payments,
color: Colors.green.shade700,
size: 16,
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
payment.paymentMethodName ?? "",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
),
),
if ((payment.splitTotal ?? 0) > 1)
Text(
'Split ${payment.splitNumber ?? 0} of ${payment.splitTotal ?? 0}',
style: TextStyle(
fontSize: 12,
color: Colors.grey.shade600,
),
),
],
),
),
Text(
(payment.amount ?? 0).currencyFormatRpV2,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: AppColors.green,
),
),
],
);
}
} }
@@ -0,0 +1,94 @@
import 'package:enaklo_pos/core/components/dashed_divider.dart';
import 'package:enaklo_pos/core/components/spaces.dart';
import 'package:enaklo_pos/core/constants/colors.dart';
import 'package:enaklo_pos/core/extensions/int_ext.dart';
import 'package:enaklo_pos/data/models/response/order_response_model.dart';
import 'package:flutter/material.dart';
class SalesPaymentSummary extends StatelessWidget {
final Order? order;
const SalesPaymentSummary({super.key, this.order});
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Ringkasan Pembayaran',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: AppColors.primary,
),
),
const SpaceHeight(12),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Subtotal',
style: TextStyle(color: Colors.grey.shade700),
),
Text((order?.subtotal ?? 0).currencyFormatRpV2),
],
),
const SpaceHeight(4),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Tax',
style: TextStyle(color: Colors.grey.shade700),
),
Text((order?.taxAmount ?? 0).currencyFormatRpV2),
],
),
const SpaceHeight(4),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Discount',
style: TextStyle(color: Colors.grey.shade700),
),
Text((order?.discountAmount ?? 0).currencyFormatRpV2),
],
),
const SpaceHeight(8),
const DashedDivider(
color: AppColors.grey,
),
const SpaceHeight(8),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'Total',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
Text(
(order?.totalAmount ?? 0).currencyFormatRpV2,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: AppColors.primary,
),
),
],
),
],
),
);
}
}
@@ -1,6 +1,7 @@
import 'dart:developer'; import 'dart:developer';
import 'package:enaklo_pos/core/components/flushbar.dart'; import 'package:enaklo_pos/core/components/flushbar.dart';
import 'package:enaklo_pos/core/components/spaces.dart';
import 'package:enaklo_pos/core/extensions/build_context_ext.dart'; import 'package:enaklo_pos/core/extensions/build_context_ext.dart';
import 'package:enaklo_pos/data/models/response/customer_response_model.dart'; import 'package:enaklo_pos/data/models/response/customer_response_model.dart';
import 'package:enaklo_pos/data/models/response/order_response_model.dart'; import 'package:enaklo_pos/data/models/response/order_response_model.dart';
@@ -39,6 +40,7 @@ class _SplitBillPageState extends State<SplitBillPage> {
// Per Amount Split Data // Per Amount Split Data
TextEditingController amountController = TextEditingController(); TextEditingController amountController = TextEditingController();
int splitAmount = 0; int splitAmount = 0;
int remainingAmount = 0;
List<OrderItem> getOrderItemPending() => List<OrderItem> getOrderItemPending() =>
widget.order.orderItems widget.order.orderItems
@@ -46,9 +48,24 @@ class _SplitBillPageState extends State<SplitBillPage> {
.toList() ?? .toList() ??
[]; [];
init() {
setState(() {
remainingAmount =
(widget.order.totalAmount ?? 0) - (widget.order.totalPaid ?? 0);
selectedSplitType = widget.order.splitType == 'AMOUNT' ? 1 : 0;
});
}
@override
void initState() {
init();
super.initState();
}
@override @override
void dispose() { void dispose() {
amountController.dispose(); amountController.dispose();
super.dispose(); super.dispose();
} }
@@ -160,6 +177,50 @@ class _SplitBillPageState extends State<SplitBillPage> {
), ),
SizedBox(height: 8), SizedBox(height: 8),
], ],
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Total terbayar',
style: TextStyle(
fontSize: 14,
color: AppColorSplitBill.textPrimary,
fontWeight: FontWeight.w600,
),
),
Text(
'Rp ${_formatCurrency(widget.order.totalPaid ?? 0)}',
style: TextStyle(
fontSize: 14,
color: AppColorSplitBill.textPrimary,
fontWeight: FontWeight.w600,
),
),
],
),
SizedBox(height: 2),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Sisa Tagihan',
style: TextStyle(
fontSize: 14,
color: Colors.red,
fontWeight: FontWeight.w600,
),
),
Text(
'Rp ${_formatCurrency(widget.order.remainingAmount ?? 0)}',
style: TextStyle(
fontSize: 14,
color: Colors.red,
fontWeight: FontWeight.w600,
),
),
],
),
SizedBox(height: 2),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
@@ -210,13 +271,7 @@ class _SplitBillPageState extends State<SplitBillPage> {
SizedBox(height: 24), SizedBox(height: 24),
// Split Type Selection // Split Type Selection
Row( _buildRowButtonSplit(),
children: [
_buildSplitTypeButton('Per Produk', 0),
SizedBox(width: 16),
_buildSplitTypeButton('Per Jumlah', 1),
],
),
SizedBox(height: 32), SizedBox(height: 32),
@@ -263,6 +318,23 @@ class _SplitBillPageState extends State<SplitBillPage> {
); );
} }
Widget _buildRowButtonSplit() {
switch (widget.order.splitType) {
case 'AMOUNT':
return _buildSplitTypeButton('Per Jumlah', 1);
case 'ITEM':
return _buildSplitTypeButton('Per Produk', 0);
default:
return Row(
children: [
_buildSplitTypeButton('Per Produk', 0),
SizedBox(width: 16),
_buildSplitTypeButton('Per Jumlah', 1),
],
);
}
}
Widget _buildCustomer(BuildContext context) { Widget _buildCustomer(BuildContext context) {
return Container( return Container(
padding: EdgeInsets.all(16), padding: EdgeInsets.all(16),
@@ -286,7 +358,9 @@ class _SplitBillPageState extends State<SplitBillPage> {
Widget _buildOrderItem(OrderItem item) { Widget _buildOrderItem(OrderItem item) {
return Container( return Container(
padding: EdgeInsets.symmetric(vertical: 12), padding: EdgeInsets.symmetric(vertical: 12),
child: Row( child: Column(
children: [
Row(
children: [ children: [
Expanded( Expanded(
child: Column( child: Column(
@@ -330,6 +404,59 @@ class _SplitBillPageState extends State<SplitBillPage> {
), ),
], ],
), ),
if ((item.paidQuantity ?? 0) > 1) ...[
SpaceHeight(6),
Align(
alignment: Alignment.centerRight,
child: Container(
padding:
const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(
color: AppColorSplitBill.primary.withOpacity(0.2),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: AppColorSplitBill.primary),
),
child: RichText(
text: TextSpan(
children: [
TextSpan(
text: '${item.paidQuantity} ',
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: AppColorSplitBill.primary,
),
),
TextSpan(
text: 'dari ',
style: const TextStyle(
fontSize: 12,
color: AppColorSplitBill.primary,
),
),
TextSpan(
text: '${item.quantity} ',
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: AppColorSplitBill.primary,
),
),
TextSpan(
text: 'kuantiti telah dibayar.',
style: const TextStyle(
fontSize: 12,
color: AppColorSplitBill.primary,
),
),
],
),
),
),
)
],
],
),
); );
} }
@@ -441,7 +568,7 @@ class _SplitBillPageState extends State<SplitBillPage> {
Widget _buildProductSplitItem(OrderItem item) { Widget _buildProductSplitItem(OrderItem item) {
int selectedQty = selectedProducts[item.id] ?? 0; int selectedQty = selectedProducts[item.id] ?? 0;
int maxQty = item.quantity ?? 0; int maxQty = (item.quantity ?? 0) - (item.paidQuantity ?? 0);
return Container( return Container(
margin: EdgeInsets.only(bottom: 12), margin: EdgeInsets.only(bottom: 12),
@@ -587,8 +714,7 @@ class _SplitBillPageState extends State<SplitBillPage> {
), ),
), ),
SizedBox(height: 16), SizedBox(height: 16),
Expanded( Column(
child: Column(
children: [ children: [
Container( Container(
padding: EdgeInsets.all(16), padding: EdgeInsets.all(16),
@@ -682,7 +808,7 @@ class _SplitBillPageState extends State<SplitBillPage> {
), ),
), ),
Text( Text(
'Rp ${_formatCurrency((widget.order.totalAmount ?? 0) - splitAmount)}', 'Rp ${_formatCurrency((remainingAmount) - splitAmount)}',
style: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
color: AppColorSplitBill.textSecondary, color: AppColorSplitBill.textSecondary,
@@ -695,7 +821,6 @@ class _SplitBillPageState extends State<SplitBillPage> {
), ),
], ],
), ),
),
], ],
); );
} }
@@ -799,7 +924,8 @@ class _SplitBillPageState extends State<SplitBillPage> {
} }
} else { } else {
// Per Amount Split // Per Amount Split
int totalAmount = widget.order.totalAmount ?? 0; int totalAmount =
(widget.order.totalAmount ?? 0) - (widget.order.totalPaid ?? 0);
if (splitAmount > 0 && splitAmount <= totalAmount) { if (splitAmount > 0 && splitAmount <= totalAmount) {
// Create split order object with the specified amount // Create split order object with the specified amount
@@ -538,7 +538,8 @@ class _SuccessOrderPageState extends State<SuccessOrderPage>
Widget _buildProductCard(int index) { Widget _buildProductCard(int index) {
final item = widget.productQuantity[index]; final item = widget.productQuantity[index];
final totalPrice = (item.product.price ?? 0) * item.quantity; final totalPrice = (item.product.price ?? 0) * item.quantity +
(item.variant?.priceModifier ?? 0);
return TweenAnimationBuilder<double>( return TweenAnimationBuilder<double>(
tween: Tween<double>(begin: 0.0, end: 1.0), tween: Tween<double>(begin: 0.0, end: 1.0),
@@ -634,7 +635,8 @@ class _SuccessOrderPageState extends State<SuccessOrderPage>
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
child: Text( child: Text(
(item.product.price ?? 0) ((item.product.price ?? 0) +
(item.variant?.priceModifier ?? 0))
.toString() .toString()
.currencyFormatRpV2, .currencyFormatRpV2,
style: TextStyle( style: TextStyle(
@@ -1,6 +1,7 @@
import 'package:enaklo_pos/core/constants/colors.dart'; import 'package:enaklo_pos/core/constants/colors.dart';
import 'package:enaklo_pos/core/extensions/build_context_ext.dart'; import 'package:enaklo_pos/core/extensions/build_context_ext.dart';
import 'package:enaklo_pos/core/extensions/date_time_ext.dart'; import 'package:enaklo_pos/core/extensions/date_time_ext.dart';
import 'package:enaklo_pos/core/extensions/int_ext.dart';
import 'package:enaklo_pos/core/extensions/string_ext.dart'; import 'package:enaklo_pos/core/extensions/string_ext.dart';
import 'package:enaklo_pos/core/function/app_function.dart'; import 'package:enaklo_pos/core/function/app_function.dart';
import 'package:enaklo_pos/data/models/response/order_response_model.dart'; import 'package:enaklo_pos/data/models/response/order_response_model.dart';
@@ -712,7 +713,7 @@ class _SuccessPaymentPageState extends State<SuccessPaymentPage> {
), ),
), ),
Text( Text(
(order.totalAmount ?? 0).toString().currencyFormatRpV2, widget.nominalBayar.currencyFormatRpV2,
style: const TextStyle( style: const TextStyle(
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@@ -886,7 +887,7 @@ class _SuccessPaymentPageState extends State<SuccessPaymentPage> {
], ],
), ),
Text( Text(
(order.totalAmount ?? 0).toString().currencyFormatRpV2, widget.nominalBayar.currencyFormatRpV2,
style: const TextStyle( style: const TextStyle(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@@ -964,7 +965,7 @@ class _SuccessPaymentPageState extends State<SuccessPaymentPage> {
], ],
), ),
child: Text( child: Text(
(order.totalAmount ?? 0).toString().currencyFormatRpV2, widget.nominalBayar.currencyFormatRpV2,
style: const TextStyle( style: const TextStyle(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@@ -24,12 +24,27 @@ class SuccessSaveOrderPage extends StatefulWidget {
} }
class _SuccessSaveOrderPageState extends State<SuccessSaveOrderPage> { class _SuccessSaveOrderPageState extends State<SuccessSaveOrderPage> {
int totalPrice = 0;
getPrice() {
setState(() {
totalPrice = widget.productQuantity.fold(
0,
(previousValue, element) =>
previousValue +
(element.product.price! * element.quantity) +
(element.variant?.priceModifier ?? 0),
);
});
}
@override @override
void initState() { void initState() {
super.initState(); super.initState();
context context
.read<OrderLoaderBloc>() .read<OrderLoaderBloc>()
.add(OrderLoaderEvent.getById(widget.orderId)); .add(OrderLoaderEvent.getById(widget.orderId));
getPrice();
} }
@override @override
@@ -380,7 +395,8 @@ class _SuccessSaveOrderPageState extends State<SuccessSaveOrderPage> {
Widget _buildProductCard(int index) { Widget _buildProductCard(int index) {
final item = widget.productQuantity[index]; final item = widget.productQuantity[index];
final totalPrice = (item.product.price ?? 0) * item.quantity; final totalPrice = (item.product.price ?? 0) * item.quantity +
(item.variant?.priceModifier ?? 0);
return Container( return Container(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
@@ -464,7 +480,10 @@ class _SuccessSaveOrderPageState extends State<SuccessSaveOrderPage> {
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
child: Text( child: Text(
(item.product.price ?? 0).toString().currencyFormatRpV2, ((item.product.price ?? 0) +
(item.variant?.priceModifier ?? 0))
.toString()
.currencyFormatRpV2,
style: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
color: Colors.grey.shade700, color: Colors.grey.shade700,
@@ -707,7 +726,7 @@ class _SuccessSaveOrderPageState extends State<SuccessSaveOrderPage> {
), ),
), ),
Text( Text(
(order.totalAmount ?? 0).toString().currencyFormatRpV2, totalPrice.toString().currencyFormatRpV2,
style: const TextStyle( style: const TextStyle(
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@@ -876,7 +895,7 @@ class _SuccessSaveOrderPageState extends State<SuccessSaveOrderPage> {
], ],
), ),
Text( Text(
(order.totalAmount ?? 0).toString().currencyFormatRpV2, totalPrice.toString().currencyFormatRpV2,
style: const TextStyle( style: const TextStyle(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@@ -954,7 +973,7 @@ class _SuccessSaveOrderPageState extends State<SuccessSaveOrderPage> {
], ],
), ),
child: Text( child: Text(
(order.totalAmount ?? 0).toString().currencyFormatRpV2, totalPrice.toString().currencyFormatRpV2,
style: const TextStyle( style: const TextStyle(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@@ -0,0 +1,26 @@
import 'package:bloc/bloc.dart';
import 'package:enaklo_pos/data/datasources/table_remote_datasource.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'transfer_table_event.dart';
part 'transfer_table_state.dart';
part 'transfer_table_bloc.freezed.dart';
class TransferTableBloc extends Bloc<TransferTableEvent, TransferTableState> {
final TableRemoteDataSource _dataSource;
TransferTableBloc(this._dataSource) : super(TransferTableState.initial()) {
on<_TransferTable>((event, emit) async {
emit(_Loading());
final result = await _dataSource.transferTable(
fromTableId: event.fromTableId,
toTableId: event.toTableId,
);
result.fold(
(l) => emit(_Error(l)),
(r) => emit(_Success()),
);
});
}
}
@@ -0,0 +1,832 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'transfer_table_bloc.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
/// @nodoc
mixin _$TransferTableEvent {
String get fromTableId => throw _privateConstructorUsedError;
String get toTableId => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(String fromTableId, String toTableId)
transferTable,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(String fromTableId, String toTableId)? transferTable,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(String fromTableId, String toTableId)? transferTable,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_TransferTable value) transferTable,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_TransferTable value)? transferTable,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_TransferTable value)? transferTable,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
/// Create a copy of TransferTableEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$TransferTableEventCopyWith<TransferTableEvent> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $TransferTableEventCopyWith<$Res> {
factory $TransferTableEventCopyWith(
TransferTableEvent value, $Res Function(TransferTableEvent) then) =
_$TransferTableEventCopyWithImpl<$Res, TransferTableEvent>;
@useResult
$Res call({String fromTableId, String toTableId});
}
/// @nodoc
class _$TransferTableEventCopyWithImpl<$Res, $Val extends TransferTableEvent>
implements $TransferTableEventCopyWith<$Res> {
_$TransferTableEventCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of TransferTableEvent
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? fromTableId = null,
Object? toTableId = null,
}) {
return _then(_value.copyWith(
fromTableId: null == fromTableId
? _value.fromTableId
: fromTableId // ignore: cast_nullable_to_non_nullable
as String,
toTableId: null == toTableId
? _value.toTableId
: toTableId // ignore: cast_nullable_to_non_nullable
as String,
) as $Val);
}
}
/// @nodoc
abstract class _$$TransferTableImplCopyWith<$Res>
implements $TransferTableEventCopyWith<$Res> {
factory _$$TransferTableImplCopyWith(
_$TransferTableImpl value, $Res Function(_$TransferTableImpl) then) =
__$$TransferTableImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({String fromTableId, String toTableId});
}
/// @nodoc
class __$$TransferTableImplCopyWithImpl<$Res>
extends _$TransferTableEventCopyWithImpl<$Res, _$TransferTableImpl>
implements _$$TransferTableImplCopyWith<$Res> {
__$$TransferTableImplCopyWithImpl(
_$TransferTableImpl _value, $Res Function(_$TransferTableImpl) _then)
: super(_value, _then);
/// Create a copy of TransferTableEvent
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? fromTableId = null,
Object? toTableId = null,
}) {
return _then(_$TransferTableImpl(
fromTableId: null == fromTableId
? _value.fromTableId
: fromTableId // ignore: cast_nullable_to_non_nullable
as String,
toTableId: null == toTableId
? _value.toTableId
: toTableId // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
class _$TransferTableImpl implements _TransferTable {
const _$TransferTableImpl(
{required this.fromTableId, required this.toTableId});
@override
final String fromTableId;
@override
final String toTableId;
@override
String toString() {
return 'TransferTableEvent.transferTable(fromTableId: $fromTableId, toTableId: $toTableId)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$TransferTableImpl &&
(identical(other.fromTableId, fromTableId) ||
other.fromTableId == fromTableId) &&
(identical(other.toTableId, toTableId) ||
other.toTableId == toTableId));
}
@override
int get hashCode => Object.hash(runtimeType, fromTableId, toTableId);
/// Create a copy of TransferTableEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$TransferTableImplCopyWith<_$TransferTableImpl> get copyWith =>
__$$TransferTableImplCopyWithImpl<_$TransferTableImpl>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(String fromTableId, String toTableId)
transferTable,
}) {
return transferTable(fromTableId, toTableId);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(String fromTableId, String toTableId)? transferTable,
}) {
return transferTable?.call(fromTableId, toTableId);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(String fromTableId, String toTableId)? transferTable,
required TResult orElse(),
}) {
if (transferTable != null) {
return transferTable(fromTableId, toTableId);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_TransferTable value) transferTable,
}) {
return transferTable(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_TransferTable value)? transferTable,
}) {
return transferTable?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_TransferTable value)? transferTable,
required TResult orElse(),
}) {
if (transferTable != null) {
return transferTable(this);
}
return orElse();
}
}
abstract class _TransferTable implements TransferTableEvent {
const factory _TransferTable(
{required final String fromTableId,
required final String toTableId}) = _$TransferTableImpl;
@override
String get fromTableId;
@override
String get toTableId;
/// Create a copy of TransferTableEvent
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$TransferTableImplCopyWith<_$TransferTableImpl> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
mixin _$TransferTableState {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() loading,
required TResult Function() success,
required TResult Function(String message) error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? initial,
TResult? Function()? loading,
TResult? Function()? success,
TResult? Function(String message)? error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? loading,
TResult Function()? success,
TResult Function(String message)? error,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_Initial value) initial,
required TResult Function(_Loading value) loading,
required TResult Function(_Success value) success,
required TResult Function(_Error value) error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_Initial value)? initial,
TResult? Function(_Loading value)? loading,
TResult? Function(_Success value)? success,
TResult? Function(_Error value)? error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_Initial value)? initial,
TResult Function(_Loading value)? loading,
TResult Function(_Success value)? success,
TResult Function(_Error value)? error,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $TransferTableStateCopyWith<$Res> {
factory $TransferTableStateCopyWith(
TransferTableState value, $Res Function(TransferTableState) then) =
_$TransferTableStateCopyWithImpl<$Res, TransferTableState>;
}
/// @nodoc
class _$TransferTableStateCopyWithImpl<$Res, $Val extends TransferTableState>
implements $TransferTableStateCopyWith<$Res> {
_$TransferTableStateCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of TransferTableState
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
abstract class _$$InitialImplCopyWith<$Res> {
factory _$$InitialImplCopyWith(
_$InitialImpl value, $Res Function(_$InitialImpl) then) =
__$$InitialImplCopyWithImpl<$Res>;
}
/// @nodoc
class __$$InitialImplCopyWithImpl<$Res>
extends _$TransferTableStateCopyWithImpl<$Res, _$InitialImpl>
implements _$$InitialImplCopyWith<$Res> {
__$$InitialImplCopyWithImpl(
_$InitialImpl _value, $Res Function(_$InitialImpl) _then)
: super(_value, _then);
/// Create a copy of TransferTableState
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
class _$InitialImpl implements _Initial {
const _$InitialImpl();
@override
String toString() {
return 'TransferTableState.initial()';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType && other is _$InitialImpl);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() loading,
required TResult Function() success,
required TResult Function(String message) error,
}) {
return initial();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? initial,
TResult? Function()? loading,
TResult? Function()? success,
TResult? Function(String message)? error,
}) {
return initial?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? loading,
TResult Function()? success,
TResult Function(String message)? error,
required TResult orElse(),
}) {
if (initial != null) {
return initial();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_Initial value) initial,
required TResult Function(_Loading value) loading,
required TResult Function(_Success value) success,
required TResult Function(_Error value) error,
}) {
return initial(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_Initial value)? initial,
TResult? Function(_Loading value)? loading,
TResult? Function(_Success value)? success,
TResult? Function(_Error value)? error,
}) {
return initial?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_Initial value)? initial,
TResult Function(_Loading value)? loading,
TResult Function(_Success value)? success,
TResult Function(_Error value)? error,
required TResult orElse(),
}) {
if (initial != null) {
return initial(this);
}
return orElse();
}
}
abstract class _Initial implements TransferTableState {
const factory _Initial() = _$InitialImpl;
}
/// @nodoc
abstract class _$$LoadingImplCopyWith<$Res> {
factory _$$LoadingImplCopyWith(
_$LoadingImpl value, $Res Function(_$LoadingImpl) then) =
__$$LoadingImplCopyWithImpl<$Res>;
}
/// @nodoc
class __$$LoadingImplCopyWithImpl<$Res>
extends _$TransferTableStateCopyWithImpl<$Res, _$LoadingImpl>
implements _$$LoadingImplCopyWith<$Res> {
__$$LoadingImplCopyWithImpl(
_$LoadingImpl _value, $Res Function(_$LoadingImpl) _then)
: super(_value, _then);
/// Create a copy of TransferTableState
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
class _$LoadingImpl implements _Loading {
const _$LoadingImpl();
@override
String toString() {
return 'TransferTableState.loading()';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType && other is _$LoadingImpl);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() loading,
required TResult Function() success,
required TResult Function(String message) error,
}) {
return loading();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? initial,
TResult? Function()? loading,
TResult? Function()? success,
TResult? Function(String message)? error,
}) {
return loading?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? loading,
TResult Function()? success,
TResult Function(String message)? error,
required TResult orElse(),
}) {
if (loading != null) {
return loading();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_Initial value) initial,
required TResult Function(_Loading value) loading,
required TResult Function(_Success value) success,
required TResult Function(_Error value) error,
}) {
return loading(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_Initial value)? initial,
TResult? Function(_Loading value)? loading,
TResult? Function(_Success value)? success,
TResult? Function(_Error value)? error,
}) {
return loading?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_Initial value)? initial,
TResult Function(_Loading value)? loading,
TResult Function(_Success value)? success,
TResult Function(_Error value)? error,
required TResult orElse(),
}) {
if (loading != null) {
return loading(this);
}
return orElse();
}
}
abstract class _Loading implements TransferTableState {
const factory _Loading() = _$LoadingImpl;
}
/// @nodoc
abstract class _$$SuccessImplCopyWith<$Res> {
factory _$$SuccessImplCopyWith(
_$SuccessImpl value, $Res Function(_$SuccessImpl) then) =
__$$SuccessImplCopyWithImpl<$Res>;
}
/// @nodoc
class __$$SuccessImplCopyWithImpl<$Res>
extends _$TransferTableStateCopyWithImpl<$Res, _$SuccessImpl>
implements _$$SuccessImplCopyWith<$Res> {
__$$SuccessImplCopyWithImpl(
_$SuccessImpl _value, $Res Function(_$SuccessImpl) _then)
: super(_value, _then);
/// Create a copy of TransferTableState
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
class _$SuccessImpl implements _Success {
const _$SuccessImpl();
@override
String toString() {
return 'TransferTableState.success()';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType && other is _$SuccessImpl);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() loading,
required TResult Function() success,
required TResult Function(String message) error,
}) {
return success();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? initial,
TResult? Function()? loading,
TResult? Function()? success,
TResult? Function(String message)? error,
}) {
return success?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? loading,
TResult Function()? success,
TResult Function(String message)? error,
required TResult orElse(),
}) {
if (success != null) {
return success();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_Initial value) initial,
required TResult Function(_Loading value) loading,
required TResult Function(_Success value) success,
required TResult Function(_Error value) error,
}) {
return success(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_Initial value)? initial,
TResult? Function(_Loading value)? loading,
TResult? Function(_Success value)? success,
TResult? Function(_Error value)? error,
}) {
return success?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_Initial value)? initial,
TResult Function(_Loading value)? loading,
TResult Function(_Success value)? success,
TResult Function(_Error value)? error,
required TResult orElse(),
}) {
if (success != null) {
return success(this);
}
return orElse();
}
}
abstract class _Success implements TransferTableState {
const factory _Success() = _$SuccessImpl;
}
/// @nodoc
abstract class _$$ErrorImplCopyWith<$Res> {
factory _$$ErrorImplCopyWith(
_$ErrorImpl value, $Res Function(_$ErrorImpl) then) =
__$$ErrorImplCopyWithImpl<$Res>;
@useResult
$Res call({String message});
}
/// @nodoc
class __$$ErrorImplCopyWithImpl<$Res>
extends _$TransferTableStateCopyWithImpl<$Res, _$ErrorImpl>
implements _$$ErrorImplCopyWith<$Res> {
__$$ErrorImplCopyWithImpl(
_$ErrorImpl _value, $Res Function(_$ErrorImpl) _then)
: super(_value, _then);
/// Create a copy of TransferTableState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? message = null,
}) {
return _then(_$ErrorImpl(
null == message
? _value.message
: message // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
class _$ErrorImpl implements _Error {
const _$ErrorImpl(this.message);
@override
final String message;
@override
String toString() {
return 'TransferTableState.error(message: $message)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ErrorImpl &&
(identical(other.message, message) || other.message == message));
}
@override
int get hashCode => Object.hash(runtimeType, message);
/// Create a copy of TransferTableState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$ErrorImplCopyWith<_$ErrorImpl> get copyWith =>
__$$ErrorImplCopyWithImpl<_$ErrorImpl>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() loading,
required TResult Function() success,
required TResult Function(String message) error,
}) {
return error(message);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? initial,
TResult? Function()? loading,
TResult? Function()? success,
TResult? Function(String message)? error,
}) {
return error?.call(message);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? loading,
TResult Function()? success,
TResult Function(String message)? error,
required TResult orElse(),
}) {
if (error != null) {
return error(message);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_Initial value) initial,
required TResult Function(_Loading value) loading,
required TResult Function(_Success value) success,
required TResult Function(_Error value) error,
}) {
return error(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_Initial value)? initial,
TResult? Function(_Loading value)? loading,
TResult? Function(_Success value)? success,
TResult? Function(_Error value)? error,
}) {
return error?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_Initial value)? initial,
TResult Function(_Loading value)? loading,
TResult Function(_Success value)? success,
TResult Function(_Error value)? error,
required TResult orElse(),
}) {
if (error != null) {
return error(this);
}
return orElse();
}
}
abstract class _Error implements TransferTableState {
const factory _Error(final String message) = _$ErrorImpl;
String get message;
/// Create a copy of TransferTableState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
_$$ErrorImplCopyWith<_$ErrorImpl> get copyWith =>
throw _privateConstructorUsedError;
}
@@ -0,0 +1,8 @@
part of 'transfer_table_bloc.dart';
@freezed
class TransferTableEvent with _$TransferTableEvent {
const factory TransferTableEvent.transferTable(
{required String fromTableId,
required String toTableId}) = _TransferTable;
}
@@ -0,0 +1,9 @@
part of 'transfer_table_bloc.dart';
@freezed
class TransferTableState with _$TransferTableState {
const factory TransferTableState.initial() = _Initial;
const factory TransferTableState.loading() = _Loading;
const factory TransferTableState.success() = _Success;
const factory TransferTableState.error(String message) = _Error;
}
@@ -0,0 +1,319 @@
import 'dart:developer';
import 'package:dropdown_search/dropdown_search.dart';
import 'package:enaklo_pos/core/components/buttons.dart';
import 'package:enaklo_pos/core/components/custom_modal_dialog.dart';
import 'package:enaklo_pos/core/components/flushbar.dart';
import 'package:enaklo_pos/core/components/spaces.dart';
import 'package:enaklo_pos/core/constants/colors.dart';
import 'package:enaklo_pos/core/extensions/build_context_ext.dart';
import 'package:enaklo_pos/data/models/response/table_model.dart';
import 'package:enaklo_pos/presentation/home/bloc/get_table_status/get_table_status_bloc.dart';
import 'package:enaklo_pos/presentation/table/blocs/transfer_table/transfer_table_bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class TransferTableDialog extends StatefulWidget {
final TableModel fromTable;
const TransferTableDialog({
super.key,
required this.fromTable,
});
@override
State<TransferTableDialog> createState() => _TransferTableDialogState();
}
class _TransferTableDialogState extends State<TransferTableDialog> {
TableModel? selectTable;
@override
void initState() {
super.initState();
context
.read<GetTableStatusBloc>()
.add(GetTableStatusEvent.getTablesStatus('available'));
}
@override
Widget build(BuildContext context) {
return BlocListener<TransferTableBloc, TransferTableState>(
listener: (context, state) {
state.maybeWhen(
orElse: () {},
success: () {
context.pop();
},
);
},
child: CustomModalDialog(
title: 'Transfer Meja',
subtitle: 'Pilih meja yang tersedia',
contentPadding:
const EdgeInsets.symmetric(horizontal: 16.0, vertical: 24.0),
minWidth: context.deviceWidth * 0.4,
minHeight: context.deviceHeight * 0.4,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Pilih Meja',
style: TextStyle(
color: AppColors.black,
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
const SpaceHeight(6.0),
BlocBuilder<GetTableStatusBloc, GetTableStatusState>(
builder: (context, state) {
return state.maybeWhen(
orElse: () =>
Center(child: const CircularProgressIndicator()),
loading: () =>
Center(child: const CircularProgressIndicator()),
success: (tables) {
final availableTables = tables;
if (selectTable == null && availableTables.isNotEmpty) {
selectTable = availableTables.first;
}
if (availableTables.isEmpty) {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.orange[50],
borderRadius: BorderRadius.circular(16),
border: Border.all(
color: Colors.orange,
width: 1,
),
),
child: const Text(
'Tidak ada meja yang tersedia. Silakan pilih opsi lain.',
style: TextStyle(color: Colors.orange),
),
);
}
return DropdownSearch<TableModel>(
items: tables,
selectedItem: selectTable,
// Dropdown properties
dropdownDecoratorProps: DropDownDecoratorProps(
dropdownSearchDecoration: InputDecoration(
hintText: "Pilih meja",
hintStyle: TextStyle(
color: Colors.grey.shade600,
fontSize: 14,
),
prefixIcon: Icon(
Icons.category_outlined,
color: Colors.grey.shade500,
size: 20,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(
color: Colors.grey.shade300,
width: 1.5,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(
color: Colors.grey.shade300,
width: 1.5,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(
color: Colors.blue.shade400,
width: 2,
),
),
filled: true,
fillColor: Colors.white,
contentPadding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 16,
),
),
),
// Popup properties
popupProps: PopupProps.menu(
showSearchBox: true,
searchFieldProps: TextFieldProps(
decoration: InputDecoration(
hintText: "Cari meja...",
prefixIcon: const Icon(Icons.search),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
contentPadding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 12,
),
),
),
menuProps: MenuProps(
backgroundColor: Colors.white,
elevation: 8,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
itemBuilder: (context, category, isSelected) {
return Container(
padding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 12,
),
decoration: BoxDecoration(
color: isSelected
? Colors.blue.shade50
: Colors.transparent,
border: Border(
bottom: BorderSide(
color: Colors.grey.shade100,
width: 0.5,
),
),
),
child: Row(
children: [
Container(
width: 8,
height: 8,
decoration: BoxDecoration(
color: isSelected
? Colors.blue.shade600
: Colors.grey.shade400,
shape: BoxShape.circle,
),
),
const SizedBox(width: 12),
Expanded(
child: Text(
category.tableName ?? "",
style: TextStyle(
fontSize: 14,
fontWeight: isSelected
? FontWeight.w600
: FontWeight.w500,
color: isSelected
? Colors.blue.shade700
: Colors.black87,
),
),
),
if (isSelected)
Icon(
Icons.check,
color: Colors.blue.shade600,
size: 18,
),
],
),
);
},
emptyBuilder: (context, searchEntry) {
return Container(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.search_off,
color: Colors.grey.shade400,
size: 48,
),
const SizedBox(height: 12),
Text(
searchEntry.isEmpty
? "Tidak ada meja tersedia"
: "Tidak ditemukan meja dengan '${searchEntry}'",
style: TextStyle(
color: Colors.grey.shade600,
fontSize: 14,
),
textAlign: TextAlign.center,
),
],
),
);
},
),
// Item as string (for search functionality)
itemAsString: (TableModel table) =>
table.tableName ?? "",
// Comparison function
compareFn: (TableModel? item1, TableModel? item2) {
return item1?.id == item2?.id;
},
// On changed callback
onChanged: (TableModel? selectedTable) {
if (selectedTable != null) {
setState(() {
selectTable = selectedTable;
});
log("selectTable: ${selectTable!.tableName}");
}
},
// Validator (optional)
validator: (TableModel? value) {
if (value == null) {
return "Meja harus dipilih";
}
return null;
},
);
},
);
}),
],
),
SpaceHeight(24),
BlocBuilder<TransferTableBloc, TransferTableState>(
builder: (context, state) {
return state.maybeWhen(
orElse: () => Button.filled(
onPressed: () {
if (selectTable == null) {
AppFlushbar.showError(
context, 'Silahkan Pilih Meja Tujuan');
return;
}
context.read<TransferTableBloc>().add(
TransferTableEvent.transferTable(
fromTableId: widget.fromTable.id ?? "",
toTableId: selectTable!.id ?? "",
),
);
},
label: "Transfer",
),
loading: () => Center(
child: const CircularProgressIndicator(),
),
);
},
),
],
),
),
);
}
}
+81 -24
View File
@@ -1,3 +1,4 @@
import 'package:enaklo_pos/core/components/flushbar.dart';
import 'package:enaklo_pos/core/constants/colors.dart'; import 'package:enaklo_pos/core/constants/colors.dart';
import 'package:enaklo_pos/core/extensions/build_context_ext.dart'; import 'package:enaklo_pos/core/extensions/build_context_ext.dart';
import 'package:enaklo_pos/data/models/response/table_model.dart'; import 'package:enaklo_pos/data/models/response/table_model.dart';
@@ -5,7 +6,9 @@ import 'package:enaklo_pos/presentation/home/pages/dashboard_page.dart';
import 'package:enaklo_pos/presentation/table/blocs/change_position_table/change_position_table_bloc.dart'; import 'package:enaklo_pos/presentation/table/blocs/change_position_table/change_position_table_bloc.dart';
import 'package:enaklo_pos/presentation/table/blocs/create_table/create_table_bloc.dart'; import 'package:enaklo_pos/presentation/table/blocs/create_table/create_table_bloc.dart';
import 'package:enaklo_pos/presentation/table/blocs/get_table/get_table_bloc.dart'; import 'package:enaklo_pos/presentation/table/blocs/get_table/get_table_bloc.dart';
import 'package:enaklo_pos/presentation/table/blocs/transfer_table/transfer_table_bloc.dart';
import 'package:enaklo_pos/presentation/table/dialogs/form_table_new_dialog.dart'; import 'package:enaklo_pos/presentation/table/dialogs/form_table_new_dialog.dart';
import 'package:enaklo_pos/presentation/table/dialogs/transfer_table_dialog.dart';
import 'package:enaklo_pos/presentation/table/widgets/table_widget.dart'; import 'package:enaklo_pos/presentation/table/widgets/table_widget.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
@@ -41,8 +44,11 @@ class _TablePageState extends State<TablePage> {
// Untuk drag // Untuk drag
TableModel? draggingTable; TableModel? draggingTable;
Offset? _tapPosition;
// Ubah function toggleSelectTable menjadi selectTable // Ubah function toggleSelectTable menjadi selectTable
void selectTable(TableModel table) { void selectTable(TableModel table) {
if (table.status == 'occupied') return;
setState(() { setState(() {
if (selectedTable == table) { if (selectedTable == table) {
selectedTable = null; // Deselect jika table yang sama diklik selectedTable = null; // Deselect jika table yang sama diklik
@@ -111,10 +117,24 @@ class _TablePageState extends State<TablePage> {
), ),
), ),
backgroundColor: const Color(0xFFF7F8FA), backgroundColor: const Color(0xFFF7F8FA),
body: BlocBuilder<GetTableBloc, GetTableState>( body: BlocListener<TransferTableBloc, TransferTableState>(
listener: (context, state) {
state.maybeWhen(
orElse: () {},
success: () {
AppFlushbar.showSuccess(context, 'Transfer Table Success');
context.read<GetTableBloc>().add(const GetTableEvent.getTables());
},
error: (message) {
AppFlushbar.showError(context, message);
},
);
},
child: BlocBuilder<GetTableBloc, GetTableState>(
builder: (context, state) { builder: (context, state) {
return state.maybeWhen( return state.maybeWhen(
orElse: () => SizedBox.shrink(), orElse: () => SizedBox.shrink(),
loading: () => const Center(child: CircularProgressIndicator()),
success: (tables) => SafeArea( success: (tables) => SafeArea(
child: Stack( child: Stack(
children: [ children: [
@@ -191,7 +211,8 @@ class _TablePageState extends State<TablePage> {
draggingTable = table; draggingTable = table;
}); });
}, },
onDraggableCanceled: (velocity, offset) { onDraggableCanceled:
(velocity, offset) {
setState(() { setState(() {
draggingTable = null; draggingTable = null;
}); });
@@ -199,26 +220,36 @@ class _TablePageState extends State<TablePage> {
onDragEnd: (details) { onDragEnd: (details) {
setState(() { setState(() {
draggingTable = null; draggingTable = null;
final RenderBox box = context final RenderBox box =
.findRenderObject() as RenderBox; context.findRenderObject()
final Offset local = as RenderBox;
box.globalToLocal(details.offset); final Offset local = box
table.positionX = .globalToLocal(details.offset);
local.dx.clamp(0, mapWidth - 120); table.positionX = local.dx
table.positionY = .clamp(0, mapWidth - 120);
local.dy.clamp(0, mapHeight - 80); table.positionY = local.dy
.clamp(0, mapHeight - 80);
});
context context
.read<ChangePositionTableBloc>() .read<ChangePositionTableBloc>()
.add(ChangePositionTableEvent .add(ChangePositionTableEvent
.changePositionTable( .changePositionTable(
tableId: table.id ?? "", tableId: table.id ?? "",
position: details.offset, position: Offset(
table.positionX ?? 0.0,
table.positionY ?? 0.0,
),
)); ));
});
}, },
child: GestureDetector( child: GestureDetector(
onTap: () => selectTable(table), onTap: () => selectTable(table),
onTapDown: (details) => _tapPosition =
details.globalPosition,
onLongPress: () {
if (table.status == 'occupied') {
_showPopupMenu(context, table);
}
},
child: TableWidget( child: TableWidget(
table: table, table: table,
isSelected: isSelected, isSelected: isSelected,
@@ -244,6 +275,7 @@ class _TablePageState extends State<TablePage> {
); );
}, },
), ),
),
); );
} }
@@ -362,17 +394,7 @@ class _TablePageState extends State<TablePage> {
context.push(DashboardPage( context.push(DashboardPage(
table: selectedTable!, table: selectedTable!,
)); ));
} else { } else {}
// Handle occupied table click - load draft order and navigate to payment
// context.read<CheckoutBloc>().add(
// CheckoutEvent.loadDraftOrder(data!),
// );
// log("Data Draft Order: ${data!.toMap()}");
// context.push(PaymentTablePage(
// table: widget.table,
// draftOrder: data!,
// ));
}
}, },
child: const Text( child: const Text(
"Tempatkan Pesanan", "Tempatkan Pesanan",
@@ -397,4 +419,39 @@ class _TablePageState extends State<TablePage> {
], ],
); );
} }
void _showPopupMenu(BuildContext context, TableModel table) {
final RenderBox overlay =
Overlay.of(context).context.findRenderObject() as RenderBox;
showMenu(
context: context,
position: RelativeRect.fromRect(
_tapPosition != null
? Rect.fromLTWH(_tapPosition!.dx, _tapPosition!.dy, 0, 0)
: Rect.fromLTWH(100, 100, 0, 0),
Offset.zero & overlay.size,
),
color: AppColors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
elevation: 1,
items: [
PopupMenuItem(
onTap: () {
showDialog(
context: context,
builder: (context) => TransferTableDialog(fromTable: table),
);
},
child: Row(
children: [
Icon(Icons.swap_horiz),
SizedBox(width: 8),
Text('Transfer'),
],
),
),
],
);
}
} }
@@ -11,18 +11,28 @@ class TableWidget extends StatelessWidget {
// Fungsi untuk menentukan jumlah kursi di tiap sisi // Fungsi untuk menentukan jumlah kursi di tiap sisi
Map<String, int> getChairDistribution(int capacity) { Map<String, int> getChairDistribution(int capacity) {
if (capacity == 2) { if (capacity == 1) {
return {'top': 0, 'bottom': 0, 'left': 1, 'right': 0};
} else if (capacity == 2) {
return {'top': 0, 'bottom': 0, 'left': 1, 'right': 1}; return {'top': 0, 'bottom': 0, 'left': 1, 'right': 1};
} else if (capacity == 3) {
return {'top': 1, 'bottom': 0, 'left': 1, 'right': 1};
} else if (capacity == 4) { } else if (capacity == 4) {
return {'top': 1, 'bottom': 1, 'left': 1, 'right': 1}; return {'top': 1, 'bottom': 1, 'left': 1, 'right': 1};
} else if (capacity == 5) {
return {'top': 2, 'bottom': 1, 'left': 1, 'right': 1};
} else if (capacity == 6) { } else if (capacity == 6) {
return {'top': 2, 'bottom': 2, 'left': 1, 'right': 1}; return {'top': 2, 'bottom': 2, 'left': 1, 'right': 1};
} else if (capacity == 7) {
return {'top': 3, 'bottom': 2, 'left': 1, 'right': 1};
} else if (capacity == 8) { } else if (capacity == 8) {
return {'top': 3, 'bottom': 3, 'left': 1, 'right': 1}; return {'top': 3, 'bottom': 3, 'left': 1, 'right': 1};
} else if (capacity == 9) {
return {'top': 4, 'bottom': 3, 'left': 1, 'right': 1};
} else if (capacity == 10) { } else if (capacity == 10) {
return {'top': 4, 'bottom': 4, 'left': 1, 'right': 1}; return {'top': 4, 'bottom': 4, 'left': 1, 'right': 1};
} else { } else {
int side = (capacity / 4).floor(); int side = ((capacity - 2) / 2).floor();
return {'top': side, 'bottom': side, 'left': 1, 'right': 1}; return {'top': side, 'bottom': side, 'left': 1, 'right': 1};
} }
} }
@@ -73,14 +83,22 @@ class TableWidget extends StatelessWidget {
); );
return Container( return Container(
width: 120, width: (table.capacity ?? 0) > 16
? 240
: (table.capacity ?? 0) > 8
? 180
: 120,
height: 80, height: 80,
child: Stack( child: Stack(
alignment: Alignment.center, alignment: Alignment.center,
children: [ children: [
// Meja utama // Meja utama
Container( Container(
width: 100, width: (table.capacity ?? 0) > 16
? 220
: (table.capacity ?? 0) > 8
? 160
: 100,
height: 60, height: 60,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
+29 -42
View File
@@ -5,23 +5,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: _fe_analyzer_shared name: _fe_analyzer_shared
sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab" sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "76.0.0" version: "67.0.0"
_macros:
dependency: transitive
description: dart
source: sdk
version: "0.3.3"
analyzer: analyzer:
dependency: transitive dependency: transitive
description: description:
name: analyzer name: analyzer
sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e" sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.11.0" version: "6.4.1"
another_flushbar: another_flushbar:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -106,10 +101,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: build name: build
sha256: cef23f1eda9b57566c81e2133d196f8e3df48f244b317368d65c5943d91148f0 sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.2" version: "2.4.1"
build_config: build_config:
dependency: transitive dependency: transitive
description: description:
@@ -130,26 +125,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: build_resolvers name: build_resolvers
sha256: "99d3980049739a985cf9b21f30881f46db3ebc62c5b8d5e60e27440876b1ba1e" sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.3" version: "2.4.2"
build_runner: build_runner:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: build_runner name: build_runner
sha256: "74691599a5bc750dc96a6b4bfd48f7d9d66453eab04c7f4063134800d6a5c573" sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.14" version: "2.4.13"
build_runner_core: build_runner_core:
dependency: transitive dependency: transitive
description: description:
name: build_runner_core name: build_runner_core
sha256: "22e3aa1c80e0ada3722fe5b63fd43d9c8990759d0a2cf489c8c5d7b2bdebc021" sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.0.0" version: "7.3.2"
built_collection: built_collection:
dependency: transitive dependency: transitive
description: description:
@@ -314,10 +309,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: dart_style name: dart_style
sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab" sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.7" version: "2.3.6"
dartx: dartx:
dependency: transitive dependency: transitive
description: description:
@@ -585,10 +580,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: freezed name: freezed
sha256: "44c19278dd9d89292cf46e97dc0c1e52ce03275f40a97c5a348e802a924bf40e" sha256: a434911f643466d78462625df76fd9eb13e57348ff43fe1f77bbe909522c67a1
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.5.7" version: "2.5.2"
freezed_annotation: freezed_annotation:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -809,26 +804,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker name: leak_tracker
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "10.0.9" version: "11.0.2"
leak_tracker_flutter_testing: leak_tracker_flutter_testing:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker_flutter_testing name: leak_tracker_flutter_testing
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.9" version: "3.0.10"
leak_tracker_testing: leak_tracker_testing:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker_testing name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.1" version: "3.0.2"
lints: lints:
dependency: transitive dependency: transitive
description: description:
@@ -845,14 +840,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.0" version: "1.3.0"
macros:
dependency: transitive
description:
name: macros
sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656"
url: "https://pub.dev"
source: hosted
version: "0.1.3-main.0"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
@@ -873,10 +860,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.16.0" version: "1.17.0"
mime: mime:
dependency: transitive dependency: transitive
description: description:
@@ -1406,10 +1393,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.4" version: "0.7.7"
time: time:
dependency: transitive dependency: transitive
description: description:
@@ -1470,10 +1457,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: vector_math name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.4" version: "2.2.0"
vm_service: vm_service:
dependency: transitive dependency: transitive
description: description:
@@ -1571,5 +1558,5 @@ packages:
source: hosted source: hosted
version: "3.1.3" version: "3.1.3"
sdks: sdks:
dart: ">=3.7.0-0 <4.0.0" dart: ">=3.8.0-0 <4.0.0"
flutter: ">=3.27.4" flutter: ">=3.27.4"
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 B

After

Width:  |  Height:  |  Size: 522 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 73 KiB