UI_HEADER_ICON UI_ERR_MSG_CONTENT
This commit is contained in:
parent
3c7ce422a9
commit
5e6c091faa
@ -368,7 +368,6 @@ class ApiService {
|
||||
await _initializeToken();
|
||||
}
|
||||
|
||||
final userId = '1';
|
||||
final url;
|
||||
|
||||
if (role == 'manager') {
|
||||
@ -389,6 +388,20 @@ class ApiService {
|
||||
return response;
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> findSingleEnquiryData(id) async {
|
||||
// print(_token);
|
||||
if (_token == null) {
|
||||
await _initializeToken();
|
||||
}
|
||||
final url = Uri.parse('${Env.apiUrl}enquiry/enquiryList?enquiry_id=$id');
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
};
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
return response;
|
||||
}
|
||||
|
||||
//------------------------------------ Quotation ------------------------------------------------
|
||||
|
||||
Future<Map<String, dynamic>> fetchQuotationList(int managerId) async {
|
||||
|
||||
@ -1,10 +1,15 @@
|
||||
import 'package:dropdown_search/dropdown_search.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:nhance_partner/presentation/layouts/responsive_layout.dart';
|
||||
import 'package:universal_html/html.dart' as html;
|
||||
|
||||
import '../../../../core/config/env.dart';
|
||||
import '../../../../core/routing/routes.dart';
|
||||
import '../../../../core/services/api_service.dart';
|
||||
import '../../../../data/services/auth_service.dart';
|
||||
import '../../../../data/utils/Pagination.dart';
|
||||
@ -47,18 +52,24 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
'remarks',
|
||||
];
|
||||
late String isActive = "1";
|
||||
html.File? docUploadedRCFile;
|
||||
html.File? docUploadedIDProof;
|
||||
html.File? docUploadedPrevPolicy;
|
||||
// PlatformFile? passportFile;
|
||||
|
||||
PlatformFile? docUploadedRCFile;
|
||||
PlatformFile? docUploadedIDProof;
|
||||
PlatformFile? docUploadedPrevPolicy;
|
||||
|
||||
String? selectedRCFile;
|
||||
String? selectedIdProof;
|
||||
String? selectedPrevPolicy;
|
||||
String? passportFileUrlFromApi;
|
||||
|
||||
String? rcFileUrlFromApi;
|
||||
String? idProofFileUrlFromApi;
|
||||
String? prevPolicyFileUrlFromApi;
|
||||
|
||||
String? selectedId;
|
||||
bool isLoading = false;
|
||||
|
||||
String? selectedVehicleType;
|
||||
int? selectedVehicleTypeId;
|
||||
String? selectedInsurer;
|
||||
|
||||
Map<String, TextEditingController> controllers = {};
|
||||
@ -109,7 +120,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
for (String field in tabHeader) {
|
||||
controllers[field] = TextEditingController();
|
||||
}
|
||||
// updateData();
|
||||
|
||||
_initializeToken();
|
||||
Future.microtask(() {
|
||||
managerId = ref.watch(managerIdProvider);
|
||||
@ -118,8 +129,10 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
|
||||
getVehicleType();
|
||||
getInsurers();
|
||||
updateData();
|
||||
}
|
||||
|
||||
// api/enquiry/enquiryList?enquiry_id=1
|
||||
Future<void> _initializeToken() async {
|
||||
_token = await AuthService.getToken();
|
||||
print("APISERTOKEN - $_token");
|
||||
@ -189,119 +202,205 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> handleSave() async {
|
||||
print("Handl1");
|
||||
final dataSet = dataDetails();
|
||||
print("dataSetAgent - $dataSet");
|
||||
print("Handl13f");
|
||||
if (!_formKey.currentState!.validate()) return;
|
||||
// if (passportFile == null) {
|
||||
// print("❌ No file selected!");
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// const SnackBar(content: Text("Please select a file before submitting")),
|
||||
// );
|
||||
// return;
|
||||
// }
|
||||
void updateData() async {
|
||||
// if (widget.id != null && widget.id != 'create') {
|
||||
|
||||
dynamic response = await apiService.findSingleEnquiryData(1);
|
||||
// dynamic response = await apiService.findSingleAgentData(widget.id!);
|
||||
final data = response['data'];
|
||||
print("updateData - ${response['data']}");
|
||||
|
||||
if (data == null) return;
|
||||
setState(() {
|
||||
// uploadIncentiveData(dataSet);
|
||||
});
|
||||
// selectedId = widget.id;
|
||||
controllers['name']?.text = data['name'] ?? '';
|
||||
controllers['email']?.text = data['email'] ?? '';
|
||||
controllers['mobile']?.text = data['mobile'] ?? '';
|
||||
controllers['regNo']?.text = data['reg_no'] ?? '';
|
||||
controllers['remarks']?.text = data['remarks'] ?? '';
|
||||
isActive = data["is_active"];
|
||||
// selectedVehicleType = data['vehicle_type_id'] ?? '2';
|
||||
selectedVehicleTypeId = 2;
|
||||
selectedInsurer = data['insurer_id'] ?? '3';
|
||||
|
||||
print("Handl2");
|
||||
String? apiDocPath = data["rc_file_name"];
|
||||
if (apiDocPath != null && apiDocPath.isNotEmpty) {
|
||||
print('apiDocPath - $apiDocPath');
|
||||
selectedRCFile = apiDocPath.split('/').last;
|
||||
print('selectedRCFile - $selectedRCFile');
|
||||
rcFileUrlFromApi = apiDocPath;
|
||||
print('rcFileUrlFromApi - $rcFileUrlFromApi');
|
||||
docUploadedRCFile = null;
|
||||
} else {
|
||||
selectedRCFile = null;
|
||||
docUploadedRCFile = null;
|
||||
rcFileUrlFromApi = null;
|
||||
}
|
||||
|
||||
String? apiDocPathRC = data["id_proof_file_name"];
|
||||
if (apiDocPathRC != null && apiDocPathRC.isNotEmpty) {
|
||||
print('apiDocPathRC - $apiDocPathRC');
|
||||
selectedIdProof = apiDocPathRC.split('/').last;
|
||||
print('selectedIdProof - $selectedIdProof');
|
||||
prevPolicyFileUrlFromApi = apiDocPathRC;
|
||||
print('prevPolicyFileUrlFromApi - $prevPolicyFileUrlFromApi');
|
||||
docUploadedIDProof = null;
|
||||
} else {
|
||||
selectedIdProof = null;
|
||||
docUploadedIDProof = null;
|
||||
prevPolicyFileUrlFromApi = null;
|
||||
}
|
||||
|
||||
String? apiDocPathPrevPolicy = data["previous_policy_file_name"];
|
||||
if (apiDocPathPrevPolicy != null && apiDocPathPrevPolicy.isNotEmpty) {
|
||||
print('apiDocPathPrevPolicy - $apiDocPathPrevPolicy');
|
||||
selectedPrevPolicy = apiDocPathPrevPolicy.split('/').last;
|
||||
print('selectedPrevPolicy - $selectedPrevPolicy');
|
||||
idProofFileUrlFromApi = apiDocPathPrevPolicy;
|
||||
print('idProofFileUrlFromApi - $idProofFileUrlFromApi');
|
||||
docUploadedPrevPolicy = null;
|
||||
} else {
|
||||
selectedPrevPolicy = null;
|
||||
docUploadedPrevPolicy = null;
|
||||
idProofFileUrlFromApi = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Future<void> uploadIncentiveData(Map<String, dynamic> dataSet) async {
|
||||
// final uri = Uri.parse('${Env.apiUrl}agent/uploadAgentIncentiveFile');
|
||||
// // 'https://venbait.in/nhance/partner/dev/api/agent/uploadAgentIncentiveFile',
|
||||
// if (_token == null) {
|
||||
// throw Exception('Token not found. Please log in.');
|
||||
// }
|
||||
// // Use MultipartRequest (POST only)
|
||||
// final request = http.MultipartRequest('POST', uri);
|
||||
// request.headers['Authorization'] = 'Bearer $_token';
|
||||
// request.headers['app-signature'] =
|
||||
// 'nhance-partner-2025-signature-35468846JRhH551HK';
|
||||
//
|
||||
// print("USerDAta - $dataSet");
|
||||
//
|
||||
// dataSet.forEach((key, value) {
|
||||
// request.fields[key] = value.toString();
|
||||
// print("✅ Encoded travel_details2: ${request.fields[key]}");
|
||||
// });
|
||||
//
|
||||
// // Attach file if selected
|
||||
// if (passportFile != null) {
|
||||
// try {
|
||||
// final reader = html.FileReader();
|
||||
// reader.readAsArrayBuffer(passportFile!);
|
||||
// await reader.onLoad.first;
|
||||
//
|
||||
// final data = reader.result as Uint8List;
|
||||
//
|
||||
// final multipartFile = http.MultipartFile.fromBytes(
|
||||
// 'incentive_file_name',
|
||||
// data,
|
||||
// filename: passportFile!.name,
|
||||
// );
|
||||
//
|
||||
// request.files.add(multipartFile);
|
||||
// print("📎 File attached: ${passportFile!.name}");
|
||||
// } catch (e) {
|
||||
// print("❌ Failed to read file: $e");
|
||||
// }
|
||||
// } else {
|
||||
// print("⚠️ No passport file selected.");
|
||||
// }
|
||||
//
|
||||
// print("🚀 Sending request with fields: ${request.fields}");
|
||||
//
|
||||
// try {
|
||||
// final streamedResponse = await request.send();
|
||||
// final response = await http.Response.fromStream(streamedResponse);
|
||||
// print("Response status: ${response.statusCode}");
|
||||
// print("Response body: ${response.body}");
|
||||
//
|
||||
// if (response.statusCode == 200 || response.statusCode == 201) {
|
||||
// // dispose();
|
||||
// print("✅ Agent submitted successfully!");
|
||||
//
|
||||
// print("📨 Response: ${response.body}");
|
||||
//
|
||||
// final data = dataDetails(); // this is a Map<String, dynamic>
|
||||
// final agentId = data["agent_id"];
|
||||
//
|
||||
// getAgentIncenctiveFileList(agentId);
|
||||
// // context.go(AppRoutes.agentLst);
|
||||
// } else {
|
||||
// print("❌ Submission failed. Status: ${response.statusCode}");
|
||||
// print("📨 Body: ${response.body}");
|
||||
//
|
||||
// // Sort by created_on (latest first)
|
||||
//
|
||||
// showDialog(
|
||||
// context: context,
|
||||
// builder: (BuildContext context) {
|
||||
// return AlertDialog(
|
||||
// title: Text("Agent Creation Failed"),
|
||||
// content: Text(
|
||||
// "There was a problem in creating user. Please try again.",
|
||||
// ),
|
||||
// actions: [
|
||||
// TextButton(
|
||||
// child: Text("OK"),
|
||||
// onPressed: () {
|
||||
// Navigator.of(context).pop();
|
||||
// },
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// },
|
||||
// );
|
||||
// }
|
||||
// } catch (e) {
|
||||
// print("🔥 Error submitting user: $e");
|
||||
// }
|
||||
// }
|
||||
Future<void> handleSave() async {
|
||||
if (!_formKey.currentState!.validate()) return;
|
||||
setState(() {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
dataDetails();
|
||||
final dataSet = dataDetails();
|
||||
print("dataSetAgent - $dataSet");
|
||||
print("managerId - $managerId ,userId - $userId ");
|
||||
createUserData(dataSet);
|
||||
} else {
|
||||
// isDisable = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> attachFiles(http.MultipartRequest request) async {
|
||||
Future<void> addFile(PlatformFile? file, String fieldName) async {
|
||||
if (file == null) return;
|
||||
try {
|
||||
if (file.bytes != null) {
|
||||
final multipartFile = http.MultipartFile.fromBytes(
|
||||
fieldName,
|
||||
file.bytes!,
|
||||
filename: file.name,
|
||||
);
|
||||
request.files.add(multipartFile);
|
||||
} else if (file.path != null) {
|
||||
final multipartFile = await http.MultipartFile.fromPath(
|
||||
fieldName,
|
||||
file.path!,
|
||||
filename: file.name,
|
||||
);
|
||||
request.files.add(multipartFile);
|
||||
}
|
||||
print("📎 File attached: ${file.name} → $fieldName");
|
||||
} catch (e) {
|
||||
print("❌ Failed to attach $fieldName: $e");
|
||||
}
|
||||
}
|
||||
|
||||
await addFile(docUploadedRCFile, 'rc_file_name');
|
||||
await addFile(docUploadedIDProof, 'id_proof_file_name');
|
||||
await addFile(docUploadedPrevPolicy, 'previous_policy_file_name');
|
||||
}
|
||||
|
||||
Future<void> createUserData(Map<String, dynamic> userData) async {
|
||||
// final bool isUpdating = widget.id != null && widget.id != 'create';
|
||||
// final id = widget.id;
|
||||
final bool isUpdating = false;
|
||||
final uri = Uri.parse(
|
||||
// isUpdating
|
||||
// ? '${Env.apiUrl}agent/updateAgent'
|
||||
// : '${Env.apiUrl}agent/createAgent',
|
||||
'${Env.apiUrl}enquiry/createEnquiry',
|
||||
);
|
||||
if (_token == null) {
|
||||
throw Exception('Token not found. Please log in.');
|
||||
}
|
||||
|
||||
// Use MultipartRequest (POST only)
|
||||
final request = http.MultipartRequest('POST', uri);
|
||||
request.headers['Authorization'] = 'Bearer $_token';
|
||||
request.headers['app-signature'] =
|
||||
'nhance-partner-2025-signature-35468846JRhH551HK';
|
||||
|
||||
// If updating, spoof the method Laravel-style
|
||||
if (isUpdating) {
|
||||
// request.fields['id'] = id!;
|
||||
request.fields['updated_by'] = userId!.toString();
|
||||
} else {
|
||||
request.fields['created_by'] = userId!.toString();
|
||||
}
|
||||
|
||||
print("USerDAta - $userData");
|
||||
|
||||
// userData.forEach((key, value) {
|
||||
// request.fields[key] = value.toString();
|
||||
// print("✅ Encoded travel_details2: ${request.fields[key]}");
|
||||
// });
|
||||
|
||||
userData.forEach((key, value) {
|
||||
if (key != 'certificate_file_name') {
|
||||
request.fields[key] = value.toString();
|
||||
print("✅ Encoded $key: ${request.fields[key]}");
|
||||
}
|
||||
});
|
||||
|
||||
// attach files
|
||||
await attachFiles(request);
|
||||
|
||||
// request.fields['agent_id'] = selectedId.toString();
|
||||
|
||||
print(" Sending request with fields: ${request.fields}");
|
||||
|
||||
try {
|
||||
final streamedResponse = await request.send();
|
||||
final response = await http.Response.fromStream(streamedResponse);
|
||||
print("Response status: ${response.statusCode}");
|
||||
print("Response body: ${response.body}");
|
||||
|
||||
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||
// dispose();
|
||||
print("✅ Agent submitted successfully!");
|
||||
|
||||
print("Response: ${response.body}");
|
||||
context.go(AppRoutes.tabEnquiry);
|
||||
} else {
|
||||
print("❌ Submission failed. Status: ${response.statusCode}");
|
||||
print("Body: ${response.body}");
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text("Agent Creation Failed"),
|
||||
content: Text(
|
||||
"There was a problem in creating user. Please try again.",
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: Text("OK"),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
print("🔥 Error submitting user: $e");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -425,7 +524,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(label, style: _textStyle),
|
||||
Expanded(child: Text(label, style: _textStyle)),
|
||||
const SizedBox(width: 10),
|
||||
field,
|
||||
],
|
||||
@ -440,12 +539,6 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
}) {
|
||||
final isMobile = ResponsiveLayout.isMobile(context);
|
||||
|
||||
// final uploadWidget = ThemedUploadField(
|
||||
// hintText: hintText ?? "Upload Document",
|
||||
// txtwidth: isMobile ? null : MediaQuery.of(context).size.width * 0.26,
|
||||
// onFileSelected: onFileSelected,
|
||||
// );
|
||||
|
||||
final uploadWidget = ThemedUploadField(
|
||||
hintText: hintText ?? "Upload Document",
|
||||
txtwidth: MediaQuery.of(context).size.width * 0.26,
|
||||
@ -466,7 +559,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(label, style: _textStyle),
|
||||
Expanded(child: Text(label, style: _textStyle)),
|
||||
const SizedBox(width: 10),
|
||||
uploadWidget,
|
||||
],
|
||||
@ -476,7 +569,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
|
||||
Widget buildName(BuildContext context) {
|
||||
return buildResponsiveField(
|
||||
label: "Name *",
|
||||
label: "Full Name ",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['name']!,
|
||||
validator: (value) => Validators.requiredField(value, "name"),
|
||||
@ -489,7 +582,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
|
||||
Widget buildEmail(BuildContext context) {
|
||||
return buildResponsiveField(
|
||||
label: "Email *",
|
||||
label: "Email",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['email']!,
|
||||
validator: (value) => Validators.email(value, "email"),
|
||||
@ -502,7 +595,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
|
||||
Widget buildPhNumber(BuildContext context) {
|
||||
return buildResponsiveField(
|
||||
label: "Phone Number *",
|
||||
label: "Phone Number",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['mobile']!,
|
||||
validator: (value) => Validators.phone(value, "phNumber"),
|
||||
@ -515,7 +608,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
|
||||
Widget buildId(BuildContext context) {
|
||||
return buildResponsiveField(
|
||||
label: "Registration Number *",
|
||||
label: "Registration Number",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['regNo']!,
|
||||
validator: (value) => Validators.requiredField(value, "regNo"),
|
||||
@ -527,6 +620,12 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
}
|
||||
|
||||
Widget buildVehicleType(BuildContext context) {
|
||||
// Find the matching map from your list
|
||||
Map<String, dynamic>? selectedVehicle = filteredVechicleData.firstWhere(
|
||||
(item) => item['id'] == selectedVehicleTypeId,
|
||||
orElse: () => {},
|
||||
);
|
||||
|
||||
return buildResponsiveField(
|
||||
label: "Vehicle Type",
|
||||
field: Container(
|
||||
@ -537,12 +636,12 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
// height: 40,
|
||||
child: DropdownSearch<Map<String, dynamic>>(
|
||||
key: dropDownKey,
|
||||
selectedItem: null,
|
||||
selectedItem: selectedVehicle.isNotEmpty ? selectedVehicle : null,
|
||||
items: (filter, infiniteScrollProps) {
|
||||
return filteredVechicleData;
|
||||
},
|
||||
|
||||
itemAsString: (val) => val['vehicle_type'].toString(), // what to show
|
||||
itemAsString: (val) => val['vehicle_type'].toString(),
|
||||
compareFn: (item, selectedItem) =>
|
||||
item['id'] == selectedItem['id'], // ✅ compare by id
|
||||
decoratorProps: DropDownDecoratorProps(
|
||||
@ -713,7 +812,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
return buildResponsiveField(
|
||||
label: "Remarks",
|
||||
field: ThemedFormField(
|
||||
maxLength: 3,
|
||||
maxLength: 500,
|
||||
controller: controllers['remarks']!,
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
|
||||
@ -302,7 +302,7 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(label, style: _textStyle),
|
||||
Expanded(child: Text(label, style: _textStyle)),
|
||||
const SizedBox(height: 8),
|
||||
field,
|
||||
const SizedBox(height: 16),
|
||||
@ -312,7 +312,7 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(label, style: _textStyle),
|
||||
Expanded(child: Text(label, style: _textStyle)),
|
||||
const SizedBox(width: 10),
|
||||
field,
|
||||
],
|
||||
|
||||
@ -409,7 +409,7 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(label, style: _textStyle),
|
||||
Expanded(child: Text(label, style: _textStyle)),
|
||||
const SizedBox(width: 10),
|
||||
field,
|
||||
],
|
||||
@ -444,7 +444,7 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(label, style: _textStyle),
|
||||
Expanded(child: Text(label, style: _textStyle)),
|
||||
const SizedBox(width: 10),
|
||||
uploadWidget,
|
||||
],
|
||||
@ -465,38 +465,6 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDataTable5(BuildContext context) {
|
||||
if (filteredData.isEmpty) {
|
||||
return const SizedBox(
|
||||
height: 50,
|
||||
child: Center(child: Text('No available data')),
|
||||
);
|
||||
}
|
||||
|
||||
final sortedData = [...filteredData]
|
||||
..sort((a, b) => int.parse(b['id']) - int.parse(a['id']));
|
||||
return ListView.builder(
|
||||
itemCount: ResponsiveLayout.isMobile(context)
|
||||
? sortedData
|
||||
.length // only cards for mobile
|
||||
: sortedData.length + 1, // +1 for header in desktop
|
||||
itemBuilder: (context, index) {
|
||||
if (!ResponsiveLayout.isMobile(context) && index == 0) {
|
||||
return _buildHeader();
|
||||
}
|
||||
|
||||
final startIndex = (currentPage - 1) * itemsPerPage;
|
||||
final item =
|
||||
sortedData[index - (ResponsiveLayout.isMobile(context) ? 0 : 1)];
|
||||
final sno = startIndex + index;
|
||||
|
||||
return !ResponsiveLayout.isMobile(context)
|
||||
? _buildDataRow(item, sno)
|
||||
: _buildDataCard(item, sno);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDataTable(BuildContext context) {
|
||||
if (filteredData.isEmpty) {
|
||||
return const SizedBox(
|
||||
|
||||
@ -239,6 +239,8 @@ class AgentState extends ConsumerState<Agent> {
|
||||
print("Response: ${response.body}");
|
||||
context.go(AppRoutes.agentLst);
|
||||
} else {
|
||||
final responseBody = jsonDecode(response.body);
|
||||
dynamic msg = responseBody['data'];
|
||||
print("❌ Submission failed. Status: ${response.statusCode}");
|
||||
print("Body: ${response.body}");
|
||||
|
||||
@ -246,9 +248,10 @@ class AgentState extends ConsumerState<Agent> {
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text("Agent Creation Failed"),
|
||||
title: Text("Agent User Creation Failed"),
|
||||
content: Text(
|
||||
"There was a problem in creating user. Please try again.",
|
||||
msg,
|
||||
// "There was a problem in creating user. Please try again.",
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
@ -570,7 +573,8 @@ class AgentState extends ConsumerState<Agent> {
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
color: Colors.green.shade300,
|
||||
color: Color(0xFF425B5B),
|
||||
// color: Colors.green.shade300,
|
||||
),
|
||||
child: Row(
|
||||
children: const [
|
||||
|
||||
@ -161,6 +161,9 @@ class StaffState extends ConsumerState<Staff> {
|
||||
print("Response: ${response.body}");
|
||||
context.go(AppRoutes.staffLst);
|
||||
} else {
|
||||
final responseBody = jsonDecode(response.body);
|
||||
dynamic msg = responseBody['data'];
|
||||
|
||||
print("Failed to submit plan. Status: ${response.statusCode}");
|
||||
print("Error: ${response.body}");
|
||||
|
||||
@ -168,10 +171,8 @@ class StaffState extends ConsumerState<Staff> {
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text("Staff Creation Failed"),
|
||||
content: Text(
|
||||
"There was a problem submitting your plan. Please try again.",
|
||||
),
|
||||
title: Text("Staff User Creation Failed"),
|
||||
content: Text(msg),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: Text("OK"),
|
||||
|
||||
@ -19,11 +19,25 @@ class _MobileTabsState extends State<MobileTabs> {
|
||||
setState(() => _currentIndex = index);
|
||||
widget.onTabChanged(index);
|
||||
},
|
||||
items: const [
|
||||
BottomNavigationBarItem(icon: Icon(Icons.dashboard), label: "Home"),
|
||||
BottomNavigationBarItem(icon: Icon(Icons.person), label: "Profile"),
|
||||
items: [
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.event_note_sharp),
|
||||
icon: Image.asset(
|
||||
"assets/drawer/drawerImg1.png",
|
||||
height: 20,
|
||||
width: 20,
|
||||
),
|
||||
label: "Dashboard",
|
||||
),
|
||||
const BottomNavigationBarItem(
|
||||
icon: Icon(Icons.person),
|
||||
label: "Profile",
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Image.asset(
|
||||
"assets/drawer/drawerImg2.png",
|
||||
height: 20,
|
||||
width: 20,
|
||||
),
|
||||
label: "Enquiry",
|
||||
),
|
||||
],
|
||||
|
||||
@ -29,10 +29,16 @@ class TopBar extends StatelessWidget implements PreferredSizeWidget {
|
||||
backgroundColor: const Color(0xFFD6F6F4), // light cyan
|
||||
elevation: 0,
|
||||
automaticallyImplyLeading: false,
|
||||
titleSpacing: 0,
|
||||
titleSpacing: isMobile ? 0 : 30,
|
||||
title: Row(
|
||||
children: [
|
||||
if (isMobile)
|
||||
if (!isMobile)
|
||||
Image.asset(
|
||||
"assets/login/nhance-partner-logo.png",
|
||||
height: 60,
|
||||
width: 120,
|
||||
),
|
||||
if (isMobile) ...[
|
||||
IconButton(
|
||||
icon: const Icon(
|
||||
Icons.arrow_back_ios,
|
||||
@ -40,38 +46,70 @@ class TopBar extends StatelessWidget implements PreferredSizeWidget {
|
||||
size: 18,
|
||||
),
|
||||
onPressed: onBack ?? () => Navigator.pop(context),
|
||||
)
|
||||
else if (onMenuPressed != null)
|
||||
IconButton(
|
||||
icon: const Icon(Icons.menu, color: Colors.black87),
|
||||
onPressed: onMenuPressed,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
color: Colors.black87,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 16,
|
||||
|
||||
Expanded(
|
||||
child: Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
color: Colors.black87,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.notifications_none, color: Colors.black87),
|
||||
onPressed: onNotifications,
|
||||
],
|
||||
|
||||
Spacer(),
|
||||
|
||||
// else if (onMenuPressed != null)
|
||||
// IconButton(
|
||||
// icon: const Icon(Icons.menu, color: Colors.black87),
|
||||
// onPressed: onMenuPressed,
|
||||
// ),
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(50.0),
|
||||
),
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.notifications_none, color: Colors.black87),
|
||||
onPressed: onNotifications,
|
||||
),
|
||||
),
|
||||
if (!isMobile) ...[
|
||||
GestureDetector(
|
||||
onTapDown: (details) => onProfile!(details),
|
||||
child: const Icon(Icons.person_outline, color: Colors.black87),
|
||||
SizedBox(width: 10),
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(50.0),
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTapDown: (details) => onProfile!(details),
|
||||
child: const Icon(Icons.person_outline, color: Colors.black87),
|
||||
),
|
||||
),
|
||||
|
||||
// IconButton(
|
||||
// icon: const Icon(Icons.person_outline, color: Colors.black87),
|
||||
// onPressed: onProfile,
|
||||
// ),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.logout, color: Colors.black87),
|
||||
onPressed: onLogout,
|
||||
SizedBox(width: 10),
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(50.0),
|
||||
),
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.logout, color: Colors.black87),
|
||||
onPressed: onLogout,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
|
||||
Loading…
Reference in New Issue
Block a user