dashboard multiple filters added.

export_module_ui_ux_enhancement
Sikander Saleem 2 weeks ago
parent 164daa7d58
commit 7aa6637cba

@ -21,6 +21,7 @@ class AllRequestsProvider extends ChangeNotifier {
bool isHighPriorityLoading = false; bool isHighPriorityLoading = false;
bool isCalendarLoading = false; bool isCalendarLoading = false;
bool isLoading = false; bool isLoading = false;
bool isMultiFilterLoading = false;
bool _isFilterRequestLoading = false; bool _isFilterRequestLoading = false;
bool _isRequestCategoryLoading = false; bool _isRequestCategoryLoading = false;
@ -720,6 +721,57 @@ class AllRequestsProvider extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
Future<int> getDashboardMultifilterRequests(
BuildContext context, {
bool pagination = false,
List<int>? statusTransaction,
List<int>? priority,
List<int>? displayData,
}) async {
if (isMultiFilterLoading == true) return -2;
if (_allRequestsAndCount == null || pagination) {
isMultiFilterLoading = true;
notifyListeners();
}
Response response;
try {
Map<String, dynamic> body = {"typeTransaction": getStatues(context), "statusTransaction": statusTransaction ?? [], "priority": priority ?? [], "displayData": displayData ?? []};
if (pagination) {
body["pageNumber"] = 0;
body["pageSize"] = 0;
} else {
body["pageNumber"] = pageNum++;
body["pageSize"] = pageItemNumber;
}
response = await ApiManager.instance.post(URLs.getAllRequestsAndCount, body: body);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
if (_allRequestsAndCount == null) {
_allRequestsAndCount = (await AllRequestsAndCount.fromJson(json.decode(response.body)["data"][0]));
} else {
_allRequestsAndCount!.requestsDetails!.addAll((await AllRequestsAndCount.fromJson(json.decode(response.body)["data"][0])).requestsDetails!);
}
if (_allRequestsAndCount!.requestsDetails!.length >= pageItemNumber) {
nextPage = true;
} else {
nextPage = false;
}
notifyListeners();
} else {
_allRequestsAndCount = null;
}
isMultiFilterLoading = false;
notifyListeners();
return response.statusCode;
} catch (error) {
isMultiFilterLoading = false;
stateCode = -1;
notifyListeners();
return -1;
}
}
// Future<int> getCloseRequests() async { // Future<int> getCloseRequests() async {
// if (isCloseLoading == true) return -2; // if (isCloseLoading == true) return -2;
// isCloseLoading = true; // isCloseLoading = true;

@ -53,15 +53,52 @@ class DashBoardProvider extends ChangeNotifier {
int? get currentListIndex => _currentListIndex; int? get currentListIndex => _currentListIndex;
// Helper method to check if a tab index is UnAssigned
bool isUnassignedTab(int index) {
if (index >= 0 && index < tabs.length) {
return tabs[index].requestType == RequestTypeEnum.unassigned;
}
return false;
}
// Helper method to get the UnAssigned tab index (returns -1 if not found)
int getUnassignedTabIndex() {
for (int i = 0; i < tabs.length; i++) {
if (tabs[i].requestType == RequestTypeEnum.unassigned) {
return i;
}
}
return -1;
}
set currentListIndex(int? value) { set currentListIndex(int? value) {
_currentListIndex = value; _currentListIndex = value;
if (value == null) { if (value == null) {
listIndex.clear(); listIndex.clear();
}
else if (listIndex.contains(value)) {
listIndex.remove(value);
} else { } else {
listIndex.add(value); // Check if the selected tab is UnAssigned by its requestType
bool isUnassignedClicked = isUnassignedTab(value);
int unassignedIndex = getUnassignedTabIndex();
bool hasUnassignedSelected = unassignedIndex != -1 && listIndex.contains(unassignedIndex);
if (isUnassignedClicked) {
// UnAssigned is exclusive - clear all and select only UnAssigned
listIndex.clear();
listIndex.add(value);
} else {
// Other category clicked
if (hasUnassignedSelected) {
// If UnAssigned was selected, remove it first
listIndex.remove(unassignedIndex);
}
// Toggle the selected category
if (listIndex.contains(value)) {
listIndex.remove(value);
} else {
listIndex.add(value);
}
}
} }
notifyListeners(); notifyListeners();
} }
@ -130,8 +167,12 @@ class DashBoardProvider extends ChangeNotifier {
Provider.of<AllRequestsProvider>(context, listen: false) Provider.of<AllRequestsProvider>(context, listen: false)
..reset() ..reset()
..getAllRequests(context); ..getAllRequests(context);
} else if (listIndex.length == 1 && isUnassignedTab(listIndex[0])) {
// UnAssigned only - check by requestType, not by index
getRequestDetail(usersType: userType, status: tabs[listIndex[0]].tag, tabId: tabs[listIndex[0]].id);
} else { } else {
getRequestDetail(usersType: userType, status: tabs[currentListIndex!].tag, tabId: tabs[currentListIndex!].id); // Multiple categories selected
getMultiSelectCategoryRequests(usersType: userType, context: context);
} }
// notifyListeners(); // notifyListeners();
} }
@ -242,6 +283,73 @@ class DashBoardProvider extends ChangeNotifier {
getRequestDetail(showLoader: showLoader, usersType: usersType, status: 4); getRequestDetail(showLoader: showLoader, usersType: usersType, status: 4);
} }
void getMultiSelectCategoryRequests({
bool showLoader = true,
required UsersTypes usersType,
required BuildContext context,
bool? isAscending,
}) {
// Build filter arrays based on selected tabs
List<int> statusTransaction = [];
List<int> priority = [];
List<int> displayData = [];
for (int index in listIndex) {
if (index >= 0 && index < tabs.length) {
CategoryTabs tab = tabs[index];
// High Priority
if (tab.isHighPriority) {
if (!priority.contains(1)) priority.add(1);
}
// Overdue
if (tab.isOverDue) {
if (!displayData.contains(1)) displayData.add(1);
}
// Status categories (Open, InProgress, Completed, Closed)
if (!tab.isHighPriority && !tab.isOverDue && tab.requestType != RequestTypeEnum.unassigned) {
// Map requestType to status value
switch (tab.requestType) {
case RequestTypeEnum.open:
if (!statusTransaction.contains(1)) statusTransaction.add(1);
break;
case RequestTypeEnum.inProgress:
if (!statusTransaction.contains(2)) statusTransaction.add(2);
break;
case RequestTypeEnum.completed:
if (!statusTransaction.contains(4)) statusTransaction.add(4);
break;
case RequestTypeEnum.closed:
if (!statusTransaction.contains(4)) statusTransaction.add(4);
break;
case RequestTypeEnum.canceled:
if (!statusTransaction.contains(5)) statusTransaction.add(5);
break;
case RequestTypeEnum.pendingAcknowledgment:
if (!statusTransaction.contains(3)) statusTransaction.add(3);
break;
case RequestTypeEnum.unassigned:
case RequestTypeEnum.highPriority:
case RequestTypeEnum.overdue:
// These are handled separately above
break;
}
}
}
}
// Call the multi-filter API
Provider.of<AllRequestsProvider>(context, listen: false).getDashboardMultifilterRequests(
context,
pagination: false,
statusTransaction: statusTransaction,
priority: priority,
displayData: displayData,
);
}
Future<SwipeModel> makeSwipe({required Swipe model}) async { Future<SwipeModel> makeSwipe({required Swipe model}) async {
isLoading = true; isLoading = true;
SwipeModel swipeResponse = SwipeModel(data: false, message: '', responseCode: 0, isSuccess: false); SwipeModel swipeResponse = SwipeModel(data: false, message: '', responseCode: 0, isSuccess: false);

@ -5,6 +5,7 @@ import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/dashboard_latest/dashboard_provider.dart'; import 'package:test_sa/dashboard_latest/dashboard_provider.dart';
import 'package:test_sa/dashboard_latest/widgets/request_category_list.dart'; import 'package:test_sa/dashboard_latest/widgets/request_category_list.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/enum_extensions.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
@ -78,13 +79,26 @@ class _RequestCategoryFragmentState extends State<RequestCategoryFragment> with
// Reload data with new sort order // Reload data with new sort order
dashboardProvider.resetRequestDataList(); dashboardProvider.resetRequestDataList();
if (dashboardProvider.currentListIndex == null) {
} else { if (dashboardProvider.listIndex.isEmpty) {
// No category selected - do nothing or could reload default
return;
} else if (dashboardProvider.listIndex.length == 1 && dashboardProvider.isUnassignedTab(dashboardProvider.listIndex[0])) {
// UnAssigned only - check by requestType, not by index
int index = dashboardProvider.listIndex[0];
dashboardProvider.getRequestDetail( dashboardProvider.getRequestDetail(
usersType: userType ?? UsersTypes.normal_user, usersType: userType ?? UsersTypes.normal_user,
showLoader: true, showLoader: true,
status: tabs[dashboardProvider.currentListIndex!].tag, status: tabs[index].tag,
tabId: tabs[dashboardProvider.currentListIndex!].id, tabId: tabs[index].id,
isAscending: isAscending,
);
} else {
// Multiple categories - call multi-filter API
dashboardProvider.getMultiSelectCategoryRequests(
usersType: userType ?? UsersTypes.normal_user,
showLoader: true,
context: context,
isAscending: isAscending, isAscending: isAscending,
); );
} }
@ -180,26 +194,51 @@ class _RequestCategoryFragmentState extends State<RequestCategoryFragment> with
// ], // ],
// ).paddingOnly(start: 16, end: 16) // ).paddingOnly(start: 16, end: 16)
// : context.translation.allWorkOrder.heading4(context).paddingOnly(start: 16, end: 16), // : context.translation.allWorkOrder.heading4(context).paddingOnly(start: 16, end: 16),
(dashboardProvider.currentListIndex == null) (dashboardProvider.listIndex.isEmpty)
? Consumer<AllRequestsProvider>(builder: (context, snapshot, _) { ? Consumer<AllRequestsProvider>(builder: (context, snapshot, _) {
return RequestItemViewList( return RequestItemViewList(
snapshot.allRequestsAndCount?.requestsDetails ?? [], snapshot.allRequestsAndCount?.requestsDetails ?? [],
snapshot.isAllLoading, snapshot.isAllLoading,
disableScroll: true,
key: ValueKey('request_list_'), // Key changes on every tab click key: ValueKey('request_list_'), // Key changes on every tab click
); );
}) })
: dashboardProvider.isDetailLoading : dashboardProvider.listIndex.length == 1 && dashboardProvider.isUnassignedTab(dashboardProvider.listIndex[0])
? Column( // UnAssigned selected (check by requestType, not by index) - show requestDetailList
mainAxisSize: MainAxisSize.max, ? dashboardProvider.isDetailLoading
children: List.generate(3, (index) { ? Column(
return Padding( mainAxisSize: MainAxisSize.max,
padding: EdgeInsets.symmetric(vertical: 10.toScreenHeight, horizontal: 0), children: List.generate(3, (index) {
child: const SizedBox().toRequestShimmer(context, dashboardProvider.isDetailLoading), return Padding(
); padding: EdgeInsets.symmetric(vertical: 10.toScreenHeight, horizontal: 0),
})).paddingOnly(start: 16, end: 16, top: 16) child: const SizedBox().toRequestShimmer(context, dashboardProvider.isDetailLoading),
: (dashboardProvider.requestDetailList == null || dashboardProvider.requestDetailList?.data?.isEmpty == true) );
? const NoDataFound().paddingOnly(top: 80).center })).paddingOnly(start: 16, end: 16, top: 16)
: RequestCategoryList(dashboardProvider.requestDetailList?.data ?? <Data>[], dashboardProvider.isDetailLoading, dashboardProvider.requestDetailList?.totalRows ?? 0), : (dashboardProvider.requestDetailList == null || dashboardProvider.requestDetailList?.data?.isEmpty == true)
? const NoDataFound().paddingOnly(top: 80).center
: RequestCategoryList(dashboardProvider.requestDetailList?.data ?? <Data>[], dashboardProvider.isDetailLoading, dashboardProvider.requestDetailList?.totalRows ?? 0)
// Multi-select categories - show allRequestsAndCount
: Consumer<AllRequestsProvider>(builder: (context, snapshot, _) {
if (snapshot.isMultiFilterLoading) {
return Column(
mainAxisSize: MainAxisSize.max,
children: List.generate(3, (index) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 10.toScreenHeight, horizontal: 0),
child: const SizedBox().toRequestShimmer(context, snapshot.isMultiFilterLoading),
);
})).paddingOnly(start: 16, end: 16, top: 16);
}
if (snapshot.allRequestsAndCount == null || snapshot.allRequestsAndCount?.requestsDetails?.isEmpty == true) {
return const NoDataFound().paddingOnly(top: 80).center;
}
return RequestItemViewList(
snapshot.allRequestsAndCount?.requestsDetails ?? [],
snapshot.isMultiFilterLoading,
disableScroll: true,
key: ValueKey('multi_filter_list_${dashboardProvider.listIndex.join("_")}'),
);
}),
]); ]);
}); });
} }
@ -277,23 +316,47 @@ class _RequestCategoryFragmentState extends State<RequestCategoryFragment> with
width: itemWidth, // Use responsive width width: itemWidth, // Use responsive width
child: RequestTypeButton( child: RequestTypeButton(
label: tabs[index].label, label: tabs[index].label,
loading: requestsProvider.isDetailLoading && requestsProvider.currentListIndex == index, loading: requestsProvider.isDetailLoading && requestsProvider.listIndex.contains(index),
isSelected: requestsProvider.currentListIndex == index, isSelected: requestsProvider.listIndex.contains(index),
count: requestsProvider.getStatusCount(tabs[index].requestType), count: requestsProvider.getStatusCount(tabs[index].requestType),
onPressed: () async { onPressed: () async {
setState(() { setState(() {
isAscending = false; isAscending = false;
}); });
// Check if this is UnAssigned tab (index 0 for engineer)
bool isUnassignedTab = tabs[index].requestType == RequestTypeEnum.unassigned;
// Update selection state
requestsProvider.currentListIndex = index; requestsProvider.currentListIndex = index;
// Reset data
requestsProvider.resetRequestDataList(); requestsProvider.resetRequestDataList();
requestsProvider.getRequestDetail( Provider.of<AllRequestsProvider>(context, listen: false).reset();
usersType: userType ?? UsersTypes.normal_user,
showLoader: true, // If deselected (listIndex is now empty), show default data
status: tabs[index].tag, if (requestsProvider.listIndex.isEmpty) {
tabId: tabs[index].id, Provider.of<AllRequestsProvider>(context, listen: false).getAllRequests(context);
isHighPriority: tabs[index].isHighPriority, return;
isOverdue: tabs[index].isOverDue, }
);
// If UnAssigned is selected, call its separate API
if (isUnassignedTab) {
requestsProvider.getRequestDetail(
usersType: userType ?? UsersTypes.normal_user,
showLoader: true,
status: tabs[index].tag,
tabId: tabs[index].id,
);
} else {
// Multiple categories selected - call multi-filter API
requestsProvider.getMultiSelectCategoryRequests(
usersType: userType ?? UsersTypes.normal_user,
showLoader: true,
context: context,
isAscending: isAscending,
);
}
}, },
icon: tabs[index].icon, icon: tabs[index].icon,
iconColor: tabs[index].iconColor, iconColor: tabs[index].iconColor,

@ -25,8 +25,9 @@ import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
class RequestItemViewList extends StatefulWidget { class RequestItemViewList extends StatefulWidget {
final List<RequestsDetails> list; final List<RequestsDetails> list;
final bool isLoading; final bool isLoading;
final bool disableScroll;
const RequestItemViewList(this.list, this.isLoading, {Key? key}) : super(key: key); const RequestItemViewList(this.list, this.isLoading, {Key? key, this.disableScroll = false}) : super(key: key);
@override @override
State<RequestItemViewList> createState() => _RequestItemViewListState(); State<RequestItemViewList> createState() => _RequestItemViewListState();
@ -58,6 +59,7 @@ class _RequestItemViewListState extends State<RequestItemViewList> with SingleTi
: ListView.separated( : ListView.separated(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
shrinkWrap: true, shrinkWrap: true,
physics: widget.disableScroll ? const NeverScrollableScrollPhysics() : null,
itemBuilder: (cxt, index) { itemBuilder: (cxt, index) {
if (widget.isLoading) return const SizedBox().toRequestShimmer(cxt, widget.isLoading); if (widget.isLoading) return const SizedBox().toRequestShimmer(cxt, widget.isLoading);
@ -158,5 +160,3 @@ class _RequestItemViewListState extends State<RequestItemViewList> with SingleTi
itemCount: widget.isLoading ? 6 : widget.list.length); itemCount: widget.isLoading ? 6 : widget.list.length);
} }
} }

Loading…
Cancel
Save