|
@@ -0,0 +1,384 @@
|
|
|
+import 'package:flutter/material.dart';
|
|
|
+import 'package:get_it/get_it.dart';
|
|
|
+import 'package:ustest/Services/ConsultationService.dart';
|
|
|
+import 'package:ustest/Services/UserService.dart';
|
|
|
+import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
|
|
|
+import 'package:autocomplete_textfield/autocomplete_textfield.dart';
|
|
|
+
|
|
|
+class CustomPicker extends CommonPickerModel {
|
|
|
+ String digits(int value, int length) {
|
|
|
+ return '$value'.padLeft(length, "0");
|
|
|
+ }
|
|
|
+
|
|
|
+ CustomPicker({DateTime? currentTime, LocaleType? locale})
|
|
|
+ : super(locale: locale) {
|
|
|
+ this.currentTime = currentTime ?? DateTime.now();
|
|
|
+ this.setLeftIndex(this.currentTime.hour);
|
|
|
+ this.setMiddleIndex(this.currentTime.minute);
|
|
|
+ this.setRightIndex(this.currentTime.second);
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ String? leftStringAtIndex(int index) {
|
|
|
+ if (index >= 0 && index < 24) {
|
|
|
+ return this.digits(index, 2);
|
|
|
+ } else {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ String? middleStringAtIndex(int index) {
|
|
|
+ if (index >= 0 && index < 60) {
|
|
|
+ return this.digits(index, 2);
|
|
|
+ } else {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ String? rightStringAtIndex(int index) {
|
|
|
+ if (index >= 0 && index < 60) {
|
|
|
+ return this.digits(index, 2);
|
|
|
+ } else {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ String leftDivider() {
|
|
|
+ return "|";
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ String rightDivider() {
|
|
|
+ return "|";
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ List<int> layoutProportions() {
|
|
|
+ return [1, 2, 1];
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ DateTime finalTime() {
|
|
|
+ return currentTime.isUtc
|
|
|
+ ? DateTime.utc(
|
|
|
+ currentTime.year,
|
|
|
+ currentTime.month,
|
|
|
+ currentTime.day,
|
|
|
+ this.currentLeftIndex(),
|
|
|
+ this.currentMiddleIndex(),
|
|
|
+ this.currentRightIndex())
|
|
|
+ : DateTime(
|
|
|
+ currentTime.year,
|
|
|
+ currentTime.month,
|
|
|
+ currentTime.day,
|
|
|
+ this.currentLeftIndex(),
|
|
|
+ this.currentMiddleIndex(),
|
|
|
+ this.currentRightIndex());
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class ApplyConsultationScreen extends StatelessWidget {
|
|
|
+ const ApplyConsultationScreen();
|
|
|
+
|
|
|
+ @override
|
|
|
+ Widget build(BuildContext context) {
|
|
|
+ return Scaffold(
|
|
|
+ backgroundColor: Colors.grey[200],
|
|
|
+ body: const Center(
|
|
|
+ child: SizedBox(
|
|
|
+ width: 400,
|
|
|
+ child: Card(
|
|
|
+ child: ApplyConsultationForm(),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class ApplyConsultationForm extends StatefulWidget {
|
|
|
+ const ApplyConsultationForm();
|
|
|
+ @override
|
|
|
+ _ApplyConsultationFormState createState() => _ApplyConsultationFormState();
|
|
|
+}
|
|
|
+
|
|
|
+class _ApplyConsultationFormState extends State<ApplyConsultationForm> {
|
|
|
+ final expertCodeController = TextEditingController();
|
|
|
+ final deviceCodeController = TextEditingController();
|
|
|
+ final scanPositionController = TextEditingController();
|
|
|
+ final timeController = TextEditingController(text: DateTime.now().toString());
|
|
|
+ final patientCodeController = TextEditingController();
|
|
|
+
|
|
|
+ GlobalKey<AutoCompleteTextFieldState<String>> exportKey = GlobalKey();
|
|
|
+ double _formProgress = 0;
|
|
|
+
|
|
|
+ @override
|
|
|
+ Widget build(BuildContext context) {
|
|
|
+ return Form(
|
|
|
+ child: Column(
|
|
|
+ mainAxisSize: MainAxisSize.min,
|
|
|
+ children: [
|
|
|
+ LinearProgressIndicator(value: _formProgress),
|
|
|
+ Text('Apply', style: Theme.of(context).textTheme.headline4),
|
|
|
+ Padding(
|
|
|
+ padding: const EdgeInsets.all(8.0),
|
|
|
+ child: FutureBuilder<List<String>>(
|
|
|
+ future: fetchExperts(),
|
|
|
+ builder: (context, snapshot) {
|
|
|
+ if (snapshot.hasError) {
|
|
|
+ return const Center(
|
|
|
+ child: Text('An error has occurred!'),
|
|
|
+ );
|
|
|
+ } else if (snapshot.hasData) {
|
|
|
+ return SimpleAutoCompleteTextField(
|
|
|
+ key: exportKey,
|
|
|
+ suggestions: snapshot.data!,
|
|
|
+ controller: expertCodeController,
|
|
|
+ decoration: const InputDecoration(hintText: 'export'),
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ return const Center(
|
|
|
+ child: CircularProgressIndicator(),
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }),
|
|
|
+ ),
|
|
|
+ Padding(
|
|
|
+ padding: const EdgeInsets.all(8.0),
|
|
|
+ child: TextFormField(
|
|
|
+ controller: deviceCodeController,
|
|
|
+ decoration: const InputDecoration(hintText: 'device'),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ Padding(
|
|
|
+ padding: const EdgeInsets.all(8.0),
|
|
|
+ child: TextFormField(
|
|
|
+ controller: scanPositionController,
|
|
|
+ decoration: const InputDecoration(hintText: 'scan position'),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ Padding(
|
|
|
+ padding: const EdgeInsets.all(8.0),
|
|
|
+ child: Row(
|
|
|
+ children: [
|
|
|
+ Expanded(
|
|
|
+ child: TextFormField(
|
|
|
+ controller: timeController,
|
|
|
+ decoration: const InputDecoration(hintText: 'time'),
|
|
|
+ )),
|
|
|
+ TextButton(
|
|
|
+ onPressed: () {
|
|
|
+ DatePicker.showDatePicker(context,
|
|
|
+ showTitleActions: true,
|
|
|
+ minTime: DateTime(2022, 3, 5),
|
|
|
+ maxTime: DateTime(2024, 6, 7),
|
|
|
+ theme: DatePickerTheme(
|
|
|
+ headerColor: Colors.orange,
|
|
|
+ backgroundColor: Colors.blue,
|
|
|
+ itemStyle: TextStyle(
|
|
|
+ color: Colors.white,
|
|
|
+ fontWeight: FontWeight.bold,
|
|
|
+ fontSize: 18),
|
|
|
+ doneStyle:
|
|
|
+ TextStyle(color: Colors.white, fontSize: 16)),
|
|
|
+ onChanged: (date) {
|
|
|
+ print('change $date in time zone ' +
|
|
|
+ date.timeZoneOffset.inHours.toString());
|
|
|
+ }, onConfirm: (date) {
|
|
|
+ print('confirm $date');
|
|
|
+ }, currentTime: DateTime.now(), locale: LocaleType.en);
|
|
|
+ },
|
|
|
+ child: Text(
|
|
|
+ 'date',
|
|
|
+ style: TextStyle(color: Colors.blue),
|
|
|
+ )),
|
|
|
+ TextButton(
|
|
|
+ onPressed: () {
|
|
|
+ DatePicker.showTimePicker(context, showTitleActions: true,
|
|
|
+ onChanged: (date) {
|
|
|
+ print('change $date in time zone ' +
|
|
|
+ date.timeZoneOffset.inHours.toString());
|
|
|
+ }, onConfirm: (date) {
|
|
|
+ print('confirm $date');
|
|
|
+ }, currentTime: DateTime.now());
|
|
|
+ },
|
|
|
+ child: Text(
|
|
|
+ 'time',
|
|
|
+ style: TextStyle(color: Colors.blue),
|
|
|
+ )),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ Padding(
|
|
|
+ padding: const EdgeInsets.all(8.0),
|
|
|
+ child: Row(
|
|
|
+ mainAxisAlignment: MainAxisAlignment.center,
|
|
|
+ children: [
|
|
|
+ TextButton(
|
|
|
+ style: ButtonStyle(
|
|
|
+ foregroundColor: MaterialStateProperty.resolveWith(
|
|
|
+ (Set<MaterialState> states) {
|
|
|
+ return states.contains(MaterialState.disabled)
|
|
|
+ ? null
|
|
|
+ : Colors.white;
|
|
|
+ }),
|
|
|
+ backgroundColor: MaterialStateProperty.resolveWith(
|
|
|
+ (Set<MaterialState> states) {
|
|
|
+ return states.contains(MaterialState.disabled)
|
|
|
+ ? null
|
|
|
+ : Colors.blue;
|
|
|
+ }),
|
|
|
+ ),
|
|
|
+ onPressed: _showWelcomeScreen,
|
|
|
+ child: const Text('Submit'),
|
|
|
+ ),
|
|
|
+ Padding(
|
|
|
+ padding: const EdgeInsets.all(8.0),
|
|
|
+ child: TextButton(
|
|
|
+ style: ButtonStyle(
|
|
|
+ foregroundColor: MaterialStateProperty.resolveWith(
|
|
|
+ (Set<MaterialState> states) {
|
|
|
+ return states.contains(MaterialState.disabled)
|
|
|
+ ? null
|
|
|
+ : Colors.white;
|
|
|
+ }),
|
|
|
+ backgroundColor: MaterialStateProperty.resolveWith(
|
|
|
+ (Set<MaterialState> states) {
|
|
|
+ return states.contains(MaterialState.disabled)
|
|
|
+ ? null
|
|
|
+ : Colors.blue;
|
|
|
+ }),
|
|
|
+ ),
|
|
|
+ onPressed: () => {Navigator.of(context).pop()},
|
|
|
+ child: const Text('Cancel'),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ )),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ void _showWelcomeScreen() async {
|
|
|
+ try {
|
|
|
+ ApplyConsultationRequest _model = new ApplyConsultationRequest(
|
|
|
+ "expertusercode", "d", "s", DateTime.now(), List.empty(), "", "");
|
|
|
+ var service = GetIt.instance.get<UserService>();
|
|
|
+ var userName = expertCodeController.text;
|
|
|
+ var password = deviceCodeController.text;
|
|
|
+ var host = scanPositionController.text;
|
|
|
+ var result = await service.signInAsync(host, userName, password);
|
|
|
+ if (result != null) {
|
|
|
+ Navigator.of(context).pushNamed('/');
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ print('signInAsync ex: $e');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ fetchExperts() {}
|
|
|
+}
|
|
|
+
|
|
|
+class ExportInfo {
|
|
|
+ final String id;
|
|
|
+ final String name;
|
|
|
+
|
|
|
+ ExportInfo({required this.id, required this.name});
|
|
|
+
|
|
|
+ factory ExportInfo.fromJson(Map<String, dynamic> json) {
|
|
|
+ var item = ExportInfo(
|
|
|
+ id: json['id'] as String,
|
|
|
+ name: json['name'] as String,
|
|
|
+ );
|
|
|
+
|
|
|
+ return item;
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String, dynamic> toMap() {
|
|
|
+ return {
|
|
|
+ 'id': id,
|
|
|
+ 'name': name,
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ String toString() {
|
|
|
+ return 'ExportInfo{id: $id}, {name: $name}';
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+enum NotificationTypeEnum {
|
|
|
+ Daiding,
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ ChatMsgNotification,
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ UpgradeVersionNotification,
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ LogoffNotification,
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ DisconnectNotification,
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ ConnectionNotification,
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ FinishNotifyRecordsMessage,
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ InvitedEnterRoomNotification,
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ CancelInvitedEnterRoomNotification,
|
|
|
+}
|
|
|
+
|
|
|
+class ConnectionNotification {
|
|
|
+ NotificationTypeEnum notificationType;
|
|
|
+ ConnectionNotification({
|
|
|
+ this.notificationType = NotificationTypeEnum.Daiding,
|
|
|
+ });
|
|
|
+ factory ConnectionNotification.fromJson(Map<String, dynamic> map) {
|
|
|
+ return ConnectionNotification(
|
|
|
+ notificationType: NotificationTypeEnum.values
|
|
|
+ .firstWhere((e) => e.index == map['NotificationType']),
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class DisconnectNotification {
|
|
|
+ NotificationTypeEnum notificationType;
|
|
|
+ DisconnectNotification({
|
|
|
+ this.notificationType = NotificationTypeEnum.Daiding,
|
|
|
+ });
|
|
|
+ factory DisconnectNotification.fromJson(Map<String, dynamic> map) {
|
|
|
+ return DisconnectNotification(
|
|
|
+ notificationType: NotificationTypeEnum.values
|
|
|
+ .firstWhere((e) => e.index == map['NotificationType']),
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class FinishNotifyRecordsMessage {}
|