This commit is contained in:
Hamza-Ayed
2025-09-01 18:29:05 +03:00
parent d71686d9f1
commit 6c87f7291d
33 changed files with 3118 additions and 7333 deletions

View File

@@ -1,5 +1,3 @@
import 'package:Intaleq/controller/functions/encrypt_decrypt.dart';
import 'package:Intaleq/views/auth/login_page.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
@@ -8,8 +6,8 @@ import 'package:Intaleq/constant/colors.dart';
import 'package:Intaleq/constant/style.dart';
import 'package:Intaleq/controller/profile/profile_controller.dart';
import 'package:Intaleq/main.dart';
import 'package:Intaleq/views/auth/login_page.dart';
import 'package:Intaleq/views/widgets/elevated_btn.dart';
import 'package:Intaleq/views/widgets/my_scafold.dart';
import 'package:Intaleq/views/widgets/my_textField.dart';
import 'package:Intaleq/views/widgets/mycircular.dart';
@@ -18,239 +16,319 @@ import '../../../controller/functions/log_out.dart';
class PassengerProfilePage extends StatelessWidget {
PassengerProfilePage({super.key});
LogOutController logOutController = Get.put(LogOutController());
final LogOutController logOutController = Get.put(LogOutController());
@override
Widget build(BuildContext context) {
Get.put(ProfileController());
return MyScafolld(
isleading: true,
title: 'My Profile'.tr,
body: [
GetBuilder<ProfileController>(
builder: (controller) => controller.isloading
? const MyCircularProgressIndicator()
: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: SizedBox(
height: Get.height,
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Edit Profile'.tr,
style: AppStyle.headTitle2,
),
ListTile(
title: Text(
'Name'.tr,
style: AppStyle.title,
),
leading: const Icon(
Icons.person_pin_rounded,
size: 35,
),
trailing: const Icon(Icons.arrow_forward_ios),
subtitle: Text(
'${(controller.prfoileData['first_name'])} ${(controller.prfoileData['last_name'])}'),
onTap: () {
controller.updatField(
'first_name', TextInputType.name);
},
),
ListTile(
title: Text(
'Gender'.tr,
style: AppStyle.title,
),
leading: Image.asset(
'assets/images/gender.png',
width: 35,
),
trailing: const Icon(Icons.arrow_forward_ios),
subtitle: Text((controller.prfoileData['gender']
.toString())),
onTap: () {
Get.defaultDialog(
title: 'Update Gender'.tr,
content: Column(
children: [
GenderPicker(),
MyElevatedButton(
title: 'Update'.tr,
onPressed: () {
controller.updateColumn({
'id': controller.prfoileData['id']
.toString(),
'gender': (controller.gender),
});
Get.back();
},
)
],
));
// controller.updatField('gender');
},
),
ListTile(
title: Text(
'Education'.tr,
style: AppStyle.title,
),
leading: Image.asset(
'assets/images/education.png',
width: 35,
),
trailing: const Icon(Icons.arrow_forward_ios),
subtitle: Text(controller.prfoileData['education']
.toString()),
onTap: () {
Get.defaultDialog(
barrierDismissible: true,
title: 'Update Education'.tr,
content: SizedBox(
height: 200,
child: Column(
children: [
EducationDegreePicker(),
],
),
),
confirm: MyElevatedButton(
title: 'Update Education'.tr,
onPressed: () {
controller.updateColumn({
'id': controller.prfoileData['id']
.toString(),
'education':
controller.selectedDegree,
});
Get.back();
},
));
},
),
ListTile(
title: Text(
'Employment Type'.tr,
style: AppStyle.title,
),
leading: Image.asset(
'assets/images/employmentType.png',
width: 35,
),
trailing: const Icon(Icons.arrow_forward_ios),
subtitle: Text(controller
.prfoileData['employmentType']
.toString()),
onTap: () {
controller.updatField(
'employmentType', TextInputType.name);
},
),
ListTile(
title: Text(
'Marital Status'.tr,
style: AppStyle.title,
),
leading: Image.asset(
'assets/images/maritalStatus.png',
width: 35,
),
trailing: const Icon(Icons.arrow_forward_ios),
subtitle: Text(controller
.prfoileData['maritalStatus']
.toString()),
onTap: () {
controller.updatField(
'maritalStatus', TextInputType.name);
},
),
ListTile(
title: Text(
'SOS Phone'.tr,
style: AppStyle.title,
),
leading: const Icon(
Icons.sos,
color: AppColor.redColor,
size: 35,
),
trailing: const Icon(Icons.arrow_forward_ios),
subtitle: Text(
(controller.prfoileData['sosPhone'])
.toString()),
onTap: () async {
await controller.updatField(
'sosPhone', TextInputType.phone);
box.write(BoxName.sosPhonePassenger,
controller.prfoileData['sosPhone']);
},
),
// const Spacer(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
MyElevatedButton(
title: 'Sign Out'.tr,
onPressed: () {
LogOutController().logOutPassenger();
}),
GetBuilder<LogOutController>(
builder: (logOutController) {
return MyElevatedButton(
title: 'Delete My Account'.tr,
onPressed: () {
Get.defaultDialog(
title:
'Are you sure to delete your account?'
.tr,
content: Form(
key: logOutController.formKey1,
child: MyTextForm(
controller: logOutController
.emailTextController,
label: 'Type your Email'.tr,
hint: 'Type your Email'.tr,
type:
TextInputType.emailAddress,
),
),
confirm: MyElevatedButton(
title: 'Delete My Account'.tr,
kolor: AppColor.redColor,
onPressed: () async {
await logOutController
.deletePassengerAccount();
}),
cancel: MyElevatedButton(
title: 'No I want'.tr,
onPressed: () {
logOutController
.emailTextController
.clear();
logOutController.update();
Get.back();
}));
});
}),
],
),
],
),
),
),
)),
return Scaffold(
backgroundColor: Colors.grey[100],
appBar: AppBar(
title: Text('My Profile'.tr,
style: const TextStyle(fontWeight: FontWeight.bold)),
backgroundColor: Colors.grey[100],
elevation: 0,
centerTitle: true,
),
body: GetBuilder<ProfileController>(
builder: (controller) {
if (controller.isloading) {
return const MyCircularProgressIndicator();
}
return ListView(
padding:
const EdgeInsets.symmetric(horizontal: 16.0, vertical: 10.0),
children: [
_buildProfileHeader(controller),
const SizedBox(height: 24),
_buildSectionCard(
'Personal Information'.tr,
[
_buildProfileTile(
icon: Icons.person_outline,
color: Colors.blue,
title: 'Name'.tr,
subtitle:
'${controller.prfoileData['first_name'] ?? ''} ${controller.prfoileData['last_name'] ?? ''}',
onTap: () =>
controller.updatField('first_name', TextInputType.name),
),
_buildProfileTile(
icon: Icons.wc_outlined,
color: Colors.pink,
title: 'Gender'.tr,
subtitle: controller.prfoileData['gender']?.toString() ??
'Not set'.tr,
onTap: () => _showGenderDialog(controller),
),
_buildProfileTile(
icon: Icons.school_outlined,
color: Colors.orange,
title: 'Education'.tr,
subtitle: controller.prfoileData['education']?.toString() ??
'Not set'.tr,
onTap: () => _showEducationDialog(controller),
),
],
),
const SizedBox(height: 24),
_buildSectionCard(
'Work & Contact'.tr,
[
_buildProfileTile(
icon: Icons.work_outline,
color: Colors.green,
title: 'Employment Type'.tr,
subtitle:
controller.prfoileData['employmentType']?.toString() ??
'Not set'.tr,
onTap: () => controller.updatField(
'employmentType', TextInputType.name),
),
_buildProfileTile(
icon: Icons.favorite_border,
color: Colors.purple,
title: 'Marital Status'.tr,
subtitle:
controller.prfoileData['maritalStatus']?.toString() ??
'Not set'.tr,
onTap: () => controller.updatField(
'maritalStatus', TextInputType.name),
),
_buildProfileTile(
icon: Icons.sos_outlined,
color: Colors.red,
title: 'SOS Phone'.tr,
subtitle: controller.prfoileData['sosPhone']?.toString() ??
'Not set'.tr,
onTap: () async {
await controller.updatField(
'sosPhone', TextInputType.phone);
box.write(BoxName.sosPhonePassenger,
controller.prfoileData['sosPhone']);
},
),
],
),
const SizedBox(height: 32),
_buildAccountActions(context, logOutController),
],
);
},
),
);
}
Widget _buildProfileHeader(ProfileController controller) {
String fullName =
'${controller.prfoileData['first_name'] ?? ''} ${controller.prfoileData['last_name'] ?? ''}';
String initials = (fullName.isNotEmpty && fullName.contains(" "))
? fullName.split(" ").map((e) => e.isNotEmpty ? e[0] : "").join()
: (fullName.isNotEmpty ? fullName[0] : "");
// Logic to hide email if it contains 'intaleqapp.com'
String email = box.read(BoxName.email) ?? '';
if (email.contains('intaleqapp.com')) {
email = ''; // Clear the email if it contains the domain
}
return Center(
child: Column(
children: [
CircleAvatar(
radius: 50,
backgroundColor: AppColor.primaryColor.withOpacity(0.2),
child: Text(
initials,
style:
const TextStyle(fontSize: 40, color: AppColor.primaryColor),
),
),
const SizedBox(height: 12),
Text(
fullName,
style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
),
if (email
.isNotEmpty) // Only show the Text widget if the email is not empty
Text(
email,
style: TextStyle(fontSize: 16, color: Colors.grey[600]),
),
],
),
);
}
Widget _buildSectionCard(String title, List<Widget> children) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(left: 8.0, bottom: 8.0),
child: Text(
title,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.grey[700]),
),
),
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
),
child: Column(
children: children,
),
),
],
);
}
Widget _buildProfileTile({
required IconData icon,
required Color color,
required String title,
required String subtitle,
required VoidCallback onTap,
}) {
return ListTile(
onTap: onTap,
leading: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: color.withOpacity(0.1),
borderRadius: BorderRadius.circular(10),
),
child: Icon(icon, color: color, size: 24),
),
title: Text(title, style: const TextStyle(fontWeight: FontWeight.w500)),
subtitle: Text(subtitle, style: TextStyle(color: Colors.grey[600])),
trailing:
Icon(Icons.arrow_forward_ios, size: 16, color: Colors.grey[400]),
);
}
Widget _buildAccountActions(
BuildContext context, LogOutController logOutController) {
return Column(
children: [
SizedBox(
width: double.infinity,
child: TextButton.icon(
icon: const Icon(Icons.logout),
label: Text('Sign Out'.tr),
style: TextButton.styleFrom(
foregroundColor: Colors.blueGrey,
padding: const EdgeInsets.symmetric(vertical: 12),
),
onPressed: () {
logOutController.logOutPassenger();
},
),
),
const SizedBox(height: 8),
SizedBox(
width: double.infinity,
child: TextButton.icon(
icon: const Icon(Icons.delete_forever_outlined),
label: Text('Delete My Account'.tr),
style: TextButton.styleFrom(
foregroundColor: Colors.red,
padding: const EdgeInsets.symmetric(vertical: 12),
),
onPressed: () =>
_showDeleteAccountDialog(context, logOutController),
),
),
],
);
}
void _showGenderDialog(ProfileController controller) {
Get.defaultDialog(
title: 'Update Gender'.tr,
content: Column(
children: [
GenderPicker(),
const SizedBox(height: 16),
MyElevatedButton(
title: 'Update'.tr,
onPressed: () {
controller.updateColumn({
'id': controller.prfoileData['id'].toString(),
'gender': controller.gender,
});
Get.back();
},
)
],
),
);
}
void _showEducationDialog(ProfileController controller) {
Get.defaultDialog(
title: 'Update Education'.tr,
content: Column(
children: [
EducationDegreePicker(),
const SizedBox(height: 16),
MyElevatedButton(
title: 'Update'.tr,
onPressed: () {
controller.updateColumn({
'id': controller.prfoileData['id'].toString(),
'education': controller.selectedDegree,
});
Get.back();
},
),
],
),
);
}
void _showDeleteAccountDialog(
BuildContext context, LogOutController logOutController) {
Get.defaultDialog(
title: 'Delete My Account'.tr,
middleText: 'Are you sure? This action cannot be undone.'.tr,
content: Form(
key: logOutController.formKey1,
child: MyTextForm(
controller: logOutController.emailTextController,
label: 'Confirm your Email'.tr,
hint: 'Type your Email'.tr,
type: TextInputType.emailAddress,
),
),
confirm: MyElevatedButton(
title: 'Delete Permanently'.tr,
kolor: AppColor.redColor,
onPressed: () async {
await logOutController.deletePassengerAccount();
},
),
cancel: TextButton(
child: Text('Cancel'.tr),
onPressed: () {
logOutController.emailTextController.clear();
Get.back();
},
),
);
}
}
class GenderPicker extends StatelessWidget {
final ProfileController controller = Get.put(ProfileController());
// --- Helper Widgets for Pickers ---
class GenderPicker extends StatelessWidget {
final ProfileController controller = Get.find<ProfileController>();
final List<String> genderOptions = ['Male'.tr, 'Female'.tr, 'Other'.tr];
GenderPicker({super.key});
@@ -258,14 +336,14 @@ class GenderPicker extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SizedBox(
height: 100,
height: 150,
child: CupertinoPicker(
itemExtent: 32.0,
itemExtent: 40.0,
onSelectedItemChanged: (int index) {
controller.setGender(genderOptions[index]);
},
children: genderOptions.map((String value) {
return Text(value);
return Center(child: Text(value));
}).toList(),
),
);
@@ -273,216 +351,34 @@ class GenderPicker extends StatelessWidget {
}
class EducationDegreePicker extends StatelessWidget {
final ProfileController controller = Get.put(ProfileController());
final ProfileController controller = Get.find<ProfileController>();
final List<String> degreeOptions = [
'High School Diploma'.tr,
'Associate Degree'.tr,
'Bachelor\'s Degree'.tr,
'Master\'s Degree'.tr,
"Bachelor's Degree".tr,
"Master's Degree".tr,
'Doctoral Degree'.tr,
];
EducationDegreePicker({Key? key}) : super(key: key);
EducationDegreePicker({super.key});
@override
Widget build(BuildContext context) {
return SizedBox(
height: 200,
height: 180,
child: CupertinoPicker(
// backgroundColor: AppColor.accentColor,
// looping: true,
squeeze: 2,
// diameterRatio: 5,
itemExtent: 32,
itemExtent: 40.0,
onSelectedItemChanged: (int index) {
controller.setDegree(degreeOptions[index]);
},
children: degreeOptions.map((String value) {
return Text(value);
return Center(child: Text(value));
}).toList(),
),
);
}
}
class CountryPicker extends StatelessWidget {
final ProfileController controller = Get.put(ProfileController());
final List<String> countryOptions = [
'Jordan',
'Syria',
'Egypt',
'Turkey',
'Saudi Arabia',
'Qatar',
'Bahrain',
'Kuwait',
'USA'
];
CountryPicker({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return GetBuilder<ProfileController>(builder: (controller) {
return Padding(
padding: const EdgeInsets.all(20),
child: ListView(
children: [
const SizedBox(
height: 20,
),
Text(
"Select Your Country".tr,
style: AppStyle.headTitle2,
textAlign: TextAlign.center,
),
// const SizedBox(
// height: 20,
// ),
Padding(
padding: const EdgeInsets.all(10),
child: Text(
"To ensure you receive the most accurate information for your location, please select your country below. This will help tailor the app experience and content to your country."
.tr,
style: AppStyle.title,
textAlign: TextAlign.center,
),
),
SizedBox(
height: 200,
child: CupertinoPicker(
itemExtent: 32,
onSelectedItemChanged: (int index) {
controller.setCountry(countryOptions[index]);
box.write(BoxName.countryCode,
countryOptions[index]); // Save in English
},
children: List.generate(
countryOptions.length,
(index) => Center(
child: Text(
countryOptions[index]
.tr, // Display translated if not English
style: AppStyle.title,
),
),
),
),
),
MyElevatedButton(
title: 'Select Country'.tr, // Use translated text for button
onPressed: () {
Get.find<LoginController>().saveCountryCode(controller
.selectedCountry
.toString()); // No conversion needed
box.write(
BoxName.countryCode, //
controller.selectedCountry); // Already saved in English
if (controller.selectedCountry == null) {
Get.snackbar("You should select your country".tr, '');
} else {
Get.snackbar(controller.selectedCountry.toString().tr, '');
Get.off(LoginPage());
}
},
)
],
),
);
});
}
}
class CountryPickerFromSetting extends StatelessWidget {
final ProfileController controller = Get.put(ProfileController());
final LoginController loginController = Get.put(LoginController());
final List<String> countryOptions = [
'Jordan',
'USA',
'Egypt',
'Turkey',
'Saudi Arabia',
'Qatar',
'Bahrain',
'Kuwait',
];
CountryPickerFromSetting({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return GetBuilder<ProfileController>(builder: (controller) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('Select Your Country'.tr),
),
child: Padding(
padding: const EdgeInsets.all(20.0),
child: ListView(
children: [
const SizedBox(
height: 20,
),
// Text(
// "Select Your Country".tr,
// style: AppStyle.headTitle2,
// textAlign: TextAlign.center,
// ),
// const SizedBox(
// height: 20,
// ),
Padding(
padding: const EdgeInsets.all(10),
child: Text(
"To ensure you receive the most accurate information for your location, please select your country below. This will help tailor the app experience and content to your country."
.tr,
style: AppStyle.headTitle2,
textAlign: TextAlign.center,
),
),
SizedBox(
height: 200,
child: CupertinoPicker(
itemExtent: 32,
onSelectedItemChanged: (int index) {
controller.setCountry(countryOptions[index]);
box.write(BoxName.countryCode,
countryOptions[index]); // Save in English
},
children: List.generate(
countryOptions.length,
(index) => Center(
child: Text(
countryOptions[index]
.tr, // Display translated if not English
style: AppStyle.title,
),
),
),
),
),
MyElevatedButton(
title: 'Select Country'.tr, // Use translated text for button
onPressed: () async {
loginController.saveCountryCode(controller.selectedCountry
.toString()); // No conversion needed
box.write(
BoxName.countryCode, //
controller.selectedCountry); // Already saved in English
Get.snackbar(controller.selectedCountry.toString().tr, '',
backgroundColor: AppColor.greenColor);
// Get.back();//
// Get.back();
},
)
],
)),
);
});
}
}
// NOTE: The CountryPicker and CountryPickerFromSetting widgets were not part of the main
// profile page UI, so they are excluded here to keep the file focused.
// If they are needed elsewhere, they should be moved to their own files.