From 58a7ca933dd7a6ab18faa3e61e6f6ccfcbe00b00 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Thu, 27 Jun 2024 16:50:23 +0300 Subject: [PATCH] feat(feed): Dio, retrofit and freezed model stump --- lib/core/token_storage.dart | 17 +- .../bloc/blog_post_create_bloc.dart | 48 ++-- .../bloc/blog_post_create_state.dart | 14 +- .../blog_post_create_screen.dart | 20 +- .../blog_post_create_credentials_model.dart | 16 ++ ...post_create_credentials_model.freezed.dart | 235 ++++++++++++++++++ .../blog_post_create_credentials_model.g.dart | 25 ++ .../repositories/blog_repository.dart | 20 ++ .../services/blog_service.dart | 14 ++ .../services/blog_service.g.dart | 78 ++++++ .../bloc/blog_post_edit_bloc.dart | 32 ++- .../bloc/blog_post_edit_state.dart | 21 +- .../blog_post_edit_screen.dart | 17 +- 13 files changed, 481 insertions(+), 76 deletions(-) create mode 100644 lib/presentation/feed/blog_post_create_screen/models/blog_post_create_credentials_model.dart create mode 100644 lib/presentation/feed/blog_post_create_screen/models/blog_post_create_credentials_model.freezed.dart create mode 100644 lib/presentation/feed/blog_post_create_screen/models/blog_post_create_credentials_model.g.dart create mode 100644 lib/presentation/feed/blog_post_create_screen/repositories/blog_repository.dart create mode 100644 lib/presentation/feed/blog_post_create_screen/services/blog_service.dart create mode 100644 lib/presentation/feed/blog_post_create_screen/services/blog_service.g.dart diff --git a/lib/core/token_storage.dart b/lib/core/token_storage.dart index 82d2935..01ac606 100644 --- a/lib/core/token_storage.dart +++ b/lib/core/token_storage.dart @@ -3,7 +3,7 @@ import 'package:eatvio_app/locator_service.dart'; import 'package:hive_flutter/hive_flutter.dart'; abstract class TokenStorage { - static addTokenToDioHeader(String token) { + static _addTokenToDioHeader(String token) { sl().options.headers['Authorization'] = 'Bearer $token'; } @@ -13,20 +13,19 @@ abstract class TokenStorage { if (token == null) { return false; } else { - addTokenToDioHeader(token); + _addTokenToDioHeader(token); return true; } } - static getTokenFromStorage() async => await Hive.openBox('token') - ..get('token'); + static Future getTokenFromStorage() async => + (await Hive.openBox('token')).get('token'); static saveTokenInStorage(String token) async { - await Hive.openBox('token') - ..put('token', token); - addTokenToDioHeader(token); + (await Hive.openBox('token')).put('token', token); + _addTokenToDioHeader(token); } - static removeTokenInStorage(String token) async => await Hive.openBox('token') - ..delete('token'); + static removeTokenInStorage() async => + (await Hive.openBox('token')).delete('token'); } diff --git a/lib/presentation/feed/blog_post_create_screen/bloc/blog_post_create_bloc.dart b/lib/presentation/feed/blog_post_create_screen/bloc/blog_post_create_bloc.dart index d2f448b..7ddbaca 100644 --- a/lib/presentation/feed/blog_post_create_screen/bloc/blog_post_create_bloc.dart +++ b/lib/presentation/feed/blog_post_create_screen/bloc/blog_post_create_bloc.dart @@ -1,11 +1,11 @@ import 'dart:async'; +import 'package:dio/dio.dart'; import 'package:eatvio_app/app_router.dart'; +import 'package:eatvio_app/locator_service.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:hive/hive.dart'; -import 'package:http/http.dart' as http; import 'package:image_picker/image_picker.dart'; import 'dart:convert'; import '/core/app_export.dart'; @@ -39,7 +39,7 @@ class BlogPostCreateBloc blog_postModelObj: currentState.blog_postModelObj, title: currentState.title, description: currentState.description, - youtube_url: currentState.youtube_url, + youtubeURL: currentState.youtubeURL, token: currentState.token, ), ); @@ -49,7 +49,7 @@ class BlogPostCreateBloc token: token, title: TextEditingController(), description: TextEditingController(), - youtube_url: TextEditingController(), + youtubeURL: TextEditingController(), ), ); } @@ -64,8 +64,9 @@ class BlogPostCreateBloc var response = await sendBlogPost( currentState.title?.text, - currentState.youtube_url?.text, + currentState.youtubeURL?.text, currentState.description?.text, + currentState.image, ); if (response.statusCode == 200) { @@ -78,34 +79,35 @@ class BlogPostCreateBloc } } - FutureOr sendBlogPost( - String? title, - String? youtube_url, - String? description, - ) async { - String url = '${dotenv.env['SERVER_ROOT']!}/feed/create'; - final box = await Hive.openBox('token'); - final token = box.get('token'); + sendBlogPost(String? title, String? youtubeURL, String? description, + XFile? image) async { + String url = '/blog_post/create'; + final Map credentials = { 'title': title, 'description': description, - 'youtube_url': youtube_url, + 'youtube_url': youtubeURL, 'status': 'active', + 'image': image, }; - var response = await http.post( - Uri.parse(url), - headers: { - 'Content-Type': 'application/json', - 'Authorization': 'Bearer $token', - }, - body: json.encode(credentials), - encoding: utf8, + var response = await sl().post( + url, + data: json.encode(credentials), ); return response; } FutureOr _uploadImages( - UploadImages event, Emitter emit) {} + UploadImages event, Emitter emit) { + if (state is BlogPostCreateLoadedState) { + var currentState = state as BlogPostCreateLoadedState; + emit( + currentState.copyWith( + image: event.image, + ), + ); + } + } } diff --git a/lib/presentation/feed/blog_post_create_screen/bloc/blog_post_create_state.dart b/lib/presentation/feed/blog_post_create_screen/bloc/blog_post_create_state.dart index 6014e3d..4da3f5a 100644 --- a/lib/presentation/feed/blog_post_create_screen/bloc/blog_post_create_state.dart +++ b/lib/presentation/feed/blog_post_create_screen/bloc/blog_post_create_state.dart @@ -27,33 +27,37 @@ class BlogPostCreateLoadedState extends BlogPostCreateState { this.blog_postModelObj, this.title, this.description, - this.youtube_url, + this.youtubeURL, + this.image, this.isLoading = false, }); BlogPostCreateModel? blog_postModelObj; TextEditingController? title; TextEditingController? description; - TextEditingController? youtube_url; + TextEditingController? youtubeURL; String? token; bool isLoading; + XFile? image; @override List get props => - [blog_postModelObj, title, description, youtube_url]; + [blog_postModelObj, title, description, youtubeURL]; BlogPostCreateLoadedState copyWith({ BlogPostCreateModel? blog_postModelObj, TextEditingController? title, TextEditingController? description, - TextEditingController? youtube_url, + TextEditingController? youtubeURL, String? token, + XFile? image, bool isLoading = false, }) { return BlogPostCreateLoadedState( blog_postModelObj: blog_postModelObj ?? this.blog_postModelObj, title: title ?? this.title, description: description ?? this.description, - youtube_url: youtube_url ?? this.youtube_url, + youtubeURL: youtubeURL ?? this.youtubeURL, token: token ?? this.token, + image: image ?? this.image, isLoading: this.isLoading, ); } diff --git a/lib/presentation/feed/blog_post_create_screen/blog_post_create_screen.dart b/lib/presentation/feed/blog_post_create_screen/blog_post_create_screen.dart index f02a512..225a771 100644 --- a/lib/presentation/feed/blog_post_create_screen/blog_post_create_screen.dart +++ b/lib/presentation/feed/blog_post_create_screen/blog_post_create_screen.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; import 'package:eatvio_app/widgets/custom_text_form_field.dart'; import 'package:eatvio_app/widgets/custom_outlined_button.dart'; +import 'dart:io'; class BlogPostCreateScreen extends StatelessWidget { const BlogPostCreateScreen({Key? key}) : super(key: key); @@ -43,6 +44,7 @@ class BlogPostCreateScreen extends StatelessWidget { } _buildBlogPostCreate(BuildContext context, BlogPostCreateLoadedState state) { + print(state.image); return Scaffold( resizeToAvoidBottomInset: false, body: Container( @@ -85,7 +87,7 @@ class BlogPostCreateScreen extends StatelessWidget { Text("Ссылка на YouTube", style: theme.textTheme.bodyLarge), CustomTextFormField( - controller: state.youtube_url, + controller: state.youtubeURL, validator: _validateYouTubeLink, ), SizedBox(height: 8.0), @@ -101,7 +103,7 @@ class BlogPostCreateScreen extends StatelessWidget { // Add widget for image upload here CustomOutlinedButton( onPressed: () => _submitForm(context, state.title!.text, - state.description!.text, state.youtube_url!.text), + state.description!.text, state.youtubeURL!.text), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, text: 'Создать', ), @@ -144,7 +146,7 @@ _buildAddPhoto(BuildContext context, BlogPostCreateLoadedState state) { onTap: addImage(context, isLoading), child: Stack( children: [ - if (!isLoading) + if (state.image == null) Container( margin: EdgeInsets.symmetric(horizontal: 10.h), padding: EdgeInsets.symmetric( @@ -158,8 +160,6 @@ _buildAddPhoto(BuildContext context, BlogPostCreateLoadedState state) { mainAxisAlignment: MainAxisAlignment.end, mainAxisSize: MainAxisSize.min, children: [ - // Показывайте прелоадер, если загрузка активна - Padding( padding: EdgeInsets.only( left: 7.h, @@ -178,7 +178,7 @@ _buildAddPhoto(BuildContext context, BlogPostCreateLoadedState state) { ], ), ), - if (isLoading) + if (state.image != null) Container( margin: EdgeInsets.symmetric(horizontal: 10.h), padding: EdgeInsets.symmetric( @@ -188,12 +188,8 @@ _buildAddPhoto(BuildContext context, BlogPostCreateLoadedState state) { decoration: AppDecoration.fillGray.copyWith( borderRadius: BorderRadiusStyle.roundedBorder5, ), - child: Center( - child: CircularProgressIndicator( - color: appTheme - .blueGray300), // Замените на свой прелоадер при необходимости - ), - ), + child: Image(image: FileImage(File(state.image!.path))), + ) ], ), ); diff --git a/lib/presentation/feed/blog_post_create_screen/models/blog_post_create_credentials_model.dart b/lib/presentation/feed/blog_post_create_screen/models/blog_post_create_credentials_model.dart new file mode 100644 index 0000000..1464eb0 --- /dev/null +++ b/lib/presentation/feed/blog_post_create_screen/models/blog_post_create_credentials_model.dart @@ -0,0 +1,16 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; +part 'blog_post_create_credentials_model.freezed.dart'; +part 'blog_post_create_credentials_model.g.dart'; + +@freezed +class BlogPostCreateCredentialsModel with _$BlogPostCreateCredentialsModel { + const factory BlogPostCreateCredentialsModel({ + required String title, + required String description, + @JsonKey(name: 'youtube_url') required String youtubeUrl, + @Default('active') String status, + }) = _BlogPostCreateCredentialsModel; + + factory BlogPostCreateCredentialsModel.fromJson(Map json) => + _$BlogPostCreateCredentialsModelFromJson(json); +} diff --git a/lib/presentation/feed/blog_post_create_screen/models/blog_post_create_credentials_model.freezed.dart b/lib/presentation/feed/blog_post_create_screen/models/blog_post_create_credentials_model.freezed.dart new file mode 100644 index 0000000..87eb9e1 --- /dev/null +++ b/lib/presentation/feed/blog_post_create_screen/models/blog_post_create_credentials_model.freezed.dart @@ -0,0 +1,235 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'blog_post_create_credentials_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +BlogPostCreateCredentialsModel _$BlogPostCreateCredentialsModelFromJson( + Map json) { + return _BlogPostCreateCredentialsModel.fromJson(json); +} + +/// @nodoc +mixin _$BlogPostCreateCredentialsModel { + String get title => throw _privateConstructorUsedError; + String get description => throw _privateConstructorUsedError; + @JsonKey(name: 'youtube_url') + String get youtubeUrl => throw _privateConstructorUsedError; + String get status => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $BlogPostCreateCredentialsModelCopyWith + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $BlogPostCreateCredentialsModelCopyWith<$Res> { + factory $BlogPostCreateCredentialsModelCopyWith( + BlogPostCreateCredentialsModel value, + $Res Function(BlogPostCreateCredentialsModel) then) = + _$BlogPostCreateCredentialsModelCopyWithImpl<$Res, + BlogPostCreateCredentialsModel>; + @useResult + $Res call( + {String title, + String description, + @JsonKey(name: 'youtube_url') String youtubeUrl, + String status}); +} + +/// @nodoc +class _$BlogPostCreateCredentialsModelCopyWithImpl<$Res, + $Val extends BlogPostCreateCredentialsModel> + implements $BlogPostCreateCredentialsModelCopyWith<$Res> { + _$BlogPostCreateCredentialsModelCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? title = null, + Object? description = null, + Object? youtubeUrl = null, + Object? status = null, + }) { + return _then(_value.copyWith( + title: null == title + ? _value.title + : title // ignore: cast_nullable_to_non_nullable + as String, + description: null == description + ? _value.description + : description // ignore: cast_nullable_to_non_nullable + as String, + youtubeUrl: null == youtubeUrl + ? _value.youtubeUrl + : youtubeUrl // ignore: cast_nullable_to_non_nullable + as String, + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as String, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$BlogPostCreateCredentialsModelImplCopyWith<$Res> + implements $BlogPostCreateCredentialsModelCopyWith<$Res> { + factory _$$BlogPostCreateCredentialsModelImplCopyWith( + _$BlogPostCreateCredentialsModelImpl value, + $Res Function(_$BlogPostCreateCredentialsModelImpl) then) = + __$$BlogPostCreateCredentialsModelImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String title, + String description, + @JsonKey(name: 'youtube_url') String youtubeUrl, + String status}); +} + +/// @nodoc +class __$$BlogPostCreateCredentialsModelImplCopyWithImpl<$Res> + extends _$BlogPostCreateCredentialsModelCopyWithImpl<$Res, + _$BlogPostCreateCredentialsModelImpl> + implements _$$BlogPostCreateCredentialsModelImplCopyWith<$Res> { + __$$BlogPostCreateCredentialsModelImplCopyWithImpl( + _$BlogPostCreateCredentialsModelImpl _value, + $Res Function(_$BlogPostCreateCredentialsModelImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? title = null, + Object? description = null, + Object? youtubeUrl = null, + Object? status = null, + }) { + return _then(_$BlogPostCreateCredentialsModelImpl( + title: null == title + ? _value.title + : title // ignore: cast_nullable_to_non_nullable + as String, + description: null == description + ? _value.description + : description // ignore: cast_nullable_to_non_nullable + as String, + youtubeUrl: null == youtubeUrl + ? _value.youtubeUrl + : youtubeUrl // ignore: cast_nullable_to_non_nullable + as String, + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$BlogPostCreateCredentialsModelImpl + implements _BlogPostCreateCredentialsModel { + const _$BlogPostCreateCredentialsModelImpl( + {required this.title, + required this.description, + @JsonKey(name: 'youtube_url') required this.youtubeUrl, + this.status = 'active'}); + + factory _$BlogPostCreateCredentialsModelImpl.fromJson( + Map json) => + _$$BlogPostCreateCredentialsModelImplFromJson(json); + + @override + final String title; + @override + final String description; + @override + @JsonKey(name: 'youtube_url') + final String youtubeUrl; + @override + @JsonKey() + final String status; + + @override + String toString() { + return 'BlogPostCreateCredentialsModel(title: $title, description: $description, youtubeUrl: $youtubeUrl, status: $status)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$BlogPostCreateCredentialsModelImpl && + (identical(other.title, title) || other.title == title) && + (identical(other.description, description) || + other.description == description) && + (identical(other.youtubeUrl, youtubeUrl) || + other.youtubeUrl == youtubeUrl) && + (identical(other.status, status) || other.status == status)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => + Object.hash(runtimeType, title, description, youtubeUrl, status); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$BlogPostCreateCredentialsModelImplCopyWith< + _$BlogPostCreateCredentialsModelImpl> + get copyWith => __$$BlogPostCreateCredentialsModelImplCopyWithImpl< + _$BlogPostCreateCredentialsModelImpl>(this, _$identity); + + @override + Map toJson() { + return _$$BlogPostCreateCredentialsModelImplToJson( + this, + ); + } +} + +abstract class _BlogPostCreateCredentialsModel + implements BlogPostCreateCredentialsModel { + const factory _BlogPostCreateCredentialsModel( + {required final String title, + required final String description, + @JsonKey(name: 'youtube_url') required final String youtubeUrl, + final String status}) = _$BlogPostCreateCredentialsModelImpl; + + factory _BlogPostCreateCredentialsModel.fromJson(Map json) = + _$BlogPostCreateCredentialsModelImpl.fromJson; + + @override + String get title; + @override + String get description; + @override + @JsonKey(name: 'youtube_url') + String get youtubeUrl; + @override + String get status; + @override + @JsonKey(ignore: true) + _$$BlogPostCreateCredentialsModelImplCopyWith< + _$BlogPostCreateCredentialsModelImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/presentation/feed/blog_post_create_screen/models/blog_post_create_credentials_model.g.dart b/lib/presentation/feed/blog_post_create_screen/models/blog_post_create_credentials_model.g.dart new file mode 100644 index 0000000..bf339e9 --- /dev/null +++ b/lib/presentation/feed/blog_post_create_screen/models/blog_post_create_credentials_model.g.dart @@ -0,0 +1,25 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'blog_post_create_credentials_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$BlogPostCreateCredentialsModelImpl + _$$BlogPostCreateCredentialsModelImplFromJson(Map json) => + _$BlogPostCreateCredentialsModelImpl( + title: json['title'] as String, + description: json['description'] as String, + youtubeUrl: json['youtube_url'] as String, + status: json['status'] as String? ?? 'active', + ); + +Map _$$BlogPostCreateCredentialsModelImplToJson( + _$BlogPostCreateCredentialsModelImpl instance) => + { + 'title': instance.title, + 'description': instance.description, + 'youtube_url': instance.youtubeUrl, + 'status': instance.status, + }; diff --git a/lib/presentation/feed/blog_post_create_screen/repositories/blog_repository.dart b/lib/presentation/feed/blog_post_create_screen/repositories/blog_repository.dart new file mode 100644 index 0000000..74f79cd --- /dev/null +++ b/lib/presentation/feed/blog_post_create_screen/repositories/blog_repository.dart @@ -0,0 +1,20 @@ +import 'package:eatvio_app/presentation/feed/blog_post_create_screen/models/blog_post_create_credentials_model.dart'; +import 'package:eatvio_app/presentation/feed/blog_post_create_screen/services/blog_service.dart'; + +class BlogRepository { + final BlogService blogService; + + BlogRepository({ + required this.blogService, + }); + + Future createBlogPost( + BlogPostCreateCredentialsModel model) async { + try { + return (await blogService.createBlogPost(model)); + } catch (e) { + print(e); + throw (e); + } + } +} diff --git a/lib/presentation/feed/blog_post_create_screen/services/blog_service.dart b/lib/presentation/feed/blog_post_create_screen/services/blog_service.dart new file mode 100644 index 0000000..e559383 --- /dev/null +++ b/lib/presentation/feed/blog_post_create_screen/services/blog_service.dart @@ -0,0 +1,14 @@ +import 'package:eatvio_app/presentation/feed/blog_post_create_screen/models/blog_post_create_credentials_model.dart'; +import 'package:dio/dio.dart'; +import 'package:retrofit/retrofit.dart'; + +part 'blog_service.g.dart'; + +@RestApi() +abstract class BlogService { + factory BlogService(Dio dio, {String baseUrl}) = _BlogService; + + @POST('/blog_post/create') + Future createBlogPost( + BlogPostCreateCredentialsModel model); +} diff --git a/lib/presentation/feed/blog_post_create_screen/services/blog_service.g.dart b/lib/presentation/feed/blog_post_create_screen/services/blog_service.g.dart new file mode 100644 index 0000000..eef2fc9 --- /dev/null +++ b/lib/presentation/feed/blog_post_create_screen/services/blog_service.g.dart @@ -0,0 +1,78 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'blog_service.dart'; + +// ************************************************************************** +// RetrofitGenerator +// ************************************************************************** + +// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers + +class _BlogService implements BlogService { + _BlogService( + this._dio, { + this.baseUrl, + }); + + final Dio _dio; + + String? baseUrl; + + @override + Future createBlogPost( + BlogPostCreateCredentialsModel model) async { + final _extra = {}; + final queryParameters = {}; + final _headers = {}; + const Map? _data = null; + final _result = await _dio.fetch>( + _setStreamType(Options( + method: 'POST', + headers: _headers, + extra: _extra, + ) + .compose( + _dio.options, + '/blog_post/create', + queryParameters: queryParameters, + data: _data, + ) + .copyWith( + baseUrl: _combineBaseUrls( + _dio.options.baseUrl, + baseUrl, + )))); + final value = BlogPostCreateCredentialsModel.fromJson(_result.data!); + return value; + } + + RequestOptions _setStreamType(RequestOptions requestOptions) { + if (T != dynamic && + !(requestOptions.responseType == ResponseType.bytes || + requestOptions.responseType == ResponseType.stream)) { + if (T == String) { + requestOptions.responseType = ResponseType.plain; + } else { + requestOptions.responseType = ResponseType.json; + } + } + return requestOptions; + } + + String _combineBaseUrls( + String dioBaseUrl, + String? baseUrl, + ) { + if (baseUrl == null || baseUrl.trim().isEmpty) { + return dioBaseUrl; + } + + final url = Uri.parse(baseUrl); + + if (url.isAbsolute) { + return url.toString(); + } + + return Uri.parse(dioBaseUrl).resolveUri(url).toString(); + } +} diff --git a/lib/presentation/feed/blog_post_edit_screen/bloc/blog_post_edit_bloc.dart b/lib/presentation/feed/blog_post_edit_screen/bloc/blog_post_edit_bloc.dart index 6b45f84..07dc31c 100644 --- a/lib/presentation/feed/blog_post_edit_screen/bloc/blog_post_edit_bloc.dart +++ b/lib/presentation/feed/blog_post_edit_screen/bloc/blog_post_edit_bloc.dart @@ -44,22 +44,29 @@ class BlogPostEditBloc extends Bloc { if (data is Map) { if (state is BlogPostEditLoadedState) { var currentState = state as BlogPostEditLoadedState; - emit(currentState.copyWith( + emit( + currentState.copyWith( blog_postModelObj: currentState.blog_postModelObj, blog_post: currentState.blog_post, title: currentState.title, description: currentState.description, - youtube_url: currentState.youtube_url,),); + youtubeURL: currentState.youtubeURL, + ), + ); } else { - emit(BlogPostEditLoadedState( + emit( + BlogPostEditLoadedState( blog_post: data, title: TextEditingController(text: data['title']), description: TextEditingController(text: data['description']), - youtube_url: TextEditingController(text: data['youtube_url']),),); + youtubeURL: TextEditingController(text: data['youtubeURL']), + ), + ); } } else { // Один или несколько ключевых полей отсутствуют, обрабатываем ошибку - emit(BlogPostEditErrorState('Некоторые необходимые данные отсутствуют.')); + emit(BlogPostEditErrorState( + 'Некоторые необходимые данные отсутствуют.')); } } else { // Статус ответа не равен 200, обрабатываем ошибку @@ -71,21 +78,24 @@ class BlogPostEditBloc extends Bloc { } } - FutureOr _editBlogPost(EditBlogPost event, Emitter emit) async { + FutureOr _editBlogPost( + EditBlogPost event, Emitter emit) async { if (state is BlogPostEditLoadedState) { var currentState = state as BlogPostEditLoadedState; var response = await sendBlogPost( currentState.blog_post, currentState.title?.text, - currentState.youtube_url?.text, + currentState.youtubeURL?.text, currentState.description?.text, ); if (response.statusCode == 200) { - AppRouter.navigatorKey.currentContext?.goNamed('blogPostScreen', extra: currentState.blog_post?['id'].toString()); + AppRouter.navigatorKey.currentContext?.goNamed('blogPostScreen', + extra: currentState.blog_post?['id'].toString()); } else { - print('Failed to edit blog post. Status Code: ${response.statusCode} ${response.body}'); + print( + 'Failed to edit blog post. Status Code: ${response.statusCode} ${response.body}'); } } } @@ -93,7 +103,7 @@ class BlogPostEditBloc extends Bloc { FutureOr sendBlogPost( Map? blog_post, String? title, - String? youtube_url, + String? youtubeURL, String? description, ) async { int id = blog_post?['id']; @@ -103,7 +113,7 @@ class BlogPostEditBloc extends Bloc { 'id': id, 'title': title, 'description': description, - 'youtube_url': youtube_url, + 'youtubeURL': youtubeURL, }; var response = await http.post( diff --git a/lib/presentation/feed/blog_post_edit_screen/bloc/blog_post_edit_state.dart b/lib/presentation/feed/blog_post_edit_screen/bloc/blog_post_edit_state.dart index 4381948..cc2d5f3 100644 --- a/lib/presentation/feed/blog_post_edit_screen/bloc/blog_post_edit_state.dart +++ b/lib/presentation/feed/blog_post_edit_screen/bloc/blog_post_edit_state.dart @@ -22,34 +22,35 @@ class BlogPostEditState extends Equatable { } class BlogPostEditLoadedState extends BlogPostEditState { - BlogPostEditLoadedState( - {this.blog_postModelObj, - this.blog_post, - this.title, - this.description, - this.youtube_url,}); + BlogPostEditLoadedState({ + this.blog_postModelObj, + this.blog_post, + this.title, + this.description, + this.youtubeURL, + }); BlogPostEditModel? blog_postModelObj; Map? blog_post; TextEditingController? title; TextEditingController? description; - TextEditingController? youtube_url; + TextEditingController? youtubeURL; @override List get props => - [blog_postModelObj, blog_post, title, description, youtube_url]; + [blog_postModelObj, blog_post, title, description, youtubeURL]; BlogPostEditLoadedState copyWith({ BlogPostEditModel? blog_postModelObj, Map? blog_post, TextEditingController? title, TextEditingController? description, - TextEditingController? youtube_url, + TextEditingController? youtubeURL, }) { return BlogPostEditLoadedState( blog_postModelObj: blog_postModelObj ?? this.blog_postModelObj, blog_post: blog_post ?? this.blog_post, title: title ?? this.title, description: description ?? this.description, - youtube_url: youtube_url ?? this.youtube_url, + youtubeURL: youtubeURL ?? this.youtubeURL, ); } } diff --git a/lib/presentation/feed/blog_post_edit_screen/blog_post_edit_screen.dart b/lib/presentation/feed/blog_post_edit_screen/blog_post_edit_screen.dart index 6af1c51..7012a55 100644 --- a/lib/presentation/feed/blog_post_edit_screen/blog_post_edit_screen.dart +++ b/lib/presentation/feed/blog_post_edit_screen/blog_post_edit_screen.dart @@ -10,9 +10,12 @@ class BlogPostEditScreen extends StatelessWidget { static Widget builder(BuildContext context, blog_postID) { return BlocProvider( - create: (context) => - BlogPostEditBloc(BlogPostEditState(blog_postModelObj: BlogPostEditModel(blog_postID: blog_postID.toString())))..add(BlogPostEditInitialEvent()), - child: BlogPostEditScreen(),); + create: (context) => BlogPostEditBloc(BlogPostEditState( + blog_postModelObj: + BlogPostEditModel(blog_postID: blog_postID.toString()))) + ..add(BlogPostEditInitialEvent()), + child: BlogPostEditScreen(), + ); } Widget build(BuildContext context) { @@ -74,7 +77,8 @@ class BlogPostEditScreen extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ CachedNetworkImage( - imageUrl: dotenv.env['STORAGE_URL']! + (state.blog_post?['image'] ?? ''), + imageUrl: dotenv.env['STORAGE_URL']! + + (state.blog_post?['image'] ?? ''), imageBuilder: (context, imageProvider) => CircleAvatar( backgroundImage: imageProvider, radius: 25, @@ -98,13 +102,14 @@ class BlogPostEditScreen extends StatelessWidget { ), SizedBox(height: 16.0), TextFormField( - controller: state.youtube_url, + controller: state.youtubeURL, decoration: InputDecoration(labelText: 'Ссылка'), ), SizedBox(height: 16.0), // Здесь нужно добавить виджет для загрузки картинки ElevatedButton( - onPressed: () => context.read().add(EditBlogPost()), + onPressed: () => + context.read().add(EditBlogPost()), child: Text('Сохранить'), ), ],