diff --git a/lib/presentation/profile/my_profile_screen/bloc/my_profile_bloc.dart b/lib/presentation/profile/my_profile_screen/bloc/my_profile_bloc.dart index 29c6c673..eab8dd94 100644 --- a/lib/presentation/profile/my_profile_screen/bloc/my_profile_bloc.dart +++ b/lib/presentation/profile/my_profile_screen/bloc/my_profile_bloc.dart @@ -1,4 +1,6 @@ //import 'package:eatvio_app/presentation/auth/auth_screen/auth_screen.dart'; +import 'dart:async'; + import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; import '/core/app_export.dart'; @@ -7,6 +9,7 @@ import 'package:http/http.dart' as http; import 'dart:convert'; import 'package:hive/hive.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; +import 'package:image_picker/image_picker.dart'; part 'my_profile_event.dart'; part 'my_profile_state.dart'; @@ -15,6 +18,7 @@ part 'my_profile_state.dart'; class MyProfileBloc extends Bloc { MyProfileBloc(MyProfileState initialState) : super(initialState) { on(_onInitialize); + on(_uploadAvatar); } Future _onInitialize( @@ -242,4 +246,35 @@ class MyProfileBloc extends Bloc { return "экстремальный (несколько интенсивных тренировок в день)"; } } // колхоз, но свитчкейсы в дарте странно ведут себя при сравнении double + + Future _uploadAvatar( + UploadAvatar event, Emitter emit) async { + if (state is MyProfileLoadedState) { + var currentState = state as MyProfileLoadedState; + + await uploadImageToServer(event.image.path, currentState.token); + } + } + + Future uploadImageToServer(String imagePath, String? token) async { + String url = '${dotenv.env['SERVER_ROOT']!}/profile/photo/upload'; + print(url); + var request = http.MultipartRequest('POST', Uri.parse(url)); + request.headers['Authorization'] = 'Bearer $token'; + + request.files.add(await http.MultipartFile.fromPath('photo', imagePath)); + + var client = http.Client(); + var streamedResponse = await client.send(request); + + if (streamedResponse.statusCode == 200) { + var response = await http.Response.fromStream(streamedResponse); + var imageUrl = response.body; + print('Image successfully uploaded'); + return imageUrl; + } else { + throw Exception( + 'Failed to upload image. Status code: ${streamedResponse.statusCode} ${streamedResponse}}'); + } + } } diff --git a/lib/presentation/profile/my_profile_screen/bloc/my_profile_event.dart b/lib/presentation/profile/my_profile_screen/bloc/my_profile_event.dart index 99c025a4..ca76f246 100644 --- a/lib/presentation/profile/my_profile_screen/bloc/my_profile_event.dart +++ b/lib/presentation/profile/my_profile_screen/bloc/my_profile_event.dart @@ -14,3 +14,10 @@ class MyProfileInitialEvent extends MyProfileEvent { @override List get props => []; } + +class UploadAvatar extends MyProfileEvent { + UploadAvatar(this.image); + final XFile image; + @override + List get props => [image]; +} diff --git a/lib/presentation/profile/my_profile_screen/my_profile_screen.dart b/lib/presentation/profile/my_profile_screen/my_profile_screen.dart index 3b12b13d..d02f26d2 100644 --- a/lib/presentation/profile/my_profile_screen/my_profile_screen.dart +++ b/lib/presentation/profile/my_profile_screen/my_profile_screen.dart @@ -5,6 +5,7 @@ import 'package:eatvio_app/widgets/app_bar/appbar_subtitle.dart'; import 'package:eatvio_app/widgets/custom_bottom_bar.dart'; import 'package:eatvio_app/widgets/custom_text_form_field.dart'; import 'package:carousel_slider/carousel_slider.dart'; +import 'package:image_picker/image_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter/services.dart'; @@ -139,27 +140,41 @@ class MyProfileScreen extends StatelessWidget { /// Section Widget _buildInfo(BuildContext context, MyProfileLoadedState state) { - print(state.user?['profile_photo_url']); return Column(children: [ - CachedNetworkImage( - imageUrl: state.user?['profile_photo_url'], - imageBuilder: (context, imageProvider) => CircleAvatar( - backgroundImage: imageProvider, - radius: 60, - ), - placeholder: (context, url) => CircularProgressIndicator(), - errorWidget: (context, url, error) => CircleAvatar( - child: Icon(Icons.person), - backgroundColor: Colors.grey[200], - radius: 60, - ), - ), + GestureDetector( + onTap: addImage(context), + child: CachedNetworkImage( + imageUrl: + dotenv.env['STORAGE_URL']! + state.user?['profile_photo_path'], + imageBuilder: (context, imageProvider) => CircleAvatar( + backgroundImage: imageProvider, + radius: 60, + ), + placeholder: (context, url) => CircularProgressIndicator(), + errorWidget: (context, url, error) => CircleAvatar( + child: Icon(Icons.person), + backgroundColor: Colors.grey[200], + radius: 60, + ), + )), AppbarSubtitle(text: state.user?['name']), SizedBox(height: 20.v), Text(state.userDetails?['additional_info']), ]); } + addImage(BuildContext context) { + return () async { + final picker = ImagePicker(); + List? images = await picker.pickMultiImage(); + if (images.isNotEmpty) { + for (var image in images) { + context.read().add(UploadAvatar(image)); + } + } + }; + } + onTapSettings(BuildContext context) { return () { Navigator.pushNamed(context, AppRoutes.mySettings);