service request comment done
parent
ce143947d1
commit
37a9cd3cc9
@ -0,0 +1,112 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
|
import 'package:http/http.dart';
|
||||||
|
import 'package:test_sa/controllers/api_routes/api_manager.dart';
|
||||||
|
import 'package:test_sa/controllers/api_routes/urls.dart';
|
||||||
|
import 'package:test_sa/extensions/context_extension.dart';
|
||||||
|
import 'package:test_sa/models/comment.dart';
|
||||||
|
|
||||||
|
import '../../../new_views/common_widgets/app_lazy_loading.dart';
|
||||||
|
|
||||||
|
class CommentsProvider extends ChangeNotifier {
|
||||||
|
// number of items call in each request
|
||||||
|
final pageItemNumber = 12;
|
||||||
|
|
||||||
|
//reset provider data
|
||||||
|
void reset() {
|
||||||
|
comments = [];
|
||||||
|
nextPage = true;
|
||||||
|
stateCode = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// state code of current request to defied error message
|
||||||
|
// like 400 customer request failed
|
||||||
|
// 500 service not available
|
||||||
|
int stateCode;
|
||||||
|
|
||||||
|
// true if there is next page in product list and false if not
|
||||||
|
bool nextPage = true;
|
||||||
|
|
||||||
|
// list of user requests
|
||||||
|
List<Comment> comments = [];
|
||||||
|
|
||||||
|
// when requests in-process _loading = true
|
||||||
|
// done _loading = true
|
||||||
|
// failed _loading = false
|
||||||
|
bool isLoading;
|
||||||
|
|
||||||
|
/// return -2 if request in progress
|
||||||
|
/// return -1 if error happen when sending request
|
||||||
|
/// return state code if request complete may be 200, 404 or 403
|
||||||
|
/// for more details check http state manager
|
||||||
|
/// lib\controllers\http_status_manger\http_status_manger.dart
|
||||||
|
Future<int> getComments({@required String callId}) async {
|
||||||
|
if (isLoading == true) return -2;
|
||||||
|
isLoading = true;
|
||||||
|
notifyListeners();
|
||||||
|
Response response;
|
||||||
|
try {
|
||||||
|
response = await ApiManager.instance.get(URLs.getComments + "?callRequestId=$callId");
|
||||||
|
|
||||||
|
stateCode = response.statusCode;
|
||||||
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||||
|
List requestsListJson = json.decode(response.body)["data"];
|
||||||
|
List<Comment> commentsPage = requestsListJson.map((request) => Comment.fromJson(request)).toList();
|
||||||
|
comments ??= [];
|
||||||
|
comments.addAll(commentsPage);
|
||||||
|
if (commentsPage.length == pageItemNumber) {
|
||||||
|
nextPage = true;
|
||||||
|
} else {
|
||||||
|
nextPage = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
return response.statusCode;
|
||||||
|
} catch (error) {
|
||||||
|
print(error);
|
||||||
|
isLoading = false;
|
||||||
|
stateCode = -1;
|
||||||
|
notifyListeners();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// return -2 if request in progress
|
||||||
|
/// return -1 if error happen when sending request
|
||||||
|
/// return state code if request complete may be 200, 404 or 403
|
||||||
|
/// for more details check http state manager
|
||||||
|
/// lib\controllers\http_status_manger\http_status_manger.dart
|
||||||
|
Future<int> addComment(BuildContext context, {@required Comment comment}) async {
|
||||||
|
if (isLoading == true) return -2;
|
||||||
|
isLoading = true;
|
||||||
|
Response response;
|
||||||
|
try {
|
||||||
|
comment.id = 0;
|
||||||
|
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
|
||||||
|
response = await ApiManager.instance.post(URLs.addComment, body: comment.toJson());
|
||||||
|
|
||||||
|
stateCode = response.statusCode;
|
||||||
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||||
|
reset(); //visit.status = pentry.ppmVisitStatus;
|
||||||
|
notifyListeners();
|
||||||
|
Fluttertoast.showToast(msg: context.translation.successfulRequestMessage);
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
} else {
|
||||||
|
Fluttertoast.showToast(msg: "${context.translation.failedToCompleteRequest} ${jsonDecode(response.body)["message"]}");
|
||||||
|
}
|
||||||
|
isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
return response.statusCode;
|
||||||
|
} catch (error) {
|
||||||
|
print(error);
|
||||||
|
isLoading = false;
|
||||||
|
stateCode = -1;
|
||||||
|
notifyListeners();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,75 @@
|
|||||||
|
class Comment {
|
||||||
|
Comment({
|
||||||
|
this.id,
|
||||||
|
this.callRequestId,
|
||||||
|
this.createdOn,
|
||||||
|
this.createdBy,
|
||||||
|
this.comment,
|
||||||
|
});
|
||||||
|
|
||||||
|
Comment.fromJson(dynamic json) {
|
||||||
|
id = json['id'];
|
||||||
|
callRequestId = json['callRequestId'];
|
||||||
|
createdOn = json['createdOn'];
|
||||||
|
createdBy = json['createdBy'] != null ? CreatedBy.fromJson(json['createdBy']) : null;
|
||||||
|
comment = json['comment'];
|
||||||
|
}
|
||||||
|
num id;
|
||||||
|
num callRequestId;
|
||||||
|
String createdOn;
|
||||||
|
CreatedBy createdBy;
|
||||||
|
String comment;
|
||||||
|
Comment copyWith({
|
||||||
|
num id,
|
||||||
|
num callRequestId,
|
||||||
|
String createdOn,
|
||||||
|
CreatedBy createdBy,
|
||||||
|
String comment,
|
||||||
|
}) =>
|
||||||
|
Comment(
|
||||||
|
id: id ?? this.id,
|
||||||
|
callRequestId: callRequestId ?? this.callRequestId,
|
||||||
|
createdOn: createdOn ?? this.createdOn,
|
||||||
|
createdBy: createdBy ?? this.createdBy,
|
||||||
|
comment: comment ?? this.comment,
|
||||||
|
);
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final map = <String, dynamic>{};
|
||||||
|
map['id'] = id;
|
||||||
|
map['callRequestId'] = callRequestId;
|
||||||
|
map['createdOn'] = createdOn;
|
||||||
|
if (createdBy != null) {
|
||||||
|
map['createdBy'] = createdBy.toJson();
|
||||||
|
}
|
||||||
|
map['comment'] = comment;
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CreatedBy {
|
||||||
|
CreatedBy({
|
||||||
|
this.userId,
|
||||||
|
this.userName,
|
||||||
|
});
|
||||||
|
|
||||||
|
CreatedBy.fromJson(dynamic json) {
|
||||||
|
userId = json['userId'];
|
||||||
|
userName = json['userName'];
|
||||||
|
}
|
||||||
|
String userId;
|
||||||
|
String userName;
|
||||||
|
CreatedBy copyWith({
|
||||||
|
String userId,
|
||||||
|
String userName,
|
||||||
|
}) =>
|
||||||
|
CreatedBy(
|
||||||
|
userId: userId ?? this.userId,
|
||||||
|
userName: userName ?? this.userName,
|
||||||
|
);
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final map = <String, dynamic>{};
|
||||||
|
map['userId'] = userId;
|
||||||
|
map['userName'] = userName;
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,125 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:test_sa/controllers/providers/api/comments_provider.dart';
|
||||||
|
import 'package:test_sa/controllers/providers/api/user_provider.dart';
|
||||||
|
import 'package:test_sa/controllers/validator/validator.dart';
|
||||||
|
import 'package:test_sa/extensions/context_extension.dart';
|
||||||
|
import 'package:test_sa/extensions/int_extensions.dart';
|
||||||
|
import 'package:test_sa/extensions/string_extensions.dart';
|
||||||
|
import 'package:test_sa/extensions/text_extensions.dart';
|
||||||
|
import 'package:test_sa/extensions/widget_extensions.dart';
|
||||||
|
import 'package:test_sa/models/comment.dart';
|
||||||
|
import 'package:test_sa/models/enums/user_types.dart';
|
||||||
|
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
|
||||||
|
import 'package:test_sa/views/widgets/loaders/lazy_loading.dart';
|
||||||
|
import 'package:test_sa/views/widgets/loaders/no_item_found.dart';
|
||||||
|
|
||||||
|
import '../../../../new_views/app_style/app_color.dart';
|
||||||
|
import '../../../widgets/loaders/loading_manager.dart';
|
||||||
|
|
||||||
|
class CommentsBottomSheet extends StatefulWidget {
|
||||||
|
final String requestId;
|
||||||
|
const CommentsBottomSheet({Key key, @required this.requestId}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<CommentsBottomSheet> createState() => _CommentsBottomSheetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CommentsBottomSheetState extends State<CommentsBottomSheet> {
|
||||||
|
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||||
|
String text;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final commentsProvider = Provider.of<CommentsProvider>(context, listen: false);
|
||||||
|
final userProvider = Provider.of<UserProvider>(context, listen: false);
|
||||||
|
return Container(
|
||||||
|
height: MediaQuery.of(context).size.height * 0.55,
|
||||||
|
clipBehavior: Clip.antiAlias,
|
||||||
|
margin: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
borderRadius: const BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20)),
|
||||||
|
),
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight),
|
||||||
|
child: Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: LoadingManager(
|
||||||
|
isLoading: commentsProvider.isLoading,
|
||||||
|
isFailedLoading: commentsProvider.comments == null,
|
||||||
|
stateCode: commentsProvider.stateCode,
|
||||||
|
onRefresh: () async {
|
||||||
|
commentsProvider.reset();
|
||||||
|
await commentsProvider.getComments(callId: widget.requestId);
|
||||||
|
},
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 40.toScreenWidth,
|
||||||
|
height: 5.toScreenHeight,
|
||||||
|
decoration: BoxDecoration(color: AppColor.neutral40, borderRadius: BorderRadius.circular(30)),
|
||||||
|
),
|
||||||
|
Align(
|
||||||
|
alignment: AlignmentDirectional.centerStart,
|
||||||
|
child: context.translation.comments.heading3(context).custom(fontWeight: FontWeight.w600).paddingOnly(top: 16, bottom: 16),
|
||||||
|
),
|
||||||
|
commentsProvider.comments.isEmpty
|
||||||
|
? NoItemFound(message: context.translation.noServiceRequestFound).expanded
|
||||||
|
: LazyLoading(
|
||||||
|
nextPage: commentsProvider.nextPage,
|
||||||
|
onLazyLoad: () async => await commentsProvider.getComments(callId: widget.requestId),
|
||||||
|
child: ListView.separated(
|
||||||
|
itemCount: commentsProvider.comments.length,
|
||||||
|
separatorBuilder: (cxt, index) => 8.height,
|
||||||
|
itemBuilder: (context, itemIndex) {
|
||||||
|
final model = commentsProvider.comments[itemIndex];
|
||||||
|
return Card(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
(model?.createdBy?.userName ?? "Nurse").heading6(context),
|
||||||
|
8.height,
|
||||||
|
(model?.comment ?? "").bodyText(context),
|
||||||
|
8.height,
|
||||||
|
Align(
|
||||||
|
alignment: AlignmentDirectional.bottomEnd,
|
||||||
|
child: DateTime.tryParse(model.createdOn).toIso8601String().toServiceRequestDetailsFormat.tinyFont(context),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).paddingAll(16),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
).expanded,
|
||||||
|
if (userProvider.user.type == UsersTypes.normal_user) 16.height,
|
||||||
|
if (userProvider.user.type == UsersTypes.normal_user)
|
||||||
|
AppTextFormField(
|
||||||
|
labelText: "Type any comment",
|
||||||
|
backgroundColor: AppColor.neutral30,
|
||||||
|
alignLabelWithHint: true,
|
||||||
|
validator: (value) => Validator.hasValue(value) ? null : context.translation.requiredField,
|
||||||
|
textInputType: TextInputType.multiline,
|
||||||
|
suffixIcon: "comment_send".toSvgAsset().paddingOnly(end: 16).onPress(() {
|
||||||
|
if (_formKey.currentState.validate()) {
|
||||||
|
_formKey.currentState.save();
|
||||||
|
final comment = Comment(id: 0, callRequestId: num.tryParse(widget.requestId ?? ""), comment: text);
|
||||||
|
commentsProvider.addComment(context, comment: comment);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
onSaved: (value) {
|
||||||
|
text = value;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
16.height,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue