payfrit-app/lib/models/menu_item.dart
John Mizerek 9995eb2ff7 feat: implement full recursive menu customization system
- Add MenuItem model with hierarchical structure support
- Implement recursive menu browsing with infinite depth support
- Add ExpansionTile for collapsible modifier sections
- Implement radio/checkbox logic based on ItemMaxNumSelectionReq
- Add automatic pre-selection for ItemIsCheckedByDefault items
- Implement validation for ItemRequiresChildSelection and max limits
- Add recursive price calculation across all depth levels
- Support intelligent selection behavior (radio groups, parent/child deselection)
- Add proper error messaging for validation failures
- Connect menu items API endpoint
- Update navigation flow to menu browse after service point selection
2025-12-29 10:32:31 -08:00

60 lines
1.9 KiB
Dart

class MenuItem {
final int itemId;
final int categoryId;
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.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"] as num).toInt(),
categoryId: (json["ItemCategoryID"] as num).toInt(),
name: (json["ItemName"] as String?) ?? "",
description: (json["ItemDescription"] as String?) ?? "",
parentItemId: (json["ItemParentItemID"] as num?)?.toInt() ?? 0,
price: (json["ItemPrice"] as num?)?.toDouble() ?? 0.0,
isActive: _parseBool(json["ItemIsActive"]),
isCheckedByDefault: _parseBool(json["ItemIsCheckedByDefault"]),
requiresChildSelection: _parseBool(json["ItemRequiresChildSelection"]),
maxNumSelectionReq: (json["ItemMaxNumSelectionReq"] as num?)?.toInt() ?? 0,
isCollapsible: _parseBool(json["ItemIsCollapsible"]),
sortOrder: (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;
}