first commit
This commit is contained in:
543
lib/screen/queue/queue_screen.dart
Normal file
543
lib/screen/queue/queue_screen.dart
Normal file
@@ -0,0 +1,543 @@
|
||||
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<Layanan>>(List.empty());
|
||||
final activeLayanan = useState<List<dynamic>>(List.empty());
|
||||
final selectedPrinter =
|
||||
useState<PrinterDev>(PrinterDev(deviceName: "a", id: 0));
|
||||
final selectedBooth =
|
||||
useState<Booth>(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<BranchModel?>(null);
|
||||
|
||||
final selectedLayanan = useState<Layanan>(Layanan(
|
||||
name: 'x', id: 0, priority: 0, isConsultDoctor: 'n', code: '0'));
|
||||
final getNumberLoading = useState(false);
|
||||
final btnSize = useState<Map<String, dynamic>>({'name': 'n'});
|
||||
Future getData() async {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
var raw_data = prefs.getString('tb-westerindo') ?? 'a';
|
||||
|
||||
if (raw_data != 'a') {
|
||||
List<Layanan> 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<Layanan> 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<bool> getNumberLoading,
|
||||
ValueNotifier<int> tapAnimation,
|
||||
Layanan e,
|
||||
ValueNotifier<Layanan> selectedLayanan,
|
||||
BuildContext context,
|
||||
Null getDataApi(dynamic e),
|
||||
ValueNotifier<Map<String, dynamic>> btnSize,
|
||||
ValueNotifier<String> 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)),
|
||||
)
|
||||
],
|
||||
));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user