Files
eatvio_app/lib/features/profile/presentation/pages/profile_screen.dart
2024-09-30 17:44:25 +03:00

368 lines
16 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:eatvio_app/core/const.dart';
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
import 'package:eatvio_app/features/feed/presentation/widgets/blog_post_widget.dart';
import 'package:eatvio_app/features/profile/models/circumference_model.dart';
import 'package:eatvio_app/features/profile/models/weight_model.dart';
import 'package:eatvio_app/features/profile/presentation/bloc/profile_cubit/profile_cubit.dart';
import 'package:eatvio_app/features/profile/presentation/bloc/profile_cubit/profile_state.dart';
import 'package:eatvio_app/features/profile/presentation/widgets/circumference_chart_widget.dart';
import 'package:eatvio_app/features/profile/presentation/widgets/imt_chart_widget.dart';
import 'package:eatvio_app/features/profile/presentation/widgets/weight_chart_widget.dart';
import 'package:eatvio_app/locator_service.dart';
import 'package:eatvio_app/theme/theme_helper.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:go_router/go_router.dart';
import 'package:rive/rive.dart';
import 'package:share_plus/share_plus.dart';
class ProfileScreen extends StatefulWidget {
final Author? author;
const ProfileScreen({super.key, this.author});
@override
State<ProfileScreen> createState() => _ProfileScreenState();
}
class _ProfileScreenState extends State<ProfileScreen> {
List<CircumferenceModel> circumferencePoints = [];
List<WeightModel> weightPoints = [];
final List<String> chipsLabelList = ['Вес', 'Замеры', 'ИМТ'];
final List<String> chipsIntervalLabelList = ['1М', '3М', '6М', '1Г', 'ВСЁ ВРЕМЯ'];
final List<String> chipsIntervalList = ['1', '3', '6', '12', 'all'];
int _selectedChipIndex = 0;
int _selectedIntervalChipIndex = 0;
final ProfileCubit profileCubit = sl<ProfileCubit>();
@override
void initState() {
super.initState();
widget.author == null ? profileCubit.getMyProfile() : profileCubit.getProfileBySlug(widget.author!.authorSlug);
}
@override
Widget build(BuildContext context) {
return BlocBuilder<ProfileCubit, ProfileState>(
bloc: profileCubit,
builder: (BuildContext context, ProfileState state) {
if (state is ProfileStateLoaded) {
if (state.circumferencePoints != null) {
circumferencePoints = state.circumferencePoints!;
weightPoints = state.weightPoints!;
}
return Scaffold(
backgroundColor: Colors.grey.shade200,
appBar: widget.author == null ? AppBar(toolbarHeight: 0) : AppBar(),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(
bottom: Radius.circular(16),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
CircleAvatar(
radius: 32,
backgroundImage: NetworkImage(state.profile.profilePhotoUrl),
),
const SizedBox(width: 12),
Text(
state.profile.name,
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w500,
height: 1,
),
),
const Spacer(),
Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
child: SvgPicture.asset(
height: 28,
width: 28,
'assets/icons/subscribers.svg',
colorFilter: ColorFilter.mode(appTheme.blueA400, BlendMode.srcIn),
),
),
SizedBox(width: 8),
Column(
children: [
Text(
'123',
style: TextStyle(
height: 1,
fontSize: 18,
fontWeight: FontWeight.w500,
color: Colors.black87,
),
),
Text(
'Подписчика',
style: TextStyle(
height: 1,
fontSize: 12,
fontWeight: FontWeight.w400,
color: Colors.black38,
),
),
],
),
],
),
GestureDetector(
onTap: () => Share.shareUri(
Uri.parse(
baseUrl + '/ru/profile/' + state.profile.slug,
),
),
child: Container(
padding: EdgeInsets.only(left: 16),
child: SvgPicture.asset(
height: 24,
width: 24,
'assets/icons/share.svg',
colorFilter: ColorFilter.mode(appTheme.blueA400, BlendMode.srcIn),
),
),
),
],
),
),
if (state.profileDetails.additionalInfo.isNotEmpty)
Container(
alignment: Alignment.centerLeft,
padding: const EdgeInsets.all(16),
child: Text(
state.profileDetails.additionalInfo,
style: TextStyle(
color: Colors.black.withOpacity(0.4),
height: 1,
),
),
),
if (widget.author != null) const SizedBox(height: 8),
if (widget.author != null)
Row(
children: [
SizedBox(width: 16),
GestureDetector(
onTap: () => GoRouter.of(context).pushNamed(
'chatScreen',
),
child: Container(
alignment: Alignment.center,
padding: EdgeInsets.all(8),
width: (MediaQuery.of(context).size.width - 40) / 2,
decoration: BoxDecoration(
color: appTheme.blueA400.withOpacity(0.1),
borderRadius: BorderRadius.circular(16),
),
child: Text(
'Сообщение',
style: TextStyle(
color: appTheme.blueA400,
),
),
),
),
SizedBox(width: 8),
Container(
alignment: Alignment.center,
padding: EdgeInsets.all(8),
width: (MediaQuery.of(context).size.width - 40) / 2,
decoration: BoxDecoration(
color: appTheme.blueA400,
borderRadius: BorderRadius.circular(16),
),
child: Text(
'Подписаться',
style: TextStyle(
color: Colors.white,
),
),
),
SizedBox(width: 16),
],
),
if (widget.author != null) SizedBox(height: 16),
if (widget.author == null) _divider(context),
if (widget.author == null)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 8),
SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 16),
scrollDirection: Axis.horizontal,
child: Row(
children: [
_choiceChipWidget(0),
SizedBox(width: 8),
_choiceChipWidget(1),
SizedBox(width: 8),
_choiceChipWidget(2),
],
),
),
Builder(
builder: (context) {
switch (_selectedChipIndex) {
case 0:
return WeightChartWidget(
weightPoints: weightPoints,
profileCubit: profileCubit,
);
case 1:
return CircumferenceChartWidget(
circumferencePoints: circumferencePoints,
profileCubit: profileCubit,
);
case 2:
return ImtChartWidget(
weightPoints: weightPoints,
);
}
return SizedBox.shrink();
},
),
SizedBox(height: 8),
Row(
children: [
SizedBox(width: 16),
_choiceIntervalChipWidget(0),
SizedBox(width: 8),
_choiceIntervalChipWidget(1),
SizedBox(width: 8),
_choiceIntervalChipWidget(2),
SizedBox(width: 8),
_choiceIntervalChipWidget(3),
SizedBox(width: 8),
_choiceIntervalChipWidget(4),
],
),
SizedBox(height: 8),
],
),
],
),
),
SizedBox(height: 16),
ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) => BlogPostWidget(feedBlogPostModel: state.blogPosts[index]),
separatorBuilder: (context, index) => SizedBox(height: 8),
itemCount: state.blogPosts.length,
),
SizedBox(height: 16),
],
),
),
);
} else if (state is ProfileStateError) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: Padding(
padding: const EdgeInsets.all(16),
child: Text(state.errorMessage),
),
),
);
} else {
return Scaffold(
appBar: AppBar(),
body: Center(
child: SizedBox(
height: 32,
width: 32,
child: RiveAnimation.asset(
'assets/rive_animations/loading.riv',
),
),
),
);
}
},
);
}
_divider(BuildContext context) {
return Container(
height: 0.4,
width: MediaQuery.of(context).size.width - 32,
decoration: BoxDecoration(
color: Colors.black26,
borderRadius: BorderRadius.circular(16),
),
);
}
_choiceIntervalChipWidget(int index) {
return ChoiceChip(
selectedColor: Colors.grey.withOpacity(0.1),
pressElevation: 0,
showCheckmark: false,
side: BorderSide.none,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
label: Text(chipsIntervalLabelList[index]),
labelStyle: TextStyle(
color: appTheme.gray600,
fontWeight: FontWeight.w500,
fontSize: 12,
),
selected: _selectedIntervalChipIndex == index,
onSelected: (bool selected) {
profileCubit.getMyProfile(period: chipsIntervalList[index]);
setState(() {
_selectedIntervalChipIndex = index;
});
},
);
}
_choiceChipWidget(int index) {
return ChoiceChip(
selectedColor: appTheme.blueA400,
pressElevation: 0,
showCheckmark: false,
side: BorderSide.none,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
label: Text(chipsLabelList[index]),
labelStyle: TextStyle(
color: index == _selectedChipIndex ? Colors.white : appTheme.gray600,
fontWeight: FontWeight.w500,
fontSize: 12,
),
selected: _selectedChipIndex == index,
backgroundColor: appTheme.gray100,
onSelected: (bool selected) {
setState(() {
_selectedChipIndex = index;
});
},
);
}
}