prop/lib/microwaveprop_web/live/submit_live.ex
Graham McIntire 7d0978f7d5
Add /submit route for user QSO submission
Maidenhead grid module converts grid squares to lat/lon coordinates.
Submission form validates grids, bands, modes, and email, computes
positions and distance, then triggers the weather/HRRR/terrain
processing pipeline via Oban.
2026-03-29 16:46:35 -05:00

125 lines
3.3 KiB
Elixir

defmodule MicrowavepropWeb.SubmitLive do
@moduledoc false
use MicrowavepropWeb, :live_view
alias Microwaveprop.Radio
alias Microwaveprop.Radio.Qso
alias Microwaveprop.Workers.QsoWeatherEnqueueWorker
@band_options [
{"1296 MHz", "1296"},
{"2304 MHz", "2304"},
{"3456 MHz", "3456"},
{"5760 MHz", "5760"},
{"10 GHz", "10000"},
{"24 GHz", "24000"},
{"47 GHz", "47000"},
{"76 GHz", "75000"}
]
@mode_options ~w(CW SSB FM FT8 FT4)
@impl true
def mount(_params, _session, socket) do
changeset = Radio.change_qso(%Qso{})
{:ok,
assign(socket,
page_title: "Submit QSO",
form: to_form(changeset),
band_options: @band_options,
mode_options: @mode_options
)}
end
@impl true
def handle_event("validate", %{"qso" => qso_params}, socket) do
changeset =
%Qso{}
|> Radio.change_qso(qso_params)
|> Map.put(:action, :validate)
{:noreply, assign(socket, form: to_form(changeset))}
end
def handle_event("save", %{"qso" => qso_params}, socket) do
case Radio.create_qso(qso_params) do
{:ok, qso} ->
Oban.insert(QsoWeatherEnqueueWorker.new(%{}))
{:noreply,
socket
|> put_flash(:info, "QSO submitted successfully!")
|> push_navigate(to: ~p"/qsos/#{qso.id}")}
{:error, changeset} ->
{:noreply, assign(socket, form: to_form(changeset))}
end
end
@impl true
def render(assigns) do
~H"""
<Layouts.app flash={@flash}>
<.header>
Submit QSO
<:subtitle>Submit a microwave QSO for propagation analysis</:subtitle>
</.header>
<.form for={@form} id="qso-form" phx-change="validate" phx-submit="save" class="space-y-4">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<.input field={@form[:station1]} type="text" label="Station 1" placeholder="W5XD" />
<.input
field={@form[:grid1]}
type="text"
label="Grid 1"
placeholder="EM12kp"
phx-debounce="blur"
/>
<.input field={@form[:station2]} type="text" label="Station 2" placeholder="K5TR" />
<.input
field={@form[:grid2]}
type="text"
label="Grid 2"
placeholder="EM00cd"
phx-debounce="blur"
/>
</div>
<p class="text-sm text-base-content/60 -mt-2">
Be as specific as possible with grid squares (6 characters preferred, e.g. EM12kp).
</p>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<.input
field={@form[:band]}
type="select"
label="Band"
prompt="Select band"
options={@band_options}
/>
<.input
field={@form[:mode]}
type="select"
label="Mode"
prompt="Select mode"
options={@mode_options}
/>
<.input field={@form[:qso_timestamp]} type="datetime-local" label="Timestamp (UTC)" />
</div>
<.input
field={@form[:submitter_email]}
type="email"
label="Your Email"
placeholder="you@example.com"
/>
<div class="mt-6">
<.button phx-disable-with="Submitting..." class="btn-primary">Submit QSO</.button>
</div>
</.form>
</Layouts.app>
"""
end
end