cleaner module api call fixed in new ui/ux ehancement.

ui_ux_rollout_merge
Sikander Saleem 1 day ago
parent 5b5010113b
commit f6fa5218b6

@ -13,6 +13,7 @@ import 'package:test_sa/controllers/providers/settings/setting_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/app_bar_widget.dart'; import 'package:test_sa/dashboard_latest/widgets/app_bar_widget.dart';
import 'package:test_sa/dashboard_latest/widgets/progress_fragment.dart'; import 'package:test_sa/dashboard_latest/widgets/progress_fragment.dart';
import 'package:test_sa/dashboard_latest/widgets/request_category_fragment_housekeeper.dart';
import 'package:test_sa/dashboard_latest/widgets/requests_fragment.dart'; import 'package:test_sa/dashboard_latest/widgets/requests_fragment.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
@ -58,17 +59,22 @@ class _DashboardViewState extends State<DashboardView> {
_dashBoardProvider.setTabs(userType: userProvider.user!.type!, context: context); _dashBoardProvider.setTabs(userType: userProvider.user!.type!, context: context);
_dashBoardProvider.getDashBoardCount(usersType: userProvider.user!.type!); _dashBoardProvider.getDashBoardCount(usersType: userProvider.user!.type!);
_dashBoardProvider.resetRequestDataList(); _dashBoardProvider.resetRequestDataList();
_dashBoardProvider.currentListIndex = null;
Provider.of<AllRequestsProvider>(context, listen: false) if (userProvider.isHouseKeeper) {
..reset() _dashBoardProvider.currentListIndex = 0;
..getAllRequests(context); _dashBoardProvider.getRequestDetail(
usersType: userProvider.user!.type!,
// _dashBoardProvider.getRequestDetail( showLoader: true,
// usersType: userProvider.user!.type!, status: _dashBoardProvider.tabs[_dashBoardProvider.currentListIndex!].tag,
// status: _dashBoardProvider.tabs[_dashBoardProvider.currentListIndex].tag, tabId: _dashBoardProvider.tabs[_dashBoardProvider.currentListIndex!].id,
// tabId: _dashBoardProvider.tabs[_dashBoardProvider.currentListIndex].id, // isAscending: _dashBoardProvider.isAscending,
// isHighPriority: _dashBoardProvider.tabs[_dashBoardProvider.currentListIndex].isHighPriority, );
// isOverdue: _dashBoardProvider.tabs[_dashBoardProvider.currentListIndex].isOverDue); } else {
_dashBoardProvider.currentListIndex = null;
Provider.of<AllRequestsProvider>(context, listen: false)
..reset()
..getAllRequests(context);
}
} }
void getInitialData() { void getInitialData() {
@ -145,7 +151,7 @@ class _DashboardViewState extends State<DashboardView> {
children: [ children: [
16.height, ProgressFragment(), 16.height, 16.height, ProgressFragment(), 16.height,
// const RequestsFragment(), // const RequestsFragment(),
const RequestCategoryFragment() context.userProvider.isHouseKeeper ? const RequestCategoryFragmentHouseKeeper() : const RequestCategoryFragment()
], ],
), ),
), ),

@ -80,6 +80,7 @@ class _RequestCategoryFragmentState extends State<RequestCategoryFragment> with
// Reload data with new sort order // Reload data with new sort order
dashboardProvider.resetRequestDataList(); dashboardProvider.resetRequestDataList();
Provider.of<AllRequestsProvider>(context, listen: false).reset();
if (dashboardProvider.listIndex.isEmpty) { if (dashboardProvider.listIndex.isEmpty) {
// No category selected - do nothing or could reload default // No category selected - do nothing or could reload default

@ -0,0 +1,240 @@
import 'package:flutter/material.dart';
import 'package:provider/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/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/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/enums/user_types.dart';
import 'package:test_sa/models/new_models/dashboard_detail.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/tab_button.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
/// Separate component for HouseKeeper role
/// HouseKeeper has simpler requirements:
/// - Single-select only (no multi-select)
/// - Uses getRequestDetail API only
/// - Default shows first category (In Progress)
class RequestCategoryFragmentHouseKeeper extends StatefulWidget {
const RequestCategoryFragmentHouseKeeper({Key? key}) : super(key: key);
@override
State<RequestCategoryFragmentHouseKeeper> createState() => _RequestCategoryFragmentHouseKeeperState();
}
class _RequestCategoryFragmentHouseKeeperState extends State<RequestCategoryFragmentHouseKeeper> with SingleTickerProviderStateMixin {
bool isAscending = false;
late AnimationController _animationController;
late Animation<double> _headerFadeAnimation;
late Animation<Offset> _headerSlideAnimation;
final ScrollController _scrollController = ScrollController();
// int _selectedIndex = 0; // Default first tab
@override
void initState() {
super.initState();
_animationController = AnimationController(
duration: const Duration(milliseconds: 1200),
vsync: this,
);
// Header animation (appears first, faster)
_headerFadeAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.0, 0.4, curve: Curves.easeOut),
),
);
_headerSlideAnimation = Tween<Offset>(
begin: const Offset(0.0, -0.3),
end: Offset.zero,
).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.0, 0.5, curve: Curves.easeOutCubic),
),
);
_animationController.forward();
// Load first category data on init
WidgetsBinding.instance.addPostFrameCallback((_) {
_loadCategoryData(0);
});
}
@override
void dispose() {
_animationController.dispose();
_scrollController.dispose();
super.dispose();
}
void _loadCategoryData(int index) {
final dashboardProvider = Provider.of<DashBoardProvider>(context, listen: false);
List<CategoryTabs> tabs = CategoryTabs.getTabs(userType: UsersTypes.houseKeeper, context: context);
if (index >= 0 && index < tabs.length) {
dashboardProvider.resetRequestDataList();
dashboardProvider.getRequestDetail(
usersType: UsersTypes.houseKeeper,
showLoader: true,
status: tabs[index].tag,
tabId: tabs[index].id,
isAscending: isAscending,
);
}
}
void _toggleSort(DashBoardProvider dashboardProvider) {
setState(() {
isAscending = !isAscending;
});
// Reload current category with new sort order
_loadCategoryData(dashboardProvider.currentListIndex!);
}
@override
Widget build(BuildContext context) {
return Consumer<DashBoardProvider>(builder: (context, dashboardProvider, child) {
List<CategoryTabs> tabs = CategoryTabs.getTabs(userType: UsersTypes.houseKeeper, context: context);
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// Tabs
_buildTabs(tabs, dashboardProvider),
// Header with sort
FadeTransition(
opacity: _headerFadeAnimation,
child: SlideTransition(
position: _headerSlideAnimation,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
'All Tasks'.addTranslation.heading4(context),
Transform.flip(
flipY: isAscending,
child: 'dashboard/sort_descending'.toSvgAsset(
width: 24,
height: 24,
color: AppColor.headingTextColor(context),
).onPress(()=>_toggleSort(dashboardProvider)),
)
],
).paddingOnly(start: 16, end: 16),
),
),
// Data list
dashboardProvider.isDetailLoading
? Column(
mainAxisSize: MainAxisSize.max,
children: List.generate(3, (index) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 10.toScreenHeight, horizontal: 0),
child: const SizedBox().toRequestShimmer(context, dashboardProvider.isDetailLoading),
);
}),
).paddingOnly(start: 16, end: 16, top: 16)
: (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,
),
],
);
});
}
Widget _buildTabs(List<CategoryTabs> tabs, DashBoardProvider dashboardProvider) {
// Calculate item width
final screenWidth = MediaQuery.of(context).size.width;
final isTablet = context.isTablet();
final visibleItemsWithPeek = isTablet ? 4.5 : 3.5;
const spacing = 4.0;
const horizontalPadding = 16.0;
final availableWidth = screenWidth - (horizontalPadding * 2);
final fullItems = visibleItemsWithPeek.floor();
final totalSpacing = (fullItems - 1) * spacing + (spacing * 0.5);
final itemWidth = (availableWidth - totalSpacing) / visibleItemsWithPeek;
return SizedBox(
height: itemWidth + 16,
child: ListView.separated(
controller: _scrollController,
scrollDirection: Axis.horizontal,
separatorBuilder: (cxt, index) => const SizedBox(width: 4),
padding: const EdgeInsets.only(bottom: 16, left: horizontalPadding, right: horizontalPadding),
itemBuilder: (cxt, index) {
// Animation
final delay = index * 0.08;
final animation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: Interval(
delay.clamp(0.0, 0.8),
(delay + 0.3).clamp(0.0, 1.0),
curve: Curves.easeOut,
),
),
);
final slideAnimation = Tween<Offset>(
begin: const Offset(-0.3, 0.0),
end: Offset.zero,
).animate(
CurvedAnimation(
parent: _animationController,
curve: Interval(
delay.clamp(0.0, 0.8),
(delay + 0.3).clamp(0.0, 1.0),
curve: Curves.easeOutCubic,
),
),
);
return FadeTransition(
opacity: animation,
child: SlideTransition(
position: slideAnimation,
child: SizedBox(
width: itemWidth,
child: RequestTypeButton(
label: tabs[index].label,
loading: dashboardProvider.isDetailLoading && dashboardProvider.currentListIndex == index,
isSelected: dashboardProvider.currentListIndex == index,
count: dashboardProvider.getStatusCount(tabs[index].requestType),
onPressed: () {
setState(() {
isAscending = false;
// _selectedIndex = index;
});
dashboardProvider.currentListIndex = index;
_loadCategoryData(index);
},
icon: tabs[index].icon,
iconColor: tabs[index].iconColor,
),
),
),
);
},
itemCount: tabs.length,
),
);
}
}

@ -115,7 +115,9 @@ class _LandPageState extends State<LandPage> {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
_userProvider!.getSwipeLastTransaction(userId: _userProvider!.user!.userID!); _userProvider!.getSwipeLastTransaction(userId: _userProvider!.user!.userID!);
_userProvider!.getSiteContactInfo(); _userProvider!.getSiteContactInfo();
Provider.of<VendorProvider>(context, listen: false).getData(); if(!_userProvider!.isHouseKeeper) {
Provider.of<VendorProvider>(context, listen: false).getData();
}
}); });
} }
_pages = <Widget>[ _pages = <Widget>[

Loading…
Cancel
Save