How to structure a large live view app?

I am suggesting a technique I learned from the book Absinthe/GraphQL…

For example…

  def list_requests_query(criteria \\ []) do
    query = from(p in Request)

    Enum.reduce(criteria, query, fn
      {:limit, limit}, query ->
        from p in query, limit: ^limit

      {:offset, offset}, query ->
        from p in query, offset: ^offset

      {:filter, filters}, query ->
        filter_with(filters, query)

      {:order, order}, query ->
        from p in query, order_by: [{^order, ^@order_field}]

      {:preload, preloads}, query ->
        from p in query, preload: ^preloads

      arg, query ->
        Logger.info("args is not matched in query #{inspect(arg)}")
        query
    end)
  end

  defp filter_with(filters, query) do
    Enum.reduce(filters, query, fn
      {:user_id, user_id}, query ->
        from q in query, where: q.user_id == ^user_id

      {:is_fetched, is_fetched}, query ->
        from q in query, where: q.is_fetched == ^is_fetched

      {:is_post_processed, is_post_processed}, query ->
        from q in query, where: q.is_post_processed == ^is_post_processed

      {:with_medium_path, true}, query ->
        from q in query, where: not is_nil(q.medium_path)

      {:with_medium_path, false}, query ->
        from q in query, where: is_nil(q.medium_path)

      arg, query ->
        Logger.info("args is not matched in query #{inspect(arg)}")
        query
    end)
  end

  def list_requests(criteria \\ []) do
    criteria
    |> list_requests_query()
    |> Repo.all()
  end

Using this, I could probably do something like…

        filter by location
        filter by category
        move to the next month
        move to the previous month
        show/hide the events that already have occured this month
        filter by the person who created the event

… and this would translate to

[filter: [by_location: location, by_category: category, by_month: month ...]]
|> App.list_requests()
17 Likes