### LiveView Template for Empty State Handling Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_mysql/AGENTS.md Provides an example of handling empty states in LiveView streams using Tailwind CSS classes. This approach is used when direct counting or empty state checks on the stream are not supported. ```html
{task.name}
``` -------------------------------- ### Install Phoenix Analytics dependency Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/README.md Add the phoenix_analytics package to your project's mix.exs file to include it as a dependency. ```elixir def deps do [ {:phoenix_analytics, "~> 0.4"} ] end ``` -------------------------------- ### Render LiveView Form in Template (HEEx) Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_sqlite/AGENTS.md Shows how to render a form in a Phoenix LiveView HEEx template using the `<.form>` function component, passing the form assign created with `to_form/1`. It also includes an example of rendering an input field. ```heex <.form for={@form} id="todo-form" phx-change="validate" phx-submit="save"> <.input field={@form[:field]} type="text" /> ``` -------------------------------- ### GET /analytics/popular-content Source: https://context7.com/lalabuy948/phoenixanalytics/llms.txt Retrieves popular pages, referrers, 404 errors, and device distribution metrics. ```APIDOC ## GET /analytics/popular-content ### Description Fetches aggregated analytics data for pages, referrers, and device types. ### Method GET ### Endpoint /analytics/popular-content ### Parameters #### Query Parameters - **from_date** (string) - Required - Start date - **to_date** (string) - Required - End date ### Response #### Success Response (200) - **data** (array) - List of objects containing source and visit counts #### Response Example [ {"source": "/", "visits": 500}, {"source": "/products", "visits": 350} ] ``` -------------------------------- ### GET /analytics/time-series Source: https://context7.com/lalabuy948/phoenixanalytics/llms.txt Retrieves analytics data grouped by time intervals for trend analysis. ```APIDOC ## GET /analytics/time-series ### Description Returns metrics like visits or requests grouped by hour, day, month, or year. ### Method GET ### Endpoint /analytics/time-series ### Parameters #### Query Parameters - **interval** (string) - Required - One of: hour, day, month, year - **from_date** (string) - Required - **to_date** (string) - Required ### Response #### Success Response (200) - **data** (array) - Time-series data points #### Response Example [ {"date": "2024-01-01", "visits": 150, "unique_visitors": 100} ] ``` -------------------------------- ### Optimize Queries with Cache Service Source: https://context7.com/lalabuy948/phoenixanalytics/llms.txt Provides patterns for getting, adding, and fetching analytics data with automatic caching to reduce database load. ```elixir alias PhoenixAnalytics.Services.Cache {:ok, value} = Cache.get("analytics:visitors:2024-01") Cache.add("analytics:visitors:2024-01", 1234) result = Cache.fetch("analytics:visitors:2024-01", fn -> repo = MyApp.Repo query = PhoenixAnalytics.Queries.Analytics.unique_visitors("2024-01-01", "2024-01-31") repo.one(query) end) ``` -------------------------------- ### GET /analytics/average-views Source: https://context7.com/lalabuy948/phoenixanalytics/llms.txt Retrieves the average number of page views per visit within a specified date range. ```APIDOC ## GET /analytics/average-views ### Description Calculates the average views per visit for the given timeframe. ### Method GET ### Endpoint /analytics/average-views ### Parameters #### Query Parameters - **from_date** (string) - Required - Start date in YYYY-MM-DD HH:MM:SS format - **to_date** (string) - Required - End date in YYYY-MM-DD HH:MM:SS format ### Response #### Success Response (200) - **avg_views** (float) - The calculated average views per visit #### Response Example { "avg_views": 3.5 } ``` -------------------------------- ### Creating Forms from Params Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_sqlite/AGENTS.md Illustrates how to initialize a form from event parameters, optionally nesting them under a specific name. ```elixir def handle_event("submitted", params, socket) do {:noreply, assign(socket, form: to_form(params))} end def handle_event("submitted", %{"user" => user_params}, socket) do {:noreply, assign(socket, form: to_form(user_params, as: :user))} end ``` -------------------------------- ### Managing LiveView Streams Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_sqlite/AGENTS.md Demonstrates how to implement LiveView streams for efficient list rendering, including appending, resetting, and handling empty states in templates. ```elixir stream(socket, :messages, [new_msg]) stream(socket, :messages, [new_msg], reset: true) stream(socket, :messages, [new_msg], at: -1) stream_delete(socket, :messages, msg) ``` ```heex
{msg.text}
``` -------------------------------- ### Create a form from a changeset Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_mysql/AGENTS.md Demonstrates how to initialize a form assign in a LiveView module using an Ecto changeset. This process automatically handles data, parameters, and error mapping for the form. ```elixir %MyApp.Users.User{} |> Ecto.Changeset.change() |> to_form() ``` -------------------------------- ### Configure Phoenix Analytics Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/README.md Set up the repository and application domain in your environment configuration file. ```elixir config :phoenix_analytics, repo: MyApp.Repo, app_domain: System.get_env("PHX_HOST") || "example.com", cache_ttl: System.get_env("CACHE_TTL") || 60 ``` -------------------------------- ### Run database migrations Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/README.md Generate and execute migrations to create the necessary analytics tables in your database. ```shell mix ecto.gen.migration add_phoenix_analytics ``` ```elixir defmodule MyApp.Repo.Migrations.AddPhoenixAnalytics do use Ecto.Migration def up, do: PhoenixAnalytics.Migration.up() def down, do: PhoenixAnalytics.Migration.down() end ``` ```shell mix ecto.migrate ``` -------------------------------- ### Creating LiveView Form from Event Params Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_mysql/AGENTS.md Shows how to create a form assignable within a LiveView from parameters received in an `handle_event`. The `to_form/1` function is used, expecting string keys in the map. ```elixir def handle_event("submitted", params, socket) do {:noreply, assign(socket, form: to_form(params))} end ``` -------------------------------- ### Run Database Migrations Source: https://context7.com/lalabuy948/phoenixanalytics/llms.txt Define and execute Ecto migrations to create the necessary analytics tables and indexes in your database. ```elixir defmodule MyApp.Repo.Migrations.AddPhoenixAnalytics do use Ecto.Migration def up, do: PhoenixAnalytics.Migration.up() def down, do: PhoenixAnalytics.Migration.down() end defmodule MyApp.Repo.Migrations.AddPhoenixAnalyticsIndexes do use Ecto.Migration def change do PhoenixAnalytics.Migration.add_indexes() end end ``` -------------------------------- ### Phoenix LiveView Navigation with `<.link>` Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_sqlite/AGENTS.md Demonstrates the modern approach to navigation in Phoenix LiveView using the `<.link>` component for `navigate` and `patch` actions. It replaces deprecated functions like `live_redirect` and `live_patch`. ```heex <.link navigate={@href}>Navigate <.link patch={@href}>Patch ``` -------------------------------- ### Implement Distributed Analytics with PubSub Source: https://context7.com/lalabuy948/phoenixanalytics/llms.txt Demonstrates how to subscribe to request events and broadcast logs across multiple nodes for real-time dashboards. ```elixir alias PhoenixAnalytics.Services.PubSub PubSub.subscribe() request_log = %RequestLog{...} PubSub.broadcast(request_log) receive do {:request_sent, request_log} -> IO.inspect(request_log) end ``` -------------------------------- ### Correct Form and Input Usage in LiveView Template (HEEx) Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_sqlite/AGENTS.md Illustrates the correct way to use the `<.form>` and `<.input>` components in a LiveView template by always referencing the form assign (`@form`). It contrasts this with the incorrect method of directly accessing the changeset. ```heex <%!-- ALWAYS do this (valid) --%> <.form for={@form} id="my-form"> <.input field={@form[:field]} type="text" /> <%!-- NEVER do this (invalid) --%> <%!-- <.form for={@changeset} id="my-form"> <.input field={@changeset[:field]} type="text" /> --%> ``` -------------------------------- ### HEEx List Comprehension for Template Content Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_postgres/AGENTS.md Demonstrates the correct way to generate template content using comprehensions in HEEx. It emphasizes using `<%= for ... %>` for iterating over collections and generating HTML, avoiding non-for comprehensions. ```heex <%= for item <- @collection do %> ... item ... <% end %> ``` -------------------------------- ### LiveView Stream Operations for Collections Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_mysql/AGENTS.md Demonstrates essential operations for managing collections using LiveView streams, including appending, resetting, prepending, and deleting items. These methods are crucial for efficient handling of dynamic data to prevent memory issues. ```elixir stream(socket, :messages, [new_msg]) stream(socket, :messages, [new_msg], reset: true) stream(socket, :messages, [new_msg], at: -1) stream_delete(socket, :messages, msg) ``` -------------------------------- ### LiveView Stream Operations Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_postgres/AGENTS.md Demonstrates essential operations for managing collections using LiveView streams, including appending, resetting, prepending, and deleting items. It emphasizes avoiding memory issues and runtime errors with large collections. ```elixir socket |> stream(:messages, [new_msg]) socket |> stream(:messages, [new_msg], reset: true) socket |> stream(:messages, [new_msg], at: -1) stream_delete(socket, :messages, msg) ``` -------------------------------- ### Retrieve Analytics Metrics in Elixir Source: https://context7.com/lalabuy948/phoenixanalytics/llms.txt Demonstrates how to query average views per visit, popular pages, referrers, 404 errors, and device distributions using the PhoenixAnalytics query module. ```elixir from_date = "2024-01-01 00:00:00" to_date = "2024-01-31 23:59:59" repo = MyApp.Repo query = PhoenixAnalytics.Queries.Analytics.average_views_per_visit(from_date, to_date) avg_views = repo.one(query) query = PhoenixAnalytics.Queries.Analytics.popular_pages(from_date, to_date) popular = repo.all(query) query = PhoenixAnalytics.Queries.Analytics.popular_referer(from_date, to_date) referrers = repo.all(query) query = PhoenixAnalytics.Queries.Analytics.popular_not_found(from_date, to_date) not_found = repo.all(query) query = PhoenixAnalytics.Queries.Analytics.popular_device_types(from_date, to_date) devices = repo.all(query) ``` -------------------------------- ### Create LiveView Form from Changeset (Elixir) Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_sqlite/AGENTS.md Demonstrates how to create a form assign from an Ecto changeset in a LiveView module. This form assign is then used to render the form in the template. The `:as` option is automatically computed. ```elixir defmodule MyApp.Users.User do use Ecto.Schema ... end # In LiveView module: # Assuming you have a changeset available as @changeset {:ok, socket} = assign(socket, :form, to_form(changeset)) # Or directly from a new changeset: changeset = %MyApp.Users.User{} |> Ecto.Changeset.change() {:ok, socket} = assign(socket, :form, to_form(changeset)) ``` -------------------------------- ### Phoenix HEEx Form Handling with Components Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_sqlite/AGENTS.md Demonstrates the correct way to build forms in Phoenix using HEEx components. It emphasizes using `Phoenix.Component.form/1` and `Phoenix.Component.inputs_for/1`, and accessing form data via `@form[:field]`. Avoids deprecated functions like `Phoenix.HTML.form_for`. ```heex <.form for={@form} id="msg-form"> ... access fields like @form[:field] ... ``` -------------------------------- ### Manage Request Logs with Batcher Service Source: https://context7.com/lalabuy948/phoenixanalytics/llms.txt Explains the automatic batching mechanism for request logs and how to manually insert logs into the system. ```elixir alias PhoenixAnalytics.Services.Batcher alias PhoenixAnalytics.Entities.RequestLog request_log = %RequestLog{ request_id: Ecto.UUID.generate(), method: "GET", path: "/api/users", status_code: 200, duration_ms: 45 } Batcher.insert(request_log) ``` -------------------------------- ### LiveView Template for Stream Consumption Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_mysql/AGENTS.md Illustrates the required structure for a LiveView template to consume and display data from a stream. It emphasizes setting `phx-update="stream"` on the parent element and using the stream name as the DOM ID for child elements. ```html
{msg.text}
``` -------------------------------- ### Filtering Data with LiveView Streams Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_sqlite/AGENTS.md Shows how to filter data by refetching and re-streaming the collection with the reset option, as streams are not enumerable. ```elixir def handle_event("filter", %{"filter" => filter}, socket) do messages = list_messages(filter) {:noreply, socket |> assign(:messages_empty?, messages == []) |> stream(:messages, messages, reset: true)} end ``` -------------------------------- ### LiveViewTest Element Assertions Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_mysql/AGENTS.md Demonstrates how to use `Phoenix.LiveViewTest` and `LazyHTML` for writing robust tests. It emphasizes referencing element IDs from templates and avoiding raw HTML testing in favor of element presence checks. ```elixir assert has_element?(view, "#my-form") ``` -------------------------------- ### HEEx List Comprehensions for Template Content Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_mysql/AGENTS.md Shows the correct syntax for generating template content using list comprehensions in HEEx. It mandates the use of `<%= for ... %>` for iterating over collections, discouraging the use of `<% Enum.each %>`. ```HEEx <%= for item <- @collection do %>
<%= item %>
<% end %> ``` -------------------------------- ### HEEx List Comprehension for Template Content Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_sqlite/AGENTS.md Illustrates the correct way to generate lists of elements within HEEx templates using `Enum.each` is discouraged. Instead, use the `<%= for ... %>` syntax for comprehensions to render collections. ```heex <%= for item <- @collection do %> ... render item ... <% end %> ``` -------------------------------- ### Refetching and Resetting LiveView Streams Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_mysql/AGENTS.md Shows how to refetch data and reset an entire stream collection with `reset: true` when filtering or updating items. This is the recommended approach as LiveView streams are not enumerable. ```elixir def handle_event("filter", %{"filter" => filter}, socket) do # re-fetch the messages based on the filter messages = list_messages(filter) {:noreply, socket |> assign(:messages_empty?, messages == []) # reset the stream with the new messages |> stream(:messages, messages, reset: true)} end ``` -------------------------------- ### Enable tracking and dashboard Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/README.md Register the request tracker plug in your endpoint and define the dashboard route in your router. ```elixir plug PhoenixAnalytics.Plugs.RequestTracker ``` ```elixir use PhoenixAnalytics.Web, :router phoenix_analytics_dashboard "/analytics" ``` -------------------------------- ### Creating Nested LiveView Form from Event Params Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_mysql/AGENTS.md Demonstrates how to create a nested form assignable within a LiveView from event parameters. The `to_form/2` function with the `as:` option is used to specify the parameter nesting. ```elixir def handle_event("submitted", %{"user" => user_params}, socket) do {:noreply, assign(socket, form: to_form(user_params, as: :user))} end ``` -------------------------------- ### Create LiveView Form from Changeset in Elixir Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_postgres/AGENTS.md Demonstrates how to create a form assignable for LiveView templates by converting an Ecto changeset. This process involves piping the changeset through `Ecto.Changeset.change/1` and then `to_form/1`. The resulting form assign can be passed to the `<.form>` component in the template. ```elixir defmodule MyApp.Users.User do use Ecto.Schema ... end # In LiveView module: # Assuming you have a changeset named `changeset` form_assign = %MyApp.Users.User{} |> Ecto.Changeset.change() |> to_form() ``` -------------------------------- ### HEEx Conditional Class Attributes Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_sqlite/AGENTS.md Demonstrates the correct syntax for applying conditional CSS classes in HEEx templates using list syntax `[...]`. It shows how to combine static classes with dynamically added ones based on conditions, including nested `if` expressions. ```heex Text ``` -------------------------------- ### HEEx Class Attribute List Syntax for Conditional Classes Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_mysql/AGENTS.md Demonstrates the correct way to use the class attribute in HEEx templates when dealing with multiple or conditional classes. It requires using the list `[...]` syntax and wrapping `if` expressions within `{...}` with parentheses. ```HEEx Text ``` -------------------------------- ### Elixir Conditional Logic with `cond` Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_sqlite/AGENTS.md Illustrates the correct way to handle multiple conditional statements in Elixir HEEx templates. It shows how to use the `cond` block, which is preferred over `if/else if` or `if/elsif` for clarity and correctness. ```elixir <%= cond do %> <% condition -> %> ... <% condition2 -> %> ... <% true -> %> ... <% end %> ``` -------------------------------- ### Utilize Phoenix Analytics Utility Functions Source: https://context7.com/lalabuy948/phoenixanalytics/llms.txt Provides helper functions for identifying device types from user agents, generating database-compatible timestamps, creating UUIDs, and detecting the active database type. ```elixir alias PhoenixAnalytics.Services.Utility # Get device type from user agent string Utility.get_device_type("Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X)...") # => "mobile" Utility.get_device_type("Mozilla/5.0 (iPad; CPU OS 14_4 like Mac OS X)...") # => "tablet" Utility.get_device_type("Mozilla/5.0 (Windows NT 10.0; Win64; x64)...") # => "desktop" # Get current timestamp in database-compatible format Utility.inserted_at() # => "2024-01-15 14:30:45.123" # Generate UUID Utility.uuid() # => "550e8400-e29b-41d4-a716-446655440000" # Detect configured database type Utility.database_type() # => :postgres | :sqlite | :mysql ``` -------------------------------- ### POST /batcher/insert Source: https://context7.com/lalabuy948/phoenixanalytics/llms.txt Manually insert a request log into the batching service. ```APIDOC ## POST /batcher/insert ### Description Adds a request log to the batcher for bulk insertion into the database. ### Method POST ### Endpoint /batcher/insert ### Request Body - **request_id** (string) - Required - **method** (string) - Required - **path** (string) - Required - **status_code** (integer) - Required ### Response #### Success Response (200) - **status** (string) - Confirmation of insertion ``` -------------------------------- ### Phoenix LiveView Testing with LazyHTML Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_postgres/AGENTS.md Details the use of `Phoenix.LiveViewTest` and `LazyHTML` for writing assertions in LiveView tests. It emphasizes referencing element IDs, testing outcomes, and avoiding raw HTML testing. ```elixir assert has_element?(view, "#my-form") html = render(view) document = LazyHTML.from_fragment(html) matches = LazyHTML.filter(document, "your-complex-selector") IO.inspect(matches, label: "Matches") ``` -------------------------------- ### Ecto Association Preloading Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_mysql/AGENTS.md Illustrates the importance of preloading Ecto associations when they will be accessed in templates to avoid N+1 query problems. This ensures that related data is fetched efficiently. ```elixir # Example of preloading an association query = from u in User, preload: [:posts] Repo.all(query) ``` -------------------------------- ### Ecto Changeset Programmatic Field Setting Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_mysql/AGENTS.md Explains how to handle fields that are set programmatically (e.g., `user_id`) by not including them in `cast` calls and instead setting them directly when creating the struct. This is a security best practice. ```elixir # Incorrect: Including user_id in cast # changeset = cast(struct, params, ~w(name email user_id)) # Correct: Setting user_id programmatically changeset = cast(struct, params, ~w(name email)) |> put_assoc(:user, user_struct) # or similar direct assignment ``` -------------------------------- ### Define Phoenix Scoped Routes Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_sqlite/AGENTS.md Demonstrates how to use scope blocks in Phoenix to automatically alias controller or live view modules. This prevents redundant module prefixes in route definitions. ```elixir scope "/admin", AppWeb.Admin do pipe_through :browser live "/users", UserLive, :index end ``` -------------------------------- ### Integrate Request Tracker Plug Source: https://context7.com/lalabuy948/phoenixanalytics/llms.txt Add the RequestTracker plug to your endpoint or router to begin capturing HTTP request metrics. ```elixir plug PhoenixAnalytics.Plugs.RequestTracker ``` -------------------------------- ### Query Time-Series Analytics in Elixir Source: https://context7.com/lalabuy948/phoenixanalytics/llms.txt Shows how to fetch time-series data grouped by intervals like 'day' or 'hour' for trend analysis and performance monitoring. ```elixir from_date = "2024-01-01 00:00:00" to_date = "2024-01-31 23:59:59" repo = MyApp.Repo query = PhoenixAnalytics.Queries.Analytics.visits_per_period(from_date, to_date, "day") daily_visits = repo.all(query) query = PhoenixAnalytics.Queries.Analytics.slowest_pages(from_date, to_date) slow_pages = repo.all(query) ``` -------------------------------- ### Accessing List Elements in Elixir Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_sqlite/AGENTS.md Demonstrates the correct way to access elements in an Elixir list by index. Since Elixir lists do not support index-based access syntax, developers must use Enum.at/2 or pattern matching. ```elixir i = 0 mylist = ["blue", "green"] # Correct way to access by index value = Enum.at(mylist, i) ``` -------------------------------- ### Debugging LiveView Tests Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_sqlite/AGENTS.md Provides a pattern for debugging failed test selectors by inspecting the rendered HTML fragment using LazyHTML. ```elixir html = render(view) document = LazyHTML.from_fragment(html) matches = LazyHTML.filter(document, "your-complex-selector") IO.inspect(matches, label: "Matches") ``` -------------------------------- ### HEEx Interpolation within Tags and Attributes Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_sqlite/AGENTS.md Explains the correct usage of interpolation in HEEx templates. It highlights that `{...}` should be used for attribute interpolation and within tag bodies, while `<%= ... %>` is for block constructs (if, cond, case, for) within tag bodies. ```heex
{@my_assign} <%= if @some_block_condition do %> {@another_assign} <% end %>
``` -------------------------------- ### Binding Expressions in Elixir Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_sqlite/AGENTS.md Illustrates the correct approach to binding results from conditional expressions in Elixir. Because variables are immutable, results must be assigned to a variable rather than attempting to rebind inside a block. ```elixir socket = if connected?(socket) do assign(socket, :val, val) else socket end ``` -------------------------------- ### Configure Dashboard Routes Source: https://context7.com/lalabuy948/phoenixanalytics/llms.txt Expose the built-in analytics dashboard by adding the dashboard route macro to your Phoenix router. ```elixir use PhoenixAnalytics.Web, :router phoenix_analytics_dashboard "/analytics" phoenix_analytics_dashboard "/admin/analytics", as: :admin_analytics_dashboard, on_mount: [MyAppWeb.AuthHook], root_layout: {MyAppWeb.Layouts, :admin_root} ``` -------------------------------- ### HEEx HTML Comment Syntax Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_sqlite/AGENTS.md Specifies the correct syntax for creating HTML comments within HEEx templates. It uses the `<%!-- comment --%>` syntax, ensuring comments are properly processed by the HEEx engine. ```heex <%!-- This is a HEEx HTML comment --%> ``` -------------------------------- ### Ecto Changeset Field Access Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_mysql/AGENTS.md Demonstrates the correct method for accessing fields within an Ecto.Changeset using `Ecto.Changeset.get_field/3`. This is the recommended way to retrieve field values from a changeset. ```elixir changeset = %YourSchema.Changeset{} field_value = Ecto.Changeset.get_field(changeset, :your_field_name) ``` -------------------------------- ### Correct vs Incorrect form access Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_mysql/AGENTS.md Highlights the mandatory pattern of accessing form fields via the form assign rather than the changeset directly. Direct changeset access in templates is unsupported and causes runtime errors. ```html+heex <%!-- Valid pattern --%> <.form for={@form} id="my-form"> <.input field={@form[:field]} type="text" /> <%!-- Invalid pattern --%> <.form for={@changeset} id="my-form"> <.input field={@changeset[:field]} type="text" /> ``` -------------------------------- ### Ecto Schema Field Definition Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_mysql/AGENTS.md Shows the convention of using the `:string` type for all Ecto.Schema fields, including those that map to `:text` columns in the database. This ensures consistency in schema definitions. ```elixir defmodule MyApp.User do use Ecto.Schema schema "users" do field :name, :string field :email, :string # ... other fields timestamps() end end ``` -------------------------------- ### Query Analytics Data Source: https://context7.com/lalabuy948/phoenixanalytics/llms.txt Use the provided query modules to programmatically retrieve metrics like unique visitors, pageviews, and response times. ```elixir query = PhoenixAnalytics.Queries.Analytics.unique_visitors(from_date, to_date) repo.one(query) query = PhoenixAnalytics.Queries.Analytics.total_pageviews(from_date, to_date) repo.one(query) query = PhoenixAnalytics.Queries.Analytics.average_response_time(from_date, to_date) repo.one(query) ``` -------------------------------- ### Incorrect Usage of LiveView Form Components in HEEx Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_postgres/AGENTS.md Highlights an anti-pattern in Phoenix LiveView HEEx templates where a changeset is directly passed to the `<.form>` component or its fields are accessed directly from the changeset. This is explicitly forbidden and will lead to errors. Always use a form assign derived from `to_form/2`. ```heex <%!-- NEVER do this (invalid) --%> <.form for={@changeset} id="my-form"> <.input field={@changeset[:field]} type="text" /> ``` -------------------------------- ### Phoenix LiveView JS Hook with `phx-update="ignore"` Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_sqlite/AGENTS.md Explains the requirement to use `phx-update="ignore"` when a JS hook manages its own DOM manipulation. This prevents LiveView from attempting to reconcile changes that the hook has already handled. ```heex
``` -------------------------------- ### HEEx Literal Curly Brace Interpolation Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_sqlite/AGENTS.md Shows how to display literal curly braces `{` and `}` within HEEx templates, particularly in code blocks like `
` or ``. The `phx-no-curly-interpolation` attribute is used to disable automatic interpolation.

```heex

  let obj = {key: "val"}

```

--------------------------------

### Binding Results of Conditional Expressions in Elixir

Source: https://github.com/lalabuy948/phoenixanalytics/blob/master/examples/phoenix_mysql/AGENTS.md

Elixir variables are immutable. This snippet shows how to correctly bind the result of a conditional expression to a variable instead of attempting to rebind inside the block.

```elixir
socket = 
  if connected?(socket) do
    assign(socket, :val, val)
  end
```

=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.