Skip to content

Commit

Permalink
create bloc elements to handle fetching posts
Browse files Browse the repository at this point in the history
  • Loading branch information
hassan-kamel committed Apr 20, 2024
1 parent 0111d52 commit b910cb7
Show file tree
Hide file tree
Showing 19 changed files with 507 additions and 92 deletions.
1 change: 1 addition & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,5 @@
<data android:mimeType="text/plain"/>
</intent>
</queries>
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
34 changes: 34 additions & 0 deletions lib/business-logic/bloc/post_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:minly_media_mobile/data/Repositories/post.repository.dart';
import 'package:minly_media_mobile/data/models/post/post.dart';
import 'package:minly_media_mobile/data/services/post.service.dart';

part 'post_event.dart';
part 'post_state.dart';

class PostsBloc extends Bloc<PostsEvent, PostsState> {
PostsBloc() : super(PostsInitial()) {
// listeners
on<PostsFetchEvent>(_fetchPosts);
}
// handlers
FutureOr<void> _fetchPosts(
PostsFetchEvent event, Emitter<PostsState> emit) async {
emit(PostsFetching());
try {
print('hi');
final posts = await PostRepository(postService: PostService())
.getPosts(event.pageNumber, event.pageSize);

emit(PostFetchedSuccessfully(posts: posts));

print(posts.toString());
} catch (e) {
emit(PostFetchError(message: e.toString()));
print(e.toString());
}
}
}
22 changes: 22 additions & 0 deletions lib/business-logic/bloc/post_event.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
part of 'post_bloc.dart';

abstract class PostsEvent extends Equatable {}

class PostsFetchEvent extends PostsEvent {
final int pageNumber;
final int pageSize;

PostsFetchEvent({required this.pageNumber, required this.pageSize});

@override
List<Object> get props => [pageNumber, pageSize];
}

class PostErrorEvent extends PostsEvent {
final String message;

PostErrorEvent({required this.message});

@override
List<Object> get props => [message];
}
27 changes: 27 additions & 0 deletions lib/business-logic/bloc/post_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
part of 'post_bloc.dart';

sealed class PostsState extends Equatable {
const PostsState();

@override
List<Object> get props => [];
}

final class PostsInitial extends PostsState {
final List<Post> posts = [];

PostsInitial();
}

final class PostsFetching extends PostsState {}

final class PostFetchedSuccessfully extends PostsState {
final List<Post> posts;

const PostFetchedSuccessfully({required this.posts});
}

final class PostFetchError extends PostsState {
final String message;
const PostFetchError({required this.message});
}
8 changes: 0 additions & 8 deletions lib/business-logic/cubit/posts_cubit.dart

This file was deleted.

6 changes: 0 additions & 6 deletions lib/business-logic/cubit/posts_state.dart

This file was deleted.

5 changes: 4 additions & 1 deletion lib/data/Repositories/post.repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ class PostRepository {
PostRepository({required this.postService});

Future<List<Post>> getPosts(int pageNumber, int pageSize) async {
final posts = await postService.getPosts(pageNumber, pageSize);
final postsResponse = await postService.getPosts(pageNumber, pageSize);

List<dynamic> posts = postsResponse['data'];
print(posts);
return posts.map((post) => Post.fromJson(post)).toList();
}
}
5 changes: 5 additions & 0 deletions lib/data/models/post/author.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,9 @@ class Author {
String? fullName;

Author({this.id, this.fullName});

Author.fromJson(dynamic json) {
id = json['id'];
fullName = json['fullName'];
}
}
5 changes: 5 additions & 0 deletions lib/data/models/post/liked_by.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,9 @@ class LikedBy {
String? fullName;

LikedBy({this.id, this.fullName});

LikedBy.fromJson(dynamic json) {
id = json['id'];
fullName = json['fullName'];
}
}
11 changes: 5 additions & 6 deletions lib/data/models/post/post.dart
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
import 'package:minly_media_mobile/data/models/post/author.dart';
import 'package:minly_media_mobile/data/models/post/liked_by.dart';

class Post {
late String id;
late String caption;
late String mediaUrl;
late DateTime createdAt;
late String createdAt;
late String type;
late List<LikedBy> likedBy;
late List<dynamic> likedBy;
late Author author;

Post.fromJson(Map<String, dynamic> data) {
Post.fromJson(dynamic data) {
id = data['id'];
caption = data['caption'];
mediaUrl = data['mediaUrl'];
createdAt = DateTime.parse(data['createdAt']);
createdAt = data['createdAt'];
type = data['type'];
likedBy = data['likedBy'];
author = data['author'];
author = Author.fromJson(data['author']);
}
}
12 changes: 7 additions & 5 deletions lib/data/services/post.service.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:minly_media_mobile/constants/strings.dart';

Expand All @@ -16,17 +18,17 @@ class PostService {
}

// get posts
Future<List<Map<String, dynamic>>> getPosts(
int pageNumber, int pageSize) async {
Future<Map<String, dynamic>> getPosts(int pageNumber, int pageSize) async {
try {
Response response =
await dio.get('/posts?pageNumber=$pageNumber&pageSize=$pageSize');
await dio.get('/post?pageNumber=$pageNumber&pageSize=$pageSize');

print("response$response");
return response.data;

return jsonDecode(response.toString());
} catch (e) {
print(e.toString());
return [];
return {};
}
}
}
27 changes: 16 additions & 11 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:minly_media_mobile/app_router.dart';
import 'package:minly_media_mobile/business-logic/bloc/post_bloc.dart';

void main() {
runApp(const MinlyMediaApp());
Expand All @@ -11,17 +13,20 @@ class MinlyMediaApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp.router(
// Remove the debug banner
debugShowCheckedModeBanner: false,
// Set the routes
routerConfig: appRouter,
title: 'Flutter Demo',
// Set the theme
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: const Color.fromARGB(185, 12, 194, 164)),
useMaterial3: true,
return BlocProvider(
create: (context) => PostsBloc(),
child: MaterialApp.router(
// Remove the debug banner
debugShowCheckedModeBanner: false,
// Set the routes
routerConfig: appRouter,
title: 'Flutter Demo',
// Set the theme
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: const Color.fromARGB(185, 12, 194, 164)),
useMaterial3: true,
),
),
);
}
Expand Down
50 changes: 49 additions & 1 deletion lib/presentation/screens/home_tabs/feeds.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:minly_media_mobile/business-logic/bloc/post_bloc.dart';
import 'package:minly_media_mobile/presentation/widgets/post.dart';

class FeedsTab extends StatefulWidget {
Expand All @@ -9,8 +11,54 @@ class FeedsTab extends StatefulWidget {
}

class _FeedsTabState extends State<FeedsTab> {
@override
void initState() {
super.initState();

BlocProvider.of<PostsBloc>(context)
.add(PostsFetchEvent(pageNumber: 1, pageSize: 10));
}

@override
Widget build(BuildContext context) {
return Container(child: const Post());
return BlocBuilder<PostsBloc, PostsState>(
builder: (context, state) {
// initial state
if (state is PostsInitial ||
state is PostFetchedSuccessfully && state.posts.isEmpty) {
return const Center(
child: Text('No Data'),
);
}

// fetching state
if (state is PostsFetching || state is PostsInitial) {
const Center(
child: CircularProgressIndicator(),
);
}
// error state
if (state is PostFetchError) {
return Center(
child: Text(state.message),
);
}

// success state
if (state is PostFetchedSuccessfully) {
return ListView.builder(
itemCount: state.posts.length,
itemBuilder: (BuildContext context, int index) {
return PostWidget(post: state.posts[index]);
},
);
}

// unknown state
return const Center(
child: Text('Something went wrong'),
);
},
);
}
}
Loading

0 comments on commit b910cb7

Please sign in to comment.