update cart
This commit is contained in:
@@ -22,13 +22,14 @@ class ProductModel extends HiveObject {
|
||||
this.description,
|
||||
required this.basePrice,
|
||||
this.images,
|
||||
this.thumbnail,
|
||||
required this.thumbnail,
|
||||
this.imageCaptions,
|
||||
this.customLink360,
|
||||
this.specifications,
|
||||
this.category,
|
||||
this.brand,
|
||||
this.unit,
|
||||
this.conversionOfSm,
|
||||
required this.isActive,
|
||||
required this.isFeatured,
|
||||
this.erpnextItemCode,
|
||||
@@ -58,7 +59,7 @@ class ProductModel extends HiveObject {
|
||||
|
||||
/// Thumbnail image URL
|
||||
@HiveField(5)
|
||||
final String? thumbnail;
|
||||
final String thumbnail;
|
||||
|
||||
/// Image captions (JSON encoded map of image_url -> caption)
|
||||
@HiveField(6)
|
||||
@@ -85,6 +86,11 @@ class ProductModel extends HiveObject {
|
||||
@HiveField(11)
|
||||
final String? unit;
|
||||
|
||||
/// Conversion factor for Square Meter UOM (tiles per m²)
|
||||
/// Used to calculate: Số viên = Số lượng × conversionOfSm
|
||||
@HiveField(17)
|
||||
final double? conversionOfSm;
|
||||
|
||||
/// Whether product is active
|
||||
@HiveField(12)
|
||||
final bool isActive;
|
||||
@@ -117,7 +123,7 @@ class ProductModel extends HiveObject {
|
||||
description: json['description'] as String?,
|
||||
basePrice: (json['base_price'] as num).toDouble(),
|
||||
images: json['images'] != null ? jsonEncode(json['images']) : null,
|
||||
thumbnail: json['thumbnail'] as String?,
|
||||
thumbnail: json['thumbnail'] as String,
|
||||
imageCaptions: json['image_captions'] != null
|
||||
? jsonEncode(json['image_captions'])
|
||||
: null,
|
||||
@@ -128,6 +134,9 @@ class ProductModel extends HiveObject {
|
||||
category: json['category'] as String?,
|
||||
brand: json['brand'] as String?,
|
||||
unit: json['unit'] as String?,
|
||||
conversionOfSm: json['conversion_of_sm'] != null
|
||||
? (json['conversion_of_sm'] as num).toDouble()
|
||||
: null,
|
||||
isActive: json['is_active'] as bool? ?? true,
|
||||
isFeatured: json['is_featured'] as bool? ?? false,
|
||||
erpnextItemCode: json['erpnext_item_code'] as String?,
|
||||
@@ -227,7 +236,7 @@ class ProductModel extends HiveObject {
|
||||
description: json['description'] as String?,
|
||||
basePrice: price,
|
||||
images: imagesList.isNotEmpty ? jsonEncode(imagesList) : null,
|
||||
thumbnail: thumbnailUrl,
|
||||
thumbnail: thumbnailUrl ?? '',
|
||||
imageCaptions: imageCaptionsMap.isNotEmpty
|
||||
? jsonEncode(imageCaptionsMap)
|
||||
: null,
|
||||
@@ -239,6 +248,9 @@ class ProductModel extends HiveObject {
|
||||
json['item_group'] as String?, // Try item_group_name first, fallback to item_group
|
||||
brand: json['brand'] as String?,
|
||||
unit: json['stock_uom'] as String? ?? 'm²',
|
||||
conversionOfSm: json['conversion_of_sm'] != null
|
||||
? (json['conversion_of_sm'] as num).toDouble()
|
||||
: null,
|
||||
isActive: (json['disabled'] as int?) == 0, // Frappe uses 'disabled' field
|
||||
isFeatured: false, // Not provided by API, default to false
|
||||
erpnextItemCode: json['name'] as String, // Store item code for reference
|
||||
@@ -270,6 +282,7 @@ class ProductModel extends HiveObject {
|
||||
'category': category,
|
||||
'brand': brand,
|
||||
'unit': unit,
|
||||
'conversion_of_sm': conversionOfSm,
|
||||
'is_active': isActive,
|
||||
'is_featured': isFeatured,
|
||||
'erpnext_item_code': erpnextItemCode,
|
||||
@@ -349,6 +362,7 @@ class ProductModel extends HiveObject {
|
||||
String? category,
|
||||
String? brand,
|
||||
String? unit,
|
||||
double? conversionOfSm,
|
||||
bool? isActive,
|
||||
bool? isFeatured,
|
||||
String? erpnextItemCode,
|
||||
@@ -368,6 +382,7 @@ class ProductModel extends HiveObject {
|
||||
category: category ?? this.category,
|
||||
brand: brand ?? this.brand,
|
||||
unit: unit ?? this.unit,
|
||||
conversionOfSm: conversionOfSm ?? this.conversionOfSm,
|
||||
isActive: isActive ?? this.isActive,
|
||||
isFeatured: isFeatured ?? this.isFeatured,
|
||||
erpnextItemCode: erpnextItemCode ?? this.erpnextItemCode,
|
||||
@@ -410,6 +425,7 @@ class ProductModel extends HiveObject {
|
||||
category: category,
|
||||
brand: brand,
|
||||
unit: unit,
|
||||
conversionOfSm: conversionOfSm,
|
||||
isActive: isActive,
|
||||
isFeatured: isFeatured,
|
||||
erpnextItemCode: erpnextItemCode,
|
||||
|
||||
@@ -22,13 +22,14 @@ class ProductModelAdapter extends TypeAdapter<ProductModel> {
|
||||
description: fields[2] as String?,
|
||||
basePrice: (fields[3] as num).toDouble(),
|
||||
images: fields[4] as String?,
|
||||
thumbnail: fields[5] as String?,
|
||||
thumbnail: fields[5] as String,
|
||||
imageCaptions: fields[6] as String?,
|
||||
customLink360: fields[7] as String?,
|
||||
specifications: fields[8] as String?,
|
||||
category: fields[9] as String?,
|
||||
brand: fields[10] as String?,
|
||||
unit: fields[11] as String?,
|
||||
conversionOfSm: (fields[17] as num?)?.toDouble(),
|
||||
isActive: fields[12] as bool,
|
||||
isFeatured: fields[13] as bool,
|
||||
erpnextItemCode: fields[14] as String?,
|
||||
@@ -40,7 +41,7 @@ class ProductModelAdapter extends TypeAdapter<ProductModel> {
|
||||
@override
|
||||
void write(BinaryWriter writer, ProductModel obj) {
|
||||
writer
|
||||
..writeByte(17)
|
||||
..writeByte(18)
|
||||
..writeByte(0)
|
||||
..write(obj.productId)
|
||||
..writeByte(1)
|
||||
@@ -74,7 +75,9 @@ class ProductModelAdapter extends TypeAdapter<ProductModel> {
|
||||
..writeByte(15)
|
||||
..write(obj.createdAt)
|
||||
..writeByte(16)
|
||||
..write(obj.updatedAt);
|
||||
..write(obj.updatedAt)
|
||||
..writeByte(17)
|
||||
..write(obj.conversionOfSm);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -9,6 +9,27 @@ library;
|
||||
/// Represents a tile/construction product in the application.
|
||||
/// Used across all layers but originates in the domain layer.
|
||||
class Product {
|
||||
|
||||
const Product({
|
||||
required this.productId,
|
||||
required this.name,
|
||||
this.description,
|
||||
required this.basePrice,
|
||||
required this.images,
|
||||
required this.thumbnail,
|
||||
required this.imageCaptions,
|
||||
this.customLink360,
|
||||
required this.specifications,
|
||||
this.category,
|
||||
this.brand,
|
||||
this.unit,
|
||||
this.conversionOfSm,
|
||||
required this.isActive,
|
||||
required this.isFeatured,
|
||||
this.erpnextItemCode,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
});
|
||||
/// Unique identifier
|
||||
final String productId;
|
||||
|
||||
@@ -25,7 +46,7 @@ class Product {
|
||||
final List<String> images;
|
||||
|
||||
/// Thumbnail image URL
|
||||
final String? thumbnail;
|
||||
final String thumbnail;
|
||||
|
||||
/// Image captions
|
||||
final Map<String, String> imageCaptions;
|
||||
@@ -45,6 +66,10 @@ class Product {
|
||||
/// Unit of measurement (e.g., "m²", "viên", "hộp")
|
||||
final String? unit;
|
||||
|
||||
/// Conversion factor for Square Meter UOM (tiles per m²)
|
||||
/// Used to calculate: Số viên = Số lượng × conversionOfSm
|
||||
final double? conversionOfSm;
|
||||
|
||||
/// Product is active
|
||||
final bool isActive;
|
||||
|
||||
@@ -60,26 +85,6 @@ class Product {
|
||||
/// Last updated date
|
||||
final DateTime updatedAt;
|
||||
|
||||
const Product({
|
||||
required this.productId,
|
||||
required this.name,
|
||||
this.description,
|
||||
required this.basePrice,
|
||||
required this.images,
|
||||
this.thumbnail,
|
||||
required this.imageCaptions,
|
||||
this.customLink360,
|
||||
required this.specifications,
|
||||
this.category,
|
||||
this.brand,
|
||||
this.unit,
|
||||
required this.isActive,
|
||||
required this.isFeatured,
|
||||
this.erpnextItemCode,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
});
|
||||
|
||||
/// Get primary image URL
|
||||
String? get primaryImage => images.isNotEmpty ? images.first : null;
|
||||
|
||||
@@ -134,6 +139,7 @@ class Product {
|
||||
String? category,
|
||||
String? brand,
|
||||
String? unit,
|
||||
double? conversionOfSm,
|
||||
bool? isActive,
|
||||
bool? isFeatured,
|
||||
String? erpnextItemCode,
|
||||
@@ -153,6 +159,7 @@ class Product {
|
||||
category: category ?? this.category,
|
||||
brand: brand ?? this.brand,
|
||||
unit: unit ?? this.unit,
|
||||
conversionOfSm: conversionOfSm ?? this.conversionOfSm,
|
||||
isActive: isActive ?? this.isActive,
|
||||
isFeatured: isFeatured ?? this.isFeatured,
|
||||
erpnextItemCode: erpnextItemCode ?? this.erpnextItemCode,
|
||||
|
||||
@@ -238,7 +238,7 @@ class ProductCard extends ConsumerWidget {
|
||||
width: double.infinity,
|
||||
height: 36.0,
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: product.inStock ? onAddToCart : null,
|
||||
onPressed: !product.inStock ? onAddToCart : null,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColors.primaryBlue,
|
||||
foregroundColor: AppColors.white,
|
||||
@@ -256,7 +256,7 @@ class ProductCard extends ConsumerWidget {
|
||||
),
|
||||
icon: const Icon(Icons.shopping_cart, size: 16.0),
|
||||
label: Text(
|
||||
product.inStock ? 'Thêm vào giỏ' : l10n.outOfStock,
|
||||
!product.inStock ? 'Thêm vào giỏ' : l10n.outOfStock,
|
||||
style: const TextStyle(
|
||||
fontSize: 12.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
|
||||
Reference in New Issue
Block a user