Compare commits
3 Commits
master
...
etqan_ovr_
| Author | SHA1 | Date |
|---|---|---|
|
|
74bcf3e1b7 | 1 week ago |
|
|
912f7b23f1 | 1 week ago |
|
|
99414bf787 | 1 week ago |
@ -0,0 +1,129 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:mohem_flutter_app/api/api_client.dart';
|
||||
import 'package:mohem_flutter_app/app_state/app_state.dart';
|
||||
import 'package:mohem_flutter_app/classes/consts.dart';
|
||||
import 'package:mohem_flutter_app/models/etqan_ovr/etqan_get_employee_incident_report.dart';
|
||||
import 'package:mohem_flutter_app/models/etqan_ovr/etqan_get_requests_model.dart';
|
||||
import 'package:mohem_flutter_app/models/etqan_ovr/etqan_getprojects_model.dart';
|
||||
import 'package:mohem_flutter_app/models/generic_response_model.dart';
|
||||
import 'package:mohem_flutter_app/models/mowadhafhi/get_department_sections.dart';
|
||||
import 'package:mohem_flutter_app/models/mowadhafhi/get_project_departments.dart';
|
||||
import 'package:mohem_flutter_app/models/mowadhafhi/get_projects.dart';
|
||||
import 'package:mohem_flutter_app/models/mowadhafhi/get_section_topics.dart';
|
||||
import 'package:mohem_flutter_app/models/mowadhafhi/get_ticket_details.dart';
|
||||
import 'package:mohem_flutter_app/models/mowadhafhi/get_ticket_transactions.dart';
|
||||
import 'package:mohem_flutter_app/models/mowadhafhi/get_ticket_types.dart';
|
||||
import 'package:mohem_flutter_app/models/mowadhafhi/get_tickets_list.dart';
|
||||
import 'package:mohem_flutter_app/models/mowadhafhi/get_transaction_attachment_model.dart';
|
||||
|
||||
class EtqanApiClient {
|
||||
static final EtqanApiClient _instance = EtqanApiClient._internal();
|
||||
|
||||
EtqanApiClient._internal();
|
||||
|
||||
factory EtqanApiClient() => _instance;
|
||||
|
||||
Future<List<EtqanGetProjectsResponse>> getEtqanProjects() async {
|
||||
String url = "${ApiConsts.cocRest}ETQAN_GetProjects";
|
||||
Map<String, dynamic> postParams = <String, dynamic>{"P_SELECTED_EMPLOYEE_NUMBER": AppState().memberInformationList?.eMPLOYEENUMBER};
|
||||
postParams.addAll(AppState().postParamsJson);
|
||||
return await ApiClient().postJsonForObject(
|
||||
(json) {
|
||||
List<EtqanGetProjectsResponse>? responseData = <EtqanGetProjectsResponse>[];
|
||||
if (json["ETQAN_GetProjects_Response"] != null && json["ETQAN_GetProjects_Response"].isNotEmpty) {
|
||||
json["ETQAN_GetProjects_Response"].forEach((element) {
|
||||
responseData.add(EtqanGetProjectsResponse.fromJson(element));
|
||||
});
|
||||
}
|
||||
return responseData;
|
||||
},
|
||||
url,
|
||||
postParams,
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<EtqanGetEmployeeOvrRequestsResponse>> getEmployeeEtqanRequests() async {
|
||||
String url = "${ApiConsts.cocRest}ETQAN_GetEmployeeOVRRequests";
|
||||
Map<String, dynamic> postParams = <String, dynamic>{
|
||||
"ETQAN_EmployeeID": AppState().memberInformationList?.eMPLOYEENUMBER,
|
||||
"P_SELECTED_EMPLOYEE_NUMBER": AppState().memberInformationList?.eMPLOYEENUMBER,
|
||||
};
|
||||
postParams.addAll(AppState().postParamsJson);
|
||||
return await ApiClient().postJsonForObject(
|
||||
(json) {
|
||||
List<EtqanGetEmployeeOvrRequestsResponse> responseData = <EtqanGetEmployeeOvrRequestsResponse>[];
|
||||
if (json["ETQAN_GetEmployeeOVRRequests_Response"] != null && json["ETQAN_GetEmployeeOVRRequests_Response"].isNotEmpty) {
|
||||
json["ETQAN_GetEmployeeOVRRequests_Response"].forEach((element) {
|
||||
responseData.add(EtqanGetEmployeeOvrRequestsResponse.fromJson(element));
|
||||
});
|
||||
}
|
||||
|
||||
if (responseData.isNotEmpty) {
|
||||
for (EtqanGetEmployeeOvrRequestsResponse action in responseData) {
|
||||
action.createdDate = action.createdDate?.split(" ")[0];
|
||||
}
|
||||
responseData.sort((EtqanGetEmployeeOvrRequestsResponse a, EtqanGetEmployeeOvrRequestsResponse b) => (b.createdDate ?? '').compareTo(a.createdDate ?? ''));
|
||||
}
|
||||
|
||||
return responseData;
|
||||
},
|
||||
url,
|
||||
postParams,
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<EtqanGetIncidentRequestResponse>> getEtqanIncidentRequests(String ticketNo) async {
|
||||
String url = "${ApiConsts.cocRest}ETQAN_GetIncidentRequest";
|
||||
Map<String, dynamic> postParams = <String, dynamic>{"ETQAN_TicketNumber": ticketNo, "P_SELECTED_EMPLOYEE_NUMBER": AppState().memberInformationList?.eMPLOYEENUMBER};
|
||||
postParams.addAll(AppState().postParamsJson);
|
||||
return await ApiClient().postJsonForObject(
|
||||
(json) {
|
||||
List<EtqanGetIncidentRequestResponse> responseData = <EtqanGetIncidentRequestResponse>[];
|
||||
if (json["ETQAN_GetIncidentRequest_Response"] != null && json["ETQAN_GetIncidentRequest_Response"].isNotEmpty) {
|
||||
json["ETQAN_GetIncidentRequest_Response"].forEach((element) {
|
||||
responseData.add(EtqanGetIncidentRequestResponse.fromJson(element));
|
||||
});
|
||||
}
|
||||
return responseData;
|
||||
},
|
||||
url,
|
||||
postParams,
|
||||
);
|
||||
}
|
||||
|
||||
Future<int?> createRequest(String description, int? projectID, String? attachmentBase64) async {
|
||||
String url = "${ApiConsts.cocRest}ETQAN_CreateIncident";
|
||||
Map<String, dynamic> postParams = <String, dynamic>{
|
||||
"P_SELECTED_EMPLOYEE_NUMBER": AppState().memberInformationList?.eMPLOYEENUMBER,
|
||||
"P_USER_NAME": AppState().memberInformationList?.eMPLOYEENUMBER,
|
||||
"ETQAN_Emp_EmployeeNumber": AppState().memberInformationList?.eMPLOYEENUMBER,
|
||||
"ETQAN_Description": description,
|
||||
"ETQAN_ProjectId": projectID,
|
||||
"ETQAN_FileInfoBase64": attachmentBase64,
|
||||
"ETQAN_IsAnonymous": false,
|
||||
};
|
||||
|
||||
postParams.addAll(AppState().postParamsJson);
|
||||
return await ApiClient().postJsonForObject(
|
||||
(json) {
|
||||
if (json["ETQAN_CreateIncident_Response"] != null) {
|
||||
var response = json["ETQAN_CreateIncident_Response"];
|
||||
if (response["id"] != null && response["ticketNumber"] != null) {
|
||||
return 1;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
|
||||
// "ETQAN_CreateIncident_Response": {
|
||||
// "id": "00adabe4-4a32-4b35-1f00-08de4d152e7c",
|
||||
// "ticketNumber": "OVR/OLY/2026/224"
|
||||
// },
|
||||
},
|
||||
url,
|
||||
postParams,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
import 'dart:convert';
|
||||
|
||||
class EtqanGetEmployeeIncidentRequestModel {
|
||||
List<EtqanGetIncidentRequestResponse>? etqanGetIncidentRequestResponse;
|
||||
|
||||
EtqanGetEmployeeIncidentRequestModel({
|
||||
this.etqanGetIncidentRequestResponse,
|
||||
});
|
||||
|
||||
factory EtqanGetEmployeeIncidentRequestModel.fromRawJson(String str) => EtqanGetEmployeeIncidentRequestModel.fromJson(json.decode(str));
|
||||
|
||||
String toRawJson() => json.encode(toJson());
|
||||
|
||||
factory EtqanGetEmployeeIncidentRequestModel.fromJson(Map<String, dynamic> json) => EtqanGetEmployeeIncidentRequestModel(
|
||||
etqanGetIncidentRequestResponse: json["ETQAN_GetIncidentRequest_Response"] == null ? [] : List<EtqanGetIncidentRequestResponse>.from(json["ETQAN_GetIncidentRequest_Response"]!.map((x) => EtqanGetIncidentRequestResponse.fromJson(x))),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"ETQAN_GetIncidentRequest_Response": etqanGetIncidentRequestResponse == null ? [] : List<dynamic>.from(etqanGetIncidentRequestResponse!.map((x) => x.toJson())),
|
||||
};
|
||||
}
|
||||
|
||||
class EtqanGetIncidentRequestResponse {
|
||||
String? key;
|
||||
String? value;
|
||||
|
||||
EtqanGetIncidentRequestResponse({
|
||||
this.key,
|
||||
this.value,
|
||||
});
|
||||
|
||||
factory EtqanGetIncidentRequestResponse.fromRawJson(String str) => EtqanGetIncidentRequestResponse.fromJson(json.decode(str));
|
||||
|
||||
String toRawJson() => json.encode(toJson());
|
||||
|
||||
factory EtqanGetIncidentRequestResponse.fromJson(Map<String, dynamic> json) => EtqanGetIncidentRequestResponse(
|
||||
key: json["key"],
|
||||
value: json["value"],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"key": key,
|
||||
"value": value,
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
import 'dart:convert';
|
||||
|
||||
class EtqanGetEmployeeRequestsModel {
|
||||
List<EtqanGetEmployeeOvrRequestsResponse>? etqanGetEmployeeOvrRequestsResponse;
|
||||
|
||||
EtqanGetEmployeeRequestsModel({
|
||||
this.etqanGetEmployeeOvrRequestsResponse,
|
||||
});
|
||||
|
||||
factory EtqanGetEmployeeRequestsModel.fromRawJson(String str) => EtqanGetEmployeeRequestsModel.fromJson(json.decode(str));
|
||||
|
||||
String toRawJson() => json.encode(toJson());
|
||||
|
||||
factory EtqanGetEmployeeRequestsModel.fromJson(Map<String, dynamic> json) => EtqanGetEmployeeRequestsModel(
|
||||
etqanGetEmployeeOvrRequestsResponse: json["ETQAN_GetEmployeeOVRRequests_Response"] == null ? [] : List<EtqanGetEmployeeOvrRequestsResponse>.from(json["ETQAN_GetEmployeeOVRRequests_Response"]!.map((x) => EtqanGetEmployeeOvrRequestsResponse.fromJson(x))),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"ETQAN_GetEmployeeOVRRequests_Response": etqanGetEmployeeOvrRequestsResponse == null ? [] : List<dynamic>.from(etqanGetEmployeeOvrRequestsResponse!.map((x) => x.toJson())),
|
||||
};
|
||||
}
|
||||
|
||||
class EtqanGetEmployeeOvrRequestsResponse {
|
||||
String? createdDate;
|
||||
String? description;
|
||||
String? id;
|
||||
String? ticketNumber;
|
||||
|
||||
EtqanGetEmployeeOvrRequestsResponse({
|
||||
this.createdDate,
|
||||
this.description,
|
||||
this.id,
|
||||
this.ticketNumber,
|
||||
});
|
||||
|
||||
factory EtqanGetEmployeeOvrRequestsResponse.fromRawJson(String str) => EtqanGetEmployeeOvrRequestsResponse.fromJson(json.decode(str));
|
||||
|
||||
String toRawJson() => json.encode(toJson());
|
||||
|
||||
factory EtqanGetEmployeeOvrRequestsResponse.fromJson(Map<String, dynamic> json) => EtqanGetEmployeeOvrRequestsResponse(
|
||||
createdDate: json["createdDate"],
|
||||
description: json["description"],
|
||||
id: json["id"],
|
||||
ticketNumber: json["ticketNumber"],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"createdDate": createdDate,
|
||||
"description": description,
|
||||
"id": id,
|
||||
"ticketNumber": ticketNumber,
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
import 'dart:convert';
|
||||
|
||||
class EtqanGetProjectsModel {
|
||||
List<EtqanGetProjectsResponse>? etqanGetProjectsResponse;
|
||||
|
||||
EtqanGetProjectsModel({
|
||||
this.etqanGetProjectsResponse,
|
||||
});
|
||||
|
||||
factory EtqanGetProjectsModel.fromRawJson(String str) => EtqanGetProjectsModel.fromJson(json.decode(str));
|
||||
|
||||
String toRawJson() => json.encode(toJson());
|
||||
|
||||
factory EtqanGetProjectsModel.fromJson(Map<String, dynamic> json) => EtqanGetProjectsModel(
|
||||
etqanGetProjectsResponse: json["ETQAN_GetProjects_Response"] == null ? [] : List<EtqanGetProjectsResponse>.from(json["ETQAN_GetProjects_Response"]!.map((x) => EtqanGetProjectsResponse.fromJson(x))),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"ETQAN_GetProjects_Response": etqanGetProjectsResponse == null ? [] : List<dynamic>.from(etqanGetProjectsResponse!.map((x) => x.toJson())),
|
||||
};
|
||||
}
|
||||
|
||||
class EtqanGetProjectsResponse {
|
||||
String? projectAr;
|
||||
String? projectCode;
|
||||
String? projectEn;
|
||||
int? projectId;
|
||||
|
||||
EtqanGetProjectsResponse({
|
||||
this.projectAr,
|
||||
this.projectCode,
|
||||
this.projectEn,
|
||||
this.projectId,
|
||||
});
|
||||
|
||||
factory EtqanGetProjectsResponse.fromRawJson(String str) => EtqanGetProjectsResponse.fromJson(json.decode(str));
|
||||
|
||||
String toRawJson() => json.encode(toJson());
|
||||
|
||||
factory EtqanGetProjectsResponse.fromJson(Map<String, dynamic> json) => EtqanGetProjectsResponse(
|
||||
projectAr: json["projectAr"],
|
||||
projectCode: json["projectCode"],
|
||||
projectEn: json["projectEn"],
|
||||
projectId: json["projectId"],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"projectAr": projectAr,
|
||||
"projectCode": projectCode,
|
||||
"projectEn": projectEn,
|
||||
"projectId": projectId,
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,181 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mohem_flutter_app/api/etqan_ovr_api_client.dart';
|
||||
import 'package:mohem_flutter_app/classes/utils.dart';
|
||||
import 'package:mohem_flutter_app/models/etqan_ovr/etqan_get_employee_incident_report.dart';
|
||||
import 'package:mohem_flutter_app/models/etqan_ovr/etqan_get_requests_model.dart';
|
||||
import 'package:mohem_flutter_app/models/etqan_ovr/etqan_getprojects_model.dart';
|
||||
import 'package:speech_to_text/speech_recognition_result.dart';
|
||||
import 'package:speech_to_text/speech_to_text.dart';
|
||||
|
||||
class EtqanOvrProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
||||
// Home screen state
|
||||
List<EtqanGetProjectsResponse>? getEtqanProjectsList;
|
||||
List<EtqanGetEmployeeOvrRequestsResponse>? getEtqanEmployeeRequestsList;
|
||||
List<EtqanGetIncidentRequestResponse>? getEtqanEmployeeIncidnetRequest;
|
||||
bool isLoading = false;
|
||||
String? _ticketId;
|
||||
|
||||
// Speech to text state
|
||||
final SpeechToText _speechToText = SpeechToText();
|
||||
bool _speechEnabled = false;
|
||||
bool _isListening = false;
|
||||
|
||||
// Getters for speech state
|
||||
bool get speechEnabled => _speechEnabled;
|
||||
|
||||
bool get isListening => _isListening;
|
||||
|
||||
// Getter for ticketId
|
||||
String get getTicketId => _ticketId ?? '';
|
||||
|
||||
// Setter for ticketId
|
||||
void setTicketId(String ticketId) {
|
||||
_ticketId = ticketId;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// Create request screen state
|
||||
EtqanGetProjectsResponse? selectedProject;
|
||||
String? selectedEmployeeNumber;
|
||||
File? attachment;
|
||||
String? attachmentBase64;
|
||||
String description = '';
|
||||
|
||||
/// Initialize speech recognition - call this once when screen loads
|
||||
Future<void> initSpeech() async {
|
||||
_speechEnabled = await _speechToText.initialize();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Start listening for speech input
|
||||
Future<void> startListening(String localeId, TextEditingController controller) async {
|
||||
await _speechToText.listen(
|
||||
onResult: (SpeechRecognitionResult result) {
|
||||
description = result.recognizedWords;
|
||||
controller.text = result.recognizedWords;
|
||||
controller.selection = TextSelection.fromPosition(TextPosition(offset: controller.text.length));
|
||||
notifyListeners();
|
||||
},
|
||||
localeId: localeId,
|
||||
);
|
||||
_isListening = true;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Stop listening for speech input
|
||||
Future<void> stopListening() async {
|
||||
await _speechToText.stop();
|
||||
_isListening = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Toggle listening state
|
||||
Future<void> toggleListening(String localeId, TextEditingController controller) async {
|
||||
if (_isListening) {
|
||||
await stopListening();
|
||||
} else {
|
||||
await startListening(localeId, controller);
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch Etqan Projects
|
||||
Future<void> fetchEtqanProjects(BuildContext context) async {
|
||||
isLoading = true;
|
||||
notifyListeners();
|
||||
Utils.showLoading(context);
|
||||
getEtqanProjectsList?.clear();
|
||||
getEtqanProjectsList = await EtqanApiClient().getEtqanProjects();
|
||||
Utils.hideLoading(context);
|
||||
isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// Fetch Etqan Employee Requests
|
||||
Future<void> fetchEtqanEmployeeRequests(BuildContext context) async {
|
||||
isLoading = true;
|
||||
notifyListeners();
|
||||
Utils.showLoading(context);
|
||||
getEtqanEmployeeRequestsList?.clear();
|
||||
getEtqanEmployeeRequestsList = await EtqanApiClient().getEmployeeEtqanRequests();
|
||||
Utils.hideLoading(context);
|
||||
isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// Fetch Etqan Employee Incident Report
|
||||
Future<void> fetchEtqanEmployeeIncidentRequests(BuildContext context, String ticketNo) async {
|
||||
isLoading = true;
|
||||
notifyListeners();
|
||||
Utils.showLoading(context);
|
||||
getEtqanEmployeeIncidnetRequest?.clear();
|
||||
getEtqanEmployeeIncidnetRequest = await EtqanApiClient().getEtqanIncidentRequests(ticketNo);
|
||||
Utils.hideLoading(context);
|
||||
isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// Set selected project
|
||||
void setSelectedProject(EtqanGetProjectsResponse? project) {
|
||||
selectedProject = project;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// Set selected employee number
|
||||
void setSelectedEmployeeNumber(String? employeeNumber) {
|
||||
selectedEmployeeNumber = employeeNumber;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// Set attachment with base64
|
||||
void setAttachment(File file, String base64) {
|
||||
attachment = file;
|
||||
attachmentBase64 = base64;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// Remove attachment
|
||||
void removeAttachment() {
|
||||
attachment = null;
|
||||
attachmentBase64 = null;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// Set description
|
||||
void setDescription(String value) {
|
||||
description = value;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// Clear create request form
|
||||
void clearCreateRequestForm() {
|
||||
selectedProject = null;
|
||||
selectedEmployeeNumber = null;
|
||||
attachment = null;
|
||||
attachmentBase64 = null;
|
||||
description = '';
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// Submit request
|
||||
Future<bool> submitRequest(BuildContext context) async {
|
||||
try {
|
||||
Utils.showLoading(context);
|
||||
int? isSuccess = await EtqanApiClient().createRequest(description, selectedProject?.projectId, attachmentBase64);
|
||||
Utils.hideLoading(context);
|
||||
if (isSuccess == 1) {
|
||||
getEtqanEmployeeRequestsList = await EtqanApiClient().getEmployeeEtqanRequests();
|
||||
notifyListeners();
|
||||
Navigator.of(context).pop();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch (ex) {
|
||||
Utils.hideLoading(context);
|
||||
Utils.handleException(ex, context, null);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,279 @@
|
||||
import 'dart:io';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mohem_flutter_app/app_state/app_state.dart';
|
||||
import 'package:mohem_flutter_app/classes/colors.dart';
|
||||
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
|
||||
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
|
||||
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
|
||||
import 'package:mohem_flutter_app/models/etqan_ovr/etqan_getprojects_model.dart';
|
||||
import 'package:mohem_flutter_app/provider/etqan_ovr_provider.dart';
|
||||
import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
|
||||
import 'package:mohem_flutter_app/widgets/bottom_sheet.dart';
|
||||
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
|
||||
import 'package:mohem_flutter_app/widgets/image_picker.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class EtqanOvrCreateRequest extends StatefulWidget {
|
||||
const EtqanOvrCreateRequest({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_EtqanOvrCreateRequestState createState() => _EtqanOvrCreateRequestState();
|
||||
}
|
||||
|
||||
class _EtqanOvrCreateRequestState extends State<EtqanOvrCreateRequest> {
|
||||
final TextEditingController _descriptionController = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
var provider = context.read<EtqanOvrProviderModel>();
|
||||
provider.initSpeech();
|
||||
provider.fetchEtqanProjects(context);
|
||||
provider.clearCreateRequestForm();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_descriptionController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: AppBarWidget(context, title: LocaleKeys.createRequest.tr(), showHomeButton: false),
|
||||
body: Consumer<EtqanOvrProviderModel>(
|
||||
builder: (BuildContext context, EtqanOvrProviderModel provider, Widget? child) {
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
(ListView(
|
||||
shrinkWrap: true,
|
||||
physics: const BouncingScrollPhysics(),
|
||||
padding: const EdgeInsets.all(21),
|
||||
children: <Widget>[
|
||||
_buildDropdownField(
|
||||
label: LocaleKeys.project.tr(),
|
||||
hint: LocaleKeys.selectProject.tr(),
|
||||
value: _getProjectDisplayName(provider.selectedProject),
|
||||
onTap: () => _showProjectSelectionSheet(context, provider),
|
||||
),
|
||||
16.height,
|
||||
// _buildDropdownField(
|
||||
// label: 'Employee Number',
|
||||
// hint: 'Write a message',
|
||||
// value: provider.selectedEmployeeNumber,
|
||||
// onTap: () {
|
||||
// // TODO: Show employee selection dialog
|
||||
// },
|
||||
// ),
|
||||
// 16.height,
|
||||
_buildAttachmentSection(provider),
|
||||
16.height,
|
||||
_buildDescriptionField(provider),
|
||||
24.height,
|
||||
],
|
||||
)).expanded,
|
||||
DefaultButton(LocaleKeys.submit.tr(), () async {
|
||||
provider.setDescription(_descriptionController.text);
|
||||
await provider.submitRequest(context);
|
||||
}).insideContainer,
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String? _getProjectDisplayName(EtqanGetProjectsResponse? project) {
|
||||
if (project == null) return null;
|
||||
return AppState().isArabic(context) ? project.projectAr : project.projectEn;
|
||||
}
|
||||
|
||||
void _showProjectSelectionSheet(BuildContext context, EtqanOvrProviderModel provider) {
|
||||
if (provider.getEtqanProjectsList == null || provider.getEtqanProjectsList!.isEmpty) {
|
||||
return;
|
||||
}
|
||||
showMyBottomSheet(
|
||||
context,
|
||||
callBackFunc: () {},
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
child: Text(LocaleKeys.selectProject.tr(), style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: Color(0xff2B353E))),
|
||||
),
|
||||
const Divider(),
|
||||
ListView.separated(
|
||||
shrinkWrap: true,
|
||||
physics: const BouncingScrollPhysics(),
|
||||
itemCount: provider.getEtqanProjectsList!.length,
|
||||
separatorBuilder: (BuildContext context, int index) => const Divider(height: 1),
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
EtqanGetProjectsResponse project = provider.getEtqanProjectsList![index];
|
||||
bool isSelected = provider.selectedProject?.projectId == project.projectId;
|
||||
return ListTile(
|
||||
title: Text(
|
||||
AppState().isArabic(context) ? (project.projectAr ?? '') : (project.projectEn ?? ''),
|
||||
style: TextStyle(fontSize: 14, fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400, color: isSelected ? MyColors.gradiantEndColor : const Color(0xff2B353E)),
|
||||
),
|
||||
trailing: isSelected ? const Icon(Icons.check, color: MyColors.gradiantEndColor) : null,
|
||||
onTap: () {
|
||||
provider.setSelectedProject(project);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
16.height,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDropdownField({required String label, required String hint, String? value, required VoidCallback onTap}) {
|
||||
return InkWell(
|
||||
onTap: onTap,
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 15),
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(15), color: Colors.white, border: Border.all(color: const Color(0xffefefef), width: 1)),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(label, style: const TextStyle(fontSize: 11, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.44)),
|
||||
const SizedBox(height: 4),
|
||||
Text(value ?? hint, style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: value != null ? const Color(0xff2B353E) : const Color(0xff575757), letterSpacing: -0.56)),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Icon(Icons.keyboard_arrow_down, color: Color(0xff575757)),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildAttachmentSection(EtqanOvrProviderModel provider) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(15), color: Colors.white, border: Border.all(color: const Color(0xffefefef), width: 1)),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(LocaleKeys.supportingDocument.tr(), style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2B353E))),
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Text(LocaleKeys.attachments.tr(), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: Color(0xff2B353E))),
|
||||
if (provider.attachment == null)
|
||||
InkWell(
|
||||
onTap: () {
|
||||
ImageOptions.showImageOptionsNew(context, true, (String base64, File file) {
|
||||
provider.setAttachment(file, base64);
|
||||
Navigator.of(context).pop();
|
||||
});
|
||||
},
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 8),
|
||||
decoration: BoxDecoration(color: MyColors.gradiantEndColor, borderRadius: BorderRadius.circular(8)),
|
||||
child: Text(LocaleKeys.add.tr(), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600, color: Colors.white)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (provider.attachment != null) ...<Widget>[
|
||||
const SizedBox(height: 12),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
const Icon(Icons.attach_file, size: 18, color: Color(0xff575757)),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(child: Text(provider.attachment!.path.split('/').last, style: const TextStyle(fontSize: 12, color: Color(0xff575757)), overflow: TextOverflow.ellipsis)),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
provider.removeAttachment();
|
||||
},
|
||||
child: const Icon(Icons.close, size: 18, color: Colors.red),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDescriptionField(EtqanOvrProviderModel provider) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 15),
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(15), color: Colors.white, border: Border.all(color: const Color(0xffefefef), width: 1)),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Text(LocaleKeys.description.tr(), style: const TextStyle(fontSize: 11, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.44)),
|
||||
GestureDetector(
|
||||
onTap:
|
||||
provider.speechEnabled
|
||||
? () {
|
||||
String localeId = AppState().isArabic(context) ? 'ar_SA' : 'en_US';
|
||||
provider.toggleListening(localeId, _descriptionController);
|
||||
}
|
||||
: null,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(color: provider.isListening ? MyColors.gradiantEndColor.withOpacity(0.1) : Colors.transparent, borderRadius: BorderRadius.circular(20)),
|
||||
child: Icon(
|
||||
provider.isListening ? Icons.mic : Icons.mic_none,
|
||||
color: provider.isListening ? MyColors.gradiantEndColor : (provider.speechEnabled ? MyColors.grey57Color : Colors.grey.shade300),
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (provider.isListening)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Container(width: 8, height: 8, decoration: BoxDecoration(color: Colors.red, borderRadius: BorderRadius.circular(4))),
|
||||
const SizedBox(width: 8),
|
||||
Text('Listening...', style: TextStyle(fontSize: 12, color: MyColors.gradiantEndColor, fontWeight: FontWeight.w500)),
|
||||
],
|
||||
),
|
||||
),
|
||||
TextField(
|
||||
controller: _descriptionController,
|
||||
maxLines: 4,
|
||||
onChanged: (String value) => provider.setDescription(value),
|
||||
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: Color(0xff2B353E), letterSpacing: -0.44),
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
hintText: LocaleKeys.writeAMessage.tr(),
|
||||
hintStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: Color(0xff575757), letterSpacing: -0.56),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
border: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,106 @@
|
||||
import 'package:easy_localization/easy_localization.dart' as lclize;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:mohem_flutter_app/app_state/app_state.dart';
|
||||
import 'package:mohem_flutter_app/classes/colors.dart';
|
||||
import 'package:mohem_flutter_app/config/routes.dart';
|
||||
import 'package:mohem_flutter_app/extensions/int_extensions.dart' ;
|
||||
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
|
||||
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
|
||||
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
|
||||
import 'package:mohem_flutter_app/models/etqan_ovr/etqan_get_requests_model.dart';
|
||||
import 'package:mohem_flutter_app/provider/etqan_ovr_provider.dart';
|
||||
import 'package:mohem_flutter_app/classes/utils.dart';
|
||||
import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
|
||||
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:intl/src/intl/text_direction.dart' as intl;
|
||||
|
||||
class EtqanOvrHome extends StatefulWidget {
|
||||
const EtqanOvrHome({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_EtqanOvrHomeState createState() => _EtqanOvrHomeState();
|
||||
}
|
||||
|
||||
class _EtqanOvrHomeState extends State<EtqanOvrHome> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
context.read<EtqanOvrProviderModel>().fetchEtqanEmployeeRequests(context);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: AppBarWidget(context, title: LocaleKeys.etqanRequest.tr()),
|
||||
body: Consumer<EtqanOvrProviderModel>(
|
||||
builder: (BuildContext context, EtqanOvrProviderModel provider, Widget? child) {
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
(provider.getEtqanEmployeeRequestsList == null || provider.getEtqanEmployeeRequestsList!.isEmpty
|
||||
? Utils.getNoDataWidget(context)
|
||||
: ListView.separated(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
padding: const EdgeInsets.all(20),
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
EtqanGetEmployeeOvrRequestsResponse data = provider.getEtqanEmployeeRequestsList![index];
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
context.read<EtqanOvrProviderModel>().setTicketId(data.ticketNumber ?? '');
|
||||
Navigator.pushNamed(context, AppRoutes.etqanGetIncidientRequest);
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(15), border: Border.all(color: const Color(0xffefefef), width: 1)),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
(data.ticketNumber ?? "").toText14(isBold: true, color: MyColors.darkTextColor),
|
||||
Directionality(textDirection: TextDirection.ltr, child: (data.createdDate ?? "").toText12(color: MyColors.grey70Color)),
|
||||
],
|
||||
),
|
||||
8.height,
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
(data.description ?? "").toText12(color: MyColors.grey57Color),
|
||||
RotatedBox(
|
||||
quarterTurns: AppState().isArabic(context) ? 2 : 0,
|
||||
child: SvgPicture.asset("assets/images/arrow_next.svg", color: MyColors.grey70Color, width: 16, height: 16),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (BuildContext context, int index) => 12.height,
|
||||
itemCount: provider.getEtqanEmployeeRequestsList!.length,
|
||||
))
|
||||
.expanded,
|
||||
DefaultButton(LocaleKeys.createRequest.tr(), () async {
|
||||
await Navigator.pushNamed(context, AppRoutes.etqanCreateRequest);
|
||||
// getOpenTickets();
|
||||
}).insideContainer,
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,110 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mohem_flutter_app/classes/colors.dart';
|
||||
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
|
||||
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
|
||||
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
|
||||
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
|
||||
import 'package:mohem_flutter_app/models/etqan_ovr/etqan_get_employee_incident_report.dart';
|
||||
import 'package:mohem_flutter_app/provider/etqan_ovr_provider.dart';
|
||||
import 'package:mohem_flutter_app/classes/utils.dart';
|
||||
import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class EtqanOvrRequestDetailed extends StatefulWidget {
|
||||
const EtqanOvrRequestDetailed({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_EtqanOvrRequestDetailedState createState() => _EtqanOvrRequestDetailedState();
|
||||
}
|
||||
|
||||
class _EtqanOvrRequestDetailedState extends State<EtqanOvrRequestDetailed> {
|
||||
List<String> get fieldOrder => ['Project', 'Created', 'Occurrence Time', 'OVR Reference No', 'Involved Employee Number', 'Description'];
|
||||
|
||||
List<String> get hiddenFields => ['OVR Id', 'Is Anonymous'];
|
||||
|
||||
List<EtqanGetIncidentRequestResponse> _getOrderedList(List<EtqanGetIncidentRequestResponse> list) {
|
||||
List<EtqanGetIncidentRequestResponse> orderedList = [];
|
||||
|
||||
List<EtqanGetIncidentRequestResponse> filteredList = list.where((EtqanGetIncidentRequestResponse item) => !hiddenFields.any((f) => f.toLowerCase() == item.key?.toLowerCase())).toList();
|
||||
|
||||
for (String fieldName in fieldOrder) {
|
||||
var item = filteredList.firstWhere((e) => e.key?.toLowerCase() == fieldName.toLowerCase(), orElse: () => EtqanGetIncidentRequestResponse());
|
||||
if (item.key != null) {
|
||||
orderedList.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
for (var item in filteredList) {
|
||||
if (!fieldOrder.any((f) => f.toLowerCase() == item.key?.toLowerCase())) {
|
||||
orderedList.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
return orderedList;
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
var provider = context.read<EtqanOvrProviderModel>();
|
||||
provider.fetchEtqanEmployeeIncidentRequests(context, provider.getTicketId);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: AppBarWidget(context, title: LocaleKeys.etqanRequest.tr()),
|
||||
body: Consumer<EtqanOvrProviderModel>(
|
||||
builder: (BuildContext context, EtqanOvrProviderModel provider, Widget? child) {
|
||||
if (provider.getEtqanEmployeeIncidnetRequest == null || provider.getEtqanEmployeeIncidnetRequest!.isEmpty) {
|
||||
return Utils.getNoDataWidget(context);
|
||||
}
|
||||
|
||||
List<EtqanGetIncidentRequestResponse> orderedList = _getOrderedList(provider.getEtqanEmployeeIncidnetRequest!);
|
||||
|
||||
return SingleChildScrollView(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
border: Border.all(color: const Color(0xffefefef), width: 1),
|
||||
boxShadow: <BoxShadow>[BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2))],
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children:
|
||||
orderedList.asMap().entries.map((MapEntry<int, EtqanGetIncidentRequestResponse> entry) {
|
||||
int index = entry.key;
|
||||
EtqanGetIncidentRequestResponse data = entry.value;
|
||||
bool isLast = index == orderedList.length - 1;
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Expanded(flex: 2, child: (data.key ?? "").toText12(isBold: true, color: MyColors.grey57Color)),
|
||||
8.width,
|
||||
Expanded(flex: 3, child: (data.value ?? "-").toText14(color: MyColors.darkTextColor)),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (!isLast) const Padding(padding: EdgeInsets.only(left: 14, right: 14), child: Divider(height: 1, thickness: 1, color: Color(0xffefefef))),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue