Edit Profile Page Updated
This commit is contained in:
parent
32a468f51d
commit
aa08648a56
@ -1,8 +1,87 @@
|
|||||||
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:uae_stat/presentation/components/my_bottom_nav_bar.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
class ProfileScreen extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
State<ProfileScreen> createState() => _ProfileScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ProfileScreenState extends State<ProfileScreen> {
|
||||||
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
final TextEditingController _fullNameController = TextEditingController();
|
||||||
|
final TextEditingController _dateController = TextEditingController();
|
||||||
|
// To keep track of the selected date
|
||||||
|
DateTime? _selectedDate;
|
||||||
|
|
||||||
|
// Date format for the display
|
||||||
|
final DateFormat _dateFormat = DateFormat('yyyy-MM-dd');
|
||||||
|
final List<String> _countries = [
|
||||||
|
'United Arab Emirates',
|
||||||
|
'United States',
|
||||||
|
'India',
|
||||||
|
'Canada'
|
||||||
|
];
|
||||||
|
String? _selectedCountry;
|
||||||
|
bool _termsAccepted = false;
|
||||||
|
|
||||||
|
// Regular expression to validate Full Name (no special characters)
|
||||||
|
final RegExp _nameRegExp = RegExp(r"^[a-zA-Z\s]+$");
|
||||||
|
|
||||||
|
// Function to open the date picker
|
||||||
|
Future<void> _pickDate() async {
|
||||||
|
final DateTime today = DateTime.now();
|
||||||
|
final DateTime initialDate = _selectedDate ?? today.subtract(const Duration(days: 365 * 18)); // Default to 18 years ago
|
||||||
|
final DateTime firstDate = today.subtract(const Duration(days: 365 * 100)); // Allow picking dates back to 100 years ago
|
||||||
|
final DateTime lastDate = today; // Allow picking dates up to today
|
||||||
|
|
||||||
|
// Updated Date format to DD/MM/YYYY
|
||||||
|
final DateFormat _dateFormat = DateFormat('dd/MM/yyyy');
|
||||||
|
|
||||||
|
final DateTime? pickedDate = await showDatePicker(
|
||||||
|
context: context,
|
||||||
|
initialDate: initialDate,
|
||||||
|
firstDate: firstDate,
|
||||||
|
lastDate: lastDate,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (pickedDate != null && pickedDate != _selectedDate) {
|
||||||
|
setState(() {
|
||||||
|
_selectedDate = pickedDate;
|
||||||
|
_dateController.text = _dateFormat.format(pickedDate);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to validate the DOB field
|
||||||
|
String? _validateDob(String? value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'Please select your date of birth';
|
||||||
|
}
|
||||||
|
|
||||||
|
final DateTime selectedDate = _selectedDate!;
|
||||||
|
final DateTime today = DateTime.now();
|
||||||
|
|
||||||
|
// Check if the selected date is in the future
|
||||||
|
if (selectedDate.isAfter(today)) {
|
||||||
|
return 'Date of birth cannot be in the future';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String? _validateDropdown(String? value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'Please select an option';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _toggleCheckbox(bool? value) {
|
||||||
|
setState(() {
|
||||||
|
_termsAccepted = value ?? false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
class ProfileScreen extends StatelessWidget {
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@ -11,7 +90,9 @@ class ProfileScreen extends StatelessWidget {
|
|||||||
elevation: 0,
|
elevation: 0,
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
icon: Icon(Icons.arrow_back_ios_new, color: Colors.black),
|
icon: Icon(Icons.arrow_back_ios_new, color: Colors.black),
|
||||||
onPressed: () {},
|
onPressed: () {
|
||||||
|
print("Back Button");
|
||||||
|
},
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
'My Profile',
|
'My Profile',
|
||||||
@ -32,95 +113,259 @@ class ProfileScreen extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
child: Padding(
|
child: Form(
|
||||||
padding: const EdgeInsets.all(16.0),
|
key: _formKey,
|
||||||
child: Column(
|
child: Padding(
|
||||||
children: [
|
padding: const EdgeInsets.all(20.0),
|
||||||
CircleAvatar(
|
child: Column(
|
||||||
radius: 50,
|
children: [
|
||||||
backgroundImage: AssetImage("assets/edit_profile/profile.png"), // Replace with actual image URL
|
CircleAvatar(
|
||||||
child: Align(
|
radius: 50,
|
||||||
alignment: Alignment.bottomRight,
|
backgroundImage:
|
||||||
child: CircleAvatar(
|
AssetImage("assets/edit_profile/profile.png"),
|
||||||
radius: 15,
|
// Replace with actual image URL
|
||||||
backgroundColor: Colors.white,
|
child: Align(
|
||||||
child: Icon(
|
alignment: Alignment.bottomRight,
|
||||||
Icons.camera_alt,
|
child: CircleAvatar(
|
||||||
size: 15,
|
radius: 15,
|
||||||
color: Colors.grey,
|
backgroundColor: Colors.white,
|
||||||
|
child: Icon(
|
||||||
|
Icons.camera_alt,
|
||||||
|
size: 15,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
SizedBox(height: 20),
|
||||||
SizedBox(height: 20),
|
Row(
|
||||||
ProfileField(label: 'Name', hintText: 'Mohammad Hassan'),
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
SizedBox(height: 10),
|
children: [
|
||||||
ProfileField(label: 'Email', hintText: 'mohammad.hassan@fcsc.gov.ae'),
|
Text("User Name",
|
||||||
SizedBox(height: 10),
|
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
|
||||||
ProfileField(label: 'Password', hintText: '********', obscureText: true),
|
),
|
||||||
SizedBox(height: 10),
|
],
|
||||||
ProfileField(label: 'Date of Birth', hintText: '23/05/1995', isDropdown: true),
|
),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
ProfileField(label: 'Country/Region', hintText: 'United Arab Emirates', isDropdown: true),
|
TextFormField(
|
||||||
SizedBox(height: 20),
|
decoration: InputDecoration(
|
||||||
ElevatedButton.icon(
|
hintText: 'Mohammad Hassan',
|
||||||
onPressed: () {},
|
hintStyle: TextStyle(color: Colors.grey),
|
||||||
icon: Icon(Icons.save,color: Colors.white,),
|
border: OutlineInputBorder(
|
||||||
label: Text('Save',style: TextStyle(color: Colors.white),),
|
borderRadius: BorderRadius.circular(8),
|
||||||
style: ElevatedButton.styleFrom(
|
),enabled: false,
|
||||||
backgroundColor: Color(0xFF92722A),
|
|
||||||
minimumSize: Size(double.infinity, 50),
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
SizedBox(height: 10),
|
||||||
],
|
Row(
|
||||||
),
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
),
|
children: [
|
||||||
|
Text("E-mail",
|
||||||
|
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
TextFormField(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: 'mohammad.hassan@fcsc.gov.ae',
|
||||||
|
hintStyle: TextStyle(color: Colors.grey),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),enabled: false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text("Full Name",
|
||||||
|
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
TextFormField(
|
||||||
|
enabled: true,
|
||||||
|
validator: (value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'Required';
|
||||||
|
}
|
||||||
|
final nameRegex = RegExp(r"^[a-zA-Z\s]+$");
|
||||||
|
if (!nameRegex.hasMatch(value)) {
|
||||||
|
return 'Invalid Characters';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
controller: _fullNameController,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: "Mohammad",
|
||||||
|
hintStyle: TextStyle(color: Colors.grey),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text("Date of Birth*",
|
||||||
|
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
|
||||||
),
|
TextFormField(
|
||||||
//bottomNavigationBar: MyBottomNavBar(),
|
controller: _dateController,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
hintText: 'Select your Date of Birth',
|
||||||
|
suffixIcon: const Icon(Icons.arrow_drop_down_sharp),
|
||||||
|
),
|
||||||
|
|
||||||
);
|
readOnly: true,
|
||||||
}
|
onTap: _pickDate,
|
||||||
}
|
validator: _validateDob,
|
||||||
|
),
|
||||||
|
|
||||||
class ProfileField extends StatelessWidget {
|
SizedBox(height: 10),
|
||||||
final String label;
|
Row(
|
||||||
final String hintText;
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
final bool obscureText;
|
children: [
|
||||||
final bool isDropdown;
|
Text("Country/Region*",
|
||||||
|
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
DropdownButtonFormField<String>(
|
||||||
|
value: _selectedCountry,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
labelText: 'Select',
|
||||||
|
),
|
||||||
|
items: _countries
|
||||||
|
.map((item) => DropdownMenuItem<String>(
|
||||||
|
value: item,
|
||||||
|
child: Text(item),
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
onChanged: (String? newValue) {
|
||||||
|
setState(() {
|
||||||
|
_selectedCountry = newValue;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
validator: _validateDropdown,
|
||||||
|
),
|
||||||
|
SizedBox(height: 20),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Checkbox(
|
||||||
|
value: _termsAccepted,
|
||||||
|
onChanged: _toggleCheckbox,
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
SizedBox(height: 10,),
|
||||||
|
Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
text: 'I agree to the ',
|
||||||
|
style: TextStyle(color: Colors.black),
|
||||||
|
children: [
|
||||||
|
TextSpan(
|
||||||
|
text: 'Terms & Conditions',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.blue,
|
||||||
|
decoration: TextDecoration.underline,
|
||||||
|
),
|
||||||
|
recognizer: TapGestureRecognizer()
|
||||||
|
..onTap = () {
|
||||||
|
// Add action for Terms & Conditions tap
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextSpan(
|
||||||
|
text: ' and ',
|
||||||
|
style: TextStyle(color: Colors.black),
|
||||||
|
),
|
||||||
|
TextSpan(
|
||||||
|
text: 'Privacy Policy',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.blue,
|
||||||
|
decoration: TextDecoration.underline,
|
||||||
|
),
|
||||||
|
recognizer: TapGestureRecognizer()
|
||||||
|
..onTap = () {
|
||||||
|
// Add action for Privacy Policy tap
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextSpan(
|
||||||
|
text: ' of FCSC.',
|
||||||
|
style: TextStyle(color: Colors.black),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.visible,
|
||||||
|
softWrap: true,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 20),
|
||||||
|
|
||||||
ProfileField({
|
Center(child: Text("Change Password",style: TextStyle(color: Colors.blue,decoration: TextDecoration.underline),),),
|
||||||
required this.label,
|
SizedBox(height: 20),
|
||||||
required this.hintText,
|
ElevatedButton.icon(
|
||||||
this.obscureText = false,
|
onPressed: () {
|
||||||
this.isDropdown = false,
|
if (_formKey.currentState?.validate() ?? false) {
|
||||||
});
|
_formKey.currentState?.save();
|
||||||
|
}
|
||||||
@override
|
},
|
||||||
Widget build(BuildContext context) {
|
icon: Icon(
|
||||||
return Column(
|
Icons.save,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
color: Colors.white,
|
||||||
children: [
|
),
|
||||||
Text(
|
label: Text(
|
||||||
label,
|
'Save',
|
||||||
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
|
style: TextStyle(color: Colors.white),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
style: ElevatedButton.styleFrom(
|
||||||
TextFormField(
|
backgroundColor: Color(0xFF92722A),
|
||||||
obscureText: obscureText,
|
minimumSize: Size(double.infinity, 50),
|
||||||
readOnly: isDropdown,
|
shape: RoundedRectangleBorder(
|
||||||
decoration: InputDecoration(
|
borderRadius: BorderRadius.circular(8),
|
||||||
hintText: hintText,
|
),
|
||||||
suffixIcon: isDropdown ? Icon(Icons.arrow_drop_down) : null,
|
),
|
||||||
border: OutlineInputBorder(
|
),
|
||||||
borderRadius: BorderRadius.circular(8),
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
|
//bottomNavigationBar: MyBottomNavBar(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
import 'package:external_repos/external_repos.dart';
|
import 'package:external_repos/external_repos.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
|||||||
16
pubspec.lock
16
pubspec.lock
@ -753,6 +753,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.0"
|
||||||
|
nested:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: nested
|
||||||
|
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
package_config:
|
package_config:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -857,6 +865,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.1"
|
version: "1.5.1"
|
||||||
|
provider:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: provider
|
||||||
|
sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.1.2"
|
||||||
pub_semver:
|
pub_semver:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@ -51,6 +51,7 @@ dependencies:
|
|||||||
freezed_annotation: ^2.4.4
|
freezed_annotation: ^2.4.4
|
||||||
shared_preferences: ^2.2.3
|
shared_preferences: ^2.2.3
|
||||||
flutter_rating_bar: ^4.0.1
|
flutter_rating_bar: ^4.0.1
|
||||||
|
provider: ^6.1.2
|
||||||
|
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
fading_edge_scrollview: ^4.1.1
|
fading_edge_scrollview: ^4.1.1
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user