import 'dart:io'; import 'package:bookmywages/consts_widgets/app_assets.dart'; import 'package:bookmywages/consts_widgets/app_colors.dart'; import 'package:bookmywages/consts_widgets/comman_button.dart'; import 'package:bookmywages/consts_widgets/comman_textformfiled.dart'; import 'package:bookmywages/viewmodel/api_controller.dart'; import 'package:bookmywages/viewmodel/consts_api.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:image_picker/image_picker.dart'; class EditProfile extends StatefulWidget { const EditProfile({super.key}); @override State createState() => _EditProfileState(); } class _EditProfileState extends State { File? _image; final ImagePicker _picker = ImagePicker(); final TextEditingController nameController = TextEditingController(); final TextEditingController numberController = TextEditingController(); final TextEditingController emailController = TextEditingController(); final TextEditingController addressController = TextEditingController(); bool _isProfileDataInitialized = false; Future _pickImage() async { final pickedFile = await _picker.pickImage(source: ImageSource.gallery); if (pickedFile != null) { setState(() { _image = File(pickedFile.path); }); } } // Helper method to validate and construct image URL String? _getValidImageUrl(String? imageUrl) { if (imageUrl == null || imageUrl.isEmpty) { return null; } // Check if URL is complete (has a filename) if (imageUrl.endsWith('/') || imageUrl.endsWith('/images/')) { return null; } // Ensure URL is properly formatted if (!imageUrl.startsWith('http')) { return null; } return imageUrl; } // Helper widget for safe network image loading Widget _buildNetworkImage(String? imageUrl, {BoxFit fit = BoxFit.cover}) { final validUrl = _getValidImageUrl(imageUrl); if (validUrl == null) { return Image.asset(AppAssets.profile, fit: fit); } return Image.network( validUrl, fit: fit, loadingBuilder: (context, child, loadingProgress) { if (loadingProgress == null) return child; return Center( child: CircularProgressIndicator( value: loadingProgress.expectedTotalBytes != null ? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes! : null, ), ); }, errorBuilder: (context, error, stackTrace) { print('Error loading image: $error'); return Image.asset(AppAssets.profile, fit: fit); }, ); } // Helper method for CircleAvatar image provider ImageProvider _getAvatarImageProvider(String? imageUrl) { if (_image != null) { return FileImage(_image!); } final validUrl = _getValidImageUrl(imageUrl); if (validUrl != null) { return NetworkImage(validUrl); } return const AssetImage(AppAssets.profile); } final TextStyle gilroyTextStyle = const TextStyle( fontFamily: 'Gilroy-Bold', fontWeight: FontWeight.w700, fontSize: 20, height: 1.45, letterSpacing: 0.01, ); @override void dispose() { nameController.dispose(); numberController.dispose(); emailController.dispose(); addressController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { double width = MediaQuery.of(context).size.width; double height = MediaQuery.of(context).size.height; return Scaffold( backgroundColor: AppColors.secondprimary, resizeToAvoidBottomInset: false, body: SafeArea( child: LayoutBuilder( builder: (context, constraints) { return SingleChildScrollView( padding: EdgeInsets.only( bottom: MediaQuery.of(context).viewInsets.bottom, ), child: ConstrainedBox( constraints: BoxConstraints(minHeight: constraints.maxHeight), child: IntrinsicHeight( child: Column( children: [ Stack( children: [ SizedBox( width: double.infinity, height: height * 0.4, child: Consumer( builder: (context, ref, _) { final profileData = ref.watch( profilegetuserProvider, ); return profileData.when( data: (profiles) { final profile = profiles.isNotEmpty ? profiles[0] : null; if (profile != null && !_isProfileDataInitialized) { WidgetsBinding.instance .addPostFrameCallback((_) { setState(() { nameController.text = profile.name ?? ''; numberController.text = profile.number ?? ''; emailController.text = profile.email ?? ''; addressController.text = profile.address ?? ''; _isProfileDataInitialized = true; }); }); } return _image == null ? _buildNetworkImage( profile?.profilePic1, ) : Image.file( _image!, fit: BoxFit.cover, ); }, loading: () => const Center( child: CircularProgressIndicator(), ), error: (error, _) => Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.error, size: 50), Text('Error loading profile: $error'), ], ), ), ); }, ), ), Positioned( bottom: 0, child: CustomPaint( size: Size(width, height * 0.4), painter: RightToLeftFullWidthTrianglePainter(), ), ), Positioned( bottom: height * 0.03, left: width / 2 - 170, child: Consumer( builder: (context, ref, _) { final profileData = ref.watch( profilegetuserProvider, ); return profileData.when( data: (profiles) { final profile = profiles.isNotEmpty ? profiles[0] : null; return CircleAvatar( radius: 68, backgroundColor: Colors.white, child: CircleAvatar( radius: 65, backgroundImage: _getAvatarImageProvider( profile?.profilePic1, ), onBackgroundImageError: (error, stackTrace) { print( 'Avatar image error: $error', ); }, ), ); }, loading: () => const CircleAvatar( radius: 68, backgroundColor: Colors.white, child: CircleAvatar( radius: 65, child: CircularProgressIndicator(), ), ), error: (error, _) => const CircleAvatar( radius: 68, backgroundColor: Colors.white, child: CircleAvatar( radius: 65, backgroundImage: AssetImage( AppAssets.menu, ), ), ), ); }, ), ), Positioned( bottom: height * 0.08, left: width / 2 - 20, child: Consumer( builder: (context, ref, _) { final profileData = ref.watch( profilegetuserProvider, ); return profileData.when( data: (profiles) { final profile = profiles.isNotEmpty ? profiles[0] : null; if (profile == null) { return Text( 'No Profile Data', style: gilroyTextStyle, ); } return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Text( profile.name ?? 'No Name', style: gilroyTextStyle, ), IconButton( onPressed: _pickImage, icon: const Icon(Icons.edit), ), ], ), Row( children: [ const Icon( Icons.location_city, size: 20, ), const SizedBox(width: 4), Text( profile.address ?? 'No address available', style: const TextStyle( fontSize: 12, ), ), ], ), ], ); }, loading: () => const CircularProgressIndicator(), error: (error, _) => Text( 'Error: $error', style: gilroyTextStyle, ), ); }, ), ), ], ), const SizedBox(height: 30), Padding( padding: EdgeInsets.symmetric(horizontal: width * 0.05), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("Name", style: gilroyTextStyle), const SizedBox(height: 15), CommonTextFormField( hintText: "Enter your name", controller: nameController, ), const SizedBox(height: 30), Text("Mobile Number", style: gilroyTextStyle), const SizedBox(height: 15), CommonTextFormField( hintText: "Enter your mobile number", keyboardType: TextInputType.phone, controller: numberController, ), const SizedBox(height: 30), Text("Address", style: gilroyTextStyle), const SizedBox(height: 15), CommonTextFormField( hintText: "Enter your address", controller: addressController, ), const SizedBox(height: 30), Text("Email", style: gilroyTextStyle), const SizedBox(height: 15), CommonTextFormField( hintText: "Enter your email", keyboardType: TextInputType.emailAddress, controller: emailController, ), const SizedBox(height: 30), Center( child: Consumer( builder: (context, ref, _) { return CommanButton( width: width * 0.6, text: "Save", textStyle: TextStyle( fontFamily: 'Gilroy-Bold', fontWeight: FontWeight.w700, fontSize: 23, height: 1.0, letterSpacing: 0.01, color: AppColors.secondprimary, ), onPressed: () async { try { final repo = ref.read( profileupdateRepositoryProvider, ); await repo.updateProfile( url: ConstsApi.upadateprofile, name: nameController.text, number: numberController.text, email: emailController.text, address: addressController.text, imageFile: _image, ); if (mounted) { Fluttertoast.showToast( msg: "Profile updated successfully", toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.BOTTOM, backgroundColor: Colors.green, textColor: Colors.white, ); ref.refresh(profilegetuserProvider); Future.delayed( const Duration(milliseconds: 1500), () { if (mounted) { Navigator.of(context).pop(); } }, ); } } catch (e) { if (mounted) { Fluttertoast.showToast( msg: "Error updating profile: $e", toastLength: Toast.LENGTH_LONG, gravity: ToastGravity.BOTTOM, backgroundColor: Colors.red, textColor: Colors.white, ); } } }, ); }, ), ), const SizedBox(height: 30), ], ), ), ], ), ), ), ); }, ), ), ); } } class RightToLeftFullWidthTrianglePainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { final paint = Paint()..color = Colors.white; final path = Path(); path.moveTo(size.width, 0); path.lineTo(size.width, size.height); path.lineTo(0, size.height); path.close(); canvas.drawPath(path, paint); } @override bool shouldRepaint(CustomPainter oldDelegate) => false; }