second commit

This commit is contained in:
Anbarasu
2026-05-27 10:35:09 +05:30
parent c53794c04c
commit 1435ac47b0
501 changed files with 52818 additions and 0 deletions

View File

@@ -0,0 +1,330 @@
import 'package:flutter/material.dart';
import 'package:shimmer/shimmer.dart';
import '../Model/Response/products/product_info.dart';
class ProductBottomSheet {
static void show(BuildContext context, List<ProductDetails> productDetails, {bool? isAmountReceived}) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
builder: (context) {
double totalAmount = 0;
double totalTax = 0;
double sub = 0;
double totalDiscount = 0; // ⭐ ADD THIS
double otherCharges = 0; // ⭐ ADD THIS
for (var product in productDetails) {
totalAmount = product.productsumprice ?? 0.0;
sub = (product.price ?? 0.0) * (product.orderqty ?? 1);
totalTax = product.totaltaxamount ?? 0.0;
totalDiscount = product.discountamount ?? 0.0;
otherCharges = product.othercharges ?? 0.0;
}
final totalWithTax = totalAmount + totalTax;
// Calculate dynamic height
const itemHeight = 112.0;
final maxContentHeight = MediaQuery.of(context).size.height * 0.7;
final calculatedHeight = (productDetails.length * itemHeight) + 200;
return SafeArea(
child: Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom,
),
child: ConstrainedBox(
constraints: BoxConstraints(
maxHeight: calculatedHeight > maxContentHeight ? maxContentHeight : calculatedHeight,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Grab handle
Container(
width: 40,
height: 4,
margin: const EdgeInsets.only(top: 12, bottom: 10),
decoration: BoxDecoration(
color: Colors.grey[400],
borderRadius: BorderRadius.circular(8),
),
),
// Title row
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Row(
children: [
const Expanded(
child: Text(
'Product Details',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
),
IconButton(
icon: const Icon(Icons.cancel),
onPressed: () => Navigator.of(context).pop(),
),
],
),
),
const SizedBox(height: 4),
// Product List
if (productDetails.isEmpty)
const Padding(
padding: EdgeInsets.all(20),
child: Center(
child: Text(
"Looks like this order doesn't have any products.",
style: TextStyle(fontSize: 16, color: Colors.grey, fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
),
)
else
Flexible(
child: ListView.builder(
padding: const EdgeInsets.symmetric(horizontal: 16),
shrinkWrap: true,
itemCount: productDetails.length,
itemBuilder: (context, index) {
final product = productDetails[index];
return Padding(
padding: const EdgeInsets.only(bottom: 16.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.network(
product.productimage ?? '',
width: 80,
height: 80,
fit: BoxFit.cover,
loadingBuilder: (context, child, loadingProgress) {
if (loadingProgress == null) return child;
return Shimmer.fromColors(
baseColor: Colors.grey[300]!,
highlightColor: Colors.grey[100]!,
child: Container(
width: 80,
height: 80,
color: Colors.white,
),
);
},
errorBuilder: (context, error, stackTrace) => Container(
width: 80,
height: 80,
color: Colors.grey[200],
child: const Icon(Icons.image, color: Colors.grey),
),
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(
child: Text(
product.productname ?? '',
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
const SizedBox(width: 8),
Text(
"${((product.price ?? 0) * (product.orderqty ?? 1) + (product.taxamount ?? 0)).toStringAsFixed(2)}",
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
],
),
const SizedBox(height: 4),
Text(
"${product.orderqty} ${product.unitname}",
style: const TextStyle(color: Colors.grey),
),
const SizedBox(height: 4),
// Text(
// "Tax: ₹${product.taxamount?.toStringAsFixed(2) ?? '0.00'}",
// style: const TextStyle(color: Colors.grey),
// ),
],
),
),
],
),
);
},
),
),
// Bottom Summary
Visibility(
visible: productDetails.isNotEmpty,
child: Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
decoration: const BoxDecoration(
border: Border(top: BorderSide(color: Colors.grey, width: 0.3)),
color: Colors.white,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text("Amount", style: TextStyle(fontSize: 16)),
Text("${totalAmount.toStringAsFixed(2)}"),
],
),
const SizedBox(height: 4),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text("Tax", style: TextStyle(fontSize: 16)),
Text("${totalTax.toStringAsFixed(2)}"),
],
),
const SizedBox(height: 4),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text("OtherCharges", style: TextStyle(fontSize: 16)),
Text("${otherCharges.toStringAsFixed(2)}"),
],
),
const SizedBox(height: 4),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text("Discount", style: TextStyle(fontSize: 16)),
Text("${totalDiscount.toStringAsFixed(2)}"),
],
),
const SizedBox(height: 5),
const DottedLine2(),
const SizedBox(height: 5),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text("Total", style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
Text("${totalWithTax.toStringAsFixed(2)}", style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
],
),
const SizedBox(height: 10),
Visibility(
visible: isAmountReceived ?? false,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Row(
children: [
Icon(Icons.check_circle, color: Colors.green,),
SizedBox(width: 4,),
Text("Amount Received", style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500)),
],
),
Text("${totalWithTax.toStringAsFixed(2)}", style: const TextStyle(fontSize: 16)),
],
),
),
],
),
),
),
],
),
),
),
);
},
);
}
}
class DottedLine extends StatelessWidget {
final double height;
final double dotSize;
final Color color;
const DottedLine({
super.key,
this.height = 40,
this.dotSize = 4,
this.color = Colors.grey,
});
@override
Widget build(BuildContext context) {
int count = (height / (dotSize * 2)).floor();
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(count, (index) {
return Container(
width: 1.5,
height: dotSize,
margin: EdgeInsets.symmetric(vertical: dotSize / 2),
color: color,
);
}),
);
}
}
class DottedLine2 extends StatelessWidget {
final double width;
final double dotSize;
final Color color;
const DottedLine2({
super.key,
this.width = double.infinity,
this.dotSize = 4,
this.color = Colors.grey,
});
@override
Widget build(BuildContext context) {
// If width is infinite, get screen width
final screenWidth = MediaQuery.of(context).size.width;
final actualWidth = width == double.infinity ? screenWidth : width;
int count = (actualWidth / (dotSize * 2)).floor();
return SizedBox(
width: actualWidth,
height: dotSize,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: List.generate(count, (_) {
return Container(
width: dotSize,
height: 1,
color: color,
);
}),
),
);
}
}

View File

@@ -0,0 +1,74 @@
import 'package:flutter/material.dart';
class AppBottomSheets {
static void showConfirmation(
BuildContext context, {
required VoidCallback onAccept,
VoidCallback? onCancel,
String title = "Confirmation",
String message = "Are you sure you want to continue?",
}) {
showModalBottomSheet(
context: context,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
backgroundColor: Colors.white,
builder: (context) {
return Padding(
padding: const EdgeInsets.fromLTRB(20, 20, 20, 30),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
/// 🔹 Title
Text(
title,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 12),
/// 🔹 Message
Text(
message,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 15, color: Colors.grey[700]),
),
const SizedBox(height: 24),
/// 🔹 Buttons
Row(
children: [
Expanded(
child: OutlinedButton(
onPressed: () {
Navigator.pop(context);
Future.microtask(() => onCancel?.call());
},
child: const Text('Cancel'),
),
),
const SizedBox(width: 12),
Expanded(
child: ElevatedButton(
onPressed: () {
Navigator.pop(context);
Future.microtask(() => onAccept());
},
child: const Text('Accept'),
),
),
],
),
],
),
);
},
);
}
}

View File

View File