Files
Xpress-rider/lib/views/Dashboard/profile/Profilepage.dart

465 lines
17 KiB
Dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; // ⭐ REQUIRED
import 'package:nearle/views/Dashboard/profile/informations/help_center.dart';
import 'package:nearle/views/Dashboard/profile/informations/profile.dart';
import 'package:nearle/views/Dashboard/profile/informations/saved_address.dart';
import 'package:nearle/views/Dashboard/profile/informations/faq.dart';
import 'package:nearle/views/Dashboard/profile/informations/notifications_page.dart';
import 'package:nearle/views/Dashboard/profile/informations/support_ticket.dart';
import 'package:nearle/views/helpers/constants/Colorconstants.dart';
import 'package:nearle/views/helpers/constants/Font_constant.dart';
import 'package:nearle/views/onboardscreens/Sign_in.dart';
import 'package:nearle/controllers/profile_controller.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:nearle/views/Dashboard/profile/informations/order_alert_sound.dart';
import 'package:nearle/controllers/rewards_controller.dart';
import 'package:nearle/views/Dashboard/profile/rewards_card.dart';
import 'package:nearle/views/Dashboard/profile/informations/rider_rewards_page.dart';
import 'package:nearle/utils/mqtt_service.dart';
class ProfilePage extends StatefulWidget {
const ProfilePage({super.key});
@override
State<ProfilePage> createState() => _ProfilePageState();
}
class _ProfilePageState extends State<ProfilePage> {
late final ProfileController _profileController =
Get.isRegistered<ProfileController>()
? Get.find<ProfileController>()
: Get.put(ProfileController(), permanent: true);
final RewardsController _rewardsController = Get.put(RewardsController());
String _name = '';
String _email = '';
String _contact = '';
@override
void initState() {
super.initState();
_loadProfilePrefs();
ever(_profileController.userName, (_) => _assignFromController());
ever(_profileController.userEmail, (_) => _assignFromController());
ever(_profileController.userContact, (_) => _assignFromController());
ever(_profileController.userAddress, (_) => _assignFromController());
_profileController.loadFromPrefs();
}
Future<void> _loadProfilePrefs() async {
final prefs = await SharedPreferences.getInstance();
setState(() {
_name = prefs.getString('user_name') ?? '';
_email = prefs.getString('user_email') ?? '';
_contact = prefs.getString('contactno') ?? '';
_contact = prefs.getString('contactno') ?? '';
});
final userId = prefs.getInt('userid') ?? 0;
if (userId > 0) {
_rewardsController.fetchBonusSummary(userId);
}
}
void _assignFromController() {
setState(() {
if (_profileController.userName.value.trim().isNotEmpty) {
_name = _profileController.userName.value.trim();
}
if (_profileController.userEmail.value.trim().isNotEmpty) {
_email = _profileController.userEmail.value.trim();
}
if (_profileController.userContact.value.trim().isNotEmpty) {
_contact = _profileController.userContact.value.trim();
}
});
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: Colors.grey.shade200,
appBar: AppBar(
backgroundColor: Colors.grey.shade200,
elevation: 0,
toolbarHeight: 70.h, // ⭐ responsive
title: Padding(
padding: EdgeInsets.only(top: 12.h),
child: Text(
"PROFILE",
style: TextStyle(
fontSize: FontConstants.xxxLarge(context).sp,
fontWeight: FontWeight.bold,
fontFamily: FontConstants.fontFamily,
color: Colors.black,
),
),
),
bottom: PreferredSize(
preferredSize: Size.fromHeight(1.h),
child: Divider(height: 1.h, color: Colors.grey),
),
),
body: SingleChildScrollView(
physics: const ClampingScrollPhysics(),
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 16.w),
child: Padding(
padding: EdgeInsets.only(bottom: 40.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 20.h),
/// ⭐ PROFILE CARD RESPONSIVE
Container(
padding: EdgeInsets.all(16.r),
decoration: BoxDecoration(
color: ColorConstants.primaryColor,
borderRadius: BorderRadius.circular(20.r),
),
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
Icons.person,
color: Colors.white,
size: 22.sp,
),
SizedBox(width: 6.w),
Flexible(
child: Text(
_name.isNotEmpty ? _name : "",
style: TextStyle(
color: Colors.white,
fontSize: 18.sp,
fontWeight: FontWeight.bold,
),
overflow: TextOverflow.ellipsis,
),
),
],
),
SizedBox(height: 12.h),
Row(
children: [
Icon(
Icons.phone,
color: Colors.white,
size: 20.sp,
),
SizedBox(width: 6.w),
Flexible(
child: Text(
_contact.isNotEmpty ? _contact : "",
style: TextStyle(
color: Colors.white,
fontSize: 16.sp,
),
),
),
],
),
SizedBox(height: 12.h),
Row(
children: [
Icon(
Icons.email,
color: Colors.white,
size: 20.sp,
),
SizedBox(width: 6.w),
Flexible(
child: Text(
_email.isNotEmpty ? _email : "",
style: TextStyle(
color: Colors.white,
fontSize: 16.sp,
),
overflow: TextOverflow.ellipsis,
),
),
],
),
],
),
),
/// ⭐ Circle Avatar Responsive
Obx(() {
final path = _profileController.imagePath.value;
final hasImage =
path.isNotEmpty && File(path).existsSync();
return CircleAvatar(
radius: 40.r,
backgroundColor: Colors.grey.shade300,
backgroundImage: hasImage
? FileImage(File(path))
: null,
child: !hasImage
? Icon(
Icons.person,
color: Colors.white,
size: 40.sp,
)
: null,
);
}),
],
),
),
SizedBox(height: 20.h),
// ⭐ REWARDS SECTION
RewardsCard(controller: _rewardsController),
SizedBox(height: 20.h),
_buildHeader("Your Information"),
_buildBox([
_buildInfoTile(Icons.person, "Profile"),
Divider(),
_buildInfoTile(Icons.location_on, "Saved Address"),
Divider(),
_buildInfoTile(Icons.card_giftcard, "Rewards"),
Divider(),
_buildInfoTile(Icons.notifications, "Notification"),
]),
SizedBox(height: 20.h),
_buildHeader("Support"),
_buildBox([
_buildInfoTile(Icons.support_agent, "Help Centre"),
Divider(),
_buildInfoTile(Icons.local_activity, "Support tickets"),
]),
SizedBox(height: 20.h),
_buildHeader("Other Information"),
_buildBox([
_buildInfoTile(Icons.translate, "Faq"),
Divider(),
// _buildInfoTile(Icons.sticky_note_2, "Terms & Conditions"),
// Divider(),
_buildInfoTile(
Icons.notifications_active,
"Order alert sound",
),
]),
SizedBox(height: 55.h),
/// ⭐ Logout Button Responsive
SizedBox(
height: 55.h,
width: double.infinity,
child: OutlinedButton(
onPressed: () => _showLogoutDialog(context),
style: OutlinedButton.styleFrom(
backgroundColor: ColorConstants.secondaryColor,
side: BorderSide(color: Colors.black, width: 0.2.w),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.r),
),
),
child: Text(
"Logout",
style: TextStyle(
fontSize: 20.sp,
fontWeight: FontWeight.bold,
color: Colors.black,
fontFamily: FontConstants.fontFamily,
),
),
),
),
SizedBox(height: 15.h),
Center(
child: Text(
"App Version 1.2.19",
style: TextStyle(
fontSize: 16.sp,
color: Colors.grey.shade600,
fontFamily: FontConstants.fontFamily,
),
),
),
],
),
),
),
),
),
);
}
Widget _buildHeader(String title) {
return Padding(
padding: EdgeInsets.all(8.r),
child: Text(
title,
style: TextStyle(
fontSize: 22.sp,
fontWeight: FontWeight.bold,
fontFamily: FontConstants.fontFamily,
color: Colors.black,
),
),
);
}
Widget _buildBox(List<Widget> children) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12.r),
),
child: Column(children: children),
);
}
Widget _buildInfoTile(IconData icon, String title) {
return ListTile(
leading: Icon(icon, size: 26.sp),
title: Text(
title,
style: TextStyle(
fontSize: 19.sp,
fontWeight: FontWeight.w500,
fontFamily: FontConstants.fontFamily,
),
),
trailing: Icon(Icons.arrow_forward_ios, size: 22.sp),
onTap: () => _handleNavigation(title),
);
}
void _handleNavigation(String title) {
switch (title) {
case "Profile":
Get.to(() => Profile());
break;
case "Saved Address":
Get.to(() => const SavedAddressPage());
break;
case "Notification":
Get.to(() => const NotificationsPage());
break;
case "Help Centre":
Get.to(() => HelpCenter());
break;
case "Support tickets":
Get.to(() => SupportTicket());
break;
case "Rewards":
Get.to(() => const RiderRewardsPage());
break;
case "Faq":
Get.to(() => const FaqPage());
break;
// case "Terms & Conditions":
// Get.to(() => const TermsCondition());
// break;
case "Order alert sound":
Get.to(() => const OrderAlertSoundPage());
break;
default:
debugPrint("Tapped on $title — no page linked yet.");
}
}
}
void _showLogoutDialog(BuildContext context) {
showDialog(
context: context,
barrierDismissible: true,
builder: (BuildContext context) {
return Center(
child: FittedBox(
child: AlertDialog(
backgroundColor: ColorConstants.secondaryColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.r),
),
title: Text(
"Logout",
style: TextStyle(
fontSize: 22.sp,
fontWeight: FontWeight.bold,
fontFamily: FontConstants.fontFamily,
),
),
content: Text(
"Are you sure you want to logout?",
style: TextStyle(
fontSize: 19.sp,
fontFamily: FontConstants.fontFamily,
),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text(
"No",
style: TextStyle(
fontSize: 19.sp,
color: Colors.grey,
fontFamily: FontConstants.fontFamily,
),
),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: const Color.fromARGB(255, 153, 121, 167),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.r),
),
),
onPressed: () async {
final prefs = await SharedPreferences.getInstance();
final userId =
prefs.getInt('userid') ?? prefs.getInt('userId') ?? 0;
if (userId != 0) {
await prefs.remove('skipped_orders_cache_$userId');
}
NearleMqttService().disconnect();
prefs.setBool('logged_out', true);
Get.offAll(() => const SignIn());
},
child: Text(
"Yes",
style: TextStyle(
fontSize: 19.sp,
color: Colors.black,
fontFamily: FontConstants.fontFamily,
),
),
),
],
),
),
);
},
);
}