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"""
<%= 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..." />
0} class="absolute z-10 w-full bg-white border-l border-r border-b border-zinc-400 rounded-b overflow-hidden" >
<% else %>

User-selected code

<.code_display code={@selected_code.code} label={@selected_code.description} />
<% end %>
""" 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) }) Phoenix.PubSub.broadcast( :medicode_pubsub, "transcriptions:#{socket.assigns.chunk.transcription_id}", {:transcription_chunk_updated, socket.assigns.chunk.id} ) 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