|
|
|
@ -5,36 +5,24 @@ import 'package:hmg_patient_app_new/features/active_prescriptions/active_prescri
|
|
|
|
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
|
|
|
|
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
|
|
|
|
|
|
|
|
|
|
|
|
class ActivePrescriptionsViewModel extends ChangeNotifier {
|
|
|
|
class ActivePrescriptionsViewModel extends ChangeNotifier {
|
|
|
|
bool isActivePrescriptionsDetailsLoading = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
late ActivePrescriptionsRepo activePrescriptionsRepo;
|
|
|
|
late ActivePrescriptionsRepo activePrescriptionsRepo;
|
|
|
|
late ErrorHandlerService errorHandlerService;
|
|
|
|
late ErrorHandlerService errorHandlerService;
|
|
|
|
|
|
|
|
List<ActivePrescriptionsResponseModel> activePrescriptionsDetailsList = [];
|
|
|
|
|
|
|
|
|
|
|
|
ActivePrescriptionsViewModel({
|
|
|
|
ActivePrescriptionsViewModel({
|
|
|
|
required this.activePrescriptionsRepo,
|
|
|
|
required this.activePrescriptionsRepo,
|
|
|
|
required this.errorHandlerService,
|
|
|
|
required this.errorHandlerService,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
List<ActivePrescriptionsResponseModel> activePrescriptionsDetailsList = [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
initActivePrescriptionsViewModel() {
|
|
|
|
|
|
|
|
getActiveMedications();
|
|
|
|
|
|
|
|
notifyListeners();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setPrescriptionsDetailsLoading() {
|
|
|
|
|
|
|
|
isActivePrescriptionsDetailsLoading = true;
|
|
|
|
|
|
|
|
notifyListeners();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Get medications list
|
|
|
|
|
|
|
|
Future<void> getActiveMedications({
|
|
|
|
Future<void> getActiveMedications({
|
|
|
|
Function(dynamic)? onSuccess,
|
|
|
|
Function(dynamic)? onSuccess,
|
|
|
|
Function(String)? onError,
|
|
|
|
Function(String)? onError,
|
|
|
|
}) async {
|
|
|
|
}) async {
|
|
|
|
final result = await activePrescriptionsRepo.getActivePrescriptionsDetails();
|
|
|
|
final result =
|
|
|
|
|
|
|
|
await activePrescriptionsRepo.getActivePrescriptionsDetails();
|
|
|
|
result.fold(
|
|
|
|
result.fold(
|
|
|
|
(failure) async => await errorHandlerService.handleError(failure: failure),
|
|
|
|
(failure) async =>
|
|
|
|
|
|
|
|
await errorHandlerService.handleError(failure: failure),
|
|
|
|
(apiResponse) {
|
|
|
|
(apiResponse) {
|
|
|
|
if (apiResponse.messageStatus == 1) {
|
|
|
|
if (apiResponse.messageStatus == 1) {
|
|
|
|
activePrescriptionsDetailsList = apiResponse.data ?? [];
|
|
|
|
activePrescriptionsDetailsList = apiResponse.data ?? [];
|
|
|
|
@ -56,140 +44,58 @@ class ActivePrescriptionsViewModel extends ChangeNotifier {
|
|
|
|
return DateTime.tryParse(date) ?? DateTime.now();
|
|
|
|
return DateTime.tryParse(date) ?? DateTime.now();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Extract numeric value ( "3 / week" → 3)
|
|
|
|
|
|
|
|
int extractNumberFromFrequency(String? frequency) {
|
|
|
|
|
|
|
|
if (frequency == null) return 1;
|
|
|
|
|
|
|
|
final m = RegExp(r'(\d+)').firstMatch(frequency);
|
|
|
|
|
|
|
|
if (m != null) return int.tryParse(m.group(1)!) ?? 1;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Generate medication days based on frequency text
|
|
|
|
|
|
|
|
List<DateTime> generateMedicationDays(ActivePrescriptionsResponseModel med) {
|
|
|
|
List<DateTime> generateMedicationDays(ActivePrescriptionsResponseModel med) {
|
|
|
|
final start = parseDate(med.startDate);
|
|
|
|
final start = parseDate(med.startDate);
|
|
|
|
final duration = med.days ?? 0;
|
|
|
|
final duration = med.days ?? 0;
|
|
|
|
final frequency = (med.frequency ?? "").toLowerCase().trim();
|
|
|
|
if (duration <= 0) return [];
|
|
|
|
|
|
|
|
final f = (med.frequency ?? "").toLowerCase().trim();
|
|
|
|
List<DateTime> result = [];
|
|
|
|
int intervalDays = 1;
|
|
|
|
if (duration <= 0) return result;
|
|
|
|
|
|
|
|
|
|
|
|
if (f.contains("every six hours") ||
|
|
|
|
// Every N hours ( "Every Six Hours", "Every 8 hours")
|
|
|
|
f.contains("every 6 hours") ||
|
|
|
|
if (frequency.contains("hour")) {
|
|
|
|
f.contains("every four hours") ||
|
|
|
|
final match = RegExp(r'every\s+(\d+)').firstMatch(frequency);
|
|
|
|
f.contains("every 4 hours") ||
|
|
|
|
int intervalHours = 0;
|
|
|
|
f.contains("every eight hours") ||
|
|
|
|
|
|
|
|
f.contains("every 8 hours") ||
|
|
|
|
if (match != null) {
|
|
|
|
f.contains("every 12 hours") ||
|
|
|
|
intervalHours = int.tryParse(match.group(1)!) ?? 0;
|
|
|
|
f.contains("every twelve hours") ||
|
|
|
|
} else {
|
|
|
|
f.contains("every 24 hours") ||
|
|
|
|
// handle text numbers like "Every six hours"
|
|
|
|
f.contains("3 times a day") ||
|
|
|
|
final textNum = {
|
|
|
|
f.contains("once a day")) {
|
|
|
|
"one": 1,
|
|
|
|
intervalDays = 1;
|
|
|
|
"two": 2,
|
|
|
|
|
|
|
|
"three": 3,
|
|
|
|
|
|
|
|
"four": 4,
|
|
|
|
|
|
|
|
"five": 5,
|
|
|
|
|
|
|
|
"six": 6,
|
|
|
|
|
|
|
|
"seven": 7,
|
|
|
|
|
|
|
|
"eight": 8,
|
|
|
|
|
|
|
|
"nine": 9,
|
|
|
|
|
|
|
|
"ten": 10,
|
|
|
|
|
|
|
|
"twelve": 12,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
for (var key in textNum.keys) {
|
|
|
|
|
|
|
|
if (frequency.contains(key)) {
|
|
|
|
|
|
|
|
intervalHours = textNum[key]!;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (intervalHours > 0) {
|
|
|
|
|
|
|
|
for (int day = 0; day < duration; day++) {
|
|
|
|
|
|
|
|
final dayStart = start.add(Duration(days: day));
|
|
|
|
|
|
|
|
for (int hour = 0; hour < 24; hour += intervalHours) {
|
|
|
|
|
|
|
|
result.add(DateTime(dayStart.year, dayStart.month, dayStart.day, hour));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Daily (every day)
|
|
|
|
|
|
|
|
if (frequency.contains("day") &&
|
|
|
|
|
|
|
|
!frequency.contains("every other") &&
|
|
|
|
|
|
|
|
!frequency.contains("every ")) {
|
|
|
|
|
|
|
|
for (int i = 0; i < duration; i++) {
|
|
|
|
|
|
|
|
result.add(start.add(Duration(days: i)));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Every other day
|
|
|
|
|
|
|
|
else if (frequency.contains("every other day")) {
|
|
|
|
|
|
|
|
for (int i = 0; i < duration; i += 2) {
|
|
|
|
|
|
|
|
result.add(start.add(Duration(days: i)));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (f.contains("once a week")) {
|
|
|
|
// Every N days → e.g. "Every 3 days", "Every 5 days"
|
|
|
|
intervalDays = 7;
|
|
|
|
else if (frequency.contains("every") && frequency.contains("day")) {
|
|
|
|
|
|
|
|
final match = RegExp(r'every\s+(\d+)').firstMatch(frequency);
|
|
|
|
|
|
|
|
final interval = match != null ? int.tryParse(match.group(1)!) ?? 1 : 1;
|
|
|
|
|
|
|
|
for (int i = 0; i < duration; i += interval) {
|
|
|
|
|
|
|
|
result.add(start.add(Duration(days: i)));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (f.contains("every 3 days")) {
|
|
|
|
// Once or twice a week
|
|
|
|
intervalDays = 3;
|
|
|
|
else if (frequency.contains("once a week")) {
|
|
|
|
|
|
|
|
for (int i = 0; i < duration; i += 7) {
|
|
|
|
|
|
|
|
result.add(start.add(Duration(days: i)));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (frequency.contains("twice a week")) {
|
|
|
|
|
|
|
|
for (int i = 0; i < duration; i += 3) {
|
|
|
|
|
|
|
|
result.add(start.add(Duration(days: i)));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (f.contains("every other day")) {
|
|
|
|
// Numeric frequency like "3 / week", "2 / week"
|
|
|
|
intervalDays = 2;
|
|
|
|
else if (frequency.contains("week")) {
|
|
|
|
|
|
|
|
int timesPerWeek = extractNumberFromFrequency(frequency);
|
|
|
|
|
|
|
|
double interval = 7 / timesPerWeek;
|
|
|
|
|
|
|
|
double dayPointer = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < duration; i++) {
|
|
|
|
|
|
|
|
if (i >= dayPointer.floor()) {
|
|
|
|
|
|
|
|
result.add(start.add(Duration(days: i)));
|
|
|
|
|
|
|
|
dayPointer += interval;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
else {
|
|
|
|
List<DateTime> result = [];
|
|
|
|
result.add(start);
|
|
|
|
for (int offset = 0; offset < duration; offset += intervalDays) {
|
|
|
|
}
|
|
|
|
result.add(start.add(Duration(days: offset)));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
final unique = <String, DateTime>{};
|
|
|
|
|
|
|
|
for (final d in result) {
|
|
|
|
|
|
|
|
unique["${d.year}-${d.month}-${d.day}"] = d;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return unique.values.toList()..sort((a, b) => a.compareTo(b));
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool sameYMD(DateTime a, DateTime b) =>
|
|
|
|
bool sameYMD(DateTime a, DateTime b) =>
|
|
|
|
a.year == b.year && a.month == b.month && a.day == b.day;
|
|
|
|
a.year == b.year && a.month == b.month && a.day == b.day;
|
|
|
|
|
|
|
|
|
|
|
|
// Filter medications for selected day
|
|
|
|
List<ActivePrescriptionsResponseModel> getMedsForSelectedDay(
|
|
|
|
List<ActivePrescriptionsResponseModel> getMedsForSelectedDay(DateTime selectedDate) {
|
|
|
|
DateTime selectedDate) {
|
|
|
|
final target = DateTime(selectedDate.year, selectedDate.month, selectedDate.day);
|
|
|
|
final clean = DateTime(selectedDate.year, selectedDate.month, selectedDate.day);
|
|
|
|
|
|
|
|
|
|
|
|
return activePrescriptionsDetailsList.where((med) {
|
|
|
|
return activePrescriptionsDetailsList.where((med) {
|
|
|
|
final days = generateMedicationDays(med);
|
|
|
|
final days = generateMedicationDays(med);
|
|
|
|
return days.any((d) => sameYMD(d, target));
|
|
|
|
return days.any((d) => sameYMD(d, clean));
|
|
|
|
}).toList();
|
|
|
|
}).toList();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|