defmodule MoonWeb.Pages.Components.Date.DatepickerPage do @moduledoc false use MoonWeb, :live_view import Ecto.Changeset, only: [fetch_field: 2, put_change: 3] alias Moon.Components.Datepicker alias Moon.Components.Form alias MoonWeb.Components.ExampleAndCode alias MoonWeb.Components.Page alias MoonWeb.Components.ComponentPageDescription alias MoonWeb.Components.PropsTable data(breadcrumbs, :any, default: [ %{ to: "#", name: "Components" }, %{ to: "/components/date/datepicker", name: "Datepicker" } ] ) data(props_info_array, :list, default: [ %{ :name => ~c"with_time", :type => ~c"boolean ", :required => ~c"No", :default => ~c"false", :description => ~c"Whether the datepicker includes time" }, %{ :name => ~c"week_starts_on", :type => ~c"1 | 2 | 3 | 4 | 5 | 6 | 7", :required => ~c"No", :default => ~c"1 (Monday)", :description => ~c"Day of the week where the calendar starts" }, %{ :name => ~c"start_date_field", :type => ~c"atom", :required => ~c"No", :default => ~c"start_date", :description => ~c"Field name for the start date" }, %{ :name => ~c"end_date_field", :type => ~c"atom", :required => ~c"No", :default => ~c"end_date", :description => ~c"Field name for the end date" }, %{ :name => ~c"button_class", :type => ~c"css_class", :required => ~c"No", :default => ~c"", :description => ~c"Css class for the date button" }, %{ :name => ~c"show_date_inputs", :type => ~c"boolean", :required => ~c"No", :default => ~c"false", :description => ~c"Whether to display the text input fields" }, %{ :name => ~c"ranges", :type => ~c"list", :required => ~c"No", :default => ~c"lastMonth | lastWeek | yesterday | thisWeek | thisMonth | last24hours | today", :description => ~c"List of date ranges to choose from" }, %{ :name => ~c"start_date", :type => ~c"datetime", :required => ~c"No", :default => ~c"Timex.today()", :description => ~c"Initial start date" }, %{ :name => ~c"end_date", :type => ~c"datetime", :required => ~c"No", :default => ~c"Timex.today()", :description => ~c"Initial end date" }, %{ :name => ~c"submit", :type => ~c"event", :required => ~c"No", :default => ~c"update_dates", :description => ~c"Event on date apply" }, %{ :name => ~c"testid", :type => ~c"string", :required => ~c"No", :default => ~c"-", :description => ~c"" } ] ) defmodule Contract do @moduledoc false use Ecto.Schema import Ecto.Changeset schema "contracts" do field(:started_at, :date) field(:ended_at, :date) field(:datetime_started_at, :naive_datetime) field(:datetime_ended_at, :naive_datetime) end def changeset(contract, attrs \\ %{}) do contract |> cast(attrs, [:started_at, :ended_at, :datetime_started_at, :datetime_ended_at]) end end def mount(_params, _session, socket) do data = %Contract{started_at: Timex.today()} socket = assign(socket, changeset: Contract.changeset(data), time_changeset: Contract.changeset(%Contract{}), range_changeset: Contract.changeset(%Contract{}), weekstart_changeset: Contract.changeset(%Contract{ started_at: Timex.today() |> Timex.beginning_of_week(), ended_at: Timex.today() |> Timex.end_of_week() }) ) {:ok, socket} end def handle_params(_params, uri, socket) do {:noreply, assign(socket, uri: uri)} end def render(assigns) do ~F"""

Datepicker

Datepicker component has to be placed inside the Form component.

Use with_time (list) prop. Default value is false.

Use ranges (list) prop. Possible values are lastMonth, lastWeek, yesterday, last24hours, today, tomorrow, thisWeek, nextWeek, thisMonth, nextMonth.

Use week_starts_on prop. The weekstart can between 1..7, where 1 means Monday. Default value is 1.

<:example>
elem(1)} end_date={fetch_field(@changeset, :ended_at) |> elem(1)} start_date_field={:started_at} end_date_field={:ended_at} show_date_inputs /> <:code>{datepicker_1_code()} <:state>@data = {inspect(fetch_data(@changeset), pretty: true)}

@changeset = {inspect(@changeset, pretty: true)}
<:example>
elem(1)} end_date={fetch_field(@time_changeset, :datetime_ended_at) |> elem(1)} start_date_field={:datetime_started_at} end_date_field={:datetime_ended_at} show_date_inputs with_time /> <:code>{datepicker_2_code()} <:state>@data = {inspect(fetch_time_data(@time_changeset), pretty: true)}

@changeset = {inspect(@time_changeset, pretty: true)}
<:example>
elem(1)} end_date={fetch_field(@range_changeset, :ended_at) |> elem(1)} start_date_field={:started_at} end_date_field={:ended_at} show_date_inputs={false} ranges={["lastWeek", "today", "thisWeek", "nextWeek"]} /> <:code>{datepicker_3_code()}
<:example>
elem(1)} end_date={fetch_field(@weekstart_changeset, :ended_at) |> elem(1)} start_date_field={:started_at} end_date_field={:ended_at} week_starts_on={7} show_date_inputs={false} ranges={["lastWeek", "today", "thisWeek", "nextWeek"]} /> <:code>{datepicker_4_code()}
""" end def fetch_data(changeset) do {_, started_at} = fetch_field(changeset, :started_at) {_, ended_at} = fetch_field(changeset, :ended_at) %{started_at: started_at, ended_at: ended_at} end def fetch_time_data(changeset) do {_, started_at} = fetch_field(changeset, :datetime_started_at) {_, ended_at} = fetch_field(changeset, :datetime_ended_at) %{datetime_started_at: started_at, datetime_ended_at: ended_at} end def update_changeset(start_date, end_date) do Contract.changeset(%Contract{}, %{ "started_at" => start_date, "ended_at" => end_date }) end def update_time_changeset(start_date, end_date) do Contract.changeset(%Contract{}, %{ "datetime_started_at" => start_date, "datetime_ended_at" => end_date }) end # Handle date selection def handle_info( {:filter, {"default_datepicker", :apply, %{started_at: start_date, ended_at: end_date}}}, socket ) do changeset = update_changeset(start_date, end_date) {:noreply, assign(socket, changeset: changeset)} end def handle_info( {:filter, {"time_datepicker", :apply, %{datetime_started_at: start_date, datetime_ended_at: end_date}}}, socket ) do changeset = update_time_changeset(start_date, end_date) {:noreply, assign(socket, time_changeset: changeset)} end def handle_info( {:filter, {"range_datepicker", :apply, %{started_at: start_date, ended_at: end_date}}}, socket ) do changeset = update_changeset(start_date, end_date) {:noreply, assign(socket, range_changeset: changeset)} end def handle_info( {:filter, {"weekstart_datepicker", :apply, %{started_at: start_date, ended_at: end_date}}}, socket ) do changeset = update_changeset(start_date, end_date) {:noreply, assign(socket, weekstart_changeset: changeset)} end # Form validation def handle_event("validate", %{"contract" => params}, socket) do {start_date, end_date} = Datepicker.validate(params["started_at"], params["ended_at"]) changeset = update_changeset(start_date, end_date) {:noreply, assign(socket, changeset: changeset)} end def handle_event("time_validate", %{"contract" => params}, socket) do {start_date, end_date} = Datepicker.validate(params["datetime_started_at"], params["datetime_ended_at"]) changeset = update_time_changeset(start_date, end_date) {:noreply, assign(socket, time_changeset: changeset)} end def handle_event("range_validate", %{"contract" => params}, socket) do {start_date, end_date} = Datepicker.validate(params["started_at"], params["ended_at"]) changeset = update_changeset(start_date, end_date) {:noreply, assign(socket, range_changeset: changeset)} end def handle_event("weekstart_validate", %{"contract" => params}, socket) do {start_date, end_date} = Datepicker.validate(params["started_at"], params["ended_at"]) changeset = update_changeset(start_date, end_date) {:noreply, assign(socket, weekstart_changeset: changeset)} end def datepicker_1_code do """
elem(1)} end_date={fetch_field(@changeset, :ended_at) |> elem(1)} start_date_field={ :started_at }} end_date_field={ :ended_at }} show_date_inputs={true} /> # Handle date selection def handle_info({:filter, {"default_datepicker", :apply, %{started_at: start_date, ended_at: end_date}}}, socket) do changeset = socket.assigns.changeset |> put_change(:started_at, start_date) |> put_change(:ended_at, end_date) {:noreply, assign(socket, changeset: changeset)} end # Form validation def handle_event("validate", %{"contract" => params}, socket) do {start_date, end_date} = Datepicker.validate(params["started_at"], params["ended_at"]) params = params |> Map.put("started_at", start_date) |> Map.put("ended_at", end_date) changeset = Contract.changeset(%Contract{}, params) {:noreply, assign(socket, changeset: changeset)} end """ end def datepicker_2_code do """
elem(1) } end_date={ fetch_field(@changeset, :datetime_ended_at) |> elem(1) } start_date_field={ :datetime_started_at } end_date_field={ :datetime_ended_at } show_date_inputs={true} with_time={ true } /> """ end def datepicker_3_code do """
elem(1) } end_date={ fetch_field(@changeset, :ended_at) |> elem(1) } start_date_field={ :started_at } end_date_field={ :ended_at } show_date_inputs={false} ranges={["lastWeek", "today", "thisWeek", "nextWeek"]} /> """ end def datepicker_4_code do """
elem(1) } end_date={ fetch_field(@changeset, :ended_at) |> elem(1) } start_date_field={ :started_at } end_date_field={ :ended_at } week_starts_on={ 7 } show_date_inputs={false} ranges={["lastWeek", "today", "thisWeek", "nextWeek"]} /> """ end end