Added AskPrescriptionFor Paharmacy

master
FaizHashmiCS22 5 months ago
parent b4d881d24e
commit e685cc9575

@ -1,4 +1,5 @@
import 'package:flutter/cupertino.dart';
import 'package:hmg_qline/views/kiosk_screens/kiosk_qr_scanner_screen.dart';
import 'package:hmg_qline/views/main_queue_screen/main_queue_screen.dart';
import 'package:hmg_qline/views/splash_screen/splash_screen.dart';
import 'package:hmg_qline/views/kiosk_screens/kiosk_main_screen.dart';
@ -8,11 +9,13 @@ class AppRoutes {
static const String splash = "/splash";
static const String mainQueueScreen = "/mainQueueScreen";
static const String kioskMainScreen = "/kioskMainScreen";
static const String kioskQrScannerScreen = "/kioskQrScannerScreen";
static const String initialRoute = splash;
static final Map<String, WidgetBuilder> routes = {
splash: (context) => const SplashScreen(),
kioskMainScreen: (context) => const KioskMainScreen(),
mainQueueScreen: (context) => const MainQueueScreen(),
kioskQrScannerScreen: (context) => KioskQrScannerScreen(),
};
}

@ -20,6 +20,7 @@ class AppStrings {
static String awaitingQueueNumberAr = "في انتظار رقم قائمة الانتظار";
static String counterNo = "Counter Number: ";
static String awaitingArrivalAr = "في انتظار وصول المرضى";
static String configurationIssueContactAdmin = "There is something wrong with configuration. Please contact Admin.";
}
class AppColors {
@ -29,6 +30,7 @@ class AppColors {
static Color blueColor = const Color(0xFF3C86D0);
static Color redColor = Colors.red;
static Color greenColor = Colors.green;
static Color whiteColor = Colors.white;
static Color yellowColor = const Color(0xFFC99609);
static Color brownColor = const Color(0xFF460707);
static Color blackColor = Colors.black54;

@ -1,4 +1,5 @@
import 'dart:ui';
import 'package:hmg_qline/models/kiosk_language_config_model.dart';
import 'package:hmg_qline/models/kiosk_queue_model.dart';
import 'package:hmg_qline/utilities/enums.dart';
import 'package:hmg_qline/utilities/extensions.dart';
@ -61,6 +62,7 @@ class GlobalConfigurationsModel {
double? projectLongitude;
int? cityKey;
List<KioskQueueModel>? kioskQueueList;
List<KioskLanguageConfigModel>? kioskLanguageConfigList;
GlobalConfigurationsModel({
this.id,
@ -120,6 +122,7 @@ class GlobalConfigurationsModel {
this.projectLongitude,
this.cityKey,
this.kioskQueueList,
this.kioskLanguageConfigList,
});
GlobalConfigurationsModel.fromJson(Map<String, dynamic> json) {
@ -183,6 +186,13 @@ class GlobalConfigurationsModel {
cityKey = json['cityKey'];
if (json['kioskQueue'] != null) {
kioskQueueList = List<KioskQueueModel>.from(json['kioskQueue'].map((kioskQueueJson) => KioskQueueModel.fromJson(kioskQueueJson)));
} else {
kioskQueueList = [];
}
if (json['kioskConfig'] != null) {
kioskLanguageConfigList = List<KioskLanguageConfigModel>.from(json['kioskConfig'].map((kioskQueueJson) => KioskLanguageConfigModel.fromJson(kioskQueueJson)));
} else {
kioskLanguageConfigList = [];
}
}
}

@ -0,0 +1,46 @@
import 'dart:ui' as ui;
class KioskLanguageConfigModel {
int? id;
int? languageID;
ui.TextDirection languageTextDirection;
String? languageName;
String? languageNameN;
String? shortForm;
String? yourTicketNoText;
String? waitForYourTurnText;
String? thankYouText;
String? goBackToMainPage;
bool? isActive;
KioskLanguageConfigModel({
required this.id,
required this.languageID,
this.languageTextDirection = ui.TextDirection.ltr,
required this.languageName,
required this.languageNameN,
required this.shortForm,
required this.yourTicketNoText,
required this.waitForYourTurnText,
required this.thankYouText,
required this.goBackToMainPage,
required this.isActive,
});
factory KioskLanguageConfigModel.fromJson(Map<String, dynamic> json) {
return KioskLanguageConfigModel(
id: json['id'],
languageID: json['languageID'],
languageTextDirection: ((json['languageTextDirection'] == null || json['languageTextDirection'] == 0 ) ? ui.TextDirection.ltr : ui.TextDirection.rtl),
// 0 for English and 1 for Others
languageName: json['languageName'],
languageNameN: json['languageNameN'],
shortForm: json['shortForm'],
yourTicketNoText: json['yourTicketNoText'],
waitForYourTurnText: json['waitForYourTurnText'],
thankYouText: json['thankYouText'],
goBackToMainPage: json['goBackToMainPage'],
isActive: json['isActive'],
);
}
}

@ -7,6 +7,8 @@ class KioskQueueModel {
String? queueName;
String? queueNameN;
int? kioskID;
bool? isPharmacyQueue;
String? kioskName;
String? kioskNameN;
String? ipAddress;
@ -25,6 +27,7 @@ class KioskQueueModel {
this.queueName,
this.queueNameN,
this.kioskID,
this.isPharmacyQueue,
this.kioskName,
this.kioskNameN,
this.ipAddress,
@ -44,6 +47,7 @@ class KioskQueueModel {
queueName = json['queueName'];
queueNameN = json['queueNameN'];
kioskID = json['kioskID'];
isPharmacyQueue = json['isPharmacyQueue'] ?? true;
kioskName = json['kioskName'];
kioskNameN = json['kioskNameN'];
ipAddress = json['ipAddress'];

@ -16,7 +16,7 @@ abstract class ScreenDetailsRepo {
Future<GenericRespModel?> createTestTickets({required int ticketNumber});
Future<GenericRespModel?> createTicketFromKiosk({required int projectId, required int queueId});
Future<GenericRespModel?> createTicketFromKiosk({required int projectId, required int queueId, int patientId = 0});
Future<WidgetsConfigModel?> getScreenConfigurationsByIP({required String ipAddress});
@ -85,11 +85,12 @@ class ScreenDetailsRepoImp implements ScreenDetailsRepo {
}
@override
Future<GenericRespModel?> createTicketFromKiosk({required int projectId, required int queueId}) async {
Future<GenericRespModel?> createTicketFromKiosk({required int projectId, required int queueId, int patientId = 0}) async {
try {
var params = {
"projectID": "$projectId",
"queueID": "$queueId",
"patientID": "$patientId",
"isVidaPlus": false,
"createdBy": "101",
"apiKey": AppConstants.apiKey,

@ -34,6 +34,7 @@ enum LanguageEnum {
enum KioskScreenStateEnums {
languageState,
queueSelectionState,
ticketNoState,
askPrescriptionState,
ticketNumState,
busyState,
}

@ -33,7 +33,11 @@ extension NavigationExt on BuildContext {
Navigator.pushReplacementNamed(this, route);
}
popView() => Navigator.of(this).pop();
navigateTo(String route) {
Navigator.pushNamed(this, route);
}
popScreen() => Navigator.of(this).pop();
}
extension ScreenOrientationExt on ScreenOrientationEnum {

@ -1,10 +1,11 @@
import 'dart:developer';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:hmg_qline/config/dependency_injection.dart';
import 'package:hmg_qline/constants/app_constants.dart';
import 'package:hmg_qline/models/generic_response_model.dart';
import 'package:hmg_qline/models/global_config_model.dart';
import 'package:hmg_qline/models/kiosk_language_config_model.dart';
import 'package:hmg_qline/models/kiosk_queue_model.dart';
import 'package:hmg_qline/models/kiosk_ticket_model.dart';
import 'package:hmg_qline/models/prayers_widget_model.dart';
@ -17,6 +18,7 @@ import 'package:hmg_qline/utilities/enums.dart';
import 'package:hmg_qline/utilities/extensions.dart';
import 'package:hmg_qline/view_models/queuing_view_model.dart';
import 'package:hmg_qline/views/view_helpers/info_components.dart';
import 'package:qr_code_scanner_plus/qr_code_scanner_plus.dart';
class ScreenConfigViewModel extends ChangeNotifier {
final ScreenDetailsRepo screenDetailsRepo;
@ -69,27 +71,6 @@ class ScreenConfigViewModel extends ChangeNotifier {
notifyListeners();
}
KioskScreenStateEnums kioskScreenStateEnum = KioskScreenStateEnums.languageState;
void updateKioskScreenState(KioskScreenStateEnums state) {
kioskScreenStateEnum = state;
notifyListeners();
}
KioskPatientTicket? kioskPatientTicket = KioskPatientTicket();
void updateTicketGeneratedFromKiosk(KioskPatientTicket? value) {
kioskPatientTicket = value;
notifyListeners();
}
LanguageEnum currentSelectedKioskLanguage = LanguageEnum.english;
void updateCurrentSelectedKioskLanguage(LanguageEnum value) {
currentSelectedKioskLanguage = value;
notifyListeners();
}
updateCurrentScreenRotation(ScreenOrientationEnum value) {
globalConfigurationsModel.orientationTypeEnum = value;
notifyListeners();
@ -132,10 +113,6 @@ class ScreenConfigViewModel extends ChangeNotifier {
GlobalConfigurationsModel globalConfigurationsModel = GlobalConfigurationsModel();
Future<void> getGlobalConfigurationsByIP() async {
// // TODO: TEST ONLY
// updateCurrentScreenTypeEnum(ScreenTypeEnum.kioskScreen);
// updateCurrentQTypeEnum(QTypeEnum.general);
GlobalConfigurationsModel? response = await screenDetailsRepo.getGlobalScreenConfigurations(ipAddress: currentScreenIP);
if (response == null) {
log("response; $response");
@ -318,6 +295,52 @@ class ScreenConfigViewModel extends ChangeNotifier {
}
}
// *************************** KIOSK FUNCTIONS *************************
KioskScreenStateEnums kioskScreenStateEnum = KioskScreenStateEnums.languageState;
void updateKioskScreenState(KioskScreenStateEnums state) {
kioskScreenStateEnum = state;
notifyListeners();
}
KioskPatientTicket? kioskPatientTicket = KioskPatientTicket();
void updateTicketGeneratedFromKiosk(KioskPatientTicket? value) {
kioskPatientTicket = value;
notifyListeners();
}
KioskLanguageConfigModel? currentSelectedKioskLanguage;
void updateCurrentSelectedKioskLanguageModel(KioskLanguageConfigModel value) {
currentSelectedKioskLanguage = value;
notifyListeners();
}
late KioskQueueModel currentSelectedKioskQueueModel;
void updateCurrentSelectedKioskQueueModel(KioskQueueModel value) {
currentSelectedKioskQueueModel = value;
notifyListeners();
}
Future<bool> generateTicketForQueue({required KioskQueueModel kioskQueueModel, int patientId = 0}) async {
updateKioskScreenState(KioskScreenStateEnums.busyState);
KioskPatientTicket? kioskPatientTicket = await createTicketFromKiosk(
projectId: kioskQueueModel.projectID ?? 0,
queueId: kioskQueueModel.queueID ?? 0,
patientId: patientId,
);
if (kioskPatientTicket == null) {
updateKioskScreenState(KioskScreenStateEnums.languageState);
return false;
}
updateTicketGeneratedFromKiosk(kioskPatientTicket);
updateKioskScreenState(KioskScreenStateEnums.ticketNumState);
return true;
}
Future<void> createTestTickets({required int numOfTicketsToCreate}) async {
int startTicket = 123457100;
@ -333,9 +356,13 @@ class ScreenConfigViewModel extends ChangeNotifier {
log("last ticket is: $startTicket ");
}
Future<KioskPatientTicket?> createTicketFromKiosk({required int projectId, required int queueId}) async {
Future<KioskPatientTicket?> createTicketFromKiosk({required int projectId, required int queueId, int patientId = 0}) async {
try {
GenericRespModel? response = await screenDetailsRepo.createTicketFromKiosk(projectId: projectId, queueId: queueId);
GenericRespModel? response = await screenDetailsRepo.createTicketFromKiosk(
projectId: projectId,
queueId: queueId,
patientId: patientId,
);
if (response == null || response.messageStatus != 1) {
logger.e("response null from createTicketFromKiosk");
return null;
@ -361,4 +388,82 @@ class ScreenConfigViewModel extends ChangeNotifier {
logger.i("response from acknowledgeTicket ${response.data}");
}
}
// ***************************** TEXT INPUT PATIENT ID FUNCTIONS *********************
final TextEditingController patientIdController = TextEditingController();
@override
void dispose() {
patientIdController.dispose();
super.dispose();
}
Future<void> onPatientIdSubmitted(String text) async {
int? patientId = int.tryParse(text);
if (patientId != null && patientId > 0) {
isGeneratingTicket = true;
await generateTicketForQueue(kioskQueueModel: currentSelectedKioskQueueModel, patientId: patientId);
patientIdController.clear();
await Future.delayed(const Duration(seconds: 2)).whenComplete(() => isGeneratingTicket = false);
}
}
// *************************** QR SCANNER FUNCTIONS *************************
Barcode? qrCodeResult;
QRViewController? qrViewController;
bool isGeneratingTicket = false;
Future<void> flipCamera() async {
await qrViewController!.flipCamera();
}
void onQRViewCreated({
required QRViewController controller,
required VoidCallback onSuccess,
required VoidCallback onFailure,
}) async {
qrViewController = controller;
controller.scannedDataStream.listen((scanData) async {
logger.i("Found: ${scanData.code} and isGeneratingTicket: $isGeneratingTicket");
if (isGeneratingTicket) return;
await validateAndGenerateTicketFromQR(data: scanData, onFailure: onFailure, onSuccess: onSuccess);
});
await flipCamera();
}
Future<void> validateAndGenerateTicketFromQR({required var data, required VoidCallback onSuccess, required VoidCallback onFailure}) async {
if (data == null) return;
qrCodeResult = data;
notifyListeners();
final code = qrCodeResult!.code;
int? patientId = int.tryParse(code ?? '');
if (patientId != null && patientId > 0) {
isGeneratingTicket = true;
bool status = await generateTicketForQueue(kioskQueueModel: currentSelectedKioskQueueModel, patientId: patientId);
qrCodeResult = null;
notifyListeners();
if (status) {
log("status: $status");
onSuccess();
}
await Future.delayed(const Duration(seconds: 2)).whenComplete(() => isGeneratingTicket = false);
}
}
Future<void> reassemble() async {
if (qrViewController != null) {
if (defaultTargetPlatform == TargetPlatform.android) {
await qrViewController!.pauseCamera();
} else if (defaultTargetPlatform == TargetPlatform.iOS) {
await qrViewController!.resumeCamera();
}
await qrViewController!.flipCamera();
}
}
}

@ -1,5 +1,3 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:hmg_qline/constants/app_constants.dart';
@ -160,7 +158,13 @@ Widget noPatientInQueue({required String text, required String fontName, require
}
}
Widget commonSelectionCardKiosk({required ScreenConfigViewModel screenConfigViewModel, required String title, required String icon, required VoidCallback onTap}) {
Widget commonSelectionCardKiosk({
required LanguageEnum screenLanguageEnum,
required TextDirection textDirection,
required String title,
required String icon,
required VoidCallback onTap,
}) {
return InkWell(
onTap: onTap,
child: SizedBox(
@ -170,7 +174,7 @@ Widget commonSelectionCardKiosk({required ScreenConfigViewModel screenConfigView
margin: const EdgeInsets.all(10),
decoration: AppColors.configWidgetDecoration,
child: Directionality(
textDirection: screenConfigViewModel.globalConfigurationsModel.textDirection,
textDirection: textDirection,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
@ -180,7 +184,7 @@ Widget commonSelectionCardKiosk({required ScreenConfigViewModel screenConfigView
title,
fontSize: SizeConfig.getWidthMultiplier() * 6,
fontHeight: 1,
fontFamily: screenConfigViewModel.globalConfigurationsModel.screenLanguageEnum == LanguageEnum.arabic ? AppStrings.fontNameCairo : AppStrings.fontNamePoppins,
fontFamily: screenLanguageEnum == LanguageEnum.arabic ? AppStrings.fontNameCairo : AppStrings.fontNamePoppins,
),
],
),
@ -189,3 +193,68 @@ Widget commonSelectionCardKiosk({required ScreenConfigViewModel screenConfigView
),
);
}
Widget commonShadowButton({
required LanguageEnum screenLanguageEnum,
required TextDirection textDirection,
required String title,
required String icon,
required double fontSize,
required VoidCallback onTap,
}) {
return InkWell(
onTap: onTap,
child: Container(
constraints: BoxConstraints(minWidth: SizeConfig.getWidthMultiplier() * 40),
padding: const EdgeInsets.all(30),
margin: const EdgeInsets.all(10),
decoration: AppColors.configWidgetDecoration,
child: Directionality(
textDirection: textDirection,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (icon.isNotEmpty) ...[
SvgPicture.asset(icon, height: SizeConfig.getWidthMultiplier() * 12),
const SizedBox(height: 15),
],
AppText(
title,
fontSize: fontSize,
fontFamily: screenLanguageEnum == LanguageEnum.arabic ? AppStrings.fontNameCairo : AppStrings.fontNamePoppins,
),
],
),
),
),
);
}
Widget customShadowTextField({
required TextEditingController controller,
required String hintText,
required Function(String) onSubmitted,
TextDirection textDirection = TextDirection.ltr,
TextInputType keyboardType = TextInputType.text,
bool obscureText = false,
}) {
return Container(
margin: const EdgeInsets.all(10),
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 8),
decoration: AppColors.configWidgetDecoration,
child: Directionality(
textDirection: textDirection,
child: TextField(
controller: controller,
keyboardType: keyboardType,
obscureText: obscureText,
decoration: InputDecoration(
hintText: hintText,
border: InputBorder.none,
),
style: const TextStyle(fontSize: 16),
onSubmitted: onSubmitted,
),
),
);
}

@ -4,6 +4,7 @@ class AppScaffold extends StatelessWidget {
final String appBarTitle;
final Widget body;
final bool isLoading;
final bool resizeToAvoidBottomInset;
final bool isShowAppBar;
final Widget? bottomSheet;
final Color? backgroundColor;
@ -19,6 +20,7 @@ class AppScaffold extends StatelessWidget {
this.appBarTitle = '',
required this.body,
this.isLoading = false,
this.resizeToAvoidBottomInset = false,
this.isShowAppBar = true,
this.bottomSheet,
this.backgroundColor,
@ -37,6 +39,7 @@ class AppScaffold extends StatelessWidget {
FocusScope.of(context).requestFocus(FocusNode());
},
child: Scaffold(
resizeToAvoidBottomInset: resizeToAvoidBottomInset,
backgroundColor: backgroundColor ?? Theme.of(context).scaffoldBackgroundColor,
drawer: drawer,
extendBody: extendBody,

@ -1,10 +1,8 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:hmg_qline/config/routes.dart';
import 'package:hmg_qline/constants/app_constants.dart';
import 'package:hmg_qline/models/generic_response_model.dart';
import 'package:hmg_qline/models/kiosk_language_config_model.dart';
import 'package:hmg_qline/models/kiosk_queue_model.dart';
import 'package:hmg_qline/models/kiosk_ticket_model.dart';
import 'package:hmg_qline/utilities/enums.dart';
import 'package:hmg_qline/utilities/extensions.dart';
import 'package:hmg_qline/view_models/screen_config_view_model.dart';
@ -23,28 +21,31 @@ class KioskMainScreen extends StatelessWidget {
return Consumer<ScreenConfigViewModel>(
builder: (BuildContext context, ScreenConfigViewModel screenConfigVM, Widget? child) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (screenConfigVM.globalConfigurationsModel.screenTypeEnum != ScreenTypeEnum.roomLevelScreen) ...[
Expanded(
flex: getFlexForScreenTypes(screenConfigVM),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Row(
children: [
if (screenConfigVM.globalConfigurationsModel.isWeatherReq) ...[
getWeatherWidget(screenConfigVM),
],
const SizedBox(width: 20),
if (screenConfigVM.globalConfigurationsModel.isPrayerTimeReq) ...[
getPrayerWidget(screenConfigVM),
if (screenConfigVM.globalConfigurationsModel.isWeatherReq || screenConfigVM.globalConfigurationsModel.isPrayerTimeReq) ...[
Expanded(
flex: getFlexForScreenTypes(screenConfigVM),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Row(
children: [
if (screenConfigVM.globalConfigurationsModel.isWeatherReq) ...[
getWeatherWidget(screenConfigVM),
],
const SizedBox(width: 20),
if (screenConfigVM.globalConfigurationsModel.isPrayerTimeReq) ...[
getPrayerWidget(screenConfigVM),
],
],
],
),
),
),
)
const SizedBox(height: 12),
]
],
const SizedBox(height: 12),
Expanded(flex: 10, child: dataContentKiosk(context: context)),
Expanded(flex: 10, child: Center(child: dataContentKiosk(context: context))),
if (!screenConfigVM.globalConfigurationsModel.isWeatherReq && !screenConfigVM.globalConfigurationsModel.isPrayerTimeReq) ...[
const SizedBox(height: 100),
],
@ -55,37 +56,45 @@ class KioskMainScreen extends StatelessWidget {
}
Widget kioskLanguageStateWidget(ScreenConfigViewModel screenConfigViewModel) {
bool isLanguageConfigAvailable = screenConfigViewModel.globalConfigurationsModel.kioskLanguageConfigList != null;
if (!isLanguageConfigAvailable) {
return noPatientInQueue(
text: AppStrings.configurationIssueContactAdmin,
fontName: AppStrings.fontNamePoppins,
isForRoomLevel: false,
isRoomNoRequired: false,
counterNo: 0,
roomText: '',
);
}
return GridView.builder(
itemCount: 2,
itemCount: isLanguageConfigAvailable ? screenConfigViewModel.globalConfigurationsModel.kioskLanguageConfigList!.length : 2,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemBuilder: (BuildContext context, int index) {
KioskLanguageConfigModel languageConfigModel = screenConfigViewModel.globalConfigurationsModel.kioskLanguageConfigList![index];
return Padding(
padding: const EdgeInsets.all(20),
child: commonSelectionCardKiosk(
screenConfigViewModel: screenConfigViewModel,
title: index == 0 ? "English" : "عربي",
textDirection: screenConfigViewModel.globalConfigurationsModel.textDirection,
screenLanguageEnum: screenConfigViewModel.globalConfigurationsModel.screenLanguageEnum,
title: languageConfigModel.languageName ?? "",
icon: AppAssets.languageIcon,
onTap: () async {
if (index == 0) {
if (screenConfigViewModel.globalConfigurationsModel.kioskQueueList != null && screenConfigViewModel.globalConfigurationsModel.kioskQueueList!.length == 1) {
await generateTicketForQueue(
screenConfigViewModel: screenConfigViewModel,
kioskQueueModel: screenConfigViewModel.globalConfigurationsModel.kioskQueueList![0],
);
screenConfigViewModel.updateCurrentSelectedKioskLanguageModel(languageConfigModel);
if (screenConfigViewModel.globalConfigurationsModel.kioskQueueList != null && screenConfigViewModel.globalConfigurationsModel.kioskQueueList!.length == 1) {
screenConfigViewModel.updateCurrentSelectedKioskQueueModel(screenConfigViewModel.globalConfigurationsModel.kioskQueueList!.first);
if (screenConfigViewModel.globalConfigurationsModel.kioskQueueList!.first.isPharmacyQueue ?? false) {
screenConfigViewModel.updateKioskScreenState(KioskScreenStateEnums.askPrescriptionState);
} else {
screenConfigViewModel.updateCurrentSelectedKioskLanguage(LanguageEnum.english);
screenConfigViewModel.updateKioskScreenState(KioskScreenStateEnums.queueSelectionState);
}
} else {
if (screenConfigViewModel.globalConfigurationsModel.kioskQueueList != null && screenConfigViewModel.globalConfigurationsModel.kioskQueueList!.length == 1) {
await generateTicketForQueue(
screenConfigViewModel: screenConfigViewModel,
kioskQueueModel: screenConfigViewModel.globalConfigurationsModel.kioskQueueList![0],
await screenConfigViewModel.generateTicketForQueue(
kioskQueueModel: screenConfigViewModel.currentSelectedKioskQueueModel,
);
} else {
screenConfigViewModel.updateCurrentSelectedKioskLanguage(LanguageEnum.arabic);
screenConfigViewModel.updateKioskScreenState(KioskScreenStateEnums.queueSelectionState);
}
} else {
screenConfigViewModel.updateKioskScreenState(KioskScreenStateEnums.queueSelectionState);
}
},
),
@ -94,11 +103,27 @@ class KioskMainScreen extends StatelessWidget {
);
}
Widget kioskQueueSelectionStateWidget(ScreenConfigViewModel screenConfigViewModel) {
bool isEnglish = screenConfigViewModel.currentSelectedKioskLanguage == LanguageEnum.english;
Widget configurationWidgetIssue() {
return Center(
child: noPatientInQueue(
text: AppStrings.configurationIssueContactAdmin,
fontName: AppStrings.fontNamePoppins,
isForRoomLevel: false,
isRoomNoRequired: false,
counterNo: 0,
roomText: '',
),
);
}
Widget kioskQueueSelectionStateWidget(ScreenConfigViewModel screenConfigViewModel) {
bool isQueueListAvailable = screenConfigViewModel.globalConfigurationsModel.kioskQueueList != null && screenConfigViewModel.globalConfigurationsModel.kioskQueueList!.isNotEmpty;
if (!isQueueListAvailable) {
return configurationWidgetIssue();
}
TextDirection textDirection = screenConfigViewModel.currentSelectedKioskLanguage?.languageTextDirection ?? TextDirection.ltr;
return Directionality(
textDirection: isEnglish ? TextDirection.ltr : TextDirection.rtl,
textDirection: textDirection,
child: GridView.builder(
itemCount: screenConfigViewModel.globalConfigurationsModel.kioskQueueList!.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
@ -113,11 +138,17 @@ class KioskMainScreen extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
children: [
commonSelectionCardKiosk(
screenConfigViewModel: screenConfigViewModel,
title: screenConfigViewModel.currentSelectedKioskLanguage == LanguageEnum.english ? "${kioskQueueModel.queueName}" : "${kioskQueueModel.queueNameN}",
textDirection: textDirection,
screenLanguageEnum: screenConfigViewModel.globalConfigurationsModel.screenLanguageEnum,
title: textDirection == TextDirection.ltr ? "${kioskQueueModel.queueName}" : "${kioskQueueModel.queueNameN}",
icon: AppAssets.kioskQueueIcon,
onTap: () async {
await generateTicketForQueue(screenConfigViewModel: screenConfigViewModel, kioskQueueModel: kioskQueueModel);
screenConfigViewModel.updateCurrentSelectedKioskQueueModel(kioskQueueModel);
if (kioskQueueModel.isPharmacyQueue ?? false) {
screenConfigViewModel.updateKioskScreenState(KioskScreenStateEnums.askPrescriptionState);
} else {
await screenConfigViewModel.generateTicketForQueue(kioskQueueModel: kioskQueueModel);
}
},
),
],
@ -126,17 +157,79 @@ class KioskMainScreen extends StatelessWidget {
);
}
Widget kioskAskPrescriptionState(ScreenConfigViewModel screenConfigViewModel, BuildContext context) {
KioskLanguageConfigModel? kioskSelectedLanguageModel = screenConfigViewModel.currentSelectedKioskLanguage;
TextDirection textDirection = screenConfigViewModel.currentSelectedKioskLanguage?.languageTextDirection ?? TextDirection.ltr;
String fontFamily = (textDirection == TextDirection.rtl) ? AppStrings.fontNameCairo : AppStrings.fontNamePoppins;
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: AppText(
"If you have a prescription. Please enter your patient number or scan your profile QR from Sulaiman Al Habib Mobile App?",
fontSize: SizeConfig.getWidthMultiplier() * 4,
textAlign: TextAlign.center,
textDirection: textDirection,
fontFamily: fontFamily,
),
),
customShadowTextField(
controller: screenConfigViewModel.patientIdController,
hintText: "Enter Patient ID here",
keyboardType: TextInputType.number,
onSubmitted: screenConfigViewModel.onPatientIdSubmitted,
),
commonShadowButton(
screenLanguageEnum: screenConfigViewModel.globalConfigurationsModel.screenLanguageEnum,
textDirection: textDirection,
title: "Scan QR from HMG App",
icon: "",
fontSize: SizeConfig.getWidthMultiplier() * 4,
onTap: () => context.navigateTo(AppRoutes.kioskQrScannerScreen)),
// const SizedBox(height: 50),
commonShadowButton(
screenLanguageEnum: screenConfigViewModel.globalConfigurationsModel.screenLanguageEnum,
textDirection: textDirection,
title: "I don't have a prescription.",
icon: "",
fontSize: SizeConfig.getWidthMultiplier() * 4,
onTap: () async {
await screenConfigViewModel.generateTicketForQueue(
kioskQueueModel: screenConfigViewModel.currentSelectedKioskQueueModel,
);
},
),
const SizedBox(height: 10),
InkWell(
onTap: () => screenConfigViewModel.updateKioskScreenState(KioskScreenStateEnums.languageState),
child: AppText(
kioskSelectedLanguageModel?.goBackToMainPage ?? "Go to Main Page",
fontSize: SizeConfig.getWidthMultiplier() * 4,
textAlign: TextAlign.center,
textDecoration: TextDecoration.underline,
textDirection: textDirection,
fontHeight: 1,
fontFamily: fontFamily,
),
),
],
);
}
Widget kioskTicketNumberStateWidget(ScreenConfigViewModel screenConfigViewModel) {
bool isEnglish = screenConfigViewModel.currentSelectedKioskLanguage == LanguageEnum.english;
KioskLanguageConfigModel? kioskSelectedLanguageModel = screenConfigViewModel.currentSelectedKioskLanguage;
TextDirection textDirection = screenConfigViewModel.currentSelectedKioskLanguage?.languageTextDirection ?? TextDirection.ltr;
String fontFamily = (textDirection == TextDirection.rtl) ? AppStrings.fontNameCairo : AppStrings.fontNamePoppins;
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AppText(
isEnglish ? "Your Ticket Number is: " : "رقم تذكرتك هو:",
kioskSelectedLanguageModel?.yourTicketNoText ?? "",
fontSize: SizeConfig.getWidthMultiplier() * 6,
textDirection: isEnglish ? TextDirection.ltr : TextDirection.rtl,
textDirection: textDirection,
fontHeight: 1,
fontFamily: isEnglish ? AppStrings.fontNameCairo : AppStrings.fontNamePoppins,
fontFamily: fontFamily,
),
const SizedBox(height: 20),
AppText(
@ -144,17 +237,17 @@ class KioskMainScreen extends StatelessWidget {
fontSize: SizeConfig.getWidthMultiplier() * 10,
fontHeight: 1,
fontWeight: FontWeight.bold,
textDirection: isEnglish ? TextDirection.ltr : TextDirection.rtl,
fontFamily: isEnglish ? AppStrings.fontNameCairo : AppStrings.fontNamePoppins,
textDirection: textDirection,
fontFamily: fontFamily,
),
const SizedBox(height: 20),
AppText(
isEnglish ? "Please take the receipt and wait for your turn. \nThank you 😊" : "يرجى أخذ الإيصال وانتظار دورك.\n شكرًا لك 😊",
"${kioskSelectedLanguageModel?.waitForYourTurnText ?? "Please take the receipt and wait for your turn."} \n ${kioskSelectedLanguageModel?.thankYouText ?? "Thank you"}",
fontSize: SizeConfig.getWidthMultiplier() * 3,
textAlign: TextAlign.center,
textDirection: isEnglish ? TextDirection.ltr : TextDirection.rtl,
textDirection: textDirection,
fontHeight: 1,
fontFamily: isEnglish ? AppStrings.fontNameCairo : AppStrings.fontNamePoppins,
fontFamily: fontFamily,
),
const SizedBox(height: 100),
InkWell(
@ -162,36 +255,19 @@ class KioskMainScreen extends StatelessWidget {
screenConfigViewModel.updateKioskScreenState(KioskScreenStateEnums.languageState);
},
child: AppText(
isEnglish ? "Go to Main Page" : "اذهب إلى الصفحة الرئيسية",
kioskSelectedLanguageModel?.goBackToMainPage ?? "Go to Main Page",
fontSize: SizeConfig.getWidthMultiplier() * 3,
textAlign: TextAlign.center,
textDecoration: TextDecoration.underline,
textDirection: isEnglish ? TextDirection.ltr : TextDirection.rtl,
textDirection: textDirection,
fontHeight: 1,
fontFamily: isEnglish ? AppStrings.fontNameCairo : AppStrings.fontNamePoppins,
fontFamily: fontFamily,
),
),
],
);
}
Future<void> generateTicketForQueue({
required ScreenConfigViewModel screenConfigViewModel,
required KioskQueueModel kioskQueueModel,
}) async {
screenConfigViewModel.updateKioskScreenState(KioskScreenStateEnums.busyState);
KioskPatientTicket? kioskPatientTicket = await screenConfigViewModel.createTicketFromKiosk(
projectId: kioskQueueModel.projectID ?? 0,
queueId: kioskQueueModel.queueID ?? 0,
);
if (kioskPatientTicket == null) {
screenConfigViewModel.updateKioskScreenState(KioskScreenStateEnums.languageState);
return;
}
screenConfigViewModel.updateTicketGeneratedFromKiosk(kioskPatientTicket);
screenConfigViewModel.updateKioskScreenState(KioskScreenStateEnums.ticketNoState);
}
Widget dataContentKiosk({required BuildContext context}) {
return Padding(
padding: const EdgeInsets.all(10),
@ -200,8 +276,9 @@ class KioskMainScreen extends StatelessWidget {
return switch (screenConfigViewModel.kioskScreenStateEnum) {
KioskScreenStateEnums.languageState => kioskLanguageStateWidget(screenConfigViewModel),
KioskScreenStateEnums.queueSelectionState => kioskQueueSelectionStateWidget(screenConfigViewModel),
KioskScreenStateEnums.ticketNoState => kioskTicketNumberStateWidget(screenConfigViewModel),
KioskScreenStateEnums.busyState => const Center(child: CircularProgressIndicator()),
KioskScreenStateEnums.askPrescriptionState => kioskAskPrescriptionState(screenConfigViewModel, context),
KioskScreenStateEnums.ticketNumState => kioskTicketNumberStateWidget(screenConfigViewModel),
KioskScreenStateEnums.busyState => const CircularProgressIndicator(),
};
},
),
@ -216,6 +293,7 @@ class KioskMainScreen extends StatelessWidget {
return RotatedBox(
quarterTurns: screenOrientationEnum.getTurnsByOrientation(),
child: AppScaffold(
resizeToAvoidBottomInset: false,
appBar: const AppHeader(),
body: getBody(context: context),
bottomNavigationBar: const AppFooter(),

@ -0,0 +1,142 @@
import 'package:flutter/material.dart';
import 'package:hmg_qline/constants/app_constants.dart';
import 'package:hmg_qline/utilities/extensions.dart';
import 'package:hmg_qline/view_models/screen_config_view_model.dart';
import 'package:hmg_qline/views/view_helpers/size_config.dart';
import 'package:provider/provider.dart';
import 'package:qr_code_scanner_plus/qr_code_scanner_plus.dart';
class KioskQrScannerScreen extends StatelessWidget {
KioskQrScannerScreen({super.key});
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
@override
Widget build(BuildContext context) {
final screenConfigViewModel = context.read<ScreenConfigViewModel>();
final size = MediaQuery.of(context).size;
final scanArea = (size.width < size.height ? size.width : size.height) * 0.6;
return Scaffold(
body: SafeArea(
child: Stack(
children: [
Column(
children: <Widget>[
Expanded(
flex: 9,
child: QRView(
key: qrKey,
overlay: QrScannerOverlayShape(
borderColor: AppColors.redColor,
borderRadius: 10,
borderLength: 30,
borderWidth: 10,
cutOutSize: scanArea,
),
onQRViewCreated: (controller) {
screenConfigViewModel.onQRViewCreated(
controller: controller,
onSuccess: () => context.popScreen(),
onFailure: () {},
);
}),
),
],
),
Positioned(
top: 0,
left: 0,
right: 0,
child: Container(
color: Colors.black.withOpacity(0.4),
padding: const EdgeInsets.all(16),
child: Align(
alignment: Alignment.centerLeft,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
onTap: () => context.popScreen(),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(
Icons.arrow_back,
color: AppColors.whiteColor,
size: SizeConfig.getHeightMultiplier() * 0.3,
),
const SizedBox(width: 8),
Text(
'Back',
style: TextStyle(
color: AppColors.whiteColor,
fontSize: SizeConfig.getHeightMultiplier() * 0.3,
fontWeight: FontWeight.w500,
),
),
],
),
),
GestureDetector(
onTap: () => screenConfigViewModel.flipCamera(),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(
Icons.flip_camera_ios_outlined,
color: AppColors.whiteColor,
size: SizeConfig.getHeightMultiplier() * 0.4,
),
],
),
),
],
),
),
),
),
Positioned(
bottom: SizeConfig.getHeightMultiplier() * 0.5,
left: 0,
right: 0,
child: Center(
child: Consumer<ScreenConfigViewModel>(
builder: (BuildContext context, ScreenConfigViewModel screenConfigViewModel, _) {
String text = "";
if (screenConfigViewModel.qrCodeResult != null) {
final code = screenConfigViewModel.qrCodeResult?.code;
int? patientId = int.tryParse(code ?? '');
if (patientId != null && patientId > 0) {
text = "Patient ID: $patientId\nGenerating Ticket...";
} else {
text = "Invalid QR Code. Please scan a valid patient ID.";
}
} else {
text = "Please scan your Patient QR from Sulaiman Al Habib Mobile App";
}
return Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
text,
textAlign: TextAlign.center,
style: TextStyle(
color: AppColors.whiteColor,
fontSize: SizeConfig.getHeightMultiplier() * 0.3,
fontWeight: FontWeight.w500,
),
),
);
},
),
),
),
],
),
),
);
}
}

@ -47,6 +47,7 @@ class SplashScreen extends StatelessWidget {
// If the data is loaded successfully
if (snapshot.connectionState == ConnectionState.done) {
Future.delayed(const Duration(seconds: 1)).whenComplete(() {
log("context.read<ScreenConfigViewModel>().currentScreenTypeEnum: ${context.read<ScreenConfigViewModel>().currentScreenTypeEnum}");
if (context.read<ScreenConfigViewModel>().currentScreenTypeEnum == ScreenTypeEnum.kioskScreen) {
context.navigateReplaceTo(AppRoutes.kioskMainScreen);
} else {

@ -6,10 +6,6 @@
#include "generated_plugin_registrant.h"
#include <charset_converter/charset_converter_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) charset_converter_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "CharsetConverterPlugin");
charset_converter_plugin_register_with_registrar(charset_converter_registrar);
}

@ -3,7 +3,6 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
charset_converter
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST

@ -1,14 +1,6 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
archive:
dependency: transitive
description:
name: archive
sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d
url: "https://pub.dev"
source: hosted
version: "3.6.1"
args:
dependency: transitive
description:
@ -57,14 +49,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.0"
charset_converter:
dependency: transitive
description:
name: charset_converter
sha256: a601f27b78ca86c3d88899d53059786d9c3f3c485b64974e9105c06c2569aef5
url: "https://pub.dev"
source: hosted
version: "2.3.0"
clock:
dependency: transitive
description:
@ -105,14 +89,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.6"
csslib:
dependency: transitive
description:
name: csslib
sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e"
url: "https://pub.dev"
source: hosted
version: "1.0.2"
cupertino_icons:
dependency: "direct main"
description:
@ -137,22 +113,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.7"
esc_pos_printer:
dependency: "direct main"
description:
name: esc_pos_printer
sha256: "312b05f909f3f7dd1e6a3332cf384dcee2c3a635138823654cd9c0133d8b5c45"
url: "https://pub.dev"
source: hosted
version: "4.1.0"
esc_pos_utils:
dependency: "direct main"
description:
name: esc_pos_utils
sha256: "8ec0013d7a7f1e790ced6b09b95ce3bf2c6f9468a3e2bc49ece000761d86c6f8"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
fading_edge_scrollview:
dependency: transitive
description:
@ -240,14 +200,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "8.2.8"
gbk_codec:
dependency: transitive
description:
name: gbk_codec
sha256: "3af5311fc9393115e3650ae6023862adf998051a804a08fb804f042724999f61"
url: "https://pub.dev"
source: hosted
version: "0.4.0"
get_it:
dependency: "direct main"
description:
@ -256,24 +208,8 @@ packages:
url: "https://pub.dev"
source: hosted
version: "8.0.3"
hex:
dependency: transitive
description:
name: hex
sha256: "4e7cd54e4b59ba026432a6be2dd9d96e4c5205725194997193bf871703b82c4a"
url: "https://pub.dev"
source: hosted
version: "0.2.0"
html:
dependency: transitive
description:
name: html
sha256: "1fc58edeaec4307368c60d59b7e15b9d658b57d7f3125098b6294153c75337ec"
url: "https://pub.dev"
source: hosted
version: "0.15.5"
http:
dependency: "direct main"
dependency: "direct overridden"
description:
name: http
sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010
@ -288,14 +224,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.2"
image:
dependency: transitive
description:
name: image
sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6"
url: "https://pub.dev"
source: hosted
version: "3.3.0"
intl:
dependency: "direct main"
description:
@ -528,14 +456,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.8"
pool:
dependency: transitive
description:
name: pool
sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
url: "https://pub.dev"
source: hosted
version: "1.5.1"
provider:
dependency: "direct main"
description:
@ -544,6 +464,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "6.1.2"
qr_code_scanner_plus:
dependency: "direct main"
description:
name: qr_code_scanner_plus
sha256: "39696b50d277097ee4d90d4292de36f38c66213a4f5216a06b2bdd2b63117859"
url: "https://pub.dev"
source: hosted
version: "2.0.10+1"
rxdart:
dependency: transitive
description:
@ -608,22 +536,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.4.1"
shelf:
dependency: transitive
description:
name: shelf
sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
url: "https://pub.dev"
source: hosted
version: "1.4.1"
signalr_core:
dependency: "direct main"
description:
name: signalr_core
sha256: "27c4ce798c8fedc2f7e3e4668c2b1dbcf6ee2a93f40ad24284b5f5bbed84529d"
sha256: dca676372a00c051511591ed0e24521ff7aa4e9320a7fa778a1007f7f522c8c0
url: "https://pub.dev"
source: hosted
version: "1.1.2"
version: "1.1.1"
sky_engine:
dependency: transitive
description: flutter
@ -645,22 +565,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "7.0.0"
sse:
sse_client:
dependency: transitive
description:
name: sse
sha256: "4389a01d5bc7ef3e90fbc645f8e7c6d8711268adb1f511e14ae9c71de47ee32b"
name: sse_client
sha256: "71bd826430b41ab20a69d85bf2dfe9f11cfe222938e681ada1aea71fc8adf348"
url: "https://pub.dev"
source: hosted
version: "4.1.7"
sse_channel:
dependency: transitive
description:
name: sse_channel
sha256: "9aad5d4eef63faf6ecdefb636c0f857bd6f74146d2196087dcf4b17ab5b49b1b"
url: "https://pub.dev"
source: hosted
version: "0.1.1"
version: "0.1.0"
stack_trace:
dependency: transitive
description:
@ -785,18 +697,18 @@ packages:
dependency: transitive
description:
name: web
sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
url: "https://pub.dev"
source: hosted
version: "0.5.1"
version: "1.1.1"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
sha256: "58c6666b342a38816b2e7e50ed0f1e261959630becd4c879c4f26bfa14aa5a42"
sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
url: "https://pub.dev"
source: hosted
version: "2.4.5"
version: "2.4.0"
win32:
dependency: transitive
description:

@ -40,7 +40,7 @@ dependencies:
get_it: ^8.0.2
connectivity_plus: ^6.1.0
flutter_svg: ^2.0.14
http: ^1.2.2
# http: ^1.2.2
blinking_text: ^1.0.2
just_audio: ^0.9.42
flutter_tts: ^4.2.0
@ -51,12 +51,14 @@ dependencies:
marquee: ^2.2.3
logger: ^2.4.0
fluttertoast: ^8.2.8
esc_pos_printer: ^4.0.0 # Ensure you are using the latest version
esc_pos_utils: ^1.0.0
qr_code_scanner_plus: ^2.0.10+1
# esc_pos_printer: ^4.0.0 # Ensure you are using the latest version
# esc_pos_utils: ^1.0.0
# win32: ^5.8.0
# tuple: ^2.0.2
dependency_overrides:
http: ^1.2.2
dev_dependencies:
flutter_test:

@ -6,13 +6,10 @@
#include "generated_plugin_registrant.h"
#include <charset_converter/charset_converter_plugin.h>
#include <connectivity_plus/connectivity_plus_windows_plugin.h>
#include <flutter_tts/flutter_tts_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
CharsetConverterPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("CharsetConverterPlugin"));
ConnectivityPlusWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin"));
FlutterTtsPluginRegisterWithRegistrar(

@ -3,7 +3,6 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
charset_converter
connectivity_plus
flutter_tts
)

Loading…
Cancel
Save