I got an error import 'dart:convert';
import 'package:fitstand/src/models/customer/menu_items_model.dart'; // Assuming OrderItem needs MenuItem
// Example Order Model - Adjust fields and types based on your ACTUAL backend response
class Order {
final int id;
final int? userId;
final int? restaurantId;
final int? addressId;
final Map<String, dynamic>? deliveryAddressSnapshot; // Store as Map
final double? totalAmount;
final String? paymentGateway;
final String? paymentId;
final String? paymentStatus;
final String? orderStatus;
final String? razorpayOrderId;
final DateTime? orderDate; // Use DateTime for created_at/updated_at
final String? restaurantName; // Add if backend includes it via relationship
final List<OrderItem>? items; // List of order items
final double? subTotal; // Added field
final double? deliveryCharge; // Added field
Order({
required this.id,
this.userId,
this.restaurantId,
this.addressId,
this.deliveryAddressSnapshot,
this.totalAmount,
this.paymentGateway,
this.paymentId,
this.paymentStatus,
this.orderStatus,
this.razorpayOrderId,
this.orderDate,
this.restaurantName,
this.items,
this.subTotal, // Added to constructor
this.deliveryCharge, // Added to constructor
});
factory Order.fromJson(Map<String, dynamic> json) {
// Helper to safely parse DateTime
DateTime? parseOptionalDate(String? dateString) {
if (dateString == null) return null;
try { return DateTime.parse(dateString).toLocal(); } // Convert to local time
catch (e) { print("Error parsing date: $dateString"); return null; }
}
// Helper to safely decode JSON string if needed (depends on backend response)
Map<String, dynamic>? decodeJsonString(dynamic jsonField) {
if (jsonField == null) return null;
if (jsonField is Map<String, dynamic>) return jsonField; // Already a map
if (jsonField is String) {
try {
// *** Use the imported jsonDecode ***
return jsonDecode(jsonField) as Map<String, dynamic>?;
// **********************************
}
catch (e) { print("Error decoding JSON string field: $e"); return null; }
}
return null; // Not a map or string
}
return Order(
id: json['id'] as int? ?? 0, // Handle potential null ID? Unlikely but safe.
userId: json['user_id'] as int?,
restaurantId: json['restaurant_id'] as int?,
addressId: json['address_id'] as int?,
// Use helper in case backend sends string OR map
deliveryAddressSnapshot: decodeJsonString(json['delivery_address_snapshot']),
//totalAmount: double.tryParse(json['total_amount']?.toString() ?? '0.0'),
totalAmount: _parseDouble(json['total_amount']),
subTotal: _parseDouble(json['sub_total']),
deliveryCharge: _parseDouble(json['delivery_charge']),
paymentGateway: json['payment_gateway'] as String?,
paymentId: json['payment_id'] as String?,
paymentStatus: json['payment_status'] as String?,
orderStatus: json['order_status'] as String?,
razorpayOrderId: json['razorpay_order_id'] as String?,
orderDate: parseOptionalDate(json['created_at']), // Parse created_at
// Add restaurant name parsing if backend includes it (e.g., via relationship)
restaurantName: json['restaurant']?['name'] as String?, // Example if nested under 'restaurant'
// Parse items list if included in the response
items: json['items'] != null && json['items'] is List
? (json['items'] as List).map((itemJson) => OrderItem.fromJson(itemJson)).toList()
: null,
//subTotal: json['sub_total']?.toDouble(), // Added to fromJson
//deliveryCharge: json['delivery_charge']?.toDouble(), // Added to fromJson
);
}
static double? _parseDouble(dynamic value) {
if (value == null) return null;
if (value is double) return value;
if (value is int) return value.toDouble();
if (value is String) return double.tryParse(value);
return null;
}
}
class OrderItem {
final int id;
final int? orderId;
final int? menuItemId;
final int? quantity;
final double? price;
final String? specialRequest;
// Add fields from related MenuItem if backend includes them
final String? menuItemName;
final String? menuItemPhoto;
final String? menuItemFoodType; // Add food type
// You might have the full MenuItem object nested
final MenuItem? menuItem; // Example if the full item is nested
OrderItem({
required this.id,
this.orderId,
this.menuItemId,
this.quantity,
this.price,
this.specialRequest,
this.menuItemName,
this.menuItemPhoto,
this.menuItemFoodType,
this.menuItem, // Add to constructor
});
factory OrderItem.fromJson(Map<String, dynamic> json) {
return OrderItem(
id: json['id'] as int? ?? 0,
orderId: json['order_id'] as int?,
menuItemId: json['menu_item_id'] as int?,
quantity: json['quantity'] as int?,
//price: double.tryParse(json['price']?.toString() ?? '0.0'),
price: _parseDouble(json['price']),
specialRequest: json['special_request'] as String?,
// Parse nested menu item details if backend sends them
// Adjust keys ('menu_item', 'item_name', 'photo') based on your actual API response
menuItemName: json['menu_item']?['item_name'] as String?,
//menuItemPhoto: json['menu_item']?['photo'] as String?,
menuItemPhoto: json['menu_item_photo'] ?? json['menu_item']?['photo_url'] ?? json['menu_item']?['photo'],
menuItemFoodType: json['menu_item']?['food_type'] as String?,
// If the full MenuItem object is nested under 'menu_item':
menuItem: json['menu_item'] != null ? MenuItem.fromJson(json['menu_item']) : null,
);
}
static double? _parseDouble(dynamic value) {
if (value == null) return null;
if (value is double) return value;
if (value is int) return value.toDouble();
if (value is String) return double.tryParse(value);
return null;
}
} when I was trying to see order details. My order_model.dart is: This happens after I have updated code for photo: My order_model.dart code is: import 'dart:convert'; import 'package:fitstand/src/models/customer/menu_items_model.dart'; // Assuming OrderItem needs MenuItem
// Example Order Model - Adjust fields and types based on your ACTUAL backend response class Order { final int id; final int? userId; final int? restaurantId; final int? addressId; final Map<String, dynamic>? deliveryAddressSnapshot; // Store as Map final double? totalAmount; final String? paymentGateway; final String? paymentId; final String? paymentStatus; final String? orderStatus; final String? razorpayOrderId; final DateTime? orderDate; // Use DateTime for created_at/updated_at final String? restaurantName; // Add if backend includes it via relationship final List? items; // List of order items
final double? subTotal; // Added field final double? deliveryCharge; // Added field
Order({ required this.id, this.userId, this.restaurantId, this.addressId, this.deliveryAddressSnapshot, this.totalAmount, this.paymentGateway, this.paymentId, this.paymentStatus, this.orderStatus, this.razorpayOrderId, this.orderDate, this.restaurantName, this.items,
this.subTotal, // Added to constructor
this.deliveryCharge, // Added to constructor
});
factory Order.fromJson(Map<String, dynamic> json) { // Helper to safely parse DateTime DateTime? parseOptionalDate(String? dateString) { if (dateString == null) return null; try { return DateTime.parse(dateString).toLocal(); } // Convert to local time catch (e) { print("Error parsing date: $dateString"); return null; } }
// Helper to safely decode JSON string if needed (depends on backend response)
Map<String, dynamic>? decodeJsonString(dynamic jsonField) {
if (jsonField == null) return null;
if (jsonField is Map<String, dynamic>) return jsonField; // Already a map
if (jsonField is String) {
try {
// *** Use the imported jsonDecode ***
return jsonDecode(jsonField) as Map<String, dynamic>?;
// **********************************
}
catch (e) { print("Error decoding JSON string field: $e"); return null; }
}
return null; // Not a map or string
}
return Order(
id: json['id'] as int? ?? 0, // Handle potential null ID? Unlikely but safe.
userId: json['user_id'] as int?,
restaurantId: json['restaurant_id'] as int?,
addressId: json['address_id'] as int?,
// Use helper in case backend sends string OR map
deliveryAddressSnapshot: decodeJsonString(json['delivery_address_snapshot']),
//totalAmount: double.tryParse(json['total_amount']?.toString() ?? '0.0'),
totalAmount: _parseDouble(json['total_amount']),
subTotal: _parseDouble(json['sub_total']),
deliveryCharge: _parseDouble(json['delivery_charge']),
paymentGateway: json['payment_gateway'] as String?,
paymentId: json['payment_id'] as String?,
paymentStatus: json['payment_status'] as String?,
orderStatus: json['order_status'] as String?,
razorpayOrderId: json['razorpay_order_id'] as String?,
orderDate: parseOptionalDate(json['created_at']), // Parse created_at
// Add restaurant name parsing if backend includes it (e.g., via relationship)
restaurantName: json['restaurant']?['name'] as String?, // Example if nested under 'restaurant'
// Parse items list if included in the response
items: json['items'] != null && json['items'] is List
? (json['items'] as List).map((itemJson) => OrderItem.fromJson(itemJson)).toList()
: null,
//subTotal: json['sub_total']?.toDouble(), // Added to fromJson
//deliveryCharge: json['delivery_charge']?.toDouble(), // Added to fromJson
);
} static double? _parseDouble(dynamic value) { if (value == null) return null; if (value is double) return value; if (value is int) return value.toDouble(); if (value is String) return double.tryParse(value); return null; } }
class OrderItem { final int id; final int? orderId; final int? menuItemId; final int? quantity; final double? price; final String? specialRequest; // Add fields from related MenuItem if backend includes them final String? menuItemName; final String? menuItemPhoto; final String? menuItemFoodType; // Add food type
// You might have the full MenuItem object nested final MenuItem? menuItem; // Example if the full item is nested
OrderItem({ required this.id, this.orderId, this.menuItemId, this.quantity, this.price, this.specialRequest, this.menuItemName, this.menuItemPhoto, this.menuItemFoodType, this.menuItem, // Add to constructor });
factory OrderItem.fromJson(Map<String, dynamic> json) { return OrderItem( id: json['id'] as int? ?? 0, orderId: json['order_id'] as int?, menuItemId: json['menu_item_id'] as int?, quantity: json['quantity'] as int?, //price: double.tryParse(json['price']?.toString() ?? '0.0'), price: _parseDouble(json['price']), specialRequest: json['special_request'] as String?, // Parse nested menu item details if backend sends them // Adjust keys ('menu_item', 'item_name', 'photo') based on your actual API response menuItemName: json['menu_item']?['item_name'] as String?, //menuItemPhoto: json['menu_item']?['photo'] as String?, menuItemPhoto: json['menu_item_photo'] ?? json['menu_item']?['photo_url'] ?? json['menu_item']?['photo'], menuItemFoodType: json['menu_item']?['food_type'] as String?, // If the full MenuItem object is nested under 'menu_item': menuItem: json['menu_item'] != null ? MenuItem.fromJson(json['menu_item']) : null, ); } static double? _parseDouble(dynamic value) { if (value == null) return null; if (value is double) return value; if (value is int) return value.toDouble(); if (value is String) return double.tryParse(value); return null; } }