Skip to content

Commit

Permalink
Merge pull request #99 from karina-klinkeviciute/#61
Browse files Browse the repository at this point in the history
#61 Added messages list and message page
  • Loading branch information
karina-klinkeviciute committed Jan 27, 2022
2 parents 18417e5 + 21e0aae commit f050ffe
Show file tree
Hide file tree
Showing 8 changed files with 233 additions and 33 deletions.
3 changes: 3 additions & 0 deletions lib/constants/api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import 'package:rainbow_challenge/constants/app.dart';
class Api {
static const String baseUrl = 'https://rainbowchallenge.lt';

// Messages
static const String messagesEndpoint = "/api/message/";

// News
static const String newsEndpoint = '/api/news/';

Expand Down
31 changes: 0 additions & 31 deletions lib/pages/messages.dart

This file was deleted.

58 changes: 58 additions & 0 deletions lib/pages/messages/message_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:rainbow_challenge/services/dio_client.dart';
import 'package:rainbow_challenge/utils/model/message.dart';
import 'package:rainbow_challenge/utils/repository/messages_repository.dart';
import 'package:rainbow_challenge/widgets/wrapper_main.dart';

class MessagePage extends StatefulWidget {
final Message message;

MessagePage({required this.message});

@override
State<StatefulWidget> createState() {
return _MessagePageState(message: message);
}
}

class _MessagePageState extends State<MessagePage> {
final Message message;

_MessagePageState({required this.message});

@override
void initState() {
super.initState();
updateMessage();
}

@override
Widget build(BuildContext context) {
return WrapperMainWidget(
mainArea: Padding(
padding: EdgeInsets.all(24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(DateFormat('yyyy-MM-dd kk:mm').format(message.timeSent)),
Container(
height: 24,
),
Text(message.messageText ?? ""),
Container(
height: 24,
),
Text(message.adminSender ?? ""),
],
)),
title: "Pranešimas",
);
}

Future<void> updateMessage() async {
await MessagesRepository(dioClient: DioClient())
.setSeen(message.uuid ?? "");
}
}
106 changes: 106 additions & 0 deletions lib/pages/messages/messages_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import 'package:flutter/material.dart';
import 'package:rainbow_challenge/services/dio_client.dart';
import 'package:rainbow_challenge/theme/colors.dart';
import 'package:rainbow_challenge/utils/model/message.dart';
import 'package:rainbow_challenge/utils/repository/messages_repository.dart';
import 'package:rainbow_challenge/widgets/widgets.dart';

import 'message_page.dart';

class MessagesPage extends StatefulWidget {
const MessagesPage({Key? key}) : super(key: key);

@override
State<StatefulWidget> createState() {
return _MessagesPageState();
}
}

class _MessagesPageState extends State<MessagesPage> {
List<Message> messages = List<Message>.empty(growable: true);
bool isLoading = true;

@override
void initState() {
super.initState();
loadData();
}

@override
Widget build(BuildContext context) {
return WrapperMainWidget(
mainArea: getMainAreaView(context),
title: "Pranešimai",
);
}

Widget getMainAreaView(BuildContext context) {
if (isLoading)
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [CircularProgressIndicator()]);

return ListView.separated(
scrollDirection: Axis.vertical,
shrinkWrap: true,
padding: const EdgeInsets.only(left: 24, right: 24, top: 10),
itemCount: messages.length,
itemBuilder: (BuildContext context, int index) {
return getListViewCell(messages[index]);
},
separatorBuilder: (BuildContext context, int index) => const Divider(
thickness: 1,
height: 10,
),
);
}

Widget getListViewCell(Message message) {
return GestureDetector(
child: Container(
height: 50,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Text(message.messageText ?? "",
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontWeight: message.seen
? FontWeight.normal
: FontWeight.bold))),
Icon(
Icons.chevron_right_outlined,
color: ThemeColors.secondaryColor.withOpacity(0.7),
size: 24.0,
),
],
)),
onTap: () async {
await onMessageClick(message);
});
}

Future onMessageClick(Message message) async {
await Navigator.push(context, MaterialPageRoute(builder: (context) {
return MessagePage(message: message);
}));
setState(() {
isLoading = true;
});

loadData();
}

Future loadData() async {
var fetchedMessages =
await MessagesRepository(dioClient: DioClient()).fetchMessages();

setState(() {
messages = fetchedMessages;
isLoading = false;
});
}
}
2 changes: 1 addition & 1 deletion lib/pages/pages.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export 'home_empty.dart';
export 'home.dart';
export 'loading.dart';
export 'logout.dart';
export 'messages.dart';
export 'messages/messages_page.dart';
export 'navigation.dart';
export 'qr_code.dart';
export 'regions.dart';
Expand Down
41 changes: 41 additions & 0 deletions lib/utils/model/message.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import 'dart:convert';

Message messageFromJson(String str) => Message.fromJson(json.decode(str));

String messageToJson(Message data) => json.encode(data.toJson());

class Message {
Message({
required this.uuid,
required this.messageText,
required this.user,
required this.adminSender,
required this.timeSent,
required this.seen,
});

String? uuid;
String? messageText;
String? user;
String? adminSender;
DateTime timeSent;
bool seen;

factory Message.fromJson(Map<String, dynamic> json) => Message(
uuid: json["uuid"],
messageText: json["message_text"],
user: json["user"],
adminSender: json["admin_sender"],
timeSent: DateTime.parse(json["time_sent"]),
seen: json["seen"],
);

Map<String, dynamic> toJson() => {
"uuid": uuid,
"message_text": messageText,
"user": user,
"admin_sender": adminSender,
"time_sent": timeSent.toIso8601String(),
"seen": seen,
};
}
18 changes: 18 additions & 0 deletions lib/utils/repository/messages_repository.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import 'package:rainbow_challenge/constants/api.dart';
import 'package:rainbow_challenge/services/dio_client.dart';
import 'package:rainbow_challenge/utils/model/message.dart';

class MessagesRepository {
final DioClient dioClient;
MessagesRepository({required this.dioClient});

Future<List<Message>> fetchMessages() async {
final messagesResponse = await dioClient.getList(Api.messagesEndpoint);
return messagesResponse!.map((e) => Message.fromJson(e)).toList();
}

Future setSeen(String id) {
var body = {"seen": true};
return dioClient.updateItem("${Api.messagesEndpoint}${id}/", body);
}
}
7 changes: 6 additions & 1 deletion lib/widgets/wrapper_main.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:rainbow_challenge/theme/colors.dart';

// A widget that uses a built in Scaffold widget with pages that use standard
// Scaffold structure with standard Scaffold.AppBar settings and BottomMenuWidget()
Expand All @@ -7,19 +8,23 @@ class WrapperMainWidget extends StatelessWidget {
final Widget mainArea;
final Color bodyBackgroundColor;
final bool useAppBar;
final String title;

const WrapperMainWidget(
{Key? key,
required this.mainArea,
this.bodyBackgroundColor = Colors.white,
this.useAppBar = true})
this.useAppBar = true,
this.title = ""})
: super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: useAppBar
? AppBar(
backgroundColor: bodyBackgroundColor,
title: Text(title,
style: TextStyle(color: ThemeColors.secondaryColor)),
)
: null,
backgroundColor: bodyBackgroundColor,
Expand Down

0 comments on commit f050ffe

Please sign in to comment.