replaced fab icon with icon on page
This commit is contained in:
parent
7f0c4d075d
commit
af5bfcaa59
@ -50,7 +50,6 @@ class _PaymentRequestDetailScreenState extends State<PaymentRequestDetailScreen>
|
|||||||
|
|
||||||
void _checkPermissionToSubmit(PaymentRequestData request) {
|
void _checkPermissionToSubmit(PaymentRequestData request) {
|
||||||
const draftStatusId = '6537018f-f4e9-4cb3-a210-6c3b2da999d7';
|
const draftStatusId = '6537018f-f4e9-4cb3-a210-6c3b2da999d7';
|
||||||
|
|
||||||
final isCreatedByCurrentUser = employeeInfo?.id == request.createdBy.id;
|
final isCreatedByCurrentUser = employeeInfo?.id == request.createdBy.id;
|
||||||
final hasDraftNextStatus =
|
final hasDraftNextStatus =
|
||||||
request.nextStatus.any((s) => s.id == draftStatusId);
|
request.nextStatus.any((s) => s.id == draftStatusId);
|
||||||
@ -109,7 +108,6 @@ class _PaymentRequestDetailScreenState extends State<PaymentRequestDetailScreen>
|
|||||||
body: SafeArea(child: Obx(() {
|
body: SafeArea(child: Obx(() {
|
||||||
if (controller.isLoading.value &&
|
if (controller.isLoading.value &&
|
||||||
controller.paymentRequest.value == null) {
|
controller.paymentRequest.value == null) {
|
||||||
// Show skeleton only if data not yet loaded
|
|
||||||
return SkeletonLoaders.paymentRequestDetailSkeletonLoader();
|
return SkeletonLoaders.paymentRequestDetailSkeletonLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +122,6 @@ class _PaymentRequestDetailScreenState extends State<PaymentRequestDetailScreen>
|
|||||||
return Center(child: MyText.bodyMedium("No data to display."));
|
return Center(child: MyText.bodyMedium("No data to display."));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ Actual content
|
|
||||||
return MyRefreshIndicator(
|
return MyRefreshIndicator(
|
||||||
onRefresh: controller.fetchPaymentRequestDetail,
|
onRefresh: controller.fetchPaymentRequestDetail,
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
@ -140,14 +137,19 @@ class _PaymentRequestDetailScreenState extends State<PaymentRequestDetailScreen>
|
|||||||
child: Card(
|
child: Card(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(5)),
|
borderRadius: BorderRadius.circular(5)),
|
||||||
elevation: 3,
|
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
vertical: 14, horizontal: 14),
|
vertical: 12, horizontal: 14),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
_Header(request: request, colorParser: _parseColor),
|
_Header(
|
||||||
|
request: request,
|
||||||
|
colorParser: _parseColor,
|
||||||
|
employeeInfo: employeeInfo,
|
||||||
|
onEdit: () =>
|
||||||
|
_openEditPaymentRequestBottomSheet(request),
|
||||||
|
),
|
||||||
const Divider(height: 30, thickness: 1.2),
|
const Divider(height: 30, thickness: 1.2),
|
||||||
_Logs(
|
_Logs(
|
||||||
logs: request.updateLogs, colorParser: _parseColor),
|
logs: request.updateLogs, colorParser: _parseColor),
|
||||||
@ -168,36 +170,6 @@ class _PaymentRequestDetailScreenState extends State<PaymentRequestDetailScreen>
|
|||||||
);
|
);
|
||||||
})),
|
})),
|
||||||
bottomNavigationBar: _buildBottomActionBar(),
|
bottomNavigationBar: _buildBottomActionBar(),
|
||||||
|
|
||||||
// ✅ Added Floating Action Button for Edit
|
|
||||||
floatingActionButton: Obx(() {
|
|
||||||
final request = controller.paymentRequest.value;
|
|
||||||
|
|
||||||
// Don't show FAB if loading or data not loaded
|
|
||||||
if (controller.isLoading.value ||
|
|
||||||
request == null ||
|
|
||||||
employeeInfo == null) {
|
|
||||||
return const SizedBox.shrink();
|
|
||||||
}
|
|
||||||
|
|
||||||
final canEdit = PaymentRequestPermissionHelper.canEditPaymentRequest(
|
|
||||||
employeeInfo,
|
|
||||||
request,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!canEdit) return const SizedBox.shrink();
|
|
||||||
|
|
||||||
return FloatingActionButton.extended(
|
|
||||||
onPressed: () => _openEditPaymentRequestBottomSheet(request),
|
|
||||||
backgroundColor: contentTheme.primary,
|
|
||||||
icon: const Icon(Icons.edit),
|
|
||||||
label: MyText.bodyMedium(
|
|
||||||
"Edit Payment Request",
|
|
||||||
fontWeight: 600,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,7 +200,6 @@ class _PaymentRequestDetailScreenState extends State<PaymentRequestDetailScreen>
|
|||||||
.hasAnyPermission(status.permissionIds ?? []);
|
.hasAnyPermission(status.permissionIds ?? []);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
// Normal status buttons
|
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
@ -253,7 +224,6 @@ class _PaymentRequestDetailScreenState extends State<PaymentRequestDetailScreen>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
// If status is reimbursement, show reimbursement bottom sheet
|
|
||||||
if (status.id == reimbursementStatusId) {
|
if (status.id == reimbursementStatusId) {
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
@ -268,15 +238,11 @@ class _PaymentRequestDetailScreenState extends State<PaymentRequestDetailScreen>
|
|||||||
onClose: () {},
|
onClose: () {},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// If status is b8586f67-dc19-49c3-b4af-224149efe1d3, open create expense
|
|
||||||
} else if (status.id ==
|
} else if (status.id ==
|
||||||
'b8586f67-dc19-49c3-b4af-224149efe1d3') {
|
'b8586f67-dc19-49c3-b4af-224149efe1d3') {
|
||||||
showCreateExpenseBottomSheet(
|
showCreateExpenseBottomSheet(
|
||||||
statusId: status.id,
|
statusId: status.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Normal status flow
|
|
||||||
} else {
|
} else {
|
||||||
final comment = await showCommentBottomSheet(
|
final comment = await showCommentBottomSheet(
|
||||||
context, status.displayName);
|
context, status.displayName);
|
||||||
@ -298,8 +264,11 @@ class _PaymentRequestDetailScreenState extends State<PaymentRequestDetailScreen>
|
|||||||
if (success) await controller.fetchPaymentRequestDetail();
|
if (success) await controller.fetchPaymentRequestDetail();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Text(status.displayName,
|
child: MyText.bodySmall(
|
||||||
style: const TextStyle(color: Colors.white)),
|
status.displayName,
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: 600,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
),
|
),
|
||||||
@ -391,21 +360,57 @@ class PaymentRequestPermissionHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _Header extends StatelessWidget {
|
// ------------------ Sub-widgets ------------------
|
||||||
|
|
||||||
|
class _Header extends StatelessWidget with UIMixin {
|
||||||
final PaymentRequestData request;
|
final PaymentRequestData request;
|
||||||
final Color Function(String) colorParser;
|
final Color Function(String) colorParser;
|
||||||
const _Header({required this.request, required this.colorParser});
|
final VoidCallback? onEdit;
|
||||||
|
final EmployeeInfo? employeeInfo;
|
||||||
|
|
||||||
|
_Header({
|
||||||
|
required this.request,
|
||||||
|
required this.colorParser,
|
||||||
|
this.onEdit,
|
||||||
|
this.employeeInfo,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final statusColor = colorParser(request.expenseStatus.color);
|
final statusColor = colorParser(request.expenseStatus.color);
|
||||||
return Row(
|
|
||||||
|
final canEdit = employeeInfo != null &&
|
||||||
|
PaymentRequestPermissionHelper.canEditPaymentRequest(
|
||||||
|
employeeInfo, request);
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
MyText.bodyMedium(
|
||||||
|
'ID: ${request.paymentRequestUID}',
|
||||||
|
fontWeight: 700,
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
if (canEdit)
|
||||||
|
IconButton(
|
||||||
|
onPressed: onEdit,
|
||||||
|
icon: Icon(Icons.edit, color: contentTheme.primary),
|
||||||
|
tooltip: "Edit Payment Request",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.calendar_month, size: 18, color: Colors.grey),
|
const Icon(Icons.calendar_month,
|
||||||
|
size: 18, color: Colors.grey),
|
||||||
MySpacing.width(6),
|
MySpacing.width(6),
|
||||||
MyText.bodySmall('Created At:', fontWeight: 600),
|
MyText.bodySmall('Created At:', fontWeight: 600),
|
||||||
MySpacing.width(6),
|
MySpacing.width(6),
|
||||||
@ -443,10 +448,14 @@ class _Header extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------ Logs, Parties, Details, Documents ------------------
|
||||||
|
|
||||||
class _Logs extends StatelessWidget {
|
class _Logs extends StatelessWidget {
|
||||||
final List<UpdateLog> logs;
|
final List<UpdateLog> logs;
|
||||||
final Color Function(String) colorParser;
|
final Color Function(String) colorParser;
|
||||||
@ -578,11 +587,32 @@ class _Parties extends StatelessWidget {
|
|||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
_labelValueRow('Project', request.project.name),
|
MyText.bodySmall("Parties:", fontWeight: 600),
|
||||||
_labelValueRow('Payee', request.payee),
|
MySpacing.height(8),
|
||||||
_labelValueRow('Created By',
|
Row(
|
||||||
'${request.createdBy.firstName} ${request.createdBy.lastName}'),
|
children: [
|
||||||
_labelValueRow('Pre-Approved', request.isAdvancePayment ? 'Yes' : 'No'),
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
MyText.labelMedium("Payee", fontWeight: 600),
|
||||||
|
MySpacing.height(2),
|
||||||
|
MyText.bodyMedium(request.payee),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
MyText.labelMedium("Project", fontWeight: 600),
|
||||||
|
MySpacing.height(2),
|
||||||
|
MyText.bodyMedium(request.project.name),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -626,7 +656,7 @@ class _Documents extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
MyText.bodySmall("Documents:", fontWeight: 600),
|
MyText.bodySmall("Documents:", fontWeight: 600),
|
||||||
const SizedBox(height: 12),
|
MySpacing.height(12),
|
||||||
ListView.separated(
|
ListView.separated(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
@ -679,7 +709,7 @@ class _Documents extends StatelessWidget {
|
|||||||
size: 20, color: Colors.grey[600]),
|
size: 20, color: Colors.grey[600]),
|
||||||
const SizedBox(width: 7),
|
const SizedBox(width: 7),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: MyText.labelSmall(
|
child: MyText.bodySmall(
|
||||||
doc.fileName,
|
doc.fileName,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user