feat: Enhance document filtering; implement multi-select support and add date range filters
This commit is contained in:
parent
25b20fedda
commit
1fafe77211
@ -10,12 +10,11 @@ class DocumentController extends GetxController {
|
|||||||
var documents = <DocumentItem>[].obs;
|
var documents = <DocumentItem>[].obs;
|
||||||
var filters = Rxn<DocumentFiltersData>();
|
var filters = Rxn<DocumentFiltersData>();
|
||||||
|
|
||||||
// Selected filters
|
// ✅ Selected filters (multi-select support)
|
||||||
var selectedFilter = "".obs;
|
var selectedUploadedBy = <String>[].obs;
|
||||||
var selectedUploadedBy = "".obs;
|
var selectedCategory = <String>[].obs;
|
||||||
var selectedCategory = "".obs;
|
var selectedType = <String>[].obs;
|
||||||
var selectedType = "".obs;
|
var selectedTag = <String>[].obs;
|
||||||
var selectedTag = "".obs;
|
|
||||||
|
|
||||||
// Pagination state
|
// Pagination state
|
||||||
var pageNumber = 1.obs;
|
var pageNumber = 1.obs;
|
||||||
@ -31,6 +30,11 @@ class DocumentController extends GetxController {
|
|||||||
// NEW: search
|
// NEW: search
|
||||||
var searchQuery = ''.obs;
|
var searchQuery = ''.obs;
|
||||||
var searchController = TextEditingController();
|
var searchController = TextEditingController();
|
||||||
|
// New filter fields
|
||||||
|
var isUploadedAt = true.obs;
|
||||||
|
var isVerified = RxnBool();
|
||||||
|
var startDate = Rxn<String>();
|
||||||
|
var endDate = Rxn<String>();
|
||||||
|
|
||||||
// ------------------ API Calls -----------------------
|
// ------------------ API Calls -----------------------
|
||||||
|
|
||||||
@ -157,17 +161,21 @@ class DocumentController extends GetxController {
|
|||||||
|
|
||||||
/// Clear selected filters
|
/// Clear selected filters
|
||||||
void clearFilters() {
|
void clearFilters() {
|
||||||
selectedUploadedBy.value = "";
|
selectedUploadedBy.clear();
|
||||||
selectedCategory.value = "";
|
selectedCategory.clear();
|
||||||
selectedType.value = "";
|
selectedType.clear();
|
||||||
selectedTag.value = "";
|
selectedTag.clear();
|
||||||
|
isUploadedAt.value = true;
|
||||||
|
isVerified.value = null;
|
||||||
|
startDate.value = null;
|
||||||
|
endDate.value = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if any filters are active (for red dot indicator)
|
/// Check if any filters are active (for red dot indicator)
|
||||||
bool hasActiveFilters() {
|
bool hasActiveFilters() {
|
||||||
return selectedUploadedBy.value.isNotEmpty ||
|
return selectedUploadedBy.isNotEmpty ||
|
||||||
selectedCategory.value.isNotEmpty ||
|
selectedCategory.isNotEmpty ||
|
||||||
selectedType.value.isNotEmpty ||
|
selectedType.isNotEmpty ||
|
||||||
selectedTag.value.isNotEmpty;
|
selectedTag.isNotEmpty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,12 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:marco/controller/document/user_document_controller.dart';
|
import 'package:marco/controller/document/user_document_controller.dart';
|
||||||
import 'package:marco/helpers/utils/base_bottom_sheet.dart';
|
import 'package:marco/helpers/utils/base_bottom_sheet.dart';
|
||||||
|
import 'package:marco/helpers/utils/date_time_utils.dart';
|
||||||
import 'package:marco/helpers/widgets/my_spacing.dart';
|
import 'package:marco/helpers/widgets/my_spacing.dart';
|
||||||
import 'package:marco/helpers/widgets/my_text.dart';
|
import 'package:marco/helpers/widgets/my_text.dart';
|
||||||
import 'package:marco/helpers/widgets/my_text_style.dart';
|
import 'package:marco/helpers/widgets/my_text_style.dart';
|
||||||
import 'package:marco/model/document/document_filter_model.dart';
|
import 'package:marco/model/document/document_filter_model.dart';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
class UserDocumentFilterBottomSheet extends StatelessWidget {
|
class UserDocumentFilterBottomSheet extends StatelessWidget {
|
||||||
final String entityId;
|
final String entityId;
|
||||||
@ -36,15 +38,21 @@ class UserDocumentFilterBottomSheet extends StatelessWidget {
|
|||||||
onCancel: () => Get.back(),
|
onCancel: () => Get.back(),
|
||||||
onSubmit: () {
|
onSubmit: () {
|
||||||
final combinedFilter = {
|
final combinedFilter = {
|
||||||
'uploadedBy': docController.selectedUploadedBy.value,
|
'uploadedByIds': docController.selectedUploadedBy.toList(),
|
||||||
'category': docController.selectedCategory.value,
|
'documentCategoryIds': docController.selectedCategory.toList(),
|
||||||
'type': docController.selectedType.value,
|
'documentTypeIds': docController.selectedType.toList(),
|
||||||
'tag': docController.selectedTag.value,
|
'documentTagIds': docController.selectedTag.toList(),
|
||||||
|
'isUploadedAt': docController.isUploadedAt.value,
|
||||||
|
'startDate': docController.startDate.value,
|
||||||
|
'endDate': docController.endDate.value,
|
||||||
|
if (docController.isVerified.value != null)
|
||||||
|
'isVerified': docController.isVerified.value,
|
||||||
};
|
};
|
||||||
|
|
||||||
docController.fetchDocuments(
|
docController.fetchDocuments(
|
||||||
entityTypeId: entityTypeId,
|
entityTypeId: entityTypeId,
|
||||||
entityId: entityId,
|
entityId: entityId,
|
||||||
filter: combinedFilter.toString(),
|
filter: jsonEncode(combinedFilter),
|
||||||
reset: true,
|
reset: true,
|
||||||
);
|
);
|
||||||
Get.back();
|
Get.back();
|
||||||
@ -67,32 +75,209 @@ class UserDocumentFilterBottomSheet extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
// --- Date Filter (Uploaded On / Updated On) ---
|
||||||
|
_buildField(
|
||||||
|
"Choose Date",
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
// Segmented Buttons
|
||||||
|
Obx(() {
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(color: Colors.grey.shade300),
|
||||||
|
borderRadius: BorderRadius.circular(24),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () =>
|
||||||
|
docController.isUploadedAt.value = true,
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 10),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: docController.isUploadedAt.value
|
||||||
|
? Colors.indigo.shade400
|
||||||
|
: Colors.transparent,
|
||||||
|
borderRadius:
|
||||||
|
const BorderRadius.horizontal(
|
||||||
|
left: Radius.circular(24),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: MyText(
|
||||||
|
"Uploaded On",
|
||||||
|
style: MyTextStyle.bodyMedium(
|
||||||
|
color:
|
||||||
|
docController.isUploadedAt.value
|
||||||
|
? Colors.white
|
||||||
|
: Colors.black87,
|
||||||
|
fontWeight: 600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () => docController
|
||||||
|
.isUploadedAt.value = false,
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 10),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: !docController.isUploadedAt.value
|
||||||
|
? Colors.indigo.shade400
|
||||||
|
: Colors.transparent,
|
||||||
|
borderRadius:
|
||||||
|
const BorderRadius.horizontal(
|
||||||
|
right: Radius.circular(24),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: MyText(
|
||||||
|
"Updated On",
|
||||||
|
style: MyTextStyle.bodyMedium(
|
||||||
|
color: !docController
|
||||||
|
.isUploadedAt.value
|
||||||
|
? Colors.white
|
||||||
|
: Colors.black87,
|
||||||
|
fontWeight: 600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
MySpacing.height(12),
|
||||||
|
|
||||||
|
// Date Range
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Obx(() {
|
||||||
|
return _dateButton(
|
||||||
|
label: docController.startDate.value == null
|
||||||
|
? 'Start Date'
|
||||||
|
: DateTimeUtils.formatDate(
|
||||||
|
DateTime.parse(
|
||||||
|
docController.startDate.value!),
|
||||||
|
'dd MMM yyyy',
|
||||||
|
),
|
||||||
|
onTap: () async {
|
||||||
|
final picked = await showDatePicker(
|
||||||
|
context: context,
|
||||||
|
initialDate: DateTime.now(),
|
||||||
|
firstDate: DateTime(2000),
|
||||||
|
lastDate: DateTime.now(),
|
||||||
|
);
|
||||||
|
if (picked != null) {
|
||||||
|
docController.startDate.value =
|
||||||
|
picked.toIso8601String();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
MySpacing.width(12),
|
||||||
|
Expanded(
|
||||||
|
child: Obx(() {
|
||||||
|
return _dateButton(
|
||||||
|
label: docController.endDate.value == null
|
||||||
|
? 'End Date'
|
||||||
|
: DateTimeUtils.formatDate(
|
||||||
|
DateTime.parse(
|
||||||
|
docController.endDate.value!),
|
||||||
|
'dd MMM yyyy',
|
||||||
|
),
|
||||||
|
onTap: () async {
|
||||||
|
final picked = await showDatePicker(
|
||||||
|
context: context,
|
||||||
|
initialDate: DateTime.now(),
|
||||||
|
firstDate: DateTime(2000),
|
||||||
|
lastDate: DateTime.now(),
|
||||||
|
);
|
||||||
|
if (picked != null) {
|
||||||
|
docController.endDate.value =
|
||||||
|
picked.toIso8601String();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
MySpacing.height(8),
|
MySpacing.height(8),
|
||||||
_buildDynamicField(
|
_multiSelectField(
|
||||||
label: "Uploaded By",
|
label: "Uploaded By",
|
||||||
items: filterData.uploadedBy,
|
items: filterData.uploadedBy,
|
||||||
fallback: "Select Uploaded By",
|
fallback: "Select Uploaded By",
|
||||||
selectedValue: docController.selectedUploadedBy,
|
selectedValues: docController.selectedUploadedBy,
|
||||||
),
|
),
|
||||||
_buildDynamicField(
|
_multiSelectField(
|
||||||
label: "Category",
|
label: "Category",
|
||||||
items: filterData.documentCategory,
|
items: filterData.documentCategory,
|
||||||
fallback: "Select Category",
|
fallback: "Select Category",
|
||||||
selectedValue: docController.selectedCategory,
|
selectedValues: docController.selectedCategory,
|
||||||
),
|
),
|
||||||
_buildDynamicField(
|
_multiSelectField(
|
||||||
label: "Type",
|
label: "Type",
|
||||||
items: filterData.documentType,
|
items: filterData.documentType,
|
||||||
fallback: "Select Type",
|
fallback: "Select Type",
|
||||||
selectedValue: docController.selectedType,
|
selectedValues: docController.selectedType,
|
||||||
),
|
),
|
||||||
_buildDynamicField(
|
_multiSelectField(
|
||||||
label: "Tag",
|
label: "Tag",
|
||||||
items: filterData.documentTag,
|
items: filterData.documentTag,
|
||||||
fallback: "Select Tag",
|
fallback: "Select Tag",
|
||||||
selectedValue: docController.selectedTag,
|
selectedValues: docController.selectedTag,
|
||||||
),
|
),
|
||||||
].where((w) => w != null).cast<Widget>().toList(),
|
|
||||||
|
// --- Verified Toggle ---
|
||||||
|
_buildField(
|
||||||
|
"Only Verified",
|
||||||
|
Obx(() {
|
||||||
|
return Container(
|
||||||
|
padding: MySpacing.xy(12, 6),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.grey.shade100,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: Colors.grey.shade300),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
MyText(
|
||||||
|
"Verified Documents Only",
|
||||||
|
style: MyTextStyle.bodyMedium(),
|
||||||
|
),
|
||||||
|
Switch(
|
||||||
|
value: docController.isVerified.value ?? false,
|
||||||
|
onChanged: (val) {
|
||||||
|
docController.isVerified.value =
|
||||||
|
val ? true : null;
|
||||||
|
},
|
||||||
|
activeColor: Colors.indigo,
|
||||||
|
materialTapTargetSize:
|
||||||
|
MaterialTapTargetSize.shrinkWrap,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
],
|
||||||
)
|
)
|
||||||
: Center(
|
: Center(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@ -110,70 +295,161 @@ class UserDocumentFilterBottomSheet extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget? _buildDynamicField({
|
Widget _multiSelectField({
|
||||||
required String label,
|
required String label,
|
||||||
required List<FilterItem> items,
|
required List<FilterItem> items,
|
||||||
required String fallback,
|
required String fallback,
|
||||||
required RxString selectedValue,
|
required RxList<String> selectedValues,
|
||||||
}) {
|
}) {
|
||||||
if (items.isEmpty) return null;
|
if (items.isEmpty) return const SizedBox.shrink();
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
MyText.labelMedium(label),
|
MyText.labelMedium(label),
|
||||||
MySpacing.height(8),
|
MySpacing.height(8),
|
||||||
_popupSelector(items, fallback, selectedValue: selectedValue),
|
Obx(() {
|
||||||
|
final selectedNames = items
|
||||||
|
.where((f) => selectedValues.contains(f.id))
|
||||||
|
.map((f) => f.name)
|
||||||
|
.join(", ");
|
||||||
|
final displayText =
|
||||||
|
selectedNames.isNotEmpty ? selectedNames : fallback;
|
||||||
|
|
||||||
|
return Builder(
|
||||||
|
builder: (context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () async {
|
||||||
|
final RenderBox button =
|
||||||
|
context.findRenderObject() as RenderBox;
|
||||||
|
final RenderBox overlay = Overlay.of(context)
|
||||||
|
.context
|
||||||
|
.findRenderObject() as RenderBox;
|
||||||
|
|
||||||
|
final position = button.localToGlobal(Offset.zero);
|
||||||
|
|
||||||
|
await showMenu(
|
||||||
|
context: context,
|
||||||
|
position: RelativeRect.fromLTRB(
|
||||||
|
position.dx,
|
||||||
|
position.dy + button.size.height,
|
||||||
|
overlay.size.width - position.dx - button.size.width,
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
items: items.map(
|
||||||
|
(f) {
|
||||||
|
return PopupMenuItem<String>(
|
||||||
|
enabled: false, // prevent auto-close
|
||||||
|
child: StatefulBuilder(
|
||||||
|
builder: (context, setState) {
|
||||||
|
final isChecked = selectedValues.contains(f.id);
|
||||||
|
return CheckboxListTile(
|
||||||
|
dense: true,
|
||||||
|
value: isChecked,
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
controlAffinity:
|
||||||
|
ListTileControlAffinity.leading,
|
||||||
|
title: MyText(f.name),
|
||||||
|
|
||||||
|
// --- Styles ---
|
||||||
|
checkColor: Colors.white, // tick color
|
||||||
|
side: const BorderSide(
|
||||||
|
color: Colors.black,
|
||||||
|
width: 1.5), // border when unchecked
|
||||||
|
|
||||||
|
fillColor:
|
||||||
|
MaterialStateProperty.resolveWith<Color>(
|
||||||
|
(states) {
|
||||||
|
if (states
|
||||||
|
.contains(MaterialState.selected)) {
|
||||||
|
return Colors.indigo; // checked → Indigo
|
||||||
|
}
|
||||||
|
return Colors.white; // unchecked → White
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
onChanged: (val) {
|
||||||
|
if (val == true) {
|
||||||
|
selectedValues.add(f.id);
|
||||||
|
} else {
|
||||||
|
selectedValues.remove(f.id);
|
||||||
|
}
|
||||||
|
setState(() {}); // refresh UI
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
).toList(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: MySpacing.all(12),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.grey.shade100,
|
||||||
|
border: Border.all(color: Colors.grey.shade300),
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: MyText(
|
||||||
|
displayText,
|
||||||
|
style: const TextStyle(color: Colors.black87),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Icon(Icons.arrow_drop_down, color: Colors.grey),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}),
|
||||||
MySpacing.height(16),
|
MySpacing.height(16),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _popupSelector(
|
Widget _buildField(String label, Widget child) {
|
||||||
List<FilterItem> items,
|
return Column(
|
||||||
String fallback, {
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
required RxString selectedValue,
|
children: [
|
||||||
}) {
|
MyText.labelMedium(label),
|
||||||
return Obx(() {
|
MySpacing.height(8),
|
||||||
final currentValue = _getCurrentName(selectedValue.value, items, fallback);
|
child,
|
||||||
return PopupMenuButton<String>(
|
MySpacing.height(8),
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
],
|
||||||
onSelected: (val) => selectedValue.value = val,
|
);
|
||||||
itemBuilder: (context) => items
|
|
||||||
.map(
|
|
||||||
(f) => PopupMenuItem<String>(
|
|
||||||
value: f.id,
|
|
||||||
child: MyText(f.name),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
child: Container(
|
|
||||||
padding: MySpacing.all(12),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.grey.shade100,
|
|
||||||
border: Border.all(color: Colors.grey.shade300),
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: MyText(
|
|
||||||
currentValue,
|
|
||||||
style: const TextStyle(color: Colors.black87),
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Icon(Icons.arrow_drop_down, color: Colors.grey),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String _getCurrentName(String selectedId, List<FilterItem> list, String fallback) {
|
Widget _dateButton({required String label, required VoidCallback onTap}) {
|
||||||
if (selectedId.isEmpty) return fallback;
|
return GestureDetector(
|
||||||
final match = list.firstWhereOrNull((f) => f.id == selectedId);
|
onTap: onTap,
|
||||||
return match?.name ?? fallback;
|
child: Container(
|
||||||
|
padding: MySpacing.xy(16, 12),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.grey.shade100,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: Colors.grey.shade300),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.calendar_today, size: 16, color: Colors.grey),
|
||||||
|
MySpacing.width(8),
|
||||||
|
Expanded(
|
||||||
|
child: MyText(
|
||||||
|
label,
|
||||||
|
style: MyTextStyle.bodyMedium(),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@ import 'package:marco/helpers/widgets/custom_app_bar.dart';
|
|||||||
import 'package:marco/helpers/widgets/my_confirmation_dialog.dart';
|
import 'package:marco/helpers/widgets/my_confirmation_dialog.dart';
|
||||||
import 'package:marco/helpers/widgets/my_snackbar.dart';
|
import 'package:marco/helpers/widgets/my_snackbar.dart';
|
||||||
import 'package:marco/controller/permission_controller.dart';
|
import 'package:marco/controller/permission_controller.dart';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
|
||||||
class UserDocumentsPage extends StatefulWidget {
|
class UserDocumentsPage extends StatefulWidget {
|
||||||
final String? entityId;
|
final String? entityId;
|
||||||
@ -504,10 +506,18 @@ class _UserDocumentsPageState extends State<UserDocumentsPage> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: MyRefreshIndicator(
|
child: MyRefreshIndicator(
|
||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
|
final combinedFilter = {
|
||||||
|
'uploadedByIds': docController.selectedUploadedBy.toList(),
|
||||||
|
'documentCategoryIds':
|
||||||
|
docController.selectedCategory.toList(),
|
||||||
|
'documentTypeIds': docController.selectedType.toList(),
|
||||||
|
'documentTagIds': docController.selectedTag.toList(),
|
||||||
|
};
|
||||||
|
|
||||||
await docController.fetchDocuments(
|
await docController.fetchDocuments(
|
||||||
entityTypeId: entityTypeId,
|
entityTypeId: entityTypeId,
|
||||||
entityId: resolvedEntityId,
|
entityId: resolvedEntityId,
|
||||||
filter: docController.selectedFilter.value,
|
filter: jsonEncode(combinedFilter),
|
||||||
reset: true,
|
reset: true,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -577,7 +587,7 @@ class _UserDocumentsPageState extends State<UserDocumentsPage> {
|
|||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
builder: (_) => DocumentUploadBottomSheet(
|
builder: (_) => DocumentUploadBottomSheet(
|
||||||
isEmployee:
|
isEmployee:
|
||||||
widget.isEmployee, // 👈 Pass the employee flag here
|
widget.isEmployee,
|
||||||
onSubmit: (data) async {
|
onSubmit: (data) async {
|
||||||
final success = await uploadController.uploadDocument(
|
final success = await uploadController.uploadDocument(
|
||||||
name: data["name"],
|
name: data["name"],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user