Your changes

This commit is contained in:
divya abdar
2025-12-11 18:36:11 +05:30
parent 3bf27cc29d
commit 9faf983b95
36 changed files with 4677 additions and 1046 deletions

View File

@@ -4,7 +4,11 @@ import '../services/invoice_service.dart';
class InvoiceInstallmentScreen extends StatefulWidget {
final int invoiceId;
const InvoiceInstallmentScreen({super.key, required this.invoiceId});
const InvoiceInstallmentScreen({
super.key,
required this.invoiceId,
});
@override
State<InvoiceInstallmentScreen> createState() =>
@@ -35,39 +39,188 @@ class _InvoiceInstallmentScreenState extends State<InvoiceInstallmentScreen> {
@override
Widget build(BuildContext context) {
final width = MediaQuery.of(context).size.width;
return Scaffold(
appBar: AppBar(title: const Text("Installments")),
backgroundColor: Colors.grey.shade100,
appBar: AppBar(
title: const Text("Installments"),
elevation: 1,
),
body: loading
? const Center(child: CircularProgressIndicator())
: installments.isEmpty
? const Center(
child: Text("Installments not created yet",
style: TextStyle(fontSize: 18)),
)
? _buildEmptyState()
: ListView.builder(
padding: const EdgeInsets.all(16),
padding: EdgeInsets.symmetric(
horizontal: width * 0.04,
vertical: 16,
),
itemCount: installments.length,
itemBuilder: (_, i) {
final inst = installments[i];
return Card(
child: ListTile(
title: Text(
"Amount: ₹${inst['amount']?.toString() ?? '0'}"),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Date: ${inst['installment_date'] ?? 'N/A'}"),
Text(
"Payment: ${inst['payment_method'] ?? 'N/A'}"),
Text(
"Reference: ${inst['reference_no'] ?? 'N/A'}"),
],
),
),
);
return InstallmentCard(inst: installments[i]);
},
),
);
}
Widget _buildEmptyState() {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.receipt_long,
size: 70, color: Colors.grey.shade400),
const SizedBox(height: 12),
Text(
"No Installments Created",
style: TextStyle(
fontSize: 18,
color: Colors.grey.shade600,
),
),
],
),
);
}
}
class InstallmentCard extends StatelessWidget {
final Map inst;
const InstallmentCard({super.key, required this.inst});
String getString(key) => inst[key]?.toString() ?? "N/A";
@override
Widget build(BuildContext context) {
final width = MediaQuery.of(context).size.width;
final isTablet = width > 600;
final padding = isTablet ? 28.0 : 20.0;
final amountSize = isTablet ? 30.0 : 26.0;
return LayoutBuilder(
builder: (context, constraints) {
return Container(
margin: const EdgeInsets.only(bottom: 18),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(18),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 12,
offset: const Offset(0, 4),
),
],
),
child: Padding(
padding: EdgeInsets.all(padding),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Amount + Payment Method Row
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"${getString('amount')}",
style: TextStyle(
fontSize: amountSize,
fontWeight: FontWeight.bold,
letterSpacing: 0.2,
),
),
// Payment Chip
Container(
padding: EdgeInsets.symmetric(
vertical: isTablet ? 8 : 6,
horizontal: isTablet ? 16 : 12,
),
decoration: BoxDecoration(
color: Colors.blue.shade50,
borderRadius: BorderRadius.circular(50),
),
child: Text(
getString('payment_method'),
style: TextStyle(
fontWeight: FontWeight.w600,
color: Colors.blue.shade700,
fontSize: isTablet ? 15 : 13.5,
),
),
),
],
),
SizedBox(height: isTablet ? 24 : 18),
// Responsive Info Rows
buildInfoRow(
Icons.calendar_month,
"Date",
getString("installment_date"),
isTablet
),
SizedBox(height: isTablet ? 14 : 10),
buildInfoRow(
Icons.confirmation_number,
"Reference",
getString("reference_no"),
isTablet
),
SizedBox(height: isTablet ? 24 : 18),
Divider(color: Colors.grey.shade300, thickness: 1),
SizedBox(height: isTablet ? 10 : 6),
Align(
alignment: Alignment.centerRight,
child: Text(
"Installment #${inst['id'] ?? ''}",
style: TextStyle(
fontSize: isTablet ? 15 : 13,
color: Colors.grey.shade600,
fontWeight: FontWeight.w500,
),
),
),
],
),
),
);
},
);
}
/// Responsive info row builder
Widget buildInfoRow(IconData icon, String label, String value, bool isTablet) {
return Row(
children: [
Icon(icon, size: isTablet ? 24 : 20, color: Colors.grey.shade600),
const SizedBox(width: 10),
Text(
"$label:",
style: TextStyle(
fontSize: isTablet ? 17 : 15,
fontWeight: FontWeight.w600,
color: Colors.grey.shade700,
),
),
const SizedBox(width: 6),
Expanded(
child: Text(
value,
style: TextStyle(
fontSize: isTablet ? 16 : 15,
color: Colors.grey.shade800,
fontWeight: FontWeight.w500,
),
),
),
],
);
}
}