From 2133dedfae7b8e81600b3aecf38ced0330ea6db2 Mon Sep 17 00:00:00 2001 From: Vaibhav Surve Date: Thu, 4 Sep 2025 17:41:11 +0530 Subject: [PATCH] feat: Refactor employee detail navigation and add employee profile screen with tabbed interface --- lib/view/document/user_document_screen.dart | 23 ++--- .../employees/employee_detail_screen.dart | 90 ++++--------------- .../employees/employee_profile_screen.dart | 80 +++++++++++++++++ lib/view/layouts/user_profile_right_bar.dart | 10 +-- 4 files changed, 115 insertions(+), 88 deletions(-) create mode 100644 lib/view/employees/employee_profile_screen.dart diff --git a/lib/view/document/user_document_screen.dart b/lib/view/document/user_document_screen.dart index 402704c..c2d78ee 100644 --- a/lib/view/document/user_document_screen.dart +++ b/lib/view/document/user_document_screen.dart @@ -139,7 +139,7 @@ class _UserDocumentsPageState extends State { ), IconButton( icon: const Icon(Icons.arrow_forward_ios, color: Colors.black54), - onPressed: () {/* future actions */}, + onPressed: () {}, ), ], ), @@ -257,14 +257,19 @@ class _UserDocumentsPageState extends State { @override Widget build(BuildContext context) { + // Conditionally show AppBar (example: hide if employee view) + final bool showAppBar = !widget.isEmployee; + return Scaffold( backgroundColor: const Color(0xFFF1F1F1), - appBar: CustomAppBar( - title: 'Documents', - onBackPressed: () { - Get.back(); - }, - ), + appBar: showAppBar + ? CustomAppBar( + title: 'Documents', + onBackPressed: () { + Get.back(); + }, + ) + : null, body: _buildBody(context), floatingActionButton: FloatingActionButton.extended( onPressed: () { @@ -289,17 +294,13 @@ class _UserDocumentsPageState extends State { ); if (success) { - // ✅ Only close on success Navigator.pop(context); - - // Refresh list docController.fetchDocuments( entityTypeId: entityTypeId, entityId: resolvedEntityId, reset: true, ); } else { - // ❌ Don’t close, show error Get.snackbar("Error", "Upload failed, please try again"); } }, diff --git a/lib/view/employees/employee_detail_screen.dart b/lib/view/employees/employee_detail_screen.dart index 27fb507..ffd1a63 100644 --- a/lib/view/employees/employee_detail_screen.dart +++ b/lib/view/employees/employee_detail_screen.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:intl/intl.dart'; import 'package:marco/controller/employee/employees_screen_controller.dart'; -import 'package:marco/controller/project_controller.dart'; +import 'package:marco/helpers/widgets/custom_app_bar.dart'; import 'package:marco/helpers/widgets/avatar.dart'; import 'package:marco/helpers/widgets/my_spacing.dart'; import 'package:marco/helpers/widgets/my_text.dart'; @@ -15,6 +15,7 @@ import 'package:marco/helpers/widgets/my_refresh_indicator.dart'; class EmployeeDetailPage extends StatefulWidget { final String employeeId; final bool fromProfile; + const EmployeeDetailPage({ super.key, required this.employeeId, @@ -30,6 +31,7 @@ class _EmployeeDetailPageState extends State { Get.put(EmployeesScreenController()); final PermissionController _permissionController = Get.find(); + @override void initState() { super.initState(); @@ -60,7 +62,6 @@ class _EmployeeDetailPageState extends State { } } - /// Row builder with email/phone tap & copy support Widget _buildLabelValueRow(String label, String value, {bool isMultiLine = false}) { final lowerLabel = label.toLowerCase(); @@ -91,9 +92,8 @@ class _EmployeeDetailPageState extends State { fontWeight: FontWeight.normal, color: (isEmail || isPhone) ? Colors.indigo : Colors.black54, fontSize: 14, - decoration: (isEmail || isPhone) - ? TextDecoration.underline - : TextDecoration.none, + decoration: + (isEmail || isPhone) ? TextDecoration.underline : TextDecoration.none, ), ), ); @@ -147,7 +147,6 @@ class _EmployeeDetailPageState extends State { ); } - /// Info card Widget _buildInfoCard(employee) { return Card( elevation: 3, @@ -188,73 +187,22 @@ class _EmployeeDetailPageState extends State { @override Widget build(BuildContext context) { + final bool showAppBar = !widget.fromProfile; + return Scaffold( backgroundColor: const Color(0xFFF1F1F1), - appBar: PreferredSize( - preferredSize: const Size.fromHeight(72), - child: AppBar( - backgroundColor: const Color(0xFFF5F5F5), - elevation: 0.5, - automaticallyImplyLeading: false, - titleSpacing: 0, - title: Padding( - padding: MySpacing.xy(16, 0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - IconButton( - icon: const Icon(Icons.arrow_back_ios_new, - color: Colors.black, size: 20), - onPressed: () { - if (widget.fromProfile) { - Get.back(); - } else { - Get.offNamed('/dashboard/employees'); - } - }, - ), - MySpacing.width(8), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - MyText.titleLarge( - 'Employee Details', - fontWeight: 700, - color: Colors.black, - ), - MySpacing.height(2), - GetBuilder( - builder: (projectController) { - final projectName = - projectController.selectedProject?.name ?? - 'Select Project'; - return Row( - children: [ - const Icon(Icons.work_outline, - size: 14, color: Colors.grey), - MySpacing.width(4), - Expanded( - child: MyText.bodySmall( - projectName, - fontWeight: 600, - overflow: TextOverflow.ellipsis, - color: Colors.grey[700], - ), - ), - ], - ); - }, - ), - ], - ), - ), - ], - ), - ), - ), - ), + appBar: showAppBar + ? CustomAppBar( + title: 'Employee Details', + onBackPressed: () { + if (widget.fromProfile) { + Get.back(); + } else { + Get.offNamed('/dashboard/employees'); + } + }, + ) + : null, body: Obx(() { if (controller.isLoadingEmployeeDetails.value) { return const Center(child: CircularProgressIndicator()); diff --git a/lib/view/employees/employee_profile_screen.dart b/lib/view/employees/employee_profile_screen.dart new file mode 100644 index 0000000..726c452 --- /dev/null +++ b/lib/view/employees/employee_profile_screen.dart @@ -0,0 +1,80 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:marco/view/employees/employee_detail_screen.dart'; +import 'package:marco/view/document/user_document_screen.dart'; +import 'package:marco/helpers/widgets/custom_app_bar.dart'; + +class EmployeeProfilePage extends StatefulWidget { + final String employeeId; + + const EmployeeProfilePage({super.key, required this.employeeId}); + + @override + State createState() => _EmployeeProfilePageState(); +} + +class _EmployeeProfilePageState extends State + with SingleTickerProviderStateMixin { + late TabController _tabController; + + @override + void initState() { + super.initState(); + _tabController = TabController(length: 2, vsync: this); + } + + @override + void dispose() { + _tabController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: const Color(0xFFF1F1F1), + appBar: CustomAppBar( + title: "Employee Profile", + onBackPressed: () => Get.back(), + ), + body: Column( + children: [ + // ---------------- TabBar outside AppBar ---------------- + Container( + color: Colors.white, + child: TabBar( + controller: _tabController, + labelColor: Colors.black, + unselectedLabelColor: Colors.grey, + indicatorColor: Colors.red, + tabs: const [ + Tab(text: "Details"), + Tab(text: "Documents"), + ], + ), + ), + + // ---------------- TabBarView ---------------- + Expanded( + child: TabBarView( + controller: _tabController, + children: [ + // Details Tab + EmployeeDetailPage( + employeeId: widget.employeeId, + fromProfile: true, + ), + + // Documents Tab + UserDocumentsPage( + entityId: widget.employeeId, + isEmployee: true, + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/view/layouts/user_profile_right_bar.dart b/lib/view/layouts/user_profile_right_bar.dart index 9b2712d..45dc62f 100644 --- a/lib/view/layouts/user_profile_right_bar.dart +++ b/lib/view/layouts/user_profile_right_bar.dart @@ -9,10 +9,9 @@ import 'package:marco/helpers/widgets/my_text.dart'; import 'package:marco/helpers/widgets/avatar.dart'; import 'package:marco/model/employees/employee_info.dart'; import 'package:marco/controller/auth/mpin_controller.dart'; -import 'package:marco/view/employees/employee_detail_screen.dart'; +import 'package:marco/view/employees/employee_profile_screen.dart'; import 'package:marco/view/document/user_document_screen.dart'; - class UserProfileBar extends StatefulWidget { final bool isCondensed; const UserProfileBar({Key? key, this.isCondensed = false}) : super(key: key); @@ -182,7 +181,7 @@ class _UserProfileBarState extends State _menuItemRow( icon: LucideIcons.file_text, label: 'My Documents', - onTap: _onDocumentsTap, + onTap: _onDocumentsTap, ), SizedBox(height: spacingHeight), _menuItemRow( @@ -246,15 +245,14 @@ class _UserProfileBarState extends State } void _onProfileTap() { - Get.to(() => EmployeeDetailPage( + Get.to(() => EmployeeProfilePage( employeeId: employeeInfo.id, - fromProfile: true, )); } void _onDocumentsTap() { Get.to(() => UserDocumentsPage( - entityId: "${employeeInfo.id}", + entityId: "${employeeInfo.id}", isEmployee: true, )); }