Features: - Beacon scanner service for detecting nearby beacons - Beacon cache for offline-first beacon resolution - Preload cache for instant menu display - Business selector screen for multi-location support - Rescan button widget for quick beacon refresh - Sign-in dialog for guest checkout flow - Task type model for server tasks Improvements: - Enhanced menu browsing with category filtering - Improved cart view with better modifier display - Order history with detailed order tracking - Chat screen improvements - Better error handling in API service Fixes: - CashApp payment return crash fix - Modifier nesting issues resolved - Auto-expand modifier groups Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
63 lines
2.4 KiB
Dart
63 lines
2.4 KiB
Dart
class MenuItem {
|
|
final int itemId;
|
|
final int categoryId;
|
|
final String categoryName;
|
|
final String name;
|
|
final String description;
|
|
final int parentItemId;
|
|
final double price;
|
|
final bool isActive;
|
|
final bool isCheckedByDefault;
|
|
final bool requiresChildSelection;
|
|
final int maxNumSelectionReq;
|
|
final bool isCollapsible;
|
|
final int sortOrder;
|
|
|
|
const MenuItem({
|
|
required this.itemId,
|
|
required this.categoryId,
|
|
required this.categoryName,
|
|
required this.name,
|
|
required this.description,
|
|
required this.parentItemId,
|
|
required this.price,
|
|
required this.isActive,
|
|
required this.isCheckedByDefault,
|
|
required this.requiresChildSelection,
|
|
required this.maxNumSelectionReq,
|
|
required this.isCollapsible,
|
|
required this.sortOrder,
|
|
});
|
|
|
|
factory MenuItem.fromJson(Map<String, dynamic> json) {
|
|
return MenuItem(
|
|
itemId: (json["ItemID"] ?? json["itemid"] as num?)?.toInt() ?? 0,
|
|
categoryId: (json["ItemCategoryID"] ?? json["itemcategoryid"] as num?)?.toInt() ?? 0,
|
|
categoryName: (json["ItemCategoryName"] ?? json["itemcategoryname"] as String?) ?? "",
|
|
name: (json["ItemName"] ?? json["itemname"] as String?) ?? "",
|
|
description: (json["ItemDescription"] ?? json["itemdescription"] as String?) ?? "",
|
|
parentItemId: (json["ItemParentItemID"] ?? json["itemparentitemid"] as num?)?.toInt() ?? 0,
|
|
price: (json["ItemPrice"] ?? json["itemprice"] as num?)?.toDouble() ?? 0.0,
|
|
isActive: _parseBool(json["ItemIsActive"] ?? json["itemisactive"]),
|
|
isCheckedByDefault: _parseBool(json["ItemIsCheckedByDefault"] ?? json["itemischeckedbydefault"]),
|
|
requiresChildSelection: _parseBool(json["ItemRequiresChildSelection"] ?? json["itemrequireschildselection"]),
|
|
maxNumSelectionReq: (json["ItemMaxNumSelectionReq"] ?? json["itemmaxnumselectionreq"] as num?)?.toInt() ?? 0,
|
|
isCollapsible: _parseBool(json["ItemIsCollapsible"] ?? json["itemiscollapsible"]),
|
|
sortOrder: (json["ItemSortOrder"] ?? json["itemsortorder"] as num?)?.toInt() ?? 0,
|
|
);
|
|
}
|
|
|
|
static bool _parseBool(dynamic value) {
|
|
if (value == null) return false;
|
|
if (value is bool) return value;
|
|
if (value is num) return value != 0;
|
|
if (value is String) {
|
|
final lower = value.toLowerCase();
|
|
return lower == "true" || lower == "1";
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool get isRootItem => parentItemId == 0;
|
|
bool get isModifier => parentItemId != 0;
|
|
}
|