|
|
@ -1,6 +1,8 @@
|
|
|
|
|
|
|
|
import 'package:diplomaticquarterapp/config/config.dart';
|
|
|
|
import 'package:diplomaticquarterapp/core/enum/viewstate.dart';
|
|
|
|
import 'package:diplomaticquarterapp/core/enum/viewstate.dart';
|
|
|
|
import 'package:diplomaticquarterapp/core/viewModels/feedback/feedback_view_model.dart';
|
|
|
|
import 'package:diplomaticquarterapp/core/viewModels/feedback/feedback_view_model.dart';
|
|
|
|
import 'package:diplomaticquarterapp/pages/base/base_view.dart';
|
|
|
|
import 'package:diplomaticquarterapp/pages/base/base_view.dart';
|
|
|
|
|
|
|
|
import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart';
|
|
|
|
import 'package:diplomaticquarterapp/uitl/app_toast.dart';
|
|
|
|
import 'package:diplomaticquarterapp/uitl/app_toast.dart';
|
|
|
|
import 'package:diplomaticquarterapp/uitl/date_uitl.dart';
|
|
|
|
import 'package:diplomaticquarterapp/uitl/date_uitl.dart';
|
|
|
|
import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart';
|
|
|
|
import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart';
|
|
|
@ -13,12 +15,15 @@ import 'package:diplomaticquarterapp/widgets/data_display/text.dart';
|
|
|
|
import 'package:diplomaticquarterapp/widgets/input/text_field.dart';
|
|
|
|
import 'package:diplomaticquarterapp/widgets/input/text_field.dart';
|
|
|
|
import 'package:diplomaticquarterapp/widgets/others/StarRating.dart';
|
|
|
|
import 'package:diplomaticquarterapp/widgets/others/StarRating.dart';
|
|
|
|
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
|
|
|
|
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
|
|
|
|
|
|
|
|
import 'package:diplomaticquarterapp/widgets/others/floating_button_search.dart';
|
|
|
|
import 'package:flutter/cupertino.dart';
|
|
|
|
import 'package:flutter/cupertino.dart';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
|
|
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
|
|
|
|
|
|
|
import 'package:speech_to_text/speech_recognition_error.dart';
|
|
|
|
import 'dart:convert';
|
|
|
|
import 'dart:convert';
|
|
|
|
import 'dart:io';
|
|
|
|
import 'dart:io';
|
|
|
|
import 'appointment_history.dart';
|
|
|
|
import 'appointment_history.dart';
|
|
|
|
|
|
|
|
import 'package:speech_to_text/speech_to_text.dart' as stt;
|
|
|
|
|
|
|
|
|
|
|
|
class SendFeedbackPage extends StatefulWidget {
|
|
|
|
class SendFeedbackPage extends StatefulWidget {
|
|
|
|
@override
|
|
|
|
@override
|
|
|
@ -35,8 +40,10 @@ class _SendFeedbackPageState extends State<SendFeedbackPage> {
|
|
|
|
String message;
|
|
|
|
String message;
|
|
|
|
final formKey = GlobalKey<FormState>();
|
|
|
|
final formKey = GlobalKey<FormState>();
|
|
|
|
MessageType messageType = MessageType.NON;
|
|
|
|
MessageType messageType = MessageType.NON;
|
|
|
|
|
|
|
|
var _currentLocaleId;
|
|
|
|
|
|
|
|
stt.SpeechToText speech = stt.SpeechToText();
|
|
|
|
|
|
|
|
var reconizedWord;
|
|
|
|
|
|
|
|
var event = RobotProvider();
|
|
|
|
String getSelected(BuildContext context) {
|
|
|
|
String getSelected(BuildContext context) {
|
|
|
|
switch (messageType) {
|
|
|
|
switch (messageType) {
|
|
|
|
case MessageType.ComplaintOnAnAppointment:
|
|
|
|
case MessageType.ComplaintOnAnAppointment:
|
|
|
@ -61,13 +68,10 @@ class _SendFeedbackPageState extends State<SendFeedbackPage> {
|
|
|
|
return TranslationBase.of(context).notClassified;
|
|
|
|
return TranslationBase.of(context).notClassified;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setMessageType(MessageType messageType) {
|
|
|
|
setMessageType(MessageType messageType) {
|
|
|
|
setState(() {
|
|
|
|
setState(() {
|
|
|
|
this.messageType = messageType;
|
|
|
|
this.messageType = messageType;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
@override
|
|
|
@ -116,7 +120,7 @@ class _SendFeedbackPageState extends State<SendFeedbackPage> {
|
|
|
|
getSelected(context),
|
|
|
|
getSelected(context),
|
|
|
|
variant: 'bodyText',
|
|
|
|
variant: 'bodyText',
|
|
|
|
),
|
|
|
|
),
|
|
|
|
margin: EdgeInsets.only(left: 10,right: 10),
|
|
|
|
margin: EdgeInsets.only(left: 10, right: 10),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
Icon(
|
|
|
|
Icon(
|
|
|
|
Icons.arrow_drop_down,
|
|
|
|
Icons.arrow_drop_down,
|
|
|
@ -127,8 +131,8 @@ class _SendFeedbackPageState extends State<SendFeedbackPage> {
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
if (appointHistory != null && messageType ==
|
|
|
|
if (appointHistory != null &&
|
|
|
|
MessageType.ComplaintOnAnAppointment)
|
|
|
|
messageType == MessageType.ComplaintOnAnAppointment)
|
|
|
|
InkWell(
|
|
|
|
InkWell(
|
|
|
|
onTap: () {
|
|
|
|
onTap: () {
|
|
|
|
setState(() {
|
|
|
|
setState(() {
|
|
|
@ -203,10 +207,13 @@ class _SendFeedbackPageState extends State<SendFeedbackPage> {
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
if (messageType == MessageType.ComplaintOnAnAppointment && model.appointHistoryList.length != 0 &&
|
|
|
|
if (messageType == MessageType.ComplaintOnAnAppointment &&
|
|
|
|
|
|
|
|
model.appointHistoryList.length != 0 &&
|
|
|
|
isShowListAppointHistory)
|
|
|
|
isShowListAppointHistory)
|
|
|
|
Container(
|
|
|
|
Container(
|
|
|
|
height: model.appointHistoryList.length>2?MediaQuery.of(context).size.height * 0.25:MediaQuery.of(context).size.height * 0.15,
|
|
|
|
height: model.appointHistoryList.length > 2
|
|
|
|
|
|
|
|
? MediaQuery.of(context).size.height * 0.25
|
|
|
|
|
|
|
|
: MediaQuery.of(context).size.height * 0.15,
|
|
|
|
child: ListView.builder(
|
|
|
|
child: ListView.builder(
|
|
|
|
itemCount: model.appointHistoryList.length,
|
|
|
|
itemCount: model.appointHistoryList.length,
|
|
|
|
itemBuilder: (context, index) => InkWell(
|
|
|
|
itemBuilder: (context, index) => InkWell(
|
|
|
@ -336,6 +343,10 @@ class _SendFeedbackPageState extends State<SendFeedbackPage> {
|
|
|
|
maxLines: 25,
|
|
|
|
maxLines: 25,
|
|
|
|
minLines: 13,
|
|
|
|
minLines: 13,
|
|
|
|
controller: messageController,
|
|
|
|
controller: messageController,
|
|
|
|
|
|
|
|
suffixIcon: Icons.mic,
|
|
|
|
|
|
|
|
onSuffixTap: () {
|
|
|
|
|
|
|
|
openSpeechReco();
|
|
|
|
|
|
|
|
},
|
|
|
|
validator: (value) {
|
|
|
|
validator: (value) {
|
|
|
|
if (value.isEmpty)
|
|
|
|
if (value.isEmpty)
|
|
|
|
return TranslationBase.of(context).emptyMessage;
|
|
|
|
return TranslationBase.of(context).emptyMessage;
|
|
|
@ -345,11 +356,12 @@ class _SendFeedbackPageState extends State<SendFeedbackPage> {
|
|
|
|
),
|
|
|
|
),
|
|
|
|
InkWell(
|
|
|
|
InkWell(
|
|
|
|
onTap: () {
|
|
|
|
onTap: () {
|
|
|
|
ImageOptions.showImageOptions(context, (String image,File file) {
|
|
|
|
ImageOptions.showImageOptions(context,
|
|
|
|
|
|
|
|
(String image, File file) {
|
|
|
|
setState(() {
|
|
|
|
setState(() {
|
|
|
|
images.add(image);
|
|
|
|
images.add(image);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
} );
|
|
|
|
});
|
|
|
|
},
|
|
|
|
},
|
|
|
|
child: Container(
|
|
|
|
child: Container(
|
|
|
|
margin: EdgeInsets.only(left: 10, right: 10, top: 15),
|
|
|
|
margin: EdgeInsets.only(left: 10, right: 10, top: 15),
|
|
|
@ -427,18 +439,21 @@ class _SendFeedbackPageState extends State<SendFeedbackPage> {
|
|
|
|
child: SecondaryButton(
|
|
|
|
child: SecondaryButton(
|
|
|
|
label: TranslationBase.of(context).send,
|
|
|
|
label: TranslationBase.of(context).send,
|
|
|
|
textColor: Colors.white,
|
|
|
|
textColor: Colors.white,
|
|
|
|
disabled: (titleController.text.toString().isEmpty || messageController.text.toString().isEmpty|| messageType == MessageType.NON),
|
|
|
|
disabled: (titleController.text.toString().isEmpty ||
|
|
|
|
|
|
|
|
messageController.text.toString().isEmpty ||
|
|
|
|
|
|
|
|
messageType == MessageType.NON),
|
|
|
|
onTap: () {
|
|
|
|
onTap: () {
|
|
|
|
final form = formKey.currentState;
|
|
|
|
final form = formKey.currentState;
|
|
|
|
if (form.validate())
|
|
|
|
if (form.validate()) if (messageType != MessageType.NON) {
|
|
|
|
if (messageType != MessageType.NON){
|
|
|
|
|
|
|
|
GifLoaderDialogUtils.showMyDialog(context);
|
|
|
|
GifLoaderDialogUtils.showMyDialog(context);
|
|
|
|
model.sendCOCItem(
|
|
|
|
model
|
|
|
|
|
|
|
|
.sendCOCItem(
|
|
|
|
title: titleController.text,
|
|
|
|
title: titleController.text,
|
|
|
|
attachment: images.length > 0 ? images[0] : "",
|
|
|
|
attachment: images.length > 0 ? images[0] : "",
|
|
|
|
details: messageController.text,
|
|
|
|
details: messageController.text,
|
|
|
|
cOCTypeName: getCOCName(),
|
|
|
|
cOCTypeName: getCOCName(),
|
|
|
|
appointHistory:messageType == MessageType.ComplaintOnAnAppointment
|
|
|
|
appointHistory: messageType ==
|
|
|
|
|
|
|
|
MessageType.ComplaintOnAnAppointment
|
|
|
|
? appointHistory
|
|
|
|
? appointHistory
|
|
|
|
: null)
|
|
|
|
: null)
|
|
|
|
.then((value) {
|
|
|
|
.then((value) {
|
|
|
@ -456,9 +471,10 @@ class _SendFeedbackPageState extends State<SendFeedbackPage> {
|
|
|
|
AppToast.showErrorToast(message: model.error);
|
|
|
|
AppToast.showErrorToast(message: model.error);
|
|
|
|
GifLoaderDialogUtils.hideDialog(context);
|
|
|
|
GifLoaderDialogUtils.hideDialog(context);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});}
|
|
|
|
});
|
|
|
|
else {
|
|
|
|
} else {
|
|
|
|
AppToast.showErrorToast(message: TranslationBase.of(context).selectPart);
|
|
|
|
AppToast.showErrorToast(
|
|
|
|
|
|
|
|
message: TranslationBase.of(context).selectPart);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
),
|
|
|
|
),
|
|
|
@ -513,21 +529,56 @@ class _SendFeedbackPageState extends State<SendFeedbackPage> {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
));
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
openSpeechReco() async {
|
|
|
|
|
|
|
|
new RoboSearch(context: context).showAlertDialog(context);
|
|
|
|
|
|
|
|
_currentLocaleId =
|
|
|
|
|
|
|
|
TranslationBase.of(AppGlobal.context).locale.languageCode;
|
|
|
|
|
|
|
|
bool available = await speech.initialize(
|
|
|
|
|
|
|
|
onStatus: statusListener, onError: errorListener);
|
|
|
|
|
|
|
|
if (available) {
|
|
|
|
|
|
|
|
speech.listen(
|
|
|
|
|
|
|
|
onResult: resultListener,
|
|
|
|
|
|
|
|
// listenMode: ListenMode.confirmation,
|
|
|
|
|
|
|
|
localeId: _currentLocaleId == 'en' ? 'en-US' : 'ar-SA',
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
print("The user has denied the use of speech recognition.");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void errorListener(SpeechRecognitionError error) {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void statusListener(String status) {
|
|
|
|
|
|
|
|
reconizedWord = status == 'listening' ? 'Lisening...' : 'Sorry....';
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void resultListener(result) {
|
|
|
|
|
|
|
|
reconizedWord = result.recognizedWords;
|
|
|
|
|
|
|
|
event.setValue({"searchText": reconizedWord});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (result.finalResult == true) {
|
|
|
|
|
|
|
|
setState(() {
|
|
|
|
|
|
|
|
RoboSearch.closeAlertDialog(context);
|
|
|
|
|
|
|
|
messageController.text = reconizedWord;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class FeedbackTypeDialog extends StatefulWidget {
|
|
|
|
class FeedbackTypeDialog extends StatefulWidget {
|
|
|
|
final Function(MessageType) onValueSelected;
|
|
|
|
final Function(MessageType) onValueSelected;
|
|
|
|
final MessageType messageTypeDialog;
|
|
|
|
final MessageType messageTypeDialog;
|
|
|
|
|
|
|
|
|
|
|
|
const FeedbackTypeDialog({Key key, this.onValueSelected, this.messageTypeDialog=MessageType.NON}) : super(key: key);
|
|
|
|
const FeedbackTypeDialog(
|
|
|
|
|
|
|
|
{Key key, this.onValueSelected, this.messageTypeDialog = MessageType.NON})
|
|
|
|
|
|
|
|
: super(key: key);
|
|
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
@override
|
|
|
|
State createState() => new FeedbackTypeDialogState();
|
|
|
|
State createState() => new FeedbackTypeDialogState();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class FeedbackTypeDialogState extends State<FeedbackTypeDialog> {
|
|
|
|
class FeedbackTypeDialogState extends State<FeedbackTypeDialog> {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MessageType messageTypeDialog = MessageType.NON;
|
|
|
|
MessageType messageTypeDialog = MessageType.NON;
|
|
|
|
|
|
|
|
|
|
|
|
setMessageDialogType(MessageType messageType) {
|
|
|
|
setMessageDialogType(MessageType messageType) {
|
|
|
@ -535,6 +586,7 @@ class FeedbackTypeDialogState extends State<FeedbackTypeDialog> {
|
|
|
|
messageTypeDialog = messageType;
|
|
|
|
messageTypeDialog = messageType;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
@override
|
|
|
|
void initState() {
|
|
|
|
void initState() {
|
|
|
|
messageTypeDialog = widget.messageTypeDialog;
|
|
|
|
messageTypeDialog = widget.messageTypeDialog;
|
|
|
@ -562,10 +614,10 @@ class FeedbackTypeDialogState extends State<FeedbackTypeDialog> {
|
|
|
|
Expanded(
|
|
|
|
Expanded(
|
|
|
|
flex: 1,
|
|
|
|
flex: 1,
|
|
|
|
child: InkWell(
|
|
|
|
child: InkWell(
|
|
|
|
onTap: () => setMessageDialogType(
|
|
|
|
onTap: () => setMessageDialogType(MessageType.NON),
|
|
|
|
MessageType.NON),
|
|
|
|
|
|
|
|
child: ListTile(
|
|
|
|
child: ListTile(
|
|
|
|
title: Texts(TranslationBase.of(context).notClassified),
|
|
|
|
title:
|
|
|
|
|
|
|
|
Texts(TranslationBase.of(context).notClassified),
|
|
|
|
leading: Radio(
|
|
|
|
leading: Radio(
|
|
|
|
value: MessageType.NON,
|
|
|
|
value: MessageType.NON,
|
|
|
|
groupValue: messageTypeDialog,
|
|
|
|
groupValue: messageTypeDialog,
|
|
|
@ -589,7 +641,8 @@ class FeedbackTypeDialogState extends State<FeedbackTypeDialog> {
|
|
|
|
onTap: () => setMessageDialogType(
|
|
|
|
onTap: () => setMessageDialogType(
|
|
|
|
MessageType.ComplaintOnAnAppointment),
|
|
|
|
MessageType.ComplaintOnAnAppointment),
|
|
|
|
child: ListTile(
|
|
|
|
child: ListTile(
|
|
|
|
title: Texts(TranslationBase.of(context).complainAppo),
|
|
|
|
title:
|
|
|
|
|
|
|
|
Texts(TranslationBase.of(context).complainAppo),
|
|
|
|
leading: Radio(
|
|
|
|
leading: Radio(
|
|
|
|
value: MessageType.ComplaintOnAnAppointment,
|
|
|
|
value: MessageType.ComplaintOnAnAppointment,
|
|
|
|
groupValue: messageTypeDialog,
|
|
|
|
groupValue: messageTypeDialog,
|
|
|
@ -613,7 +666,8 @@ class FeedbackTypeDialogState extends State<FeedbackTypeDialog> {
|
|
|
|
onTap: () => setMessageDialogType(
|
|
|
|
onTap: () => setMessageDialogType(
|
|
|
|
MessageType.ComplaintWithoutAppointment),
|
|
|
|
MessageType.ComplaintWithoutAppointment),
|
|
|
|
child: ListTile(
|
|
|
|
child: ListTile(
|
|
|
|
title: Texts(TranslationBase.of(context).complainWithoutAppo),
|
|
|
|
title: Texts(
|
|
|
|
|
|
|
|
TranslationBase.of(context).complainWithoutAppo),
|
|
|
|
leading: Radio(
|
|
|
|
leading: Radio(
|
|
|
|
value: MessageType.ComplaintWithoutAppointment,
|
|
|
|
value: MessageType.ComplaintWithoutAppointment,
|
|
|
|
groupValue: messageTypeDialog,
|
|
|
|
groupValue: messageTypeDialog,
|
|
|
@ -634,8 +688,7 @@ class FeedbackTypeDialogState extends State<FeedbackTypeDialog> {
|
|
|
|
Expanded(
|
|
|
|
Expanded(
|
|
|
|
flex: 1,
|
|
|
|
flex: 1,
|
|
|
|
child: InkWell(
|
|
|
|
child: InkWell(
|
|
|
|
onTap: () =>
|
|
|
|
onTap: () => setMessageDialogType(MessageType.Question),
|
|
|
|
setMessageDialogType(MessageType.Question),
|
|
|
|
|
|
|
|
child: ListTile(
|
|
|
|
child: ListTile(
|
|
|
|
title: Texts(TranslationBase.of(context).question),
|
|
|
|
title: Texts(TranslationBase.of(context).question),
|
|
|
|
leading: Radio(
|
|
|
|
leading: Radio(
|
|
|
@ -690,7 +743,8 @@ class FeedbackTypeDialogState extends State<FeedbackTypeDialog> {
|
|
|
|
value: MessageType.Suggestion,
|
|
|
|
value: MessageType.Suggestion,
|
|
|
|
groupValue: messageTypeDialog,
|
|
|
|
groupValue: messageTypeDialog,
|
|
|
|
activeColor: Theme.of(context).primaryColor,
|
|
|
|
activeColor: Theme.of(context).primaryColor,
|
|
|
|
onChanged: (MessageType value) => setMessageDialogType(value),
|
|
|
|
onChanged: (MessageType value) =>
|
|
|
|
|
|
|
|
setMessageDialogType(value),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|