diff --git a/Controllers/AccountController.cs b/Controllers/AccountController.cs index 7e828b0..66dc79b 100644 --- a/Controllers/AccountController.cs +++ b/Controllers/AccountController.cs @@ -67,7 +67,7 @@ namespace vita_asistente.Controllers // GET: /Account/Login [HttpGet] - public IActionResult Login(string returnUrl = null) + public IActionResult Login(string? returnUrl = null) { ViewData["ReturnUrl"] = returnUrl; return View(); @@ -76,7 +76,7 @@ namespace vita_asistente.Controllers // POST: /Account/Login [HttpPost] [ValidateAntiForgeryToken] - public async Task Login(LoginViewModel model, string returnUrl = null) + public async Task Login(LoginViewModel model, string? returnUrl = null) { ViewData["ReturnUrl"] = returnUrl; @@ -90,7 +90,7 @@ namespace vita_asistente.Controllers if (result.Succeeded) { - return RedirectToLocal(returnUrl); + return RedirectToLocal(!string.IsNullOrEmpty(returnUrl) ? returnUrl : string.Empty); } if (result.RequiresTwoFactor) { @@ -143,7 +143,7 @@ namespace vita_asistente.Controllers // GET: /Account/LoginWith2fa (opcional) [HttpGet] - public IActionResult LoginWith2fa(bool rememberMe, string returnUrl = null) + public IActionResult LoginWith2fa(bool rememberMe, string? returnUrl = null) { // Implementar si se usa 2FA return View(); diff --git a/Controllers/PacientesController.cs b/Controllers/PacientesController.cs new file mode 100644 index 0000000..38e47cd --- /dev/null +++ b/Controllers/PacientesController.cs @@ -0,0 +1,62 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using System.Linq; +using System.Threading.Tasks; +using vita_asistente.Data; +using vita_asistente.Data.Models; + +namespace vita_asistente.Controllers +{ + [Authorize] + public class PacientesController : Controller + { + private readonly ApplicationDbContext _context; + + public PacientesController(ApplicationDbContext context) + { + _context = context; + } + + // GET: Pacientes + public async Task Index(string nombreBusqueda) + { + var pacientes = _context.Pacientes.AsNoTracking(); + + if (!string.IsNullOrWhiteSpace(nombreBusqueda)) + { + pacientes = pacientes.Where(p => + (p.Nombre + " " + p.Apellido).Contains(nombreBusqueda.Trim()) || + p.Documento.Contains(nombreBusqueda.Trim())); + } + + ViewBag.NombreBusqueda = nombreBusqueda; + return View(await pacientes.OrderByDescending(p => p.FechaRegistro).ToListAsync()); + } + + // GET: Pacientes/Details/5 + public async Task Details(string id) + { + if (id == null) return NotFound(); + var paciente = await _context.Pacientes.FindAsync(id); + if (paciente == null) return NotFound(); + return View(paciente); + } + + // POST: Pacientes/Activate/5 + [HttpPost] + [Authorize(Roles = "Admin")] + [ValidateAntiForgeryToken] + public async Task Activate(string id) + { + var paciente = await _context.Pacientes.FindAsync(id); + if (paciente == null) return NotFound(); + + paciente.IsActive = true; + _context.Pacientes.Update(paciente); + await _context.SaveChangesAsync(); + + return RedirectToAction(nameof(Index)); + } + } +} \ No newline at end of file diff --git a/Controllers/RolesController.cs b/Controllers/RolesController.cs index ee9bd6f..3eb4092 100644 --- a/Controllers/RolesController.cs +++ b/Controllers/RolesController.cs @@ -117,7 +117,7 @@ namespace vita_asistente.Controllers // Pero primero verificamos si tiene usuarios asignados using var scope = HttpContext.RequestServices.CreateScope(); var userManager = scope.ServiceProvider.GetRequiredService>(); - var usersInRole = await userManager.GetUsersInRoleAsync(role.Name); + var usersInRole = await userManager.GetUsersInRoleAsync(role.Name ?? string.Empty); if (usersInRole.Any()) { @@ -157,7 +157,7 @@ namespace vita_asistente.Controllers // Verificar que no tenga usuarios asignados using var scope = HttpContext.RequestServices.CreateScope(); var userManager = scope.ServiceProvider.GetRequiredService>(); - var usersInRole = await userManager.GetUsersInRoleAsync(role.Name); + var usersInRole = await userManager.GetUsersInRoleAsync(role.Name ?? string.Empty); if (usersInRole.Any()) { diff --git a/Controllers/UsuariosController.cs b/Controllers/UsuariosController.cs index f4544f1..a33a7fa 100644 --- a/Controllers/UsuariosController.cs +++ b/Controllers/UsuariosController.cs @@ -167,8 +167,8 @@ namespace vita_asistente.Controllers RolesDisponibles = todosLosRoles.Select(r => new RoleCheckbox { RoleId = r.Id, - RoleName = r.Name, - IsSelected = rolesDelUsuario.Contains(r.Name) + RoleName = r.Name ?? string.Empty, + IsSelected = rolesDelUsuario.Contains(r.Name ?? string.Empty) }).ToList() }; return View(model); @@ -183,7 +183,7 @@ namespace vita_asistente.Controllers if (usuario == null) return NotFound(); var rolesDelUsuario = await _userManager.GetRolesAsync(usuario); - var rolesSeleccionados = model.RolesDisponibles.Where(r => r.IsSelected).Select(r => r.RoleName).ToList(); + var rolesSeleccionados = model.RolesDisponibles.Where(r => r.IsSelected).Where(r => !string.IsNullOrEmpty(r.RoleName)).Select(r => r.RoleName).ToList(); // Remover roles que ya no están seleccionados var rolesAEliminar = rolesDelUsuario.Except(rolesSeleccionados).ToList(); @@ -206,15 +206,15 @@ namespace vita_asistente.Controllers // ViewModels para la gestión de roles (dentro del mismo archivo por simplicidad) public class ManageRolesViewModel { - public string UsuarioId { get; set; } - public string UsuarioNombre { get; set; } - public List RolesDisponibles { get; set; } + public required string UsuarioId { get; set; } + public required string UsuarioNombre { get; set; } + public required List RolesDisponibles { get; set; } } - public class RoleCheckbox +public class RoleCheckbox { - public string RoleId { get; set; } - public string RoleName { get; set; } + public required string RoleId { get; set; } + public required string RoleName { get; set; } public bool IsSelected { get; set; } } } diff --git a/Data/ApplicationDbContext.cs b/Data/ApplicationDbContext.cs index 467940a..fbd9369 100644 --- a/Data/ApplicationDbContext.cs +++ b/Data/ApplicationDbContext.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; +using vita_asistente.Data.Models; using vita_asistente.Models; namespace vita_asistente.Data @@ -10,5 +11,18 @@ namespace vita_asistente.Data : base(options) { } + + // DbSet for Paciente model + public DbSet Pacientes { get; set; } + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + + builder.Entity().ToTable("AspNetUsers"); + builder.Entity() + .ToTable("Pacientes") + .HasBaseType(); + } } } diff --git a/Data/Models/Paciente.cs b/Data/Models/Paciente.cs new file mode 100644 index 0000000..b4c7eb6 --- /dev/null +++ b/Data/Models/Paciente.cs @@ -0,0 +1,30 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using vita_asistente.Models; + +namespace vita_asistente.Data.Models +{ + public class Paciente : ApplicationUser + { + [StringLength(100)] + public string NombreContactoEmergencia { get; set; } = string.Empty; + + [StringLength(50)] + public string TelefonoContactoEmergencia { get; set; } = string.Empty; + + [StringLength(50)] + public string TipoSangre { get; set; } = string.Empty; + + public bool TieneAlergiasMedicamentosas { get; set; } + + [StringLength(500)] + public string AlergiasDescripcion { get; set; } = string.Empty; + + public DateTime FechaRegistro { get; set; } + + /// + /// Indicates whether the patient account is active and can log in + /// + public bool IsActive { get; set; } = true; // Default to active + } +} \ No newline at end of file diff --git a/Migrations/20260810173940_InitialCreate.Designer.cs b/Migrations/20260811005032_InitialCreate.Designer.cs similarity index 85% rename from Migrations/20260810173940_InitialCreate.Designer.cs rename to Migrations/20260811005032_InitialCreate.Designer.cs index 7359f32..dc75706 100644 --- a/Migrations/20260810173940_InitialCreate.Designer.cs +++ b/Migrations/20260811005032_InitialCreate.Designer.cs @@ -12,7 +12,7 @@ using vita_asistente.Data; namespace vita_asistente.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20260810173940_InitialCreate")] + [Migration("20260811005032_InitialCreate")] partial class InitialCreate { /// @@ -239,6 +239,41 @@ namespace vita_asistente.Migrations .HasDatabaseName("UserNameIndex"); b.ToTable("AspNetUsers", (string)null); + + b.UseTptMappingStrategy(); + }); + + modelBuilder.Entity("vita_asistente.Data.Models.Paciente", b => + { + b.HasBaseType("vita_asistente.Models.ApplicationUser"); + + b.Property("AlergiasDescripcion") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("FechaRegistro") + .HasColumnType("datetime(6)"); + + b.Property("NombreContactoEmergencia") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("TelefonoContactoEmergencia") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("TieneAlergiasMedicamentosas") + .HasColumnType("tinyint(1)"); + + b.Property("TipoSangre") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.ToTable("Pacientes", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => @@ -291,6 +326,15 @@ namespace vita_asistente.Migrations .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); + + modelBuilder.Entity("vita_asistente.Data.Models.Paciente", b => + { + b.HasOne("vita_asistente.Models.ApplicationUser", null) + .WithOne() + .HasForeignKey("vita_asistente.Data.Models.Paciente", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); #pragma warning restore 612, 618 } } diff --git a/Migrations/20260810173940_InitialCreate.cs b/Migrations/20260811005032_InitialCreate.cs similarity index 87% rename from Migrations/20260810173940_InitialCreate.cs rename to Migrations/20260811005032_InitialCreate.cs index e015ebb..e85cf8b 100644 --- a/Migrations/20260810173940_InitialCreate.cs +++ b/Migrations/20260811005032_InitialCreate.cs @@ -206,6 +206,35 @@ namespace vita_asistente.Migrations }) .Annotation("MySql:CharSet", "utf8mb4"); + migrationBuilder.CreateTable( + name: "Pacientes", + columns: table => new + { + Id = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + NombreContactoEmergencia = table.Column(type: "varchar(100)", maxLength: 100, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + TelefonoContactoEmergencia = table.Column(type: "varchar(50)", maxLength: 50, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + TipoSangre = table.Column(type: "varchar(50)", maxLength: 50, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + TieneAlergiasMedicamentosas = table.Column(type: "tinyint(1)", nullable: false), + AlergiasDescripcion = table.Column(type: "varchar(500)", maxLength: 500, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + FechaRegistro = table.Column(type: "datetime(6)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Pacientes", x => x.Id); + table.ForeignKey( + name: "FK_Pacientes_AspNetUsers_Id", + column: x => x.Id, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + migrationBuilder.CreateIndex( name: "IX_AspNetRoleClaims_RoleId", table: "AspNetRoleClaims", @@ -262,6 +291,9 @@ namespace vita_asistente.Migrations migrationBuilder.DropTable( name: "AspNetUserTokens"); + migrationBuilder.DropTable( + name: "Pacientes"); + migrationBuilder.DropTable( name: "AspNetRoles"); diff --git a/Migrations/20260811012627_AddIsActiveColumnToPacientes.Designer.cs b/Migrations/20260811012627_AddIsActiveColumnToPacientes.Designer.cs new file mode 100644 index 0000000..bc1fa2a --- /dev/null +++ b/Migrations/20260811012627_AddIsActiveColumnToPacientes.Designer.cs @@ -0,0 +1,344 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using vita_asistente.Data; + +#nullable disable + +namespace vita_asistente.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20260811012627_AddIsActiveColumnToPacientes")] + partial class AddIsActiveColumnToPacientes + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.29") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("RoleId") + .HasColumnType("varchar(255)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("vita_asistente.Models.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Apellido") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Direccion") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Documento") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("Nombre") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("RolPrincipal") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + + b.UseTptMappingStrategy(); + }); + + modelBuilder.Entity("vita_asistente.Data.Models.Paciente", b => + { + b.HasBaseType("vita_asistente.Models.ApplicationUser"); + + b.Property("AlergiasDescripcion") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("FechaRegistro") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("NombreContactoEmergencia") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("TelefonoContactoEmergencia") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("TieneAlergiasMedicamentosas") + .HasColumnType("tinyint(1)"); + + b.Property("TipoSangre") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.ToTable("Pacientes", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("vita_asistente.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("vita_asistente.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("vita_asistente.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("vita_asistente.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("vita_asistente.Data.Models.Paciente", b => + { + b.HasOne("vita_asistente.Models.ApplicationUser", null) + .WithOne() + .HasForeignKey("vita_asistente.Data.Models.Paciente", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/20260811012627_AddIsActiveColumnToPacientes.cs b/Migrations/20260811012627_AddIsActiveColumnToPacientes.cs new file mode 100644 index 0000000..349ebf0 --- /dev/null +++ b/Migrations/20260811012627_AddIsActiveColumnToPacientes.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace vita_asistente.Migrations +{ + /// + public partial class AddIsActiveColumnToPacientes : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "IsActive", + table: "Pacientes", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "IsActive", + table: "Pacientes"); + } + } +} diff --git a/Migrations/ApplicationDbContextModelSnapshot.cs b/Migrations/ApplicationDbContextModelSnapshot.cs index 783e42e..2da3688 100644 --- a/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/Migrations/ApplicationDbContextModelSnapshot.cs @@ -236,6 +236,44 @@ namespace vita_asistente.Migrations .HasDatabaseName("UserNameIndex"); b.ToTable("AspNetUsers", (string)null); + + b.UseTptMappingStrategy(); + }); + + modelBuilder.Entity("vita_asistente.Data.Models.Paciente", b => + { + b.HasBaseType("vita_asistente.Models.ApplicationUser"); + + b.Property("AlergiasDescripcion") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("FechaRegistro") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("NombreContactoEmergencia") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("TelefonoContactoEmergencia") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("TieneAlergiasMedicamentosas") + .HasColumnType("tinyint(1)"); + + b.Property("TipoSangre") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.ToTable("Pacientes", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => @@ -288,6 +326,15 @@ namespace vita_asistente.Migrations .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); + + modelBuilder.Entity("vita_asistente.Data.Models.Paciente", b => + { + b.HasOne("vita_asistente.Models.ApplicationUser", null) + .WithOne() + .HasForeignKey("vita_asistente.Data.Models.Paciente", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); #pragma warning restore 612, 618 } } diff --git a/ViewModels/LoginViewModel.cs b/ViewModels/LoginViewModel.cs index 41a19d2..4a10b18 100644 --- a/ViewModels/LoginViewModel.cs +++ b/ViewModels/LoginViewModel.cs @@ -7,12 +7,12 @@ namespace vita_asistente.ViewModels [Required] [EmailAddress] [Display(Name = "Correo electrónico")] - public string Email { get; set; } + public required string Email { get; set; } [Required] [DataType(DataType.Password)] [Display(Name = "Contraseña")] - public string Password { get; set; } + public required string Password { get; set; } [Display(Name = "Recordarme")] public bool RememberMe { get; set; } diff --git a/ViewModels/RegisterViewModel.cs b/ViewModels/RegisterViewModel.cs index f6a507d..1bdae08 100644 --- a/ViewModels/RegisterViewModel.cs +++ b/ViewModels/RegisterViewModel.cs @@ -6,37 +6,37 @@ namespace vita_asistente.ViewModels { [Required] [Display(Name = "Nombre")] - public string Nombre { get; set; } + public required string Nombre { get; set; } [Required] [Display(Name = "Apellido")] - public string Apellido { get; set; } + public required string Apellido { get; set; } [Required] [Display(Name = "Documento")] - public string Documento { get; set; } + public required string Documento { get; set; } [Required] [Display(Name = "Dirección")] - public string Direccion { get; set; } + public required string Direccion { get; set; } [Required] [Display(Name = "Teléfono")] - public string Telefono { get; set; } // puedes usar PhoneNumber de Identity también + public required string Telefono { get; set; } // puedes usar PhoneNumber de Identity también [Required] [EmailAddress] [Display(Name = "Correo electrónico")] - public string Email { get; set; } + public required string Email { get; set; } [Required] [DataType(DataType.Password)] [Display(Name = "Contraseña")] - public string Password { get; set; } + public required string Password { get; set; } [DataType(DataType.Password)] [Display(Name = "Confirmar contraseña")] [Compare("Password", ErrorMessage = "Las contraseñas no coinciden")] - public string ConfirmPassword { get; set; } + public required string ConfirmPassword { get; set; } } } diff --git a/Views/Pacientes/Index.cshtml b/Views/Pacientes/Index.cshtml new file mode 100644 index 0000000..c2bfc40 --- /dev/null +++ b/Views/Pacientes/Index.cshtml @@ -0,0 +1,88 @@ +@model List + +@{ + ViewData["Title"] = "Pacientes"; + Layout = "_Layout"; +} + +
+

Lista de Pacientes

+ + @if (User.IsInRole("Admin")) + { + Nuevo Paciente + } + +
+
+
+
+ + +
+
+ + @if (!string.IsNullOrEmpty(ViewBag.NombreBusqueda)) + { + Limpiar + } +
+
+ + + + + + + + + + + + + + @foreach (var paciente in Model) + { + + + + + + + + + } + +
DocumentoNombre CompletoEmailFecha RegistroEstadoAcciones
@Html.DisplayFor(modelItem => paciente.Documento)@Html.DisplayFor(modelItem => paciente.Nombre) @Html.DisplayFor(modelItem => paciente.Apellido)@Html.DisplayFor(modelItem => paciente.Email)@Html.DisplayFor(modelItem => paciente.FechaRegistro.ToShortDateString()) + @if (paciente.IsActive) + { + Activo + } + else + { + Inactivo + } + + @if (User.IsInRole("Admin") || (User.Identity != null && User.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier")?.Value == paciente.Id)) + { + Ver + @if (User.IsInRole("Admin")) + { + Editar + @if (!paciente.IsActive) + { +
+ +
+ } + else + { + Desactivar + } + } + } +
+
+
+
\ No newline at end of file diff --git a/Views/Roles/Disable.cshtml b/Views/Roles/Disable.cshtml index 63a7e88..c5b1088 100644 --- a/Views/Roles/Disable.cshtml +++ b/Views/Roles/Disable.cshtml @@ -1,3 +1,4 @@ +@using Microsoft.AspNetCore.Identity @model IdentityRole @{ @@ -8,6 +9,23 @@

¿Está seguro que desea deshabilitar este rol? Esto afectará a los usuarios con este rol.

+
+ + @Html.AntiForgeryToken() +
+ + Cancelar +
+
+ +@{ + ViewData["Title"] = "Deshabilitar rol"; +} + +

Deshabilitar rol: @Model.Name

+ +

¿Está seguro que desea deshabilitar este rol? Esto afectará a los usuarios con este rol.

+
@Html.AntiForgeryToken() diff --git a/Views/Roles/Edit.cshtml b/Views/Roles/Edit.cshtml index 7998d19..437908b 100644 --- a/Views/Roles/Edit.cshtml +++ b/Views/Roles/Edit.cshtml @@ -1,3 +1,4 @@ +@using Microsoft.AspNetCore.Identity @model IdentityRole @{ @@ -19,6 +20,29 @@
+section scripts { + @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} +} + +@{ + ViewData["Title"] = "Editar rol"; +} + +

Editar rol: @Model.Name

+ +
+ +
+ + + +
+
+ + Cancelar +
+
+ section scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} } \ No newline at end of file diff --git a/Views/Roles/Index.cshtml b/Views/Roles/Index.cshtml index 1d6d4ce..bbf51f9 100644 --- a/Views/Roles/Index.cshtml +++ b/Views/Roles/Index.cshtml @@ -2,7 +2,30 @@ @model IEnumerable

Roles

-

Crear nuevo rol

+ + + + +

Crear nuevo rol

@@ -13,19 +36,19 @@
NombreAcciones
Editar - +