Update project

This commit is contained in:
2026-07-23 15:36:11 +05:30
parent 1197cfc161
commit 14fffa40c6
84 changed files with 20918 additions and 2761 deletions

View File

@@ -0,0 +1,243 @@
// Models for:
// GET /live/api/v1/mob/products/getproductsbysubcategory
// ?categoryid=&tenantid=&locationid=
//
// Mirrors the response shape exactly (field names/casing kept as-is, e.g.
// the API's inconsistent "Subcategoryname" on the product object vs.
// "subcategoryname" on the section object).
class GroceryProductsResponse {
final int code;
final GroceryData data;
final String message;
final bool status;
GroceryProductsResponse({
required this.code,
required this.data,
required this.message,
required this.status,
});
factory GroceryProductsResponse.fromJson(Map<String, dynamic> json) {
return GroceryProductsResponse(
code: _asInt(json['code']),
data: GroceryData.fromJson(
(json['data'] as Map<String, dynamic>?) ?? const {}),
message: (json['message'] as String?) ?? '',
status: (json['status'] as bool?) ?? false,
);
}
}
class GroceryData {
final String address;
final String city;
final List<GrocerySubcategory> details;
final String licenseno;
final String locationname;
final String pickuplat;
final int pickuplocationid;
final String pickuplong;
final String postcode;
final String primarycontact;
final String primaryemail;
final String suburb;
final String tenantname;
GroceryData({
required this.address,
required this.city,
required this.details,
required this.licenseno,
required this.locationname,
required this.pickuplat,
required this.pickuplocationid,
required this.pickuplong,
required this.postcode,
required this.primarycontact,
required this.primaryemail,
required this.suburb,
required this.tenantname,
});
factory GroceryData.fromJson(Map<String, dynamic> json) {
return GroceryData(
address: (json['address'] as String?) ?? '',
city: (json['city'] as String?) ?? '',
details: ((json['details'] as List<dynamic>?) ?? const [])
.map((e) => GrocerySubcategory.fromJson(e as Map<String, dynamic>))
.toList(),
licenseno: (json['licenseno'] as String?) ?? '',
locationname: (json['locationname'] as String?) ?? '',
pickuplat: (json['pickuplat'] as String?) ?? '',
pickuplocationid: _asInt(json['pickuplocationid']),
pickuplong: (json['pickuplong'] as String?) ?? '',
postcode: (json['postcode'] as String?) ?? '',
primarycontact: (json['primarycontact'] as String?) ?? '',
primaryemail: (json['primaryemail'] as String?) ?? '',
suburb: (json['suburb'] as String?) ?? '',
tenantname: (json['tenantname'] as String?) ?? '',
);
}
}
/// One row in `details`, e.g. "Vegetables & Fruits", "Dairy, Deli & Egg".
class GrocerySubcategory {
final int subcategoryId;
final String subcategoryName;
final String image;
final List<GroceryProduct> products;
GrocerySubcategory({
required this.subcategoryId,
required this.subcategoryName,
required this.image,
required this.products,
});
factory GrocerySubcategory.fromJson(Map<String, dynamic> json) {
return GrocerySubcategory(
subcategoryId: _asInt(json['subcategoryid']),
subcategoryName: (json['subcategoryname'] as String?) ?? 'Other',
image: (json['image'] as String?) ?? '',
products: ((json['products'] as List<dynamic>?) ?? const [])
.map((e) => GroceryProduct.fromJson(e as Map<String, dynamic>))
.toList(),
);
}
}
class GroceryProduct {
final int productId;
final int applocationId;
final int productLocationId;
final int tenantId;
final int categoryId;
final String categoryName;
final int subcategoryId;
// Note: the API returns this capitalized on the product object.
final String subcategoryNameOnProduct;
final int discountId;
final num discountValue;
final String productName;
final String productDesc;
final String? productSku;
final String? productBrand;
final String productUnit;
final String unitValue;
final String? topPicks;
final num productCost;
final num? taxAmount;
final num? taxPercent;
final num productTax;
final int productStock;
final int productCombo;
final int variants;
final int quantity;
final num? retailPrice;
final num? diffPrice;
final num? diffPercent;
final int approve;
final String productStatus;
final String? productImage;
GroceryProduct({
required this.productId,
required this.applocationId,
required this.productLocationId,
required this.tenantId,
required this.categoryId,
required this.categoryName,
required this.subcategoryId,
required this.subcategoryNameOnProduct,
required this.discountId,
required this.discountValue,
required this.productName,
required this.productDesc,
this.productSku,
this.productBrand,
required this.productUnit,
required this.unitValue,
this.topPicks,
required this.productCost,
this.taxAmount,
this.taxPercent,
required this.productTax,
required this.productStock,
required this.productCombo,
required this.variants,
required this.quantity,
this.retailPrice,
this.diffPrice,
this.diffPercent,
required this.approve,
required this.productStatus,
this.productImage,
});
/// Selling price shown to the customer: retail price if set, else cost.
num get displayPrice => retailPrice ?? productCost;
/// Struck-through "was" price — only meaningful when the API sent a
/// positive diffprice (an actual discount amount).
num get displayOriginalPrice =>
(diffPrice != null && diffPrice! > 0) ? displayPrice + diffPrice! : displayPrice;
bool get isInStock => productStatus.toLowerCase() == 'available';
bool get isActive => productStatus.toLowerCase() != 'inactive';
factory GroceryProduct.fromJson(Map<String, dynamic> json) {
return GroceryProduct(
productId: _asInt(json['productid']),
applocationId: _asInt(json['applocationid']),
productLocationId: _asInt(json['productlocationid']),
tenantId: _asInt(json['tenantid']),
categoryId: _asInt(json['categoryid']),
categoryName: (json['categoryname'] as String?) ?? '',
subcategoryId: _asInt(json['subcategoryid']),
subcategoryNameOnProduct: (json['Subcategoryname'] as String?) ?? '',
discountId: _asInt(json['discountid']),
discountValue: _asNum(json['discountvalue']),
productName: (json['productname'] as String?) ?? 'Product',
productDesc: (json['productdesc'] as String?) ?? '',
productSku: json['productsku'] as String?,
productBrand: json['productbrand'] as String?,
productUnit: (json['productunit'] as String?) ?? '',
unitValue: (json['unitvalue'] as String?) ?? '',
topPicks: json['toppicks'] as String?,
productCost: _asNum(json['productcost']),
taxAmount: json['taxamount'] == null ? null : _asNum(json['taxamount']),
taxPercent:
json['taxpercent'] == null ? null : _asNum(json['taxpercent']),
productTax: _asNum(json['producttax']),
productStock: _asInt(json['productstock']),
productCombo: _asInt(json['productcombo']),
variants: _asInt(json['variants']),
quantity: _asInt(json['quantity']),
retailPrice:
json['retailprice'] == null ? null : _asNum(json['retailprice']),
diffPrice: json['diffprice'] == null ? null : _asNum(json['diffprice']),
diffPercent:
json['diffpercent'] == null ? null : _asNum(json['diffpercent']),
approve: _asInt(json['approve']),
productStatus: (json['productstatus'] as String?) ?? '',
productImage: json['productimage'] as String?,
);
}
}
int _asInt(dynamic v) {
if (v == null) return 0;
if (v is int) return v;
if (v is num) return v.toInt();
return int.tryParse(v.toString()) ?? 0;
}
num _asNum(dynamic v) {
if (v == null) return 0;
if (v is num) return v;
return num.tryParse(v.toString()) ?? 0;
}