edit profile screen ui
This commit is contained in:
158
lib/Utils/Common/ImageUpload.dart
Normal file
158
lib/Utils/Common/ImageUpload.dart
Normal file
@@ -0,0 +1,158 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:traderscircuit/Utils/Common/sized_box.dart';
|
||||
import 'package:traderscircuit/controller/profile_image_controller.dart';
|
||||
|
||||
import 'ImagePicker.dart';
|
||||
import 'SingleFilePicker.dart';
|
||||
|
||||
class ImageUploadBottomSheet {
|
||||
final ProfileImageController editProfileImage =
|
||||
Get.put(ProfileImageController());
|
||||
showModal(
|
||||
BuildContext context,
|
||||
bool showFile,
|
||||
Function(String) onImagePicked,
|
||||
) {
|
||||
return showModalBottomSheet(
|
||||
isScrollControlled: true,
|
||||
context: context,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(26.r),
|
||||
topRight: Radius.circular(26.r),
|
||||
),
|
||||
),
|
||||
builder: (context) {
|
||||
return Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: 36.w, vertical: 26.h),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.of(context).viewInsets.bottom),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
(showFile) ? 'Select Image/File' : 'Select Image',
|
||||
style: TextStyle(
|
||||
color: const Color(0xff444444),
|
||||
fontSize: 22.sp,
|
||||
),
|
||||
),
|
||||
sizedBoxHeight(40.h),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
// editProfileImage.getImage(ImageSource.camera);
|
||||
var result = await ImagePickerMethod()
|
||||
.getImage(ImageSource.camera);
|
||||
onImagePicked(result);
|
||||
|
||||
Get.back();
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
CircleAvatar(
|
||||
radius: 27.r,
|
||||
backgroundColor: const Color(0xFFE8C69F80),
|
||||
child: Icon(
|
||||
Icons.camera_alt_outlined,
|
||||
size: 30.sp,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 6.h,
|
||||
),
|
||||
Text(
|
||||
'Camera',
|
||||
style: TextStyle(
|
||||
fontSize: 13.sp,
|
||||
color: const Color(0xff444444),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
sizedBoxWidth(36.w),
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
var result = await ImagePickerMethod()
|
||||
.getImage(ImageSource.gallery);
|
||||
onImagePicked(result);
|
||||
Get.back();
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
CircleAvatar(
|
||||
radius: 27.r,
|
||||
backgroundColor: const Color(0xFFE8C69F80),
|
||||
child: Icon(
|
||||
Icons.image_outlined,
|
||||
size: 30.sp,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 6.h,
|
||||
),
|
||||
Text(
|
||||
'Gallery',
|
||||
style: TextStyle(
|
||||
fontSize: 13.sp,
|
||||
color: const Color(0xff444444),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Visibility(visible: showFile, child: sizedBoxWidth(36.w)),
|
||||
Visibility(
|
||||
visible: showFile,
|
||||
child: GestureDetector(
|
||||
onTap: () async {
|
||||
var result =
|
||||
await SingleFilePickerMethod().pickFile();
|
||||
onImagePicked(result?.path ?? "");
|
||||
Get.back();
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
CircleAvatar(
|
||||
radius: 27.r,
|
||||
backgroundColor: const Color(0xFFE8C69F80),
|
||||
child: Icon(
|
||||
Icons.file_copy_outlined,
|
||||
size: 30.sp,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 6.h,
|
||||
),
|
||||
Text(
|
||||
'File',
|
||||
style: TextStyle(
|
||||
fontSize: 13.sp,
|
||||
color: const Color(0xff444444),
|
||||
fontFamily: 'Poppins'),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
23
lib/Utils/Common/SingleFilePicker.dart
Normal file
23
lib/Utils/Common/SingleFilePicker.dart
Normal file
@@ -0,0 +1,23 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
|
||||
class SingleFilePickerMethod {
|
||||
Future<File?> pickFile() async {
|
||||
FilePickerResult? result = await FilePicker.platform.pickFiles(
|
||||
type: FileType.custom,
|
||||
allowedExtensions: [
|
||||
'jpg',
|
||||
'jpeg',
|
||||
'png',
|
||||
'pdf'
|
||||
], // Define the allowed file types
|
||||
);
|
||||
|
||||
if (result != null) {
|
||||
return File(result.files.single.path!);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
50
lib/controller/profile_image_controller.dart
Normal file
50
lib/controller/profile_image_controller.dart
Normal file
@@ -0,0 +1,50 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:image_cropper/image_cropper.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
|
||||
class ProfileImageController extends GetxController {
|
||||
RxString profilePicPath = "".obs;
|
||||
//RxString fileNameFromPath = "".obs;
|
||||
|
||||
void getImage(ImageSource imgSource) async {
|
||||
final ImagePicker picker = ImagePicker();
|
||||
print('profilePicPath $profilePicPath');
|
||||
final XFile? pickedImg = await picker.pickImage(source: imgSource);
|
||||
if (pickedImg != null) {
|
||||
final CroppedFile? croppedImg = await ImageCropper().cropImage(
|
||||
sourcePath: pickedImg.path,
|
||||
aspectRatio: const CropAspectRatio(ratioX: 1, ratioY: 1),
|
||||
compressFormat: ImageCompressFormat.jpg,
|
||||
maxHeight: 512,
|
||||
maxWidth: 512,
|
||||
compressQuality: 100,
|
||||
cropStyle: CropStyle.circle,
|
||||
aspectRatioPresets: [
|
||||
CropAspectRatioPreset.square,
|
||||
],
|
||||
uiSettings: [
|
||||
AndroidUiSettings(
|
||||
toolbarTitle: "Crop Image",
|
||||
toolbarColor: Get.theme.appBarTheme.backgroundColor,
|
||||
// toolbarWidgetColor: ColorConstants.kWhite,
|
||||
backgroundColor: Colors.black,
|
||||
activeControlsWidgetColor: Colors.red,
|
||||
// initAspectRatio: CropAspectRatioPreset.original,
|
||||
cropFrameColor: Colors.white,
|
||||
lockAspectRatio: false,
|
||||
),
|
||||
IOSUiSettings(
|
||||
title: 'Crop Image',
|
||||
),
|
||||
]);
|
||||
if (croppedImg != null) {
|
||||
// profilPic = croppedImg.path;
|
||||
profilePicPath.value = croppedImg.path;
|
||||
|
||||
// Get.back();
|
||||
// fileNameFromPath.value = extractFileName(croppedImg.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,4 +44,8 @@ class RouteName {
|
||||
//contact us
|
||||
static const String contactUsMain = '/contactUsMain';
|
||||
static const String contactUsMainDetails = '/contactUsMainDetails';
|
||||
|
||||
//my Profile
|
||||
|
||||
static const String myProfileScreen = '/myProfileScreen';
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'package:traderscircuit/view/Sidemenu/FaqScreen.dart';
|
||||
import 'package:traderscircuit/view/Sidemenu/PrivacyPolicy.dart';
|
||||
import 'package:traderscircuit/view/Sidemenu/TermsAndCondition.dart';
|
||||
import 'package:traderscircuit/view/Sidemenu/contactUs/contact_us_main.dart';
|
||||
import 'package:traderscircuit/view/Sidemenu/myProfile/my_profile_screen.dart';
|
||||
|
||||
import 'package:traderscircuit/view/login/AddDetails.dart';
|
||||
import 'package:traderscircuit/view/login/Kyc.dart';
|
||||
@@ -156,6 +157,11 @@ class AppRoutes {
|
||||
GetPage(
|
||||
name: RouteName.contactUsMainDetails,
|
||||
page: () => const ContactUsDetailsScreen(),
|
||||
),
|
||||
//my profile
|
||||
GetPage(
|
||||
name: RouteName.myProfileScreen,
|
||||
page: () => const MyProfileScreen(),
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ class _SideMenuState extends State<SideMenu> {
|
||||
InkWell(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
// Get.toNamed(RouteName.investorprofile);
|
||||
Get.toNamed(RouteName.myProfileScreen);
|
||||
});
|
||||
},
|
||||
child: Padding(
|
||||
|
||||
321
lib/view/Sidemenu/myProfile/my_profile_screen.dart
Normal file
321
lib/view/Sidemenu/myProfile/my_profile_screen.dart
Normal file
@@ -0,0 +1,321 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../../Utils/Common/CommonAppbar.dart';
|
||||
import '../../../Utils/Common/CustomTextFormField.dart';
|
||||
import '../../../Utils/Common/ImageUpload.dart';
|
||||
import '../../../Utils/Common/commonBotton.dart';
|
||||
import '../../../Utils/text.dart';
|
||||
import '../../../controller/profile_image_controller.dart';
|
||||
import '../../onBoarding/splashScreen1.dart';
|
||||
|
||||
class MyProfileScreen extends StatefulWidget {
|
||||
const MyProfileScreen({super.key});
|
||||
|
||||
@override
|
||||
State<MyProfileScreen> createState() => _MyProfileScreenState();
|
||||
}
|
||||
|
||||
class _MyProfileScreenState extends State<MyProfileScreen> {
|
||||
final ProfileImageController editProfileImage =
|
||||
Get.put(ProfileImageController());
|
||||
RxBool isEdit = false.obs;
|
||||
final GlobalKey<FormState> formK = GlobalKey<FormState>();
|
||||
TextEditingController fullNameController = TextEditingController();
|
||||
TextEditingController emailController = TextEditingController();
|
||||
TextEditingController phoneNoController = TextEditingController();
|
||||
TextEditingController dobController = TextEditingController();
|
||||
TextEditingController cityController = TextEditingController();
|
||||
|
||||
DateTime timebackPressed = DateTime.now();
|
||||
|
||||
Future<void> _selectDate(BuildContext context) async {
|
||||
final DateTime? picked = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: DateTime.now(),
|
||||
firstDate: DateTime(1900),
|
||||
lastDate: DateTime.now(),
|
||||
builder: (context, child) {
|
||||
return Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
colorScheme: const ColorScheme.light(
|
||||
surface: Colors.black,
|
||||
onSurface: Colors.white,
|
||||
primary: Color(0xff9A0000),
|
||||
onPrimary: Colors.white,
|
||||
),
|
||||
textButtonTheme: TextButtonThemeData(
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: child!);
|
||||
});
|
||||
|
||||
if (picked != null && picked != DateTime.now()) {
|
||||
setState(() {
|
||||
dobController.text = "${picked.toLocal()}".split(' ')[0];
|
||||
final birthDate = DateTime(
|
||||
picked.year,
|
||||
picked.month,
|
||||
picked.day,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Obx(
|
||||
() => Form(
|
||||
key: formK,
|
||||
child: Scaffold(
|
||||
appBar: CommonAppbar(
|
||||
height: 75,
|
||||
titleTxt: "",
|
||||
customActionWidget: text16W400(""),
|
||||
),
|
||||
backgroundColor: Colors.black,
|
||||
extendBody: true,
|
||||
body: Stack(
|
||||
children: [
|
||||
const CommonBlurLeft(),
|
||||
const CommonBlurRight(),
|
||||
Stack(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16, vertical: 16),
|
||||
child: ListView(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
text25W600("My Profile"),
|
||||
isEdit.value
|
||||
? const SizedBox()
|
||||
: InkWell(
|
||||
onTap: () {
|
||||
isEdit.value = true;
|
||||
},
|
||||
child: CircleAvatar(
|
||||
radius: 20.r,
|
||||
backgroundColor: const Color(0xFF5A5A5A),
|
||||
child: Icon(
|
||||
Icons.edit,
|
||||
size: 20.sp,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Gap(20),
|
||||
Center(
|
||||
child: Stack(
|
||||
children: [
|
||||
Obx(
|
||||
() =>
|
||||
editProfileImage.profilePicPath.value != ''
|
||||
? ClipOval(
|
||||
child: SizedBox.fromSize(
|
||||
size: Size.fromRadius(60.r),
|
||||
child: editProfileImage
|
||||
.profilePicPath
|
||||
.value !=
|
||||
''
|
||||
? Image(
|
||||
image: FileImage(
|
||||
File(
|
||||
editProfileImage
|
||||
.profilePicPath
|
||||
.value,
|
||||
),
|
||||
),
|
||||
fit: BoxFit.cover,
|
||||
width: 200.w,
|
||||
height: 200.h,
|
||||
)
|
||||
: Image.asset(
|
||||
"assets/images/blank-profile-picture-973460_1280.png"),
|
||||
),
|
||||
)
|
||||
: ClipOval(
|
||||
child: SizedBox.fromSize(
|
||||
size: Size.fromRadius(60.r),
|
||||
child:
|
||||
// ProfileObj?.user?.profileImage !=
|
||||
// null
|
||||
// ? ClipOval(
|
||||
// child: SizedBox.fromSize(
|
||||
// size: Size.fromRadius(25.r),
|
||||
// child: CircleAvatar(
|
||||
// backgroundImage:
|
||||
// NetworkImage(ProfileObj!
|
||||
// .user!
|
||||
// .profileImage!),
|
||||
// radius: 25.r,
|
||||
// ),
|
||||
// ),
|
||||
// )
|
||||
// :
|
||||
Image.asset(
|
||||
"assets/images/png/Ellipse 560 (1).png",
|
||||
width: 130,
|
||||
height: 130,
|
||||
)),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
ImageUploadBottomSheet().showModal(
|
||||
context,
|
||||
false,
|
||||
(result) {
|
||||
print("File path is $result");
|
||||
editProfileImage.profilePicPath.value =
|
||||
result;
|
||||
},
|
||||
);
|
||||
},
|
||||
child: CircleAvatar(
|
||||
radius: 20.r,
|
||||
backgroundColor: const Color(0xFF5A5A5A),
|
||||
child: Icon(
|
||||
Icons.camera_alt_outlined,
|
||||
size: 20.sp,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
text18W400("Full Name"),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 15.h,
|
||||
),
|
||||
CustomTextFormField(
|
||||
textEditingController: fullNameController,
|
||||
enabled: isEdit.value,
|
||||
validator: (value) {
|
||||
if (value == "") {
|
||||
return "Name is Required";
|
||||
}
|
||||
},
|
||||
),
|
||||
SizedBox(
|
||||
height: 30.h,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
text18W400("Email Address"),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 15.h,
|
||||
),
|
||||
CustomTextFormField(
|
||||
textEditingController: emailController,
|
||||
enabled: isEdit.value,
|
||||
texttype: TextInputType.emailAddress,
|
||||
),
|
||||
SizedBox(
|
||||
height: 30.h,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
text18W400("Phone Number"),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 15.h,
|
||||
),
|
||||
CustomTextFormField(
|
||||
textEditingController: phoneNoController,
|
||||
enabled: isEdit.value,
|
||||
texttype: TextInputType.phone,
|
||||
),
|
||||
SizedBox(
|
||||
height: 30.h,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
text18W400("Date Of Birth"),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 15.h,
|
||||
),
|
||||
CustomTextFormField(
|
||||
textEditingController: dobController,
|
||||
enabled: isEdit.value,
|
||||
suffixIcon: const Icon(
|
||||
Icons.calendar_month_outlined,
|
||||
color: Colors.white,
|
||||
),
|
||||
readonly: true,
|
||||
onTap: () {
|
||||
_selectDate(context);
|
||||
},
|
||||
),
|
||||
SizedBox(
|
||||
height: 30.h,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
text18W400("City"),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 15.h,
|
||||
),
|
||||
CustomTextFormField(
|
||||
textEditingController: cityController,
|
||||
enabled: isEdit.value,
|
||||
),
|
||||
SizedBox(
|
||||
height: 40.h,
|
||||
),
|
||||
!isEdit.value
|
||||
? const SizedBox()
|
||||
: SizedBox(
|
||||
width: Get.width,
|
||||
child: kycBtn(
|
||||
text: "Save",
|
||||
onTap: () {
|
||||
final isValid =
|
||||
formK.currentState?.validate();
|
||||
|
||||
if (isValid!) {}
|
||||
},
|
||||
bgClr: const Color(0xFF6C0000),
|
||||
borderClr: const Color(0xFF990000),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user