Merge branch 'master' into haroon_dev

# Conflicts:
#	lib/features/prescriptions/prescriptions_view_model.dart
#	lib/presentation/appointments/appointment_details_page.dart
pull/107/head
haroon amjad 1 month ago
commit b37804d012

File diff suppressed because one or more lines are too long

@ -1,122 +1,128 @@
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
"idiom" : "iphone",
"scale" : "1x",
"size" : "29x29"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
"idiom" : "ipad",
"scale" : "1x",
"size" : "20x20"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
"idiom" : "ipad",
"scale" : "2x",
"size" : "20x20"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"size" : "1024x1024",
"filename" : "icon 1.jpg",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
"scale" : "1x",
"size" : "1024x1024"
},
{
"filename" : "Icon-App-76x76@2x.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "76x76"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

After

Width:  |  Height:  |  Size: 815 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 B

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 450 B

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 462 B

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 704 B

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 B

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 586 B

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 762 B

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 16 KiB

@ -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".needTranslation, 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. ".needTranslation + 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
);
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;
// });
}
}
}
}
}

@ -0,0 +1,178 @@
import 'dart:async';
import 'package:device_calendar_plus/device_calendar_plus.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:jiffy/jiffy.dart' show Jiffy;
class CalenderUtilsNew {
final DeviceCalendar calender = DeviceCalendar.instance;
List<Calendar> writableCalender = [];
CalenderUtilsNew._instance() {
getCalenders();
}
static final CalenderUtilsNew instance = CalenderUtilsNew._instance();
Future<void> getCalenders() async {
CalendarPermissionStatus result = await DeviceCalendar.instance.hasPermissions();
if (result != CalendarPermissionStatus.granted) await DeviceCalendar.instance.requestPermissions();
var calenders = await calender.listCalendars();
calenders.forEach((calender) {
if (!calender.readOnly) {
writableCalender.add(calender);
}
});
}
FutureOr<bool> createOrUpdateEvent({required String title, required String description, required String location, DateTime? scheduleDateTime, String? eventId, int? reminderMinutes}) async {
if (writableCalender.isEmpty) {
await getCalenders();
}
var writableCalendars = writableCalender.first;
String eventResult = "";
CalendarPermissionStatus result = await DeviceCalendar.instance.hasPermissions();
if (result != CalendarPermissionStatus.granted) await DeviceCalendar.instance.requestPermissions();
print(result);
// String eventId = await getEventIdIfEventExist(title!.split("#").last);
// if (eventId.isEmpty) {
eventResult = await DeviceCalendar.instance.createEvent(
calendarId: writableCalendars!.id,
title: title,
description: description,
startDate: scheduleDateTime!,
endDate: scheduleDateTime!.add(Duration(minutes: 30)),
reminderMinutes: reminderMinutes);
return eventResult.isNotEmpty;
// }
// await DeviceCalendar.instance.updateEvent(
// eventId: eventId,
// title: title,
// description: description,
// startDate: scheduleDateTime!,
// endDate: scheduleDateTime!.add(Duration(minutes: 30)),
// );
// return eventId.isNotEmpty;
}
FutureOr<bool> createMultipleEvents(
{required int reminderMinutes,
int? frequencyNumber,
required int days,
required String orderDate,
required String itemDescriptionN,
required String route,
Function(String)? onFailure,
String? prescriptionNumber}) async {
DateTime currentDay = DateTime.now();
DateTime actualDate = DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day, 8, 0);
print("the frequency is $frequencyNumber");
frequencyNumber ??= 2; //Some time frequency number is null so by default will be 2
int interval = calculateIntervalAsPerFrequency(frequencyNumber);
// int remainingDays = days - (Jiffy.parseFromDateTime(DateTime.now()).diff(Jiffy.parseFromDateTime(DateUtil.convertStringToDate(orderDate)), unit: Unit.day) as int);
Duration difference = (actualDate.difference(DateUtil.convertStringToDate(orderDate)));
int remainingDays = 5;
// if (remainingDays.isNegative) {
// onFailure?.call("Prescription date has been already passed you can not add a reminder for this prescription.");
// return false;
// }
bool statusOfOperation = false;
for (int i = 0; i < remainingDays; i++) {
//event for number of days.
for (int j = 0; j < frequencyNumber; j++) {
statusOfOperation = await createOrUpdateEvent(
title: "$itemDescriptionN} Medication about to due for prescription , #$prescriptionNumber",
description: "$itemDescriptionN $frequencyNumber $route ",
scheduleDateTime: actualDate,
location: '',
//event id with varitions
reminderMinutes: reminderMinutes);
if (!statusOfOperation) return false;
actualDate = actualDate.add(Duration(hours: interval));
// if (actualDate.difference(currentDay).inDays == 1) break;
}
// actualDate = actualDate.add(Duration(days: 1));
}
return statusOfOperation;
}
int calculateIntervalAsPerFrequency(int frequencyNumber) {
return 24 ~/ frequencyNumber;
}
FutureOr<List<Event>> getEvents() async {
var availableCalender = writableCalender.first;
DateTime startEventsDate = Jiffy.parseFromDateTime(DateTime.now()).subtract(days: 30).dateTime;
DateTime endEventsDate = Jiffy.parseFromDateTime(DateTime.now()).add(days: 120).dateTime;
return await calender.listEvents(startEventsDate, endEventsDate, calendarIds: [availableCalender.id]);
}
FutureOr<bool> checkIfEventExist(String admissionId) async {
if (writableCalender.isEmpty) {
await getCalenders();
}
List<Event> events = await getEvents();
if (events.isEmpty) return false;
for (var event in events) {
List<String> title = event.title!.split("#");
if (title.contains(admissionId)) return true;
}
return false;
}
FutureOr<String> getEventIdIfEventExist(String admissionId) async {
if (writableCalender.isEmpty) {
await getCalenders();
}
List<Event> events = await getEvents();
if (events.isEmpty) return "";
for (var event in events) {
List<String> title = event.title!.split("#");
if (title.contains(admissionId)) return event.eventId;
}
return "";
}
FutureOr<bool> checkAndRemove({required String id}) async {
if (writableCalender.isEmpty) {
await getCalenders();
}
List<Event> events = await getEvents();
if (events.isEmpty) return false;
for (var event in events) {
List<String> title = event.title!.split("#");
if (title.contains(id)) {
calender.deleteEvent(eventId: event.eventId);
return true;
}
}
return false;
}
FutureOr<bool> checkAndRemoveMultipleItems({required String id}) async {
if (writableCalender.isEmpty) {
await getCalenders();
}
List<Event> events = await getEvents();
if (events.isEmpty) return false;
bool statusOfOperation = false;
for (var event in events) {
List<String> title = event.title.split("#");
if (title.contains(id)) {
calender.deleteEvent(eventId: event.eventId);
statusOfOperation = true;
}
}
return statusOfOperation;
}
}

@ -17,8 +17,7 @@ class DateUtil {
final endIndex = date.indexOf(end, startIndex + start.length);
return DateTime.fromMillisecondsSinceEpoch(int.parse(
date.substring(startIndex + start.length, endIndex),
))
;
));
}
static DateTime convertStringToDateSaudiTimezone(String date, int projectId) {

@ -265,6 +265,12 @@ class AuthenticationRepoImp implements AuthenticationRepo {
newRequest.isDentalAllowedBackend = false;
newRequest.forRegisteration = newRequest.isRegister ?? false;
newRequest.isRegister = false;
//silent login case removed token and login token
if(newRequest.logInTokenID.isEmpty && newRequest.isSilentLogin == true) {
newRequest.logInTokenID = null;
newRequest.deviceToken = null;
}
}
Map<String, dynamic> familyRequest = {};

@ -8,12 +8,15 @@ import 'package:hmg_patient_app_new/features/location/GeocodeResponse.dart';
import 'package:hmg_patient_app_new/features/location/PlaceDetails.dart';
import 'package:hmg_patient_app_new/features/location/PlacePrediction.dart';
import 'package:hmg_patient_app_new/features/location/location_view_model.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/calender_utils_new.dart';
import 'package:hmg_patient_app_new/features/prescriptions/models/resp_models/patient_prescriptions_response_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/models/resp_models/prescription_delivery_response_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/models/resp_models/prescription_detail_response_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_repo.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_delivery_order_summary_page.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/widgets/map/map_utility_screen.dart';
@ -63,6 +66,11 @@ class PrescriptionsViewModel extends ChangeNotifier {
notifyListeners();
}
checkIfReminderExistForPrescription(int index) async {
prescriptionDetailsList[index].hasReminder = await CalenderUtilsNew.instance.checkIfEventExist(prescriptionDetailsList[index].itemID?.toString() ?? "");
}
setPrescriptionsDetailsLoading() {
isPrescriptionsDetailsLoading = true;
prescriptionDetailsList.clear();
@ -144,6 +152,9 @@ class PrescriptionsViewModel extends ChangeNotifier {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
prescriptionDetailsList = apiResponse.data!;
prescriptionDetailsList.forEach((element) async {
await checkIfReminderExistForPrescription(prescriptionDetailsList.indexOf(element));
});
isPrescriptionsDetailsLoading = false;
notifyListeners();
if (onSuccess != null) {
@ -197,6 +208,10 @@ class PrescriptionsViewModel extends ChangeNotifier {
);
}
showError(String errorMessage) {
getIt<DialogService>().showErrorBottomSheet(message: errorMessage);
}
Future<void> submitPrescriptionDeliveryRequest(
{required String latitude,
required String longitude,

@ -1,10 +1,15 @@
import 'dart:async';
import 'dart:collection';
import 'dart:io';
import 'package:device_calendar/device_calendar.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/utils/calender_utils_new.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
@ -62,10 +67,15 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
@override
void initState() {
scheduleMicrotask(() {
if (AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel)) {
scheduleMicrotask(() async {
CalenderUtilsNew calendarUtils = await CalenderUtilsNew.instance;
var doesExist = await calendarUtils.checkIfEventExist("${widget.patientAppointmentHistoryResponseModel.appointmentNo}");
print("the appointment reminder exist $doesExist");
myAppointmentsViewModel.setAppointmentReminder(doesExist, widget.patientAppointmentHistoryResponseModel);
setState((){
});
}
});
super.initState();
}
@ -133,6 +143,10 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
},
onCancelTap: () async {
myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true);
var isEventAddedOrRemoved = await CalenderUtilsNew.instance.checkAndRemove( id:"${widget.patientAppointmentHistoryResponseModel.appointmentNo}", );
setState(() {
myAppointmentsViewModel.setAppointmentReminder(isEventAddedOrRemoved, widget.patientAppointmentHistoryResponseModel);
});
LoaderBottomSheet.showLoader(loadingText: "Cancelling Appointment, Please Wait...".needTranslation);
await myAppointmentsViewModel.cancelAppointment(
patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel,
@ -271,11 +285,55 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
// activeThumbColor: AppColors.successColor,
activeTrackColor: AppColors.successColor.withValues(alpha: .15),
value: widget.patientAppointmentHistoryResponseModel.hasReminder!,
onChanged: (newValue) {
onChanged: (newValue) async {
CalenderUtilsNew calender = CalenderUtilsNew.instance;
bool isEventAddedOrRemoved = false;
if(newValue == true){
DateTime startDate = DateTime.now();
DateTime endDate = DateUtil.convertStringToDate(widget
.patientAppointmentHistoryResponseModel.appointmentDate);
BottomSheetUtils().showReminderBottomSheet(
context,
endDate,
widget.patientAppointmentHistoryResponseModel.doctorNameObj??"",
"${widget.patientAppointmentHistoryResponseModel.appointmentNo}"??"",
"",
"",
title: "Appointment with ${widget.patientAppointmentHistoryResponseModel.doctorNameObj}".needTranslation,
description:"${widget.patientAppointmentHistoryResponseModel.doctorNameObj} will be having an appointment on ${widget.patientAppointmentHistoryResponseModel.appointmentDate}".needTranslation,
onSuccess: () {
setState(() {
myAppointmentsViewModel.setAppointmentReminder(newValue, widget.patientAppointmentHistoryResponseModel);
});
},
isMultiAllowed: true,
onMultiDateSuccess: (int selectedIndex) async {
isEventAddedOrRemoved = await calender.createOrUpdateEvent(
title: "Appointment Reminder with ${widget.patientAppointmentHistoryResponseModel.doctorNameObj} on ${DateUtil.convertStringToDate(widget
.patientAppointmentHistoryResponseModel.appointmentDate)}, Appointment #${widget.patientAppointmentHistoryResponseModel.appointmentNo}".needTranslation,
description: "Appointment Reminder with ${widget.patientAppointmentHistoryResponseModel.doctorNameObj} in ${widget
.patientAppointmentHistoryResponseModel.projectName}",
scheduleDateTime: DateUtil.convertStringToDate(widget
.patientAppointmentHistoryResponseModel.appointmentDate),
eventId: "${widget.patientAppointmentHistoryResponseModel.appointmentNo}",
location: '',
reminderMinutes: selectedIndex
);
setState(() {
myAppointmentsViewModel.setAppointmentReminder(isEventAddedOrRemoved, widget.patientAppointmentHistoryResponseModel);
});
},
);
}else {
isEventAddedOrRemoved = await calender.checkAndRemove( id:"${widget.patientAppointmentHistoryResponseModel.appointmentNo}", );
setState(() {
myAppointmentsViewModel.setAppointmentReminder(!isEventAddedOrRemoved, widget.patientAppointmentHistoryResponseModel);
});
}
},
),
],
).paddingSymmetrical(16.h, 16.h),

@ -47,7 +47,9 @@ class _NewReferralPageState extends State<NewReferralPage> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
_loadData();
});
}
void _handleNextStep() {
@ -144,6 +146,9 @@ class _NewReferralPageState extends State<NewReferralPage> {
}
void _loadData() {
final authVM = context.read<AuthenticationViewModel>();
final habibWalletVM = context.read<HabibWalletViewModel>();
final hmgServicesVM = context.read<HmgServicesViewModel>();

@ -4,7 +4,6 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/utils/calendar_utils.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
@ -41,7 +40,6 @@ class _PrescriptionDetailPageState extends State<PrescriptionDetailPage> {
@override
void initState() {
checkAndRemove(false);
// locationUtils = new LocationUtils(isShowConfirmDialog: true, context: context);
// WidgetsBinding.instance.addPostFrameCallback((_) => locationUtils.getCurrentLocation());
if (!widget.isFromAppointments) {

@ -2,7 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/utils/calendar_utils.dart';
import 'package:hmg_patient_app_new/core/utils/calender_utils_new.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
@ -10,6 +10,8 @@ import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_mo
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
class PrescriptionItemView extends StatelessWidget {
int index;
@ -154,15 +156,20 @@ class PrescriptionItemView extends StatelessWidget {
activeTrackColor: AppColors.successColor.withValues(alpha: .15),
value: isLoading ? false : prescriptionVM.prescriptionDetailsList[index].hasReminder!,
onChanged: (newValue) async {
CalenderUtilsNew calender = CalenderUtilsNew.instance;
if (prescriptionVM.prescriptionDetailsList[index].hasReminder ?? false) {
await checkAndRemove(prescriptionVM.prescriptionDetailsList[index].hasReminder, delete: true);
prescriptionVM.notify();
LoaderBottomSheet.showLoader(loadingText: "Removing Reminders");
bool resultValue = await calender.checkAndRemoveMultipleItems(id:prescriptionVM.prescriptionDetailsList[index].itemID.toString());
prescriptionVM.setPrescriptionItemReminder(newValue, prescriptionVM.prescriptionDetailsList[index]);
LoaderBottomSheet.hideLoader();
return;
}
DateTime startDate = DateTime.now();
DateTime endDate = DateTime(startDate.year, startDate.month, startDate.day + prescriptionVM.prescriptionDetailsList[index].days!.toInt());
showReminderBottomSheet(
BottomSheetUtils().showReminderBottomSheet(
context,
endDate,
"",
@ -173,18 +180,29 @@ class PrescriptionItemView extends StatelessWidget {
description:
"${prescriptionVM.prescriptionDetailsList[index].itemDescription} ${prescriptionVM.prescriptionDetailsList[index].frequency} ${prescriptionVM.prescriptionDetailsList[index].route} ",
onSuccess: () {
prescriptionVM.setPrescriptionItemReminder(newValue, prescriptionVM.prescriptionDetailsList[index]);
},
isMultiAllowed: true,
onMultiDateSuccess: (int selectedIndex) {
setCalender(context,
eventId: prescriptionVM.prescriptionDetailsList[index].itemID.toString(),
selectedMinutes: selectedIndex,
onMultiDateSuccess: (int selectedIndex) async{
bool isEventAdded = await calender.createMultipleEvents(
reminderMinutes: selectedIndex,
frequencyNumber: prescriptionVM.prescriptionDetailsList[index].frequencyNumber?.toInt(),
days: prescriptionVM.prescriptionDetailsList[index].days!.toInt(),
orderDate: prescriptionVM.prescriptionDetailsList[index].orderDate!,
itemDescriptionN: prescriptionVM.prescriptionDetailsList[index].itemDescription!,
route: prescriptionVM.prescriptionDetailsList[index].route!);
route: prescriptionVM.prescriptionDetailsList[index].route!,
onFailure: (errorMessage)=> prescriptionVM.showError(errorMessage),
prescriptionNumber: prescriptionVM.prescriptionDetailsList[index].itemID.toString(),
);
prescriptionVM.setPrescriptionItemReminder(isEventAdded, prescriptionVM.prescriptionDetailsList[index]);
// setCalender(context,
// eventId: prescriptionVM.prescriptionDetailsList[index].itemID.toString(),
// selectedMinutes: selectedIndex,
// frequencyNumber: prescriptionVM.prescriptionDetailsList[index].frequencyNumber?.toInt(),
// days: prescriptionVM.prescriptionDetailsList[index].days!.toInt(),
// orderDate: prescriptionVM.prescriptionDetailsList[index].orderDate!,
// itemDescriptionN: prescriptionVM.prescriptionDetailsList[index].itemDescription!,
// route: prescriptionVM.prescriptionDetailsList[index].route!);
},
);
},

@ -100,7 +100,7 @@ class _PrescriptionReminderViewState extends State<PrescriptionReminderView> {
text: LocaleKeys.setReminder.tr(),
onPressed: () {
Navigator.of(context).pop();
widget.setReminder(_selectedOption);
widget.setReminder(_options[_selectedOption]);
},
backgroundColor: AppColors.bgGreenColor,
borderColor: AppColors.bgGreenColor,

@ -1,11 +1,65 @@
import 'dart:io' show Platform;
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/utils/calender_utils_new.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_reminder_view.dart';
import 'package:hmg_patient_app_new/services/permission_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:permission_handler/permission_handler.dart';
class BottomSheetUtils{
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".needTranslation, child: PrescriptionReminderView(
setReminder: (int value) async {
if (!isMultiAllowed!) {
if (onMultiDateSuccess == null) {
CalenderUtilsNew calendarUtils = CalenderUtilsNew.instance;
await calendarUtils.createOrUpdateEvent(
title: title ?? "You have appointment with Dr. ".needTranslation + doctorName,
description: description ?? "At " + appoDateFormatted + " " + appoTimeFormatted,
scheduleDateTime: dateTime,
eventId: eventId,
location: '');
onSuccess();
}
} else {
onMultiDateSuccess!(value);
}
},
), callBackFunc: () {}, isFullScreen: false);
}
}
void showCommonBottomSheet(BuildContext context,
{required Widget child,
Function(String?)? callBackFunc,

@ -45,6 +45,7 @@ dependencies:
file_picker: ^10.3.2
local_auth: ^2.3.0
share_plus: ^11.1.0
device_calendar_plus: ^0.3.1
device_calendar:
git: https://github.com/bardram/device_calendar
manage_calendar_events: ^2.0.3

Loading…
Cancel
Save