|
|
|
|
@ -53,8 +53,8 @@ class _DashboardScreenForDependetState extends State<DashboardScreenForDependet>
|
|
|
|
|
// WP_Radius (null when "any"), _filterMinDiscount drives WP_Min_Discount (null when "any").
|
|
|
|
|
// Committed on "Apply filters"/"Reset"; persisted here so reopening the sheet shows the
|
|
|
|
|
// last-applied selection (availability's source of truth is selectedTypeFilter itself).
|
|
|
|
|
String _filterSortBy = 'nearest';
|
|
|
|
|
String _filterDistance = '5km';
|
|
|
|
|
String _filterSortBy = 'newest';
|
|
|
|
|
String _filterDistance = 'any';
|
|
|
|
|
String _filterMinDiscount = 'any';
|
|
|
|
|
bool isNearestOffers = true;
|
|
|
|
|
bool isLoading = true;
|
|
|
|
|
@ -335,7 +335,11 @@ class _DashboardScreenForDependetState extends State<DashboardScreenForDependet>
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
int nextPage = currentPage + 1;
|
|
|
|
|
String catParam = (currentCategoryId == "all" || currentCategoryId == "0") ? "" : currentCategoryId;
|
|
|
|
|
// Must match fetchOffers's category resolution exactly (including the selected
|
|
|
|
|
// subcategory, if any) - otherwise pagination silently switches filters mid-scroll,
|
|
|
|
|
// fetching an overlapping result set under the same page number and duplicating items.
|
|
|
|
|
String effectiveCategoryId = _selectedSubcategoryId ?? currentCategoryId;
|
|
|
|
|
String catParam = (effectiveCategoryId == "all" || effectiveCategoryId == "0") ? "" : effectiveCategoryId;
|
|
|
|
|
String? offerTypeParam = OffersAndDiscountsApiClient.mapOfferTypeFilter(selectedTypeFilter);
|
|
|
|
|
String? queryParam = searchQuery.trim().isNotEmpty ? searchQuery.trim() : null;
|
|
|
|
|
int? radiusParam = _radiusFromFilterDistance(_filterDistance);
|
|
|
|
|
@ -378,7 +382,8 @@ class _DashboardScreenForDependetState extends State<DashboardScreenForDependet>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> _onRefresh() async {
|
|
|
|
|
await Future.wait<dynamic>(<Future<void>>[fetchCategories(), fetchOffers(categoryId: currentCategoryId.isEmpty ? "all" : currentCategoryId, query: _searchController.text)]);
|
|
|
|
|
String effectiveCategoryId = _selectedSubcategoryId ?? (currentCategoryId.isEmpty ? "all" : currentCategoryId);
|
|
|
|
|
await Future.wait<dynamic>(<Future<void>>[fetchCategories(), fetchOffers(categoryId: effectiveCategoryId, query: _searchController.text)]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// '5km'/'10km'/'25km' -> 5/10/25 for WP_Radius; 'any' -> null (omit the param - no distance cap).
|
|
|
|
|
@ -835,10 +840,22 @@ class _DashboardScreenForDependetState extends State<DashboardScreenForDependet>
|
|
|
|
|
// Replaces the old All/In Store/Online chip row: a fixed "Filters" chip (opens the filters
|
|
|
|
|
// bottom sheet) + a divider, then a horizontally scrollable row of subcategory chips fetched
|
|
|
|
|
// from the API for whichever main category is currently selected (see fetchSubcategories).
|
|
|
|
|
// How many of the 4 filter sections are away from their default value
|
|
|
|
|
// (Availability: all, Sort by: newest, Distance: any, Minimum discount: any).
|
|
|
|
|
int _activeFilterCount() {
|
|
|
|
|
int count = 0;
|
|
|
|
|
if (selectedTypeFilter != 'all') count++;
|
|
|
|
|
if (_filterSortBy != 'newest') count++;
|
|
|
|
|
if (_filterDistance != 'any') count++;
|
|
|
|
|
if (_filterMinDiscount != 'any') count++;
|
|
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Widget _buildFiltersRow(bool isAr) {
|
|
|
|
|
// "All Categories" (or nothing selected) has no subcategories to show at all - only a
|
|
|
|
|
// specific main category, once it has actually loaded some, gets the divider + chip row.
|
|
|
|
|
bool showSubcategoriesRow = currentCategoryId.isNotEmpty && currentCategoryId != "all" && (isSubcategoriesLoading || subcategoriesList.isNotEmpty);
|
|
|
|
|
int activeFilterCount = _activeFilterCount();
|
|
|
|
|
|
|
|
|
|
return Padding(
|
|
|
|
|
padding: const EdgeInsets.only(top: 14, bottom: 2),
|
|
|
|
|
@ -846,22 +863,39 @@ class _DashboardScreenForDependetState extends State<DashboardScreenForDependet>
|
|
|
|
|
height: 38,
|
|
|
|
|
child: Row(
|
|
|
|
|
children: <Widget>[
|
|
|
|
|
InkWell(
|
|
|
|
|
borderRadius: BorderRadius.circular(6),
|
|
|
|
|
onTap: _showFiltersBottomSheet,
|
|
|
|
|
child: Container(
|
|
|
|
|
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
|
|
|
|
|
alignment: Alignment.center,
|
|
|
|
|
decoration: BoxDecoration(borderRadius: BorderRadius.circular(6), color: MyColors.lightGreyEAColor),
|
|
|
|
|
child: Row(
|
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
|
children: <Widget>[
|
|
|
|
|
SvgPicture.asset("assets/icons/filter_icon.svg", width: 14, height: 14, colorFilter: const ColorFilter.mode(MyColors.black, BlendMode.srcIn)),
|
|
|
|
|
const SizedBox(width: 5),
|
|
|
|
|
LocaleKeys.filters.tr().toText12(color: MyColors.black),
|
|
|
|
|
],
|
|
|
|
|
Stack(
|
|
|
|
|
clipBehavior: Clip.none,
|
|
|
|
|
children: <Widget>[
|
|
|
|
|
InkWell(
|
|
|
|
|
borderRadius: BorderRadius.circular(6),
|
|
|
|
|
onTap: _showFiltersBottomSheet,
|
|
|
|
|
child: Container(
|
|
|
|
|
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
|
|
|
|
|
alignment: Alignment.center,
|
|
|
|
|
decoration: BoxDecoration(borderRadius: BorderRadius.circular(6), color: MyColors.lightGreyEAColor),
|
|
|
|
|
child: Row(
|
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
|
children: <Widget>[
|
|
|
|
|
SvgPicture.asset("assets/icons/filter_icon.svg", width: 14, height: 14, colorFilter: const ColorFilter.mode(MyColors.black, BlendMode.srcIn)),
|
|
|
|
|
const SizedBox(width: 5),
|
|
|
|
|
LocaleKeys.filters.tr().toText12(color: MyColors.black),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
if (activeFilterCount > 0)
|
|
|
|
|
PositionedDirectional(
|
|
|
|
|
top: -6,
|
|
|
|
|
end: -6,
|
|
|
|
|
child: Container(
|
|
|
|
|
width: 18,
|
|
|
|
|
height: 18,
|
|
|
|
|
alignment: Alignment.center,
|
|
|
|
|
decoration: const BoxDecoration(color: MyColors.darkIconColor, shape: BoxShape.circle),
|
|
|
|
|
child: '$activeFilterCount'.toText10(isBold: true, color: Colors.white),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
if (showSubcategoriesRow) ...<Widget>[
|
|
|
|
|
Container(margin: const EdgeInsets.symmetric(horizontal: 10), width: 1, height: 20, color: const Color(0xFFE2E8F0)),
|
|
|
|
|
|