657 lines
22 KiB
Dart
Executable File
657 lines
22 KiB
Dart
Executable File
import 'package:flutter/material.dart';
|
||
import 'package:google_fonts/google_fonts.dart';
|
||
import 'package:nhancepolicy/service/api_service.dart';
|
||
|
||
class ClaimHistoryPopup extends StatefulWidget {
|
||
final String ticket_id;
|
||
final String empName;
|
||
final String empCode;
|
||
final String policyType;
|
||
final String clientPolicyNo;
|
||
final String claimAmount;
|
||
final String claimNo;
|
||
final String postToken;
|
||
|
||
const ClaimHistoryPopup({
|
||
Key? key,
|
||
required this.ticket_id,
|
||
required this.empName,
|
||
required this.empCode,
|
||
required this.policyType,
|
||
required this.clientPolicyNo,
|
||
required this.claimAmount,
|
||
required this.claimNo,
|
||
required this.postToken,
|
||
}) : super(key: key);
|
||
|
||
@override
|
||
State<ClaimHistoryPopup> createState() => _ClaimHistoryPopupState();
|
||
}
|
||
|
||
class _ClaimHistoryPopupState extends State<ClaimHistoryPopup> {
|
||
late ApiService apiService;
|
||
List<Map<String, dynamic>> getClaimsHistoryList = [];
|
||
List<String> stepKeys = [];
|
||
late Map<String, dynamic> stepMap;
|
||
int _index = 4;
|
||
bool isLoading = false;
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
apiService = ApiService(context);
|
||
print(widget.postToken);
|
||
print(widget.claimAmount);
|
||
print(widget.claimNo);
|
||
print(widget.clientPolicyNo);
|
||
print(widget.empCode);
|
||
print(widget.policyType);
|
||
print(widget.ticket_id);
|
||
getClaimsHistoryDetails();
|
||
}
|
||
|
||
@override
|
||
void dispose() {
|
||
super.dispose();
|
||
}
|
||
|
||
Future<void> getClaimsHistoryDetails() async {
|
||
setState(() {
|
||
isLoading = true;
|
||
});
|
||
try {
|
||
print('10');
|
||
// final ticketID = widget.ticket_id;
|
||
// if (ticketID != '' || ticketID != null) {
|
||
// return;
|
||
// }
|
||
final response = await apiService.getClaimsHistoryToApi(
|
||
widget.ticket_id, widget.postToken);
|
||
if (response['status'] == 'success') {
|
||
setState(() {
|
||
isLoading = false;
|
||
});
|
||
setState(() {
|
||
getClaimsHistoryList = [
|
||
Map<String, dynamic>.from(response['data']['ticket_data'])
|
||
];
|
||
stepMap = getClaimsHistoryList[0];
|
||
stepKeys = stepMap.keys.toList();
|
||
print('Claims History List $getClaimsHistoryList');
|
||
// originalData = getCDPolicies;
|
||
// filteredData = List.from(originalData);
|
||
// print('filteredData');
|
||
// print(filteredData);
|
||
});
|
||
} else {
|
||
setState(() {
|
||
isLoading = false;
|
||
});
|
||
|
||
// ToastHelper.showWarningToast(
|
||
// context, 'Request failed with status: ${response.statusCode}');
|
||
print('Request failed with status: ${response['code']}');
|
||
}
|
||
} catch (e) {
|
||
setState(() {
|
||
isLoading = false;
|
||
});
|
||
print('Exception occurred: $e');
|
||
} finally {
|
||
setState(() {
|
||
isLoading = false;
|
||
});
|
||
}
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
// if (getClaimsHistoryList.isEmpty) {
|
||
// return SizedBox(
|
||
// height: 50,
|
||
// child: Center(child: Text('No available Claims')),
|
||
// );
|
||
// }
|
||
return Container(
|
||
constraints: BoxConstraints(maxWidth: 800, maxHeight: 800),
|
||
padding: EdgeInsets.all(20),
|
||
decoration: BoxDecoration(
|
||
color: Colors.white,
|
||
borderRadius: BorderRadius.circular(12),
|
||
),
|
||
child: SingleChildScrollView(
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Row(
|
||
children: [
|
||
Expanded(
|
||
child: Align(
|
||
alignment: Alignment.centerLeft,
|
||
child: Text(
|
||
'Claim History',
|
||
style: GoogleFonts.poppins(
|
||
fontSize: 20,
|
||
fontWeight: FontWeight.w500,
|
||
color: Color(0xFF101010),
|
||
),
|
||
),
|
||
),
|
||
),
|
||
MouseRegion(
|
||
cursor: SystemMouseCursors.click, // Show pointer cursor
|
||
child: GestureDetector(
|
||
onTap: () => Navigator.of(context).pop(),
|
||
child: Container(
|
||
height: 30,
|
||
width: 30,
|
||
decoration: BoxDecoration(
|
||
color: Colors.white,
|
||
border: Border.all(color: Color(0xFFBCBCBC)),
|
||
borderRadius: BorderRadius.circular(6),
|
||
),
|
||
child: const Icon(
|
||
Icons.close,
|
||
size: 25,
|
||
color: Color(0xFFBCBCBC),
|
||
),
|
||
),
|
||
),
|
||
)
|
||
],
|
||
),
|
||
SizedBox(height: 10),
|
||
Container(
|
||
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 20),
|
||
decoration: BoxDecoration(
|
||
color: Color(0xFFFFFFFF), // White background
|
||
borderRadius: BorderRadius.circular(12),
|
||
boxShadow: const [
|
||
BoxShadow(
|
||
color: Color(0xFFEBEBEB), // Shadow color
|
||
blurRadius: 14, // How soft the shadow is
|
||
spreadRadius: 2, // How much it spreads
|
||
offset: Offset(0, 1), // X and Y offset
|
||
),
|
||
],
|
||
),
|
||
padding: const EdgeInsets.all(16),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Row(
|
||
children: [
|
||
Expanded(
|
||
child: _buildKeyValue('Name',
|
||
'${widget.empName ?? ''} (${widget.empCode ?? ''})'),
|
||
),
|
||
SizedBox(width: 16),
|
||
Expanded(
|
||
child: _buildKeyValue('Policy Name',
|
||
'${widget.policyType ?? ''} - ${widget.clientPolicyNo ?? ''}')),
|
||
],
|
||
),
|
||
SizedBox(height: 16),
|
||
Row(
|
||
children: [
|
||
Expanded(
|
||
child: _buildKeyValue(
|
||
'Claim Amount', '₹${widget.claimAmount ?? ''}'),
|
||
),
|
||
SizedBox(width: 16),
|
||
Expanded(
|
||
child: _buildKeyValue(
|
||
'Claim Number', widget.claimNo ?? ''),
|
||
),
|
||
],
|
||
),
|
||
],
|
||
),
|
||
),
|
||
SizedBox(height: 10),
|
||
// Container(
|
||
// padding: const EdgeInsets.all(16),
|
||
// child: Stepper(
|
||
// currentStep: _index,
|
||
// onStepCancel: () {
|
||
// if (_index > 0) {
|
||
// setState(() {
|
||
// _index -= 1;
|
||
// });
|
||
// }
|
||
// },
|
||
// onStepContinue: () {
|
||
// if (_index < 4) {
|
||
// setState(() {
|
||
// _index += 1;
|
||
// });
|
||
// }
|
||
// },
|
||
// onStepTapped: (int index) {
|
||
// setState(() {
|
||
// _index = index;
|
||
// });
|
||
// },
|
||
// steps: <Step>[
|
||
// Step(
|
||
// title: Text('Step 1: PAYMENT INITIATED'),
|
||
// content: Text('Pay Initiate Date: 05-05-2025'),
|
||
// isActive: true,
|
||
// state: StepState.complete,
|
||
// ),
|
||
// Step(
|
||
// title: Text('Step 2: INFORMATION REQUIRED'),
|
||
// content: Text('Raised Date: 05-05-2025'),
|
||
// isActive: true,
|
||
// state: StepState.complete,
|
||
// ),
|
||
// Step(
|
||
// title: Text('Step 3: CLAIM NO. UPDATION'),
|
||
// content: Column(
|
||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||
// children: [
|
||
// Text('Claim Number: 4315440'),
|
||
// Text('Registration Date: 05-05-2025'),
|
||
// ],
|
||
// ),
|
||
// isActive: true,
|
||
// state: StepState.complete,
|
||
// ),
|
||
// Step(
|
||
// title: Text('Step 4: QUERY DOCUMENT REQUIRED'),
|
||
// content: Text('Query Received Date: 05-05-2025'),
|
||
// isActive: true,
|
||
// state: StepState.complete,
|
||
// ),
|
||
// Step(
|
||
// title: Text('Step 5: APPROVED'),
|
||
// content: Column(
|
||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||
// children: [
|
||
// Text('Approved Amount: 4315440'),
|
||
// Text('Approved Date: 05-05-2025'),
|
||
// Text('Approved Letter: Lorem ipsum...'),
|
||
// Text('Description: Lorem ipsum...'),
|
||
// ],
|
||
// ),
|
||
// isActive: true,
|
||
// state: StepState.complete,
|
||
// ),
|
||
// ],
|
||
// ),
|
||
// )
|
||
// Column(
|
||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||
// children: List.generate(5, (index) {
|
||
// return _buildStep(
|
||
// stepNumber: index + 1,
|
||
// title: _getStepTitle(index),
|
||
// content: _getStepContent(index),
|
||
// isLast: index == 4,
|
||
// );
|
||
// }),
|
||
// )
|
||
|
||
isLoading
|
||
? Container(
|
||
// color: Color(0x98FFFCE5), // Semi-transparent background
|
||
child: Center(
|
||
child: // Your GIF loader widget
|
||
Image.asset(
|
||
height: 60,
|
||
width: 60,
|
||
'assets/nhance-loader.gif'), // Adjust path to your GIF loader
|
||
),
|
||
)
|
||
: Container(
|
||
child: getClaimsHistoryList.isNotEmpty
|
||
? Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: List.generate(stepKeys.length, (index) {
|
||
String stepTitleKey = stepKeys[index];
|
||
Map<String, dynamic> stepData =
|
||
stepMap[stepTitleKey];
|
||
|
||
print('stepTitleKey');
|
||
print(stepTitleKey);
|
||
print('stepData');
|
||
print(stepData);
|
||
|
||
Widget content = _getStepContentFromApi(stepData);
|
||
print('check');
|
||
print(context);
|
||
|
||
// // 🟡 Skip step if there's no valid content (e.g., ID NOT GENERATED case)
|
||
// if ((content as Column).children.isEmpty) {
|
||
// print(
|
||
// "Skipping step $stepTitleKey due to no valid content");
|
||
// content = Text("No content available",
|
||
// style: TextStyle(color: Colors.grey));
|
||
// // or `return Container()`
|
||
// }
|
||
|
||
// if (content == null) {
|
||
// print(
|
||
// "Skipping step: $stepTitleKey due to no valid content");
|
||
// return const SizedBox(); // Completely skip step
|
||
// }
|
||
|
||
return _buildStep(
|
||
stepNumber: index + 1,
|
||
title: _getStepTitleFromApi(
|
||
stepTitleKey, stepData),
|
||
content: content,
|
||
|
||
// content: _getStepContentFromApi(stepData),
|
||
isLast: index == stepKeys.length - 1,
|
||
);
|
||
}),
|
||
)
|
||
: Container(
|
||
height: MediaQuery.of(context).size.height * 0.4,
|
||
// color: Colors.red,
|
||
child: Center(
|
||
child: Column(
|
||
children: [
|
||
Image.asset(
|
||
'assets/claimsData.png', // Replace 'default_image.png' with your default image asset path
|
||
width: 350,
|
||
height: 350,
|
||
fit: BoxFit.cover,
|
||
),
|
||
const Text(
|
||
'No Available Claims',
|
||
style: TextStyle(
|
||
fontWeight: FontWeight.w500,
|
||
fontSize: 15),
|
||
),
|
||
],
|
||
)),
|
||
),
|
||
)
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildStep({
|
||
required int stepNumber,
|
||
// required String title,
|
||
required Widget title,
|
||
required Widget content,
|
||
bool isLast = false,
|
||
}) {
|
||
print(title);
|
||
print("contentss - $content");
|
||
final noContent;
|
||
if ((content as Column).children.isEmpty) {
|
||
noContent = 0;
|
||
} else {
|
||
noContent = 1;
|
||
}
|
||
|
||
return Row(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
// Left Column with circle + line
|
||
Column(
|
||
children: [
|
||
// Add top spacing before circle
|
||
SizedBox(height: stepNumber == 1 ? 0 : 4),
|
||
|
||
// Step number circle
|
||
Container(
|
||
height: 28,
|
||
width: 28,
|
||
decoration: BoxDecoration(
|
||
color: Color(0xFF00A5A8),
|
||
shape: BoxShape.circle,
|
||
),
|
||
alignment: Alignment.center,
|
||
child: Text(
|
||
'$stepNumber',
|
||
style: TextStyle(
|
||
color: Colors.white,
|
||
fontSize: 13,
|
||
fontWeight: FontWeight.w600,
|
||
),
|
||
),
|
||
),
|
||
|
||
// Dotted line below circle (except for last step)
|
||
if (!isLast)
|
||
Container(
|
||
height: noContent == 1 ? 70 : 25, // increase to extend line
|
||
width: 2,
|
||
margin: EdgeInsets.only(top: 4, bottom: 4),
|
||
child: CustomPaint(
|
||
painter: DottedLinePainter(),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
|
||
SizedBox(width: 12),
|
||
|
||
// Right Side: Step title and content
|
||
|
||
Expanded(
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
title,
|
||
if (noContent == 1) SizedBox(height: noContent == 0 ? 0 : 8),
|
||
if (noContent == 1)
|
||
Container(
|
||
width: double.infinity,
|
||
padding: EdgeInsets.all(12),
|
||
decoration: BoxDecoration(
|
||
color: Color(0xFFF7F7F7),
|
||
borderRadius: BorderRadius.circular(8),
|
||
border: Border.all(color: Color(0xFFE0E0E0)),
|
||
),
|
||
child: content,
|
||
),
|
||
if (noContent == 1) SizedBox(height: isLast ? 0 : 16),
|
||
],
|
||
),
|
||
),
|
||
],
|
||
);
|
||
}
|
||
|
||
// String _getStepTitleFromApi(String status, Map<String, dynamic> data) {
|
||
// final modifiedBy = data['modified_by'] ?? '';
|
||
// final modifiedAt = data['modified_at'] ?? '';
|
||
// return '$status ($modifiedBy – $modifiedAt)';
|
||
// }
|
||
|
||
Widget _getStepTitleFromApi(String status, Map<String, dynamic> data) {
|
||
final modifiedBy = data['modified_by'] ?? '';
|
||
final modifiedAt = data['modified_at'] ?? '';
|
||
final symbol = (data['modified_by'] != null && data['modified_by'] != '') ? ' - ' : '';
|
||
|
||
return RichText(
|
||
text: TextSpan(
|
||
children: [
|
||
TextSpan(
|
||
text: status,
|
||
style: GoogleFonts.poppins(
|
||
fontSize: 15,
|
||
fontWeight: FontWeight.w500,
|
||
color: Color(0xFF212120), // Status color
|
||
),
|
||
),
|
||
TextSpan(
|
||
text: ' ($modifiedBy$symbol$modifiedAt)',
|
||
style: GoogleFonts.poppins(
|
||
fontSize: 14,
|
||
fontWeight: FontWeight.w400,
|
||
color: Color(0xFF565656), // Subtitle color
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _getStepContentFromApi(Map<String, dynamic> data) {
|
||
List<Widget> rows = [];
|
||
|
||
print("data - $data");
|
||
|
||
// bool hasDisplayFields(Map<String, dynamic> map) {
|
||
// for (var entry in map.entries) {
|
||
// if (entry.value is Map<String, dynamic>) {
|
||
// final innerMap = entry.value as Map<String, dynamic>;
|
||
// if (innerMap.containsKey('display_name') ||
|
||
// innerMap.containsKey('display_value')) {
|
||
// print("display fields found");
|
||
// return true;
|
||
// }
|
||
// }
|
||
// }
|
||
// return false;
|
||
// }
|
||
//
|
||
// if (!hasDisplayFields(data)) {
|
||
// print("❌ Skipping because no display fields found");
|
||
// return SizedBox.shrink(); // or return an empty Container/Spacer if needed
|
||
// }
|
||
|
||
data.forEach((key, value) {
|
||
// Skip metadata
|
||
if (key == 'modified_by' || key == 'modified_at') return;
|
||
|
||
if (value is Map<String, dynamic>) {
|
||
final displayName = value['display_name'];
|
||
final displayValue = value['display_value'];
|
||
|
||
if (displayName != null && displayValue != null) {
|
||
print("✅ displayName - $displayName, displayValue - $displayValue");
|
||
rows.add(_buildHistoryListData(displayName, displayValue));
|
||
rows.add(SizedBox(height: 6));
|
||
}
|
||
}
|
||
});
|
||
|
||
// data.forEach((key, value) {
|
||
// // Skip metadata fields
|
||
// if (key == 'modified_by' || key == 'modified_at') return;
|
||
// print("ContentKey - $key");
|
||
// print("Content - $value");
|
||
// String displayName = value['display_name'] ?? key;
|
||
// String displayValue = value['display_value'] ?? 'N/A';
|
||
//
|
||
// print("displayName - $displayName");
|
||
// print("displayValue - $displayValue");
|
||
// if (displayName == 'N/A' || displayValue == 'N/A') return;
|
||
//
|
||
// rows.add(_buildHistoryListData(displayName, displayValue));
|
||
// rows.add(SizedBox(height: 6));
|
||
// });
|
||
|
||
return Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: rows,
|
||
);
|
||
}
|
||
|
||
Widget _buildKeyValue(String title, String value) {
|
||
final displayValue =
|
||
(value == null || value.trim().isEmpty) ? 'N/A' : value;
|
||
return Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Text(
|
||
title,
|
||
style: GoogleFonts.poppins(
|
||
color: Color(0xFF747474),
|
||
fontWeight: FontWeight.w400,
|
||
fontSize: 16,
|
||
),
|
||
),
|
||
SizedBox(height: 4),
|
||
Text(
|
||
displayValue,
|
||
style: GoogleFonts.poppins(
|
||
color: Color(0xFF000000),
|
||
fontWeight: FontWeight.w500,
|
||
fontSize: 16,
|
||
),
|
||
),
|
||
],
|
||
);
|
||
}
|
||
|
||
Widget _buildHistoryListData(String title, String value) {
|
||
print("_buildHistoryListData");
|
||
final displayValue =
|
||
(value == null || value.trim().isEmpty) ? 'N/A' : value;
|
||
|
||
return Padding(
|
||
padding: const EdgeInsets.symmetric(vertical: 6), // optional spacing
|
||
child: Row(
|
||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||
crossAxisAlignment: CrossAxisAlignment.center,
|
||
children: [
|
||
// Title - Align to center left
|
||
Expanded(
|
||
child: Align(
|
||
alignment: Alignment.centerLeft,
|
||
child: Text(
|
||
title,
|
||
style: GoogleFonts.poppins(
|
||
color: const Color(0xFF747474),
|
||
fontWeight: FontWeight.w400,
|
||
fontSize: 14,
|
||
),
|
||
),
|
||
),
|
||
),
|
||
|
||
// Value - Align to center right
|
||
Expanded(
|
||
child: Align(
|
||
alignment: Alignment.centerRight,
|
||
child: Text(
|
||
displayValue,
|
||
style: GoogleFonts.poppins(
|
||
color: const Color(0xFF000000),
|
||
fontWeight: FontWeight.w400,
|
||
fontSize: 14,
|
||
),
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
}
|
||
|
||
class DottedLinePainter extends CustomPainter {
|
||
@override
|
||
void paint(Canvas canvas, Size size) {
|
||
const dashHeight = 2.0;
|
||
const dashSpace = 3.0;
|
||
double startY = 0;
|
||
final paint = Paint()
|
||
..color = Colors.grey.shade400
|
||
..strokeWidth = 1;
|
||
|
||
while (startY < size.height) {
|
||
canvas.drawLine(
|
||
Offset(0, startY),
|
||
Offset(0, startY + dashHeight),
|
||
paint,
|
||
);
|
||
startY += dashHeight + dashSpace;
|
||
}
|
||
}
|
||
|
||
@override
|
||
bool shouldRepaint(CustomPainter oldDelegate) => false;
|
||
}
|