File size: 5,196 Bytes
3f219b5 aeeeee4 3f219b5 5f7f244 3f219b5 aeeeee4 3f219b5 5f7f244 aeeeee4 f296c58 aeeeee4 f296c58 5f7f244 92f1e06 5f7f244 42d83b8 5f7f244 92f1e06 42d83b8 f296c58 aeeeee4 b25aea3 aeeeee4 96365df 3280f20 96365df 5f7f244 96365df aeeeee4 9da0664 aeeeee4 9da0664 aeeeee4 cad3c5b 3f219b5 aeeeee4 3280f20 aeeeee4 b25aea3 5f7f244 b25aea3 3280f20 3f219b5 f296c58 3280f20 5f7f244 92f1e06 fad254c 5f7f244 3f219b5 92f1e06 3cf8d48 3f219b5 5f7f244 17a7eb5 f296c58 5fc337e f296c58 5f7f244 f296c58 aeeeee4 278333f f296c58 278333f f296c58 278333f aeeeee4 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
defmodule MedicodeWeb.Components.CodeSelect do
@moduledoc """
An auto-complete select field that allows users to search for codes to add by either `code` or `description`.
"""
use MedicodeWeb, :live_component
import MedicodeWeb.Components, only: [code_display: 1]
alias Medicode.Feedback
alias Medicode.Transcriptions
@impl Phoenix.LiveComponent
def mount(socket) do
socket =
socket
|> assign(:codes, [])
|> assign(:selected_code, nil)
|> assign(:submitted_code_feedback, nil)
{:ok, socket}
end
@impl Phoenix.LiveComponent
def update(
%{id: id, text: text, current_user: current_user, chunk: chunk} = _assigns,
socket
) do
form = to_form(%{"search_term" => ""}, as: id)
socket =
socket
|> assign(:form, form)
|> assign(:text, text)
|> assign(:current_user, current_user)
|> assign(:chunk, chunk)
{:ok, socket}
end
@impl Phoenix.LiveComponent
def render(assigns) do
~H"""
<div class="w-full" phx-click-away="clear-codes" phx-target={@myself}>
<%= if is_nil(@selected_code) do %>
<.form for={@form} phx-change="suggest-code" phx-target={@myself} class="relative">
<.input
type="text"
field={@form[:search_term]}
class="w-full rounded"
style={if length(@codes) > 0, do: "border-radius: 0.25rem 0.25rem 0 0 !important;"}
placeholder="Search for another code..."
/>
<div
:if={length(@codes) > 0}
class="absolute z-10 w-full bg-white border-l border-r border-b border-zinc-400 rounded-b overflow-hidden"
>
<button
:for={code <- @codes}
type="button"
class="w-full text-left px-2 py-1 text-sm border-b border-zinc-100 last:border-b-0 hover:bg-blue-200"
phx-click="choose-code"
phx-value-code={code.code}
phx-target={@myself}
>
<%= code.code %>: <%= code.description %>
</button>
</div>
</.form>
<% else %>
<div class="px-[14px]">
<div class="flex justify-between pb-1 border-b border-zinc-300">
<p class="leading-normal font-bold text-type-black-primary uppercase">
User-selected code
</p>
<button type="button" phx-click="clear-code" phx-target={@myself}>
<.icon name="hero-x-circle" />
</button>
</div>
<.code_display code={@selected_code.code} label={@selected_code.description} />
</div>
<% end %>
</div>
"""
end
@impl Phoenix.LiveComponent
def handle_event("suggest-code", params, socket) do
form_id = socket.assigns.form.id
%{^form_id => %{"search_term" => value}} = params
suggested_codes = Medicode.Coding.search_for_code_vector(value)
{:noreply, assign(socket, :codes, suggested_codes)}
end
def handle_event("clear-codes", _params, socket) do
{:noreply, assign(socket, :codes, [])}
end
def handle_event("choose-code", %{"code" => code}, socket) do
selected_code = Enum.find(socket.assigns.codes, &(&1.code == code))
text_vector = Medicode.Coding.compute_vector_as_list(socket.assigns.text)
code_feedback =
Feedback.insert_and_return(%{
text: socket.assigns.text,
text_vector: text_vector,
response: true,
code_vector_id: selected_code.id
})
Transcriptions.upsert_code_vector_for_transcription_chunk(%{
assigned_by_user_id: socket.assigns.current_user.id,
code_vector_id: selected_code.id,
transcription_chunk_id: socket.assigns.chunk.id,
cosine_similarity:
Medicode.Coding.get_cosine_similarity(text_vector, selected_code.description_vector)
})
send_update(MedicodeWeb.Components.TranscriptionTextComponent,
id: "transcription-chunk-#{socket.assigns.chunk.id}",
chunk: socket.assigns.chunk,
chunk_id: socket.assigns.chunk.id,
current_user: socket.assigns.current_user,
on_feedback: &MedicodeWeb.TranscriptionsLive.Show.on_feedback/1,
on_remove_code: &MedicodeWeb.TranscriptionsLive.Show.on_remove_code/1
)
Phoenix.PubSub.broadcast(
:medicode_pubsub,
"transcriptions:#{socket.assigns.chunk.transcription_id}",
{:transcription_updated, socket.assigns.chunk}
)
socket =
if is_nil(code_feedback) do
put_flash(socket, :error, "Failed to record feedback")
else
socket
|> assign(:selected_code, selected_code)
|> assign(:submitted_code_feedback, code_feedback)
|> assign(:codes, [])
end
{:noreply, socket}
end
@impl Phoenix.LiveComponent
def handle_event(
"clear-code",
_params,
%{assigns: %{submitted_code_feedback: submitted_code_feedback}} = socket
) do
# Delete previous code feedback
Feedback.delete(submitted_code_feedback)
socket =
socket
|> assign(:codes, [])
|> assign(:selected_code, nil)
|> assign(:submitted_code_feedback, nil)
{:noreply, socket}
end
end
|