diff --git a/lib/presentation/Screens/profilepage.dart b/lib/presentation/Screens/profilepage.dart index d52c9f6c..e0e830e5 100644 --- a/lib/presentation/Screens/profilepage.dart +++ b/lib/presentation/Screens/profilepage.dart @@ -1,6 +1,12 @@ +import 'dart:convert'; +import 'dart:io'; + import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; +import 'package:image_picker/image_picker.dart'; import 'package:intl/intl.dart'; +import 'package:pocketbase/pocketbase.dart'; class ProfileScreen extends StatefulWidget { @override @@ -8,9 +14,13 @@ class ProfileScreen extends StatefulWidget { } class _ProfileScreenState extends State { + final _pb = PocketBase('https://pb.venbait.in'); + // final _pb = PocketBase('http://127.0.0.1:8090'); final _formKey = GlobalKey(); final TextEditingController _fullNameController = TextEditingController(); final TextEditingController _dateController = TextEditingController(); + final TextEditingController _usernameController = TextEditingController(); + final TextEditingController _emailController = TextEditingController(); // To keep track of the selected date DateTime? _selectedDate; @@ -24,10 +34,64 @@ class _ProfileScreenState extends State { ]; String? _selectedCountry; bool _termsAccepted = false; + final _picker = ImagePicker(); + File? _profileImage; // Regular expression to validate Full Name (no special characters) final RegExp _nameRegExp = RegExp(r"^[a-zA-Z\s]+$"); + @override + void initState() { + super.initState(); + _fetchUserData(); // Call the function to fetch user data + } + + @override + void dispose() { + _fullNameController.dispose(); + _dateController.dispose(); + super.dispose(); + } + + void _fetchUserData() async { + try { + final userId = 'tsgehyvgy6owypj'; + final adminAuth = await _pb.admins + .authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com'); + final adminToken = adminAuth.token; + final response = await http.get( + Uri.parse( + 'https://pb.venbait.in/api/collections/users/records/$userId'), + headers: { + 'Authorization': 'Bearer $adminToken', // Add token to header + 'Content-Type': 'application/json', + }, + ); + + if (response.statusCode == 200) { + final data = jsonDecode(response.body); + setState(() { + _usernameController.text = data['username']; + _emailController.text = data['email']; + }); + } else { + print('Failed to fetch user data: ${response.body}'); + } + } catch (error) { + print('Failed to fetch user data: $error'); + } + } + + void _pickImage() async { + final XFile? pickedFile = + await _picker.pickImage(source: ImageSource.gallery); + if (pickedFile != null) { + setState(() { + _profileImage = File(pickedFile.path); + }); + } + } + // Function to open the date picker Future _pickDate() async { final DateTime today = DateTime.now(); @@ -85,6 +149,186 @@ class _ProfileScreenState extends State { }); } + void _saveProfile() async { + if (_formKey.currentState?.validate() ?? false) { + try { + String userID = 'tsgehyvgy6owypj'; + // Retrieve data from text fields and other inputs + String fullName = _fullNameController.text; + // String username = 'users55538'; + // String email = 'surendarsuri30@gmail.com'; + String dateOfBirth = _dateController.text; // in DD/MM/YYYY format + String countryRegion = _selectedCountry ?? ''; + bool termsAccepted = _termsAccepted; + + // Parse the date from dd/MM/yyyy format and convert to yyyy-MM-dd + // Parse the date from dd/MM/yyyy format and format to yyyy-MM-dd + DateTime dob = DateFormat('dd/MM/yyyy').parse(dateOfBirth); + String formattedDob = DateFormat('yyyy-MM-dd').format(dob); + + // Prepare form data + final request = http.MultipartRequest( + 'PATCH', + Uri.parse( + 'https://pb.venbait.in/api/collections/users/records/$userID'), // replace with actual user ID + ); + + // Set the fields for the user profile + request.fields['full_name'] = fullName; + // request.fields['username'] = username; + // request.fields['email'] = email; + request.fields['dob'] = formattedDob; // ensure correct format + request.fields['country_region'] = countryRegion; + request.fields['terms_accepted'] = termsAccepted.toString(); + + // Add image file if selected + if (_profileImage != null) { + request.files.add( + await http.MultipartFile.fromPath('avatar', _profileImage!.path)); + } + final adminAuth = await _pb.admins + .authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com'); + final adminToken = adminAuth.token; + // Add PocketBase auth headers if needed (for authenticated requests) + request.headers['Authorization'] = 'Bearer ${adminToken}'; + + print(request); + + // Send the request + final response = await request.send(); + + if (response.statusCode == 200) { + print(response.statusCode); + _resetFormFields(); + Navigator.pushNamed(context, 'home'); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text("Profile updated successfully!"))); + } else { + // Log the response body for better debugging + final responseBody = await response.stream.bytesToString(); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text( + "Failed to update profile: ${response.reasonPhrase}, Body: $responseBody"))); + } + } catch (error) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text("Failed to update profile: $error"))); + } + } + } + + void _confirmSaveProfile() { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + // title: Text("Confirm Save"), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + "Are you sure you want to save this page?", + style: const TextStyle( + fontSize: 14, + color: Color(0xFF898C81), + fontFamily: 'Roboto', + fontWeight: FontWeight.w400, + ), + textAlign: TextAlign.center, + ), + SizedBox(height: 8), + Text.rich( + TextSpan( + text: "Once saved, you will not be able to change your ", + style: TextStyle( + fontSize: 14, + color: Color(0xFF898C81), + fontFamily: 'Roboto', + fontWeight: FontWeight.w400, + ), + children: [ + TextSpan( + text: "name", + style: TextStyle( + fontWeight: FontWeight.w700), // Bold for "name" + ), + TextSpan( + text: " or ", + ), + TextSpan( + text: "date of birth", + style: TextStyle( + fontWeight: + FontWeight.w700), // Bold for "date of birth" + ), + TextSpan( + text: ".", + ), + ], + ), + textAlign: TextAlign.center, + ) + ], + ), + actionsAlignment: + MainAxisAlignment.center, // Center-align the buttons + actions: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + side: BorderSide( + color: Color(0xFF92722A)), // Set border color for "Cancel" + foregroundColor: Color(0xFF92722A), // Set text color + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(8), // Optional rounded corners + ), + backgroundColor: Colors.white, // No background color + ), + child: Text("Cancel"), + onPressed: () { + Navigator.of(context).pop(); // Close the dialog + }, + ), + SizedBox(width: 8), // Spacing between buttons + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: + Color(0xFF92722A), // Set background color for "Confirm" + foregroundColor: Colors.white, // Set text color + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(8), // Optional rounded corners + ), + ), + child: Text("Confirm"), + onPressed: () { + Navigator.of(context).pop(); // Close the dialog + _saveProfile(); // Call save function + }, + ), + ], + ); + }, + ); + } + + void _resetFormFields() { + print('reset'); + setState(() { + // Reset all text controllers + _fullNameController.clear(); + _dateController.clear(); + _selectedCountry = null; + _termsAccepted = false; + + // Reset profile image + _profileImage = null; + + // Reset form validation state + _formKey.currentState?.reset(); + }); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -124,18 +368,22 @@ class _ProfileScreenState extends State { children: [ CircleAvatar( radius: 50, - backgroundImage: - AssetImage("assets/edit_profile/profile.png"), - // Replace with actual image URL + backgroundImage: _profileImage != null + ? FileImage(_profileImage!) + : AssetImage("assets/edit_profile/profile.png") + as ImageProvider, child: Align( alignment: Alignment.bottomRight, - child: CircleAvatar( - radius: 15, - backgroundColor: Colors.white, - child: Icon( - Icons.camera_alt, - size: 15, - color: Colors.grey, + child: GestureDetector( + onTap: _pickImage, // Call `_pickImage` on tap + child: CircleAvatar( + radius: 15, + backgroundColor: Colors.white, + child: Icon( + Icons.camera_alt, + size: 15, + color: Colors.grey, + ), ), ), ), @@ -153,6 +401,7 @@ class _ProfileScreenState extends State { ), SizedBox(height: 10), TextFormField( + controller: _usernameController, decoration: InputDecoration( hintText: 'Mohammad Hassan', hintStyle: TextStyle(color: Colors.grey), @@ -175,6 +424,7 @@ class _ProfileScreenState extends State { ), SizedBox(height: 10), TextFormField( + controller: _emailController, decoration: InputDecoration( hintText: 'mohammad.hassan@fcsc.gov.ae', hintStyle: TextStyle(color: Colors.grey), @@ -351,6 +601,7 @@ class _ProfileScreenState extends State { onPressed: () { if (_formKey.currentState?.validate() ?? false) { _formKey.currentState?.save(); + _confirmSaveProfile(); } }, icon: Icon( diff --git a/lib/presentation/routes/drawer_routes/feedback_route.dart b/lib/presentation/routes/drawer_routes/feedback_route.dart index c88133cf..ac97ff5b 100644 --- a/lib/presentation/routes/drawer_routes/feedback_route.dart +++ b/lib/presentation/routes/drawer_routes/feedback_route.dart @@ -618,11 +618,12 @@ class _FeedbackFormState extends State { final String formattedDate = DateFormat('dd-MM-yyyy').format(feedbackDateTime); - // Format date and time as DD.MM.YYYY HH:mm with UTC suffix - final String formattedDateTime = - DateFormat('dd.MM.yyyy HH:mm').format(feedbackDateTime) + ' UTC'; + // Format to the desired output: "dd.MM.yyyy HH:mm 'UTC'" + final DateFormat formatter = DateFormat("dd.MM.yyyy HH:mm 'UTC'"); + String formattedDateTime = formatter.format(feedbackDateTime); - print("Formatted Date and Time (UTC): $formattedDateTime"); + // Assuming the server timezone as UTC, you can append as needed + String submissionTime = "$formattedDateTime "; print("Formatted Date (UTC): $formattedDate"); String email = configEmail; // Direct assignment @@ -640,7 +641,7 @@ class _FeedbackFormState extends State { 1. Name: Guest 2. Date of Submission: $formattedDate - 3. Time of Submission: $formattedDateTime + 3. Time of Submission: $submissionTime Feedback: