189 lines
6.4 KiB
Dart
189 lines
6.4 KiB
Dart
import '../../../../core/network/api_client.dart';
|
|
import '../models/dashboard_metrics_model.dart';
|
|
import '../models/doctor_info_model.dart';
|
|
import '../models/patient_summary_model.dart';
|
|
|
|
class DashboardService {
|
|
final ApiClient apiClient;
|
|
|
|
DashboardService({ApiClient? client}) : apiClient = client ?? ApiClient();
|
|
|
|
String _formatTwoDigits(int n) => n.toString().padLeft(2, '0');
|
|
|
|
Future<DoctorInfoModel> getDoctorConfig() async {
|
|
try {
|
|
final response = await apiClient.dio.get('/items/configuracion');
|
|
if (response.statusCode == 200 && response.data != null) {
|
|
final data = response.data['data'] as Map<String, dynamic>;
|
|
return DoctorInfoModel.fromJson(data);
|
|
}
|
|
return const DoctorInfoModel(
|
|
nombreDoctor: 'Dr. Luis A. Castro Sosa',
|
|
especialidad: 'Cirujano Urólogo',
|
|
descripEspecialidad: '',
|
|
descripGeneral: '',
|
|
);
|
|
} catch (_) {
|
|
return const DoctorInfoModel(
|
|
nombreDoctor: 'Dr. Luis A. Castro Sosa',
|
|
especialidad: 'Cirujano Urólogo',
|
|
descripEspecialidad: '',
|
|
descripGeneral: '',
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<DashboardMetricsModel> getDashboardMetrics() async {
|
|
try {
|
|
final now = DateTime.now();
|
|
final day = _formatTwoDigits(now.day);
|
|
final month = _formatTwoDigits(now.month);
|
|
final year = now.year.toString();
|
|
final dmy = '$day/$month/$year';
|
|
final iso = '$year-$month-$day';
|
|
|
|
// Consultas concurrentes optimizadas a Directus
|
|
final results = await Future.wait([
|
|
// 0: Desglose por sexo
|
|
apiClient.dio.get('/items/pacientes?aggregate[count]=*&groupBy[]=sexo'),
|
|
|
|
// 1: Citas para hoy (condición estricta: fec_proxcita igual a la fecha del día actual)
|
|
apiClient.dio.get(
|
|
'/items/pacientes?aggregate[count]=*&filter[_or][0][fec_proxcita][_eq]=$dmy&filter[_or][1][fec_proxcita][_starts_with]=$dmy&filter[_or][2][fec_proxcita][_starts_with]=$iso',
|
|
),
|
|
|
|
// 2: Pacientes nuevos registrados hoy
|
|
apiClient.dio.get(
|
|
'/items/pacientes?aggregate[count]=*&filter[_or][0][fec_reg][_contains]=$dmy&filter[_or][1][fec_reg][_contains]=$iso',
|
|
),
|
|
|
|
// 3: Pacientes consultados hoy
|
|
apiClient.dio.get(
|
|
'/items/pacientes?aggregate[count]=*&filter[_or][0][fec_ultcon][_contains]=$dmy&filter[_or][1][fec_ultcon][_contains]=$iso',
|
|
),
|
|
|
|
// 4: Total de pacientes
|
|
apiClient.dio.get('/items/pacientes?aggregate[count]=*'),
|
|
]);
|
|
|
|
int masc = 11078;
|
|
int fem = 2634;
|
|
int citasHoy = 0;
|
|
int nuevosHoy = 0;
|
|
int consultadosHoy = 0;
|
|
int total = 13712;
|
|
|
|
// 0. Desglose por sexo
|
|
if (results[0].statusCode == 200 && results[0].data != null) {
|
|
final sexoData = results[0].data['data'] as List<dynamic>? ?? [];
|
|
for (final item in sexoData) {
|
|
final s = item['sexo']?.toString().toLowerCase() ?? '';
|
|
final count = int.tryParse(item['count'].toString()) ?? 0;
|
|
if (s.contains('masc')) masc = count;
|
|
if (s.contains('fem')) fem = count;
|
|
}
|
|
}
|
|
|
|
// 1. Citas para hoy
|
|
if (results[1].statusCode == 200 && results[1].data != null) {
|
|
final data = results[1].data['data'] as List<dynamic>? ?? [];
|
|
if (data.isNotEmpty) {
|
|
citasHoy = int.tryParse(data[0]['count'].toString()) ?? 0;
|
|
}
|
|
}
|
|
|
|
// 2. Nuevos hoy
|
|
if (results[2].statusCode == 200 && results[2].data != null) {
|
|
final data = results[2].data['data'] as List<dynamic>? ?? [];
|
|
if (data.isNotEmpty) {
|
|
nuevosHoy = int.tryParse(data[0]['count'].toString()) ?? 0;
|
|
}
|
|
}
|
|
|
|
// 3. Consultados hoy
|
|
if (results[3].statusCode == 200 && results[3].data != null) {
|
|
final data = results[3].data['data'] as List<dynamic>? ?? [];
|
|
if (data.isNotEmpty) {
|
|
consultadosHoy = int.tryParse(data[0]['count'].toString()) ?? 0;
|
|
}
|
|
}
|
|
|
|
// 4. Total pacientes
|
|
if (results[4].statusCode == 200 && results[4].data != null) {
|
|
final data = results[4].data['data'] as List<dynamic>? ?? [];
|
|
if (data.isNotEmpty) {
|
|
total = int.tryParse(data[0]['count'].toString()) ?? 13712;
|
|
}
|
|
}
|
|
|
|
return DashboardMetricsModel(
|
|
nuevosPacientes: nuevosHoy,
|
|
consultadosHoy: consultadosHoy,
|
|
citasHoy: citasHoy,
|
|
pacientesMasculinos: masc,
|
|
pacientesFemeninos: fem,
|
|
totalPacientes: total,
|
|
);
|
|
} catch (_) {
|
|
return const DashboardMetricsModel();
|
|
}
|
|
}
|
|
|
|
Future<List<PatientSummaryModel>> getRecentPatients({int limit = 5}) async {
|
|
try {
|
|
final response = await apiClient.dio.get(
|
|
'/items/pacientes?sort=-id&limit=$limit&fields=id,nombre,apellido,cedula,telefono,fec_reg,fec_proxcita,seguro,mot_cons,estado_espera',
|
|
);
|
|
if (response.statusCode == 200 && response.data != null) {
|
|
final data = response.data['data'] as List<dynamic>? ?? [];
|
|
return data
|
|
.map((item) => PatientSummaryModel.fromJson(item as Map<String, dynamic>))
|
|
.toList();
|
|
}
|
|
return [];
|
|
} catch (_) {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
Future<List<PatientSummaryModel>> getAppointmentsByDate(DateTime date, {int limit = 100}) async {
|
|
try {
|
|
final day = _formatTwoDigits(date.day);
|
|
final month = _formatTwoDigits(date.month);
|
|
final year = date.year.toString();
|
|
final dmy = '$day/$month/$year';
|
|
final iso = '$year-$month-$day';
|
|
|
|
final response = await apiClient.dio.get(
|
|
'/items/pacientes?filter[_or][0][fec_proxcita][_eq]=$dmy&filter[_or][1][fec_proxcita][_starts_with]=$dmy&filter[_or][2][fec_proxcita][_starts_with]=$iso&sort=-id&limit=$limit&fields=id,nombre,apellido,cedula,telefono,fec_proxcita,mot_cons,estado_espera',
|
|
);
|
|
|
|
final data = response.data?['data'] as List<dynamic>? ?? [];
|
|
|
|
return data
|
|
.map((item) => PatientSummaryModel.fromJson(item as Map<String, dynamic>))
|
|
.toList();
|
|
} catch (_) {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
Future<List<PatientSummaryModel>> getTodayAppointments({int limit = 50}) async {
|
|
return getAppointmentsByDate(DateTime.now(), limit: limit);
|
|
}
|
|
|
|
Future<bool> updatePatientWaitingStatus(int patientId, String nuevoEstado) async {
|
|
try {
|
|
final response = await apiClient.dio.patch(
|
|
'/items/pacientes/$patientId',
|
|
data: {'estado_espera': nuevoEstado},
|
|
);
|
|
return response.statusCode == 200;
|
|
} catch (_) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
|