70 lines
2.3 KiB
Elixir
70 lines
2.3 KiB
Elixir
defmodule MvWeb.MemberLive.Index.DatePresets do
|
|
@moduledoc """
|
|
Relative date-range presets for the date value controls (§1.25/§2.8).
|
|
|
|
Each preset resolves against a reference date "today" into a concrete
|
|
`%{from: Date.t(), to: Date.t()}` range. Rolling "last N days/months" presets
|
|
end on today; the "this month/quarter/year" presets run period-to-date from
|
|
the respective period start up to today. Resolving is pure and clock-free —
|
|
the caller passes `today` (defaulting to `Date.utc_today/0`), so the resolved
|
|
bounds are testable and reproducible.
|
|
|
|
The resolved bounds feed the same `jd_*` / `ed_*` / `cdf_*` URL params as an
|
|
absolute custom range; presets are purely an input convenience and add no new
|
|
persistence dimension.
|
|
"""
|
|
|
|
@type preset ::
|
|
:last_7_days
|
|
| :last_30_days
|
|
| :last_3_months
|
|
| :last_12_months
|
|
| :this_month
|
|
| :this_quarter
|
|
| :this_year
|
|
|
|
@type range :: %{from: Date.t(), to: Date.t()}
|
|
|
|
@presets [
|
|
:last_7_days,
|
|
:last_30_days,
|
|
:last_3_months,
|
|
:last_12_months,
|
|
:this_month,
|
|
:this_quarter,
|
|
:this_year
|
|
]
|
|
|
|
@doc """
|
|
Returns every preset key in display order (rolling windows first, then the
|
|
period-to-date presets), for rendering the preset radio list.
|
|
"""
|
|
@spec all() :: [preset()]
|
|
def all, do: @presets
|
|
|
|
@doc """
|
|
Whether `key` names a known preset.
|
|
"""
|
|
@spec preset?(term()) :: boolean()
|
|
def preset?(key), do: key in @presets
|
|
|
|
@doc """
|
|
Resolves a preset to a concrete `{from, to}` range relative to `today`
|
|
(default `Date.utc_today/0`).
|
|
"""
|
|
@spec resolve(preset(), Date.t()) :: range()
|
|
def resolve(preset, today \\ Date.utc_today())
|
|
|
|
def resolve(:last_7_days, today), do: %{from: Date.add(today, -6), to: today}
|
|
def resolve(:last_30_days, today), do: %{from: Date.add(today, -29), to: today}
|
|
def resolve(:last_3_months, today), do: %{from: Date.shift(today, month: -3), to: today}
|
|
def resolve(:last_12_months, today), do: %{from: Date.shift(today, month: -12), to: today}
|
|
def resolve(:this_month, today), do: %{from: %{today | day: 1}, to: today}
|
|
|
|
def resolve(:this_quarter, today) do
|
|
first_month = div(today.month - 1, 3) * 3 + 1
|
|
%{from: Date.new!(today.year, first_month, 1), to: today}
|
|
end
|
|
|
|
def resolve(:this_year, today), do: %{from: Date.new!(today.year, 1, 1), to: today}
|
|
end
|