2025-08-07 10:56:08 +07:00

180 lines
6.2 KiB
Dart

import 'package:cached_network_image/cached_network_image.dart';
import 'package:enaklo_pos/core/extensions/int_ext.dart';
import 'package:enaklo_pos/presentation/home/dialog/variant_dialog.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:enaklo_pos/core/constants/variables.dart';
import 'package:enaklo_pos/data/models/response/product_response_model.dart';
import 'package:enaklo_pos/presentation/home/bloc/checkout/checkout_bloc.dart';
import '../../../core/constants/colors.dart';
class ProductCard extends StatelessWidget {
final Product data;
final VoidCallback onCartButton;
const ProductCard({
super.key,
required this.data,
required this.onCartButton,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
if (data.isActive == true) {
if (data.variants!.isEmpty) {
context.read<CheckoutBloc>().add(
CheckoutEvent.addItem(data, null),
);
} else {
showDialog(
context: context,
builder: (context) => VariantDialog(product: data),
);
}
}
},
child: Container(
decoration: BoxDecoration(
color: AppColors.white,
borderRadius: BorderRadius.circular(8.0),
border: Border.all(
color: AppColors.disabled,
),
),
child: Stack(
children: [
Padding(
padding: const EdgeInsets.all(4.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(8.0)),
child: CachedNetworkImage(
imageUrl: (data.imageUrl ?? "").contains('http')
? data.imageUrl!
: '${Variables.baseUrl}/${data.imageUrl}',
fit: BoxFit.cover,
width: double.infinity,
height: 120,
errorWidget: (context, url, error) => Container(
width: double.infinity,
height: 120,
decoration: BoxDecoration(
color: AppColors.disabled.withOpacity(0.4),
),
child: const Icon(
Icons.image,
color: AppColors.grey,
),
),
),
),
const Spacer(),
Text(
"${data.name}",
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w700,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
const Spacer(),
Align(
alignment: Alignment.center,
child: Text(
'-',
style: const TextStyle(
fontSize: 12,
color: AppColors.grey,
fontWeight: FontWeight.w500,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
const Spacer(),
Align(
alignment: Alignment.center,
child: Text(
data.price!.currencyFormatRp,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 12,
),
),
),
const Spacer(),
],
),
),
BlocBuilder<CheckoutBloc, CheckoutState>(
builder: (context, state) {
return state.maybeWhen(
orElse: () => const SizedBox(),
loaded: (
products,
discountModel,
discount,
discountAmount,
tax,
serviceCharge,
totalQuantity,
totalPrice,
draftName,
orderType,
deliveryType,
) {
final totalQuantity = products
.where((item) => item.product.id == data.id)
.map((item) => item.quantity)
.fold(0, (sum, qty) => sum + qty);
if (totalQuantity == 0) {
return const SizedBox.shrink();
}
return Align(
alignment: Alignment.topRight,
child: Container(
width: 40,
height: 40,
padding: const EdgeInsets.all(6),
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(9.0)),
color: AppColors.primary,
),
child: Center(
child: Text(
totalQuantity.toString(),
style: const TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold),
),
),
),
);
},
);
},
),
if (data.isActive == false)
Container(
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(8.0)),
color: AppColors.grey.withOpacity(0.5),
),
),
],
),
),
);
}
}