Alinear BD local con esquema de produccion, login offline y publicacion portable
- Modelos renombrados para coincidir con columnas de MariaDB (ApPaterno/ApMaterno, HoraSalida, FechaFin, IdAsistenciaProfesor) - Agregado campo IdAlumno a DetalleContrato - Seed data con IDs reales de produccion (16451, 16493, profesor 15668563-1) - Login offline: solo valida RUT contra BD local, sin contraseña - ConnectivityService: checkea internet al inicio, bloquea si hay conexion - ViewLocator corregido: busca tipos en todos los ensamblados - Todos los ViewModels heredan de ViewModelBase - Publicacion self-contained para win-x64, linux-x64, osx-x64, osx-arm64 - Agregado .gitignore, removidos bin/obj/publish del tracking
This commit is contained in:
1 parent
9068122b6b
commit
fb275508ee
19 files changed
+196
-77
No files matched your search
+71
@@ -0,0 +1,71 @@
|
|||||||
|
## Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Rr]elease/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
|
||||||
|
## Publish output
|
||||||
|
publish/
|
||||||
|
|
||||||
|
## NuGet
|
||||||
|
*.nupkg
|
||||||
|
*.snupkg
|
||||||
|
.nuget/
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
|
||||||
|
## Visual Studio
|
||||||
|
.vs/
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
## Rider
|
||||||
|
.idea/
|
||||||
|
*.sln.iml
|
||||||
|
|
||||||
|
## VS Code
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
|
||||||
|
## macOS
|
||||||
|
.DS_Store
|
||||||
|
*.dmg
|
||||||
|
|
||||||
|
## Windows
|
||||||
|
Thumbs.db
|
||||||
|
ehthumbs.db
|
||||||
|
Desktop.ini
|
||||||
|
|
||||||
|
## Linux
|
||||||
|
*~
|
||||||
|
|
||||||
|
## SQLite databases
|
||||||
|
*.db
|
||||||
|
*.db-shm
|
||||||
|
*.db-wal
|
||||||
|
|
||||||
|
## Resharper
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
## NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
## BenchmarkDotNet
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
@@ -29,6 +29,7 @@ public partial class App : Application
|
|||||||
services.AddSingleton<AsistenciaRepository>();
|
services.AddSingleton<AsistenciaRepository>();
|
||||||
services.AddSingleton<AuthService>();
|
services.AddSingleton<AuthService>();
|
||||||
services.AddSingleton<AsistenciaService>();
|
services.AddSingleton<AsistenciaService>();
|
||||||
|
services.AddSingleton<ConnectivityService>();
|
||||||
services.AddSingleton<MainWindowViewModel>();
|
services.AddSingleton<MainWindowViewModel>();
|
||||||
|
|
||||||
Services = services.BuildServiceProvider();
|
Services = services.BuildServiceProvider();
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
|
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64;osx-arm64</RuntimeIdentifiers>
|
||||||
|
<SelfContained>true</SelfContained>
|
||||||
|
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -58,48 +58,48 @@ public class AppDbContext : DbContext
|
|||||||
modelBuilder.Entity<Profesor>().HasData(
|
modelBuilder.Entity<Profesor>().HasData(
|
||||||
new Profesor
|
new Profesor
|
||||||
{
|
{
|
||||||
RutPasaporte = "12345678-9",
|
RutPasaporte = "15668563-1",
|
||||||
Nombre = "Juan",
|
Nombre = "Juan",
|
||||||
Paterno = "Perez",
|
ApPaterno = "Perez",
|
||||||
Materno = "Gonzalez",
|
ApMaterno = "Gonzalez",
|
||||||
Email = "juan.perez@norteamericano.cl",
|
Email = "juan.perez@norteamericano.cl",
|
||||||
Fono = "+56912345678",
|
Fono = "+56912345678",
|
||||||
Direccion = "Av. Providencia 1234, Santiago",
|
Direccion = "Av. Providencia 1234, Santiago",
|
||||||
Clave = "",
|
Clave = "",
|
||||||
CrearClave = true
|
CrearClave = true,
|
||||||
|
Activo = true
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
modelBuilder.Entity<Curso>().HasData(
|
modelBuilder.Entity<Curso>().HasData(
|
||||||
new Curso { IdCursos = 1, NombreCurso = "English Basic A1" },
|
new Curso { IdCursos = 16451, NombreCurso = "English Basic A1" },
|
||||||
new Curso { IdCursos = 2, NombreCurso = "English Intermediate B1" },
|
new Curso { IdCursos = 16493, NombreCurso = "English Intermediate B1" }
|
||||||
new Curso { IdCursos = 3, NombreCurso = "English Advanced C1" }
|
|
||||||
);
|
);
|
||||||
|
|
||||||
modelBuilder.Entity<CursoAbierto>().HasData(
|
modelBuilder.Entity<CursoAbierto>().HasData(
|
||||||
new CursoAbierto
|
new CursoAbierto
|
||||||
{
|
{
|
||||||
IdCursoAbierto = 1,
|
IdCursoAbierto = 16451,
|
||||||
IdCursos = 1,
|
IdCursos = 16451,
|
||||||
Sala = "Sala 101",
|
Sala = "Sala 101",
|
||||||
Sede = "Providencia",
|
Sede = "Providencia",
|
||||||
HoraInicio = "09:00",
|
HoraInicio = "09:00",
|
||||||
HoraFin = "10:30",
|
HoraFin = "10:30",
|
||||||
FechaInicio = new DateTime(2026, 3, 1),
|
FechaInicio = new DateTime(2026, 3, 1),
|
||||||
FechaTermino = new DateTime(2026, 7, 31),
|
FechaFin = new DateTime(2026, 7, 31),
|
||||||
ProfesorRun = "12345678-9"
|
ProfesorRun = "15668563-1"
|
||||||
},
|
},
|
||||||
new CursoAbierto
|
new CursoAbierto
|
||||||
{
|
{
|
||||||
IdCursoAbierto = 2,
|
IdCursoAbierto = 16493,
|
||||||
IdCursos = 2,
|
IdCursos = 16493,
|
||||||
Sala = "Sala 202",
|
Sala = "Sala 202",
|
||||||
Sede = "Las Condes",
|
Sede = "Las Condes",
|
||||||
HoraInicio = "14:00",
|
HoraInicio = "14:00",
|
||||||
HoraFin = "15:30",
|
HoraFin = "15:30",
|
||||||
FechaInicio = new DateTime(2026, 3, 1),
|
FechaInicio = new DateTime(2026, 3, 1),
|
||||||
FechaTermino = new DateTime(2026, 7, 31),
|
FechaFin = new DateTime(2026, 7, 31),
|
||||||
ProfesorRun = "12345678-9"
|
ProfesorRun = "15668563-1"
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -107,32 +107,29 @@ public class AppDbContext : DbContext
|
|||||||
new DetalleContrato
|
new DetalleContrato
|
||||||
{
|
{
|
||||||
IdDetalleContrato = 1,
|
IdDetalleContrato = 1,
|
||||||
IdCursoAbierto = 1,
|
IdCursoAbierto = 16451,
|
||||||
|
IdAlumno = "11111111-1",
|
||||||
AP_Paterno = "Garcia",
|
AP_Paterno = "Garcia",
|
||||||
AP_Materno = "Lopez",
|
AP_Materno = "Lopez",
|
||||||
Nombres = "Maria",
|
Nombres = "Maria"
|
||||||
Email = "maria.garcia@email.com",
|
|
||||||
Telefono = "+56998765432"
|
|
||||||
},
|
},
|
||||||
new DetalleContrato
|
new DetalleContrato
|
||||||
{
|
{
|
||||||
IdDetalleContrato = 2,
|
IdDetalleContrato = 2,
|
||||||
IdCursoAbierto = 1,
|
IdCursoAbierto = 16451,
|
||||||
|
IdAlumno = "22222222-2",
|
||||||
AP_Paterno = "Rodriguez",
|
AP_Paterno = "Rodriguez",
|
||||||
AP_Materno = "Soto",
|
AP_Materno = "Soto",
|
||||||
Nombres = "Carlos",
|
Nombres = "Carlos"
|
||||||
Email = "carlos.rodriguez@email.com",
|
|
||||||
Telefono = "+56987654321"
|
|
||||||
},
|
},
|
||||||
new DetalleContrato
|
new DetalleContrato
|
||||||
{
|
{
|
||||||
IdDetalleContrato = 3,
|
IdDetalleContrato = 3,
|
||||||
IdCursoAbierto = 2,
|
IdCursoAbierto = 16493,
|
||||||
|
IdAlumno = "33333333-3",
|
||||||
AP_Paterno = "Martinez",
|
AP_Paterno = "Martinez",
|
||||||
AP_Materno = "Fernandez",
|
AP_Materno = "Fernandez",
|
||||||
Nombres = "Ana",
|
Nombres = "Ana"
|
||||||
Email = "ana.martinez@email.com",
|
|
||||||
Telefono = "+56976543210"
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public class AsistenciaRepository
|
|||||||
var sesion = await _context.AsistenciasProfesor.FindAsync(idSesion);
|
var sesion = await _context.AsistenciasProfesor.FindAsync(idSesion);
|
||||||
if (sesion == null) return false;
|
if (sesion == null) return false;
|
||||||
|
|
||||||
sesion.HoraFin = horaFin;
|
sesion.HoraSalida = horaFin;
|
||||||
sesion.Estado = "Finalizada";
|
sesion.Estado = "Finalizada";
|
||||||
await _context.SaveChangesAsync();
|
await _context.SaveChangesAsync();
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace Asistencia.Models;
|
|||||||
public class AsistenciaProfesor
|
public class AsistenciaProfesor
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
public int Id { get; set; }
|
public int IdAsistenciaProfesor { get; set; }
|
||||||
|
|
||||||
public int IdCursoAbierto { get; set; }
|
public int IdCursoAbierto { get; set; }
|
||||||
|
|
||||||
@@ -18,12 +18,12 @@ public class AsistenciaProfesor
|
|||||||
public string HoraInicio { get; set; } = string.Empty;
|
public string HoraInicio { get; set; } = string.Empty;
|
||||||
|
|
||||||
[MaxLength(10)]
|
[MaxLength(10)]
|
||||||
public string HoraFin { get; set; } = string.Empty;
|
public string HoraSalida { get; set; } = string.Empty;
|
||||||
|
|
||||||
[MaxLength(20)]
|
[MaxLength(20)]
|
||||||
public string Estado { get; set; } = "Activa";
|
public string Estado { get; set; } = "Activa";
|
||||||
|
|
||||||
public bool Temporal { get; set; }
|
public int Temporal { get; set; }
|
||||||
|
|
||||||
public CursoAbierto? CursoAbierto { get; set; }
|
public CursoAbierto? CursoAbierto { get; set; }
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,7 @@ public class CursoAbierto
|
|||||||
|
|
||||||
public DateTime FechaInicio { get; set; }
|
public DateTime FechaInicio { get; set; }
|
||||||
|
|
||||||
public DateTime FechaTermino { get; set; }
|
public DateTime FechaFin { get; set; }
|
||||||
|
|
||||||
[MaxLength(20)]
|
[MaxLength(20)]
|
||||||
public string ProfesorRun { get; set; } = string.Empty;
|
public string ProfesorRun { get; set; } = string.Empty;
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ public class DetalleContrato
|
|||||||
|
|
||||||
public int IdCursoAbierto { get; set; }
|
public int IdCursoAbierto { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(30)]
|
||||||
|
public string IdAlumno { get; set; } = string.Empty;
|
||||||
|
|
||||||
[MaxLength(100)]
|
[MaxLength(100)]
|
||||||
public string AP_Paterno { get; set; } = string.Empty;
|
public string AP_Paterno { get; set; } = string.Empty;
|
||||||
|
|
||||||
@@ -18,12 +21,6 @@ public class DetalleContrato
|
|||||||
[MaxLength(100)]
|
[MaxLength(100)]
|
||||||
public string Nombres { get; set; } = string.Empty;
|
public string Nombres { get; set; } = string.Empty;
|
||||||
|
|
||||||
[MaxLength(200)]
|
|
||||||
public string Email { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
[MaxLength(20)]
|
|
||||||
public string Telefono { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
public CursoAbierto? CursoAbierto { get; set; }
|
public CursoAbierto? CursoAbierto { get; set; }
|
||||||
|
|
||||||
public string NombreCompleto => $"{Nombres} {AP_Paterno} {AP_Materno}".Trim();
|
public string NombreCompleto => $"{Nombres} {AP_Paterno} {AP_Materno}".Trim();
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ public class Profesor
|
|||||||
public string Nombre { get; set; } = string.Empty;
|
public string Nombre { get; set; } = string.Empty;
|
||||||
|
|
||||||
[MaxLength(100)]
|
[MaxLength(100)]
|
||||||
public string Paterno { get; set; } = string.Empty;
|
public string ApPaterno { get; set; } = string.Empty;
|
||||||
|
|
||||||
[MaxLength(100)]
|
[MaxLength(100)]
|
||||||
public string Materno { get; set; } = string.Empty;
|
public string ApMaterno { get; set; } = string.Empty;
|
||||||
|
|
||||||
[MaxLength(200)]
|
[MaxLength(200)]
|
||||||
public string Email { get; set; } = string.Empty;
|
public string Email { get; set; } = string.Empty;
|
||||||
@@ -31,5 +31,7 @@ public class Profesor
|
|||||||
|
|
||||||
public bool CrearClave { get; set; }
|
public bool CrearClave { get; set; }
|
||||||
|
|
||||||
public string NombreCompleto => $"{Nombre} {Paterno} {Materno}".Trim();
|
public bool Activo { get; set; } = true;
|
||||||
|
|
||||||
|
public string NombreCompleto => $"{Nombre} {ApPaterno} {ApMaterno}".Trim();
|
||||||
}
|
}
|
||||||
@@ -17,21 +17,14 @@ public class AuthService
|
|||||||
|
|
||||||
public async Task<(bool Success, string Message)> LoginAsync(string rut, string password)
|
public async Task<(bool Success, string Message)> LoginAsync(string rut, string password)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(rut) || string.IsNullOrWhiteSpace(password))
|
if (string.IsNullOrWhiteSpace(rut))
|
||||||
return (false, "Ingrese usuario y contraseña");
|
return (false, "Ingrese su RUT");
|
||||||
|
|
||||||
var profesor = await _profesorRepo.BuscarPorRutAsync(rut);
|
var profesor = await _profesorRepo.BuscarPorRutAsync(rut);
|
||||||
if (profesor == null)
|
if (profesor == null)
|
||||||
return (false, "Usuario no encontrado");
|
return (false, "Usuario no encontrado");
|
||||||
|
|
||||||
if (profesor.CrearClave)
|
_currentUser = profesor;
|
||||||
return (false, "Debe crear su contraseña primero");
|
|
||||||
|
|
||||||
var authenticated = await _profesorRepo.AutenticarAsync(rut, password);
|
|
||||||
if (authenticated == null)
|
|
||||||
return (false, "Contraseña incorrecta");
|
|
||||||
|
|
||||||
_currentUser = authenticated;
|
|
||||||
return (true, "Inicio de sesión exitoso");
|
return (true, "Inicio de sesión exitoso");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using System.Net.NetworkInformation;
|
||||||
|
|
||||||
|
namespace Asistencia.Services;
|
||||||
|
|
||||||
|
public class ConnectivityService
|
||||||
|
{
|
||||||
|
public async Task<bool> HayConexionAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var ping = new Ping();
|
||||||
|
var reply = await ping.SendPingAsync("8.8.8.8", 3000);
|
||||||
|
return reply.Status == IPStatus.Success;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Linq;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Templates;
|
using Avalonia.Controls.Templates;
|
||||||
using Asistencia.ViewModels;
|
using Asistencia.ViewModels;
|
||||||
|
|
||||||
namespace Asistencia;
|
namespace Asistencia;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Given a view model, returns the corresponding view if possible.
|
|
||||||
/// </summary>
|
|
||||||
[RequiresUnreferencedCode(
|
[RequiresUnreferencedCode(
|
||||||
"Default implementation of ViewLocator involves reflection which may be trimmed away.",
|
"Default implementation of ViewLocator involves reflection which may be trimmed away.",
|
||||||
Url = "https://docs.avaloniaui.net/docs/concepts/view-locator")]
|
Url = "https://docs.avaloniaui.net/docs/concepts/view-locator")]
|
||||||
@@ -18,15 +16,17 @@ public class ViewLocator : IDataTemplate
|
|||||||
{
|
{
|
||||||
if (param is null)
|
if (param is null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal);
|
var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal);
|
||||||
var type = Type.GetType(name);
|
var type = AppDomain.CurrentDomain.GetAssemblies()
|
||||||
|
.Select(a => a.GetType(name))
|
||||||
|
.FirstOrDefault(t => t != null);
|
||||||
|
|
||||||
if (type != null)
|
if (type != null)
|
||||||
{
|
{
|
||||||
return (Control)Activator.CreateInstance(type)!;
|
return (Control)Activator.CreateInstance(type)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TextBlock { Text = "Not Found: " + name };
|
return new TextBlock { Text = "Not Found: " + name };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using System.Collections.ObjectModel;
|
|||||||
|
|
||||||
namespace Asistencia.ViewModels;
|
namespace Asistencia.ViewModels;
|
||||||
|
|
||||||
public partial class AsistenciaViewModel : ObservableObject
|
public partial class AsistenciaViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
private readonly AsistenciaService _asistenciaService;
|
private readonly AsistenciaService _asistenciaService;
|
||||||
private readonly AuthService _authService;
|
private readonly AuthService _authService;
|
||||||
@@ -91,7 +91,7 @@ public partial class AsistenciaViewModel : ObservableObject
|
|||||||
var sesion = await _asistenciaService.BuscarSesionActivaAsync(_curso.IdCursoAbierto);
|
var sesion = await _asistenciaService.BuscarSesionActivaAsync(_curso.IdCursoAbierto);
|
||||||
if (sesion != null)
|
if (sesion != null)
|
||||||
{
|
{
|
||||||
await _asistenciaService.FinalizarSesionAsync(sesion.Id);
|
await _asistenciaService.FinalizarSesionAsync(sesion.IdAsistenciaProfesor);
|
||||||
}
|
}
|
||||||
EnSesion = false;
|
EnSesion = false;
|
||||||
MensajeEstado = "Sesion finalizada";
|
MensajeEstado = "Sesion finalizada";
|
||||||
@@ -121,7 +121,7 @@ public partial class AsistenciaViewModel : ObservableObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class AlumnoAsistenciaViewModel : ObservableObject
|
public partial class AlumnoAsistenciaViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
public int IdDetalleContrato { get; }
|
public int IdDetalleContrato { get; }
|
||||||
public string NombreCompleto { get; }
|
public string NombreCompleto { get; }
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using System.Collections.ObjectModel;
|
|||||||
|
|
||||||
namespace Asistencia.ViewModels;
|
namespace Asistencia.ViewModels;
|
||||||
|
|
||||||
public partial class DashboardViewModel : ObservableObject
|
public partial class DashboardViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
private readonly AuthService _authService;
|
private readonly AuthService _authService;
|
||||||
private readonly AsistenciaService _asistenciaService;
|
private readonly AsistenciaService _asistenciaService;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using Asistencia.Services;
|
|||||||
|
|
||||||
namespace Asistencia.ViewModels;
|
namespace Asistencia.ViewModels;
|
||||||
|
|
||||||
public partial class LoginViewModel : ObservableObject
|
public partial class LoginViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
private readonly AuthService _authService;
|
private readonly AuthService _authService;
|
||||||
private readonly MainWindowViewModel _mainVm;
|
private readonly MainWindowViewModel _mainVm;
|
||||||
|
|||||||
@@ -8,26 +8,51 @@ using System.Collections.ObjectModel;
|
|||||||
|
|
||||||
namespace Asistencia.ViewModels;
|
namespace Asistencia.ViewModels;
|
||||||
|
|
||||||
public partial class MainWindowViewModel : ObservableObject
|
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 object? _currentView;
|
private object? _currentView;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private string _currentViewTitle = "Login";
|
private string _currentViewTitle = "Login";
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool _conexionDisponible;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _mensajeConexion = string.Empty;
|
||||||
|
|
||||||
public object? CurrentView
|
public object? CurrentView
|
||||||
{
|
{
|
||||||
get => _currentView;
|
get => _currentView;
|
||||||
set => SetProperty(ref _currentView, value);
|
set => SetProperty(ref _currentView, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MainWindowViewModel(AuthService authService, AsistenciaService asistenciaService)
|
public MainWindowViewModel(AuthService authService, AsistenciaService asistenciaService, ConnectivityService connectivityService)
|
||||||
{
|
{
|
||||||
_authService = authService;
|
_authService = authService;
|
||||||
_asistenciaService = asistenciaService;
|
_asistenciaService = asistenciaService;
|
||||||
CurrentView = new LoginViewModel(authService, this);
|
_connectivityService = connectivityService;
|
||||||
|
_ = VerificarConexionAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task VerificarConexionAsync()
|
||||||
|
{
|
||||||
|
var hayInternet = await _connectivityService.HayConexionAsync();
|
||||||
|
ConexionDisponible = hayInternet;
|
||||||
|
|
||||||
|
if (hayInternet)
|
||||||
|
{
|
||||||
|
MensajeConexion = "Aplicación no disponible con conexión a internet. Desconéctese para usar el sistema.";
|
||||||
|
CurrentView = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MensajeConexion = "Modo offline — Using local database";
|
||||||
|
CurrentView = new LoginViewModel(_authService, this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void NavigateToLogin()
|
public void NavigateToLogin()
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using Asistencia.Services;
|
|||||||
|
|
||||||
namespace Asistencia.ViewModels;
|
namespace Asistencia.ViewModels;
|
||||||
|
|
||||||
public partial class PerfilViewModel : ObservableObject
|
public partial class PerfilViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
private readonly AuthService _authService;
|
private readonly AuthService _authService;
|
||||||
private readonly MainWindowViewModel _mainVm;
|
private readonly MainWindowViewModel _mainVm;
|
||||||
|
|||||||
@@ -20,24 +20,17 @@
|
|||||||
Foreground="{DynamicResource PrimaryNavy}"
|
Foreground="{DynamicResource PrimaryNavy}"
|
||||||
HorizontalAlignment="Center" />
|
HorizontalAlignment="Center" />
|
||||||
|
|
||||||
<TextBlock Text="Inicie sesion con su cuenta"
|
<TextBlock Text="Modo offline — Ingrese su RUT"
|
||||||
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 Watermark="Ej: 12345678-9"
|
<TextBox PlaceholderText="Ej: 12345678-9"
|
||||||
Text="{Binding Rut}"
|
Text="{Binding Rut}"
|
||||||
FontSize="14" Margin="0,0,0,8" />
|
|
||||||
|
|
||||||
<TextBlock Text="Contrasena" FontSize="13" FontWeight="SemiBold"
|
|
||||||
Foreground="{DynamicResource TextPrimary}" />
|
|
||||||
<TextBox Watermark="Ingrese su contrasena"
|
|
||||||
Text="{Binding Password}"
|
|
||||||
PasswordChar="*"
|
|
||||||
FontSize="14" Margin="0,0,0,16" />
|
FontSize="14" Margin="0,0,0,16" />
|
||||||
|
|
||||||
<Button Content="Iniciar Sesion"
|
<Button Content="Ingresar"
|
||||||
Command="{Binding LoginCommand}"
|
Command="{Binding LoginCommand}"
|
||||||
Classes="primary"
|
Classes="primary"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
|
|||||||
@@ -17,7 +17,24 @@
|
|||||||
<vm:MainWindowViewModel />
|
<vm:MainWindowViewModel />
|
||||||
</Design.DataContext>
|
</Design.DataContext>
|
||||||
|
|
||||||
<Panel>
|
<Panel Background="{DynamicResource BackgroundSecondary}">
|
||||||
<ContentControl Content="{Binding CurrentView}" />
|
<ContentControl Content="{Binding CurrentView}" />
|
||||||
|
|
||||||
|
<Border IsVisible="{Binding ConexionDisponible}"
|
||||||
|
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||||
|
CornerRadius="16" Padding="48" Width="420"
|
||||||
|
Background="#FFF3CD" BorderBrush="#FFC107" BorderThickness="1">
|
||||||
|
<StackPanel Spacing="16" HorizontalAlignment="Center">
|
||||||
|
<TextBlock Text="Sin acceso al sistema"
|
||||||
|
FontSize="24" FontWeight="Bold"
|
||||||
|
Foreground="#856404"
|
||||||
|
HorizontalAlignment="Center" />
|
||||||
|
<TextBlock Text="{Binding MensajeConexion}"
|
||||||
|
FontSize="14" TextWrapping="Wrap"
|
||||||
|
Foreground="#856404"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
TextAlignment="Center" />
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
</Panel>
|
</Panel>
|
||||||
</Window>
|
</Window>
|
||||||
Reference in new issue
Block a user