fix(membership): add chronological sort key for custom :date fields
Custom :date values are real Date structs; sorting them by Erlang term order compares day, then month, then year, so the member list ordered them like day-first text instead of chronologically. Derive the sort key from a single shared helper that maps a date to its Gregorian day count, leaving the other value types at their already-correct natural order.
This commit is contained in:
parent
d6c322fd79
commit
1aaa0ece5d
3 changed files with 124 additions and 0 deletions
30
lib/mv/membership/custom_field_sort.ex
Normal file
30
lib/mv/membership/custom_field_sort.ex
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
defmodule Mv.Membership.CustomFieldSort do
|
||||
@moduledoc """
|
||||
Derives a term-order-comparable sort key from a custom-field value.
|
||||
|
||||
Custom-field values are stored in an Ash `:union` attribute, so a value
|
||||
arrives either as an `%Ash.Union{}` or as its already-unwrapped term. This
|
||||
module is the single source of truth for turning such a value into a key that
|
||||
`Enum.sort_by/2` can order correctly per `value_type`.
|
||||
|
||||
nil / empty handling is intentionally NOT this function's concern — the call
|
||||
sites split present from absent values before sorting.
|
||||
"""
|
||||
|
||||
@doc """
|
||||
Returns a term-order-comparable sort key for `value`, given its `value_type`.
|
||||
|
||||
For every non-date type the natural unwrapped value is returned, so
|
||||
`:integer` sorts numerically and `:string` / `:email` sort lexicographically.
|
||||
"""
|
||||
def sort_key(%Ash.Union{value: value, type: type}, _expected_type),
|
||||
do: sort_key(value, type)
|
||||
|
||||
def sort_key(value, :string) when is_binary(value), do: value
|
||||
def sort_key(value, :integer) when is_integer(value), do: value
|
||||
def sort_key(value, :boolean) when is_boolean(value), do: value
|
||||
# Gregorian day count is a chronological integer key (earlier date ⇒ smaller).
|
||||
def sort_key(%Date{} = date, :date), do: Date.to_gregorian_days(date)
|
||||
def sort_key(value, :email) when is_binary(value), do: value
|
||||
def sort_key(value, _type), do: to_string(value)
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue