Compare commits
4 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
519ce695d6 | 2 weeks ago |
|
|
7a5b753f63 | 1 month ago |
|
|
a30b9872b2 | 2 months ago |
|
|
8b9e757e61 | 2 months ago |
Binary file not shown.
|
Before Width: | Height: | Size: 37 KiB |
@ -1,3 +0,0 @@
|
|||||||
<svg width="15" height="23" viewBox="0 0 15 23" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M8.32806 22.32C7.33606 22.32 6.34406 22.2 5.35206 21.96C4.37606 21.736 3.48006 21.36 2.66406 20.832C1.86406 20.304 1.21606 19.616 0.720063 18.768C0.240063 17.92 6.25104e-05 16.88 6.25104e-05 15.648C6.25104e-05 14.4 0.248063 13.248 0.744063 12.192C1.25606 11.12 1.96806 10.168 2.88006 9.336C3.80806 8.488 4.90406 7.784 6.16806 7.224C7.43206 6.664 8.81606 6.264 10.3201 6.024L10.9921 8.688C9.68006 8.928 8.51206 9.256 7.48806 9.672C6.48006 10.088 5.62406 10.584 4.92006 11.16C4.23206 11.736 3.71206 12.368 3.36006 13.056C3.00806 13.76 2.83206 14.512 2.83206 15.312C2.83206 15.952 2.94406 16.504 3.16806 16.968C3.40806 17.448 3.72006 17.848 4.10406 18.168C4.48806 18.488 4.92006 18.744 5.40006 18.936C5.88006 19.128 6.37606 19.264 6.88806 19.344C7.40006 19.44 7.88006 19.488 8.32806 19.488C9.33606 19.488 10.3041 19.392 11.2321 19.2C12.1601 19.024 12.9841 18.784 13.7041 18.48L14.5201 21.024C14.1361 21.216 13.6081 21.408 12.9361 21.6C12.2641 21.808 11.5281 21.976 10.7281 22.104C9.92806 22.248 9.12806 22.32 8.32806 22.32ZM3.86406 9.24C3.27206 9.048 2.72806 8.744 2.23206 8.328C1.75206 7.912 1.36806 7.4 1.08006 6.792C0.792063 6.184 0.648063 5.512 0.648063 4.776C0.648063 3.768 0.904063 2.912 1.41606 2.208C1.92806 1.488 2.59206 0.943998 3.40806 0.575998C4.24006 0.191998 5.13606 -1.90735e-06 6.09606 -1.90735e-06C6.56006 -1.90735e-06 7.00806 0.0319982 7.44006 0.0959983C7.87206 0.159998 8.30406 0.255998 8.73606 0.383997L8.25606 3.072C7.92006 2.992 7.57606 2.928 7.22406 2.88C6.87206 2.832 6.56006 2.808 6.28806 2.808C5.72806 2.808 5.23206 2.896 4.80006 3.072C4.38406 3.248 4.05606 3.496 3.81606 3.816C3.59206 4.136 3.48006 4.512 3.48006 4.944C3.48006 5.312 3.58406 5.656 3.79206 5.976C4.01606 6.28 4.29606 6.544 4.63206 6.768C4.98406 6.992 5.35206 7.168 5.73606 7.296C6.13606 7.424 6.50406 7.496 6.84006 7.512L3.86406 9.24Z" fill="#2B353E"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.9 KiB |
@ -1,4 +0,0 @@
|
|||||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M1.98978 14.0362H21.2589C22.0592 14.0362 22.7076 13.3877 22.7076 12.5874C22.7076 11.7871 22.0592 11.1387 21.2589 11.1387H1.98978C1.18949 11.1387 0.541029 11.7871 0.541029 12.5874C0.541029 13.3877 1.18949 14.0362 1.98978 14.0362Z" fill="#2E3039"/>
|
|
||||||
<path d="M14.6241 20.8879C14.9764 20.8879 15.3299 20.7598 15.6087 20.5013L22.9973 13.6488C23.2952 13.3723 23.4638 12.9835 23.4609 12.5767C23.458 12.1704 23.2847 11.7833 22.9828 11.511L15.3914 4.65838C14.7974 4.12234 13.8812 4.16928 13.3451 4.76327C12.8091 5.35726 12.856 6.27345 13.45 6.80949L19.8663 12.601L13.6384 18.3769C13.0519 18.921 13.0171 19.8378 13.5613 20.4243C13.847 20.732 14.2347 20.8879 14.6241 20.8879Z" fill="#2E3039"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 803 B |
@ -1,5 +0,0 @@
|
|||||||
<svg width="24" height="22" viewBox="0 0 24 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<circle cx="7" cy="7" r="7" fill="#0B85F7" fill-opacity="0.75"/>
|
|
||||||
<circle cx="17" cy="7" r="7" fill="#18C273" fill-opacity="0.75"/>
|
|
||||||
<circle cx="12" cy="15" r="7" fill="#ED1C2B" fill-opacity="0.75"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 301 B |
@ -1,3 +0,0 @@
|
|||||||
<svg width="12" height="21" viewBox="0 0 12 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M2.72994 2.25V9.24H10.3499V11.49H2.72994V18.69H11.2499V20.94H-5.83827e-05V2.02656e-06H11.2499V2.25H2.72994Z" fill="#2B353E"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 242 B |
@ -1,4 +0,0 @@
|
|||||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M22.0102 14.0362H2.74111C1.94082 14.0362 1.29236 13.3877 1.29236 12.5874C1.29236 11.7871 1.94082 11.1387 2.74111 11.1387H22.0102C22.8105 11.1387 23.459 11.7871 23.459 12.5874C23.459 13.3877 22.8105 14.0362 22.0102 14.0362Z" fill="#2E3039"/>
|
|
||||||
<path d="M9.3759 20.8879C9.02357 20.8879 8.67007 20.7598 8.39133 20.5013L1.0027 13.6488C0.704836 13.3723 0.536202 12.9835 0.539099 12.5767C0.541997 12.1704 0.715267 11.7833 1.01719 11.511L8.60864 4.65838C9.20263 4.12234 10.1188 4.16928 10.6549 4.76327C11.1909 5.35726 11.144 6.27345 10.55 6.80949L4.13374 12.601L10.3616 18.3769C10.9481 18.921 10.9829 19.8378 10.4387 20.4243C10.153 20.732 9.76533 20.8879 9.3759 20.8879Z" fill="#2E3039"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 800 B |
@ -1,73 +1,73 @@
|
|||||||
// import 'dart:convert';
|
import 'dart:convert';
|
||||||
// import 'dart:io';
|
import 'dart:io';
|
||||||
//
|
|
||||||
// void main() async {
|
void main() async {
|
||||||
// final file = File('assets/json/body_symptoms_data.json');
|
final file = File('assets/json/body_symptoms_data.json');
|
||||||
// final content = await file.readAsString();
|
final content = await file.readAsString();
|
||||||
//
|
|
||||||
// print('File size: ${content.length} characters');
|
print('File size: ${content.length} characters');
|
||||||
//
|
|
||||||
// // Split into two parts
|
// Split into two parts
|
||||||
// final parts = content.split('export const SymptomsData = [');
|
final parts = content.split('export const SymptomsData = [');
|
||||||
// if (parts.length != 2) {
|
if (parts.length != 2) {
|
||||||
// print('ERROR: Could not split file properly');
|
print('ERROR: Could not split file properly');
|
||||||
// exit(1);
|
exit(1);
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// print('Split into ${parts.length} parts');
|
print('Split into ${parts.length} parts');
|
||||||
//
|
|
||||||
// // Process BodySymptomsData
|
// Process BodySymptomsData
|
||||||
// var bodyPart = parts[0]
|
var bodyPart = parts[0]
|
||||||
// .replaceAll('export const BodySymptomsData = ', '')
|
.replaceAll('export const BodySymptomsData = ', '')
|
||||||
// .trim()
|
.trim()
|
||||||
// .replaceAll(RegExp(r';$'), '');
|
.replaceAll(RegExp(r';$'), '');
|
||||||
//
|
|
||||||
// print('Parsing body symptoms...');
|
print('Parsing body symptoms...');
|
||||||
// Map<String, dynamic> bodySymptomsData;
|
Map<String, dynamic> bodySymptomsData;
|
||||||
// try {
|
try {
|
||||||
// bodySymptomsData = json.decode(bodyPart);
|
bodySymptomsData = json.decode(bodyPart);
|
||||||
// print('✅ Body symptoms parsed: ${bodySymptomsData.length} body parts');
|
print('✅ Body symptoms parsed: ${bodySymptomsData.length} body parts');
|
||||||
// } catch (e) {
|
} catch (e) {
|
||||||
// print('❌ Error parsing body symptoms: $e');
|
print('❌ Error parsing body symptoms: $e');
|
||||||
// exit(1);
|
exit(1);
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// // Process SymptomsData
|
// Process SymptomsData
|
||||||
// print('Processing symptoms data...');
|
print('Processing symptoms data...');
|
||||||
// var symptomsPart = parts[1]
|
var symptomsPart = parts[1]
|
||||||
// .trim()
|
.trim()
|
||||||
// .replaceAll(RegExp(r'\];$'), '')
|
.replaceAll(RegExp(r'\];$'), '')
|
||||||
// .replaceAllMapped(RegExp(r'\n(\s*)id:'), (m) => '\n${m.group(1)}"id":')
|
.replaceAllMapped(RegExp(r'\n(\s*)id:'), (m) => '\n${m.group(1)}"id":')
|
||||||
// .replaceAllMapped(RegExp(r'\n(\s*)type:'), (m) => '\n${m.group(1)}"type":')
|
.replaceAllMapped(RegExp(r'\n(\s*)type:'), (m) => '\n${m.group(1)}"type":')
|
||||||
// .replaceAllMapped(RegExp(r'\n(\s*)name:'), (m) => '\n${m.group(1)}"name":')
|
.replaceAllMapped(RegExp(r'\n(\s*)name:'), (m) => '\n${m.group(1)}"name":')
|
||||||
// .replaceAllMapped(RegExp(r'\n(\s*)common_name:'), (m) => '\n${m.group(1)}"common_name":');
|
.replaceAllMapped(RegExp(r'\n(\s*)common_name:'), (m) => '\n${m.group(1)}"common_name":');
|
||||||
//
|
|
||||||
// print('Parsing symptoms...');
|
print('Parsing symptoms...');
|
||||||
// List<dynamic> symptomsData;
|
List<dynamic> symptomsData;
|
||||||
// try {
|
try {
|
||||||
// symptomsData = json.decode('[$symptomsPart]');
|
symptomsData = json.decode('[$symptomsPart]');
|
||||||
// print('✅ Symptoms parsed: ${symptomsData.length} symptoms');
|
print('✅ Symptoms parsed: ${symptomsData.length} symptoms');
|
||||||
// } catch (e) {
|
} catch (e) {
|
||||||
// print('❌ Error parsing symptoms: $e');
|
print('❌ Error parsing symptoms: $e');
|
||||||
// print('First 1000 chars:');
|
print('First 1000 chars:');
|
||||||
// print('[$symptomsPart]'.substring(0, 1000));
|
print('[$symptomsPart]'.substring(0, 1000));
|
||||||
// exit(1);
|
exit(1);
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// // Create final JSON
|
// Create final JSON
|
||||||
// print('Creating final JSON structure...');
|
print('Creating final JSON structure...');
|
||||||
// final jsonStructure = {
|
final jsonStructure = {
|
||||||
// 'bodySymptoms': bodySymptomsData,
|
'bodySymptoms': bodySymptomsData,
|
||||||
// 'symptoms': symptomsData,
|
'symptoms': symptomsData,
|
||||||
// };
|
};
|
||||||
//
|
|
||||||
// // Write to file
|
// Write to file
|
||||||
// print('Writing to file...');
|
print('Writing to file...');
|
||||||
// final encoder = JsonEncoder.withIndent(' ');
|
final encoder = JsonEncoder.withIndent(' ');
|
||||||
// await file.writeAsString(encoder.convert(jsonStructure));
|
await file.writeAsString(encoder.convert(jsonStructure));
|
||||||
//
|
|
||||||
// print('\n✅ SUCCESS! File converted to proper JSON');
|
print('\n✅ SUCCESS! File converted to proper JSON');
|
||||||
// print('✅ Body parts: ${bodySymptomsData.length}');
|
print('✅ Body parts: ${bodySymptomsData.length}');
|
||||||
// print('✅ Symptoms: ${symptomsData.length}');
|
print('✅ Symptoms: ${symptomsData.length}');
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
|
|||||||
@ -1,316 +0,0 @@
|
|||||||
import 'dart:async';
|
|
||||||
import 'dart:collection';
|
|
||||||
import 'dart:convert';
|
|
||||||
import 'dart:io';
|
|
||||||
import 'dart:ui';
|
|
||||||
|
|
||||||
import 'package:device_calendar/device_calendar.dart';
|
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
import 'package:hmg_patient_app_new/core/dependencies.dart';
|
|
||||||
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
|
|
||||||
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
|
|
||||||
import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_reminder_view.dart';
|
|
||||||
import 'package:hmg_patient_app_new/services/dialog_service.dart';
|
|
||||||
import 'package:hmg_patient_app_new/services/permission_service.dart';
|
|
||||||
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
|
|
||||||
import 'package:jiffy/jiffy.dart';
|
|
||||||
import 'package:manage_calendar_events/manage_calendar_events.dart' as ios;
|
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
|
||||||
import 'package:timezone/data/latest.dart' as tzl;
|
|
||||||
|
|
||||||
final DeviceCalendarPlugin deviceCalendarPlugin = DeviceCalendarPlugin();
|
|
||||||
final ios.CalendarPlugin _myPlugin = ios.CalendarPlugin();
|
|
||||||
|
|
||||||
class CalendarUtils {
|
|
||||||
static Completer<CalendarUtils>? _completer;
|
|
||||||
|
|
||||||
dynamic get writableCalendars => calendars.firstWhere((c) => !c.isReadOnly!);
|
|
||||||
dynamic calendars;
|
|
||||||
|
|
||||||
CalendarUtils._(this.calendars);
|
|
||||||
|
|
||||||
// static Future<CalendarUtils> getInstance() async {
|
|
||||||
// if (_completer == null) {
|
|
||||||
// _completer = Completer<CalendarUtils>();
|
|
||||||
// print(_completer!.isCompleted);
|
|
||||||
// try {
|
|
||||||
// final dynamic calendarsResult;
|
|
||||||
// if (Platform.isIOS) {
|
|
||||||
// calendarsResult = await _myPlugin.getCalendars();
|
|
||||||
// if (!_completer!.isCompleted) {
|
|
||||||
// _completer?.complete(CalendarUtils._(await calendarsResult!));
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// calendarsResult = await deviceCalendarPlugin.retrieveCalendars();
|
|
||||||
// if (!_completer!.isCompleted) {
|
|
||||||
// _completer?.complete(CalendarUtils._(await calendarsResult.data!));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } on Exception catch (e) {
|
|
||||||
// if (!_completer!.isCompleted) {
|
|
||||||
// _completer!.completeError(e);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return _completer!.future;
|
|
||||||
// }
|
|
||||||
|
|
||||||
static Future<CalendarUtils> getInstance() async {
|
|
||||||
tzl.initializeTimeZones();
|
|
||||||
if (_completer != null) {
|
|
||||||
return _completer!.future;
|
|
||||||
}
|
|
||||||
_completer = Completer<CalendarUtils>();
|
|
||||||
try {
|
|
||||||
final dynamic calendarsResult;
|
|
||||||
if (Platform.isIOS) {
|
|
||||||
calendarsResult = await _myPlugin.getCalendars();
|
|
||||||
_completer!.complete(CalendarUtils._(calendarsResult));
|
|
||||||
} else {
|
|
||||||
calendarsResult = await deviceCalendarPlugin.retrieveCalendars();
|
|
||||||
_completer!.complete(CalendarUtils._(calendarsResult.data));
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
_completer!.completeError(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return _completer!.future;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future createOrUpdateEvents({List<DateTime>? scheduleList, String? title, String? description, List<DateTime>? scheduleDateTime, List<DayOfWeek>? daysOfWeek}) async {
|
|
||||||
tzl.initializeTimeZones();
|
|
||||||
List<Event> events = [];
|
|
||||||
Location _currentLocation;
|
|
||||||
if (DateTime.now().timeZoneName == "+04")
|
|
||||||
_currentLocation = getLocation('Asia/Dubai');
|
|
||||||
else
|
|
||||||
_currentLocation = getLocation('Asia/Riyadh');
|
|
||||||
|
|
||||||
scheduleDateTime!.forEach((element) {
|
|
||||||
RecurrenceRule recurrenceRule = RecurrenceRule(
|
|
||||||
// RecurrenceFrequency.Daily,
|
|
||||||
// daysOfWeek: daysOfWeek,
|
|
||||||
// endDate: element,
|
|
||||||
until: element, frequency: Frequency.daily,
|
|
||||||
);
|
|
||||||
//added byAamir Tz Time
|
|
||||||
Event event = Event(writableCalendars!.id,
|
|
||||||
recurrenceRule: recurrenceRule,
|
|
||||||
start: TZDateTime.from(element, _currentLocation),
|
|
||||||
end: TZDateTime.from(element.add(Duration(minutes: 30)), _currentLocation),
|
|
||||||
title: title,
|
|
||||||
description: description);
|
|
||||||
events.add(event);
|
|
||||||
});
|
|
||||||
|
|
||||||
events.forEach((element) {
|
|
||||||
deviceCalendarPlugin.createOrUpdateEvent(element);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future createOrUpdateEvent({required String title, required String description, required String location, DateTime? scheduleDateTime, String? eventId}) async {
|
|
||||||
RecurrenceRule recurrenceRule = RecurrenceRule(
|
|
||||||
// RecurrenceFrequency.Daily,
|
|
||||||
// daysOfWeek: daysOfWeek,
|
|
||||||
// endDate: scheduleDateTime,
|
|
||||||
until: scheduleDateTime, frequency: Frequency.daily,
|
|
||||||
);
|
|
||||||
|
|
||||||
Location _currentLocation;
|
|
||||||
// if (DateTime.now().timeZoneName == "+04")
|
|
||||||
// _currentLocation = getLocation('Asia/Dubai');
|
|
||||||
// else
|
|
||||||
_currentLocation = getLocation('Asia/Riyadh');
|
|
||||||
|
|
||||||
TZDateTime scheduleDateTimeUTZ = TZDateTime.from(scheduleDateTime!, _currentLocation);
|
|
||||||
|
|
||||||
print("writableCalendars-name: " + writableCalendars.name);
|
|
||||||
print("writableCalendars-Id: " + writableCalendars.id);
|
|
||||||
print("writableCalendarsToString: " + writableCalendars.toString());
|
|
||||||
print("writableCalendarsToString: " + writableCalendars!.id!);
|
|
||||||
Event event = Event(
|
|
||||||
writableCalendars!.id,
|
|
||||||
start: scheduleDateTimeUTZ,
|
|
||||||
end: scheduleDateTimeUTZ.add(Duration(minutes: 30)),
|
|
||||||
title: title,
|
|
||||||
description: description,
|
|
||||||
);
|
|
||||||
|
|
||||||
ios.CalendarEvent iosCalEvent =
|
|
||||||
ios.CalendarEvent(location: location, startDate: scheduleDateTimeUTZ, endDate: scheduleDateTimeUTZ.add(Duration(minutes: 30)), title: title, description: description, isAllDay: false);
|
|
||||||
|
|
||||||
if (Platform.isAndroid) {
|
|
||||||
Result<bool> result = await deviceCalendarPlugin.hasPermissions();
|
|
||||||
print(result);
|
|
||||||
await deviceCalendarPlugin.createOrUpdateEvent(event).catchError((e) {
|
|
||||||
print("catchError " + e.toString());
|
|
||||||
}).whenComplete(() {
|
|
||||||
print("whenComplete Calender ID " + eventId!);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
await _myPlugin.createEvent(calendarId: writableCalendars.id!, event: iosCalEvent).catchError((e) {
|
|
||||||
print("catchError " + e.toString());
|
|
||||||
}).whenComplete(() {
|
|
||||||
print("whenComplete Calender ID iOS " + eventId!);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteEvent(String _calendarId, String _eventId) async {
|
|
||||||
if (Platform.isIOS) {
|
|
||||||
await _myPlugin.deleteEvent(calendarId: _calendarId, eventId: _eventId);
|
|
||||||
} else {
|
|
||||||
await deviceCalendarPlugin.deleteEvent(_calendarId, _eventId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future retrieveEvents(
|
|
||||||
String calendarId,
|
|
||||||
RetrieveEventsParams retrieveEventsParams,
|
|
||||||
) async {
|
|
||||||
if (Platform.isIOS) {
|
|
||||||
return await _myPlugin.getEvents(calendarId: calendarId);
|
|
||||||
} else {
|
|
||||||
return await deviceCalendarPlugin.retrieveEvents(calendarId, retrieveEventsParams);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future createCalendar(
|
|
||||||
String calendarName, {
|
|
||||||
Color? calendarColor,
|
|
||||||
String? localAccountName,
|
|
||||||
}) async {
|
|
||||||
return await deviceCalendarPlugin.createCalendar(calendarName, calendarColor: calendarColor, localAccountName: localAccountName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<Map<Permission, PermissionStatus>> requestPermissions() async {
|
|
||||||
var permissionResults = [Permission.calendarFullAccess].request();
|
|
||||||
return permissionResults;
|
|
||||||
}
|
|
||||||
|
|
||||||
showReminderBottomSheet(BuildContext context, DateTime dateTime, String doctorName, String eventId, String appoDateFormatted, String appoTimeFormatted,
|
|
||||||
{required Function() onSuccess, String? title, String? description, Function(int)? onMultiDateSuccess, bool isMultiAllowed = false}) async {
|
|
||||||
if (Platform.isAndroid) {
|
|
||||||
if (await PermissionService.isCalendarPermissionEnabled()) {
|
|
||||||
_showReminderBottomSheet(context, dateTime, doctorName, eventId, appoDateFormatted, appoTimeFormatted,
|
|
||||||
onSuccess: onSuccess, title: title, description: description, onMultiDateSuccess: onMultiDateSuccess, isMultiAllowed: isMultiAllowed);
|
|
||||||
} else {
|
|
||||||
// Utils.showPermissionConsentDialog(context, TranslationBase.of(context).calendarPermission, () async {
|
|
||||||
// if (await Permission.calendarFullAccess.request().isGranted) {
|
|
||||||
// _showReminderDialog(context, dateTime, doctorName, eventId, appoDateFormatted, appoTimeFormatted,
|
|
||||||
// onSuccess: onSuccess, title: title, description: description, onMultiDateSuccess: onMultiDateSuccess, isMultiAllowed: isMultiAllowed);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (await Permission.calendarWriteOnly.request().isGranted) {
|
|
||||||
if (await Permission.calendarFullAccess.request().isGranted) {
|
|
||||||
_showReminderBottomSheet(context, dateTime, doctorName, eventId, appoDateFormatted, appoTimeFormatted,
|
|
||||||
onSuccess: onSuccess, title: title, description: description, onMultiDateSuccess: onMultiDateSuccess, isMultiAllowed: isMultiAllowed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _showReminderBottomSheet(BuildContext providedContext, DateTime dateTime, String doctorName, String eventId, String appoDateFormatted, String appoTimeFormatted,
|
|
||||||
{required Function onSuccess, String? title, String? description, Function(int)? onMultiDateSuccess, bool? isMultiAllowed}) async {
|
|
||||||
showCommonBottomSheetWithoutHeight(providedContext, title: "Set the timer of reminder", child: PrescriptionReminderView(
|
|
||||||
setReminder: (int value) async {
|
|
||||||
if (!isMultiAllowed!) {
|
|
||||||
if (onMultiDateSuccess == null) {
|
|
||||||
CalendarUtils calendarUtils = await CalendarUtils.getInstance();
|
|
||||||
await calendarUtils.createOrUpdateEvent(
|
|
||||||
title: title ?? "You have appointment with Dr. $doctorName",
|
|
||||||
description: description ?? "At $appoDateFormatted $appoTimeFormatted",
|
|
||||||
scheduleDateTime: dateTime,
|
|
||||||
eventId: eventId,
|
|
||||||
location: '');
|
|
||||||
onSuccess();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
onMultiDateSuccess!(value);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
), callBackFunc: () {}, isFullScreen: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
setCalender(BuildContext context,
|
|
||||||
{required String eventId, required int selectedMinutes, int? frequencyNumber, required int days, required String orderDate, required String itemDescriptionN, required String route}) async {
|
|
||||||
DateTime actualDate = DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day, 8, 0);
|
|
||||||
frequencyNumber ??= 2; //Some time frequency number is null so by default will be 2
|
|
||||||
|
|
||||||
int remainingDays = days - (Jiffy.parseFromDateTime(DateTime.now()).diff(Jiffy.parseFromDateTime(DateUtil.convertStringToDate(orderDate)), unit: Unit.day) as int);
|
|
||||||
if (remainingDays.isNegative) {
|
|
||||||
getIt.get<DialogService>().showErrorBottomSheet(message: "Prescription date has been already passed you can not add a reminder for this prescription.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
CalendarUtils calendarUtils = await CalendarUtils.getInstance();
|
|
||||||
|
|
||||||
try {
|
|
||||||
for (int i = 0; i < remainingDays; i++) {
|
|
||||||
//event for number of days.
|
|
||||||
for (int j = 0; j < frequencyNumber; j++) {
|
|
||||||
// event for number of times per day.
|
|
||||||
if (j != 0) {
|
|
||||||
actualDate.add(new Duration(hours: 8)); // 8 hours addition for daily dose.
|
|
||||||
}
|
|
||||||
//Time subtraction from actual reminder time. like before 30, or 1 hour.
|
|
||||||
|
|
||||||
actualDate = Jiffy.parseFromDateTime(actualDate).subtract(minutes: selectedMinutes).dateTime;
|
|
||||||
|
|
||||||
calendarUtils.createOrUpdateEvent(
|
|
||||||
title: "$itemDescriptionN} Prescription Reminder",
|
|
||||||
description: "$itemDescriptionN $frequencyNumber $route ",
|
|
||||||
scheduleDateTime: actualDate,
|
|
||||||
eventId: eventId + (i.toString() + j.toString()),
|
|
||||||
location: '', //event id with varitions
|
|
||||||
);
|
|
||||||
print("Creating event #$j for day $i → $actualDate");
|
|
||||||
actualDate = DateTime(actualDate.year, actualDate.month, actualDate.day, 8, 0);
|
|
||||||
}
|
|
||||||
actualDate = Jiffy.parseFromDateTime(actualDate).add(days: 1).dateTime;
|
|
||||||
}
|
|
||||||
} catch (ex) {
|
|
||||||
getIt.get<DialogService>().showErrorBottomSheet(message: "catch:$ex");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> checkAndRemove(hasReminder, {bool delete = false, String itemDescriptionN = ""}) async {
|
|
||||||
final ios.CalendarPlugin _myPlugin = ios.CalendarPlugin();
|
|
||||||
CalendarUtils calendarUtils = await CalendarUtils.getInstance();
|
|
||||||
DateTime startEventsDate = Jiffy.parseFromDateTime(DateTime.now()).subtract(days: 30).dateTime;
|
|
||||||
DateTime endEventsDate = Jiffy.parseFromDateTime(DateTime.now()).add(days: 120).dateTime;
|
|
||||||
RetrieveEventsParams params = RetrieveEventsParams(startDate: startEventsDate, endDate: endEventsDate);
|
|
||||||
|
|
||||||
if (calendarUtils.calendars != null) {
|
|
||||||
if (Platform.isAndroid) {
|
|
||||||
await processEvents(calendarUtils.calendars, calendarUtils, params, delete, itemDescriptionN, hasReminder);
|
|
||||||
} else {
|
|
||||||
List<ios.Calendar>? iosCalendars = await _myPlugin.getCalendars();
|
|
||||||
if (iosCalendars != null) {
|
|
||||||
await processEvents(iosCalendars.map((cal) => Calendar(id: cal.id, name: cal.name, accountName: cal.accountName)).toList(), calendarUtils, params, delete, itemDescriptionN, hasReminder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> processEvents(List<Calendar> calendars, calendarUtils, params, delete, String itemDescriptionN, hasReminder) async {
|
|
||||||
for (var calendar in calendars) {
|
|
||||||
Result<UnmodifiableListView<Event>> events = await calendarUtils.retrieveEvents(calendar.id!, params);
|
|
||||||
for (var event in events.data!) {
|
|
||||||
if (event.title!.contains(itemDescriptionN)) {
|
|
||||||
if (delete) {
|
|
||||||
await calendarUtils.deleteEvent(calendar, event);
|
|
||||||
// AppToast.showSuccessToast(message: TranslationBase.of(context).reminderCancelSuccess);
|
|
||||||
hasReminder = false;
|
|
||||||
} else {
|
|
||||||
hasReminder = false;
|
|
||||||
// setState(() {
|
|
||||||
// hasReminder = true;
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,65 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
import 'package:dartz/dartz.dart';
|
|
||||||
import 'package:hmg_patient_app_new/features/active_prescriptions/models/active_prescriptions_response_model.dart';
|
|
||||||
import '../../core/api/api_client.dart';
|
|
||||||
import '../../core/api_consts.dart';
|
|
||||||
import '../../core/common_models/generic_api_model.dart';
|
|
||||||
import '../../core/exceptions/api_failure.dart';
|
|
||||||
import '../../services/logger_service.dart';
|
|
||||||
|
|
||||||
abstract class ActivePrescriptionsRepo {
|
|
||||||
|
|
||||||
Future<Either<Failure, GenericApiModel<List<ActivePrescriptionsResponseModel>>>> getActivePrescriptionsDetails();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class ActivePrescriptionsRepoImp implements ActivePrescriptionsRepo {
|
|
||||||
final ApiClient apiClient;
|
|
||||||
final LoggerService loggerService;
|
|
||||||
|
|
||||||
ActivePrescriptionsRepoImp({required this.loggerService, required this.apiClient});
|
|
||||||
|
|
||||||
@override
|
|
||||||
|
|
||||||
Future<Either<Failure, GenericApiModel<List<ActivePrescriptionsResponseModel>>>> getActivePrescriptionsDetails() async
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
GenericApiModel<List<ActivePrescriptionsResponseModel>>? apiResponse;
|
|
||||||
Failure? failure;
|
|
||||||
await apiClient.post(
|
|
||||||
ApiConsts.getActivePrescriptionsDetails,
|
|
||||||
body: {},
|
|
||||||
onFailure: (error, statusCode, {messageStatus, failureType}) {
|
|
||||||
failure = failureType;
|
|
||||||
},
|
|
||||||
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
|
|
||||||
try {
|
|
||||||
var list = response['List_ActiveGetPrescriptionReportByPatientID'];
|
|
||||||
var res = list
|
|
||||||
.map<ActivePrescriptionsResponseModel>(
|
|
||||||
(item) => ActivePrescriptionsResponseModel.fromJson(item))
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
apiResponse = GenericApiModel<List<ActivePrescriptionsResponseModel>>(
|
|
||||||
messageStatus: messageStatus,
|
|
||||||
statusCode: statusCode,
|
|
||||||
errorMessage: null,
|
|
||||||
// data: response,
|
|
||||||
data: res
|
|
||||||
);
|
|
||||||
return apiResponse;
|
|
||||||
} catch (e) {
|
|
||||||
failure = DataParsingFailure(e.toString());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if (failure != null) return Left(failure!);
|
|
||||||
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
|
|
||||||
return Right(apiResponse!);
|
|
||||||
} catch (e) {
|
|
||||||
return Left(UnknownFailure(e.toString()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,101 +0,0 @@
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:hmg_patient_app_new/features/active_prescriptions/models/active_prescriptions_response_model.dart';
|
|
||||||
import 'package:hmg_patient_app_new/features/active_prescriptions/active_prescriptions_repo.dart';
|
|
||||||
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
|
|
||||||
|
|
||||||
class ActivePrescriptionsViewModel extends ChangeNotifier {
|
|
||||||
late ActivePrescriptionsRepo activePrescriptionsRepo;
|
|
||||||
late ErrorHandlerService errorHandlerService;
|
|
||||||
List<ActivePrescriptionsResponseModel> activePrescriptionsDetailsList = [];
|
|
||||||
|
|
||||||
ActivePrescriptionsViewModel({
|
|
||||||
required this.activePrescriptionsRepo,
|
|
||||||
required this.errorHandlerService,
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<void> getActiveMedications({
|
|
||||||
Function(dynamic)? onSuccess,
|
|
||||||
Function(String)? onError,
|
|
||||||
}) async {
|
|
||||||
final result =
|
|
||||||
await activePrescriptionsRepo.getActivePrescriptionsDetails();
|
|
||||||
result.fold(
|
|
||||||
(failure) async =>
|
|
||||||
await errorHandlerService.handleError(failure: failure),
|
|
||||||
(apiResponse) {
|
|
||||||
if (apiResponse.messageStatus == 1) {
|
|
||||||
activePrescriptionsDetailsList = apiResponse.data ?? [];
|
|
||||||
notifyListeners();
|
|
||||||
if (onSuccess != null) onSuccess(apiResponse.data);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
DateTime parseDate(String? date) {
|
|
||||||
if (date == null) return DateTime.now();
|
|
||||||
final regex = RegExp(r"\/Date\((\d+)([+-]\d+)?\)\/");
|
|
||||||
final match = regex.firstMatch(date);
|
|
||||||
if (match != null) {
|
|
||||||
final millis = int.parse(match.group(1)!);
|
|
||||||
return DateTime.fromMillisecondsSinceEpoch(millis);
|
|
||||||
}
|
|
||||||
return DateTime.tryParse(date) ?? DateTime.now();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<DateTime> generateMedicationDays(ActivePrescriptionsResponseModel med) {
|
|
||||||
final start = parseDate(med.startDate);
|
|
||||||
final duration = med.days ?? 0;
|
|
||||||
if (duration <= 0) return [];
|
|
||||||
final f = (med.frequency ?? "").toLowerCase().trim();
|
|
||||||
int intervalDays = 1;
|
|
||||||
|
|
||||||
if (f.contains("every six hours") ||
|
|
||||||
f.contains("every 6 hours") ||
|
|
||||||
f.contains("every four hours") ||
|
|
||||||
f.contains("every 4 hours") ||
|
|
||||||
f.contains("every eight hours") ||
|
|
||||||
f.contains("every 8 hours") ||
|
|
||||||
f.contains("every 12 hours") ||
|
|
||||||
f.contains("every twelve hours") ||
|
|
||||||
f.contains("every 24 hours") ||
|
|
||||||
f.contains("3 times a day") ||
|
|
||||||
f.contains("once a day")) {
|
|
||||||
intervalDays = 1;
|
|
||||||
}
|
|
||||||
else if (f.contains("once a week")) {
|
|
||||||
intervalDays = 7;
|
|
||||||
}
|
|
||||||
else if (f.contains("every 3 days")) {
|
|
||||||
intervalDays = 3;
|
|
||||||
}
|
|
||||||
else if (f.contains("every other day")) {
|
|
||||||
intervalDays = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<DateTime> result = [];
|
|
||||||
for (int offset = 0; offset < duration; offset += intervalDays) {
|
|
||||||
result.add(start.add(Duration(days: offset)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sameYMD(DateTime a, DateTime b) =>
|
|
||||||
a.year == b.year && a.month == b.month && a.day == b.day;
|
|
||||||
|
|
||||||
List<ActivePrescriptionsResponseModel> getMedsForSelectedDay(
|
|
||||||
DateTime selectedDate) {
|
|
||||||
final clean = DateTime(selectedDate.year, selectedDate.month, selectedDate.day);
|
|
||||||
|
|
||||||
return activePrescriptionsDetailsList.where((med) {
|
|
||||||
final days = generateMedicationDays(med);
|
|
||||||
return days.any((d) => sameYMD(d, clean));
|
|
||||||
}).toList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,78 +0,0 @@
|
|||||||
|
|
||||||
class ActivePrescriptionsResponseModel {
|
|
||||||
String? itemId;
|
|
||||||
String? itemDescription;
|
|
||||||
String? route;
|
|
||||||
String? frequency;
|
|
||||||
int? frequencyNumber;
|
|
||||||
int? doseDailyQuantity;
|
|
||||||
int? days;
|
|
||||||
String? startDate;
|
|
||||||
String? endDate;
|
|
||||||
String? orderDate;
|
|
||||||
String? productImageString;
|
|
||||||
bool isReminderOn;
|
|
||||||
List<String?> selectedDoseTimes = [];
|
|
||||||
|
|
||||||
ActivePrescriptionsResponseModel({
|
|
||||||
this.itemId,
|
|
||||||
this.itemDescription,
|
|
||||||
this.route,
|
|
||||||
this.frequency,
|
|
||||||
this.frequencyNumber,
|
|
||||||
this.doseDailyQuantity,
|
|
||||||
this.days,
|
|
||||||
this.startDate,
|
|
||||||
this.endDate,
|
|
||||||
this.orderDate,
|
|
||||||
this.productImageString,
|
|
||||||
this.isReminderOn = false,
|
|
||||||
List<String?>? selectedDoseTimes,
|
|
||||||
}) {
|
|
||||||
this.selectedDoseTimes = selectedDoseTimes ?? [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ========== JSON FROM ==========
|
|
||||||
factory ActivePrescriptionsResponseModel.fromJson(Map<String, dynamic> json) {
|
|
||||||
return ActivePrescriptionsResponseModel(
|
|
||||||
itemId: json["ItemID"]?.toString() ?? "",
|
|
||||||
itemDescription: json["ItemDescription"] ?? "",
|
|
||||||
route: json["Route"] ?? "",
|
|
||||||
frequency: json["Frequency"] ?? "",
|
|
||||||
frequencyNumber: json["FrequencyNumber"],
|
|
||||||
doseDailyQuantity: json["DoseDailyQuantity"] ?? 1,
|
|
||||||
days: json["Days"] ?? 0,
|
|
||||||
startDate: json["StartDate"] ?? "",
|
|
||||||
endDate: json["EndDate"] ?? "",
|
|
||||||
orderDate: json["OrderDate"] ?? "",
|
|
||||||
productImageString: json["ProductImageString"] ?? "",
|
|
||||||
isReminderOn: json["IsReminderOn"] == true,
|
|
||||||
selectedDoseTimes:
|
|
||||||
(json["SelectedDoseTimes"] as List<dynamic>?)
|
|
||||||
?.map((e) => e?.toString())
|
|
||||||
.toList() ??
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// ========== JSON TO ==========
|
|
||||||
Map<String, dynamic> toJson() {
|
|
||||||
return {
|
|
||||||
"ItemID": itemId,
|
|
||||||
"ItemDescription": itemDescription,
|
|
||||||
"Route": route,
|
|
||||||
"Frequency": frequency,
|
|
||||||
"FrequencyNumber": frequencyNumber,
|
|
||||||
"DoseDailyQuantity": doseDailyQuantity,
|
|
||||||
"Days": days,
|
|
||||||
"StartDate": startDate,
|
|
||||||
"EndDate": endDate,
|
|
||||||
"OrderDate": orderDate,
|
|
||||||
"ProductImageString": productImageString,
|
|
||||||
"IsReminderOn": isReminderOn,
|
|
||||||
"SelectedDoseTimes": selectedDoseTimes,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,96 +0,0 @@
|
|||||||
import 'package:dartz/dartz.dart';
|
|
||||||
import '../../core/api/api_client.dart';
|
|
||||||
import '../../core/api_consts.dart';
|
|
||||||
import '../../core/common_models/generic_api_model.dart';
|
|
||||||
import '../../core/exceptions/api_failure.dart';
|
|
||||||
import '../../services/logger_service.dart';
|
|
||||||
|
|
||||||
abstract class MonthlyReportsRepo {
|
|
||||||
Future<Either<Failure, GenericApiModel<dynamic>>> saveMonthlyReport({
|
|
||||||
String? email,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
class MonthlyReportsRepoImp implements MonthlyReportsRepo {
|
|
||||||
final ApiClient apiClient;
|
|
||||||
final LoggerService loggerService;
|
|
||||||
|
|
||||||
MonthlyReportsRepoImp({
|
|
||||||
required this.loggerService,
|
|
||||||
required this.apiClient,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<Either<Failure, GenericApiModel<dynamic>>> saveMonthlyReport({
|
|
||||||
String? email,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
Failure? failure;
|
|
||||||
|
|
||||||
GenericApiModel<dynamic>? reportApiResponse;
|
|
||||||
|
|
||||||
await apiClient.post(
|
|
||||||
ApiConsts.getMonthlyReports,
|
|
||||||
body: <String, dynamic>{},
|
|
||||||
onFailure: (error, statusCode, {messageStatus, failureType}) {
|
|
||||||
failure = failureType;
|
|
||||||
},
|
|
||||||
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
|
|
||||||
try {
|
|
||||||
reportApiResponse = GenericApiModel<dynamic>(
|
|
||||||
messageStatus: messageStatus,
|
|
||||||
statusCode: statusCode,
|
|
||||||
errorMessage: errorMessage,
|
|
||||||
data: response,
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
failure = DataParsingFailure(e.toString());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (failure != null) return Left(failure!);
|
|
||||||
if (reportApiResponse == null) return Left(ServerFailure("Unknown error"));
|
|
||||||
|
|
||||||
if ((reportApiResponse!.messageStatus ?? 0) != 1) {
|
|
||||||
return Right(reportApiResponse!);
|
|
||||||
}
|
|
||||||
|
|
||||||
GenericApiModel<dynamic>? emailApiResponse;
|
|
||||||
|
|
||||||
final Map<String, dynamic> emailRequest = <String, dynamic>{};
|
|
||||||
|
|
||||||
if (email != null && email.trim().isNotEmpty) {
|
|
||||||
emailRequest["Email"] = email.trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
await apiClient.post(
|
|
||||||
ApiConsts.updatePatientEmail,
|
|
||||||
body: emailRequest,
|
|
||||||
onFailure: (error, statusCode, {messageStatus, failureType}) {
|
|
||||||
failure = failureType;
|
|
||||||
},
|
|
||||||
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
|
|
||||||
try {
|
|
||||||
emailApiResponse = GenericApiModel<dynamic>(
|
|
||||||
messageStatus: messageStatus,
|
|
||||||
statusCode: statusCode,
|
|
||||||
errorMessage: errorMessage,
|
|
||||||
data: response,
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
failure = DataParsingFailure(e.toString());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (failure != null) return Left(failure!);
|
|
||||||
if (emailApiResponse == null) return Left(ServerFailure("Unknown error"));
|
|
||||||
|
|
||||||
return Right(emailApiResponse!);
|
|
||||||
} catch (e) {
|
|
||||||
loggerService.logError("MonthlyReportsRepo.saveMonthlyReport error: $e");
|
|
||||||
return Left(UnknownFailure(e.toString()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
|
|
||||||
import 'monthly_reports_repo.dart';
|
|
||||||
class MonthlyReportsViewModel extends ChangeNotifier {
|
|
||||||
final MonthlyReportsRepo monthlyReportsRepo;
|
|
||||||
final ErrorHandlerService errorHandlerService;
|
|
||||||
|
|
||||||
bool isLoading = false;
|
|
||||||
|
|
||||||
MonthlyReportsViewModel({
|
|
||||||
required this.monthlyReportsRepo,
|
|
||||||
required this.errorHandlerService,
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<bool> saveMonthlyReport({String? email}) async {
|
|
||||||
isLoading = true;
|
|
||||||
notifyListeners();
|
|
||||||
|
|
||||||
final result = await monthlyReportsRepo.saveMonthlyReport(email: email);
|
|
||||||
|
|
||||||
final success = result.fold(
|
|
||||||
(failure) {
|
|
||||||
errorHandlerService.handleError(failure: failure);
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
(apiResponse) => (apiResponse.messageStatus ?? 0) == 1,
|
|
||||||
);
|
|
||||||
|
|
||||||
isLoading = false;
|
|
||||||
notifyListeners();
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
import 'package:dartz/dartz.dart';
|
|
||||||
import '../../core/api/api_client.dart';
|
|
||||||
import '../../core/api_consts.dart';
|
|
||||||
import '../../core/exceptions/api_failure.dart';
|
|
||||||
import '../../services/logger_service.dart';
|
|
||||||
|
|
||||||
abstract class TermsConditionsRepo {
|
|
||||||
Future<Either<Failure, String>> getTermsConditions();
|
|
||||||
}
|
|
||||||
|
|
||||||
class TermsConditionsRepoImp implements TermsConditionsRepo {
|
|
||||||
final ApiClient apiClient;
|
|
||||||
final LoggerService loggerService;
|
|
||||||
|
|
||||||
TermsConditionsRepoImp({
|
|
||||||
required this.loggerService,
|
|
||||||
required this.apiClient,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<Either<Failure, String>> getTermsConditions() async {
|
|
||||||
Failure? failure;
|
|
||||||
String? html;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await apiClient.post(
|
|
||||||
ApiConsts.getTermsConditions,
|
|
||||||
body: <String, dynamic>{},
|
|
||||||
onFailure: (error, statusCode, {messageStatus, failureType}) {
|
|
||||||
failure = failureType ?? ServerFailure(error.toString());
|
|
||||||
},
|
|
||||||
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
|
|
||||||
try {
|
|
||||||
|
|
||||||
final content = response['UserAgreementContent'];
|
|
||||||
|
|
||||||
if (content is String && content.isNotEmpty) {
|
|
||||||
html = content;
|
|
||||||
} else {
|
|
||||||
failure = DataParsingFailure(
|
|
||||||
'UserAgreementContent is null or not String');
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
failure = DataParsingFailure(e.toString());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
failure = UnknownFailure(e.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (failure != null) return Left(failure!);
|
|
||||||
if (html == null || html!.isEmpty) {
|
|
||||||
return Left(ServerFailure('No terms and conditions returned'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Right(html!);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:hmg_patient_app_new/features/monthly_reports/terms_conditions_repo.dart';
|
|
||||||
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
|
|
||||||
|
|
||||||
class TermsConditionsViewModel extends ChangeNotifier {
|
|
||||||
final TermsConditionsRepo termsConditionsRepo;
|
|
||||||
final ErrorHandlerService errorHandlerService;
|
|
||||||
|
|
||||||
String? termsConditionsHtml;
|
|
||||||
bool isLoading = false;
|
|
||||||
|
|
||||||
TermsConditionsViewModel({
|
|
||||||
required this.termsConditionsRepo,
|
|
||||||
required this.errorHandlerService,
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<void> getTermsConditions({
|
|
||||||
Function()? onSuccess,
|
|
||||||
Function(String)? onError,
|
|
||||||
}) async {
|
|
||||||
isLoading = true;
|
|
||||||
notifyListeners();
|
|
||||||
|
|
||||||
final result = await termsConditionsRepo.getTermsConditions();
|
|
||||||
|
|
||||||
result.fold(
|
|
||||||
(failure) async {
|
|
||||||
await errorHandlerService.handleError(failure: failure);
|
|
||||||
isLoading = false;
|
|
||||||
notifyListeners();
|
|
||||||
if (onError != null) {
|
|
||||||
onError(failure.message ?? 'Something went wrong');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(html) {
|
|
||||||
termsConditionsHtml = html;
|
|
||||||
isLoading = false;
|
|
||||||
notifyListeners();
|
|
||||||
if (onSuccess != null) onSuccess();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,96 +0,0 @@
|
|||||||
class NotificationResponseModel {
|
|
||||||
int? id;
|
|
||||||
int? recordId;
|
|
||||||
int? patientID;
|
|
||||||
bool? projectOutSA;
|
|
||||||
String? deviceType;
|
|
||||||
String? deviceToken;
|
|
||||||
String? message;
|
|
||||||
String? messageType;
|
|
||||||
String? messageTypeData;
|
|
||||||
String? videoURL;
|
|
||||||
bool? isQueue;
|
|
||||||
String? isQueueOn;
|
|
||||||
String? createdOn;
|
|
||||||
dynamic createdBy;
|
|
||||||
String? notificationType;
|
|
||||||
bool? isSent;
|
|
||||||
String? isSentOn;
|
|
||||||
bool? isRead;
|
|
||||||
dynamic isReadOn;
|
|
||||||
int? channelID;
|
|
||||||
int? projectID;
|
|
||||||
|
|
||||||
NotificationResponseModel(
|
|
||||||
{this.id,
|
|
||||||
this.recordId,
|
|
||||||
this.patientID,
|
|
||||||
this.projectOutSA,
|
|
||||||
this.deviceType,
|
|
||||||
this.deviceToken,
|
|
||||||
this.message,
|
|
||||||
this.messageType,
|
|
||||||
this.messageTypeData,
|
|
||||||
this.videoURL,
|
|
||||||
this.isQueue,
|
|
||||||
this.isQueueOn,
|
|
||||||
this.createdOn,
|
|
||||||
this.createdBy,
|
|
||||||
this.notificationType,
|
|
||||||
this.isSent,
|
|
||||||
this.isSentOn,
|
|
||||||
this.isRead,
|
|
||||||
this.isReadOn,
|
|
||||||
this.channelID,
|
|
||||||
this.projectID});
|
|
||||||
|
|
||||||
NotificationResponseModel.fromJson(Map<String, dynamic> json) {
|
|
||||||
id = json['Id'];
|
|
||||||
recordId = json['RecordId'];
|
|
||||||
patientID = json['PatientID'];
|
|
||||||
projectOutSA = json['ProjectOutSA'];
|
|
||||||
deviceType = json['DeviceType'];
|
|
||||||
deviceToken = json['DeviceToken'];
|
|
||||||
message = json['Message'];
|
|
||||||
messageType = json['MessageType'];
|
|
||||||
messageTypeData = json['MessageTypeData'];
|
|
||||||
videoURL = json['VideoURL'];
|
|
||||||
isQueue = json['IsQueue'];
|
|
||||||
isQueueOn = json['IsQueueOn'];
|
|
||||||
createdOn = json['CreatedOn'];
|
|
||||||
createdBy = json['CreatedBy'];
|
|
||||||
notificationType = json['NotificationType'];
|
|
||||||
isSent = json['IsSent'];
|
|
||||||
isSentOn = json['IsSentOn'];
|
|
||||||
isRead = json['IsRead'];
|
|
||||||
isReadOn = json['IsReadOn'];
|
|
||||||
channelID = json['ChannelID'];
|
|
||||||
projectID = json['ProjectID'];
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
|
||||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
|
||||||
data['Id'] = this.id;
|
|
||||||
data['RecordId'] = this.recordId;
|
|
||||||
data['PatientID'] = this.patientID;
|
|
||||||
data['ProjectOutSA'] = this.projectOutSA;
|
|
||||||
data['DeviceType'] = this.deviceType;
|
|
||||||
data['DeviceToken'] = this.deviceToken;
|
|
||||||
data['Message'] = this.message;
|
|
||||||
data['MessageType'] = this.messageType;
|
|
||||||
data['MessageTypeData'] = this.messageTypeData;
|
|
||||||
data['VideoURL'] = this.videoURL;
|
|
||||||
data['IsQueue'] = this.isQueue;
|
|
||||||
data['IsQueueOn'] = this.isQueueOn;
|
|
||||||
data['CreatedOn'] = this.createdOn;
|
|
||||||
data['CreatedBy'] = this.createdBy;
|
|
||||||
data['NotificationType'] = this.notificationType;
|
|
||||||
data['IsSent'] = this.isSent;
|
|
||||||
data['IsSentOn'] = this.isSentOn;
|
|
||||||
data['IsRead'] = this.isRead;
|
|
||||||
data['IsReadOn'] = this.isReadOn;
|
|
||||||
data['ChannelID'] = this.channelID;
|
|
||||||
data['ProjectID'] = this.projectID;
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,78 +0,0 @@
|
|||||||
import 'package:dartz/dartz.dart';
|
|
||||||
import 'package:hmg_patient_app_new/core/api/api_client.dart';
|
|
||||||
import 'package:hmg_patient_app_new/core/api_consts.dart';
|
|
||||||
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
|
|
||||||
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
|
|
||||||
import 'package:hmg_patient_app_new/features/notifications/models/resp_models/notification_response_model.dart';
|
|
||||||
import 'package:hmg_patient_app_new/services/logger_service.dart';
|
|
||||||
|
|
||||||
abstract class NotificationsRepo {
|
|
||||||
Future<Either<Failure, GenericApiModel<List<NotificationResponseModel>>>> getAllNotifications({
|
|
||||||
required int notificationStatusID,
|
|
||||||
required int pagingSize,
|
|
||||||
required int currentPage,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
class NotificationsRepoImp implements NotificationsRepo {
|
|
||||||
final ApiClient apiClient;
|
|
||||||
final LoggerService loggerService;
|
|
||||||
|
|
||||||
NotificationsRepoImp({required this.loggerService, required this.apiClient});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<Either<Failure, GenericApiModel<List<NotificationResponseModel>>>> getAllNotifications({
|
|
||||||
required int notificationStatusID,
|
|
||||||
required int pagingSize,
|
|
||||||
required int currentPage,
|
|
||||||
}) async {
|
|
||||||
Map<String, dynamic> mapDevice = {
|
|
||||||
"NotificationStatusID": notificationStatusID,
|
|
||||||
"pagingSize": pagingSize,
|
|
||||||
"currentPage": currentPage,
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
GenericApiModel<List<NotificationResponseModel>>? apiResponse;
|
|
||||||
Failure? failure;
|
|
||||||
await apiClient.post(
|
|
||||||
GET_ALL_NOTIFICATIONS,
|
|
||||||
body: mapDevice,
|
|
||||||
onFailure: (error, statusCode, {messageStatus, failureType}) {
|
|
||||||
failure = failureType;
|
|
||||||
},
|
|
||||||
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
|
|
||||||
try {
|
|
||||||
final list = response['List_GetAllNotificationsFromPool'];
|
|
||||||
if (list == null || list.isEmpty) {
|
|
||||||
// Return empty list if no notifications
|
|
||||||
apiResponse = GenericApiModel<List<NotificationResponseModel>>(
|
|
||||||
messageStatus: messageStatus,
|
|
||||||
statusCode: statusCode,
|
|
||||||
errorMessage: null,
|
|
||||||
data: [],
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final notifications = list.map((item) => NotificationResponseModel.fromJson(item as Map<String, dynamic>)).toList().cast<NotificationResponseModel>();
|
|
||||||
|
|
||||||
apiResponse = GenericApiModel<List<NotificationResponseModel>>(
|
|
||||||
messageStatus: messageStatus,
|
|
||||||
statusCode: statusCode,
|
|
||||||
errorMessage: null,
|
|
||||||
data: notifications,
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
failure = DataParsingFailure(e.toString());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if (failure != null) return Left(failure!);
|
|
||||||
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
|
|
||||||
return Right(apiResponse!);
|
|
||||||
} catch (e) {
|
|
||||||
return Left(UnknownFailure(e.toString()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,113 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:hmg_patient_app_new/features/notifications/models/resp_models/notification_response_model.dart';
|
|
||||||
import 'package:hmg_patient_app_new/features/notifications/notifications_repo.dart';
|
|
||||||
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
|
|
||||||
|
|
||||||
class NotificationsViewModel extends ChangeNotifier {
|
|
||||||
bool isNotificationsLoading = false;
|
|
||||||
bool hasMoreNotifications = true;
|
|
||||||
|
|
||||||
NotificationsRepo notificationsRepo;
|
|
||||||
ErrorHandlerService errorHandlerService;
|
|
||||||
|
|
||||||
List<NotificationResponseModel> notificationsList = [];
|
|
||||||
|
|
||||||
int currentPage = 0;
|
|
||||||
int pagingSize = 14;
|
|
||||||
int notificationStatusID = 2; // Default to status 2 (e.g., unread)
|
|
||||||
|
|
||||||
NotificationsViewModel({
|
|
||||||
required this.notificationsRepo,
|
|
||||||
required this.errorHandlerService,
|
|
||||||
});
|
|
||||||
|
|
||||||
initNotificationsViewModel({int? statusID}) {
|
|
||||||
notificationsList.clear();
|
|
||||||
currentPage = 0;
|
|
||||||
hasMoreNotifications = true;
|
|
||||||
isNotificationsLoading = true;
|
|
||||||
// if (statusID != null) {
|
|
||||||
// notificationStatusID = statusID;
|
|
||||||
// }
|
|
||||||
// getAllNotifications();
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
setNotificationStatusID(int statusID) {
|
|
||||||
notificationStatusID = statusID;
|
|
||||||
notificationsList.clear();
|
|
||||||
currentPage = 0;
|
|
||||||
hasMoreNotifications = true;
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> getAllNotifications({
|
|
||||||
Function(dynamic)? onSuccess,
|
|
||||||
Function(String)? onError,
|
|
||||||
}) async {
|
|
||||||
isNotificationsLoading = true;
|
|
||||||
notifyListeners();
|
|
||||||
|
|
||||||
final result = await notificationsRepo.getAllNotifications(
|
|
||||||
notificationStatusID: notificationStatusID,
|
|
||||||
pagingSize: pagingSize,
|
|
||||||
currentPage: currentPage,
|
|
||||||
);
|
|
||||||
|
|
||||||
result.fold(
|
|
||||||
(failure) async {
|
|
||||||
isNotificationsLoading = false;
|
|
||||||
notifyListeners();
|
|
||||||
await errorHandlerService.handleError(failure: failure);
|
|
||||||
if (onError != null) {
|
|
||||||
onError(failure.toString());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(apiResponse) {
|
|
||||||
isNotificationsLoading = false;
|
|
||||||
if (apiResponse.messageStatus == 2) {
|
|
||||||
notifyListeners();
|
|
||||||
if (onError != null) {
|
|
||||||
onError(apiResponse.errorMessage ?? "Unknown error");
|
|
||||||
}
|
|
||||||
} else if (apiResponse.messageStatus == 1) {
|
|
||||||
final newNotifications = apiResponse.data ?? [];
|
|
||||||
|
|
||||||
if (newNotifications.isEmpty || newNotifications.length < pagingSize) {
|
|
||||||
hasMoreNotifications = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
notificationsList.addAll(newNotifications);
|
|
||||||
currentPage++;
|
|
||||||
|
|
||||||
notifyListeners();
|
|
||||||
if (onSuccess != null) {
|
|
||||||
onSuccess(apiResponse);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> refreshNotifications({
|
|
||||||
Function(dynamic)? onSuccess,
|
|
||||||
Function(String)? onError,
|
|
||||||
}) async {
|
|
||||||
notificationsList.clear();
|
|
||||||
currentPage = 0;
|
|
||||||
hasMoreNotifications = true;
|
|
||||||
await getAllNotifications(onSuccess: onSuccess, onError: onError);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> loadMoreNotifications({
|
|
||||||
Function(dynamic)? onSuccess,
|
|
||||||
Function(String)? onError,
|
|
||||||
}) async {
|
|
||||||
await getAllNotifications(onSuccess: onSuccess, onError: onError);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,183 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
class QrParkingResponseModel {
|
|
||||||
dynamic totalRecords;
|
|
||||||
dynamic nRowID;
|
|
||||||
int? qRParkingID;
|
|
||||||
String? description;
|
|
||||||
String? descriptionN;
|
|
||||||
dynamic qRCompare;
|
|
||||||
dynamic qRValue;
|
|
||||||
String? imagePath;
|
|
||||||
bool? isActive;
|
|
||||||
int? parkingID;
|
|
||||||
int? branchID;
|
|
||||||
int? companyID;
|
|
||||||
int? buildingID;
|
|
||||||
int? rowID;
|
|
||||||
int? gateID;
|
|
||||||
int? floorID;
|
|
||||||
dynamic imagePath1;
|
|
||||||
int? createdBy;
|
|
||||||
String? createdOn;
|
|
||||||
dynamic editedBy;
|
|
||||||
dynamic editedOn;
|
|
||||||
String? parkingDescription;
|
|
||||||
String? parkingDescriptionN;
|
|
||||||
String? gateDescription;
|
|
||||||
String? gateDescriptionN;
|
|
||||||
String? branchDescription;
|
|
||||||
String? branchDescriptionN;
|
|
||||||
String? companyDescription;
|
|
||||||
String? companyDescriptionN;
|
|
||||||
String? rowDescription;
|
|
||||||
String? rowDescriptionN;
|
|
||||||
String? floorDescription;
|
|
||||||
String? floorDescriptionN;
|
|
||||||
String? buildingDescription;
|
|
||||||
String? buildingDescriptionN;
|
|
||||||
String? qRParkingCode;
|
|
||||||
String? parkingCode;
|
|
||||||
double? latitude;
|
|
||||||
double? longitude;
|
|
||||||
String? qRImageStr;
|
|
||||||
|
|
||||||
QrParkingResponseModel({
|
|
||||||
this.totalRecords,
|
|
||||||
this.nRowID,
|
|
||||||
this.qRParkingID,
|
|
||||||
this.description,
|
|
||||||
this.descriptionN,
|
|
||||||
this.qRCompare,
|
|
||||||
this.qRValue,
|
|
||||||
this.imagePath,
|
|
||||||
this.isActive,
|
|
||||||
this.parkingID,
|
|
||||||
this.branchID,
|
|
||||||
this.companyID,
|
|
||||||
this.buildingID,
|
|
||||||
this.rowID,
|
|
||||||
this.gateID,
|
|
||||||
this.floorID,
|
|
||||||
this.imagePath1,
|
|
||||||
this.createdBy,
|
|
||||||
this.createdOn,
|
|
||||||
this.editedBy,
|
|
||||||
this.editedOn,
|
|
||||||
this.parkingDescription,
|
|
||||||
this.parkingDescriptionN,
|
|
||||||
this.gateDescription,
|
|
||||||
this.gateDescriptionN,
|
|
||||||
this.branchDescription,
|
|
||||||
this.branchDescriptionN,
|
|
||||||
this.companyDescription,
|
|
||||||
this.companyDescriptionN,
|
|
||||||
this.rowDescription,
|
|
||||||
this.rowDescriptionN,
|
|
||||||
this.floorDescription,
|
|
||||||
this.floorDescriptionN,
|
|
||||||
this.buildingDescription,
|
|
||||||
this.buildingDescriptionN,
|
|
||||||
this.qRParkingCode,
|
|
||||||
this.parkingCode,
|
|
||||||
this.latitude,
|
|
||||||
this.longitude,
|
|
||||||
this.qRImageStr,
|
|
||||||
});
|
|
||||||
|
|
||||||
QrParkingResponseModel.fromJson(Map<String, dynamic> json) {
|
|
||||||
totalRecords = json['TotalRecords'];
|
|
||||||
nRowID = json['nRowID'];
|
|
||||||
qRParkingID = json['QRParkingID'];
|
|
||||||
description = json['Description'];
|
|
||||||
descriptionN = json['DescriptionN'];
|
|
||||||
qRCompare = json['QRCompare'];
|
|
||||||
qRValue = json['QRValue'];
|
|
||||||
imagePath = json['ImagePath'];
|
|
||||||
isActive = json['IsActive'];
|
|
||||||
parkingID = json['ParkingID'];
|
|
||||||
branchID = json['BranchID'];
|
|
||||||
companyID = json['CompanyID'];
|
|
||||||
buildingID = json['BuildingID'];
|
|
||||||
rowID = json['RowID'];
|
|
||||||
gateID = json['GateID'];
|
|
||||||
floorID = json['FloorID'];
|
|
||||||
imagePath1 = json['ImagePath1'];
|
|
||||||
createdBy = json['CreatedBy'];
|
|
||||||
createdOn = json['CreatedOn'];
|
|
||||||
editedBy = json['EditedBy'];
|
|
||||||
editedOn = json['EditedOn'];
|
|
||||||
parkingDescription = json['ParkingDescription'];
|
|
||||||
parkingDescriptionN = json['ParkingDescriptionN'];
|
|
||||||
gateDescription = json['GateDescription'];
|
|
||||||
gateDescriptionN = json['GateDescriptionN'];
|
|
||||||
branchDescription = json['BranchDescription'];
|
|
||||||
branchDescriptionN = json['BranchDescriptionN'];
|
|
||||||
companyDescription = json['CompanyDescription'];
|
|
||||||
companyDescriptionN = json['CompanyDescriptionN'];
|
|
||||||
rowDescription = json['RowDescription'];
|
|
||||||
rowDescriptionN = json['RowDescriptionN'];
|
|
||||||
floorDescription = json['FloorDescription'];
|
|
||||||
floorDescriptionN = json['FloorDescriptionN'];
|
|
||||||
buildingDescription = json['BuildingDescription'];
|
|
||||||
buildingDescriptionN = json['BuildingDescriptionN'];
|
|
||||||
qRParkingCode = json['QRParkingCode'];
|
|
||||||
parkingCode = json['ParkingCode'];
|
|
||||||
latitude = _toDouble(json['Latitude']);
|
|
||||||
longitude = _toDouble(json['Longitude']);
|
|
||||||
qRImageStr = json['QRImageStr'];
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
|
||||||
final Map<String, dynamic> data = <String, dynamic>{};
|
|
||||||
data['TotalRecords'] = totalRecords;
|
|
||||||
data['nRowID'] = nRowID;
|
|
||||||
data['QRParkingID'] = qRParkingID;
|
|
||||||
data['Description'] = description;
|
|
||||||
data['DescriptionN'] = descriptionN;
|
|
||||||
data['QRCompare'] = qRCompare;
|
|
||||||
data['QRValue'] = qRValue;
|
|
||||||
data['ImagePath'] = imagePath;
|
|
||||||
data['IsActive'] = isActive;
|
|
||||||
data['ParkingID'] = parkingID;
|
|
||||||
data['BranchID'] = branchID;
|
|
||||||
data['CompanyID'] = companyID;
|
|
||||||
data['BuildingID'] = buildingID;
|
|
||||||
data['RowID'] = rowID;
|
|
||||||
data['GateID'] = gateID;
|
|
||||||
data['FloorID'] = floorID;
|
|
||||||
data['ImagePath1'] = imagePath1;
|
|
||||||
data['CreatedBy'] = createdBy;
|
|
||||||
data['CreatedOn'] = createdOn;
|
|
||||||
data['EditedBy'] = editedBy;
|
|
||||||
data['EditedOn'] = editedOn;
|
|
||||||
data['ParkingDescription'] = parkingDescription;
|
|
||||||
data['ParkingDescriptionN'] = parkingDescriptionN;
|
|
||||||
data['GateDescription'] = gateDescription;
|
|
||||||
data['GateDescriptionN'] = gateDescriptionN;
|
|
||||||
data['BranchDescription'] = branchDescription;
|
|
||||||
data['BranchDescriptionN'] = branchDescriptionN;
|
|
||||||
data['CompanyDescription'] = companyDescription;
|
|
||||||
data['CompanyDescriptionN'] = companyDescriptionN;
|
|
||||||
data['RowDescription'] = rowDescription;
|
|
||||||
data['RowDescriptionN'] = rowDescriptionN;
|
|
||||||
data['FloorDescription'] = floorDescription;
|
|
||||||
data['FloorDescriptionN'] = floorDescriptionN;
|
|
||||||
data['BuildingDescription'] = buildingDescription;
|
|
||||||
data['BuildingDescriptionN'] = buildingDescriptionN;
|
|
||||||
data['QRParkingCode'] = qRParkingCode;
|
|
||||||
data['ParkingCode'] = parkingCode;
|
|
||||||
data['Latitude'] = latitude;
|
|
||||||
data['Longitude'] = longitude;
|
|
||||||
data['QRImageStr'] = qRImageStr;
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
static double? _toDouble(dynamic v) {
|
|
||||||
if (v == null) return null;
|
|
||||||
if (v is double) return v;
|
|
||||||
if (v is int) return v.toDouble();
|
|
||||||
return double.tryParse(v.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,74 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
import 'package:dartz/dartz.dart';
|
|
||||||
import 'package:hmg_patient_app_new/features/qr_parking/models/qr_parking_response_model.dart';
|
|
||||||
import '../../core/api/api_client.dart';
|
|
||||||
import '../../core/api_consts.dart';
|
|
||||||
import '../../core/common_models/generic_api_model.dart';
|
|
||||||
import '../../core/exceptions/api_failure.dart';
|
|
||||||
import '../../services/logger_service.dart';
|
|
||||||
|
|
||||||
|
|
||||||
abstract class QrParkingRepo {
|
|
||||||
Future<Either<Failure, GenericApiModel<List<QrParkingResponseModel>>>>
|
|
||||||
getQrParking({
|
|
||||||
required int qrParkingId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
class QrParkingRepoImp implements QrParkingRepo {
|
|
||||||
final ApiClient apiClient;
|
|
||||||
final LoggerService loggerService;
|
|
||||||
|
|
||||||
QrParkingRepoImp({
|
|
||||||
required this.loggerService,
|
|
||||||
required this.apiClient,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<Either<Failure, GenericApiModel<List<QrParkingResponseModel>>>>
|
|
||||||
getQrParking({required int qrParkingId}) async {
|
|
||||||
try {
|
|
||||||
GenericApiModel<List<QrParkingResponseModel>>? apiResponse;
|
|
||||||
Failure? failure;
|
|
||||||
|
|
||||||
await apiClient.post(
|
|
||||||
ApiConsts.getQrParkingDetails, // GetQRParkingByID
|
|
||||||
body: {'QRParkingID': qrParkingId},
|
|
||||||
onFailure: (error, statusCode,
|
|
||||||
{messageStatus, failureType}) {
|
|
||||||
failure = failureType ??
|
|
||||||
StatusCodeFailure("$error ($statusCode)");
|
|
||||||
},
|
|
||||||
onSuccess: (response, statusCode,
|
|
||||||
{messageStatus, errorMessage}) {
|
|
||||||
final list =
|
|
||||||
(response['List_SWP_QRParkingModel'] as List?) ?? [];
|
|
||||||
|
|
||||||
final res = list
|
|
||||||
.map((e) => QrParkingResponseModel.fromJson(
|
|
||||||
Map<String, dynamic>.from(e),
|
|
||||||
))
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
apiResponse = GenericApiModel<List<QrParkingResponseModel>>(
|
|
||||||
messageStatus: messageStatus,
|
|
||||||
statusCode: statusCode,
|
|
||||||
errorMessage: null,
|
|
||||||
data: res,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (failure != null) return Left(failure!);
|
|
||||||
if (apiResponse == null) {
|
|
||||||
return Left(ServerFailure("Unknown error"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Right(apiResponse!);
|
|
||||||
} catch (e) {
|
|
||||||
return Left(UnknownFailure(e.toString()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,144 +0,0 @@
|
|||||||
import 'dart:convert';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:barcode_scan2/barcode_scan2.dart';
|
|
||||||
import 'package:hmg_patient_app_new/features/qr_parking/qr_parking_repo.dart';
|
|
||||||
|
|
||||||
import '../../services/cache_service.dart';
|
|
||||||
import '../../services/error_handler_service.dart';
|
|
||||||
import 'models/qr_parking_response_model.dart';
|
|
||||||
|
|
||||||
|
|
||||||
class QrParkingViewModel extends ChangeNotifier {
|
|
||||||
final QrParkingRepo qrParkingRepo;
|
|
||||||
final ErrorHandlerService errorHandlerService;
|
|
||||||
final CacheService cacheService;
|
|
||||||
String IS_GO_TO_PARKING = 'IS_GO_TO_PARKING';
|
|
||||||
|
|
||||||
bool isLoading = false;
|
|
||||||
String? error;
|
|
||||||
|
|
||||||
bool isSavePark = false;
|
|
||||||
QrParkingResponseModel? qrParkingModel;
|
|
||||||
List<QrParkingResponseModel> qrParkingList = [];
|
|
||||||
|
|
||||||
QrParkingViewModel({
|
|
||||||
required this.qrParkingRepo,
|
|
||||||
required this.errorHandlerService,
|
|
||||||
required this.cacheService,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
Future<QrParkingResponseModel?> scanAndGetParking() async {
|
|
||||||
try {
|
|
||||||
error = null;
|
|
||||||
isLoading = true;
|
|
||||||
notifyListeners();
|
|
||||||
|
|
||||||
final result = await BarcodeScanner.scan();
|
|
||||||
|
|
||||||
if (result.type != ResultType.Barcode) {
|
|
||||||
isLoading = false;
|
|
||||||
notifyListeners();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final raw = result.rawContent.trim();
|
|
||||||
if (raw.isEmpty) {
|
|
||||||
error = "Invalid QR Code";
|
|
||||||
isLoading = false;
|
|
||||||
notifyListeners();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final qrParkingId = _extractQrParkingId(raw);
|
|
||||||
if (qrParkingId == null) {
|
|
||||||
error = "Invalid QR Code";
|
|
||||||
isLoading = false;
|
|
||||||
notifyListeners();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final apiResult =
|
|
||||||
await qrParkingRepo.getQrParking(qrParkingId: qrParkingId);
|
|
||||||
|
|
||||||
final model = apiResult.fold(
|
|
||||||
(failure) {
|
|
||||||
errorHandlerService.handleError(failure: failure);
|
|
||||||
error = failure.toString();
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
(apiResponse) {
|
|
||||||
qrParkingList = apiResponse.data ?? [];
|
|
||||||
if (qrParkingList.isNotEmpty) {
|
|
||||||
return qrParkingList.first;
|
|
||||||
}
|
|
||||||
error = "Invalid Qr Code";
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (model != null) {
|
|
||||||
qrParkingModel = model;
|
|
||||||
isSavePark = true;
|
|
||||||
|
|
||||||
await cacheService.saveObject(
|
|
||||||
key: IS_GO_TO_PARKING,
|
|
||||||
value: model.toJson(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
isLoading = false;
|
|
||||||
notifyListeners();
|
|
||||||
return model;
|
|
||||||
} catch (e) {
|
|
||||||
error = "Scan error";
|
|
||||||
isLoading = false;
|
|
||||||
notifyListeners();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Load saved parking
|
|
||||||
Future<void> getIsSaveParking() async {
|
|
||||||
isLoading = true;
|
|
||||||
notifyListeners();
|
|
||||||
|
|
||||||
final parking =
|
|
||||||
await cacheService.getObject(key: IS_GO_TO_PARKING);
|
|
||||||
|
|
||||||
if (parking != null) {
|
|
||||||
isSavePark = true;
|
|
||||||
qrParkingModel = QrParkingResponseModel.fromJson(
|
|
||||||
Map<String, dynamic>.from(parking),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
isSavePark = false;
|
|
||||||
qrParkingModel = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
isLoading = false;
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reset parking
|
|
||||||
Future<void> clearParking() async {
|
|
||||||
await cacheService.remove(key: IS_GO_TO_PARKING);
|
|
||||||
isSavePark = false;
|
|
||||||
qrParkingModel = null;
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
int? _extractQrParkingId(String raw) {
|
|
||||||
try {
|
|
||||||
if (raw.startsWith("{")) {
|
|
||||||
final data = jsonDecode(raw);
|
|
||||||
return int.tryParse(data['QRParkingID'].toString());
|
|
||||||
}
|
|
||||||
return int.tryParse(raw);
|
|
||||||
} catch (_) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,97 +1,97 @@
|
|||||||
// import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
// import 'package:hmg_patient_app_new/core/enums.dart';
|
import 'package:hmg_patient_app_new/core/enums.dart';
|
||||||
//
|
|
||||||
// class ConditionsModel {
|
class ConditionsModel {
|
||||||
// final IconData icon;
|
final IconData icon;
|
||||||
// final String title;
|
final String title;
|
||||||
// final int percentage;
|
final int percentage;
|
||||||
// final String tagText;
|
final String tagText;
|
||||||
// final String clinic;
|
final String clinic;
|
||||||
// final List<String> symptoms;
|
final List<String> symptoms;
|
||||||
// final String description;
|
final String description;
|
||||||
// final String? monitorNote;
|
final String? monitorNote;
|
||||||
// final String? appointmentLabel;
|
final String? appointmentLabel;
|
||||||
// final PossibleConditionsSeverityEnum possibleConditionsSeverityEnum;
|
final PossibleConditionsSeverityEnum possibleConditionsSeverityEnum;
|
||||||
//
|
|
||||||
// ConditionsModel({
|
ConditionsModel({
|
||||||
// required this.icon,
|
required this.icon,
|
||||||
// required this.title,
|
required this.title,
|
||||||
// required this.percentage,
|
required this.percentage,
|
||||||
// required this.tagText,
|
required this.tagText,
|
||||||
// required this.clinic,
|
required this.clinic,
|
||||||
// required this.symptoms,
|
required this.symptoms,
|
||||||
// required this.description,
|
required this.description,
|
||||||
// required this.possibleConditionsSeverityEnum,
|
required this.possibleConditionsSeverityEnum,
|
||||||
// this.monitorNote,
|
this.monitorNote,
|
||||||
// this.appointmentLabel,
|
this.appointmentLabel,
|
||||||
// });
|
});
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// List<ConditionsModel> dummyConditions = [
|
List<ConditionsModel> dummyConditions = [
|
||||||
// ConditionsModel(
|
ConditionsModel(
|
||||||
// icon: Icons.psychology_alt,
|
icon: Icons.psychology_alt,
|
||||||
// possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.seekMedicalAdvice,
|
possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.seekMedicalAdvice,
|
||||||
// title: "Migraine",
|
title: "Migraine",
|
||||||
// percentage: 87,
|
percentage: 87,
|
||||||
// tagText: "Seek Medical Advice",
|
tagText: "Seek Medical Advice",
|
||||||
// clinic: "Internal Medicine Clinic",
|
clinic: "Internal Medicine Clinic",
|
||||||
// symptoms: ["Headache", "Nausea", "Sensitivity to light"],
|
symptoms: ["Headache", "Nausea", "Sensitivity to light"],
|
||||||
// description: "A migraine is a type of headache that can cause severe throbbing pain, usually on one side of the head.",
|
description: "A migraine is a type of headache that can cause severe throbbing pain, usually on one side of the head.",
|
||||||
// appointmentLabel: "Book Appointment",
|
appointmentLabel: "Book Appointment",
|
||||||
// ),
|
),
|
||||||
// ConditionsModel(
|
ConditionsModel(
|
||||||
// icon: Icons.deblur,
|
icon: Icons.deblur,
|
||||||
// title: "Tension Headache",
|
title: "Tension Headache",
|
||||||
// percentage: 37,
|
percentage: 37,
|
||||||
// tagText: "Monitor",
|
tagText: "Monitor",
|
||||||
// monitorNote: "No need to visit doctor",
|
monitorNote: "No need to visit doctor",
|
||||||
// clinic: "GP Clinic",
|
clinic: "GP Clinic",
|
||||||
// symptoms: ["Mild head pressure", "Scalp tenderness"],
|
symptoms: ["Mild head pressure", "Scalp tenderness"],
|
||||||
// description: "A tension-type headache is generally a mild to moderate pain that feels like a tight band around your head.",
|
description: "A tension-type headache is generally a mild to moderate pain that feels like a tight band around your head.",
|
||||||
// possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.monitorOnly,
|
possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.monitorOnly,
|
||||||
// ),
|
),
|
||||||
// ConditionsModel(
|
ConditionsModel(
|
||||||
// icon: Icons.medication_liquid,
|
icon: Icons.medication_liquid,
|
||||||
// title: "Meningitis",
|
title: "Meningitis",
|
||||||
// percentage: 28,
|
percentage: 28,
|
||||||
// tagText: "Emergency",
|
tagText: "Emergency",
|
||||||
// clinic: "Neurology Clinic",
|
clinic: "Neurology Clinic",
|
||||||
// symptoms: ["Mild head pressure", "Scalp tenderness"],
|
symptoms: ["Mild head pressure", "Scalp tenderness"],
|
||||||
// description: "A tension-type headache is generally a mild to moderate pain that feels like a tight band around your head.",
|
description: "A tension-type headache is generally a mild to moderate pain that feels like a tight band around your head.",
|
||||||
// appointmentLabel: "Book Appointment",
|
appointmentLabel: "Book Appointment",
|
||||||
// possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.emergency,
|
possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.emergency,
|
||||||
// ),
|
),
|
||||||
// ConditionsModel(
|
ConditionsModel(
|
||||||
// icon: Icons.psychology_alt,
|
icon: Icons.psychology_alt,
|
||||||
// title: "Migraine",
|
title: "Migraine",
|
||||||
// percentage: 87,
|
percentage: 87,
|
||||||
// tagText: "Seek Medical Advice",
|
tagText: "Seek Medical Advice",
|
||||||
// clinic: "Internal Medicine Clinic",
|
clinic: "Internal Medicine Clinic",
|
||||||
// symptoms: ["Headache", "Nausea", "Sensitivity to light"],
|
symptoms: ["Headache", "Nausea", "Sensitivity to light"],
|
||||||
// description: "A migraine is a type of headache that can cause severe throbbing pain, usually on one side of the head.",
|
description: "A migraine is a type of headache that can cause severe throbbing pain, usually on one side of the head.",
|
||||||
// appointmentLabel: "Book Appointment",
|
appointmentLabel: "Book Appointment",
|
||||||
// possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.seekMedicalAdvice,
|
possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.seekMedicalAdvice,
|
||||||
// ),
|
),
|
||||||
// ConditionsModel(
|
ConditionsModel(
|
||||||
// icon: Icons.deblur,
|
icon: Icons.deblur,
|
||||||
// title: "Tension Headache",
|
title: "Tension Headache",
|
||||||
// percentage: 37,
|
percentage: 37,
|
||||||
// tagText: "Monitor",
|
tagText: "Monitor",
|
||||||
// monitorNote: "No need to visit doctor",
|
monitorNote: "No need to visit doctor",
|
||||||
// clinic: "GP Clinic",
|
clinic: "GP Clinic",
|
||||||
// symptoms: ["Mild head pressure", "Scalp tenderness"],
|
symptoms: ["Mild head pressure", "Scalp tenderness"],
|
||||||
// description: "A tension-type headache is generally a mild to moderate pain that feels like a tight band around your head.",
|
description: "A tension-type headache is generally a mild to moderate pain that feels like a tight band around your head.",
|
||||||
// possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.monitorOnly,
|
possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.monitorOnly,
|
||||||
// ),
|
),
|
||||||
// ConditionsModel(
|
ConditionsModel(
|
||||||
// icon: Icons.medication_liquid,
|
icon: Icons.medication_liquid,
|
||||||
// title: "Meningitis",
|
title: "Meningitis",
|
||||||
// percentage: 28,
|
percentage: 28,
|
||||||
// tagText: "Emergency",
|
tagText: "Emergency",
|
||||||
// clinic: "Neurology Clinic",
|
clinic: "Neurology Clinic",
|
||||||
// symptoms: ["Mild head pressure", "Scalp tenderness"],
|
symptoms: ["Mild head pressure", "Scalp tenderness"],
|
||||||
// description: "A tension-type headache is generally a mild to moderate pain that feels like a tight band around your head.",
|
description: "A tension-type headache is generally a mild to moderate pain that feels like a tight band around your head.",
|
||||||
// appointmentLabel: "Book Appointment",
|
appointmentLabel: "Book Appointment",
|
||||||
// possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.emergency,
|
possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.emergency,
|
||||||
// ),
|
),
|
||||||
// ];
|
];
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue