import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:lba/gen/assets.gen.dart'; import 'package:lba/res/colors.dart'; class Profile extends StatefulWidget { const Profile({super.key}); @override State createState() => _ProfileState(); } class _ProfileState extends State with TickerProviderStateMixin { bool _isDarkMode = false; late AnimationController _animationController; late List> _animations; @override void initState() { super.initState(); _animationController = AnimationController( vsync: this, duration: const Duration(milliseconds: 1200), ); const int itemCount = 12; _animations = List.generate(itemCount, (index) { final double startTime = (index / itemCount) * 0.6; final double endTime = (startTime + 0.4).clamp(0.0, 1.0); return Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation( parent: _animationController, curve: Interval( startTime, endTime, curve: Curves.easeOutCubic, ), ), ); }); _animationController.forward(); } @override void dispose() { _animationController.dispose(); super.dispose(); } Widget _buildAnimatedWidget(Widget child, int index) { if (index >= _animations.length) return child; final slideAnimation = Tween( begin: const Offset(0.0, 0.5), end: Offset.zero, ).animate(_animations[index]); return FadeTransition( opacity: _animations[index], child: SlideTransition( position: slideAnimation, child: child, ), ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: PreferredSize( preferredSize: const Size.fromHeight(kToolbarHeight + 1), child: Container( decoration: BoxDecoration( color: Colors.white, borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(18), bottomRight: Radius.circular(18), ), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 4), ), ], ), child: AppBar( surfaceTintColor: Colors.white, backgroundColor: Colors.transparent, elevation: 0, centerTitle: true, title: const Text( 'Profile', style: TextStyle( color: Colors.black, fontSize: 17, fontWeight: FontWeight.w600, ), ), ), ), ), body: SingleChildScrollView( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 20.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildAnimatedWidget(_SectionTitle(title: 'General'), 0), _buildAnimatedWidget( _buildSectionContainer( child: Column( children: [ _buildInfoTile( icon: SvgPicture.asset(Assets.icons.globalSearch2.path, width: 22), title: 'Country', trailing: const Text( 'United Arab Emirates', style: TextStyle( color: LightAppColors.primary, fontSize: 15, fontWeight: FontWeight.w500), ), ), _buildInfoTile( icon: SvgPicture.asset(Assets.icons.languageSquare.path, width: 22), title: 'Language', trailing: Row( mainAxisSize: MainAxisSize.min, children: [ Image.asset(Assets.images.usa.path, width: 24), const SizedBox(width: 8), const Text('English', style: TextStyle( fontSize: 15, fontWeight: FontWeight.w500, color: Colors.black)), const SizedBox(width: 8), SvgPicture.asset(Assets.icons.arrowRight.path, color: Colors.black) ], ), ), _buildSwitchTile( icon: SvgPicture.asset(Assets.icons.brush.path, width: 22), title: 'Dark mode', value: _isDarkMode, onChanged: (value) => setState(() => _isDarkMode = value), ), ], ), ), 1, ), const SizedBox(height: 8), _buildAnimatedWidget( PressableListItem( child: _buildDecoratedNavigationTile( icon: SvgPicture.asset(Assets.icons.editProf.path, width: 22), title: 'Edit Profile'), ), 2), const SizedBox(height: 8), _buildAnimatedWidget( PressableListItem( child: _buildDecoratedNavigationTile( icon: SvgPicture.asset(Assets.icons.notification.path, color: LightAppColors.primary, width: 22), title: 'Notifications'), ), 3), const SizedBox(height: 8), _buildAnimatedWidget( PressableListItem( child: _buildDecoratedNavigationTile( icon: SvgPicture.asset(Assets.icons.emptyWallet.path, width: 22), title: 'Transactions & Wallets'), ), 4), const SizedBox(height: 8), _buildAnimatedWidget( PressableListItem( child: _buildDecoratedNavigationTile( icon: SvgPicture.asset(Assets.icons.gift.path, width: 22), title: 'Exclusive Perks'), ), 5), const SizedBox(height: 8), _buildAnimatedWidget( PressableListItem( child: _buildDecoratedNavigationTile( icon: SvgPicture.asset(Assets.icons.cardPos.path, color: LightAppColors.primary, width: 22), title: 'Payment methods'), ), 6), const SizedBox(height: 8), _buildAnimatedWidget( PressableListItem( child: _buildDecoratedNavigationTile( icon: SvgPicture.asset(Assets.icons.heart.path, width: 22), title: 'Favorite Stores'), ), 7), const SizedBox(height: 24), _buildAnimatedWidget(_SectionTitle(title: 'Preferences'), 8), _buildAnimatedWidget( PressableListItem( child: _buildDecoratedNavigationTile( icon: SvgPicture.asset(Assets.icons.shield.path, width: 22), title: 'Legal & Policies'), ), 9), const SizedBox(height: 8), _buildAnimatedWidget( PressableListItem( child: _buildDecoratedNavigationTile( icon: SvgPicture.asset(Assets.icons.messageQuestion.path, width: 22), title: 'Help & Support'), ), 10), const SizedBox(height: 8), _buildAnimatedWidget(PressableListItem(child: _buildLogoutButton()), 11), const SizedBox(height: 85), ], ), ), ), ); } Widget _buildSectionContainer({required Widget child}) { return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: child, ); } Widget _buildInfoTile( {required Widget icon, required String title, required Widget trailing}) { return Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: Row( children: [ icon, const SizedBox(width: 16), Expanded( child: Text(title, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w500, color: Colors.black))), trailing, ], ), ); } Widget _buildSwitchTile( {required Widget icon, required String title, required bool value, required ValueChanged onChanged}) { return Padding( padding: const EdgeInsets.symmetric(vertical: 2.0), child: Row( children: [ icon, const SizedBox(width: 16), Expanded( child: Text(title, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w500))), Transform.scale( scale: 0.75, child: Switch( value: value, onChanged: onChanged, activeColor: const Color(0xFF34C759), activeTrackColor: const Color(0xFF34C759).withOpacity(0.5), inactiveThumbColor: Colors.white, inactiveTrackColor: const Color.fromARGB(57, 141, 141, 141), ), ), ], ), ); } Widget _buildDecoratedNavigationTile( {required Widget icon, required String title}) { return Container( decoration: BoxDecoration( color: LightAppColors.profileField, borderRadius: BorderRadius.circular(14), border: Border.all(color: LightAppColors.divider, width: 0.5), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 17), child: Row( children: [ icon, const SizedBox(width: 16), Expanded( child: Text(title, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w500, color: Colors.black))), SvgPicture.asset(Assets.icons.arrowRight.path, color: Colors.black) ], ), ), ); } Widget _buildLogoutButton() { return Container( decoration: BoxDecoration( color: LightAppColors.profileField, borderRadius: BorderRadius.circular(14), border: Border.all(color: LightAppColors.divider, width: 0.5), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), child: Row( children: [ SvgPicture.asset( Assets.icons.logout.path, width: 22, ), const SizedBox(width: 16), const Expanded( child: Text( 'Logout', style: TextStyle( color: LightAppColors.allReviewOpener, fontSize: 16, fontWeight: FontWeight.w500), ), ), ], ), ), ); } } // ویجت برای افکت لمس class PressableListItem extends StatefulWidget { final Widget child; const PressableListItem({super.key, required this.child}); @override State createState() => _PressableListItemState(); } class _PressableListItemState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation _scaleAnimation; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 150), reverseDuration: const Duration(milliseconds: 300), ); _scaleAnimation = Tween(begin: 1.0, end: 0.97).animate( CurvedAnimation(parent: _controller, curve: Curves.easeOut), ); } @override void dispose() { _controller.dispose(); super.dispose(); } void _onTapDown(TapDownDetails details) { _controller.forward(); } void _onTapUp(TapUpDetails details) { Future.delayed(const Duration(milliseconds: 100), () { if(mounted) { _controller.reverse(); } }); } void _onTapCancel() { _controller.reverse(); } @override Widget build(BuildContext context) { return GestureDetector( onTapDown: _onTapDown, onTapUp: _onTapUp, onTapCancel: _onTapCancel, onTap: () {}, child: ScaleTransition( scale: _scaleAnimation, child: widget.child, ), ); } } class _SectionTitle extends StatelessWidget { final String title; const _SectionTitle({required this.title}); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.only(bottom: 12.0, top: 8.0, left: 12.0), child: Text( title, style: const TextStyle( fontSize: 17, fontWeight: FontWeight.bold, color: Colors.black, ), ), ); } }