Compare commits
1
Commits
fb275508ee
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d953afd3b4 |
No files matched your search
@@ -30,6 +30,7 @@ public partial class App : Application
|
|||||||
services.AddSingleton<AuthService>();
|
services.AddSingleton<AuthService>();
|
||||||
services.AddSingleton<AsistenciaService>();
|
services.AddSingleton<AsistenciaService>();
|
||||||
services.AddSingleton<ConnectivityService>();
|
services.AddSingleton<ConnectivityService>();
|
||||||
|
services.AddSingleton<SyncService>();
|
||||||
services.AddSingleton<MainWindowViewModel>();
|
services.AddSingleton<MainWindowViewModel>();
|
||||||
|
|
||||||
Services = services.BuildServiceProvider();
|
Services = services.BuildServiceProvider();
|
||||||
|
|||||||
@@ -55,82 +55,5 @@ public class AppDbContext : DbContext
|
|||||||
|
|
||||||
private static void SeedData(ModelBuilder modelBuilder)
|
private static void SeedData(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
modelBuilder.Entity<Profesor>().HasData(
|
|
||||||
new Profesor
|
|
||||||
{
|
|
||||||
RutPasaporte = "15668563-1",
|
|
||||||
Nombre = "Juan",
|
|
||||||
ApPaterno = "Perez",
|
|
||||||
ApMaterno = "Gonzalez",
|
|
||||||
Email = "juan.perez@norteamericano.cl",
|
|
||||||
Fono = "+56912345678",
|
|
||||||
Direccion = "Av. Providencia 1234, Santiago",
|
|
||||||
Clave = "",
|
|
||||||
CrearClave = true,
|
|
||||||
Activo = true
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
modelBuilder.Entity<Curso>().HasData(
|
|
||||||
new Curso { IdCursos = 16451, NombreCurso = "English Basic A1" },
|
|
||||||
new Curso { IdCursos = 16493, NombreCurso = "English Intermediate B1" }
|
|
||||||
);
|
|
||||||
|
|
||||||
modelBuilder.Entity<CursoAbierto>().HasData(
|
|
||||||
new CursoAbierto
|
|
||||||
{
|
|
||||||
IdCursoAbierto = 16451,
|
|
||||||
IdCursos = 16451,
|
|
||||||
Sala = "Sala 101",
|
|
||||||
Sede = "Providencia",
|
|
||||||
HoraInicio = "09:00",
|
|
||||||
HoraFin = "10:30",
|
|
||||||
FechaInicio = new DateTime(2026, 3, 1),
|
|
||||||
FechaFin = new DateTime(2026, 7, 31),
|
|
||||||
ProfesorRun = "15668563-1"
|
|
||||||
},
|
|
||||||
new CursoAbierto
|
|
||||||
{
|
|
||||||
IdCursoAbierto = 16493,
|
|
||||||
IdCursos = 16493,
|
|
||||||
Sala = "Sala 202",
|
|
||||||
Sede = "Las Condes",
|
|
||||||
HoraInicio = "14:00",
|
|
||||||
HoraFin = "15:30",
|
|
||||||
FechaInicio = new DateTime(2026, 3, 1),
|
|
||||||
FechaFin = new DateTime(2026, 7, 31),
|
|
||||||
ProfesorRun = "15668563-1"
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
modelBuilder.Entity<DetalleContrato>().HasData(
|
|
||||||
new DetalleContrato
|
|
||||||
{
|
|
||||||
IdDetalleContrato = 1,
|
|
||||||
IdCursoAbierto = 16451,
|
|
||||||
IdAlumno = "11111111-1",
|
|
||||||
AP_Paterno = "Garcia",
|
|
||||||
AP_Materno = "Lopez",
|
|
||||||
Nombres = "Maria"
|
|
||||||
},
|
|
||||||
new DetalleContrato
|
|
||||||
{
|
|
||||||
IdDetalleContrato = 2,
|
|
||||||
IdCursoAbierto = 16451,
|
|
||||||
IdAlumno = "22222222-2",
|
|
||||||
AP_Paterno = "Rodriguez",
|
|
||||||
AP_Materno = "Soto",
|
|
||||||
Nombres = "Carlos"
|
|
||||||
},
|
|
||||||
new DetalleContrato
|
|
||||||
{
|
|
||||||
IdDetalleContrato = 3,
|
|
||||||
IdCursoAbierto = 16493,
|
|
||||||
IdAlumno = "33333333-3",
|
|
||||||
AP_Paterno = "Martinez",
|
|
||||||
AP_Materno = "Fernandez",
|
|
||||||
Nombres = "Ana"
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@ public class AsistenciaRepository
|
|||||||
a.Estado == "Activa");
|
a.Estado == "Activa");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<AsistenciaProfesor> IniciarSesionAsync(int idCursoAbierto, string rut, DateTime fecha, string horaInicio)
|
public async Task<AsistenciaProfesor> IniciarSesionAsync(int idCursoAbierto, string rut, DateTime fecha, string horaInicio, int tipoAsignacion)
|
||||||
{
|
{
|
||||||
var sesion = new AsistenciaProfesor
|
var sesion = new AsistenciaProfesor
|
||||||
{
|
{
|
||||||
@@ -29,7 +29,8 @@ public class AsistenciaRepository
|
|||||||
RutPasaporte = rut,
|
RutPasaporte = rut,
|
||||||
FechaAsistencia = fecha,
|
FechaAsistencia = fecha,
|
||||||
HoraInicio = horaInicio,
|
HoraInicio = horaInicio,
|
||||||
Estado = "Activa"
|
Estado = "Activa",
|
||||||
|
Temporal = tipoAsignacion == 4 ? 1 : 0
|
||||||
};
|
};
|
||||||
_context.AsistenciasProfesor.Add(sesion);
|
_context.AsistenciasProfesor.Add(sesion);
|
||||||
await _context.SaveChangesAsync();
|
await _context.SaveChangesAsync();
|
||||||
|
|||||||
@@ -33,4 +33,11 @@ public class CursoRepository
|
|||||||
.Where(d => d.IdCursoAbierto == idCursoAbierto)
|
.Where(d => d.IdCursoAbierto == idCursoAbierto)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<DetalleContrato?> BuscarAlumnoPorRutAsync(int idCursoAbierto, string idAlumno)
|
||||||
|
{
|
||||||
|
return await _context.DetallesContrato
|
||||||
|
.FirstOrDefaultAsync(d => d.IdCursoAbierto == idCursoAbierto
|
||||||
|
&& d.IdAlumno == idAlumno);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -23,13 +23,16 @@ public class AsistenciaService
|
|||||||
public Task<List<DetalleContrato>> ObtenerAlumnosAsync(int idCursoAbierto)
|
public Task<List<DetalleContrato>> ObtenerAlumnosAsync(int idCursoAbierto)
|
||||||
=> _cursoRepo.BuscarAlumnosPorCursoAsync(idCursoAbierto);
|
=> _cursoRepo.BuscarAlumnosPorCursoAsync(idCursoAbierto);
|
||||||
|
|
||||||
|
public Task<DetalleContrato?> BuscarAlumnoPorRutAsync(int idCursoAbierto, string idAlumno)
|
||||||
|
=> _cursoRepo.BuscarAlumnoPorRutAsync(idCursoAbierto, idAlumno);
|
||||||
|
|
||||||
public Task<AsistenciaProfesor?> BuscarSesionActivaAsync(int idCursoAbierto)
|
public Task<AsistenciaProfesor?> BuscarSesionActivaAsync(int idCursoAbierto)
|
||||||
=> _asistenciaRepo.BuscarSesionActivaAsync(idCursoAbierto, DateTime.Today);
|
=> _asistenciaRepo.BuscarSesionActivaAsync(idCursoAbierto, DateTime.Today);
|
||||||
|
|
||||||
public async Task<AsistenciaProfesor> IniciarSesionAsync(int idCursoAbierto, string rut)
|
public async Task<AsistenciaProfesor> IniciarSesionAsync(int idCursoAbierto, string rut, int tipoAsignacion)
|
||||||
{
|
{
|
||||||
var now = DateTime.Now;
|
var now = DateTime.Now;
|
||||||
return await _asistenciaRepo.IniciarSesionAsync(idCursoAbierto, rut, now.Date, now.ToString("HH:mm"));
|
return await _asistenciaRepo.IniciarSesionAsync(idCursoAbierto, rut, now.Date, now.ToString("HH:mm"), tipoAsignacion);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> FinalizarSesionAsync(int idSesion)
|
public async Task<bool> FinalizarSesionAsync(int idSesion)
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ public class AuthService
|
|||||||
|
|
||||||
public Profesor? CurrentUser => _currentUser;
|
public Profesor? CurrentUser => _currentUser;
|
||||||
|
|
||||||
public async Task<(bool Success, string Message)> LoginAsync(string rut, string password)
|
public int TipoAsignacionActual { get; private set; }
|
||||||
|
|
||||||
|
public async Task<(bool Success, string Message)> LoginAsync(string rut, int tipoAsignacion)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(rut))
|
if (string.IsNullOrWhiteSpace(rut))
|
||||||
return (false, "Ingrese su RUT");
|
return (false, "Ingrese su RUT");
|
||||||
@@ -25,6 +27,7 @@ public class AuthService
|
|||||||
return (false, "Usuario no encontrado");
|
return (false, "Usuario no encontrado");
|
||||||
|
|
||||||
_currentUser = profesor;
|
_currentUser = profesor;
|
||||||
|
TipoAsignacionActual = tipoAsignacion;
|
||||||
return (true, "Inicio de sesión exitoso");
|
return (true, "Inicio de sesión exitoso");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Asistencia.Data;
|
||||||
|
using Asistencia.Models;
|
||||||
|
|
||||||
|
namespace Asistencia.Services;
|
||||||
|
|
||||||
|
public class SyncService
|
||||||
|
{
|
||||||
|
private readonly AppDbContext _db;
|
||||||
|
private readonly ConnectivityService _connectivity;
|
||||||
|
|
||||||
|
public SyncService(AppDbContext db, ConnectivityService connectivity)
|
||||||
|
{
|
||||||
|
_db = db;
|
||||||
|
_connectivity = connectivity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> ContarPendientesAsync()
|
||||||
|
{
|
||||||
|
var sesiones = await _db.AsistenciasProfesor
|
||||||
|
.Where(a => a.Estado == "Finalizada")
|
||||||
|
.CountAsync();
|
||||||
|
|
||||||
|
var asistencias = await _db.AsistenciasAlumno.CountAsync();
|
||||||
|
|
||||||
|
return sesiones + asistencias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<(bool Success, string Message)> SincronizarAsync(string apiUrl)
|
||||||
|
{
|
||||||
|
if (!await _connectivity.HayConexionAsync())
|
||||||
|
return (false, "Sin conexion a internet");
|
||||||
|
|
||||||
|
var pendientes = await ContarPendientesAsync();
|
||||||
|
if (pendientes == 0)
|
||||||
|
return (true, "No hay datos pendientes");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var sesiones = await _db.AsistenciasProfesor
|
||||||
|
.Where(a => a.Estado == "Finalizada")
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
foreach (var sesion in sesiones)
|
||||||
|
{
|
||||||
|
// TODO: POST to apiUrl + "/api/asistencia-profesor"
|
||||||
|
// await HttpClient.PostAsJsonAsync(apiUrl + "/api/asistencia-profesor", sesion);
|
||||||
|
}
|
||||||
|
|
||||||
|
var asistencias = await _db.AsistenciasAlumno.ToListAsync();
|
||||||
|
foreach (var asistencia in asistencias)
|
||||||
|
{
|
||||||
|
// TODO: POST to apiUrl + "/api/asistencia-alumno"
|
||||||
|
// await HttpClient.PostAsJsonAsync(apiUrl + "/api/asistencia-alumno", asistencia);
|
||||||
|
}
|
||||||
|
|
||||||
|
_db.AsistenciasProfesor.RemoveRange(sesiones);
|
||||||
|
_db.AsistenciasAlumno.RemoveRange(asistencias);
|
||||||
|
await _db.SaveChangesAsync();
|
||||||
|
|
||||||
|
return (true, $"Sincronizados {sesiones.Count} sesiones y {asistencias.Count} asistencias");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return (false, $"Error al sincronizar: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,100 +11,112 @@ public partial class AsistenciaViewModel : ViewModelBase
|
|||||||
private readonly AsistenciaService _asistenciaService;
|
private readonly AsistenciaService _asistenciaService;
|
||||||
private readonly AuthService _authService;
|
private readonly AuthService _authService;
|
||||||
private readonly MainWindowViewModel _mainVm;
|
private readonly MainWindowViewModel _mainVm;
|
||||||
private readonly CursoAbierto _curso;
|
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private string _nombreCurso = string.Empty;
|
private string _inputCursoAbierto = string.Empty;
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
private string _infoCurso = string.Empty;
|
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private bool _enSesion;
|
private bool _enSesion;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private int _totalAlumnos;
|
private string _inputRutAlumno = string.Empty;
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
private int _presentes;
|
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
private int _tardanzas;
|
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
private int _ausentes;
|
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private string _mensajeEstado = string.Empty;
|
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;
|
_asistenciaService = asistenciaService;
|
||||||
_authService = authService;
|
_authService = authService;
|
||||||
_mainVm = mainVm;
|
_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]
|
[RelayCommand]
|
||||||
private async Task IniciarSesionAsync()
|
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;
|
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;
|
EnSesion = true;
|
||||||
MensajeEstado = "Sesion iniciada - Registre la asistencia de los alumnos";
|
MensajeEstado = $"Sesion curso {idCurso} — Ingrese RUT de alumnos presentes";
|
||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private async Task FinalizarSesionAsync()
|
private async Task FinalizarSesionAsync()
|
||||||
{
|
{
|
||||||
var sesion = await _asistenciaService.BuscarSesionActivaAsync(_curso.IdCursoAbierto);
|
var sesion = await _asistenciaService.BuscarSesionActivaAsync(_idCursoAbierto);
|
||||||
if (sesion != null)
|
if (sesion != null)
|
||||||
{
|
{
|
||||||
await _asistenciaService.FinalizarSesionAsync(sesion.IdAsistenciaProfesor);
|
await _asistenciaService.FinalizarSesionAsync(sesion.IdAsistenciaProfesor);
|
||||||
}
|
}
|
||||||
EnSesion = false;
|
EnSesion = false;
|
||||||
|
AlumnosPresentes.Clear();
|
||||||
|
InputCursoAbierto = string.Empty;
|
||||||
|
InputRutAlumno = string.Empty;
|
||||||
MensajeEstado = "Sesion finalizada";
|
MensajeEstado = "Sesion finalizada";
|
||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private async Task MarcarAlumnoAsync(AlumnoAsistenciaViewModel? alumno)
|
private async Task AgregarAlumnoAsync()
|
||||||
{
|
{
|
||||||
if (alumno == null || !EnSesion) return;
|
if (!EnSesion) return;
|
||||||
|
|
||||||
alumno.CiclarTipoAsistencia();
|
HasError = false;
|
||||||
await _asistenciaService.GuardarAsistenciaAlumnoAsync(alumno.IdDetalleContrato, alumno.TipoAsistencia);
|
var rut = InputRutAlumno.Trim();
|
||||||
ActualizarContadores();
|
|
||||||
|
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]
|
[RelayCommand]
|
||||||
@@ -112,56 +124,10 @@ public partial class AsistenciaViewModel : ViewModelBase
|
|||||||
{
|
{
|
||||||
_mainVm.NavigateToDashboard();
|
_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 IdAlumno { get; set; } = string.Empty;
|
||||||
public string NombreCompleto { get; }
|
public string NombreCompleto { get; set; } = string.Empty;
|
||||||
|
|
||||||
[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"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -10,40 +10,54 @@ public partial class DashboardViewModel : ViewModelBase
|
|||||||
{
|
{
|
||||||
private readonly AuthService _authService;
|
private readonly AuthService _authService;
|
||||||
private readonly AsistenciaService _asistenciaService;
|
private readonly AsistenciaService _asistenciaService;
|
||||||
|
private readonly SyncService _syncService;
|
||||||
private readonly MainWindowViewModel _mainVm;
|
private readonly MainWindowViewModel _mainVm;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private string _nombreProfesor = string.Empty;
|
private string _nombreProfesor = string.Empty;
|
||||||
|
|
||||||
[ObservableProperty]
|
[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;
|
_authService = authService;
|
||||||
_asistenciaService = asistenciaService;
|
_asistenciaService = asistenciaService;
|
||||||
|
_syncService = syncService;
|
||||||
_mainVm = mainVm;
|
_mainVm = mainVm;
|
||||||
NombreProfesor = authService.CurrentUser?.Nombre ?? "";
|
NombreProfesor = authService.CurrentUser?.NombreCompleto ?? "";
|
||||||
_ = LoadCursosAsync();
|
TipoAsignacion = authService.TipoAsignacionActual == 1 ? "Titular" : "Reemplazo";
|
||||||
|
_ = CargarPendientesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task LoadCursosAsync()
|
private async Task CargarPendientesAsync()
|
||||||
{
|
{
|
||||||
if (_authService.CurrentUser == null) return;
|
Pendientes = await _syncService.ContarPendientesAsync();
|
||||||
|
|
||||||
var cursos = await _asistenciaService.ObtenerCursosProfesorAsync(_authService.CurrentUser.RutPasaporte);
|
|
||||||
Cursos.Clear();
|
|
||||||
foreach (var c in cursos) Cursos.Add(c);
|
|
||||||
TotalCursos = Cursos.Count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private void AbrirAsistencia(CursoAbierto? curso)
|
private void AbrirAsistencia()
|
||||||
{
|
{
|
||||||
if (curso != null)
|
_mainVm.NavigateToAsistencia();
|
||||||
_mainVm.NavigateToAsistencia(curso);
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task SincronizarAsync()
|
||||||
|
{
|
||||||
|
HasMensajeSync = false;
|
||||||
|
var (success, message) = await _syncService.SincronizarAsync("http://localhost:5000");
|
||||||
|
MensajeSync = message;
|
||||||
|
HasMensajeSync = true;
|
||||||
|
await CargarPendientesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
|
|||||||
@@ -13,7 +13,10 @@ public partial class LoginViewModel : ViewModelBase
|
|||||||
private string _rut = string.Empty;
|
private string _rut = string.Empty;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private string _password = string.Empty;
|
private bool _esTitular = true;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool _esReemplazo;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private string _errorMessage = string.Empty;
|
private string _errorMessage = string.Empty;
|
||||||
@@ -30,13 +33,24 @@ public partial class LoginViewModel : ViewModelBase
|
|||||||
_mainVm = mainVm;
|
_mainVm = mainVm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
partial void OnEsTitularChanged(bool value)
|
||||||
|
{
|
||||||
|
if (value) EsReemplazo = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void OnEsReemplazoChanged(bool value)
|
||||||
|
{
|
||||||
|
if (value) EsTitular = false;
|
||||||
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private async Task LoginAsync()
|
private async Task LoginAsync()
|
||||||
{
|
{
|
||||||
IsLoading = true;
|
IsLoading = true;
|
||||||
HasError = false;
|
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)
|
if (success)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
private readonly AuthService _authService;
|
private readonly AuthService _authService;
|
||||||
private readonly AsistenciaService _asistenciaService;
|
private readonly AsistenciaService _asistenciaService;
|
||||||
private readonly ConnectivityService _connectivityService;
|
private readonly ConnectivityService _connectivityService;
|
||||||
|
private readonly SyncService _syncService;
|
||||||
private object? _currentView;
|
private object? _currentView;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
@@ -30,11 +31,12 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
set => SetProperty(ref _currentView, value);
|
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;
|
_authService = authService;
|
||||||
_asistenciaService = asistenciaService;
|
_asistenciaService = asistenciaService;
|
||||||
_connectivityService = connectivityService;
|
_connectivityService = connectivityService;
|
||||||
|
_syncService = syncService;
|
||||||
_ = VerificarConexionAsync();
|
_ = VerificarConexionAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,13 +66,13 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
public void NavigateToDashboard()
|
public void NavigateToDashboard()
|
||||||
{
|
{
|
||||||
CurrentViewTitle = "Panel Principal";
|
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";
|
CurrentViewTitle = "Asistencia";
|
||||||
CurrentView = new AsistenciaViewModel(_asistenciaService, _authService, curso, this);
|
CurrentView = new AsistenciaViewModel(_asistenciaService, _authService, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void NavigateToPerfil()
|
public void NavigateToPerfil()
|
||||||
|
|||||||
@@ -4,130 +4,109 @@
|
|||||||
x:Class="Asistencia.Views.AsistenciaView"
|
x:Class="Asistencia.Views.AsistenciaView"
|
||||||
x:DataType="vm:AsistenciaViewModel">
|
x:DataType="vm:AsistenciaViewModel">
|
||||||
|
|
||||||
<Design.DataContext>
|
|
||||||
<vm:AsistenciaViewModel />
|
|
||||||
</Design.DataContext>
|
|
||||||
|
|
||||||
<ScrollViewer>
|
<ScrollViewer>
|
||||||
<StackPanel Spacing="0" Margin="32,24">
|
<StackPanel Spacing="0" Margin="32,24" MaxWidth="500">
|
||||||
|
|
||||||
<Button Content="Volver" Classes="secondary"
|
<Button Content="Volver" Classes="secondary"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
Command="{Binding VolverCommand}"
|
Command="{Binding VolverCommand}"
|
||||||
Margin="0,0,0,16" />
|
Margin="0,0,0,16" />
|
||||||
|
|
||||||
<TextBlock Text="{Binding NombreCurso}" Classes="page-header" />
|
<TextBlock Text="Tomar Asistencia" Classes="page-header" />
|
||||||
|
|
||||||
<Border Classes="card" Margin="0,0,0,20">
|
<Border Classes="card" Margin="0,0,0,16">
|
||||||
<StackPanel Spacing="8">
|
<StackPanel Spacing="12">
|
||||||
<TextBlock Text="{Binding InfoCurso}"
|
<TextBlock Text="ID Curso Abierto" FontSize="13" FontWeight="SemiBold"
|
||||||
FontSize="14" Foreground="{DynamicResource TextSecondary}" />
|
Foreground="{DynamicResource TextPrimary}" />
|
||||||
|
<TextBox PlaceholderText="Ej: 16451"
|
||||||
<TextBlock Text="{Binding MensajeEstado}"
|
Text="{Binding InputCursoAbierto}"
|
||||||
FontSize="13" FontWeight="SemiBold"
|
FontSize="14" />
|
||||||
Foreground="{DynamicResource PrimaryNavy}" />
|
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||||
|
<Button Content="Iniciar Sesion" Classes="success"
|
||||||
<StackPanel Orientation="Horizontal" Spacing="8" Margin="0,8,0,0">
|
|
||||||
<Button Content="Iniciar Sesion"
|
|
||||||
Classes="success"
|
|
||||||
Command="{Binding IniciarSesionCommand}"
|
Command="{Binding IniciarSesionCommand}"
|
||||||
IsVisible="{Binding !EnSesion}" />
|
IsVisible="{Binding !EnSesion}" />
|
||||||
<Button Content="Finalizar Sesion"
|
<Button Content="Finalizar Sesion" Classes="danger"
|
||||||
Classes="danger"
|
|
||||||
Command="{Binding FinalizarSesionCommand}"
|
Command="{Binding FinalizarSesionCommand}"
|
||||||
IsVisible="{Binding EnSesion}" />
|
IsVisible="{Binding EnSesion}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<Grid ColumnDefinitions="*,Auto" Margin="0,0,0,16">
|
<Border Classes="card" Margin="0,0,0,16"
|
||||||
<TextBlock Grid.Column="0"
|
IsVisible="{Binding EnSesion}">
|
||||||
Classes="section-title"
|
<StackPanel Spacing="12">
|
||||||
Text="Alumnos"
|
<TextBlock Text="RUT Alumno" FontSize="13" FontWeight="SemiBold"
|
||||||
VerticalAlignment="Center" />
|
Foreground="{DynamicResource TextPrimary}" />
|
||||||
|
<Grid ColumnDefinitions="*,Auto">
|
||||||
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="16">
|
<TextBox Grid.Column="0"
|
||||||
<StackPanel Orientation="Horizontal" Spacing="4">
|
PlaceholderText="Ej: 11111111-1"
|
||||||
<Border Background="{DynamicResource SuccessColor}"
|
Text="{Binding InputRutAlumno}"
|
||||||
CornerRadius="4" Width="12" Height="12" />
|
FontSize="14"
|
||||||
<TextBlock Text="{Binding Presentes}" FontSize="13"
|
KeyDown="OnRutAlumnoKeyDown" />
|
||||||
Foreground="{DynamicResource TextSecondary}" />
|
<Button Grid.Column="1"
|
||||||
</StackPanel>
|
Content="+"
|
||||||
<StackPanel Orientation="Horizontal" Spacing="4">
|
Classes="primary"
|
||||||
<Border Background="{DynamicResource WarningColor}"
|
Command="{Binding AgregarAlumnoCommand}"
|
||||||
CornerRadius="4" Width="12" Height="12" />
|
Margin="8,0,0,0"
|
||||||
<TextBlock Text="{Binding Tardanzas}" FontSize="13"
|
Width="40" Height="40"
|
||||||
Foreground="{DynamicResource TextSecondary}" />
|
FontSize="18" FontWeight="Bold" />
|
||||||
</StackPanel>
|
|
||||||
<StackPanel Orientation="Horizontal" Spacing="4">
|
|
||||||
<Border Background="{DynamicResource DangerColor}"
|
|
||||||
CornerRadius="4" Width="12" Height="12" />
|
|
||||||
<TextBlock Text="{Binding Ausentes}" FontSize="13"
|
|
||||||
Foreground="{DynamicResource TextSecondary}" />
|
|
||||||
</StackPanel>
|
|
||||||
</StackPanel>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<Border Classes="card" Padding="0">
|
|
||||||
<Grid RowDefinitions="Auto,*">
|
|
||||||
|
|
||||||
<Border Grid.Row="0" Background="{DynamicResource BackgroundSecondary}"
|
|
||||||
CornerRadius="12,12,0,0" Padding="16,12">
|
|
||||||
<Grid ColumnDefinitions="*,120">
|
|
||||||
<TextBlock Grid.Column="0" Text="Alumno"
|
|
||||||
FontSize="13" FontWeight="SemiBold"
|
|
||||||
Foreground="{DynamicResource TextSecondary}" />
|
|
||||||
<TextBlock Grid.Column="1" Text="Estado"
|
|
||||||
FontSize="13" FontWeight="SemiBold"
|
|
||||||
Foreground="{DynamicResource TextSecondary}"
|
|
||||||
HorizontalAlignment="Center" />
|
|
||||||
</Grid>
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<ListBox Grid.Row="1"
|
<TextBlock Text="{Binding MensajeEstado}"
|
||||||
ItemsSource="{Binding Alumnos}"
|
FontSize="13" FontWeight="SemiBold"
|
||||||
|
Foreground="{DynamicResource PrimaryNavy}"
|
||||||
|
Margin="0,0,0,12"
|
||||||
|
IsVisible="{Binding !HasError}" />
|
||||||
|
|
||||||
|
<TextBlock Text="{Binding MensajeError}"
|
||||||
|
FontSize="13"
|
||||||
|
Foreground="{DynamicResource DangerColor}"
|
||||||
|
Margin="0,0,0,12"
|
||||||
|
IsVisible="{Binding HasError}" />
|
||||||
|
|
||||||
|
<Border Classes="card" Padding="0"
|
||||||
|
IsVisible="{Binding EnSesion}">
|
||||||
|
<StackPanel>
|
||||||
|
<Border Background="{DynamicResource BackgroundSecondary}"
|
||||||
|
CornerRadius="12,12,0,0" Padding="16,12">
|
||||||
|
<TextBlock Text="Alumnos Presentes"
|
||||||
|
FontSize="13" FontWeight="SemiBold"
|
||||||
|
Foreground="{DynamicResource TextSecondary}" />
|
||||||
|
</Border>
|
||||||
|
<ListBox ItemsSource="{Binding AlumnosPresentes}"
|
||||||
Background="Transparent"
|
Background="Transparent"
|
||||||
BorderThickness="0"
|
BorderThickness="0"
|
||||||
Padding="0">
|
Padding="0"
|
||||||
|
MaxHeight="300">
|
||||||
<ListBox.ItemTemplate>
|
<ListBox.ItemTemplate>
|
||||||
<DataTemplate x:DataType="vm:AlumnoAsistenciaViewModel">
|
<DataTemplate x:DataType="vm:AlumnoPresenteViewModel">
|
||||||
<Border Padding="16,12"
|
<Border Padding="16,10"
|
||||||
BorderBrush="{DynamicResource BorderColor}"
|
BorderBrush="{DynamicResource BorderColor}"
|
||||||
BorderThickness="0,0,0,1">
|
BorderThickness="0,0,0,1">
|
||||||
<Grid ColumnDefinitions="*,120">
|
<Grid ColumnDefinitions="Auto,*">
|
||||||
<TextBlock Grid.Column="0"
|
<Border Grid.Column="0"
|
||||||
Text="{Binding NombreCompleto}"
|
Background="{DynamicResource SuccessColor}"
|
||||||
FontSize="14"
|
CornerRadius="12" Padding="10,4"
|
||||||
VerticalAlignment="Center" />
|
VerticalAlignment="Center">
|
||||||
|
<TextBlock Text="P" Foreground="White"
|
||||||
<Button Grid.Column="1"
|
FontSize="12" FontWeight="Bold" />
|
||||||
HorizontalAlignment="Center"
|
</Border>
|
||||||
Command="{Binding $parent[ListBox].((vm:AsistenciaViewModel)DataContext).MarcarAlumnoCommand}"
|
<StackPanel Grid.Column="1" Margin="12,0,0,0"
|
||||||
CommandParameter="{Binding}"
|
VerticalAlignment="Center">
|
||||||
Background="{Binding TipoAsistenciaColor}"
|
<TextBlock Text="{Binding NombreCompleto}"
|
||||||
CornerRadius="20"
|
FontSize="14" FontWeight="SemiBold" />
|
||||||
Padding="16,6"
|
<TextBlock Text="{Binding IdAlumno}"
|
||||||
FontSize="13"
|
FontSize="12"
|
||||||
FontWeight="SemiBold"
|
Foreground="{DynamicResource TextSecondary}" />
|
||||||
Foreground="White"
|
</StackPanel>
|
||||||
BorderThickness="0"
|
|
||||||
MinWidth="100">
|
|
||||||
<TextBlock Text="{Binding TipoAsistenciaTexto}"
|
|
||||||
Foreground="White" />
|
|
||||||
</Button>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListBox.ItemTemplate>
|
</ListBox.ItemTemplate>
|
||||||
</ListBox>
|
</ListBox>
|
||||||
</Grid>
|
</StackPanel>
|
||||||
</Border>
|
|
||||||
|
|
||||||
<Border Classes="card" Margin="0,16,0,0"
|
|
||||||
IsVisible="{Binding !Alumnos.Count}"
|
|
||||||
Background="#FFF3CD">
|
|
||||||
<TextBlock Text="No hay alumnos en este curso."
|
|
||||||
FontSize="14" Foreground="#856404" />
|
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Input;
|
||||||
|
using Asistencia.ViewModels;
|
||||||
|
|
||||||
namespace Asistencia.Views;
|
namespace Asistencia.Views;
|
||||||
|
|
||||||
@@ -9,4 +10,12 @@ public partial class AsistenciaView : UserControl
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnRutAlumnoKeyDown(object? sender, KeyEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Key == Key.Return && DataContext is AsistenciaViewModel vm)
|
||||||
|
{
|
||||||
|
vm.AgregarAlumnoCommand.Execute(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
<UserControl xmlns="https://github.com/avaloniaui"
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:vm="using:Asistencia.ViewModels"
|
xmlns:vm="using:Asistencia.ViewModels"
|
||||||
xmlns:models="using:Asistencia.Models"
|
|
||||||
x:Class="Asistencia.Views.DashboardView"
|
x:Class="Asistencia.Views.DashboardView"
|
||||||
x:DataType="vm:DashboardViewModel">
|
x:DataType="vm:DashboardViewModel">
|
||||||
|
|
||||||
@@ -10,18 +9,19 @@
|
|||||||
</Design.DataContext>
|
</Design.DataContext>
|
||||||
|
|
||||||
<ScrollViewer>
|
<ScrollViewer>
|
||||||
<StackPanel Spacing="0" Margin="32,24">
|
<StackPanel Spacing="0" Margin="32,24" MaxWidth="500">
|
||||||
|
|
||||||
<TextBlock Text="Panel Principal" Classes="page-header" />
|
<TextBlock Text="Panel Principal" Classes="page-header" />
|
||||||
|
|
||||||
<Border Classes="card" Margin="0,0,0,24">
|
<Border Classes="card" Margin="0,0,0,24">
|
||||||
<Grid ColumnDefinitions="*,Auto">
|
<Grid ColumnDefinitions="*,Auto">
|
||||||
<StackPanel Grid.Column="0" Spacing="4">
|
<StackPanel Grid.Column="0" Spacing="4">
|
||||||
<TextBlock Text="Bienvenido"
|
|
||||||
FontSize="14" Foreground="{DynamicResource TextSecondary}" />
|
|
||||||
<TextBlock Text="{Binding NombreProfesor}"
|
<TextBlock Text="{Binding NombreProfesor}"
|
||||||
FontSize="24" FontWeight="Bold"
|
FontSize="22" FontWeight="Bold"
|
||||||
Foreground="{DynamicResource TextPrimary}" />
|
Foreground="{DynamicResource TextPrimary}" />
|
||||||
|
<TextBlock Text="{Binding TipoAsignacion}"
|
||||||
|
FontSize="13"
|
||||||
|
Foreground="{DynamicResource TextSecondary}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="8">
|
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="8">
|
||||||
@@ -35,55 +35,38 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<TextBlock Text="Mis Cursos" Classes="section-title" Margin="0,0,0,12" />
|
<Button Content="Tomar Asistencia"
|
||||||
|
Classes="primary"
|
||||||
|
Command="{Binding AbrirAsistenciaCommand}"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
Height="50"
|
||||||
|
FontSize="16" FontWeight="SemiBold"
|
||||||
|
Margin="0,0,0,16" />
|
||||||
|
|
||||||
<ItemsControl ItemsSource="{Binding Cursos}">
|
<Border Classes="card" Margin="0,0,0,16">
|
||||||
<ItemsControl.ItemTemplate>
|
<StackPanel Spacing="12">
|
||||||
<DataTemplate x:DataType="models:CursoAbierto">
|
<Grid ColumnDefinitions="*,Auto">
|
||||||
<Border Classes="card" Margin="0,0,0,12">
|
<TextBlock Grid.Column="0"
|
||||||
<Grid ColumnDefinitions="*,Auto" RowDefinitions="Auto,Auto,Auto">
|
FontSize="14" FontWeight="SemiBold"
|
||||||
|
Foreground="{DynamicResource TextPrimary}">
|
||||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
|
||||||
Text="{Binding Curso.NombreCurso}"
|
|
||||||
FontSize="18" FontWeight="Bold"
|
|
||||||
Foreground="{DynamicResource TextPrimary}" />
|
|
||||||
|
|
||||||
<TextBlock Grid.Row="0" Grid.Column="1"
|
|
||||||
Text="{Binding Sala}"
|
|
||||||
FontSize="13"
|
|
||||||
Foreground="{DynamicResource TextSecondary}" />
|
|
||||||
|
|
||||||
<TextBlock Grid.Row="1" Grid.Column="0"
|
|
||||||
FontSize="13"
|
|
||||||
Foreground="{DynamicResource TextSecondary}"
|
|
||||||
Margin="0,4,0,0">
|
|
||||||
<TextBlock.Text>
|
<TextBlock.Text>
|
||||||
<MultiBinding StringFormat="{}{0} | {1}">
|
<MultiBinding StringFormat="Pendientes: {0}">
|
||||||
<Binding Path="Sede" />
|
<Binding Path="Pendientes" />
|
||||||
<Binding Path="HoraInicio" />
|
|
||||||
</MultiBinding>
|
</MultiBinding>
|
||||||
</TextBlock.Text>
|
</TextBlock.Text>
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
|
<Button Grid.Column="1"
|
||||||
<Button Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2"
|
Content="Sincronizar"
|
||||||
Content="Tomar Asistencia"
|
Classes="success"
|
||||||
Classes="primary"
|
Command="{Binding SincronizarCommand}" />
|
||||||
HorizontalAlignment="Left"
|
|
||||||
Margin="0,12,0,0"
|
|
||||||
Command="{Binding $parent[ItemsControl].((vm:DashboardViewModel)DataContext).AbrirAsistenciaCommand}"
|
|
||||||
CommandParameter="{Binding}" />
|
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<TextBlock Text="{Binding MensajeSync}"
|
||||||
|
FontSize="12"
|
||||||
|
Foreground="{DynamicResource SuccessColor}"
|
||||||
|
IsVisible="{Binding HasMensajeSync}" />
|
||||||
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
</DataTemplate>
|
|
||||||
</ItemsControl.ItemTemplate>
|
|
||||||
</ItemsControl>
|
|
||||||
|
|
||||||
<Border Classes="card" Margin="0,24,0,0"
|
|
||||||
IsVisible="{Binding !Cursos.Count}"
|
|
||||||
Background="#FFF3CD">
|
|
||||||
<TextBlock Text="No tiene cursos asignados actualmente."
|
|
||||||
FontSize="14" Foreground="#856404" />
|
|
||||||
</Border>
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@@ -4,10 +4,6 @@
|
|||||||
x:Class="Asistencia.Views.LoginView"
|
x:Class="Asistencia.Views.LoginView"
|
||||||
x:DataType="vm:LoginViewModel">
|
x:DataType="vm:LoginViewModel">
|
||||||
|
|
||||||
<Design.DataContext>
|
|
||||||
<vm:LoginViewModel />
|
|
||||||
</Design.DataContext>
|
|
||||||
|
|
||||||
<Panel Background="{DynamicResource BackgroundSecondary}">
|
<Panel Background="{DynamicResource BackgroundSecondary}">
|
||||||
<Border HorizontalAlignment="Center" VerticalAlignment="Center"
|
<Border HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||||
CornerRadius="16" Padding="48" Width="420"
|
CornerRadius="16" Padding="48" Width="420"
|
||||||
@@ -20,14 +16,25 @@
|
|||||||
Foreground="{DynamicResource PrimaryNavy}"
|
Foreground="{DynamicResource PrimaryNavy}"
|
||||||
HorizontalAlignment="Center" />
|
HorizontalAlignment="Center" />
|
||||||
|
|
||||||
<TextBlock Text="Modo offline — Ingrese su RUT"
|
<TextBlock Text="Modo offline"
|
||||||
FontSize="14" Foreground="{DynamicResource TextSecondary}"
|
FontSize="14" Foreground="{DynamicResource TextSecondary}"
|
||||||
HorizontalAlignment="Center" Margin="0,0,0,24" />
|
HorizontalAlignment="Center" Margin="0,0,0,24" />
|
||||||
|
|
||||||
<TextBlock Text="RUT" FontSize="13" FontWeight="SemiBold"
|
<TextBlock Text="RUT" FontSize="13" FontWeight="SemiBold"
|
||||||
Foreground="{DynamicResource TextPrimary}" />
|
Foreground="{DynamicResource TextPrimary}" />
|
||||||
<TextBox PlaceholderText="Ej: 12345678-9"
|
<TextBox PlaceholderText="Ej: 15668563-1"
|
||||||
Text="{Binding Rut}"
|
Text="{Binding Rut}"
|
||||||
|
FontSize="14" Margin="0,0,0,12" />
|
||||||
|
|
||||||
|
<TextBlock Text="Tipo de asignacion" FontSize="13" FontWeight="SemiBold"
|
||||||
|
Foreground="{DynamicResource TextPrimary}" Margin="0,0,0,4" />
|
||||||
|
<RadioButton Content="Titular"
|
||||||
|
IsChecked="{Binding EsTitular}"
|
||||||
|
GroupName="TipoAsignacion"
|
||||||
|
FontSize="14" />
|
||||||
|
<RadioButton Content="Reemplazo"
|
||||||
|
IsChecked="{Binding EsReemplazo}"
|
||||||
|
GroupName="TipoAsignacion"
|
||||||
FontSize="14" Margin="0,0,0,16" />
|
FontSize="14" Margin="0,0,0,16" />
|
||||||
|
|
||||||
<Button Content="Ingresar"
|
<Button Content="Ingresar"
|
||||||
|
|||||||
Reference in new issue
Block a user