|
|
|
@ -15,6 +15,7 @@ import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
|
|
|
|
import 'package:mc_common_app/widgets/common_widgets/branch_details_card.dart';
|
|
|
|
import 'package:mc_common_app/widgets/common_widgets/branch_details_card.dart';
|
|
|
|
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
|
|
|
|
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
|
|
|
|
import 'package:provider/provider.dart';
|
|
|
|
import 'package:provider/provider.dart';
|
|
|
|
|
|
|
|
import 'package:sizer/sizer.dart';
|
|
|
|
|
|
|
|
|
|
|
|
class ProviderProfileView extends StatefulWidget {
|
|
|
|
class ProviderProfileView extends StatefulWidget {
|
|
|
|
final int providerId;
|
|
|
|
final int providerId;
|
|
|
|
@ -49,30 +50,6 @@ class _ProviderProfileViewState extends State<ProviderProfileView> {
|
|
|
|
return Scaffold(
|
|
|
|
return Scaffold(
|
|
|
|
appBar: CustomAppBar(
|
|
|
|
appBar: CustomAppBar(
|
|
|
|
title: LocaleKeys.providerDetails.tr(),
|
|
|
|
title: LocaleKeys.providerDetails.tr(),
|
|
|
|
actions: [
|
|
|
|
|
|
|
|
Icon(
|
|
|
|
|
|
|
|
appointmentsVM.providerProfileModel!.isFavorite! ? Icons.favorite : Icons.favorite_border,
|
|
|
|
|
|
|
|
color: appointmentsVM.providerProfileModel!.isFavorite! ? MyColors.darkPrimaryColor : MyColors.black,
|
|
|
|
|
|
|
|
).horPaddingMain().onPress(
|
|
|
|
|
|
|
|
() async {
|
|
|
|
|
|
|
|
if (appointmentsVM.providerProfileModel!.isFavorite!) {
|
|
|
|
|
|
|
|
bool status = await appointmentsVM.removeProviderFromFavorite(serviceProviderID: appointmentsVM.providerProfileModel!.id!, context: context);
|
|
|
|
|
|
|
|
if (status) {
|
|
|
|
|
|
|
|
appointmentsVM.providerProfileModel!.isFavorite = false;
|
|
|
|
|
|
|
|
appointmentsVM.getMyFavoriteProviders();
|
|
|
|
|
|
|
|
setState(() {});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
bool status = await appointmentsVM.addProviderToFavorite(serviceProviderID: appointmentsVM.providerProfileModel!.id!, context: context);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (status) {
|
|
|
|
|
|
|
|
appointmentsVM.providerProfileModel!.isFavorite = true;
|
|
|
|
|
|
|
|
setState(() {});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
),
|
|
|
|
),
|
|
|
|
body: Container(
|
|
|
|
body: Container(
|
|
|
|
width: double.infinity,
|
|
|
|
width: double.infinity,
|
|
|
|
@ -84,7 +61,28 @@ class _ProviderProfileViewState extends State<ProviderProfileView> {
|
|
|
|
Column(
|
|
|
|
Column(
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
children: [
|
|
|
|
children: [
|
|
|
|
Center(child: appointmentsVM.providerProfileModel!.profileImage.buildNetworkImage(height: 250, width: double.infinity, fit: BoxFit.cover)),
|
|
|
|
Stack(
|
|
|
|
|
|
|
|
children: [
|
|
|
|
|
|
|
|
Center(
|
|
|
|
|
|
|
|
child: appointmentsVM.providerProfileModel!.profileImage.buildNetworkImage(
|
|
|
|
|
|
|
|
height: 250,
|
|
|
|
|
|
|
|
width: double.infinity,
|
|
|
|
|
|
|
|
fit: BoxFit.cover,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
Positioned(
|
|
|
|
|
|
|
|
top: 10,
|
|
|
|
|
|
|
|
right: 10,
|
|
|
|
|
|
|
|
child: FavoriteProviderButton(
|
|
|
|
|
|
|
|
isFavorite: appointmentsVM.providerProfileModel!.isFavorite!,
|
|
|
|
|
|
|
|
serviceProviderID: appointmentsVM.providerProfileModel!.id!,
|
|
|
|
|
|
|
|
onToggle: () {
|
|
|
|
|
|
|
|
setState(() {});
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
),
|
|
|
|
12.height,
|
|
|
|
12.height,
|
|
|
|
if (appointmentsVM.providerProfileModel!.memberSince!.isNotEmpty) ...[
|
|
|
|
if (appointmentsVM.providerProfileModel!.memberSince!.isNotEmpty) ...[
|
|
|
|
Row(
|
|
|
|
Row(
|
|
|
|
@ -166,3 +164,121 @@ class _ProviderProfileViewState extends State<ProviderProfileView> {
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class FavoriteProviderButton extends StatefulWidget {
|
|
|
|
|
|
|
|
final bool isFavorite;
|
|
|
|
|
|
|
|
final int serviceProviderID;
|
|
|
|
|
|
|
|
final VoidCallback onToggle;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const FavoriteProviderButton({
|
|
|
|
|
|
|
|
super.key,
|
|
|
|
|
|
|
|
required this.isFavorite,
|
|
|
|
|
|
|
|
required this.serviceProviderID,
|
|
|
|
|
|
|
|
required this.onToggle,
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
|
|
|
State<FavoriteProviderButton> createState() => _FavoriteProviderButtonState();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class _FavoriteProviderButtonState extends State<FavoriteProviderButton> with SingleTickerProviderStateMixin {
|
|
|
|
|
|
|
|
bool isLoading = false;
|
|
|
|
|
|
|
|
late bool isFavorite;
|
|
|
|
|
|
|
|
late AnimationController _animationController;
|
|
|
|
|
|
|
|
late Animation<double> _scaleAnimation;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
|
|
|
void initState() {
|
|
|
|
|
|
|
|
super.initState();
|
|
|
|
|
|
|
|
isFavorite = widget.isFavorite;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_animationController = AnimationController(
|
|
|
|
|
|
|
|
duration: const Duration(milliseconds: 300),
|
|
|
|
|
|
|
|
vsync: this,
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_scaleAnimation = Tween<double>(begin: 1.0, end: 1.3).animate(
|
|
|
|
|
|
|
|
CurvedAnimation(parent: _animationController, curve: Curves.easeInOut),
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
|
|
|
void dispose() {
|
|
|
|
|
|
|
|
_animationController.dispose();
|
|
|
|
|
|
|
|
super.dispose();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Future<void> toggleFavorite() async {
|
|
|
|
|
|
|
|
if (isLoading) return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setState(() {
|
|
|
|
|
|
|
|
isLoading = true;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_animationController.forward().then((_) => _animationController.reverse());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool success;
|
|
|
|
|
|
|
|
if (isFavorite) {
|
|
|
|
|
|
|
|
success = await context.read<AppointmentsVM>().removeProviderFromFavorite(serviceProviderID: widget.serviceProviderID);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
success = await context.read<AppointmentsVM>().addProviderToFavorite(serviceProviderID: widget.serviceProviderID);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (success) {
|
|
|
|
|
|
|
|
setState(() {
|
|
|
|
|
|
|
|
isFavorite = !isFavorite;
|
|
|
|
|
|
|
|
isLoading = false;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
context.read<AppointmentsVM>().providerProfileModel!.isFavorite = isFavorite;
|
|
|
|
|
|
|
|
if (isFavorite == false) {
|
|
|
|
|
|
|
|
context.read<AppointmentsVM>().getMyFavoriteProviders();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
widget.onToggle();
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
setState(() {
|
|
|
|
|
|
|
|
isLoading = false;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
|
|
|
|
return GestureDetector(
|
|
|
|
|
|
|
|
onTap: toggleFavorite,
|
|
|
|
|
|
|
|
child: Container(
|
|
|
|
|
|
|
|
width: 8.6.w,
|
|
|
|
|
|
|
|
height: 8.6.w,
|
|
|
|
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
|
|
|
|
color: Colors.white,
|
|
|
|
|
|
|
|
shape: BoxShape.circle,
|
|
|
|
|
|
|
|
boxShadow: [
|
|
|
|
|
|
|
|
BoxShadow(
|
|
|
|
|
|
|
|
color: const Color(0xff000000).withOpacity(.07),
|
|
|
|
|
|
|
|
blurRadius: 8,
|
|
|
|
|
|
|
|
offset: const Offset(0, 2),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
child: Center(
|
|
|
|
|
|
|
|
child: isLoading
|
|
|
|
|
|
|
|
? SizedBox(
|
|
|
|
|
|
|
|
width: 4.4.w,
|
|
|
|
|
|
|
|
height: 4.4.w,
|
|
|
|
|
|
|
|
child: const CircularProgressIndicator(
|
|
|
|
|
|
|
|
strokeWidth: 2,
|
|
|
|
|
|
|
|
valueColor: AlwaysStoppedAnimation<Color>(MyColors.darkPrimaryColor),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
: ScaleTransition(
|
|
|
|
|
|
|
|
scale: _scaleAnimation,
|
|
|
|
|
|
|
|
child: Icon(
|
|
|
|
|
|
|
|
isFavorite ? Icons.favorite : Icons.favorite_border,
|
|
|
|
|
|
|
|
color: isFavorite ? Colors.red : MyColors.darkIconColor,
|
|
|
|
|
|
|
|
size: 5.5.w,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|