fix(blogPost): create

This commit is contained in:
mso7nueh
2024-11-20 12:11:37 +03:00
parent 1ac956b448
commit a007e53aae
9 changed files with 756 additions and 90 deletions

View File

@@ -0,0 +1,28 @@
import 'package:eatvio_app/features/blog_post_create/bloc/blog_post_create_cubit/blog_post_create_state.dart';
import 'package:eatvio_app/features/blog_post_create/repositories/blog_post_repository.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
class BlogPostCreateCubit extends Cubit<BlogPostCreateState> {
final BlogPostRepository blogPostRepository;
BlogPostCreateCubit({
required this.blogPostRepository,
}) : super(BlogPostCreateState());
createBlogPost({
String? title,
String? youtubeURL,
String? description,
XFile? image,
}) async {
emit(BlogPostCreateState.loading());
await blogPostRepository.createBlogPost(
title,
youtubeURL,
description,
image,
);
emit(BlogPostCreateState.loaded());
}
}

View File

@@ -0,0 +1,16 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'blog_post_create_state.freezed.dart';
@freezed
abstract class BlogPostCreateState with _$BlogPostCreateState {
const factory BlogPostCreateState() = _BlogPostCreateState;
const factory BlogPostCreateState.loading() = BlogPostCreateStateLoading;
const factory BlogPostCreateState.loaded() = BlogPostCreateStateLoaded;
const factory BlogPostCreateState.error({
required String errorMessage,
}) = BlogPostCreateStateError;
}

View File

@@ -0,0 +1,608 @@
// 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_state.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(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');
/// @nodoc
mixin _$BlogPostCreateState {
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function() loading,
required TResult Function() loaded,
required TResult Function(String errorMessage) error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function()? loaded,
TResult? Function(String errorMessage)? error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function()? loading,
TResult Function()? loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_BlogPostCreateState value) $default, {
required TResult Function(BlogPostCreateStateLoading value) loading,
required TResult Function(BlogPostCreateStateLoaded value) loaded,
required TResult Function(BlogPostCreateStateError value) error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_BlogPostCreateState value)? $default, {
TResult? Function(BlogPostCreateStateLoading value)? loading,
TResult? Function(BlogPostCreateStateLoaded value)? loaded,
TResult? Function(BlogPostCreateStateError value)? error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_BlogPostCreateState value)? $default, {
TResult Function(BlogPostCreateStateLoading value)? loading,
TResult Function(BlogPostCreateStateLoaded value)? loaded,
TResult Function(BlogPostCreateStateError value)? error,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $BlogPostCreateStateCopyWith<$Res> {
factory $BlogPostCreateStateCopyWith(
BlogPostCreateState value, $Res Function(BlogPostCreateState) then) =
_$BlogPostCreateStateCopyWithImpl<$Res, BlogPostCreateState>;
}
/// @nodoc
class _$BlogPostCreateStateCopyWithImpl<$Res, $Val extends BlogPostCreateState>
implements $BlogPostCreateStateCopyWith<$Res> {
_$BlogPostCreateStateCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of BlogPostCreateState
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
abstract class _$$BlogPostCreateStateImplCopyWith<$Res> {
factory _$$BlogPostCreateStateImplCopyWith(_$BlogPostCreateStateImpl value,
$Res Function(_$BlogPostCreateStateImpl) then) =
__$$BlogPostCreateStateImplCopyWithImpl<$Res>;
}
/// @nodoc
class __$$BlogPostCreateStateImplCopyWithImpl<$Res>
extends _$BlogPostCreateStateCopyWithImpl<$Res, _$BlogPostCreateStateImpl>
implements _$$BlogPostCreateStateImplCopyWith<$Res> {
__$$BlogPostCreateStateImplCopyWithImpl(_$BlogPostCreateStateImpl _value,
$Res Function(_$BlogPostCreateStateImpl) _then)
: super(_value, _then);
/// Create a copy of BlogPostCreateState
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
class _$BlogPostCreateStateImpl implements _BlogPostCreateState {
const _$BlogPostCreateStateImpl();
@override
String toString() {
return 'BlogPostCreateState()';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$BlogPostCreateStateImpl);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function() loading,
required TResult Function() loaded,
required TResult Function(String errorMessage) error,
}) {
return $default();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function()? loaded,
TResult? Function(String errorMessage)? error,
}) {
return $default?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function()? loading,
TResult Function()? loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) {
if ($default != null) {
return $default();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_BlogPostCreateState value) $default, {
required TResult Function(BlogPostCreateStateLoading value) loading,
required TResult Function(BlogPostCreateStateLoaded value) loaded,
required TResult Function(BlogPostCreateStateError value) error,
}) {
return $default(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_BlogPostCreateState value)? $default, {
TResult? Function(BlogPostCreateStateLoading value)? loading,
TResult? Function(BlogPostCreateStateLoaded value)? loaded,
TResult? Function(BlogPostCreateStateError value)? error,
}) {
return $default?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_BlogPostCreateState value)? $default, {
TResult Function(BlogPostCreateStateLoading value)? loading,
TResult Function(BlogPostCreateStateLoaded value)? loaded,
TResult Function(BlogPostCreateStateError value)? error,
required TResult orElse(),
}) {
if ($default != null) {
return $default(this);
}
return orElse();
}
}
abstract class _BlogPostCreateState implements BlogPostCreateState {
const factory _BlogPostCreateState() = _$BlogPostCreateStateImpl;
}
/// @nodoc
abstract class _$$BlogPostCreateStateLoadingImplCopyWith<$Res> {
factory _$$BlogPostCreateStateLoadingImplCopyWith(
_$BlogPostCreateStateLoadingImpl value,
$Res Function(_$BlogPostCreateStateLoadingImpl) then) =
__$$BlogPostCreateStateLoadingImplCopyWithImpl<$Res>;
}
/// @nodoc
class __$$BlogPostCreateStateLoadingImplCopyWithImpl<$Res>
extends _$BlogPostCreateStateCopyWithImpl<$Res,
_$BlogPostCreateStateLoadingImpl>
implements _$$BlogPostCreateStateLoadingImplCopyWith<$Res> {
__$$BlogPostCreateStateLoadingImplCopyWithImpl(
_$BlogPostCreateStateLoadingImpl _value,
$Res Function(_$BlogPostCreateStateLoadingImpl) _then)
: super(_value, _then);
/// Create a copy of BlogPostCreateState
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
class _$BlogPostCreateStateLoadingImpl implements BlogPostCreateStateLoading {
const _$BlogPostCreateStateLoadingImpl();
@override
String toString() {
return 'BlogPostCreateState.loading()';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$BlogPostCreateStateLoadingImpl);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function() loading,
required TResult Function() loaded,
required TResult Function(String errorMessage) error,
}) {
return loading();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function()? loaded,
TResult? Function(String errorMessage)? error,
}) {
return loading?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function()? loading,
TResult Function()? loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) {
if (loading != null) {
return loading();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_BlogPostCreateState value) $default, {
required TResult Function(BlogPostCreateStateLoading value) loading,
required TResult Function(BlogPostCreateStateLoaded value) loaded,
required TResult Function(BlogPostCreateStateError value) error,
}) {
return loading(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_BlogPostCreateState value)? $default, {
TResult? Function(BlogPostCreateStateLoading value)? loading,
TResult? Function(BlogPostCreateStateLoaded value)? loaded,
TResult? Function(BlogPostCreateStateError value)? error,
}) {
return loading?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_BlogPostCreateState value)? $default, {
TResult Function(BlogPostCreateStateLoading value)? loading,
TResult Function(BlogPostCreateStateLoaded value)? loaded,
TResult Function(BlogPostCreateStateError value)? error,
required TResult orElse(),
}) {
if (loading != null) {
return loading(this);
}
return orElse();
}
}
abstract class BlogPostCreateStateLoading implements BlogPostCreateState {
const factory BlogPostCreateStateLoading() = _$BlogPostCreateStateLoadingImpl;
}
/// @nodoc
abstract class _$$BlogPostCreateStateLoadedImplCopyWith<$Res> {
factory _$$BlogPostCreateStateLoadedImplCopyWith(
_$BlogPostCreateStateLoadedImpl value,
$Res Function(_$BlogPostCreateStateLoadedImpl) then) =
__$$BlogPostCreateStateLoadedImplCopyWithImpl<$Res>;
}
/// @nodoc
class __$$BlogPostCreateStateLoadedImplCopyWithImpl<$Res>
extends _$BlogPostCreateStateCopyWithImpl<$Res,
_$BlogPostCreateStateLoadedImpl>
implements _$$BlogPostCreateStateLoadedImplCopyWith<$Res> {
__$$BlogPostCreateStateLoadedImplCopyWithImpl(
_$BlogPostCreateStateLoadedImpl _value,
$Res Function(_$BlogPostCreateStateLoadedImpl) _then)
: super(_value, _then);
/// Create a copy of BlogPostCreateState
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
class _$BlogPostCreateStateLoadedImpl implements BlogPostCreateStateLoaded {
const _$BlogPostCreateStateLoadedImpl();
@override
String toString() {
return 'BlogPostCreateState.loaded()';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$BlogPostCreateStateLoadedImpl);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function() loading,
required TResult Function() loaded,
required TResult Function(String errorMessage) error,
}) {
return loaded();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function()? loaded,
TResult? Function(String errorMessage)? error,
}) {
return loaded?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function()? loading,
TResult Function()? loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) {
if (loaded != null) {
return loaded();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_BlogPostCreateState value) $default, {
required TResult Function(BlogPostCreateStateLoading value) loading,
required TResult Function(BlogPostCreateStateLoaded value) loaded,
required TResult Function(BlogPostCreateStateError value) error,
}) {
return loaded(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_BlogPostCreateState value)? $default, {
TResult? Function(BlogPostCreateStateLoading value)? loading,
TResult? Function(BlogPostCreateStateLoaded value)? loaded,
TResult? Function(BlogPostCreateStateError value)? error,
}) {
return loaded?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_BlogPostCreateState value)? $default, {
TResult Function(BlogPostCreateStateLoading value)? loading,
TResult Function(BlogPostCreateStateLoaded value)? loaded,
TResult Function(BlogPostCreateStateError value)? error,
required TResult orElse(),
}) {
if (loaded != null) {
return loaded(this);
}
return orElse();
}
}
abstract class BlogPostCreateStateLoaded implements BlogPostCreateState {
const factory BlogPostCreateStateLoaded() = _$BlogPostCreateStateLoadedImpl;
}
/// @nodoc
abstract class _$$BlogPostCreateStateErrorImplCopyWith<$Res> {
factory _$$BlogPostCreateStateErrorImplCopyWith(
_$BlogPostCreateStateErrorImpl value,
$Res Function(_$BlogPostCreateStateErrorImpl) then) =
__$$BlogPostCreateStateErrorImplCopyWithImpl<$Res>;
@useResult
$Res call({String errorMessage});
}
/// @nodoc
class __$$BlogPostCreateStateErrorImplCopyWithImpl<$Res>
extends _$BlogPostCreateStateCopyWithImpl<$Res,
_$BlogPostCreateStateErrorImpl>
implements _$$BlogPostCreateStateErrorImplCopyWith<$Res> {
__$$BlogPostCreateStateErrorImplCopyWithImpl(
_$BlogPostCreateStateErrorImpl _value,
$Res Function(_$BlogPostCreateStateErrorImpl) _then)
: super(_value, _then);
/// Create a copy of BlogPostCreateState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? errorMessage = null,
}) {
return _then(_$BlogPostCreateStateErrorImpl(
errorMessage: null == errorMessage
? _value.errorMessage
: errorMessage // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
class _$BlogPostCreateStateErrorImpl implements BlogPostCreateStateError {
const _$BlogPostCreateStateErrorImpl({required this.errorMessage});
@override
final String errorMessage;
@override
String toString() {
return 'BlogPostCreateState.error(errorMessage: $errorMessage)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$BlogPostCreateStateErrorImpl &&
(identical(other.errorMessage, errorMessage) ||
other.errorMessage == errorMessage));
}
@override
int get hashCode => Object.hash(runtimeType, errorMessage);
/// Create a copy of BlogPostCreateState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$BlogPostCreateStateErrorImplCopyWith<_$BlogPostCreateStateErrorImpl>
get copyWith => __$$BlogPostCreateStateErrorImplCopyWithImpl<
_$BlogPostCreateStateErrorImpl>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function() loading,
required TResult Function() loaded,
required TResult Function(String errorMessage) error,
}) {
return error(errorMessage);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function()? loaded,
TResult? Function(String errorMessage)? error,
}) {
return error?.call(errorMessage);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function()? loading,
TResult Function()? loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) {
if (error != null) {
return error(errorMessage);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_BlogPostCreateState value) $default, {
required TResult Function(BlogPostCreateStateLoading value) loading,
required TResult Function(BlogPostCreateStateLoaded value) loaded,
required TResult Function(BlogPostCreateStateError value) error,
}) {
return error(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_BlogPostCreateState value)? $default, {
TResult? Function(BlogPostCreateStateLoading value)? loading,
TResult? Function(BlogPostCreateStateLoaded value)? loaded,
TResult? Function(BlogPostCreateStateError value)? error,
}) {
return error?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_BlogPostCreateState value)? $default, {
TResult Function(BlogPostCreateStateLoading value)? loading,
TResult Function(BlogPostCreateStateLoaded value)? loaded,
TResult Function(BlogPostCreateStateError value)? error,
required TResult orElse(),
}) {
if (error != null) {
return error(this);
}
return orElse();
}
}
abstract class BlogPostCreateStateError implements BlogPostCreateState {
const factory BlogPostCreateStateError({required final String errorMessage}) =
_$BlogPostCreateStateErrorImpl;
String get errorMessage;
/// Create a copy of BlogPostCreateState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
_$$BlogPostCreateStateErrorImplCopyWith<_$BlogPostCreateStateErrorImpl>
get copyWith => throw _privateConstructorUsedError;
}

View File

@@ -1,6 +1,8 @@
import 'dart:async';
import 'dart:io';
import 'package:eatvio_app/old/feed/blog_post_create_screen/bloc/blog_post_create_bloc.dart';
import 'package:eatvio_app/features/blog_post_create/bloc/blog_post_create_cubit/blog_post_create_cubit.dart';
import 'package:eatvio_app/features/blog_post_create/bloc/blog_post_create_cubit/blog_post_create_state.dart';
import 'package:eatvio_app/locator_service.dart';
import 'package:eatvio_app/theme/app_decoration.dart';
import 'package:eatvio_app/theme/theme_helper.dart';
import 'package:eatvio_app/widgets/custom_text_form_field.dart';
@@ -8,19 +10,27 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
import 'package:go_router/go_router.dart';
import 'package:image_picker/image_picker.dart';
class BlogPostCreateScreen extends StatefulWidget {
const BlogPostCreateScreen({Key? key}) : super(key: key);
const BlogPostCreateScreen({
Key? key,
}) : super(key: key);
@override
State<BlogPostCreateScreen> createState() => _BlogPostCreateScreenState();
}
class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
final blogPostCreateBloc = BlogPostCreateBloc(BlogPostCreateState())..add(BlogPostCreateInitialEvent());
final blogPostCubit = sl<BlogPostCreateCubit>();
bool shrinkImage = false;
late StreamSubscription<bool> keyboardSubscription;
XFile? image;
final titleController = TextEditingController();
final descriptionController = TextEditingController();
final youtubeUrlController = TextEditingController();
bool isLoading = false;
@override
void initState() {
@@ -40,26 +50,15 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
}
Widget build(BuildContext context) {
return BlocProvider<BlogPostCreateBloc>(
create: (BuildContext context) => blogPostCreateBloc,
child: BlocBuilder<BlogPostCreateBloc, BlogPostCreateState>(
builder: (context, state) {
if (state is BlogPostCreateInitialState) {
// Это начальное состояние, данные ещё не загружены.
return Container(
color: Colors.white,
);
} else if (state is BlogPostCreateLoadedState) {
// Данные загружены, можно строить экран.
return _buildBlogPostCreate(context, state);
} else if (state is BlogPostCreateErrorState) {
// Произошла ошибка при загрузке данных.
return Center(child: Text(state.errorMessage));
} else {
// Другие состояния, если они есть.
return Container(); // Пустой контейнер для необработанных состояний.
return BlocProvider<BlogPostCreateCubit>(
create: (BuildContext context) => blogPostCubit,
child: BlocListener<BlogPostCreateCubit, BlogPostCreateState>(
listener: (BuildContext context, BlogPostCreateState state) {
if (state is BlogPostCreateStateLoaded) {
GoRouter.of(context).pop();
}
},
child: _buildBlogPostCreate(),
),
);
}
@@ -72,8 +71,8 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
CupertinoActionSheetAction(
onPressed: () async {
final picker = ImagePicker();
XFile? image = await picker.pickImage(source: ImageSource.camera);
if (image != null) blogPostCreateBloc.add(UploadImages(image));
image = await picker.pickImage(source: ImageSource.camera);
setState(() {});
Navigator.of(context).pop();
},
child: const Row(
@@ -87,8 +86,8 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
CupertinoActionSheetAction(
onPressed: () async {
final picker = ImagePicker();
XFile? image = await picker.pickImage(source: ImageSource.gallery);
if (image != null) blogPostCreateBloc.add(UploadImages(image));
image = await picker.pickImage(source: ImageSource.gallery);
setState(() {});
Navigator.of(context).pop();
},
child: const Row(
@@ -109,7 +108,7 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
);
}
_buildBlogPostCreate(BuildContext context, BlogPostCreateLoadedState state) {
_buildBlogPostCreate() {
return Scaffold(
resizeToAvoidBottomInset: true,
appBar: AppBar(),
@@ -125,13 +124,27 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
borderRadius: BorderRadius.circular(16),
),
backgroundColor: appTheme.blueA400,
onPressed: () => _submitForm(context, state.title!.text, state.description!.text, state.youtubeURL!.text),
label: Text(
'Создать',
style: TextStyle(
color: Colors.white,
),
),
label: isLoading
? CircularProgressIndicator()
: Text(
'Создать',
style: TextStyle(
color: Colors.white,
),
),
onPressed: isLoading
? null
: () {
setState(() {
isLoading = true;
});
blogPostCubit.createBlogPost(
title: titleController.text,
description: descriptionController.text,
youtubeURL: youtubeUrlController.text,
image: image,
);
},
),
),
body: SingleChildScrollView(
@@ -143,26 +156,26 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
Text('Заголовок'),
SizedBox(height: 8),
CustomTextFormField(
controller: state.title,
controller: titleController,
),
SizedBox(height: 16),
Text('Описание'),
SizedBox(height: 8),
CustomTextFormField(
controller: state.description,
controller: descriptionController,
maxLines: 6,
minLines: 4,
),
SizedBox(height: 16),
if (state.youtubeURL!.text.isEmpty) Text('Изображение поста'),
if (state.youtubeURL!.text.isEmpty) SizedBox(height: 8),
if (state.youtubeURL!.text.isEmpty) _buildAddPhoto(state),
if (youtubeUrlController.text.isEmpty) Text('Изображение поста'),
if (youtubeUrlController.text.isEmpty) SizedBox(height: 8),
if (youtubeUrlController.text.isEmpty) _buildAddPhoto(),
SizedBox(height: 16),
if (state.image == null) Text('Ссылка на видео'),
if (state.image == null) SizedBox(height: 8),
if (state.image == null)
if (image == null) Text('Ссылка на видео'),
if (image == null) SizedBox(height: 8),
if (image == null)
CustomTextFormField(
controller: state.youtubeURL,
controller: youtubeUrlController,
),
SizedBox(height: 80),
],
@@ -171,14 +184,14 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
);
}
_buildAddPhoto(BlogPostCreateLoadedState state) {
bool isLoading = state.isLoading;
_buildAddPhoto() {
return GestureDetector(
onTap: addImage(context, isLoading),
onTap: () {
_showImagePicker();
},
child: Stack(
children: [
if (state.image == null)
if (image == null)
AnimatedContainer(
height: shrinkImage ? 52 : 128,
curve: Curves.easeIn,
@@ -202,7 +215,7 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
],
),
),
if (state.image != null)
if (image != null)
Container(
width: shrinkImage ? 52 : MediaQuery.of(context).size.width - 32,
child: ClipRRect(
@@ -210,7 +223,7 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
child: Image(
image: FileImage(
File(
state.image!.path,
image!.path,
),
),
),
@@ -220,21 +233,4 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
),
);
}
addImage(BuildContext context, bool isLoading) {
if (!isLoading) {
return () {
_showImagePicker();
};
}
}
}
_submitForm(
BuildContext context,
String title,
String description,
String youtubeURL,
) async {
context.read<BlogPostCreateBloc>().add(CreateBlogPost());
}

View File

@@ -0,0 +1,32 @@
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:eatvio_app/core/image_compressing/image_compress_utility.dart';
import 'package:eatvio_app/features/blog_post_create/services/blog_post_service.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
class BlogPostRepository {
final BlogPostService blogPostService;
BlogPostRepository({
required this.blogPostService,
});
Future<void> createBlogPost(
String? title,
String? youtubeURL,
String? description,
XFile? image,
) async {
FormData formData = FormData.fromMap({
'title': title,
'description': description,
'state': 'active',
'youtube_url': youtubeURL,
'image': image != null ? await MultipartFile.fromFile((await ImageCompressUtility.compressFile(File(image.path))).path, filename: image.name) : null,
});
return await blogPostService.createBlogPost(
formData: formData,
);
}
}

View File

@@ -9,11 +9,7 @@ abstract class BlogPostService {
@POST('/api/blogPosts/create')
@MultiPart()
Future<void> sendMessage({
@Path() String? title,
@Path() required String state,
@Path() String? description,
@Part() String? youtube_url,
@Part(name: 'image', contentType: 'multipart/form-data') List<MultipartFile>? media_data,
Future<void> createBlogPost({
@Body() required FormData formData,
});
}

View File

@@ -22,27 +22,11 @@ class _BlogPostService implements BlogPostService {
final ParseErrorLogger? errorLogger;
@override
Future<void> sendMessage({
String? title,
required String state,
String? description,
String? youtube_url,
List<MultipartFile>? media_data,
}) async {
Future<void> createBlogPost({required FormData formData}) async {
final _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
queryParameters.removeWhere((k, v) => v == null);
final _headers = <String, dynamic>{};
final _data = FormData();
if (youtube_url != null) {
_data.fields.add(MapEntry(
'youtube_url',
youtube_url,
));
}
if (media_data != null) {
_data.files.addAll(media_data.map((i) => MapEntry('image', i)));
}
final _data = formData;
final _options = _setStreamType<void>(Options(
method: 'POST',
headers: _headers,

View File

@@ -3,6 +3,9 @@ import 'package:eatvio_app/core/const.dart';
import 'package:eatvio_app/core/data/diet/repositories/diet_repository.dart';
import 'package:eatvio_app/core/data/diet/services/diet_service.dart';
import 'package:eatvio_app/core/initialization_cubit/initialization_cubit.dart';
import 'package:eatvio_app/features/blog_post_create/bloc/blog_post_create_cubit/blog_post_create_cubit.dart';
import 'package:eatvio_app/features/blog_post_create/repositories/blog_post_repository.dart';
import 'package:eatvio_app/features/blog_post_create/services/blog_post_service.dart';
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/new_messages_cubit/new_messages_cubit.dart';
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/notifications_cubit/notifications_cubit.dart';
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_cubit.dart';
@@ -70,6 +73,7 @@ Future<void> init() async {
sl.registerFactory<RegisterConsultantCubit>(() => RegisterConsultantCubit(consultantRepository: sl()));
sl.registerFactory<DiaryCubit>(() => DiaryCubit(diaryRepository: sl(), glossaryRepository: sl()));
sl.registerFactory<AboutDietCubit>(() => AboutDietCubit(dietsRepository: sl()));
sl.registerFactory<BlogPostCreateCubit>(() => BlogPostCreateCubit(blogPostRepository: sl()));
// Repository
sl.registerLazySingleton<ChatRepository>(() => ChatRepository(chatService: sl()));
@@ -84,6 +88,7 @@ Future<void> init() async {
sl.registerLazySingleton<DiaryRepository>(() => DiaryRepository(diaryService: sl()));
sl.registerLazySingleton<GlossaryRepository>(() => GlossaryRepository(glossaryService: sl()));
sl.registerLazySingleton<DietRepository>(() => DietRepository(dietsService: sl()));
sl.registerLazySingleton<BlogPostRepository>(() => BlogPostRepository(blogPostService: sl()));
// Services
sl.registerLazySingleton<ChatService>(() => ChatService(sl()));
@@ -98,6 +103,7 @@ Future<void> init() async {
sl.registerLazySingleton<DiaryService>(() => DiaryService(sl()));
sl.registerLazySingleton<GlossaryService>(() => GlossaryService(sl()));
sl.registerLazySingleton<DietService>(() => DietService(sl()));
sl.registerLazySingleton<BlogPostService>(() => BlogPostService(sl()));
// External
sl.registerLazySingleton(