Previous / next / today navigation over a date kept in the URL — the header of a page that shows one day at a time (a day's analytics, a schedule, a log).
Stateless: the buttons are <.link patch>es built by the path function
you pass, so the date lives in the URL and the page's handle_params/3
reads it (parse it with parse_param/2). Previous and next are disabled
at min / max; "Today" shows only when you are not already on it.
<.date_nav
date={@date}
today={@today}
max={@today}
path={&Routes.path("/admin/analytics?date=#{&1}")}
/>
def handle_params(params, _uri, socket) do
today = MyApp.local_today()
{:noreply, assign(socket, date: DateNav.parse_param(params["date"], today: today, max: today))}
endThe date picker
With picker (default true) a native date input sits between the
arrows. A date input only reaches the server inside a form, so it is
wrapped in one that sends pick_event (default "date_nav_pick") with
%{"date" => "YYYY-MM-DD"}; handle it with a patch:
def handle_event("date_nav_pick", %{"date" => value}, socket) do
date = DateNav.parse_param(value, today: socket.assigns.today)
{:noreply, push_patch(socket, to: Routes.path("/admin/analytics?date=#{date}"))}
endThe date is written with PhoenixKit.Utils.Date.short_with_year/1, in
the viewer's language.
Summary
Functions
Reads a "YYYY-MM-DD" URL or form value into a date. Anything that is
not a date — missing, garbage — is today; a date outside min / max
is clamped to the nearer end.