cliams bug fix

This commit is contained in:
Surendiran 2026-06-09 09:11:30 +05:30
parent 016a049a5c
commit 78d4d786a7
10 changed files with 4676 additions and 1003 deletions

File diff suppressed because one or more lines are too long

View File

@ -5,8 +5,8 @@ class Env {
);
static const String apiUrl = String.fromEnvironment(
'API_URL',
defaultValue: 'https://partner.nhanceindia.in/partner_api/api/', /* Live build (enable index.html line 18) */
// defaultValue: 'https://venbait.in/nhance/partner/dev/api/', /* Test build (enable index.html line 19) */
// defaultValue: 'https://partner.nhanceindia.in/partner_api/api/', /* Live build (enable index.html line 18) */
defaultValue: 'https://venbait.in/nhance/partner/dev/api/', /* Test build (enable index.html line 19) */
// defaultValue: 'http://localhost/nhance_partner_be/', /* localhost build (enable index.html line 19) */
);
// static const String baseUrl = String.fromEnvironment(

View File

@ -1895,37 +1895,77 @@ class ApiService {
return response;
}
Future<Map<String, dynamic>> fetchClaimList(
managerId,
int userId,
role,
) async {
// print(_token);
/// GET /claims with optional filters (e.g. manager_id, claim_type_id, from_date).
Future<Map<String, dynamic>> fetchClaims({
int? managerId,
int? agentId,
int? handlerId,
int? staffId,
int? claimTypeId,
int? claimStatusId,
int? insurerId,
String? policyNumber,
String? fromDate,
String? toDate,
}) async {
if (_token == null) {
await _initializeToken();
}
final url;
if (role == 'manager') {
url = Uri.parse('${Env.apiUrl}claim/ClaimList?manager_id=$managerId');
} else if (role == 'Accounts') {
url = Uri.parse('${Env.apiUrl}claim/ClaimList?manager_id=$managerId');
} else if (role == 'agent') {
url = Uri.parse('${Env.apiUrl}claim/ClaimList?agent_id=$userId');
} else if (role == 'handler') {
url = Uri.parse('${Env.apiUrl}claim/ClaimList?handler_id=$userId');
} else {
url = Uri.parse('${Env.apiUrl}claim/ClaimList?staff_id=$userId');
final query = <String, String>{};
void addInt(String key, int? value) {
if (value != null) query[key] = value.toString();
}
void addStr(String key, String? value) {
final trimmed = value?.trim();
if (trimmed != null && trimmed.isNotEmpty) {
query[key] = trimmed;
}
}
addInt('manager_id', managerId);
addInt('agent_id', agentId);
addInt('handler_id', handlerId);
addInt('staff_id', staffId);
addInt('claim_type_id', claimTypeId);
addInt('claim_status_id', claimStatusId);
addInt('insurer_id', insurerId);
addStr('policy_number', policyNumber);
addStr('from_date', fromDate);
addStr('to_date', toDate);
final url = Uri.parse('${Env.apiUrl}claim/ClaimList').replace(
queryParameters: query.isEmpty ? null : query,
);
final headers = {
'Authorization': 'Bearer $_token' ?? '',
'app-signature': Env.App_Signature,
};
final response = await _makeGetRequest(url, headers);
return response;
return _makeGetRequest(url, headers);
}
@Deprecated('Use fetchClaims with query parameters')
Future<Map<String, dynamic>> fetchClaimList(
managerId,
int userId,
role,
) async {
final roleStr = role?.toString().toLowerCase() ?? '';
return fetchClaims(
managerId: (roleStr == 'manager' || roleStr == 'accounts')
? int.tryParse(managerId?.toString() ?? '')
: null,
agentId: roleStr == 'agent' ? userId : null,
handlerId: roleStr == 'handler' ? userId : null,
staffId: (roleStr != 'manager' &&
roleStr != 'accounts' &&
roleStr != 'agent' &&
roleStr != 'handler')
? userId
: null,
);
}
Future<Map<String, dynamic>> findSingleClaimData(id) async {
@ -1943,6 +1983,54 @@ class ApiService {
return response;
}
/// GET claim/claimStatusList active claim statuses for filters & forms.
Future<Map<String, dynamic>> fetchClaimStatusList() async {
if (_token == null) {
await _initializeToken();
}
final url = Uri.parse('${Env.apiUrl}claim/claimStatusList');
final headers = {
'Authorization': 'Bearer $_token' ?? '',
'app-signature': Env.App_Signature,
};
return _makeGetRequest(url, headers);
}
Future<Map<String, dynamic>> fetchClaimById(dynamic id) async {
if (_token == null) {
await _initializeToken();
}
final url = Uri.parse(
'${Env.apiUrl}claim/getClaimById',
).replace(queryParameters: {'id': id.toString()});
final headers = {
'Authorization': 'Bearer $_token',
'app-signature': Env.App_Signature,
};
return _makeGetRequest(url, headers);
}
/// GET claim/deleteClaim?id=&updated_by=
Future<Map<String, dynamic>> deleteClaim({
required dynamic id,
required dynamic updatedBy,
}) async {
if (_token == null) {
await _initializeToken();
}
final url = Uri.parse('${Env.apiUrl}claim/deleteClaim').replace(
queryParameters: {
'id': id.toString(),
'updated_by': updatedBy.toString(),
},
);
final headers = {
'Authorization': 'Bearer $_token' ?? '',
'app-signature': Env.App_Signature,
};
return _makeGetRequest(url, headers);
}
// ----------------------------------- ENDORSEMENT -------------------------------------------------
Future<Map<String, dynamic>> fetchEndorsementList(
@ -2047,6 +2135,10 @@ class ApiService {
url = Uri.parse('${Env.apiUrl}master/getStaffMaster');
} else if (val == 'Claim') {
url = Uri.parse('${Env.apiUrl}master/getClaimMaster');
} else if (val == 'Claim Status' || val == 'ClaimStatus') {
url = Uri.parse('${Env.apiUrl}master/getClaimStatusMaster');
} else if (val == 'Status') {
url = Uri.parse('${Env.apiUrl}master/getStatusMaster');
} else if (val == 'Endorsement') {
url = Uri.parse('${Env.apiUrl}master/getEndorsementMaster');
} else if (val == 'Broker') {

View File

@ -18,6 +18,7 @@ import '../../../themes/indicators/customizd_file_upload.dart';
import '../../../themes/indicators/input_field_decoration.dart';
import '../../../themes/indicators/search_field_theme.dart';
import '../../../themes/indicators/text_field_theme.dart';
import '../../../widgets/policy_search_results_list.dart';
// 🔹 Custom Dialog Widget
class AddDialog extends StatefulWidget {
@ -629,43 +630,24 @@ class _AddDialogState extends State<AddDialog> {
? null
: MediaQuery.of(context).size.width * 0.26,
),
// Vehicle Search Results
if (filteredVehicleData.isNotEmpty)
Container(
width:
MediaQuery.of(context).size.width * 0.26, // optional
height: 150,
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: Colors.blueGrey.shade100),
borderRadius: BorderRadius.circular(5),
),
child: ListView.builder(
itemCount: filteredVehicleData.length,
itemBuilder: (context, index) {
final vehicle = filteredVehicleData[index];
return InkWell(
onTap: () {
setState(() {
controllers['policyNum']?.text =
vehicle['policy_number'];
filteredVehicleData.clear();
});
},
child: Container(
padding: const EdgeInsets.symmetric(
vertical: 3,
horizontal: 8,
),
// color: Colors.amber,
child: Text(
vehicle['policy_number'] ?? '-',
style: _textStyle1,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
);
SizedBox(
width: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
child: PolicySearchResultsList(
rows: filteredVehicleData,
fromVehicle: true,
onSelected: (vehicle) {
setState(() {
controllers['policyNum']?.text =
PolicySearchUtils.policyNumberFromRow(vehicle);
_vehicleSearchController.text =
PolicySearchUtils.vehicleInputValueOnSelect(
vehicle,
);
filteredVehicleData.clear();
});
},
),
),

View File

@ -19,6 +19,7 @@ import '../../../themes/indicators/customizd_file_upload.dart';
import '../../../themes/indicators/input_field_decoration.dart';
import '../../../themes/indicators/search_field_theme.dart';
import '../../../themes/indicators/text_field_theme.dart';
import '../../../widgets/policy_search_results_list.dart';
class CreateEndorsementDialog extends ConsumerStatefulWidget {
final String title;
@ -881,66 +882,27 @@ class _CreateEndorsementDialogState
},
),
/// 🔹 Vehicle Results Dropdown
if (filteredVehicleData.isNotEmpty)
Container(
margin: const EdgeInsets.only(top: 6),
height: 150,
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: const Color(0xFFE5E7EB),
),
borderRadius: BorderRadius.circular(
12,
),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(
0.05,
),
blurRadius: 6,
),
],
),
child: ListView.builder(
padding: EdgeInsets.zero,
itemCount:
filteredVehicleData.length,
itemBuilder: (context, index) {
final vehicle =
filteredVehicleData[index];
return InkWell(
onTap: () {
setState(() {
controllers['policyNum']
?.text =
vehicle['policy_number'] ??
'';
_vehicleSearchController
.text =
vehicle['policy_number'] ??
'';
filteredVehicleData.clear();
});
},
child: Padding(
padding:
const EdgeInsets.symmetric(
vertical: 8,
horizontal: 12,
),
child: Text(
vehicle['policy_number'] ??
'-',
style: _textStyle1,
overflow:
TextOverflow.ellipsis,
),
),
);
},
),
PolicySearchResultsList(
rows: filteredVehicleData,
fromVehicle: true,
borderRadius: 12,
onSelected: (vehicle) {
setState(() {
controllers['policyNum']?.text =
PolicySearchUtils
.policyNumberFromRow(
vehicle,
);
_vehicleSearchController.text =
PolicySearchUtils
.vehicleInputValueOnSelect(
vehicle,
);
filteredVehicleData.clear();
});
validateSteps();
},
),
],
),
@ -969,66 +931,26 @@ class _CreateEndorsementDialogState
},
),
/// 🔹 Policy Results Dropdown
if (filteredPolicyData.isNotEmpty)
Container(
margin: const EdgeInsets.only(top: 6),
height: 150,
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: const Color(0xFFE5E7EB),
),
borderRadius: BorderRadius.circular(
12,
),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(
0.05,
),
blurRadius: 6,
),
],
),
child: ListView.builder(
padding: EdgeInsets.zero,
itemCount:
filteredPolicyData.length,
itemBuilder: (context, index) {
final policy =
filteredPolicyData[index];
return InkWell(
onTap: () {
setState(() {
controllers['policyNum']
?.text =
policy['policy_number'] ??
'';
_policySearchController
.text =
policy['policy_number'] ??
'';
filteredPolicyData.clear();
});
},
child: Padding(
padding:
const EdgeInsets.symmetric(
vertical: 8,
horizontal: 12,
),
child: Text(
policy['policy_number'] ??
'-',
style: _textStyle1,
overflow:
TextOverflow.ellipsis,
),
),
PolicySearchResultsList(
rows: filteredPolicyData,
fromVehicle: false,
borderRadius: 12,
onSelected: (policy) {
setState(() {
final policyNo =
PolicySearchUtils
.policyNumberFromRow(
policy,
);
},
),
controllers['policyNum']?.text =
policyNo;
_policySearchController.text =
policyNo;
filteredPolicyData.clear();
});
validateSteps();
},
),
],
),

View File

@ -30,6 +30,7 @@ import 'package:flutter/services.dart';
import '../../../themes/indicators/search_field_theme.dart';
import '../../../themes/indicators/text_field_theme.dart';
import '../../../widgets/policy_search_results_list.dart';
final digitsOnlyFormatter = [FilteringTextInputFormatter.digitsOnly];
@ -1083,84 +1084,32 @@ class _endorsomentValidationState extends ConsumerState<endorsomentValidation> {
},
),
/// 🔹 Vehicle Results Dropdown
if (filteredVehicleData
.isNotEmpty)
Container(
margin:
const EdgeInsets.only(
top: 6,
),
height: 150,
decoration: BoxDecoration(
color:
Colors.white,
border: Border.all(
color:
const Color(
0xFFE5E7EB,
),
),
borderRadius:
BorderRadius.circular(
12,
),
boxShadow: [
BoxShadow(
color: Colors
.black
.withOpacity(
0.05,
),
blurRadius: 6,
),
],
),
child: ListView.builder(
padding:
EdgeInsets
.zero,
itemCount:
filteredVehicleData
.length,
itemBuilder: (context, index) {
final vehicle =
filteredVehicleData[index];
return InkWell(
onTap: () {
setState(() {
controllers['policyNum']
?.text =
vehicle['policy_number'] ??
'';
_vehicleSearchController
.text =
vehicle['policy_number'] ??
'';
filteredVehicleData
.clear();
});
},
child: Padding(
padding: const EdgeInsets.symmetric(
vertical:
8,
horizontal:
12,
),
child: Text(
vehicle['policy_number'] ??
'-',
style:
_textStyle1,
overflow:
TextOverflow
.ellipsis,
),
),
PolicySearchResultsList(
rows:
filteredVehicleData,
fromVehicle: true,
borderRadius: 12,
onSelected:
(vehicle) {
setState(() {
controllers[
'policyNum']
?.text = PolicySearchUtils
.policyNumberFromRow(
vehicle,
);
},
),
_vehicleSearchController
.text =
PolicySearchUtils
.vehicleInputValueOnSelect(
vehicle,
);
filteredVehicleData
.clear();
});
},
),
],
),
@ -1196,84 +1145,32 @@ class _endorsomentValidationState extends ConsumerState<endorsomentValidation> {
},
),
/// 🔹 Policy Results Dropdown
if (filteredPolicyData
.isNotEmpty)
Container(
margin:
const EdgeInsets.only(
top: 6,
),
height: 150,
decoration: BoxDecoration(
color:
Colors.white,
border: Border.all(
color:
const Color(
0xFFE5E7EB,
),
),
borderRadius:
BorderRadius.circular(
12,
),
boxShadow: [
BoxShadow(
color: Colors
.black
.withOpacity(
0.05,
),
blurRadius: 6,
),
],
),
child: ListView.builder(
padding:
EdgeInsets
.zero,
itemCount:
filteredPolicyData
.length,
itemBuilder: (context, index) {
final policy =
filteredPolicyData[index];
return InkWell(
onTap: () {
setState(() {
controllers['policyNum']
?.text =
policy['policy_number'] ??
'';
_policySearchController
.text =
policy['policy_number'] ??
'';
filteredPolicyData
.clear();
});
},
child: Padding(
padding: const EdgeInsets.symmetric(
vertical:
8,
horizontal:
12,
),
child: Text(
policy['policy_number'] ??
'-',
style:
_textStyle1,
overflow:
TextOverflow
.ellipsis,
),
),
PolicySearchResultsList(
rows:
filteredPolicyData,
fromVehicle: false,
borderRadius: 12,
onSelected:
(policy) {
setState(() {
final policyNo =
PolicySearchUtils
.policyNumberFromRow(
policy,
);
},
),
controllers[
'policyNum']
?.text =
policyNo;
_policySearchController
.text =
policyNo;
filteredPolicyData
.clear();
});
},
),
],
),

View File

@ -0,0 +1,170 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
/// Shared helpers for vehicle / policy search API dropdown results.
class PolicySearchUtils {
PolicySearchUtils._();
static List<Map<String, dynamic>> normalizeData(dynamic data) {
if (data == null) return [];
if (data is List) {
final out = <Map<String, dynamic>>[];
for (final item in data) {
if (item is Map) {
out.add(Map<String, dynamic>.from(item));
}
}
return out;
}
if (data is Map) {
return [Map<String, dynamic>.from(data)];
}
return [];
}
static String? rcNoFromRow(Map<String, dynamic> row) {
final rc = (row['rc_no'] ??
row['reg_no'] ??
row['vehicle_number'] ??
row['registration_no'] ??
'')
.toString()
.trim();
return rc.isEmpty ? null : rc;
}
static String insuredNameFromRow(Map<String, dynamic> row) {
return (row['customer_name'] ??
row['insured_name'] ??
row['proposer_name'] ??
row['name'] ??
'')
.toString()
.trim();
}
static String policyNumberFromRow(Map<String, dynamic> row) {
return (row['policy_number'] ?? '').toString().trim();
}
/// Value for the "Search By Vehicle Number" input after selection.
static String vehicleInputValueOnSelect(Map<String, dynamic> row) {
final rc = rcNoFromRow(row);
if (rc != null && rc.isNotEmpty) return rc;
final policy = policyNumberFromRow(row);
return policy.isNotEmpty ? policy : '';
}
}
/// Dropdown list for vehicle or policy search matches [AddClaimStepperDialog].
class PolicySearchResultsList extends StatelessWidget {
static const Color _border = Color(0xFFE2E8F0);
static const Color _muted = Color(0xFF64748B);
static const Color _titleColor = Color(0xFF0F172A);
const PolicySearchResultsList({
super.key,
required this.rows,
required this.fromVehicle,
required this.onSelected,
this.height = 150,
this.borderRadius = 10,
});
final List<Map<String, dynamic>> rows;
final bool fromVehicle;
final ValueChanged<Map<String, dynamic>> onSelected;
final double height;
final double borderRadius;
@override
Widget build(BuildContext context) {
if (rows.isEmpty) return const SizedBox.shrink();
return Container(
margin: const EdgeInsets.only(top: 6),
height: height,
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: _border),
borderRadius: BorderRadius.circular(borderRadius),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.05),
blurRadius: 6,
),
],
),
child: ListView.builder(
padding: EdgeInsets.zero,
itemCount: rows.length,
itemBuilder: (context, index) {
final row = rows[index];
final policy = PolicySearchUtils.policyNumberFromRow(row);
final rcNo = PolicySearchUtils.rcNoFromRow(row) ?? '';
final name = PolicySearchUtils.insuredNameFromRow(row);
final title = policy.isNotEmpty ? policy : rcNo;
return InkWell(
onTap: () => onSelected(row),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (fromVehicle) ...[
Text(
rcNo.isNotEmpty ? rcNo : '-',
style: GoogleFonts.inter(
fontSize: 12,
fontWeight: FontWeight.w600,
color: _titleColor,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
if (policy.isNotEmpty)
Padding(
padding: const EdgeInsets.only(top: 2),
child: Text(
policy,
style: GoogleFonts.inter(
fontSize: 10,
color: _muted,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
),
] else ...[
Text(
title.isNotEmpty ? title : '-',
style: GoogleFonts.inter(
fontSize: 12,
fontWeight: FontWeight.w600,
color: _titleColor,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
if (name.isNotEmpty)
Padding(
padding: const EdgeInsets.only(top: 2),
child: Text(
name,
style: GoogleFonts.inter(
fontSize: 10,
color: _muted,
),
),
),
],
],
),
),
);
},
),
);
}
}

View File

@ -15,8 +15,8 @@
the `--base-href` argument provided to `flutter build`.
-->
<!-- <base href="$FLUTTER_BASE_HREF"> -->
<base href="/partner/"> Live build: also check env.dart (line 8)
<!-- <base href="/nhance/partner/app/"> -->
<base href="/partner/">
<!-- <base href="/nhance/partner/app/">-->
<!-- <base href="{Env.baseHref}">-->
<meta charset="UTF-8">