feat: agregar SyncService y mejorar gestión de asistencia con nuevas funcionalidades

This commit is contained in:
Nurfog committed 2026-08-20 10:45:53 -04:00
1 parent fb275508ee
commit d953afd3b4
15 files changed
+339 -359

No files matched your search

+69 -103
View File
@@ -11,100 +11,112 @@ public partial class AsistenciaViewModel : ViewModelBase
private readonly AsistenciaService _asistenciaService;
private readonly AuthService _authService;
private readonly MainWindowViewModel _mainVm;
private readonly CursoAbierto _curso;
[ObservableProperty]
private string _nombreCurso = string.Empty;
[ObservableProperty]
private string _infoCurso = string.Empty;
private string _inputCursoAbierto = string.Empty;
[ObservableProperty]
private bool _enSesion;
[ObservableProperty]
private int _totalAlumnos;
[ObservableProperty]
private int _presentes;
[ObservableProperty]
private int _tardanzas;
[ObservableProperty]
private int _ausentes;
private string _inputRutAlumno = string.Empty;
[ObservableProperty]
private string _mensajeEstado = string.Empty;
public ObservableCollection<AlumnoAsistenciaViewModel> Alumnos { get; } = new();
[ObservableProperty]
private string _mensajeError = string.Empty;
public AsistenciaViewModel(AsistenciaService asistenciaService, AuthService authService, CursoAbierto curso, MainWindowViewModel mainVm)
[ObservableProperty]
private bool _hasError;
public ObservableCollection<AlumnoPresenteViewModel> AlumnosPresentes { get; } = new();
private int _idCursoAbierto;
public AsistenciaViewModel(AsistenciaService asistenciaService, AuthService authService, MainWindowViewModel mainVm)
{
_asistenciaService = asistenciaService;
_authService = authService;
_mainVm = mainVm;
_curso = curso;
NombreCurso = curso.Curso?.NombreCurso ?? "Curso";
InfoCurso = $"{curso.Sala} | {curso.Sede} | {curso.HoraInicio} - {curso.HoraFin}";
_ = InitAsync();
}
private async Task InitAsync()
{
var sesion = await _asistenciaService.BuscarSesionActivaAsync(_curso.IdCursoAbierto);
EnSesion = sesion != null;
var alumnos = await _asistenciaService.ObtenerAlumnosAsync(_curso.IdCursoAbierto);
var asistencias = await _asistenciaService.ObtenerAsistenciaAlumnosAsync(_curso.IdCursoAbierto);
Alumnos.Clear();
foreach (var alumno in alumnos)
{
var tipo = asistencias.TryGetValue(alumno.IdDetalleContrato, out var t) ? t : TipoAsistencia.Ausente;
Alumnos.Add(new AlumnoAsistenciaViewModel(alumno, tipo));
}
TotalAlumnos = Alumnos.Count;
ActualizarContadores();
MensajeEstado = EnSesion
? "Sesion en curso - Puede registrar asistencia"
: "Inicie la sesion para registrar asistencia";
}
[RelayCommand]
private async Task IniciarSesionAsync()
{
HasError = false;
if (!int.TryParse(InputCursoAbierto, out var idCurso))
{
MensajeError = "Ingrese un ID de curso valido";
HasError = true;
return;
}
if (_authService.CurrentUser == null) return;
await _asistenciaService.IniciarSesionAsync(_curso.IdCursoAbierto, _authService.CurrentUser.RutPasaporte);
_idCursoAbierto = idCurso;
await _asistenciaService.IniciarSesionAsync(idCurso, _authService.CurrentUser.RutPasaporte, _authService.TipoAsignacionActual);
EnSesion = true;
MensajeEstado = "Sesion iniciada - Registre la asistencia de los alumnos";
MensajeEstado = $"Sesion curso {idCurso} — Ingrese RUT de alumnos presentes";
}
[RelayCommand]
private async Task FinalizarSesionAsync()
{
var sesion = await _asistenciaService.BuscarSesionActivaAsync(_curso.IdCursoAbierto);
var sesion = await _asistenciaService.BuscarSesionActivaAsync(_idCursoAbierto);
if (sesion != null)
{
await _asistenciaService.FinalizarSesionAsync(sesion.IdAsistenciaProfesor);
}
EnSesion = false;
AlumnosPresentes.Clear();
InputCursoAbierto = string.Empty;
InputRutAlumno = string.Empty;
MensajeEstado = "Sesion finalizada";
}
[RelayCommand]
private async Task MarcarAlumnoAsync(AlumnoAsistenciaViewModel? alumno)
private async Task AgregarAlumnoAsync()
{
if (alumno == null || !EnSesion) return;
if (!EnSesion) return;
alumno.CiclarTipoAsistencia();
await _asistenciaService.GuardarAsistenciaAlumnoAsync(alumno.IdDetalleContrato, alumno.TipoAsistencia);
ActualizarContadores();
HasError = false;
var rut = InputRutAlumno.Trim();
if (string.IsNullOrWhiteSpace(rut))
{
MensajeError = "Ingrese el RUT del alumno";
HasError = true;
return;
}
if (AlumnosPresentes.Any(a => a.IdAlumno == rut))
{
MensajeError = "Este RUT ya fue registrado";
HasError = true;
InputRutAlumno = string.Empty;
return;
}
var alumno = await _asistenciaService.BuscarAlumnoPorRutAsync(_idCursoAbierto, rut);
if (alumno == null)
{
MensajeError = $"RUT {rut} no encontrado en el curso";
HasError = true;
InputRutAlumno = string.Empty;
return;
}
await _asistenciaService.GuardarAsistenciaAlumnoAsync(alumno.IdDetalleContrato, TipoAsistencia.Presente);
AlumnosPresentes.Add(new AlumnoPresenteViewModel
{
IdAlumno = rut,
NombreCompleto = alumno.NombreCompleto
});
InputRutAlumno = string.Empty;
}
[RelayCommand]
@@ -112,56 +124,10 @@ public partial class AsistenciaViewModel : ViewModelBase
{
_mainVm.NavigateToDashboard();
}
private void ActualizarContadores()
{
Presentes = Alumnos.Count(a => a.TipoAsistencia == Models.TipoAsistencia.Presente);
Tardanzas = Alumnos.Count(a => a.TipoAsistencia == Models.TipoAsistencia.Tardanza);
Ausentes = Alumnos.Count(a => a.TipoAsistencia == Models.TipoAsistencia.Ausente);
}
}
public partial class AlumnoAsistenciaViewModel : ViewModelBase
public class AlumnoPresenteViewModel
{
public int IdDetalleContrato { get; }
public string NombreCompleto { get; }
[ObservableProperty]
private int _tipoAsistencia;
[ObservableProperty]
private string _tipoAsistenciaTexto;
[ObservableProperty]
private string _tipoAsistenciaColor;
public AlumnoAsistenciaViewModel(DetalleContrato alumno, int tipoInicial)
{
IdDetalleContrato = alumno.IdDetalleContrato;
NombreCompleto = alumno.NombreCompleto;
TipoAsistencia = tipoInicial;
ActualizarDisplay();
}
public void CiclarTipoAsistencia()
{
TipoAsistencia = TipoAsistencia switch
{
Models.TipoAsistencia.Presente => Models.TipoAsistencia.Tardanza,
Models.TipoAsistencia.Tardanza => Models.TipoAsistencia.Ausente,
_ => Models.TipoAsistencia.Presente
};
ActualizarDisplay();
}
private void ActualizarDisplay()
{
TipoAsistenciaTexto = Models.TipoAsistencia.Nombre(TipoAsistencia);
TipoAsistenciaColor = TipoAsistencia switch
{
Models.TipoAsistencia.Presente => "#28A745",
Models.TipoAsistencia.Tardanza => "#FFC107",
_ => "#DC3545"
};
}
public string IdAlumno { get; set; } = string.Empty;
public string NombreCompleto { get; set; } = string.Empty;
}
+29 -15
View File
@@ -10,40 +10,54 @@ public partial class DashboardViewModel : ViewModelBase
{
private readonly AuthService _authService;
private readonly AsistenciaService _asistenciaService;
private readonly SyncService _syncService;
private readonly MainWindowViewModel _mainVm;
[ObservableProperty]
private string _nombreProfesor = string.Empty;
[ObservableProperty]
private int _totalCursos;
private string _tipoAsignacion = string.Empty;
public ObservableCollection<CursoAbierto> Cursos { get; } = new();
[ObservableProperty]
private int _pendientes;
public DashboardViewModel(AuthService authService, AsistenciaService asistenciaService, MainWindowViewModel mainVm)
[ObservableProperty]
private string _mensajeSync = string.Empty;
[ObservableProperty]
private bool _hasMensajeSync;
public DashboardViewModel(AuthService authService, AsistenciaService asistenciaService, SyncService syncService, MainWindowViewModel mainVm)
{
_authService = authService;
_asistenciaService = asistenciaService;
_syncService = syncService;
_mainVm = mainVm;
NombreProfesor = authService.CurrentUser?.Nombre ?? "";
_ = LoadCursosAsync();
NombreProfesor = authService.CurrentUser?.NombreCompleto ?? "";
TipoAsignacion = authService.TipoAsignacionActual == 1 ? "Titular" : "Reemplazo";
_ = CargarPendientesAsync();
}
private async Task LoadCursosAsync()
private async Task CargarPendientesAsync()
{
if (_authService.CurrentUser == null) return;
var cursos = await _asistenciaService.ObtenerCursosProfesorAsync(_authService.CurrentUser.RutPasaporte);
Cursos.Clear();
foreach (var c in cursos) Cursos.Add(c);
TotalCursos = Cursos.Count;
Pendientes = await _syncService.ContarPendientesAsync();
}
[RelayCommand]
private void AbrirAsistencia(CursoAbierto? curso)
private void AbrirAsistencia()
{
if (curso != null)
_mainVm.NavigateToAsistencia(curso);
_mainVm.NavigateToAsistencia();
}
[RelayCommand]
private async Task SincronizarAsync()
{
HasMensajeSync = false;
var (success, message) = await _syncService.SincronizarAsync("http://localhost:5000");
MensajeSync = message;
HasMensajeSync = true;
await CargarPendientesAsync();
}
[RelayCommand]
+16 -2
View File
@@ -13,7 +13,10 @@ public partial class LoginViewModel : ViewModelBase
private string _rut = string.Empty;
[ObservableProperty]
private string _password = string.Empty;
private bool _esTitular = true;
[ObservableProperty]
private bool _esReemplazo;
[ObservableProperty]
private string _errorMessage = string.Empty;
@@ -30,13 +33,24 @@ public partial class LoginViewModel : ViewModelBase
_mainVm = mainVm;
}
partial void OnEsTitularChanged(bool value)
{
if (value) EsReemplazo = false;
}
partial void OnEsReemplazoChanged(bool value)
{
if (value) EsTitular = false;
}
[RelayCommand]
private async Task LoginAsync()
{
IsLoading = true;
HasError = false;
var (success, message) = await _authService.LoginAsync(Rut, Password);
var tipoAsignacion = EsTitular ? 1 : 4;
var (success, message) = await _authService.LoginAsync(Rut, tipoAsignacion);
if (success)
{
+6 -4
View File
@@ -13,6 +13,7 @@ public partial class MainWindowViewModel : ViewModelBase
private readonly AuthService _authService;
private readonly AsistenciaService _asistenciaService;
private readonly ConnectivityService _connectivityService;
private readonly SyncService _syncService;
private object? _currentView;
[ObservableProperty]
@@ -30,11 +31,12 @@ public partial class MainWindowViewModel : ViewModelBase
set => SetProperty(ref _currentView, value);
}
public MainWindowViewModel(AuthService authService, AsistenciaService asistenciaService, ConnectivityService connectivityService)
public MainWindowViewModel(AuthService authService, AsistenciaService asistenciaService, ConnectivityService connectivityService, SyncService syncService)
{
_authService = authService;
_asistenciaService = asistenciaService;
_connectivityService = connectivityService;
_syncService = syncService;
_ = VerificarConexionAsync();
}
@@ -64,13 +66,13 @@ public partial class MainWindowViewModel : ViewModelBase
public void NavigateToDashboard()
{
CurrentViewTitle = "Panel Principal";
CurrentView = new DashboardViewModel(_authService, _asistenciaService, this);
CurrentView = new DashboardViewModel(_authService, _asistenciaService, _syncService, this);
}
public void NavigateToAsistencia(CursoAbierto curso)
public void NavigateToAsistencia()
{
CurrentViewTitle = "Asistencia";
CurrentView = new AsistenciaViewModel(_asistenciaService, _authService, curso, this);
CurrentView = new AsistenciaViewModel(_asistenciaService, _authService, this);
}
public void NavigateToPerfil()