From 4759c65809b96f69dd6bfe8175ad2298bc484fae Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Sat, 4 Apr 2026 09:29:32 -0500 Subject: [PATCH] Support two-callsign search on contacts page to find contacts between a pair --- lib/microwaveprop/radio.ex | 19 +++++++++++++++-- .../live/contact_live/index.ex | 2 +- .../live/contact_live_test.exs | 21 +++++++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/lib/microwaveprop/radio.ex b/lib/microwaveprop/radio.ex index eb0199f5..4445856e 100644 --- a/lib/microwaveprop/radio.ex +++ b/lib/microwaveprop/radio.ex @@ -82,9 +82,24 @@ defmodule Microwaveprop.Radio do defp maybe_search(query, ""), do: query defp maybe_search(query, search) do - pattern = "%" <> String.upcase(search) <> "%" + terms = search |> String.split() |> Enum.map(&String.trim/1) |> Enum.reject(&(&1 == "")) - where(query, [q], ilike(q.station1, ^pattern) or ilike(q.station2, ^pattern)) + case terms do + [a, b] -> + pa = "%" <> String.upcase(a) <> "%" + pb = "%" <> String.upcase(b) <> "%" + + where( + query, + [q], + (ilike(q.station1, ^pa) and ilike(q.station2, ^pb)) or + (ilike(q.station1, ^pb) and ilike(q.station2, ^pa)) + ) + + _ -> + pattern = "%" <> String.upcase(search) <> "%" + where(query, [q], ilike(q.station1, ^pattern) or ilike(q.station2, ^pattern)) + end end defp sort_opts(opts) do diff --git a/lib/microwaveprop_web/live/contact_live/index.ex b/lib/microwaveprop_web/live/contact_live/index.ex index 63078558..e88c7838 100644 --- a/lib/microwaveprop_web/live/contact_live/index.ex +++ b/lib/microwaveprop_web/live/contact_live/index.ex @@ -91,7 +91,7 @@ defmodule MicrowavepropWeb.ContactLive.Index do diff --git a/test/microwaveprop_web/live/contact_live_test.exs b/test/microwaveprop_web/live/contact_live_test.exs index 69629c3d..ca4b442f 100644 --- a/test/microwaveprop_web/live/contact_live_test.exs +++ b/test/microwaveprop_web/live/contact_live_test.exs @@ -79,6 +79,27 @@ defmodule MicrowavepropWeb.ContactLiveTest do assert aa_pos < zz_pos end + test "search by single callsign matches either station", %{conn: conn} do + create_contact(%{station1: "W5LUA", station2: "W5HN"}) + create_contact(%{station1: "K5TR", station2: "N5AC"}) + + {:ok, _lv, html} = live(conn, ~p"/contacts?search=W5LUA") + assert html =~ "W5LUA" + refute html =~ "K5TR" + end + + test "search by two callsigns finds contacts between that pair", %{conn: conn} do + create_contact(%{station1: "W5LUA", station2: "W5HN"}) + create_contact(%{station1: "W5HN", station2: "W5LUA"}) + create_contact(%{station1: "W5LUA", station2: "K5TR"}) + + {:ok, _lv, html} = live(conn, ~p"/contacts?search=W5LUA+W5HN") + assert html =~ "W5LUA" + assert html =~ "W5HN" + # The W5LUA-K5TR contact should not appear + refute html =~ "K5TR" + end + test "pagination works", %{conn: conn} do for i <- 1..25 do ts = DateTime.add(~U[2026-01-01 00:00:00Z], i * 3600, :second)