Skip to content

Commit

Permalink
feat: fetching chirp's posts
Browse files Browse the repository at this point in the history
  • Loading branch information
IamMuuo committed Aug 9, 2024
1 parent e0238e6 commit 05b61da
Show file tree
Hide file tree
Showing 7 changed files with 232 additions and 6 deletions.
8 changes: 8 additions & 0 deletions lib/constants/common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ extension StringExtension on String {
}
}

String trimTo99Characters(String text) {
if (text.length <= 99) {
return text;
} else {
return '${text.substring(0, 96)}...';
}
}

// Returns the day percent gone
double dayPercentGone() {
DateTime now = DateTime.now();
Expand Down
29 changes: 29 additions & 0 deletions lib/tools/chirp/controllers/chirp_controller.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import 'package:academia/exports/barrel.dart';
import 'package:get/get.dart';
import '../models/models.dart';
import 'package:dartz/dartz.dart';

class ChirpController extends GetxController {
final PostService _service = PostService();
UserController userController = Get.find<UserController>();
RxList<Post> posts = RxList<Post>();
RxInt currentPage = 0.obs;

@override
void onInit() {
super.onInit();
debugPrint("Chirp Controller Loaded");
}

Future<Either<String, List<Post>>> fetchPosts() async {
final result = await _service.fetchPosts(userController.authHeaders);

return result.fold((l) {
return left(l);
}, (r) {
posts.value = r["posts"];
currentPage.value = r["nextPage"];
return right(posts);
});
}
}
1 change: 1 addition & 0 deletions lib/tools/chirp/models/models.dart
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export 'core/core.dart';
export 'services/services.dart';
3 changes: 3 additions & 0 deletions lib/tools/chirp/models/services/chirp_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class ChirpService {
static const urlPrefix = "http://localhost:8080";
}
45 changes: 45 additions & 0 deletions lib/tools/chirp/models/services/post_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import 'dart:convert';

import 'package:dartz/dartz.dart';
import 'package:http/http.dart' as http;
import '../models.dart';

class PostService with ChirpService {
Future<Either<String, Map<String, dynamic>>> fetchPosts(
Map<String, String> authHeaders, {
int page = 1,
}) async {
try {
final response = await http.get(
Uri.parse("${ChirpService.urlPrefix}/posts/all?pages=$page"),
headers: authHeaders,
);

if (response.statusCode == 200) {
int nextPage = page;
// parse the posts and the next page
final Map<String, dynamic> rawData = json.decode(response.body);
if (rawData.containsKey("next") && rawData["next"] != null) {
nextPage += 1;
}

final List<Post> posts = rawData["results"]
.map((e) => Post.fromJson(e))
.toList()
.cast<Post>();

return right({
"posts": posts,
"nextPage": nextPage,
});
}
return left(
json.decode(response.body)["error"],
);
} catch (e) {
return left(
"Encountered an error we did, check your connection you must, ${e.toString()}",
);
}
}
}
2 changes: 2 additions & 0 deletions lib/tools/chirp/models/services/services.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export 'chirp_service.dart';
export 'post_service.dart';
150 changes: 144 additions & 6 deletions lib/tools/chirp/pages/chirp_home_page.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import 'package:academia/exports/barrel.dart';
import 'package:academia/tools/chirp/models/core/core.dart';
import 'package:academia/tools/chirp/pages/post_create_page.dart';
import 'package:get/get.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:lottie/lottie.dart';
import '../widgets/widgets.dart';
import '../controllers/chirp_controller.dart';

class ChirpHomePage extends StatefulWidget {
const ChirpHomePage({super.key});
Expand All @@ -13,6 +17,7 @@ class ChirpHomePage extends StatefulWidget {
class _ChirpHomePageState extends State<ChirpHomePage> {
final NotificationsController notificationsController =
Get.find<NotificationsController>();
final controller = Get.put(ChirpController());
@override
Widget build(BuildContext context) {
return Scaffold(
Expand Down Expand Up @@ -57,18 +62,55 @@ class _ChirpHomePageState extends State<ChirpHomePage> {
snap: true,
),
SliverVisibility(
visible: true,
visible: false,
sliver: SliverPersistentHeader(
floating: true,
delegate: PersistentStorySliverDelegate(child: const SizedBox()),
),
),
SliverFillRemaining(
child: Center(
child: Text(
"Coming soon!",
style: Theme.of(context).textTheme.headlineMedium,
),
child: FutureBuilder(
future: controller.fetchPosts(),
builder: (context, snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Lottie.asset("assets/lotties/fetching.json"),
Text(
"Fetching posts from fellow padawans we are.. hangon you must",
style: Theme.of(context).textTheme.headlineSmall,
textAlign: TextAlign.center,
)
],
),
);
}
return snapshot.data!.fold((l) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
l,
style: Theme.of(context).textTheme.headlineSmall,
textAlign: TextAlign.center,
)
],
);
}, (r) {
return ListView.separated(
itemBuilder: (context, index) {
final data = r[index];
return PostCard(post: data);
},
separatorBuilder: (context, index) => Divider(
thickness: 2,
color: Colors.black,
),
itemCount: r.length);
});
},
),
),
],
Expand All @@ -86,3 +128,99 @@ class _ChirpHomePageState extends State<ChirpHomePage> {
);
}
}

class PostCard extends StatelessWidget {
const PostCard({
super.key,
required this.post,
});
final Post post;

@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const CircleAvatar(
child: ProfilePictureWidget(
profileSize: 20,
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
"@${post.username}",
style: Theme.of(context).textTheme.bodySmall?.copyWith(
fontWeight: FontWeight.w800, color: Colors.grey),
),
Text(
"20 mins ago",
style: Theme.of(context).textTheme.bodySmall?.copyWith(
fontWeight: FontWeight.bold, color: Colors.grey),
),
],
),
),
const Spacer(),
IconButton(
onPressed: () {},
icon: const Icon(Ionicons.ellipsis_horizontal_circle_outline),
),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
post.title,
style: Theme.of(context).textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w700,
),
),
const SizedBox(height: 4),
Text(
trimTo99Characters(post.content),
),
],
),
Row(
children: [
IconButton(
onPressed: () {},
icon: Row(
children: [
const Icon(
Ionicons.arrow_up_circle_outline,
),
const SizedBox(width: 8),
Text(
post.upvotes.toString(),
style: GoogleFonts.ubuntu(),
)
],
),
),
const SizedBox(width: 12),
IconButton(
onPressed: () {},
icon: const Icon(Ionicons.arrow_down_circle_outline),
),
const Spacer(),
IconButton(
onPressed: () {},
icon: const Icon(Ionicons.arrow_redo_outline),
)
],
)
],
),
);
}
}

0 comments on commit 05b61da

Please sign in to comment.