Modulos Pacientes Listo
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
@model vita_asistente.Models.Pacientes
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Crear Paciente";
|
||||
Layout = "_Layout";
|
||||
}
|
||||
|
||||
<div class="container mt-4">
|
||||
<h2>Crear Nuevo Paciente</h2>
|
||||
|
||||
<form asp-action="Create" method="post" class="mt-4">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label asp-for="DocumentNumber" class="col-sm-2 col-form-label"></label>
|
||||
<div class="col-sm-10">
|
||||
<input asp-for="DocumentNumber" class="form-control" />
|
||||
<span asp-validation-for="DocumentNumber" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label asp-for="FirstName" class="col-sm-2 col-form-label"></label>
|
||||
<div class="col-sm-10">
|
||||
<input asp-for="FirstName" class="form-control" />
|
||||
<span asp-validation-for="FirstName" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label asp-for="LastName" class="col-sm-2 col-form-label"></label>
|
||||
<div class="col-sm-10">
|
||||
<input asp-for="LastName" class="form-control" />
|
||||
<span asp-validation-for="LastName" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label asp-for="Email" class="col-sm-2 col-form-label"></label>
|
||||
<div class="col-sm-10">
|
||||
<input asp-for="Email" class="form-control" />
|
||||
<span asp-validation-for="Email" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label asp-for="BirthDate" class="col-sm-2 col-form-label"></label>
|
||||
<div class="col-sm-10">
|
||||
<input asp-for="BirthDate" class="form-control" />
|
||||
<span asp-validation-for="BirthDate" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label asp-for="Phone" class="col-sm-2 col-form-label"></label>
|
||||
<div class="col-sm-10">
|
||||
<input asp-for="Phone" class="form-control" />
|
||||
<span asp-validation-for="Phone" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label asp-for="Address" class="col-sm-2 col-form-label"></label>
|
||||
<div class="col-sm-10">
|
||||
<textarea asp-for="Address" class="form-control"></textarea>
|
||||
<span asp-validation-for="Address" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label asp-for="IsActive" class="col-sm-2 col-form-label"></label>
|
||||
<div class="col-sm-10 form-check form-switch">
|
||||
<input asp-for="IsActive" class="form-check-input" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2 mt-4">
|
||||
<button type="submit" class="btn btn-primary">Guardar</button>
|
||||
<a asp-action="Index" class="btn btn-outline-secondary">Cancelar</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
@model vita_asistente.Models.Pacientes
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Eliminar Paciente";
|
||||
Layout = "_Layout";
|
||||
}
|
||||
|
||||
<div class="container mt-4">
|
||||
<h2>¿Desactivar paciente?</h2>
|
||||
|
||||
<p>Está a punto de desactivar el siguiente paciente:</p>
|
||||
|
||||
<dl class="row">
|
||||
<dt class="col-sm-2">Documento:</dt>
|
||||
<dd class="col-sm-10">@Html.DisplayFor(model => model.DocumentNumber)</dd>
|
||||
<dl class="row">
|
||||
|
||||
<dl class="row">
|
||||
<dt class="col-sm-2">Nombre:</dt>
|
||||
<dd class="col-sm-10">@Html.DisplayFor(model => model.FirstName) @Html.DisplayFor(model => model.LastName)</dd>
|
||||
<dl class="row">
|
||||
|
||||
<form asp-action="DeleteConfirmed" asp-route-id="Model.Id" method="post">
|
||||
@Html.AntiForgeryToken()
|
||||
|
||||
<div class="d-flex gap-2 mt-4">
|
||||
<button type="submit" value="Eliminar" class="btn btn-danger":><button type="submit" value="Eliminar" class="btn btn-danger ms-1">Confirmar desactivación</button>
|
||||
<a asp-action="Index" class="btn btn-outline-secondary">Cancelar</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,88 @@
|
||||
@model vita_asistente.Models.Pacientes
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Editar Paciente";
|
||||
Layout = "_Layout";
|
||||
}
|
||||
|
||||
<div class="container mt-4">
|
||||
<h2>Editar Paciente</h2>
|
||||
|
||||
<form asp-action="Edit" method="post" asp-route-id="@Model.Id" class="mt-4">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
|
||||
<input type="hidden" asp-for="Id" />
|
||||
|
||||
<div class="row mb-3">
|
||||
<label asp-for="DocumentNumber" class="col-sm-2 col-form-label"></label>
|
||||
<div class="col-sm-10">
|
||||
<input asp-for="DocumentNumber" class="form-control" readonly>
|
||||
<span asp-validation-for="DocumentNumber" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label asp-for="FirstName" class="col-sm-2 col-form-label"></label>
|
||||
<div class="col-sm-10">
|
||||
<input asp-for="FirstName" class="form-control" />
|
||||
<span asp-validation-for="FirstName" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label asp-for="LastName" class="col-sm-2 col-form-label"></label>
|
||||
<div class="col-sm-10">
|
||||
<input asp-for="LastName" class="form-control" />
|
||||
<span asp-validation-for="LastName" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label asp-for="Email" class="col-sm-2 col-form-label"></label>
|
||||
<div class="col-sm-10">
|
||||
<input asp-for="Email" class="form-control" />
|
||||
<span asp-validation-for="Email" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label asp-for="BirthDate" class="col-sm-2 col-form-label"></label>
|
||||
<div class="col-sm-10">
|
||||
<input asp-for="BirthDate" class="form-control" />
|
||||
<span asp-validation-for="BirthDate" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label asp-for="Phone" class="col-sm-2 col-form-label"></label>
|
||||
<div class="col-sm-10">
|
||||
<input asp-for="Phone" class="form-control" />
|
||||
<span asp-validation-for="Phone" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label asp-for="Address" class="col-sm-2 col-form-label"></label>
|
||||
<div class="col-sm-10">
|
||||
<textarea asp-for="Address" class="form-control"></textarea>
|
||||
<span asp-validation-for="Address" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label asp-for="IsActive" class="col-sm-2 col-form-label"></label>
|
||||
<div class="col-sm-10 form-check form-switch">
|
||||
<input asp-for="IsActive" class="form-check-input" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2 mt-4">
|
||||
<button type="submit" class="btn btn-primary">Guardar Cambios</button>
|
||||
<a asp-action="Index" class="btn btn-outline-secondary">Cancelar</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
||||
}
|
||||
+646
-76
@@ -1,88 +1,658 @@
|
||||
@model List<vita_asistente.Data.Models.Paciente>
|
||||
@model List<vita_asistente.Models.Pacientes>
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Pacientes";
|
||||
Layout = "_Layout";
|
||||
}
|
||||
|
||||
<div class="container mt-4">
|
||||
<h2>Lista de Pacientes</h2>
|
||||
|
||||
@if (User.IsInRole("Admin"))
|
||||
{
|
||||
<a asp-action="Create" class="btn btn-success mb-3">Nuevo Paciente</a>
|
||||
}
|
||||
|
||||
<div class="card">
|
||||
<div class="container mt-4 pb-5">
|
||||
<!-- Encabezado + Botón Agregar -->
|
||||
<div class="d-flex flex-wrap align-items-center justify-content-between gap-2 mb-4">
|
||||
<h2 class="mb-0">Lista de Pacientes</h2>
|
||||
@if (User.IsInRole("Admin"))
|
||||
{
|
||||
<button type="button" class="btn btn-success" data-bs-toggle="modal" data-bs-target="#createModal">
|
||||
<i class="bi bi-person-plus-fill me-1"></i> Agregar Paciente
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Buscador -->
|
||||
<div class="card shadow-sm mb-4">
|
||||
<div class="card-body">
|
||||
<form asp-action="Index" method="get" class="row g-3 mb-4">
|
||||
<div class="col-md-5">
|
||||
<form asp-action="Index" method="get" class="row g-3 align-items-end">
|
||||
<div class="col-md-8 col-lg-6">
|
||||
<label for="nombreBusqueda" class="form-label">Nombre o Documento</label>
|
||||
<input type="text" class="form-control" id="nombreBusqueda" name="nombreBusqueda"
|
||||
placeholder="Buscar por nombre o documento..." value="@ViewBag.NombreBusqueda">
|
||||
</div>
|
||||
<div class="col-md-2 d-flex align-items-end">
|
||||
<button type="submit" class="btn btn-primary me-3">Buscar</button>
|
||||
@if (!string.IsNullOrEmpty(ViewBag.NombreBusqueda))
|
||||
{
|
||||
<a asp-action="Index" class="btn btn-outline-secondary">Limpiar</a>
|
||||
}
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" id="nombreBusqueda" name="nombreBusqueda"
|
||||
placeholder="Buscar por nombre o documento..." value="@ViewBag.NombreBusqueda">
|
||||
<button type="submit" class="btn btn-primary">Buscar</button>
|
||||
@if (!string.IsNullOrEmpty(ViewBag.NombreBusqueda))
|
||||
{
|
||||
<a asp-action="Index" class="btn btn-outline-secondary">Limpiar</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<table class="table table-striped">
|
||||
<thead class="table-dark">
|
||||
<tr>
|
||||
<th>Documento</th>
|
||||
<th>Nombre Completo</th>
|
||||
<th>Email</th>
|
||||
<th>Fecha Registro</th>
|
||||
<th>Estado</th>
|
||||
<th>Acciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var paciente in Model)
|
||||
{
|
||||
<tr>
|
||||
<td>@Html.DisplayFor(modelItem => paciente.Documento)</td>
|
||||
<td>@Html.DisplayFor(modelItem => paciente.Nombre) @Html.DisplayFor(modelItem => paciente.Apellido)</td>
|
||||
<td>@Html.DisplayFor(modelItem => paciente.Email)</td>
|
||||
<td>@Html.DisplayFor(modelItem => paciente.FechaRegistro.ToShortDateString())</td>
|
||||
<td>
|
||||
@if (paciente.IsActive)
|
||||
{
|
||||
<span class="badge bg-success">Activo</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="badge bg-danger">Inactivo</span>
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
@if (User.IsInRole("Admin") || (User.Identity != null && User.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier")?.Value == paciente.Id))
|
||||
{
|
||||
<a asp-action="Details" asp-route-id="@paciente.Id" class="btn btn-sm btn-info">Ver</a>
|
||||
@if (User.IsInRole("Admin"))
|
||||
{
|
||||
<a asp-action="Edit" asp-route-id="@paciente.Id" class="btn btn-sm btn-warning ms-1">Editar</a>
|
||||
@if (!paciente.IsActive)
|
||||
{
|
||||
<form asp-action="Activate" asp-route-id="@paciente.Id" class="d-inline">
|
||||
<button type="submit" class="btn btn-sm btn-success ms-1" onclick="return confirm('¿Activar este paciente?');">Activar</button>
|
||||
</form>
|
||||
}
|
||||
else
|
||||
{
|
||||
<a asp-action="Delete" asp-route-id="@paciente.Id" class="btn btn-sm btn-danger ms-1">Desactivar</a>
|
||||
}
|
||||
}
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tabla -->
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle" id="pacientesTable">
|
||||
<thead class="table-dark">
|
||||
<tr>
|
||||
<th>Documento</th>
|
||||
<th>Nombre Completo</th>
|
||||
<th>Email</th>
|
||||
<th>Fecha Registro</th>
|
||||
<th>Estado</th>
|
||||
<th class="text-end">Acciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var paciente in Model)
|
||||
{
|
||||
<tr data-id="@paciente.Id">
|
||||
<td>@paciente.DocumentNumber</td>
|
||||
<td>@paciente.FirstName @paciente.LastName</td>
|
||||
<td>@paciente.Email</td>
|
||||
<td>@paciente.CreatedAt.ToShortDateString()</td>
|
||||
<td>
|
||||
<span class="badge @(paciente.IsActive ? "bg-success" : "bg-danger")">
|
||||
@(paciente.IsActive ? "Activo" : "Inactivo")
|
||||
</span>
|
||||
</td>
|
||||
<td class="text-end">
|
||||
<a asp-action="Details" asp-route-id="@paciente.Id" class="btn btn-sm btn-outline-info">
|
||||
<i class="bi bi-eye"></i> Ver
|
||||
</a>
|
||||
@if (User.IsInRole("Admin"))
|
||||
{
|
||||
<button type="button" class="btn btn-sm btn-outline-warning edit-btn"
|
||||
data-id="@paciente.Id"
|
||||
data-documenttype="@paciente.DocumentType"
|
||||
data-documentnumber="@paciente.DocumentNumber"
|
||||
data-firstname="@paciente.FirstName"
|
||||
data-lastname="@paciente.LastName"
|
||||
data-email="@paciente.Email"
|
||||
data-birthdate="@(paciente.BirthDate?.ToString("yyyy-MM-dd"))"
|
||||
data-address="@paciente.Address"
|
||||
data-phone="@paciente.Phone"
|
||||
data-emergencycontactname="@paciente.EmergencyContactName"
|
||||
data-emergencycontactphone="@paciente.EmergencyContactPhone"
|
||||
data-bloodtype="@paciente.BloodType"
|
||||
data-allergiesdescription="@paciente.AllergiesDescription"
|
||||
data-hasmedicationallergies="@paciente.HasMedicationAllergies.ToString().ToLower()"
|
||||
data-isactive="@paciente.IsActive.ToString().ToLower()"
|
||||
data-bs-toggle="modal" data-bs-target="#editModal">
|
||||
<i class="bi bi-pencil"></i> Editar
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-danger delete-btn"
|
||||
data-id="@paciente.Id"
|
||||
data-name="@($"{paciente.FirstName} {paciente.LastName}")"
|
||||
data-bs-toggle="modal" data-bs-target="#deleteModal">
|
||||
<i class="bi bi-trash"></i> Eliminar
|
||||
</button>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- =============== MODAL CREAR =============== -->
|
||||
<div class="modal fade" id="createModal" tabindex="-1" aria-labelledby="createModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-success text-white">
|
||||
<h5 class="modal-title" id="createModalLabel"><i class="bi bi-person-plus-fill me-2"></i>Nuevo Paciente</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<form id="createForm" asp-action="Create" method="post">
|
||||
<div class="modal-body">
|
||||
@Html.AntiForgeryToken()
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Nombre</label>
|
||||
<input type="text" class="form-control" id="createFirstName" name="FirstName" />
|
||||
<span class="text-danger" id="createFirstNameError"></span>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Apellido</label>
|
||||
<input type="text" class="form-control" id="createLastName" name="LastName" />
|
||||
<span class="text-danger" id="createLastNameError"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Tipo Documento</label>
|
||||
<input type="text" class="form-control" id="createDocumentType" name="DocumentType" />
|
||||
<span class="text-danger" id="createDocumentTypeError"></span>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Número Documento</label>
|
||||
<input type="text" class="form-control" id="createDocumentNumber" name="DocumentNumber" />
|
||||
<span class="text-danger" id="createDocumentNumberError"></span>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Email</label>
|
||||
<input type="email" class="form-control" id="createEmail" name="Email" />
|
||||
<span class="text-danger" id="createEmailError"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Fecha Nacimiento</label>
|
||||
<input type="date" class="form-control" id="createBirthDate" name="BirthDate" />
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Teléfono</label>
|
||||
<input type="text" class="form-control" id="createPhone" name="Phone" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Dirección</label>
|
||||
<input type="text" class="form-control" id="createAddress" name="Address" />
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Contacto Emergencia</label>
|
||||
<input type="text" class="form-control" id="createEmergencyContactName" name="EmergencyContactName" />
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Teléfono Emergencia</label>
|
||||
<input type="text" class="form-control" id="createEmergencyContactPhone" name="EmergencyContactPhone" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Tipo Sangre</label>
|
||||
<input type="text" class="form-control" id="createBloodType" name="BloodType" />
|
||||
</div>
|
||||
<div class="col-md-8 mb-3">
|
||||
<label class="form-label">Alergias</label>
|
||||
<input type="text" class="form-control" id="createAllergiesDescription" name="AllergiesDescription" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-check mb-3">
|
||||
<input type="checkbox" class="form-check-input" id="createHasMedicationAllergies" name="HasMedicationAllergies" value="true" />
|
||||
<label class="form-check-label" for="createHasMedicationAllergies">¿Tiene alergias a medicamentos?</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
|
||||
<button type="submit" class="btn btn-success">Guardar</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- =============== MODAL EDITAR =============== -->
|
||||
<div class="modal fade" id="editModal" tabindex="-1" aria-labelledby="editModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-warning text-dark">
|
||||
<h5 class="modal-title" id="editModalLabel"><i class="bi bi-pencil me-2"></i>Editar Paciente</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<form id="editForm" method="post">
|
||||
<div class="modal-body">
|
||||
@Html.AntiForgeryToken()
|
||||
<input type="hidden" id="editId" name="Id" />
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Nombre</label>
|
||||
<input type="text" class="form-control" id="editFirstName" name="FirstName" />
|
||||
<span class="text-danger" id="editFirstNameError"></span>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Apellido</label>
|
||||
<input type="text" class="form-control" id="editLastName" name="LastName" />
|
||||
<span class="text-danger" id="editLastNameError"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Tipo Documento</label>
|
||||
<input type="text" class="form-control" id="editDocumentType" name="DocumentType" />
|
||||
<span class="text-danger" id="editDocumentTypeError"></span>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Número Documento</label>
|
||||
<input type="text" class="form-control" id="editDocumentNumber" name="DocumentNumber" />
|
||||
<span class="text-danger" id="editDocumentNumberError"></span>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Email</label>
|
||||
<input type="email" class="form-control" id="editEmail" name="Email" />
|
||||
<span class="text-danger" id="editEmailError"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Fecha Nacimiento</label>
|
||||
<input type="date" class="form-control" id="editBirthDate" name="BirthDate" />
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Teléfono</label>
|
||||
<input type="text" class="form-control" id="editPhone" name="Phone" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Dirección</label>
|
||||
<input type="text" class="form-control" id="editAddress" name="Address" />
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Contacto Emergencia</label>
|
||||
<input type="text" class="form-control" id="editEmergencyContactName" name="EmergencyContactName" />
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Teléfono Emergencia</label>
|
||||
<input type="text" class="form-control" id="editEmergencyContactPhone" name="EmergencyContactPhone" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Tipo Sangre</label>
|
||||
<input type="text" class="form-control" id="editBloodType" name="BloodType" />
|
||||
</div>
|
||||
<div class="col-md-8 mb-3">
|
||||
<label class="form-label">Alergias</label>
|
||||
<input type="text" class="form-control" id="editAllergiesDescription" name="AllergiesDescription" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-check mb-3">
|
||||
<input type="checkbox" class="form-check-input" id="editHasMedicationAllergies" name="HasMedicationAllergies" value="true" />
|
||||
<label class="form-check-label" for="editHasMedicationAllergies">¿Tiene alergias a medicamentos?</label>
|
||||
</div>
|
||||
<div class="form-check mb-3">
|
||||
<input type="checkbox" class="form-check-input" id="editIsActive" name="IsActive" value="true" />
|
||||
<label class="form-check-label" for="editIsActive">Activo</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
|
||||
<button type="submit" class="btn btn-warning">Actualizar</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- =============== MODAL ELIMINAR =============== -->
|
||||
<div class="modal fade" id="deleteModal" tabindex="-1" aria-labelledby="deleteModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-danger text-white">
|
||||
<h5 class="modal-title" id="deleteModalLabel"><i class="bi bi-exclamation-triangle me-2"></i>Eliminar Paciente</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>¿Estás seguro de que deseas eliminar al paciente <strong id="deletePatientName"></strong>?</p>
|
||||
<p class="text-danger">Esta acción no se puede deshacer.</p>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="confirmDeleteCheck">
|
||||
<label class="form-check-label" for="confirmDeleteCheck">
|
||||
Confirmo que deseo eliminar este paciente.
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
|
||||
<form id="deleteForm" asp-action="Delete" method="post" class="d-inline">
|
||||
@Html.AntiForgeryToken()
|
||||
<input type="hidden" name="id" id="deleteId" />
|
||||
<button type="submit" class="btn btn-danger" id="deleteConfirmBtn" disabled>Eliminar</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Toast container -->
|
||||
<div id="toastContainer" class="position-fixed bottom-0 end-0 p-3" style="z-index: 1200;"></div>
|
||||
|
||||
@section Scripts {
|
||||
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
|
||||
// ---------- UTILIDADES ----------
|
||||
function showToast(message, isSuccess = true) {
|
||||
const container = document.getElementById('toastContainer');
|
||||
const toast = document.createElement('div');
|
||||
toast.className = `toast align-items-center text-white ${isSuccess ? 'bg-success' : 'bg-danger'} border-0`;
|
||||
toast.role = 'alert';
|
||||
toast.setAttribute('aria-live', 'assertive');
|
||||
toast.setAttribute('aria-atomic', 'true');
|
||||
const body = document.createElement('div');
|
||||
body.className = 'toast-body';
|
||||
body.textContent = message;
|
||||
toast.appendChild(body);
|
||||
container.appendChild(toast);
|
||||
const bsToast = new bootstrap.Toast(toast, { delay: 4000 });
|
||||
bsToast.show();
|
||||
toast.addEventListener('hidden.bs.toast', () => toast.remove());
|
||||
}
|
||||
|
||||
function getAntiForgeryToken(form) {
|
||||
return form.querySelector('input[name="__RequestVerificationToken"]')?.value || '';
|
||||
}
|
||||
|
||||
function clearValidationErrors(form) {
|
||||
form.querySelectorAll('.text-danger').forEach(el => el.textContent = '');
|
||||
}
|
||||
|
||||
function displayValidationErrors(form, errors) {
|
||||
clearValidationErrors(form);
|
||||
for (const [key, messages] of Object.entries(errors)) {
|
||||
// Buscar el span de error correspondiente: id="[formId][PropertyName]Error"
|
||||
const prefix = form.id === 'createForm' ? 'create' : 'edit';
|
||||
const span = document.getElementById(`${prefix}${key}Error`);
|
||||
if (span) {
|
||||
span.textContent = Array.isArray(messages) ? messages.join(' ') : messages;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- CREAR PACIENTE ----------
|
||||
const createForm = document.getElementById('createForm');
|
||||
const createModalEl = document.getElementById('createModal');
|
||||
const createModal = new bootstrap.Modal(createModalEl);
|
||||
|
||||
createForm.addEventListener('submit', async function (e) {
|
||||
e.preventDefault();
|
||||
clearValidationErrors(createForm);
|
||||
const formData = new FormData(createForm);
|
||||
const token = getAntiForgeryToken(createForm);
|
||||
|
||||
try {
|
||||
const response = await fetch(createForm.action, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'RequestVerificationToken': token
|
||||
},
|
||||
body: new URLSearchParams(formData)
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json();
|
||||
if (errorData.errors) {
|
||||
displayValidationErrors(createForm, errorData.errors);
|
||||
showToast('Por favor corrige los errores.', false);
|
||||
} else {
|
||||
showToast('Error al guardar.', false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
const patient = result.data;
|
||||
addRowToTable(patient);
|
||||
createModal.hide();
|
||||
showToast('Paciente creado exitosamente.');
|
||||
createForm.reset();
|
||||
} else {
|
||||
showToast('Error al crear el paciente.', false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
showToast('Ocurrió un error inesperado.', false);
|
||||
}
|
||||
});
|
||||
|
||||
// ---------- EDITAR PACIENTE ----------
|
||||
const editModalEl = document.getElementById('editModal');
|
||||
const editModal = new bootstrap.Modal(editModalEl);
|
||||
const editForm = document.getElementById('editForm');
|
||||
|
||||
function loadEditData(btn) {
|
||||
document.getElementById('editId').value = btn.dataset.id;
|
||||
document.getElementById('editFirstName').value = btn.dataset.firstname || '';
|
||||
document.getElementById('editLastName').value = btn.dataset.lastname || '';
|
||||
document.getElementById('editDocumentType').value = btn.dataset.documenttype || '';
|
||||
document.getElementById('editDocumentNumber').value = btn.dataset.documentnumber || '';
|
||||
document.getElementById('editEmail').value = btn.dataset.email || '';
|
||||
document.getElementById('editBirthDate').value = btn.dataset.birthdate || '';
|
||||
document.getElementById('editAddress').value = btn.dataset.address || '';
|
||||
document.getElementById('editPhone').value = btn.dataset.phone || '';
|
||||
document.getElementById('editEmergencyContactName').value = btn.dataset.emergencycontactname || '';
|
||||
document.getElementById('editEmergencyContactPhone').value = btn.dataset.emergencycontactphone || '';
|
||||
document.getElementById('editBloodType').value = btn.dataset.bloodtype || '';
|
||||
document.getElementById('editAllergiesDescription').value = btn.dataset.allergiesdescription || '';
|
||||
document.getElementById('editHasMedicationAllergies').checked = btn.dataset.hasmedicationallergies === 'true';
|
||||
document.getElementById('editIsActive').checked = btn.dataset.isactive === 'true';
|
||||
editForm.action = `/Pacientes/Edit/${btn.dataset.id}`;
|
||||
clearValidationErrors(editForm);
|
||||
}
|
||||
|
||||
// Asignar evento a botones de edición (incluyendo los dinámicos)
|
||||
document.addEventListener('click', function (e) {
|
||||
const btn = e.target.closest('.edit-btn');
|
||||
if (btn) {
|
||||
loadEditData(btn);
|
||||
}
|
||||
});
|
||||
|
||||
editForm.addEventListener('submit', async function (e) {
|
||||
e.preventDefault();
|
||||
clearValidationErrors(editForm);
|
||||
const formData = new FormData(editForm);
|
||||
const token = getAntiForgeryToken(editForm);
|
||||
|
||||
try {
|
||||
const response = await fetch(editForm.action, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'RequestVerificationToken': token
|
||||
},
|
||||
body: new URLSearchParams(formData)
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json();
|
||||
if (errorData.errors) {
|
||||
displayValidationErrors(editForm, errorData.errors);
|
||||
showToast('Por favor corrige los errores.', false);
|
||||
} else {
|
||||
showToast('Error al actualizar.', false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
const patient = result.data;
|
||||
updateRowInTable(patient);
|
||||
editModal.hide();
|
||||
showToast('Paciente actualizado exitosamente.');
|
||||
} else {
|
||||
showToast('Error al actualizar.', false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
showToast('Ocurrió un error inesperado.', false);
|
||||
}
|
||||
});
|
||||
|
||||
// ---------- ELIMINAR PACIENTE ----------
|
||||
const deleteModalEl = document.getElementById('deleteModal');
|
||||
const deleteModal = new bootstrap.Modal(deleteModalEl);
|
||||
const deleteForm = document.getElementById('deleteForm');
|
||||
const confirmCheck = document.getElementById('confirmDeleteCheck');
|
||||
const deleteBtn = document.getElementById('deleteConfirmBtn');
|
||||
const deletePatientName = document.getElementById('deletePatientName');
|
||||
|
||||
document.addEventListener('click', function (e) {
|
||||
const btn = e.target.closest('.delete-btn');
|
||||
if (btn) {
|
||||
const id = btn.dataset.id;
|
||||
const name = btn.dataset.name;
|
||||
deletePatientName.textContent = name;
|
||||
document.getElementById('deleteId').value = id;
|
||||
confirmCheck.checked = false;
|
||||
deleteBtn.disabled = true;
|
||||
deleteForm.action = `/Pacientes/Delete/${id}`;
|
||||
}
|
||||
});
|
||||
|
||||
confirmCheck.addEventListener('change', function () {
|
||||
deleteBtn.disabled = !this.checked;
|
||||
});
|
||||
|
||||
deleteForm.addEventListener('submit', async function (e) {
|
||||
e.preventDefault();
|
||||
const token = getAntiForgeryToken(deleteForm);
|
||||
const id = document.getElementById('deleteId').value;
|
||||
|
||||
try {
|
||||
const response = await fetch(deleteForm.action, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'RequestVerificationToken': token
|
||||
},
|
||||
body: new URLSearchParams(new FormData(deleteForm))
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
showToast('Error al eliminar.', false);
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
removeRowFromTable(id);
|
||||
deleteModal.hide();
|
||||
showToast('Paciente eliminado correctamente.');
|
||||
} else {
|
||||
showToast('Error al eliminar.', false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
showToast('Ocurrió un error inesperado.', false);
|
||||
}
|
||||
});
|
||||
|
||||
// ---------- FUNCIONES DE ACTUALIZACIÓN DE TABLA ----------
|
||||
function addRowToTable(patient) {
|
||||
const tbody = document.querySelector('#pacientesTable tbody');
|
||||
const row = document.createElement('tr');
|
||||
row.dataset.id = patient.id;
|
||||
const statusBadge = patient.isActive
|
||||
? '<span class="badge bg-success">Activo</span>'
|
||||
: '<span class="badge bg-danger">Inactivo</span>';
|
||||
|
||||
const adminActions = `
|
||||
<button type="button" class="btn btn-sm btn-outline-warning edit-btn"
|
||||
data-id="${patient.id}"
|
||||
data-documenttype="${patient.documentType || ''}"
|
||||
data-documentnumber="${patient.documentNumber || ''}"
|
||||
data-firstname="${patient.firstName || ''}"
|
||||
data-lastname="${patient.lastName || ''}"
|
||||
data-email="${patient.email || ''}"
|
||||
data-birthdate="${patient.birthDate || ''}"
|
||||
data-address="${patient.address || ''}"
|
||||
data-phone="${patient.phone || ''}"
|
||||
data-emergencycontactname="${patient.emergencyContactName || ''}"
|
||||
data-emergencycontactphone="${patient.emergencyContactPhone || ''}"
|
||||
data-bloodtype="${patient.bloodType || ''}"
|
||||
data-allergiesdescription="${patient.allergiesDescription || ''}"
|
||||
data-hasmedicationallergies="${patient.hasMedicationAllergies || false}"
|
||||
data-isactive="${patient.isActive || false}"
|
||||
data-bs-toggle="modal" data-bs-target="#editModal">
|
||||
<i class="bi bi-pencil"></i> Editar
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-danger delete-btn"
|
||||
data-id="${patient.id}"
|
||||
data-name="${patient.firstName || ''} ${patient.lastName || ''}"
|
||||
data-bs-toggle="modal" data-bs-target="#deleteModal">
|
||||
<i class="bi bi-trash"></i> Eliminar
|
||||
</button>
|
||||
`;
|
||||
|
||||
row.innerHTML = `
|
||||
<td>${patient.documentNumber || ''}</td>
|
||||
<td>${patient.firstName || ''} ${patient.lastName || ''}</td>
|
||||
<td>${patient.email || ''}</td>
|
||||
<td>${patient.createdAt ? new Date(patient.createdAt).toLocaleDateString() : 'N/A'}</td>
|
||||
<td>${statusBadge}</td>
|
||||
<td class="text-end">
|
||||
<a href="/Pacientes/Details/${encodeURIComponent(patient.id)}" class="btn btn-sm btn-outline-info">
|
||||
<i class="bi bi-eye"></i> Ver
|
||||
</a>
|
||||
${patient.id ? adminActions : ''}
|
||||
</td>
|
||||
`;
|
||||
tbody.prepend(row);
|
||||
}
|
||||
|
||||
function updateRowInTable(patient) {
|
||||
const row = document.querySelector(`#pacientesTable tbody tr[data-id="${patient.id}"]`);
|
||||
if (row) {
|
||||
const newRow = document.createElement('tr');
|
||||
newRow.dataset.id = patient.id;
|
||||
const statusBadge = patient.isActive
|
||||
? '<span class="badge bg-success">Activo</span>'
|
||||
: '<span class="badge bg-danger">Inactivo</span>';
|
||||
|
||||
const adminActions = `
|
||||
<button type="button" class="btn btn-sm btn-outline-warning edit-btn"
|
||||
data-id="${patient.id}"
|
||||
data-documenttype="${patient.documentType || ''}"
|
||||
data-documentnumber="${patient.documentNumber || ''}"
|
||||
data-firstname="${patient.firstName || ''}"
|
||||
data-lastname="${patient.lastName || ''}"
|
||||
data-email="${patient.email || ''}"
|
||||
data-birthdate="${patient.birthDate || ''}"
|
||||
data-address="${patient.address || ''}"
|
||||
data-phone="${patient.phone || ''}"
|
||||
data-emergencycontactname="${patient.emergencyContactName || ''}"
|
||||
data-emergencycontactphone="${patient.emergencyContactPhone || ''}"
|
||||
data-bloodtype="${patient.bloodType || ''}"
|
||||
data-allergiesdescription="${patient.allergiesDescription || ''}"
|
||||
data-hasmedicationallergies="${patient.hasMedicationAllergies || false}"
|
||||
data-isactive="${patient.isActive || false}"
|
||||
data-bs-toggle="modal" data-bs-target="#editModal">
|
||||
<i class="bi bi-pencil"></i> Editar
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-danger delete-btn"
|
||||
data-id="${patient.id}"
|
||||
data-name="${patient.firstName || ''} ${patient.lastName || ''}"
|
||||
data-bs-toggle="modal" data-bs-target="#deleteModal">
|
||||
<i class="bi bi-trash"></i> Eliminar
|
||||
</button>
|
||||
`;
|
||||
|
||||
newRow.innerHTML = `
|
||||
<td>${patient.documentNumber || ''}</td>
|
||||
<td>${patient.firstName || ''} ${patient.lastName || ''}</td>
|
||||
<td>${patient.email || ''}</td>
|
||||
<td>${patient.createdAt ? new Date(patient.createdAt).toLocaleDateString() : 'N/A'}</td>
|
||||
<td>${statusBadge}</td>
|
||||
<td class="text-end">
|
||||
<a href="/Pacientes/Details/${encodeURIComponent(patient.id)}" class="btn btn-sm btn-outline-info">
|
||||
<i class="bi bi-eye"></i> Ver
|
||||
</a>
|
||||
${patient.id ? adminActions : ''}
|
||||
</td>
|
||||
`;
|
||||
row.replaceWith(newRow);
|
||||
}
|
||||
}
|
||||
|
||||
function removeRowFromTable(id) {
|
||||
const row = document.querySelector(`#pacientesTable tbody tr[data-id="${id}"]`);
|
||||
if (row) row.remove();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
}
|
||||
@@ -10,7 +10,10 @@
|
||||
<title>@ViewData["Title"] - vita_asistente</title>
|
||||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
|
||||
<link rel="stylesheet" href="~/vita_asistente.styles.css" asp-append-version="true" />
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||
<links rel="stylesheet" href="~/vita_asistente.styles.css" asp-append-version="true" />
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-icons/1.11.3/font/bootstrap-icons.min.css"
|
||||
>
|
||||
</head>
|
||||
<body>
|
||||
<div class="app-wrapper">
|
||||
|
||||
Reference in New Issue
Block a user