marco.pms.mobileapp/lib/view/document/user_document_screen.dart

1024 lines
34 KiB
Dart

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import 'package:marco/controller/document/document_details_controller.dart';
import 'package:marco/controller/document/document_upload_controller.dart';
import 'package:marco/controller/document/user_document_controller.dart';
import 'package:marco/controller/permission_controller.dart';
import 'package:marco/controller/project_controller.dart';
import 'package:marco/helpers/utils/permission_constants.dart';
import 'package:marco/helpers/widgets/custom_app_bar.dart';
import 'package:marco/helpers/widgets/my_confirmation_dialog.dart';
import 'package:marco/helpers/widgets/my_refresh_indicator.dart';
import 'package:marco/helpers/widgets/my_text.dart';
import 'package:marco/helpers/widgets/my_snackbar.dart';
import 'package:marco/helpers/widgets/my_custom_skeleton.dart';
import 'package:marco/model/document/document_upload_bottom_sheet.dart';
import 'package:marco/model/document/documents_list_model.dart';
import 'package:marco/model/document/user_document_filter_bottom_sheet.dart';
import 'package:marco/view/document/document_details_page.dart';
import 'package:marco/helpers/utils/mixins/ui_mixin.dart';
class UserDocumentsPage extends StatefulWidget {
final String? entityId;
final bool isEmployee;
const UserDocumentsPage({
super.key,
this.entityId,
this.isEmployee = false,
});
@override
State<UserDocumentsPage> createState() => _UserDocumentsPageState();
}
class _UserDocumentsPageState extends State<UserDocumentsPage>
with UIMixin, SingleTickerProviderStateMixin {
late ScrollController _scrollController;
late AnimationController _fabAnimationController;
late Animation<double> _fabScaleAnimation;
DocumentController get docController => Get.find<DocumentController>();
PermissionController get permissionController =>
Get.find<PermissionController>();
DocumentDetailsController get detailsController =>
Get.find<DocumentDetailsController>();
String get entityTypeId => widget.isEmployee
? Permissions.employeeEntity
: Permissions.projectEntity;
String get resolvedEntityId => widget.isEmployee
? widget.entityId ?? ""
: Get.find<ProjectController>().selectedProject?.id ?? "";
@override
void initState() {
super.initState();
if (!Get.isRegistered<DocumentController>()) Get.put(DocumentController());
if (!Get.isRegistered<PermissionController>())
Get.put(PermissionController());
if (!Get.isRegistered<DocumentDetailsController>())
Get.put(DocumentDetailsController());
_scrollController = ScrollController()..addListener(_onScroll);
_fabAnimationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 200),
);
_fabScaleAnimation = CurvedAnimation(
parent: _fabAnimationController,
curve: Curves.easeInOut,
);
_fabAnimationController.forward();
WidgetsBinding.instance.addPostFrameCallback((_) => _initializeData());
}
void _initializeData() {
docController.fetchFilters(entityTypeId);
docController.fetchDocuments(
entityTypeId: entityTypeId,
entityId: resolvedEntityId,
reset: true,
);
}
void _onScroll() {
if (_scrollController.position.pixels >=
_scrollController.position.maxScrollExtent * 0.8) {
if (!docController.isLoading.value && docController.hasMore.value) {
docController.fetchDocuments(
entityTypeId: entityTypeId,
entityId: resolvedEntityId,
);
}
}
if (_scrollController.position.userScrollDirection ==
ScrollDirection.reverse) {
if (_fabAnimationController.isCompleted)
_fabAnimationController.reverse();
} else if (_scrollController.position.userScrollDirection ==
ScrollDirection.forward) {
if (_fabAnimationController.isDismissed)
_fabAnimationController.forward();
}
}
@override
void dispose() {
_scrollController.dispose();
_fabAnimationController.dispose();
docController.searchController.dispose();
docController.documents.clear();
super.dispose();
}
// ==================== UI BUILDERS ====================
Widget _buildSearchBar() {
return Container(
margin: const EdgeInsets.fromLTRB(16, 12, 16, 8),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(5),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.04),
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
child: TextField(
controller: docController.searchController,
onChanged: (value) {
docController.searchQuery.value = value;
docController.fetchDocuments(
entityTypeId: entityTypeId,
entityId: resolvedEntityId,
reset: true,
);
},
style: const TextStyle(fontSize: 15),
decoration: InputDecoration(
contentPadding:
const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
prefixIcon:
const Icon(Icons.search_rounded, size: 22, color: Colors.grey),
suffixIcon: ValueListenableBuilder<TextEditingValue>(
valueListenable: docController.searchController,
builder: (context, value, _) {
if (value.text.isEmpty) return const SizedBox.shrink();
return IconButton(
icon: const Icon(Icons.clear_rounded, size: 20),
color: Colors.grey.shade600,
onPressed: () {
docController.searchController.clear();
docController.searchQuery.value = '';
docController.fetchDocuments(
entityTypeId: entityTypeId,
entityId: resolvedEntityId,
reset: true,
);
},
);
},
),
hintText: 'Search by document name or type...',
hintStyle: TextStyle(color: Colors.grey.shade500, fontSize: 15),
filled: true,
fillColor: Colors.white,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide.none,
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(color: contentTheme.primary, width: 2),
),
),
),
);
}
Widget _buildFilterChips() {
return Container(
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Row(
children: [
Expanded(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Obx(() {
final hasFilters = docController.hasActiveFilters();
return Row(
children: [
if (hasFilters) ...[
_buildChip(
'Clear Filters',
icon: Icons.close_rounded,
isSelected: false,
onTap: () {
docController.clearFilters();
docController.fetchDocuments(
entityTypeId: entityTypeId,
entityId: resolvedEntityId,
reset: true,
);
},
backgroundColor: Colors.red.shade50,
textColor: Colors.red.shade700,
),
const SizedBox(width: 8),
],
_buildFilterButton(),
const SizedBox(width: 8),
_buildMoreOptionsButton(),
],
);
}),
),
),
],
),
);
}
Widget _buildChip(
String label, {
IconData? icon,
bool isSelected = false,
VoidCallback? onTap,
Color? backgroundColor,
Color? textColor,
}) {
return InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(5),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
decoration: BoxDecoration(
color: backgroundColor ??
(isSelected
? contentTheme.primary.withOpacity(0.1)
: Colors.white),
borderRadius: BorderRadius.circular(5),
border: Border.all(
color: isSelected ? contentTheme.primary : Colors.grey.shade300,
width: 1.5,
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (icon != null) ...[
Icon(
icon,
size: 16,
color: textColor ??
(isSelected ? contentTheme.primary : Colors.grey.shade700),
),
const SizedBox(width: 6),
],
MyText.labelSmall(
label,
fontWeight: 600,
color: textColor ??
(isSelected ? contentTheme.primary : Colors.grey.shade700),
),
],
),
),
);
}
Widget _buildFilterButton() {
return Obx(() {
final isFilterActive = docController.hasActiveFilters();
return Stack(
clipBehavior: Clip.none,
children: [
_buildChip(
'Filters',
icon: Icons.tune_rounded,
isSelected: isFilterActive,
onTap: () {
showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (_) => UserDocumentFilterBottomSheet(
entityId: resolvedEntityId,
entityTypeId: entityTypeId,
),
);
},
),
if (isFilterActive)
Positioned(
top: -4,
right: -4,
child: Container(
height: 10,
width: 10,
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
border: Border.all(color: const Color(0xFFF1F1F1), width: 2),
),
),
),
],
);
});
}
Widget _buildMoreOptionsButton() {
return PopupMenuButton<String>(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)),
offset: const Offset(0, 40),
child: _buildChip(
'Options',
icon: Icons.more_horiz_rounded,
),
itemBuilder: (context) => [
PopupMenuItem<String>(
enabled: false,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: MyText.bodySmall(
'Preferences',
fontWeight: 700,
color: Colors.grey.shade600,
),
),
const PopupMenuDivider(height: 1),
PopupMenuItem<String>(
value: 'show_deleted',
enabled: false,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
child: Obx(() => Row(
children: [
Icon(Icons.visibility_off_outlined,
size: 20, color: Colors.grey.shade700),
const SizedBox(width: 12),
Expanded(
child: MyText.bodyMedium('Show Deleted', fontSize: 14),
),
Switch.adaptive(
value: docController.showInactive.value,
activeColor: contentTheme.primary,
onChanged: (val) {
docController.showInactive.value = val;
docController.fetchDocuments(
entityTypeId: entityTypeId,
entityId: resolvedEntityId,
reset: true,
);
Navigator.pop(context);
},
),
],
)),
),
],
);
}
Widget _buildStatusBanner() {
return Obx(() {
if (!docController.showInactive.value) return const SizedBox.shrink();
return AnimatedContainer(
duration: const Duration(milliseconds: 300),
width: double.infinity,
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16),
decoration: BoxDecoration(
color: Colors.red.shade50,
border:
Border(bottom: BorderSide(color: Colors.red.shade100, width: 1)),
),
child: Row(
children: [
Icon(Icons.info_outline_rounded,
color: Colors.red.shade700, size: 18),
const SizedBox(width: 10),
Expanded(
child: MyText.bodySmall(
'Showing deleted documents',
fontWeight: 600,
color: Colors.red.shade700,
),
),
TextButton(
onPressed: () {
docController.showInactive.value = false;
docController.fetchDocuments(
entityTypeId: entityTypeId,
entityId: resolvedEntityId,
reset: true,
);
},
style: TextButton.styleFrom(
padding:
const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
minimumSize: Size.zero,
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
child: MyText.labelMedium(
'Hide',
fontWeight: 700,
color: Colors.red.shade700,
),
),
],
),
);
});
}
Widget _buildDocumentCard(DocumentItem doc, bool showDateHeader) {
final uploadDate =
DateFormat("dd MMM yyyy").format(doc.uploadedAt.toLocal());
final uploadTime = DateFormat("hh:mm a").format(doc.uploadedAt.toLocal());
final uploader = doc.uploadedBy.firstName.isNotEmpty
? "${doc.uploadedBy.firstName} ${doc.uploadedBy.lastName}".trim()
: "You";
final iconColor = _getDocumentTypeColor(doc.documentType.name);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (showDateHeader) _buildDateHeader(uploadDate),
Hero(
tag: 'document_${doc.id}',
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () {
Get.to(
() => DocumentDetailsPage(documentId: doc.id),
transition: Transition.rightToLeft,
duration: const Duration(milliseconds: 300),
);
},
borderRadius: BorderRadius.circular(5),
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
padding: const EdgeInsets.all(14),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(5),
border: Border.all(color: Colors.grey.shade200, width: 1),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.03),
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: iconColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(10),
),
child: Icon(
_getDocumentIcon(doc.documentType.name),
color: iconColor,
size: 24,
),
),
const SizedBox(width: 14),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.symmetric(
horizontal: 8, vertical: 3),
decoration: BoxDecoration(
color: iconColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(6),
),
child: MyText.labelSmall(
doc.documentType.name,
fontWeight: 600,
color: iconColor,
letterSpacing: 0.3,
),
),
const SizedBox(height: 8),
MyText.bodyMedium(
doc.name,
fontWeight: 600,
color: Colors.black87,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
const SizedBox(height: 6),
Row(
children: [
Icon(Icons.person_outline_rounded,
size: 14, color: Colors.grey.shade600),
const SizedBox(width: 4),
Expanded(
child: MyText.bodySmall(
'Added by $uploader',
color: Colors.grey.shade600,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
MyText.bodySmall(
uploadTime,
color: Colors.grey.shade500,
fontWeight: 500,
fontSize: 11,
),
],
),
],
),
),
_buildDocumentMenu(doc),
],
),
),
),
),
),
],
);
}
Widget _buildDateHeader(String date) {
return Padding(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 8),
child: MyText.bodySmall(
date,
fontWeight: 700,
color: Colors.grey.shade700,
letterSpacing: 0.5,
),
);
}
Widget _buildDocumentMenu(DocumentItem doc) {
return Obx(() {
final canDelete =
permissionController.hasPermission(Permissions.deleteDocument);
final canModify =
permissionController.hasPermission(Permissions.modifyDocument);
// Build menu items list
final List<PopupMenuEntry<String>> menuItems = [];
if (doc.isActive && canDelete) {
menuItems.add(
PopupMenuItem(
value: "delete",
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Row(
children: [
Icon(Icons.delete_outline_rounded,
size: 20, color: Colors.red.shade700),
const SizedBox(width: 12),
MyText.bodyMedium(
'Delete',
color: Colors.red.shade700,
)
],
),
),
);
} else if (!doc.isActive && canModify) {
menuItems.add(
PopupMenuItem(
value: "restore",
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Row(
children: [
Icon(Icons.restore_rounded,
size: 20, color: contentTheme.primary),
const SizedBox(width: 12),
MyText.bodyMedium(
'Restore',
color: contentTheme.primary,
)
],
),
),
);
}
// If no menu items, return empty widget
if (menuItems.isEmpty) {
return const SizedBox.shrink();
}
return PopupMenuButton<String>(
icon: Icon(Icons.more_vert_rounded,
color: Colors.grey.shade600, size: 20),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)),
offset: const Offset(-10, 30),
onSelected: (value) => _handleMenuAction(value, doc),
itemBuilder: (context) => menuItems,
);
});
}
Future<void> _handleMenuAction(String action, DocumentItem doc) async {
if (action == "delete") {
await showDialog<bool>(
context: context,
builder: (_) => ConfirmDialog(
title: "Delete Document",
message:
"Are you sure you want to delete \"${doc.name}\"?\n\nThis action cannot be undone.",
confirmText: "Delete",
cancelText: "Cancel",
icon: Icons.delete_forever_rounded,
confirmColor: Colors.redAccent,
onConfirm: () async {
final success = await docController.toggleDocumentActive(
doc.id,
isActive: false,
entityTypeId: entityTypeId,
entityId: resolvedEntityId,
);
if (success) {
showAppSnackbar(
title: "Deleted",
message: "Document deleted successfully",
type: SnackbarType.success,
);
} else {
showAppSnackbar(
title: "Error",
message: "Failed to delete document",
type: SnackbarType.error,
);
throw Exception("Failed to delete");
}
},
),
);
} else if (action == "restore") {
final success = await docController.toggleDocumentActive(
doc.id,
isActive: true,
entityTypeId: entityTypeId,
entityId: resolvedEntityId,
);
if (success) {
showAppSnackbar(
title: "Restored",
message: "Document restored successfully",
type: SnackbarType.success,
);
} else {
showAppSnackbar(
title: "Error",
message: "Failed to restore document",
type: SnackbarType.error,
);
}
}
}
Widget _buildEmptyState() {
return Center(
child: Padding(
padding: const EdgeInsets.all(32),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: Colors.grey.shade100,
shape: BoxShape.circle,
),
child: Icon(
Icons.folder_open_rounded,
size: 64,
color: Colors.grey.shade400,
),
),
const SizedBox(height: 24),
MyText.bodyLarge(
'No documents found',
fontWeight: 600,
color: Colors.grey.shade700,
),
const SizedBox(height: 8),
MyText.bodySmall(
'Try adjusting your filters or\nadd a new document to get started',
color: Colors.grey.shade600,
height: 1.5,
textAlign: TextAlign.center,
),
],
),
),
);
}
Widget _buildLoadingIndicator() {
return const Center(
child: Padding(
padding: EdgeInsets.all(16),
child: CircularProgressIndicator(),
),
);
}
Widget _buildNoMoreIndicator() {
return Padding(
padding: const EdgeInsets.all(16),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: 1,
width: 40,
color: Colors.grey.shade300,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: MyText.bodySmall(
'No more documents',
fontWeight: 500,
)),
Container(
height: 1,
width: 40,
color: Colors.grey.shade300,
),
],
),
),
);
}
Widget _buildPermissionDenied() {
return Center(
child: Padding(
padding: const EdgeInsets.all(32),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: Colors.red.shade50,
shape: BoxShape.circle,
),
child: Icon(
Icons.lock_outline_rounded,
size: 64,
color: Colors.red.shade300,
),
),
const SizedBox(height: 24),
MyText.bodyLarge(
'Access Denied',
fontWeight: 600,
color: Colors.grey.shade700,
),
const SizedBox(height: 8),
MyText.bodySmall(
'You don\'t have permission\nto view documents',
color: Colors.grey.shade600,
height: 1.5,
textAlign: TextAlign.center,
),
],
),
),
);
}
Widget _buildBody() {
return Obx(() {
// Check permissions
if (permissionController.permissions.isEmpty) {
return _buildLoadingIndicator();
}
if (!permissionController.hasPermission(Permissions.viewDocument)) {
return _buildPermissionDenied();
}
// Show skeleton loader
if (docController.isLoading.value && docController.documents.isEmpty) {
return SingleChildScrollView(
physics: const NeverScrollableScrollPhysics(),
child: SkeletonLoaders.documentSkeletonLoader(),
);
}
final docs = docController.documents;
return Column(
children: [
_buildSearchBar(),
_buildFilterChips(),
_buildStatusBanner(),
Expanded(
child: MyRefreshIndicator(
onRefresh: () async {
final combinedFilter = {
'uploadedByIds': docController.selectedUploadedBy.toList(),
'documentCategoryIds':
docController.selectedCategory.toList(),
'documentTypeIds': docController.selectedType.toList(),
'documentTagIds': docController.selectedTag.toList(),
};
await docController.fetchDocuments(
entityTypeId: entityTypeId,
entityId: resolvedEntityId,
filter: jsonEncode(combinedFilter),
reset: true,
);
},
child: docs.isEmpty
? ListView(
physics: const AlwaysScrollableScrollPhysics(),
children: [
SizedBox(
height: MediaQuery.of(context).size.height * 0.5,
child: _buildEmptyState(),
),
],
)
: ListView.builder(
controller: _scrollController,
physics: const AlwaysScrollableScrollPhysics(),
padding: const EdgeInsets.only(bottom: 100, top: 8),
itemCount: docs.length + 1,
itemBuilder: (context, index) {
if (index == docs.length) {
return Obx(() {
if (docController.isLoading.value) {
return _buildLoadingIndicator();
}
if (!docController.hasMore.value &&
docs.isNotEmpty) {
return _buildNoMoreIndicator();
}
return const SizedBox.shrink();
});
}
final doc = docs[index];
final currentDate = DateFormat("dd MMM yyyy")
.format(doc.uploadedAt.toLocal());
final prevDate = index > 0
? DateFormat("dd MMM yyyy")
.format(docs[index - 1].uploadedAt.toLocal())
: null;
final showDateHeader = currentDate != prevDate;
return _buildDocumentCard(doc, showDateHeader);
},
),
),
),
],
);
});
}
Widget _buildFAB() {
return Obx(() {
if (permissionController.permissions.isEmpty) {
return const SizedBox.shrink();
}
if (!permissionController.hasPermission(Permissions.uploadDocument)) {
return const SizedBox.shrink();
}
return ScaleTransition(
scale: _fabScaleAnimation,
child: FloatingActionButton.extended(
onPressed: _showUploadBottomSheet,
elevation: 4,
highlightElevation: 8,
backgroundColor: contentTheme.primary,
foregroundColor: Colors.white,
icon: const Icon(Icons.add_rounded, size: 24),
label: const Text(
'Add Document',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w600,
letterSpacing: 0.3,
),
),
),
);
});
}
void _showUploadBottomSheet() {
final uploadController = Get.put(DocumentUploadController());
showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (_) => DocumentUploadBottomSheet(
isEmployee: widget.isEmployee,
onSubmit: (data) async {
final success = await uploadController.uploadDocument(
name: data["name"],
description: data["description"],
documentId: data["documentId"],
entityId: resolvedEntityId,
documentTypeId: data["documentTypeId"],
fileName: data["attachment"]["fileName"],
base64Data: data["attachment"]["base64Data"],
contentType: data["attachment"]["contentType"],
fileSize: data["attachment"]["fileSize"],
);
if (success) {
Navigator.pop(context);
docController.fetchDocuments(
entityTypeId: entityTypeId,
entityId: resolvedEntityId,
reset: true,
);
showAppSnackbar(
title: "Success",
message: "Document uploaded successfully",
type: SnackbarType.success,
);
} else {
showAppSnackbar(
title: "Error",
message: "Upload failed, please try again",
type: SnackbarType.error,
);
}
},
),
);
}
// Helper methods for document type styling
Color _getDocumentTypeColor(String type) {
final lowerType = type.toLowerCase();
if (lowerType.contains('contract') || lowerType.contains('agreement')) {
return Colors.purple;
} else if (lowerType.contains('invoice') || lowerType.contains('receipt')) {
return Colors.green;
} else if (lowerType.contains('report')) {
return Colors.orange;
} else if (lowerType.contains('certificate')) {
return Colors.blue;
} else if (lowerType.contains('id') || lowerType.contains('identity')) {
return Colors.red;
} else {
return Colors.blueGrey;
}
}
IconData _getDocumentIcon(String type) {
final lowerType = type.toLowerCase();
if (lowerType.contains('contract') || lowerType.contains('agreement')) {
return Icons.article_rounded;
} else if (lowerType.contains('invoice') || lowerType.contains('receipt')) {
return Icons.receipt_long_rounded;
} else if (lowerType.contains('report')) {
return Icons.assessment_rounded;
} else if (lowerType.contains('certificate')) {
return Icons.workspace_premium_rounded;
} else if (lowerType.contains('id') || lowerType.contains('identity')) {
return Icons.badge_rounded;
} else {
return Icons.description_rounded;
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFF1F1F1),
appBar: !widget.isEmployee
? CustomAppBar(
title: 'Documents',
onBackPressed: () => Get.back(),
)
: null,
body: SafeArea(
child: _buildBody(),
),
floatingActionButton: _buildFAB(),
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
);
}
}