From c95a3f1581bd83b7104fd902e29a4d30d8b0f1b9 Mon Sep 17 00:00:00 2001 From: risazmat Date: Sun, 27 Sep 2026 09:01:11 +0530 Subject: [PATCH] Fix profile update endpoint/payload and hide dead menu entries --- .../tabbed_layout_component.dart | 20 ++-- .../profileManagement/Profilesettings.dart | 109 ++++++++++-------- 2 files changed, 74 insertions(+), 55 deletions(-) diff --git a/lib/screens/main_app_screen/tabbed_layout_component.dart b/lib/screens/main_app_screen/tabbed_layout_component.dart index 7b8fae7..5024305 100644 --- a/lib/screens/main_app_screen/tabbed_layout_component.dart +++ b/lib/screens/main_app_screen/tabbed_layout_component.dart @@ -178,7 +178,8 @@ class _TabbedLayoutComponentState extends State { print("Selected: $result"); }, itemBuilder: (BuildContext context) => [ - PopupMenuItem( + // COMMENTED OUT: no backend endpoint (service_request/raise_ticket) + /*PopupMenuItem( //value: 'Option 1', child: Text( 'Raise A Ticket', @@ -194,7 +195,7 @@ class _TabbedLayoutComponentState extends State { ), ); }, - ), + ),*/ PopupMenuItem( //value: 'Option 1', @@ -254,7 +255,8 @@ class _TabbedLayoutComponentState extends State { }, ), - PopupMenuItem( + // COMMENTED OUT + /*PopupMenuItem( //value: 'Option 1', child: Text( 'Setup Screen', @@ -270,9 +272,10 @@ class _TabbedLayoutComponentState extends State { ); // Add your logic for menu 2 here }, - ), + ),*/ - PopupMenuItem( + // COMMENTED OUT: no backend endpoint (/Bookmarks -> 404) + /*PopupMenuItem( //value: 'Option 1', child: Text( 'BookMark', @@ -289,9 +292,10 @@ class _TabbedLayoutComponentState extends State { ); // Add your logic for menu 2 here }, - ), + ),*/ - PopupMenuItem( + // COMMENTED OUT + /*PopupMenuItem( //value: 'Option 1', child: Text( 'System Parameter', @@ -307,7 +311,7 @@ class _TabbedLayoutComponentState extends State { ); // Add your logic for menu 2 here }, - ), + ),*/ PopupMenuItem( //value: 'Option 1', diff --git a/lib/screens/profileManagement/Profilesettings.dart b/lib/screens/profileManagement/Profilesettings.dart index 3ff118b..f9d3b59 100644 --- a/lib/screens/profileManagement/Profilesettings.dart +++ b/lib/screens/profileManagement/Profilesettings.dart @@ -32,9 +32,8 @@ class ProfileSettingsScreen extends StatefulWidget { class _ProfileSettingsScreenState extends State { ApiServiceProfileManagement apiService = ApiServiceProfileManagement(); - String? fetchedimageurl = - 'http://43.205.154.152:30165/assets/images/profile-icon.png'; - Uint8List? _imageBytes; // Uint8List to store the image data + Uint8List? _imageBytes; // Uint8List to store the picked image data + Uint8List? _fetchedImageBytes; // image bytes fetched from server String? _imageFileName; final _formKey = GlobalKey(); @@ -48,7 +47,7 @@ class _ProfileSettingsScreenState extends State { @override void initState() { super.initState(); - //fetchProfileImageData(); + fetchProfileImageData(); fetchUserProfileData(); } @@ -66,6 +65,8 @@ class _ProfileSettingsScreenState extends State { _imageBytes = imageBytes; _imageFileName = pickedImage.name; // Store the file name }); + // Upload immediately after pick (same as authsec_flutter_new) and refresh + await _submitImage(); } } catch (e) { print(e); @@ -127,10 +128,13 @@ class _ProfileSettingsScreenState extends State { } if (response.statusCode >= 200 && response.statusCode <= 209) { final Map jsonData = json.decode(response.body); - final trustedImageUrl = Uri.dataFromString(jsonData['image'], - mimeType: 'image/*', encoding: Encoding.getByName('utf-8')) - .toString(); - fetchedimageurl = trustedImageUrl; + final String base64Image = jsonData['image'] as String; + // Same as authsec_flutter_new: strip data-url prefix, base64 decode + final Uint8List imageBytes = + base64Decode(base64Image.split(',').last); + setState(() { + _fetchedImageBytes = imageBytes; + }); } else { throw Exception('Failed to load data: ${response.statusCode}'); } @@ -170,6 +174,13 @@ class _ProfileSettingsScreenState extends State { try { final token = await TokenManager.getToken(); await apiService.createFile(_imageBytes!, _imageFileName!, token!); + // Refresh displayed image (same as authsec_flutter_new getProfileImg) + await fetchProfileImageData(); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Profile image updated')), + ); + } } catch (e) { showDialog( context: context, @@ -193,21 +204,27 @@ class _ProfileSettingsScreenState extends State { Future _updateProfile() async { if (_formKey.currentState!.validate()) { - // Create a JSON object with the form data + // Same contract as authsec_flutter_new: PUT /api/updateAppUserDto/{userId} + // with only backend-persisted keys (AppUserDto: fullName, email). + final dynamic rawUserId = widget.userData['userId']; + if (rawUserId == null) { + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('User id missing, please re-login')), + ); + } + return; + } + final String userId = rawUserId.toString(); final profileData = { + 'userId': userId, 'fullName': fullNameController.text, - 'pronouns': pronounsController.text, - 'role': roleController.text, - 'department': departmentController.text, 'email': emailController.text, - 'aboutMe': aboutMeController.text, }; - //api/user-profile - final token = await TokenManager.getToken(); final String baseUrl = ApiConstants.baseUrl; - final String apiUrl = '$baseUrl/api/user-profile'; + final String apiUrl = '$baseUrl/api/updateAppUserDto/$userId'; try { final response = await http.put(Uri.parse(apiUrl), headers: { @@ -218,14 +235,31 @@ class _ProfileSettingsScreenState extends State { if (response.statusCode == 401) { LogoutService.logout(); } - if (response.statusCode <= 209) { + if (response.statusCode >= 200 && response.statusCode <= 209) { print("success"); - Navigator.of(context).pop(); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Profile updated')), + ); + Navigator.of(context).pop(); + } } else { print(response.statusCode); + print(response.body); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + 'Failed to update profile: ${response.statusCode}')), + ); + } } } catch (e) { - throw Exception('Failed to Update: $e'); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Failed to update: $e')), + ); + } } } } @@ -277,22 +311,21 @@ class _ProfileSettingsScreenState extends State { children: [ CircleAvatar( radius: 70, // Adjust as needed - backgroundImage: NetworkImage( - "$fetchedimageurl"), // Replace with your API URL + backgroundImage: (_imageBytes ?? _fetchedImageBytes) != null + ? MemoryImage(_imageBytes ?? _fetchedImageBytes!) + : null, + child: (_imageBytes ?? _fetchedImageBytes) != null + ? null + : const Icon(Icons.person, size: 60), ), SizedBox(height: 10), CustomButton( height: getVerticalSize(50), - text: _imageBytes == null - ? "Pick a Profile Photo" - : 'Upload Success', + text: "Pick a Profile Photo", margin: getMargin(top: 24, bottom: 5), onTap: () async { - if (_imageBytes != null) { - _submitImage(); - } else { - _uploadImageFile(); - } + // Pick + auto-upload, same as authsec_flutter_new + await _uploadImageFile(); }, ), ], @@ -330,9 +363,6 @@ class _ProfileSettingsScreenState extends State { } return null; }, - onChanged: (value) { - fullNameController.text = value; - }, margin: getMargin(top: 6)) ])), Padding( @@ -349,9 +379,6 @@ class _ProfileSettingsScreenState extends State { focusNode: FocusNode(), hintText: "Enter Pronouns", controller: pronounsController, - onChanged: (value) { - pronounsController.text = value; - }, margin: getMargin(top: 6)) ])), Padding( @@ -368,9 +395,6 @@ class _ProfileSettingsScreenState extends State { focusNode: FocusNode(), hintText: "Enter Role", controller: roleController, - onChanged: (value) { - roleController.text = value; - }, margin: getMargin(top: 6)) ])), Padding( @@ -387,9 +411,6 @@ class _ProfileSettingsScreenState extends State { focusNode: FocusNode(), hintText: "Enter Department or Team", controller: departmentController, - onChanged: (value) { - departmentController.text = value; - }, margin: getMargin(top: 6)) ])), Padding( @@ -412,9 +433,6 @@ class _ProfileSettingsScreenState extends State { } return null; }, - onChanged: (value) { - emailController.text = value; - }, margin: getMargin(top: 6)) ])), Padding( @@ -432,9 +450,6 @@ class _ProfileSettingsScreenState extends State { hintText: "About Me", controller: aboutMeController, maxLines: 3, - onChanged: (value) { - aboutMeController.text = value; - }, margin: getMargin(top: 6)) ])), CustomButton(