349 lines
17 KiB
Elixir
349 lines
17 KiB
Elixir
defmodule ApiWeb.IndexLive do
|
|
use ApiWeb, :live_view
|
|
use Phoenix.Component
|
|
import Ecto.Query
|
|
alias Api.Repo
|
|
require Logger
|
|
|
|
def mount(_params, _session, socket) do
|
|
Envar.load(".env")
|
|
Envar.require_env_file(".env")
|
|
client = Envar.get("FROM")
|
|
|
|
idstudyfield = if Envar.get("IDENTIFIERFIELD") == "IDSTUDY" do
|
|
true
|
|
else
|
|
false
|
|
end
|
|
|
|
socket =
|
|
socket
|
|
|> assign(:page_title, "Entrega Digital - #{client}")
|
|
|> assign(:form, %{})
|
|
|> assign(:login_result, nil)
|
|
|> assign(logged_in: false)
|
|
|> assign(list: true)
|
|
|> assign(base_url: Envar.get("CHECK_ORIGIN"))
|
|
|> assign(idsite: Envar.get("IDSITE"))
|
|
|> assign(logo: Envar.get("LOGO"))
|
|
|> assign(logo_sm: Envar.get("LOGO_SM"))
|
|
|> assign(idstudyfield: idstudyfield)
|
|
{:ok, socket}
|
|
end
|
|
|
|
def handle_event("logged", %{"patientid" => patientid, "acceso_ed" => acceso_ed}, socket) do
|
|
|
|
Logger.info("Ingreso con access: #{acceso_ed} y patientid: #{patientid}")
|
|
# Realiza la primera consulta para buscar el estudio específico
|
|
study_found = buscar_estudio(patientid, acceso_ed)
|
|
|
|
# Si se encuentra el estudio, listar todos los estudios del paciente
|
|
query =
|
|
if study_found != [] do
|
|
listar_estudios_paciente(patientid)
|
|
else
|
|
[]
|
|
end
|
|
Logger.info("lista ----> #{inspect(query)}")
|
|
|
|
|
|
{patientname, idstudy} =
|
|
case query do
|
|
[%{patientname: name, idstudy: id} | _] ->
|
|
{String.replace(name, "^", " "), id}
|
|
_ -> {nil, nil}
|
|
end
|
|
|
|
socket = case study_found do
|
|
[] ->
|
|
socket
|
|
|> assign(logged_in: query != [])
|
|
|> assign(dni: patientid)
|
|
|> assign(idstudy: idstudy)
|
|
|> assign(studies: query)
|
|
|> assign(patientname: patientname)
|
|
|> assign(list: false)
|
|
_ ->
|
|
socket
|
|
|> assign(logged_in: query != [])
|
|
|> assign(dni: patientid)
|
|
|> assign(idstudy: idstudy)
|
|
|> assign(studies: query)
|
|
|> assign(patientname: patientname)
|
|
|> assign(list: true)
|
|
end
|
|
|
|
{:noreply, socket}
|
|
end
|
|
|
|
# Función para buscar el estudio específico
|
|
def buscar_estudio(patientid, acceso_ed) do
|
|
Envar.load(".env")
|
|
Envar.require_env_file(".env")
|
|
|
|
if Envar.get("acceso_ed") == "IDSTUDY" do
|
|
idstudy = String.to_integer(acceso_ed)
|
|
|
|
query =
|
|
from s in "study",
|
|
join: p in "patient",
|
|
on: p.idpatient == s.idpatient,
|
|
|
|
where: p.patientid == ^patientid and s.idstudy == ^idstudy,
|
|
select: %{
|
|
idstudy: s.idstudy,
|
|
patientname: p.patientname
|
|
|
|
}
|
|
|
|
Repo.all(query)
|
|
else
|
|
query =
|
|
from s in "study",
|
|
join: p in "patient",
|
|
on: p.idpatient == s.idpatient,
|
|
|
|
where: p.patientid == ^patientid and s.accessionnumber == ^acceso_ed,
|
|
select: %{
|
|
idstudy: s.idstudy,
|
|
patientname: p.patientname
|
|
|
|
}
|
|
|
|
Repo.all(query)
|
|
end
|
|
end
|
|
|
|
# Función para listar todos los estudios del paciente
|
|
def listar_estudios_paciente(patientid) do
|
|
query =
|
|
from s in "study",
|
|
join: p in "patient",
|
|
on: p.idpatient == s.idpatient,
|
|
left_join: sr in "studyreport", on: sr.idstudy == s.idstudy,
|
|
where: p.patientid == ^patientid,
|
|
select: %{
|
|
idstudy: s.idstudy,
|
|
idpatient: p.idpatient,
|
|
iddocument: fragment("substring(encrypt(?::text::bytea, '1nf0rm3', 'aes')::text from 3)", sr.idstudyreport),
|
|
date: s.studydate,
|
|
dni: p.patientid,
|
|
modality: s.modality,
|
|
accession: s.accessionnumber,
|
|
patientname: p.patientname,
|
|
status: sr.idstatus,
|
|
studydescription: s.studydescription
|
|
},
|
|
order_by: [desc: s.studydate]
|
|
|
|
Repo.all(query)
|
|
end
|
|
|
|
def generate_token(idstudy, patientid) do
|
|
Envar.load(".env")
|
|
Envar.require_env_file(".env")
|
|
# Paso 1: Armar json con fecha de vencimiento (puse 2 días)
|
|
json = if Envar.get("IDENTIFIERFIELD") == "IDSTUDY" do
|
|
%{
|
|
idstudy: Integer.to_string(idstudy),
|
|
patientid: patientid,
|
|
vencimiento: DateTime.add(DateTime.utc_now(), 2 * 24 * 60 * 60, :second)
|
|
}
|
|
else
|
|
%{
|
|
accessionnumber: idstudy,
|
|
patientid: patientid,
|
|
vencimiento: DateTime.add(DateTime.utc_now(), 2 * 24 * 60 * 60, :second)
|
|
}
|
|
end
|
|
# Paso 2: Convertir json a string
|
|
json_string = Jason.encode!(json)
|
|
|
|
# Paso 3: Encriptar con query
|
|
query = "select encrypt('#{json_string}'::bytea, '1nf0rm3', 'aes')::text"
|
|
token = Repo.query!(query).rows |> hd() |> hd()
|
|
|
|
# Paso 4: Encodear para poder armar la url
|
|
token = Base.encode64(token)
|
|
token
|
|
end
|
|
|
|
def render(assigns) do
|
|
~H"""
|
|
<body class="m-0 p-0 bg-[rgb(228, 228, 228)]">
|
|
<%= if @logged_in == false do %>
|
|
<div class="relative w-[100vw] h-[100vh] overflow-auto">
|
|
<div class="absolute inset-0 min-h-screen" style="
|
|
background-image: url('/api/images/fondo.jpg');
|
|
background-size: cover;
|
|
background-position: center;
|
|
background-repeat: no-repeat;
|
|
width: 100%;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;">
|
|
<div id="padding-div" class="flex items-center justify-center py-12 md:py-20 min-h-screen">
|
|
<div class="bg-white/75 shadow-md rounded-lg p-6 w-full max-w-xl overflow-y-auto h-auto">
|
|
<div>
|
|
<div class="text-center mb-6">
|
|
<img src={assigns.logo} class="mx-auto max-w-[16rem] md:max-w-sm pt-5" />
|
|
</div>
|
|
<hr class="my-4" />
|
|
<div>
|
|
<.simple_form for={@form} phx-submit="logged">
|
|
<fieldset>
|
|
<label class="block mb-4">
|
|
<div class="login_result"><%= @login_result %></div>
|
|
</label>
|
|
<input
|
|
class="form-input block w-full mb-4 border border-gray-300 rounded-lg py-2 px-4"
|
|
placeholder="DNI"
|
|
id="patientid"
|
|
name="patientid"
|
|
type="text"
|
|
required
|
|
/>
|
|
<input
|
|
class="form-input block w-full mb-4 border border-gray-300 rounded-lg py-2 px-4"
|
|
placeholder="Estudio N°"
|
|
id="acceso_ed"
|
|
name="acceso_ed"
|
|
type="text"
|
|
required
|
|
/>
|
|
<input
|
|
class="bg-[#5bc0de] hover:bg-[#46b8da] text-white font-bold py-2 px-4 rounded w-full cursor-pointer"
|
|
type="submit"
|
|
id="ingresar"
|
|
value="Ingresar"
|
|
/>
|
|
<%= if @list != true do %>
|
|
<h1 class="text-rose-500 pl-2 font-medium">Datos incorrectos</h1>
|
|
<% end %>
|
|
</fieldset>
|
|
</.simple_form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<% else %>
|
|
<div class="flex justify-between items-center bg-gray-200 p-2 font-bold h-14 w-screen fixed top-0 left-0 z-50">
|
|
<img src={@logo_sm} alt="Logo" class="w-24">
|
|
</div>
|
|
<div class="mt-20 px-4">
|
|
<%= if length(@studies) > 0 do %>
|
|
<div class="overflow-x-auto">
|
|
<div>
|
|
<h1 class="text-2xl font-bold text-[#2f99a2]" style="text-decoration-line: underline; "><%= @patientname %></h1>
|
|
<h1 class="text-lg font-medium text-[#2f99a2] pb-5 mt-[-0.4rem]">DNI: <%= @dni %></h1>
|
|
</div>
|
|
<table class="min-w-full divide-y divide-gray-200">
|
|
<thead class="bg-gray-50">
|
|
<tr>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase w-[80%]">
|
|
Estudios
|
|
</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase hidden md:block md:table-cell">
|
|
Informe
|
|
</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase hidden md:block md:table-cell">
|
|
Imágenes
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<%= for study <- @studies do %>
|
|
<tbody class="bg-white">
|
|
<tr class="bg-gray-100 border-solid border-b-4 border-white w-[86vw] md:w-[90vw]">
|
|
<td class="px-6 py-4 flex flex-row items-start">
|
|
<div class="text-sm w-full">
|
|
<p><strong>Fecha:</strong> <%= study.date %></p>
|
|
<p><strong>DNI:</strong> <%= @dni %></p>
|
|
<p><strong>Accession N°:</strong> <%= study.accession %></p>
|
|
<p><strong>Id Study:</strong> <%= study.idstudy %></p>
|
|
<p><strong>Descripción:</strong> <%= study.studydescription %></p>
|
|
</div>
|
|
<div class="block md:hidden w-28 flex justify-around">
|
|
<%= if study.iddocument == nil do %>
|
|
<a disabled target="_blank" class="flex items-center" style="flex-direction: column;">
|
|
<svg class="w-12 h-12" style="color: #c3c3c3;" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
|
|
<path fill-rule="evenodd" d="M9 2.221V7H4.221a2 2 0 0 1 .365-.5L8.5 2.586A2 2 0 0 1 9 2.22ZM11 2v5a2 2 0 0 1-2 2H4v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2h-7ZM8 16a1 1 0 0 1 1-1h6a1 1 0 1 1 0 2H9a1 1 0 0 1-1-1Zm1-5a1 1 0 1 0 0 2h6a1 1 0 1 0 0-2H9Z" clip-rule="evenodd"/>
|
|
</svg>
|
|
<p class="text-[12px]">Informe</p>
|
|
</a>
|
|
<% else %>
|
|
<a href={"#{assigns.base_url}/api/downloadpdf/#{study.iddocument}"} target="_blank" class="flex items-center" style="flex-direction: column;">
|
|
<svg class="w-12 h-12 text-[#297177] hover:text-[#4d9aa2]" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
|
|
<path fill-rule="evenodd" d="M9 2.221V7H4.221a2 2 0 0 1 .365-.5L8.5 2.586A2 2 0 0 1 9 2.22ZM11 2v5a2 2 0 0 1-2 2H4v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2h-7ZM8 16a1 1 0 0 1 1-1h6a1 1 0 1 1 0 2H9a1 1 0 0 1-1-1Zm1-5a1 1 0 1 0 0 2h6a1 1 0 1 0 0-2H9Z" clip-rule="evenodd"/>
|
|
</svg>
|
|
<p class="text-[12px]">Informe</p>
|
|
</a>
|
|
<% end %>
|
|
<%= if assigns.idstudyfield == true do %>
|
|
<a href={"https://estudio.informemedico.com.ar/#/#{assigns.idsite}/#{generate_token(study.idstudy, @dni)}"} target="_blank" class="ml-2 flex items-center" style="flex-direction: column;">
|
|
<svg class="w-12 h-12 text-[#297177] hover:text-[#4d9aa2]" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
|
|
<path fill-rule="evenodd" d="M9 2.221V7H4.221a2 2 0 0 1 .365-.5L8.5 2.586A2 2 0 0 1 9 2.22ZM11 2v5a2 2 0 0 1-2 2H4v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2h-7Zm.394 9.553a1 1 0 0 0-1.817.062l-2.5 6A1 1 0 0 0 8 19h8a1 1 0 0 0 .894-1.447l-2-4A1 1 0 0 0 13.2 13.4l-.53.706-1.276-2.553ZM13 9.5a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0Z" clip-rule="evenodd"/>
|
|
</svg>
|
|
<p class="text-[12px]">Imágenes</p>
|
|
</a>
|
|
<% else %>
|
|
<a href={"https://estudio.informemedico.com.ar/#/#{assigns.idsite}/#{generate_token(study.accession, @dni)}"} target="_blank" class="ml-2 flex items-center" style="flex-direction: column;">
|
|
<svg class="w-12 h-12 text-[#297177] hover:text-[#4d9aa2]" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
|
|
<path fill-rule="evenodd" d="M9 2.221V7H4.221a2 2 0 0 1 .365-.5L8.5 2.586A2 2 0 0 1 9 2.22ZM11 2v5a2 2 0 0 1-2 2H4v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2h-7Zm.394 9.553a1 1 0 0 0-1.817.062l-2.5 6A1 1 0 0 0 8 19h8a1 1 0 0 0 .894-1.447l-2-4A1 1 0 0 0 13.2 13.4l-.53.706-1.276-2.553ZM13 9.5a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0Z" clip-rule="evenodd"/>
|
|
</svg>
|
|
<p class="text-[12px]">Imágenes</p>
|
|
</a>
|
|
<% end %>
|
|
</div>
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap hidden md:block md:table-cell">
|
|
<div class="flex justify-start">
|
|
<%= if study.iddocument == nil or study.status != 3 do %>
|
|
<svg class="w-12 h-12 text-gray-300" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 24 24">
|
|
<path fill-rule="evenodd" d="M9 2.221V7H4.221a2 2 0 0 1 .365-.5L8.5 2.586A2 2 0 0 1 9 2.22ZM11 2v5a2 2 0 0 1-2 2H4v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2h-7ZM8 16a1 1 0 0 1 1-1h6a1 1 0 1 1 0 2H9a1 1 0 0 1-1-1Zm1-5a1 1 0 1 0 0 2h6a1 1 0 1 0 0-2H9Z" clip-rule="evenodd"/>
|
|
</svg>
|
|
<% else %>
|
|
<a href={"#{assigns.base_url}/api/downloadpdf/#{study.iddocument}"} target="_blank">
|
|
<svg class="w-12 h-12 text-[#297177] hover:text-[#4d9aa2]" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 24 24">
|
|
<path fill-rule="evenodd" d="M9 2.221V7H4.221a2 2 0 0 1 .365-.5L8.5 2.586A2 2 0 0 1 9 2.22ZM11 2v5a2 2 0 0 1-2 2H4v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2h-7ZM8 16a1 1 0 0 1 1-1h6a1 1 0 1 1 0 2H9a1 1 0 0 1-1-1Zm1-5a1 1 0 1 0 0 2h6a1 1 0 1 0 0-2H9Z" clip-rule="evenodd"/>
|
|
</svg>
|
|
</a>
|
|
<% end %>
|
|
</div>
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap hidden md:block md:table-cell">
|
|
<%= if assigns.idstudyfield == true do %>
|
|
<a href={"https://estudio.informemedico.com.ar/#/#{assigns.idsite}/#{generate_token(study.idstudy, @dni)}"} target="_blank">
|
|
<svg class="w-12 h-12 text-[#297177] hover:text-[#4d9aa2]" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 24 24">
|
|
<path fill-rule="evenodd" d="M9 2.221V7H4.221a2 2 0 0 1 .365-.5L8.5 2.586A2 2 0 0 1 9 2.22ZM11 2v5a2 2 0 0 1-2 2H4v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2h-7Zm.394 9.553a1 1 0 0 0-1.817.062l-2.5 6A1 1 0 0 0 8 19h8a1 1 0 0 0 .894-1.447l-2-4A1 1 0 0 0 13.2 13.4l-.53.706-1.276-2.553ZM13 9.5a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0Z" clip-rule="evenodd"/>
|
|
</svg>
|
|
</a>
|
|
<% else %>
|
|
<a href={"https://estudio.informemedico.com.ar/#/#{assigns.idsite}/#{generate_token(study.accession, @dni)}"} target="_blank">
|
|
<svg class="w-12 h-12 text-[#297177] hover:text-[#4d9aa2]" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 24 24">
|
|
<path fill-rule="evenodd" d="M9 2.221V7H4.221a2 2 0 0 1 .365-.5L8.5 2.586A2 2 0 0 1 9 2.22ZM11 2v5a2 2 0 0 1-2 2H4v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2h-7Zm.394 9.553a1 1 0 0 0-1.817.062l-2.5 6A1 1 0 0 0 8 19h8a1 1 0 0 0 .894-1.447l-2-4A1 1 0 0 0 13.2 13.4l-.53.706-1.276-2.553ZM13 9.5a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0Z" clip-rule="evenodd"/>
|
|
</svg>
|
|
</a>
|
|
<% end %>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
<% end %>
|
|
</table>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
<div class="flex flex-row justify-start items-center text-right pt-5 pb-5 text-xs leading-[15px]" style="margin-left: 1.25rem;">
|
|
<p>Esta información llega a Ud.<br>
|
|
gracias a <b>Entrega Digital</b><br>
|
|
un producto de
|
|
</p>
|
|
<img src={~p"/images/im_logo_new.png"} alt="Informe Médico Logo" class="ml-4 w-32 md:w-36" />
|
|
</div>
|
|
<% end %>
|
|
</body>
|
|
"""
|
|
end
|
|
end
|