prop/lib/microwaveprop/rover/location.ex
Graham McIntire b4b8d4ec47
Some checks failed
Build base image / Build and push base image (push) Successful in 12s
Build and Push / Build CI test image (push) Successful in 14s
Build and Push / Build and Push Docker Image (push) Failing after 14m7s
simplify: DRY up shared changesets, context helpers, LiveView helpers, and structural extraction
- Create MaidenheadChangesetHelpers: consolidate grid validation, callsign
  normalization, lat/lon validation, grid/latlon derivation across 6 schemas
- Create ContextHelpers: shared fetch_owned with admin bypass, safe_enqueue
  for Oban workers, UUID casting to replace CastError rescues
- Extend LiveHelpers: add current_user/1 (removes 7 duplicate definitions),
  subscribe/2 (replaces 13 inline PubSub sites), assign_url_params/2
- Extract Propagation.ScoreStore (528 lines): separate file I/O and cache
  management from scoring logic, 13 defdelegate passthroughs
- Split SubmitLive (942->475 lines): extract CSV/ADIF upload rendering into
  3 function component modules (csv_upload, adif_upload, preview)
- Update 16 LiveViews to use shared helpers
2026-08-06 18:06:50 -05:00

46 lines
1.3 KiB
Elixir

defmodule Microwaveprop.Rover.Location do
@moduledoc """
A globally-visible rover parking location contributed by a logged-in
user. Everyone can view the list; only authenticated users can create
entries (creator tracked via `user_id`).
`status` is `:good` (recommended spot) or `:bad` (avoid —
trespass, no-go, etc.).
"""
use Ecto.Schema
import Ecto.Changeset
alias Microwaveprop.Radio.MaidenheadChangesetHelpers, as: MCH
@statuses [:good, :bad]
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "rover_locations" do
field :lat, :float
field :lon, :float
field :status, Ecto.Enum, values: @statuses, default: :good
field :notes, :string
belongs_to :user, Microwaveprop.Accounts.User
timestamps(type: :utc_datetime)
end
@type t :: %__MODULE__{}
@spec statuses() :: [atom()]
def statuses, do: @statuses
@spec changeset(t() | Ecto.Changeset.t(), map()) :: Ecto.Changeset.t()
def changeset(location, attrs) do
location
|> cast(attrs, [:lat, :lon, :status, :notes])
|> validate_required([:lat, :lon, :status])
|> MCH.validate_latlon(:lat, :lon)
|> validate_inclusion(:status, @statuses)
|> validate_length(:notes, max: 4000)
|> foreign_key_constraint(:user_id)
end
end