feat(app): Feed, recipe, blog posts, diet and plan show and index pages, state management, API implementation and layouts

This commit is contained in:
2024-05-08 14:11:18 +03:00
parent 404b22e78a
commit 76a29ebf67
45 changed files with 2759 additions and 21 deletions

View File

@@ -0,0 +1,70 @@
//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';
import 'package:eatvio_app/presentation/feed/feed_screen/models/feed_model.dart';
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 'feed_event.dart';
part 'feed_state.dart';
/// A bloc that manages the state of a Feed according to the event that is dispatched to it.
class FeedBloc extends Bloc<FeedEvent, FeedState> {
FeedBloc(FeedState initialState) : super(initialState) {
on<FeedInitialEvent>(_onInitialize);
}
Future<void> _onInitialize(
FeedInitialEvent event,
Emitter<FeedState> emit,
) async {
try {
final box = await Hive.openBox('token');
final token = box.get('token');
if (token == null) {
NavigatorService.popAndPushNamed(
AppRoutes.authScreen,
); // Если токен есть, запускаем приложение
}
final response = await http.get(
Uri.parse(dotenv.env['SERVER_ROOT']! + '/feed/index'),
);
print('Got response');
if (response.statusCode == 200) {
print('Got 200');
final data = jsonDecode(response.body);
if (data is List<dynamic>) {
print('Got List');
if (state is FeedLoadedState) {
print('Got loaded');
var currentState = state as FeedLoadedState;
emit((currentState).copyWith(
posts: data,
myProfileModelObj: currentState.myProfileModelObj,
));
} else {
print('Got unloaded');
emit(FeedLoadedState(
posts: data,
));
}
} else {
// Один или несколько ключевых полей отсутствуют, обрабатываем ошибку
emit(FeedErrorState('Неверный формат ответа API.'));
}
} else {
// Статус ответа не равен 200, обрабатываем ошибку
emit(FeedErrorState('Ошибка сервера: ${response.statusCode}'));
}
} catch (e) {
// Ошибка при декодировании JSON или другая ошибка выполнения
emit(FeedErrorState('Ошибка при получении данных ленты: $e'));
}
}
}

View File

@@ -0,0 +1,23 @@
// ignore_for_file: must_be_immutable
part of 'feed_bloc.dart';
/// Abstract class for all events that can be dispatched from the
///Feed widget.
///
/// Events must be immutable and implement the [Equatable] interface.
@immutable
abstract class FeedEvent extends Equatable {}
/// Event that is dispatched when the Feed widget is first created.
class FeedInitialEvent extends FeedEvent {
@override
List<Object?> get props => [];
}
class UploadAvatar extends FeedEvent {
UploadAvatar(this.image);
final XFile image;
@override
List<Object> get props => [image];
}

View File

@@ -0,0 +1,49 @@
// ignore_for_file: must_be_immutable
part of 'feed_bloc.dart';
class FeedState extends Equatable {
const FeedState({this.myProfileModelObj});
final FeedModel? myProfileModelObj;
@override
List<Object?> get props => [myProfileModelObj];
}
class FeedInitialState extends FeedState {
FeedInitialState({required FeedModel myProfileModelObj})
: super(myProfileModelObj: myProfileModelObj);
}
/// Represents the state of Feed in the application.
class FeedLoadedState extends FeedState {
FeedLoadedState({this.myProfileModelObj, this.posts})
: super(myProfileModelObj: null);
FeedModel? myProfileModelObj;
List<dynamic>? posts;
@override
List<Object?> get props => [
myProfileModelObj,
posts,
];
FeedLoadedState copyWith({
FeedModel? myProfileModelObj,
List<dynamic>? posts,
}) {
return FeedLoadedState(
myProfileModelObj: myProfileModelObj ?? this.myProfileModelObj,
posts: posts ?? this.posts,
);
}
}
class FeedErrorState extends FeedState {
final String errorMessage;
const FeedErrorState(this.errorMessage);
@override
List<Object> get props => [errorMessage];
}