import 'package:age_calculator/age_calculator.dart'; import 'package:buttons_tabbar/buttons_tabbar.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:gap/gap.dart'; import 'package:get_it/get_it.dart'; import 'package:velocity_x/velocity_x.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:you_app/blocs/account_cubit/account_cubit.dart'; import 'package:you_app/models/profile/profile_details.dart'; import 'package:you_app/screen/components/base_page.dart'; import 'package:you_app/screen/components/custom_button/custom_button.dart'; import 'package:you_app/screen/components/profile/no_data_widget.dart'; import 'package:you_app/screen/page/profile/widgets/left_menu_widget.dart'; import 'package:you_app/utils/alert_toast.dart'; import '../../../models/account/profile_model.dart'; import '../../../services/navigation.dart'; import '../../../utils/app_assets.dart'; import '../../../utils/app_routes.dart'; import '../../../utils/cont_const.dart'; import '../../../utils/themes.dart'; import '../../components/appbar/custom_appbar_profile.dart'; import '../../components/profile/family_widget.dart'; import '../../components/profile/photo_widget.dart'; import '../../components/profile/small_tag_widget.dart'; import '../../components/text_widget.dart'; import 'cubit/profile_cubit.dart'; import 'widgets/selection_account.bottom_sheet.dart'; class CompleteProfileScreen extends StatelessWidget { const CompleteProfileScreen( {Key? key, required this.inContact, required this.notSelfProfile, this.profileID}) : super(key: key); final bool inContact, notSelfProfile; final String? profileID; @override Widget build(BuildContext context) { return MultiBlocProvider( providers: [ BlocProvider( create: (context) => ProfileCubit(), ), BlocProvider( create: (context) => AccountCubit(), ), ], child: _CompleteProfileScreen( inContact: inContact, notSelfProfile: notSelfProfile, profileID: profileID, ), ); } } class _CompleteProfileScreen extends StatefulHookWidget { const _CompleteProfileScreen({ Key? key, required this.inContact, required this.notSelfProfile, this.profileID, }) : super(key: key); final bool inContact, notSelfProfile; final String? profileID; @override State<_CompleteProfileScreen> createState() => _CompleteProfileScreenState(); } class _CompleteProfileScreenState extends State<_CompleteProfileScreen> with AutomaticKeepAliveClientMixin<_CompleteProfileScreen> { final RefreshController refreshController = RefreshController(initialRefresh: false); @override bool get wantKeepAlive => true; @override Widget build(BuildContext context) { super.build(context); final profileCubit = context.read(); final accountCubit = context.read(); //call bool closeWidget = true; final showTheWidget = useState(false); var size = MediaQuery.of(context).size; useEffect(() { profileCubit.getProfileDataC(null); profileCubit.getAccountDataC(null); profileCubit.getProfileDetailsC(null); return; }); void onRefresh() async { // monitor network fetch profileCubit.getProfileDetailsC(null); profileCubit.getProfileDataC(null); profileCubit.getAccountDataC(null); // if failed,use refreshFailed() refreshController.refreshCompleted(); } void onLoading() async { // monitor network fetch await Future.delayed(const Duration(milliseconds: 500)); // if failed,use loadFailed(),if no data return,use LoadNodata() profileCubit.getProfileDataC(null); profileCubit.getAccountDataC(null); profileCubit.getProfileDetailsC(null); refreshController.refreshCompleted(); } List? profileList = []; List? famList = []; List experienceList = []; List mediaList = []; ProfileDetails? profileDetails; // Map? listDesc = {}; List? listLanguage = []; List? listDesc = []; String? thumbnail, username, firstName, lastName, countryId, bio, gender, height, weight, background, description, work, passcode, accountId, defaultProfileId; final age = useState(23); DateTime dob = DateTime(2000, 1, 1); bool isLoading = false; return BlocConsumer( listener: (context, state) { if (state is ProfileLoading) { isLoading = true; } if (state is CloseWidget) { closeWidget = state.value; } if (state is ProfileDetailSuccess) { defaultProfileId = state.data.id ?? ''; thumbnail = state.data.thumbnail; username = state.data.name; firstName = state.data.firstName ?? '-'; lastName = state.data.lastName ?? "-"; countryId = state.data.countryId ?? "SG"; dob = state.data.dob ?? DateTime(2000, 1, 1); gender = state.data.gender ?? ""; height = state.data.height ?? '155'; weight = state.data.weight ?? '45'; listLanguage = state.data.language ?? []; listDesc = state.data.description; bio = state.data.bio ?? ''; famList = state.data.family; mediaList = state.data.media ?? []; experienceList = state.data.experiences ?? []; background = state.data.background ?? 'You doing best'; profileDetails = state.data; if (profileDetails!.lastEditAt == null) { showTheWidget.value = true; } DateDuration duration; duration = AgeCalculator.age(dob); age.value = int.parse(duration.years.toString()); print("ini age ========== ${duration.years}"); isLoading = false; } if (state is ProfileDataSuccess) { profileList = state.data.profile; work = state.data.currentDepartementWork ?? ''; passcode = state.data.passcode ?? ''; accountId = state.data.id ?? ''; isLoading = false; } if (state is AccountDataSuccess) { //age.value = state.data.age ?? 22; isLoading = false; } if (state is CreateProfileLoading) { isLoading = false; GetIt.I().pop(); } if (state is CreateProfileSuccess) { isLoading = false; profileDetails = state.data; GetIt.I().pushNamed(AppRoutes.editProfile, args: { 'profileData': profileDetails })?.then((value) => onRefresh()); } if (state is CreateProfileError) { showToastSuccess(state.error); } }, builder: (context, state) { if (kDebugMode) { print('ini last edit'); print(profileDetails?.lastEditAt); } String formattedDob = DateFormat('yyyy-MM-dd').format(dob); return BasePage( isLoading: isLoading, appBar: CustomAppBarProfile( label: '', elevation: 0, hideBackbutton: false, backgroundColor: CustomColor.background, leftWidget: widget.notSelfProfile == false ? Image.asset(AppIcons.appIcon) .onTap(() => Scaffold.of(context).openDrawer()) : null, title: profileDetails?.lastEditAt == null ? Container() : widget.notSelfProfile == false ? HStack([ Image.asset( AppIcons.arrowGoldLeft, width: 15.sp, ), ValueTextWidget( text: username ?? '@', fontSize: 14.sp, fontWeight: FontWeight.w600, color: CustomColor.onBackground, ), Gap(4.sp), Image.asset( AppIcons.passcode, width: 15.sp, color: CustomColor.onBackground, ), Image.asset( AppIcons.arrowGoldRight, width: 15.sp, ), ]).onTap(() { accountBottomSheetSelection(context, profileList, accountId ?? '', defaultProfileId ?? '') .then((value) { if (value == true) { onRefresh(); } }); }).pOnly(left: 12.sp) : ValueTextWidget( text: username ?? '@', fontSize: 14.sp, fontWeight: FontWeight.w600, color: CustomColor.onBackground, ), actionWidget: profileDetails?.lastEditAt == null ? Container() : widget.notSelfProfile ? widget.inContact == true ? const LeftMenuProfileInContact() : const LeftMenuProfile() : Image.asset(AppIcons.editProfile).onTap(() { GetIt.I() .pushNamed(AppRoutes.editProfile, args: { 'profileData': profileDetails })?.then((value) => onRefresh()); }), ), body: SmartRefresher( header: WaterDropMaterialHeader( color: Colors.white, backgroundColor: gradientFincy[1].withOpacity(0.7), ), onRefresh: onRefresh, onLoading: onLoading, enablePullDown: true, controller: refreshController, child: profileDetails?.lastEditAt == null ? Center( child: VStack([ "Create your profile to start chatting with" .text .color(CustomColor.onBackground) .make() .centered(), "likeminded folks" .text .bold .color(CustomColor.onBackground) .make() .centered(), Gap(20.sp), GradientButton( title: "Create Profile", onTap: () { GetIt.I() .pushNamed(AppRoutes.editProfile, args: { 'profileData': profileDetails })?.then((value) => onRefresh()); }, colors: gradientFincy, gradientColors: isFillGradient, ).w56(context).centered() ]), ) : SingleChildScrollView( child: Column( children: [ //Gap(18.sp), BlocConsumer( listener: (context, state) { if (state is CloseWidget) { closeWidget = state.value; } if (state is ProfileDataSuccess) { // username = state.data.username ?? '@'; } }, builder: (context, state) { return AnimatedContainer( height: 210.sp, width: 360.sp, curve: Curves.fastLinearToSlowEaseIn, decoration: BoxDecoration( gradient: LinearGradient( colors: [ Colors.black.withOpacity(0.76), // Colors.black.withOpacity(0.0), Colors.black.withOpacity(0.79) ], begin: Alignment.topCenter, end: Alignment.bottomCenter), image: DecorationImage( opacity: 0.5, image: thumbnail == null ? const AssetImage( AppImages.defaultProfile) as ImageProvider : CachedNetworkImageProvider(thumbnail!), fit: BoxFit.cover, ), borderRadius: BorderRadius.all( Radius.circular(32.sp), ), ), duration: const Duration(milliseconds: 500), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Container( decoration: BoxDecoration( gradient: LinearGradient(colors: [ Colors.white.withOpacity(0.4), Colors.white.withOpacity(0.13) ]), //color: Colors.white.withOpacity(0.13), shape: BoxShape.circle, ), child: Image.asset(AppIcons.zoomOutGolden) .p(10.sp), ).onTap(() { // profileCubit // .changeCloseUpWidget(!closeWidget); }) ], ).pOnly(left: 10.sp), VStack([ age.value == 0 ? ValueTextWidget( text: '$username', fontSize: 16.sp, fontWeight: FontWeight.w700, color: Colors.white, letterSpacing: -23 / 100, ) : ValueTextWidget( text: '$username, ${age.value}', fontSize: 16.sp, fontWeight: FontWeight.w700, color: Colors.white, letterSpacing: -23 / 100, ), Gap(10.sp), work == '' ? ValueTextWidget( text: '$gender ', fontSize: 13.sp, fontWeight: FontWeight.w500, color: Colors.white, letterSpacing: -23 / 100, ) : ValueTextWidget( text: '$gender | $work', fontSize: 13.sp, fontWeight: FontWeight.w500, color: Colors.white, letterSpacing: -23 / 100, ), Gap(12.sp), SizedBox( width: size.width, child: Wrap( runSpacing: 5.sp, spacing: 5.sp, children: [ for (int i = 0; i < ((listDesc?.length ?? 0) > 3 ? 3 : (listDesc?.length ?? 0)); i++) SmallTagWidget( tag: listDesc![i], widgetColor: cEAF4F7.withOpacity(0.32), tagColor: Colors.white, ), (listDesc?.length ?? 0) < 4 ? Container() : SmallTagWidget( tag: '...', widgetColor: cEAF4F7.withOpacity(0.32), tagColor: Colors.white, ).onTap( () { GetIt.I() .pushNamed( AppRoutes .detailDescriptionProfile, args: { 'listDesc': listDesc }); }, ), ], ), ), ]).p8() ], ).p(12.sp), ); }, ), //widget detail profile on tab Gap(20.sp), BlocConsumer( listener: (context, state) { if (state is CloseWidget) { closeWidget = state.value; } }, builder: (context, state) { return Visibility( visible: closeWidget ? false : true, child: SizedBox( height: size.height, width: size.width, child: DefaultTabController( length: 2, child: Column( mainAxisSize: MainAxisSize.min, children: [ ButtonsTabBar( unselectedBackgroundColor: Colors.transparent, decoration: const BoxDecoration( color: Colors.transparent, ), labelStyle: TextStyle( fontSize: 13.sp, fontWeight: FontWeight.w600, color: CustomColor.onBackground, ), // backgroundColor: Colors.transparent, unselectedLabelStyle: TextStyle( fontSize: 13.sp, fontWeight: FontWeight.w400, color: textGrey, ), onTap: (p0) { // print(p0); }, splashColor: gradientFincy[1].withOpacity(0.1), tabs: [ Tab( icon: Image.asset( AppIcons.likeGolden), text: 'about'.tr(), ), // Tab( // icon: Image.asset( // AppIcons.shopGolden), // text: 'shop'.tr(), // ), // Tab( // icon: // Image.asset(AppIcons.boxGolden), // text: 'services'.tr(), // ), Tab( icon: Image.asset( AppIcons.galleryGolden), text: "media".tr(), ), // Tab( // icon: Image.asset( // AppIcons.experienceGolden), // text: // "professional_experience".tr(), // ) ], ), Gap(10.sp), Expanded( child: TabBarView( children: [ //this is tab about SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ // widget bio Container( decoration: boxNewProfile, child: VStack([ TextWidget( text: 'bio', fontSize: 14.sp, fontWeight: FontWeight.w700, color: CustomColor .onBackground, ), Gap(16.sp), SizedBox( width: size.width, child: ValueTextWidget( text: bio ?? 'There is no bio data', fontSize: 13.sp, fontWeight: FontWeight.w500, color: textRegular, ), ) ]).p(15.sp), ).pOnly( left: 4.sp, right: 4.sp, top: 16.sp, bottom: 10.sp), //widget about Container( decoration: boxNewProfile, child: VStack([ TextWidget( text: 'about', fontSize: 14.sp, fontWeight: FontWeight.w700, color: CustomColor .onBackground, ), Gap(12.sp), HStack([ TextWidget( text: 'birthday:', fontSize: 13.sp, fontWeight: FontWeight.w500, color: cA4A4A4, ), ValueTextWidget( text: ' $formattedDob', fontSize: 13.sp, fontWeight: FontWeight.w500, color: CustomColor .onBackground, ) ]), Gap(12.sp), HStack([ TextWidget( text: 'background:', fontSize: 13.sp, fontWeight: FontWeight.w500, color: cA4A4A4, ), ValueTextWidget( text: " $background", fontSize: 13.sp, fontWeight: FontWeight.w500, color: CustomColor .onBackground, ) ]), Gap(12.sp), HStack([ TextWidget( text: 'language:', fontSize: 13.sp, fontWeight: FontWeight.w500, color: cA4A4A4, ), SizedBox( width: size.width - 130, child: Wrap( children: List.generate( listLanguage ?.length ?? 0, (index) => ValueTextWidget( text: " ${index != 0 ? listLanguage![0] != "" && listLanguage![1] != "" ? " | " : "" : ""}${listLanguage![index]}", fontSize: 13.sp, fontWeight: FontWeight.w500, color: CustomColor.onBackground, )), ), ) ]), Gap(12.sp), HStack( [ TextWidget( text: 'height:', fontSize: 13.sp, fontWeight: FontWeight.w500, color: cA4A4A4, ), ValueTextWidget( text: ' $height cm', fontSize: 13.sp, fontWeight: FontWeight.w500, color: CustomColor .onBackground, ) ], ), Gap(12.sp), HStack([ TextWidget( text: 'weight:', fontSize: 13.sp, fontWeight: FontWeight.w500, color: cA4A4A4, ), ValueTextWidget( text: ' $weight kg', fontSize: 13.sp, fontWeight: FontWeight.w500, color: CustomColor .onBackground, ) ]), ]).pOnly( left: 16.sp, right: 10.sp, top: 12.sp, bottom: 10.sp), ), //widget experience Gap(10.sp), Visibility( visible: experienceList.isEmpty ? false : true, child: Container( decoration: boxNewProfile, child: VStack([ Gap(5.sp), ValueTextWidget( text: 'Professional Experience', fontSize: 14.sp, fontWeight: FontWeight.w700, color: CustomColor .onBackground, ), Gap(16.sp), ListView.separated( shrinkWrap: true, primary: false, itemCount: experienceList .length, separatorBuilder: (context, index) => Gap(12.sp), itemBuilder: (context, index) { final exp = experienceList[ index]; return HStack( [ ClipRRect( borderRadius: BorderRadius .circular( 8.sp), child: CachedNetworkImage( imageUrl: exp.image ?? "", height: 32.sp, width: 32.sp, fit: BoxFit .cover, ), ), Gap(8.sp), VStack( [ SizedBox( width: 263 .sp, child: ValueTextWidget( text: '${exp.jobTitle} | ${exp.companyName}', fontSize: 12.sp, fontWeight: FontWeight.w500, color: CustomColor .onBackground, ), ), Gap(3.sp), ValueTextWidget( text: '${exp.startDate != null ? "${DateFormat.MMM().format(exp.startDate!).toString()} ${exp.startDate?.year}" : "..."} ' '- ${(exp.status ?? "") == "active" ? "active" : exp.endDate != null ? "${DateFormat.MMM().format(exp.endDate!).toString()} ${exp.endDate?.year}" : "Present"}', fontSize: 11.sp, fontWeight: FontWeight .w400, color: cA4A4A4, ) ], ).expand(), ], ).pOnly( top: 12.sp, left: 10.sp); }, ), ]).pOnly( left: 12.sp, right: 12.sp, bottom: 10.sp, top: 10.sp), ), ), Gap(10.sp), //widget family Visibility( visible: famList!.isEmpty ? false : true, child: Container( decoration: boxNewProfile, child: VStack([ Gap(5.sp), TextWidget( text: 'family', fontSize: 14.sp, fontWeight: FontWeight.w700, color: CustomColor .onBackground, ), Gap(2.sp), ListView.builder( shrinkWrap: true, primary: false, itemCount: famList?.length ?? 0, itemBuilder: (BuildContext context, int index) { return ItemFamilyWidget( family: famList![ index], padding: EdgeInsets .symmetric( vertical: 5.sp), ).pOnly(top: 12.sp); }, ), ]).pOnly( left: 12.sp, right: 12.sp, bottom: 10.sp, top: 10.sp), ), ), ], ), ), //widget shop // const Visibility( // visible: true, // child: NoDataWidget( // text: 'no_data_shop'), // ), //widget service // const Visibility( // visible: true, // child: NoDataWidget( // text: 'no_data_services'), // ), //widget media profile mediaList.isEmpty ? const NoDataWidget( text: 'no_data_media') : SingleChildScrollView( child: Column( children: [ SizedBox( height: size.height, width: size.width, child: GridView.builder( itemCount: mediaList .length, gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, ), itemBuilder: (BuildContext context, int index) { return MediaWidget( image: mediaList[index] .url ?? 'https://images.unsplash.com/photo-1666454638303-435ad6a49533?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=686&q=80', weight: 2) .p(6.sp); }, ), ), ], ), ), ], ), ) ], ), ), ), ); }, ) ], ).p(8.sp), ), ), ); }, ); } }