enquiry issue fix
This commit is contained in:
parent
6c65a71d1f
commit
1ceccdcd43
File diff suppressed because one or more lines are too long
@ -1,4 +1,5 @@
|
|||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
@ -70,6 +71,8 @@ class EnquiryHandlerState extends ConsumerState<EnquiryListHandler> {
|
|||||||
bool isLoading = false;
|
bool isLoading = false;
|
||||||
dynamic roleId;
|
dynamic roleId;
|
||||||
bool _showFilterRow = false;
|
bool _showFilterRow = false;
|
||||||
|
Timer? _staleAssignedBlinkTimer;
|
||||||
|
bool _isBlinkPhaseOn = false;
|
||||||
|
|
||||||
Map<String, TextEditingController> controllers = {};
|
Map<String, TextEditingController> controllers = {};
|
||||||
List<String> tabHeader = [
|
List<String> tabHeader = [
|
||||||
@ -240,6 +243,30 @@ class EnquiryHandlerState extends ConsumerState<EnquiryListHandler> {
|
|||||||
getVehicleType();
|
getVehicleType();
|
||||||
getInsurers();
|
getInsurers();
|
||||||
getBroker();
|
getBroker();
|
||||||
|
|
||||||
|
_staleAssignedBlinkTimer = Timer.periodic(
|
||||||
|
const Duration(milliseconds: 700),
|
||||||
|
(_) {
|
||||||
|
if (!mounted) return;
|
||||||
|
setState(() {
|
||||||
|
_isBlinkPhaseOn = !_isBlinkPhaseOn;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_staleAssignedBlinkTimer?.cancel();
|
||||||
|
for (final controller in controllers.values) {
|
||||||
|
controller.dispose();
|
||||||
|
}
|
||||||
|
for (final rowControlMap in rowControllers.values) {
|
||||||
|
for (final controller in rowControlMap.values) {
|
||||||
|
controller.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _initializeToken() async {
|
Future<void> _initializeToken() async {
|
||||||
@ -2588,9 +2615,17 @@ class EnquiryHandlerState extends ConsumerState<EnquiryListHandler> {
|
|||||||
print('idPrimary - $idPrimary');
|
print('idPrimary - $idPrimary');
|
||||||
final editing = isEditingRow[id] ?? false;
|
final editing = isEditingRow[id] ?? false;
|
||||||
final controllers = rowControllers[id];
|
final controllers = rowControllers[id];
|
||||||
|
final shouldHighlight = _shouldHighlightAssignedRow(item);
|
||||||
|
|
||||||
return DataRow(
|
return DataRow(
|
||||||
cells: [
|
color: shouldHighlight
|
||||||
|
? WidgetStatePropertyAll(
|
||||||
|
_isBlinkPhaseOn
|
||||||
|
? const Color(0xFFFFF3E0)
|
||||||
|
: const Color(0xFFFFFFFF),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
cells: _decorateCellsForStaleAssigned([
|
||||||
// S.No.
|
// S.No.
|
||||||
// DataCell(Text('$sno', style: _dataBold)),
|
// DataCell(Text('$sno', style: _dataBold)),
|
||||||
|
|
||||||
@ -2859,10 +2894,96 @@ class EnquiryHandlerState extends ConsumerState<EnquiryListHandler> {
|
|||||||
|
|
||||||
// Status
|
// Status
|
||||||
DataCell(Text(item['status'] ?? '-', style: _dataBold)),
|
DataCell(Text(item['status'] ?? '-', style: _dataBold)),
|
||||||
],
|
], shouldHighlight),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<DataCell> _decorateCellsForStaleAssigned(
|
||||||
|
List<DataCell> cells,
|
||||||
|
bool shouldHighlight,
|
||||||
|
) {
|
||||||
|
if (!shouldHighlight) return cells;
|
||||||
|
|
||||||
|
final borderColor = _isBlinkPhaseOn
|
||||||
|
? const Color(0xFFE65100)
|
||||||
|
: const Color(0x00000000);
|
||||||
|
|
||||||
|
return cells
|
||||||
|
.map(
|
||||||
|
(cell) => DataCell(
|
||||||
|
Container(
|
||||||
|
width: double.infinity,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 3),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(color: borderColor, width: 1.3),
|
||||||
|
borderRadius: BorderRadius.circular(2),
|
||||||
|
),
|
||||||
|
child: cell.child,
|
||||||
|
),
|
||||||
|
placeholder: cell.placeholder,
|
||||||
|
showEditIcon: cell.showEditIcon,
|
||||||
|
onTap: cell.onTap,
|
||||||
|
onDoubleTap: cell.onDoubleTap,
|
||||||
|
onLongPress: cell.onLongPress,
|
||||||
|
onTapDown: cell.onTapDown,
|
||||||
|
onTapCancel: cell.onTapCancel,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _shouldHighlightAssignedRow(Map<String, dynamic> item) {
|
||||||
|
final rawStatus = (item['enquiry_status'] ?? '').toString().trim();
|
||||||
|
if (rawStatus.isEmpty) return false;
|
||||||
|
|
||||||
|
final normalizedStatus = rawStatus.toLowerCase();
|
||||||
|
final isAssignedStatus =
|
||||||
|
normalizedStatus == 'assigned' ||
|
||||||
|
(normalizedStatus.contains('assigned') &&
|
||||||
|
!normalizedStatus.contains('to be assigned'));
|
||||||
|
if (!isAssignedStatus) return false;
|
||||||
|
|
||||||
|
final assignedAt = _parseAssignedDateTime(item);
|
||||||
|
if (assignedAt == null) return false;
|
||||||
|
|
||||||
|
return DateTime.now().difference(assignedAt) >= const Duration(minutes: 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime? _parseAssignedDateTime(Map<String, dynamic> item) {
|
||||||
|
final rawDate = [
|
||||||
|
item['assigned_to_datetime'],
|
||||||
|
item['assigned_datetime'],
|
||||||
|
item['assigned_on'],
|
||||||
|
item['updated_on'],
|
||||||
|
].firstWhere(
|
||||||
|
(value) => value != null && value.toString().trim().isNotEmpty,
|
||||||
|
orElse: () => null,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (rawDate == null) return null;
|
||||||
|
|
||||||
|
final value = rawDate.toString().trim();
|
||||||
|
try {
|
||||||
|
return DateTime.parse(value);
|
||||||
|
} catch (_) {}
|
||||||
|
|
||||||
|
final parsers = [
|
||||||
|
DateFormat('dd-MM-yyyy hh:mm a'),
|
||||||
|
DateFormat('dd-MM-yyyy HH:mm'),
|
||||||
|
DateFormat('yyyy-MM-dd HH:mm:ss'),
|
||||||
|
DateFormat('yyyy-MM-dd HH:mm'),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (final parser in parsers) {
|
||||||
|
try {
|
||||||
|
return parser.parse(value);
|
||||||
|
} catch (_) {
|
||||||
|
// try next parser
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
static final _dataBold = TextStyle(
|
static final _dataBold = TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
|
|
||||||
|
|||||||
@ -66,6 +66,8 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
int totalCompletedPages = 1;
|
int totalCompletedPages = 1;
|
||||||
List<int> itemsPerPageOptions = [25, 50, 100, 200];
|
List<int> itemsPerPageOptions = [25, 50, 100, 200];
|
||||||
Timer? _debounce;
|
Timer? _debounce;
|
||||||
|
Timer? _staleAssignedBlinkTimer;
|
||||||
|
bool _isBlinkPhaseOn = false;
|
||||||
late ApiService apiService;
|
late ApiService apiService;
|
||||||
dynamic userId;
|
dynamic userId;
|
||||||
dynamic idPrimary;
|
dynamic idPrimary;
|
||||||
@ -275,6 +277,15 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
// timer = Timer.periodic(Duration(seconds: 10), (Timer t) => callRefresh()); //static
|
// timer = Timer.periodic(Duration(seconds: 10), (Timer t) => callRefresh()); //static
|
||||||
|
|
||||||
startTimer();
|
startTimer();
|
||||||
|
_staleAssignedBlinkTimer = Timer.periodic(
|
||||||
|
const Duration(milliseconds: 700),
|
||||||
|
(_) {
|
||||||
|
if (!mounted) return;
|
||||||
|
setState(() {
|
||||||
|
_isBlinkPhaseOn = !_isBlinkPhaseOn;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
for (String field in tabHeader) {
|
for (String field in tabHeader) {
|
||||||
controllers[field] = TextEditingController();
|
controllers[field] = TextEditingController();
|
||||||
}
|
}
|
||||||
@ -501,6 +512,7 @@ if (managerId != null &&
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
_staleAssignedBlinkTimer?.cancel();
|
||||||
refreshSub.close();
|
refreshSub.close();
|
||||||
_horizontalScrollController.dispose();
|
_horizontalScrollController.dispose();
|
||||||
// ... dispose other controllers ...
|
// ... dispose other controllers ...
|
||||||
@ -2484,15 +2496,29 @@ if (managerId != null &&
|
|||||||
final id = int.tryParse(data['id'].toString()) ?? 0;
|
final id = int.tryParse(data['id'].toString()) ?? 0;
|
||||||
final selectId = data['id'].toString() ?? '0';
|
final selectId = data['id'].toString() ?? '0';
|
||||||
|
|
||||||
return Container(
|
final isStaleAssigned = _shouldHighlightAssignedRow(data);
|
||||||
width: MediaQuery
|
final rowBorderColor = isStaleAssigned
|
||||||
.of(context)
|
? (_isBlinkPhaseOn
|
||||||
.size
|
? const Color(0xFFE65100)
|
||||||
.width,
|
: const Color(0xFFFFCDD2))
|
||||||
margin: EdgeInsets.fromLTRB(12, 8, 12, 8),
|
: const Color(0xFFFFECF1F7);
|
||||||
|
final rowBgColor = isStaleAssigned
|
||||||
|
? (_isBlinkPhaseOn
|
||||||
|
? const Color(0xFFFFF3E0)
|
||||||
|
: Colors.white)
|
||||||
|
: Colors.white;
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(12, 8, 12, 8),
|
||||||
|
child: Container(
|
||||||
|
width: double.infinity,
|
||||||
|
clipBehavior: Clip.antiAlias,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: rowBgColor,
|
||||||
border: Border.all(color: Color(0xFFFFECF1F7)),
|
border: Border.all(
|
||||||
|
color: rowBorderColor,
|
||||||
|
width: isStaleAssigned ? 2.0 : 1.0,
|
||||||
|
),
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
@ -2503,10 +2529,11 @@ if (managerId != null &&
|
|||||||
border: TableBorder.all(color: Colors.transparent, width: 0),
|
border: TableBorder.all(color: Colors.transparent, width: 0),
|
||||||
headingRowHeight: 0,
|
headingRowHeight: 0,
|
||||||
dividerThickness: 0.1,
|
dividerThickness: 0.1,
|
||||||
|
horizontalMargin: 16,
|
||||||
columnSpacing: 20.0,
|
columnSpacing: 20.0,
|
||||||
dataRowMinHeight: 40,
|
dataRowMinHeight: 40,
|
||||||
columns: _buildDataColumns(),
|
columns: _buildDataColumns(),
|
||||||
rows: [_buildDataRow(data, sno)],
|
rows: [_buildDataRow(data, sno, isStaleAssigned: isStaleAssigned)],
|
||||||
),
|
),
|
||||||
|
|
||||||
// Expanded content
|
// Expanded content
|
||||||
@ -2568,6 +2595,7 @@ if (managerId != null &&
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -3314,7 +3342,41 @@ if (managerId != null &&
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Now the OPTIMIZED _buildDataRow method:
|
// 2. Now the OPTIMIZED _buildDataRow method:
|
||||||
DataRow _buildDataRow(Map<String, dynamic> item, int sno) {
|
bool _shouldHighlightAssignedRow(Map<String, dynamic> item) {
|
||||||
|
final rawStatus = (item['enquiry_status'] ?? '').toString().trim();
|
||||||
|
if (rawStatus.isEmpty) return false;
|
||||||
|
|
||||||
|
final normalized = rawStatus.toLowerCase();
|
||||||
|
if (normalized != 'assigned') return false;
|
||||||
|
|
||||||
|
final value = (item['assigned_to_datetime'] ?? '').toString().trim();
|
||||||
|
if (value.isEmpty) return false;
|
||||||
|
|
||||||
|
DateTime? assignedAt;
|
||||||
|
try {
|
||||||
|
assignedAt = DateTime.parse(value);
|
||||||
|
} catch (_) {
|
||||||
|
for (final fmt in [
|
||||||
|
DateFormat('dd-MM-yyyy hh:mm a'),
|
||||||
|
DateFormat('dd-MM-yyyy HH:mm'),
|
||||||
|
DateFormat('yyyy-MM-dd HH:mm:ss'),
|
||||||
|
DateFormat('yyyy-MM-dd HH:mm'),
|
||||||
|
]) {
|
||||||
|
try {
|
||||||
|
assignedAt = fmt.parse(value);
|
||||||
|
break;
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (assignedAt == null) return false;
|
||||||
|
return DateTime.now().difference(assignedAt) >= const Duration(minutes: 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
DataRow _buildDataRow(
|
||||||
|
Map<String, dynamic> item,
|
||||||
|
int sno, {
|
||||||
|
bool isStaleAssigned = false,
|
||||||
|
}) {
|
||||||
final id = int.tryParse(item['id'].toString()) ?? 0;
|
final id = int.tryParse(item['id'].toString()) ?? 0;
|
||||||
final selectId = item['id'].toString() ?? '0';
|
final selectId = item['id'].toString() ?? '0';
|
||||||
final status = item['enquiry_status'] ?? '-';
|
final status = item['enquiry_status'] ?? '-';
|
||||||
@ -3322,6 +3384,9 @@ if (managerId != null &&
|
|||||||
final borderColor = statusBorderColors[status] ?? Color(0xFFE2E8F0);
|
final borderColor = statusBorderColors[status] ?? Color(0xFFE2E8F0);
|
||||||
|
|
||||||
return DataRow(
|
return DataRow(
|
||||||
|
color: isStaleAssigned
|
||||||
|
? const WidgetStatePropertyAll(Colors.transparent)
|
||||||
|
: null,
|
||||||
cells: [
|
cells: [
|
||||||
// Enquiry Created Date
|
// Enquiry Created Date
|
||||||
DataCell(
|
DataCell(
|
||||||
|
|||||||
22
pubspec.lock
22
pubspec.lock
@ -117,10 +117,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: characters
|
name: characters
|
||||||
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
|
sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.0"
|
version: "1.4.1"
|
||||||
charcode:
|
charcode:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -780,26 +780,26 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: matcher
|
name: matcher
|
||||||
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
|
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.17"
|
version: "0.12.19"
|
||||||
material_color_utilities:
|
material_color_utilities:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.11.1"
|
version: "0.13.0"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: meta
|
name: meta
|
||||||
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
|
sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.16.0"
|
version: "1.18.0"
|
||||||
mime:
|
mime:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1297,10 +1297,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
|
sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.6"
|
version: "0.7.11"
|
||||||
toastification:
|
toastification:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -1502,5 +1502,5 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.3"
|
version: "3.1.3"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.8.1 <4.0.0"
|
dart: ">=3.10.0-0 <4.0.0"
|
||||||
flutter: ">=3.32.0"
|
flutter: ">=3.32.0"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user