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