You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
375 lines
12 KiB
Dart
375 lines
12 KiB
Dart
import 'dart:async';
|
|
import 'dart:developer';
|
|
import 'dart:io';
|
|
|
|
import 'package:connectivity/connectivity.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:just_audio/just_audio.dart';
|
|
import 'package:queuing_system/core/api.dart';
|
|
import 'package:queuing_system/core/base/app_scaffold_widget.dart';
|
|
import 'package:queuing_system/core/config/size_config.dart';
|
|
import 'package:queuing_system/core/response_model/call_config.dart';
|
|
import 'package:queuing_system/core/response_model/patient_call.dart';
|
|
import 'package:queuing_system/header/app_header.dart';
|
|
import 'package:queuing_system/home/home_screen_components.dart';
|
|
import 'package:queuing_system/utils/call_by_voice.dart';
|
|
import 'package:queuing_system/utils/call_type.dart';
|
|
import 'package:queuing_system/utils/signalR_utils.dart';
|
|
import 'package:queuing_system/utils/utils.dart';
|
|
import 'package:queuing_system/widget/data_display/app_texts_widget.dart';
|
|
|
|
var deviceIPGlobal = "10.10.15.11";
|
|
|
|
bool isDevMode = false; // Testing IP
|
|
|
|
// var DEVICE_IP = "10.10.14.11"; // Testing IP
|
|
// var DEVICE_IP = "10.10.15.11";
|
|
|
|
// var DEVICE_IP = "10.70.249.21"; // (Make sure by Haroon before use it) Production IP
|
|
|
|
class MyHomePage extends StatefulWidget {
|
|
final String title = "MyHomePage";
|
|
|
|
const MyHomePage({Key key}) : super(key: key);
|
|
|
|
@override
|
|
State<MyHomePage> createState() => _MyHomePageState();
|
|
}
|
|
|
|
class _MyHomePageState extends State<MyHomePage> {
|
|
SignalRHelper signalRHelper = SignalRHelper();
|
|
|
|
CallConfig callConfigsGlobal = CallConfig();
|
|
List<Tickets> waitings = [];
|
|
List<Tickets> isQueuePatients = [];
|
|
|
|
bool isLoading = false;
|
|
|
|
@override
|
|
void dispose() {
|
|
super.dispose();
|
|
}
|
|
|
|
Future<String> getCurrentIP() async {
|
|
final ips = await NetworkInterface.list(type: InternetAddressType.IPv4);
|
|
for (var interface in ips) {
|
|
//TODO: WE WILL UPDATE THIS WHEN TESTING ON SCREEN
|
|
// if (interface.name == "wlan0") {
|
|
if (interface.name == "eth0") {
|
|
for (var address in interface.addresses) {
|
|
deviceIPGlobal = address.address;
|
|
print("IP with eth0: ${address.address}");
|
|
return deviceIPGlobal;
|
|
}
|
|
}
|
|
if (interface.name == "wlan0") {
|
|
for (var address in interface.addresses) {
|
|
deviceIPGlobal = address.address;
|
|
print("IP with wlan0: ${address.address}");
|
|
return deviceIPGlobal;
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
return "";
|
|
}
|
|
|
|
final AudioPlayer audioPlayer = AudioPlayer();
|
|
|
|
@override
|
|
void initState() {
|
|
listenNetworkConnectivity();
|
|
scheduleMicrotask(() async {
|
|
if (!signalRHelper.getConnectionState()) {
|
|
signalRHelper.startSignalRConnection(await getCurrentIP(), onUpdateAvailable: onUpdateAvailable, onConnect: onConnect, onConnecting: onConnecting, onDisconnect: onDisconnect);
|
|
}
|
|
});
|
|
audioPlayer.playerStateStream.listen((playerState) {
|
|
if (playerState.processingState == ProcessingState.completed) {
|
|
isCallingInProgress = false;
|
|
print("isCallingInProgress in Stream: $isCallingInProgress");
|
|
}
|
|
});
|
|
super.initState();
|
|
}
|
|
|
|
TextEditingController controller = TextEditingController();
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return AppScaffold(
|
|
appBar: AppHeader(),
|
|
body: dataContent(audioPlayer),
|
|
bottomNavigationBar: Container(
|
|
color: Colors.grey.withOpacity(0.1),
|
|
height: Utils.getHeight(),
|
|
width: double.infinity,
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
const SizedBox(width: 20),
|
|
Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
InkWell(
|
|
onTap: () {
|
|
// onUpdateAvailable("");
|
|
},
|
|
child: AppText(
|
|
"Powered By",
|
|
fontSize: SizeConfig.getWidthMultiplier() * 2.6,
|
|
fontFamily: 'Poppins-Medium.ttf',
|
|
),
|
|
),
|
|
Text(deviceIPGlobal, style: TextStyle(fontWeight: FontWeight.w500, fontSize: SizeConfig.getWidthMultiplier() * 2.2)),
|
|
],
|
|
),
|
|
const SizedBox(width: 10),
|
|
Image.asset(
|
|
"assets/images/cloud_logo.png",
|
|
height: SizeConfig.getHeightMultiplier() * 4,
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
onUpdateIPPressed() async {
|
|
// if (controller.text.isNotEmpty) {
|
|
// isLoading = true;
|
|
// setState(() {});
|
|
// DEVICE_IP = controller.text;
|
|
//
|
|
// await signalRHelper.connection.stop();
|
|
// if (!signalRHelper.getConnectionState()) {
|
|
// await signalRHelper.startSignalRConnection(DEVICE_IP, onUpdateAvailable: onUpdateAvailable, onConnect: onConnect, onConnecting: onConnecting, onDisconnect: onDisconnect);
|
|
// }
|
|
//
|
|
// controller.clear();
|
|
// waitings.clear();
|
|
// isLoading = false;
|
|
// setState(() {});
|
|
// }
|
|
}
|
|
|
|
Widget dataContent(AudioPlayer audioPlayer) {
|
|
voiceCall(audioPlayer);
|
|
// print("wlength: ${waitings.length}");
|
|
// if (waitings.length > callConfigsGlobal.screenMaxDisplayPatients) {
|
|
// final newList = waitings.sublist(0, callConfigsGlobal.screenMaxDisplayPatients );
|
|
// print("wlength: ${newList.length}");
|
|
// }
|
|
|
|
if (waitings.isEmpty) {
|
|
// No Patient in Queue
|
|
return noPatientInQueue();
|
|
} else if (waitings.length > 3) {
|
|
// Return Content With Side List
|
|
return priorityTicketsWithSideList(waitings, callConfigsGlobal);
|
|
} else {
|
|
// Return Content In Center Aligned
|
|
return priorityTickets(waitings, callConfigsGlobal);
|
|
}
|
|
}
|
|
|
|
String getCallTypeText(Tickets ticket, CallConfig callConfig) {
|
|
final callType = ticket.getCallType();
|
|
final language = callConfig.screenLanguage;
|
|
switch (callType) {
|
|
case CallType.vitalSign:
|
|
return callConfig.vitalSignText;
|
|
case CallType.doctor:
|
|
return callConfig.doctorText;
|
|
case CallType.procedure:
|
|
return callConfig.procedureText;
|
|
case CallType.vaccination:
|
|
return callConfig.vaccinationText;
|
|
case CallType.nebulization:
|
|
return callConfig.nebulizationText;
|
|
break;
|
|
default:
|
|
return callConfig.vitalSignText;
|
|
}
|
|
}
|
|
|
|
CallByVoice voiceCaller;
|
|
|
|
int callFlag = 0;
|
|
|
|
// bool isRequiredVoice({CallType callType, bool isQueue}) {
|
|
// if (callType == CallType.DOCTOR && !isQueue) {
|
|
// return true;
|
|
// }
|
|
// if (callType == CallType.NURSE && !isQueue) {
|
|
// return true;
|
|
// }
|
|
// return false;
|
|
// }
|
|
|
|
bool isCallingInProgress = false;
|
|
|
|
voiceCall(AudioPlayer audioPlayer) async {
|
|
isCallingInProgress = true;
|
|
//DONE: After calling this voice call, we should delay for milliseconds that is given by API. After that we will check if there are more patients in isQueuePatients we will remove the patient from waiting list and then update the state
|
|
if (waitings.isNotEmpty) {
|
|
if (waitings.first.isToneReq && !waitings.first.isQueue) {
|
|
audioPlayer.setAsset("assets/tones/call_tone.mp3");
|
|
await audioPlayer.play();
|
|
await Future.delayed(const Duration(seconds: 2));
|
|
isCallingInProgress = false;
|
|
}
|
|
if (waitings.first.isVoiceReq && voiceCaller == null && !waitings.first.isQueue) {
|
|
final postVoice = getCallTypeText(waitings.first, callConfigsGlobal);
|
|
voiceCaller = CallByVoice(preVoice: "Ticket Number", ticketNo: waitings.first.queueNo.trim().toString(), postVoice: postVoice, lang: 'en');
|
|
await voiceCaller.startCalling(waitings.first.queueNo.trim().toString() != waitings.first.callNoStr.trim().toString());
|
|
voiceCaller = null;
|
|
isCallingInProgress = false;
|
|
}
|
|
}
|
|
if (isQueuePatients.isNotEmpty) {
|
|
await Future.delayed(Duration(seconds: isQueuePatients.first.concurrentCallDelaySec)).whenComplete(() async {
|
|
if (isQueuePatients.isNotEmpty) {
|
|
isQueuePatients.removeAt(0);
|
|
}
|
|
if (waitings.isNotEmpty) {
|
|
// Tickets ticket = waitings.elementAt(0);
|
|
// waitings.removeAt(0);
|
|
// waitings.add(ticket);
|
|
}
|
|
if (isQueuePatients.isNotEmpty) {
|
|
// setState(() {});
|
|
}
|
|
});
|
|
} else {
|
|
// if (isQueuePatients.isEmpty && callFlag == 1) {
|
|
// callFlag == 0;
|
|
// await Future.delayed(const Duration(seconds: 3));
|
|
// waitings.clear();
|
|
// API.getCallRequestInfoByClinicInfo(DEVICE_IP, onSuccess: (waitingCalls, isQueuePatientsCalls) {
|
|
// setState(() {
|
|
// waitings = waitingCalls;
|
|
// isQueuePatients = isQueuePatientsCalls;
|
|
// // currents = currentInClinic;
|
|
// });
|
|
//
|
|
// log("--------------------");
|
|
// log("waiting: $waitings");
|
|
// log("isQueuePatients: $isQueuePatients");
|
|
// log("--------------------");
|
|
//
|
|
// updateTickets();
|
|
// }, onFailure: (error) {});
|
|
// }
|
|
}
|
|
}
|
|
|
|
Future<void> callPatientsAPI() async {
|
|
waitings.clear();
|
|
API.getCallRequestInfoByClinicInfo(deviceIPGlobal, onSuccess: (waitingCalls, isQueuePatientsCalls, callConfigs) {
|
|
setState(() {
|
|
callConfigsGlobal = callConfigs;
|
|
if (waitingCalls.length > callConfigsGlobal.screenMaxDisplayPatients) {
|
|
waitings = waitingCalls.sublist(0, callConfigsGlobal.screenMaxDisplayPatients);
|
|
} else {
|
|
waitings = waitingCalls;
|
|
}
|
|
isQueuePatients = isQueuePatientsCalls;
|
|
// currents = currentInClinic;
|
|
});
|
|
|
|
log("--------------------");
|
|
log("waiting: $waitings");
|
|
log("isQueuePatients: $isQueuePatients");
|
|
log("--------------------");
|
|
|
|
updateTickets();
|
|
}, onFailure: (error) {});
|
|
}
|
|
|
|
onUpdateAvailable(data) async {
|
|
// if (isQueuePatients.isNotEmpty && callFlag == 0) {
|
|
// callFlag = 1;
|
|
// return;
|
|
// }
|
|
if (waitings.isNotEmpty) {
|
|
print("isCallingInProgress: ${isCallingInProgress}");
|
|
print("voiceCaller: ${voiceCaller == null}");
|
|
if ((waitings.first.isToneReq && isCallingInProgress) || (waitings.first.isVoiceReq && voiceCaller != null)) {
|
|
// if (true) {
|
|
print("I will wait now for ${callConfigsGlobal.concurrentCallDelaySec} seconds");
|
|
Timer(Duration(seconds: callConfigsGlobal.concurrentCallDelaySec), () async {
|
|
await callPatientsAPI();
|
|
});
|
|
} else {
|
|
await callPatientsAPI();
|
|
}
|
|
} else {
|
|
await callPatientsAPI();
|
|
}
|
|
}
|
|
|
|
updateTickets() {
|
|
if (waitings != null && waitings.isNotEmpty) {
|
|
List<Tickets> _ticketsToUpdate = waitings.where((t) => t.callUpdated == false).toList();
|
|
API.callUpdateNotIsQueueRecordByIDAsync(deviceIPGlobal, ticket: _ticketsToUpdate.first, onSuccess: (ticketsUpdated) {
|
|
log("[${ticketsUpdated.length}] Tickets Updated: $ticketsUpdated");
|
|
}, onFailure: (e) {
|
|
log("API UPDate Tickets Failed with : ${e.toString()}");
|
|
});
|
|
}
|
|
}
|
|
|
|
onConnect() {
|
|
log("SignalR: onConnect");
|
|
}
|
|
|
|
onDisconnect(exception) {
|
|
log("SignalR: onDisconnect");
|
|
signalRHelper.startSignalRConnection(deviceIPGlobal, onUpdateAvailable: onUpdateAvailable, onConnect: onConnect, onConnecting: onConnecting, onDisconnect: onDisconnect);
|
|
}
|
|
|
|
onConnecting() {
|
|
log("SignalR: onConnecting");
|
|
}
|
|
|
|
listenNetworkConnectivity() async {
|
|
Connectivity().onConnectivityChanged.listen((event) async {
|
|
switch (event) {
|
|
case ConnectivityResult.wifi:
|
|
await getCurrentIP();
|
|
signalRHelper.connection.start();
|
|
break;
|
|
case ConnectivityResult.none:
|
|
signalRHelper.closeConnection(context);
|
|
break;
|
|
case ConnectivityResult.mobile:
|
|
break;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
// if (isQueuePatients.length > 1) {
|
|
// Timer(Duration(milliseconds: int.parse(waitings.first.queueDuration)), () {
|
|
// Tickets calledTicket = Tickets();
|
|
// if (isQueuePatients.isNotEmpty) {
|
|
// calledTicket = isQueuePatients.elementAt(0);
|
|
// isQueuePatients.removeAt(0);
|
|
// }
|
|
// if (waitings.isNotEmpty) {
|
|
// // Tickets ticket = waitings.elementAt(0);
|
|
// // waitings.removeAt(0);
|
|
// // waitings.add(ticket);
|
|
// }
|
|
// if (isQueuePatients.isNotEmpty) {
|
|
// // setState(() {});
|
|
// }
|
|
// });
|
|
// }
|