Skip to content

Instantly share code, notes, and snippets.

@mazz
Last active Oct 5, 2020
Embed
What would you like to do?
liveview
defmodule ElijahWeb.SearchLive do
use ElijahWeb, :live_view
alias Elijah.Bank
require Logger
def mount(_params, _session, socket) do
socket =
assign(socket,
query: "",
code: "",
code_search: true,
loading: false,
challenges: [],
suggestions: [],
revealed_answer: 0,
total_entries: 0
)
Logger.info("socket: ")
IO.inspect(socket)
{:ok, socket}
end
def render(assigns) do
~L"""
<div class="w-full md:w-11/12 xl:w-8/12 mx-auto text-left md:text-center">
<p class="text-lg md:text-xl text-gray-600 mb-6">
<%= if @code_search do %>
Search for an exam code<br/>
<% else %>
Search the questions for keywords<br/>
<% end %>
<%= if !@code_search do %>
<%= @total_entries %> results
<% end %>
</p>
<%= if @code_search do %>
<form phx-submit="code-search">
<% else %>
<form phx-change="suggest-term" phx-submit="query-search">
<% end %>
<label class="tag-label">
<div class="tag-append">
<%= if @code_search do %>
<input class="tag-input" type="text" name="code" value="<%= @code %>" placeholder="'B-001-001-001'" list="results" autofocus autocomplete="off" <%= if @loading, do: "readonly" %>/>
<% else %>
<input class="tag-input" type="text" name="query" value="<%= @query %>" phx-debounce="300" placeholder="'repeater station'" list="suggestions" autofocus autocomplete="off" <%= if @loading, do: "readonly" %>/>
<% end %>
<button type="submit" class="btn btn-dark" phx-disable-with="Searching...">Search</button>
</div>
</label>
</form>
<datalist id="suggestions">
<%= for suggestion <- @suggestions do %>
<option value="<%= suggestion.query_text %>"><%= suggestion.query_text %></option>
<% end %>
</datalist>
<div>&nbsp;</div>
<div class="btn-group" role="group" aria-label="Query Type">
<button class="btn btn-<%= if !@code_search, do: "outline-" %>dark" phx-click="code-search-on">Exam Code</button>
<button class="btn btn-<%= if @code_search, do: "outline-" %>dark" phx-click="query-search-on">Questions</button>
</div>
</div>
<div class="w-full md:w-11/12 xl:w-8/12 mx-auto text-left md:text-center">&nbsp;</div>
<%= if @loading do %>
<div class="mx-auto md:text-center">
<div class="spinner w-12 h-12" role="status">
<span class="sr-only">Loading...</span>
</div>
</div>
<% end %>
<%= for challenge <- @challenges do %>
<div class="w-full md:w-11/12 xl:w-8/12 mx-auto text-left">
<div class="card shadow">
<div class="card-body shadow overflow-hidden rounded-md">
<div class="container mx-auto flex justify-between items-center">
<p class="text-sm md:text-md text-gray-400 mb-2"><%= challenge.category_name %></p>
<%= if @revealed_answer == challenge.id do %>
<button class="btn btn-light rounded-full btn-sm"><%= challenge.answer %></button>
<% else %>
<button class="btn btn-light rounded-full btn-sm" phx-click="reveal-answer" phx-value-id="<%= challenge.id %>">Reveal Answer</button>
<% end %>
</div>
<h3 class="text-2xl md:text-3xl text-gray-900 leading-tight mb-3 font-bold md:font-extrabold"><%= challenge.code %></h3>
<p class="text-lg md:text-xl text-gray-900 mb-2"><%= challenge.question %> </p>
<p class="text-lg md:text-xl text-gray-600 mb-2" style="white-space: pre-line"><%= Enum.map(String.split(challenge.choices , "\n"), fn str -> str <> "\n" end)%> </p>
</div>
</div>
</div>
<div>&nbsp;</div>
<% end %>
"""
end
def handle_event("reveal-answer", %{"id" => id}, socket) do
IO.inspect(id)
case Integer.parse(id) do
:error -> {:noreply, socket}
{number, _} -> {:noreply, assign(socket, revealed_answer: number)}
end
end
def handle_event("code-search-on", _, socket) do
socket = assign(socket, code_search: true)
{:noreply, socket}
end
def handle_event("query-search-on", _, socket) do
socket = assign(socket, code_search: false)
{:noreply, socket}
end
def handle_event("code-search", %{"code" => code}, socket) do
send(self(), {:run_code_search, code})
socket =
assign(socket,
code: code,
challenges: [],
loading: true
)
{:noreply, socket}
end
def handle_event("query-search", %{"query" => query}, socket) do
send(self(), {:run_query_search, query})
socket =
assign(socket,
query: query,
challenges: [],
loading: true
)
{:noreply, socket}
end
def handle_event("suggest-term", %{"query" => prefix}, socket) do
socket =
assign(socket,
suggestions: Bank.suggested_terms(prefix),
challenges: [],
# to avoid clobbering the input field when user selects prefix
query: prefix,
loading: false
)
{:noreply, socket}
end
def handle_info({:run_code_search, code}, socket) do
case Bank.search_by_code(String.upcase(code)) do
nil ->
socket =
socket
|> put_flash(:info, "No exam code matching \"#{code}\"")
|> assign(challenges: [], code: code, loading: false)
{:noreply, socket}
challenge ->
socket = assign(socket, challenges: [challenge], code: code, loading: false)
{:noreply, socket}
end
end
def handle_info({:run_query_search, query}, socket) do
challenge = Bank.search_by_question_query(query)
if challenge.total_entries == 0 do
socket =
socket
|> put_flash(:info, "No questions containing \"#{query}\"")
|> assign(challenges: [], query: query, loading: false, total_entries: 0)
{:noreply, socket}
else
socket = assign(socket, challenges: challenge, query: query, loading: false, total_entries: challenge.total_entries, revealed_answer: 0)
{:noreply, socket}
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment