import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_pos_printer_platform_image_3/flutter_pos_printer_platform_image_3.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:ticket_booth/app/print_ticket.dart'; import 'package:ticket_booth/app/route.dart'; import 'package:ticket_booth/model/booth.dart'; import 'package:ticket_booth/model/branch_model.dart'; import 'package:ticket_booth/model/printer_device.dart'; import 'package:ticket_booth/provider/all_service_provider.dart'; import 'package:intl/intl.dart'; import 'package:ticket_booth/screen/queue/queue_provider.dart'; import 'package:ticket_booth/screen/widgets/dialog_print.dart'; import 'package:ticket_booth/screen/widgets/pasien_online_dialog.dart'; import '../../app/constant.dart'; import '../../model/cabapility_model.dart'; import '../../model/layanan.dart'; import '../widgets/error_dialog.dart'; class QueueScreen extends HookConsumerWidget { const QueueScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final isLoading = useState(true); final lyn = useState>(List.empty()); final activeLayanan = useState>(List.empty()); final selectedPrinter = useState(PrinterDev(deviceName: "a", id: 0)); final selectedBooth = useState(Booth(name: 'B001', id: 0, code: 'a')); final hostIp = useState('N'); final hostqR = useState('N'); final headerDisplay = useState('N'); final headerTicket = useState('N'); final footerTicket = useState('N'); final footerDisplay = useState('N'); final isLoadingPrint = useState(false); final errorMsg = useState(''); final splitedHost = useState(''); final tapAnimation = useState(0); final selectedCapabilityProfile = useState(CapabilityProfileModel()); final selectedBranch = useState(null); final selectedLayanan = useState(Layanan( name: 'x', id: 0, priority: 0, isConsultDoctor: 'n', code: '0')); final getNumberLoading = useState(false); final btnSize = useState>({'name': 'n'}); Future getData() async { try { final prefs = await SharedPreferences.getInstance(); var raw_data = prefs.getString('tb-westerindo') ?? 'a'; if (raw_data != 'a') { List allLayanan = ref.read(allServiceProvider); var data = json.decode(raw_data); hostIp.value = data['hostIp']; hostqR.value = data['hostQrIp']; headerDisplay.value = data['headerDisplay']; headerTicket.value = data['headerTicket']; footerTicket.value = data['footerTicket']; footerDisplay.value = data['footerDisplay']; selectedPrinter.value = PrinterDev.fromJson(data['selectedPrinter']); selectedBooth.value = Booth.fromJson(data['selectedBooth']); selectedBranch.value = BranchModel.fromJson(data['selectedBranch']); selectedCapabilityProfile.value = CapabilityProfileModel.fromJson(data['selectedCapability']); activeLayanan.value = data['activeLayanan']; btnSize.value = data['buttonSize']; print(btnSize.value); var sp = hostIp.value.split(':'); splitedHost.value = sp[0] + ":" + sp[1]; List actvLayanan = []; activeLayanan.value.forEach((e) { allLayanan.forEach((f) { if (e == f.id) { actvLayanan.add(f); } }); }); actvLayanan.sort(((a, b) => a.priority.compareTo(b.priority))); lyn.value = actvLayanan; } else { Navigator.of(context).popAndPushNamed(settingRoute); } isLoading.value = false; } catch (e) { print(e); ErrorDialog(context, e.toString(), 'ERROR'); isLoading.value = false; } } getDataApi(e) { ref.read(QueueProvider.notifier).get( branchID: selectedBranch.value?.mBranchID, booth_id: selectedBooth.value.id, service_id: e.id, hostIp: hostIp.value); } printTicketDialog(String number) { try { // DialogPrint(context, number); PrintTicket().printTicket( boothId: selectedBooth.value.name.toString(), header: headerTicket.value, date: 'a', time: 'a', antrianNumb: number, name: '', StringqrCode: hostqR.value, location: '', footer: footerTicket.value, DoctorName: selectedLayanan.value.doctorName, isConsult: selectedLayanan.value.isConsultDoctor, capabilityName: selectedCapabilityProfile.value.key ?? "default", layananName: selectedLayanan.value.name); } catch (e) { errorMsg.value = e.toString(); ErrorDialog(context, errorMsg.value, 'ERROR'); } } ref.listen(QueueProvider, (previous, next) { if (next is QueueStateLoading) { isLoadingPrint.value = true; } else if (next is QueueStateError) { errorMsg.value = next.message; ErrorDialog(context, errorMsg.value, 'ERROR'); getNumberLoading.value = false; } else if (next is QueueStateDone) { String number = next.response['data']['number'].toString(); String location = next.response['data']['location'].toString(); // print(location); DialogPrint( context, number, printTicketDialog, selectedLayanan.value.name); try { // PrintTicket().printTicket( // boothId: selectedBooth.value.name.toString(), // header: headerTicket.value, // date: 'a', // time: 'a', // antrianNumb: number, // name: '', // StringqrCode: hostqR.value, // location: location, // footer: footerTicket.value, // DoctorName: selectedLayanan.value.doctorName, // isConsult: selectedLayanan.value.isConsultDoctor, // capabilityName: selectedCapabilityProfile.value.key ?? "default", // layananName: selectedLayanan.value.name); } catch (e) { errorMsg.value = e.toString(); ErrorDialog(context, errorMsg.value, 'ERROR'); } Timer(Duration(seconds: 2), () { getNumberLoading.value = false; }); } }); useEffect(() { WidgetsBinding.instance.addPostFrameCallback((timeStamp) { getData(); }); return () {}; }, []); return Material( child: Container( height: Constant.getActualY(context: context, y: 982), width: Constant.getActualX(context: context, x: 1512), decoration: const BoxDecoration( image: DecorationImage( fit: BoxFit.cover, image: AssetImage("assets/images/new-bg.png"))), child: isLoading.value ? const SpinKitCubeGrid( color: Colors.blue, ) : Column( children: [ SizedBox( height: Constant.getActualY(context: context, y: 150), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ GestureDetector( onTap: () { // Navigator.of(context).popAndPushNamed(displayRoute); }, child: Container( width: Constant.getActualX(context: context, x: 150), height: Constant.getActualY(context: context, y: 150), margin: EdgeInsets.only( left: Constant.getActualX( context: context, x: 30)), padding: const EdgeInsets.all(20), child: Image.network( '${splitedHost.value.toString()}/one-media/one-queue/logo-westerindo.png', loadingBuilder: (context, child, loadingProgress) { if (loadingProgress == null) return child; return const CircularProgressIndicator(); }, errorBuilder: (context, error, stackTrace) { return Image.asset( 'assets/images/logo-westerindo.png', ); }, )), ), Text( headerDisplay.value, style: Constant.title(context: context), ), Container( alignment: Alignment.center, margin: EdgeInsets.only( right: Constant.getActualX(context: context, x: 30)), padding: const EdgeInsets.all(20), width: Constant.getActualX(context: context, x: 150), height: Constant.getActualY(context: context, y: 150), child: Text(selectedBranch.value?.mBranchName ?? "", textAlign: TextAlign.center, style: Constant.label(context: context).copyWith( fontWeight: FontWeight.bold, )), ), ], ), ), SizedBox( height: Constant.getActualY(context: context, y: 682), child: Row( children: [ Container( width: Constant.getActualX( context: context, x: double.parse(btnSize.value['rightLeftWidth'])), // color: Colors.green, ), Container( // color: Colors.red, width: Constant.getActualX( context: context, x: double.parse(btnSize.value['centerWidth'])), child: GridView.count( crossAxisCount: int.parse(btnSize.value['column']), childAspectRatio: double.parse(btnSize.value['childAspectRatio']), mainAxisSpacing: Constant.getActualY( context: context, y: double.parse( btnSize.value['mainAxisSpacing'])), crossAxisSpacing: Constant.getActualY( context: context, y: double.parse( btnSize.value['crossAxisSpacing'])), children: lyn.value .map((e) => ButtonLayanan( getNumberLoading, tapAnimation, e, selectedLayanan, context, getDataApi, btnSize, splitedHost)) .toList()), ), Container( width: Constant.getActualX( context: context, x: double.parse(btnSize.value['rightLeftWidth'])), // color: Colors.green, ) ], ), ), SizedBox( height: Constant.getActualY(context: context, y: 150), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( width: Constant.getActualX(context: context, x: 200), margin: EdgeInsets.only( left: Constant.getActualX(context: context, x: 30)), padding: EdgeInsets.all(20), child: Center( child: Text( selectedBooth.value.name, style: Constant.subTitle(context: context), ), )), Text( footerDisplay.value, style: Constant.title(context: context).copyWith( fontStyle: FontStyle.italic, fontWeight: FontWeight.normal), ), const DisplayClock(), ], ), ) ], ), )); } Container ButtonLayanan( ValueNotifier getNumberLoading, ValueNotifier tapAnimation, Layanan e, ValueNotifier selectedLayanan, BuildContext context, Null getDataApi(dynamic e), ValueNotifier> btnSize, ValueNotifier splitedHost) { return Container( // color: Colors.amber, child: Center( child: InkWell( onTap: getNumberLoading.value ? null : () { // DialogPrint(context, 'A0001'); // PasienOnlineDialog(context); // return; tapAnimation.value = e.id; selectedLayanan.value = e; getNumberLoading.value = true; if (e.name == "Pasien Online" && e.id == 5) { } else { getDataApi(e); } Timer(Duration(milliseconds: 250), () { tapAnimation.value = 0; }); Timer(Duration(seconds: 2), () { getNumberLoading.value = false; print("tidak loading"); }); }, child: Ink( // color: Colors.green, height: Constant.getActualY( context: context, y: double.parse(btnSize.value['btnHeight'])), width: Constant.getActualX( context: context, x: double.parse(btnSize.value['btnWidth'])), child: Stack( alignment: AlignmentDirectional.center, children: [ Image.network( '${splitedHost.value.toString()}/one-media/one-queue/${e.code}.png', fit: BoxFit.cover, color: e.id == tapAnimation.value ? Colors.grey : Colors.white, // color: Colors.white // .withOpacity(e.id == // tapAnimation.value // ? 0.7 // : 1), colorBlendMode: BlendMode.modulate, height: Constant.getActualY( context: context, y: e.id == tapAnimation.value ? 310 : 400), width: Constant.getActualX( context: context, x: e.id == tapAnimation.value ? 280 : 300), loadingBuilder: (context, child, loadingProgress) { if (loadingProgress == null) return child; return const CircularProgressIndicator(); }, errorBuilder: (context, error, stackTrace) { return Image.asset( 'assets/images/cpone-default.png', fit: BoxFit.cover, color: e.id == tapAnimation.value ? Colors.grey : Colors.white, colorBlendMode: BlendMode.modulate, height: Constant.getActualY( context: context, y: e.id == tapAnimation.value ? 310 : 400), width: Constant.getActualX( context: context, x: e.id == tapAnimation.value ? 280 : 300), ); }, ), Positioned( top: 1, child: Container( margin: EdgeInsets.only( top: Constant.getActualY(context: context, y: 10)), padding: EdgeInsets.symmetric( horizontal: Constant.getActualX(context: context, x: 10)), // color: Colors.red, height: Constant.getActualY(context: context, y: 110), width: Constant.getActualX(context: context, x: 280), child: Center( child: e.isConsultDoctor == 'N' ? Text( e.name, maxLines: 2, textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, style: Constant.layananTitle(context: context) .copyWith(color: Colors.white), ) : Column( children: [ Text( e.name, maxLines: 2, textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, style: Constant.layananTitle(context: context) .copyWith(color: Colors.white), ), Text( e.doctorName, maxLines: 1, textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, style: Constant.layananTitle(context: context) .copyWith(color: Colors.white), ) ], ), ), ), ) ], ), ), ), ), ); } } class DisplayClock extends HookConsumerWidget { const DisplayClock({ Key? key, }) : super(key: key); @override Widget build(BuildContext context, WidgetRef ref) { final strDate = useState(""); final strMonth = useState(""); final strYear = useState(""); final strHour = useState(""); final strMinute = useState(""); final strSeconds = useState(""); useEffect(() { final tmr = Timer.periodic(const Duration(seconds: 1), (timer) { final dt = DateFormat('yyyy-MMM-dd-HH-mm-ss').format(DateTime.now()); final splited = dt.split('-'); final date = splited[2].toString(); final month = splited[1].toString(); final year = splited[0].toString(); final hour = splited[3].toString(); final minute = splited[4].toString(); final second = splited[5].toString(); if (date != strDate.value) strDate.value = date; if (month != strMonth.value) strMonth.value = month; if (year != strYear.value) strYear.value = year; if (hour != strHour.value) strHour.value = hour; if (minute != strMinute.value) strMinute.value = minute; if (second != strSeconds.value) strSeconds.value = second; }); return () { tmr.cancel(); }; }, []); return Container( width: Constant.getActualX(context: context, x: 200), margin: EdgeInsets.only( right: Constant.getActualX(context: context, x: 30)), padding: EdgeInsets.all(0), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( strDate.value, style: Constant.title(context: context).copyWith( color: Colors.blue[900], fontSize: Constant.getActualX(context: context, x: 64)), ), SizedBox( width: Constant.getActualX(context: context, x: 10), ), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( strMonth.value, style: Constant.subTitle(context: context).copyWith( color: Colors.blue[900], fontSize: Constant.getActualX(context: context, x: 25)), ), Text( strYear.value, style: Constant.subTitle(context: context).copyWith( color: Colors.blue[900], fontSize: Constant.getActualX(context: context, x: 25)), ) ], ) ], ), Text( '${strHour.value} . ${strMinute.value} . ${strSeconds.value}', style: Constant.subTitle(context: context).copyWith( color: Colors.blue[900], fontSize: Constant.getActualX(context: context, x: 25)), ) ], )); } }