From ee960784f9e7e08d71f06afde0b54879ec3343dc Mon Sep 17 00:00:00 2001
From: rebebop <1941785+rebebop@users.noreply.github.com>
Date: Wed, 7 Aug 2024 16:14:18 +0200
Subject: [PATCH] Add github workflow and basic models
---
.github/workflows/docker-build.yml | 53 +++++++++
lib/mentat/activities.ex | 104 ++++++++++++++++
lib/mentat/activities/activity_record.ex | 53 +++++++++
.../activity_record_live/form_component.ex | 112 ++++++++++++++++++
.../live/activity_record_live/index.ex | 47 ++++++++
.../live/activity_record_live/index.html.heex | 56 +++++++++
.../live/activity_record_live/show.ex | 21 ++++
.../live/activity_record_live/show.html.heex | 31 +++++
.../live/provider_live/form_component.ex | 6 +-
.../live/provider_live/index.html.heex | 8 +-
lib/mentat_web/router.ex | 14 +++
...20240807135812_create_activity_records.exs | 23 ++++
test/mentat/activities_test.exs | 69 +++++++++++
.../live/activity_record_live_test.exs | 108 +++++++++++++++++
test/support/fixtures/activities_fixtures.ex | 25 ++++
15 files changed, 728 insertions(+), 2 deletions(-)
create mode 100644 .github/workflows/docker-build.yml
create mode 100644 lib/mentat/activities.ex
create mode 100644 lib/mentat/activities/activity_record.ex
create mode 100644 lib/mentat_web/live/activity_record_live/form_component.ex
create mode 100644 lib/mentat_web/live/activity_record_live/index.ex
create mode 100644 lib/mentat_web/live/activity_record_live/index.html.heex
create mode 100644 lib/mentat_web/live/activity_record_live/show.ex
create mode 100644 lib/mentat_web/live/activity_record_live/show.html.heex
create mode 100644 priv/repo/migrations/20240807135812_create_activity_records.exs
create mode 100644 test/mentat/activities_test.exs
create mode 100644 test/mentat_web/live/activity_record_live_test.exs
create mode 100644 test/support/fixtures/activities_fixtures.ex
diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml
new file mode 100644
index 0000000..ad4c529
--- /dev/null
+++ b/.github/workflows/docker-build.yml
@@ -0,0 +1,53 @@
+name: Build and upload docker image
+
+on:
+ push:
+ branches: ["main"]
+ pull_request:
+ branches: ["main"]
+
+env:
+ REGISTRY: ghcr.io
+ IMAGE_NAME: ${{ github.repository }}
+
+jobs:
+ build-and-push-image:
+ runs-on: ubuntu-latest
+
+ permissions:
+ contents: read
+ packages: write
+ attestations: write
+ id-token: write
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Log in to the Container registry
+ uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Extract metadata (tags, labels) for Docker
+ id: meta
+ uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
+ with:
+ images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
+
+ - name: Build and push Docker image
+ id: push
+ uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
+ with:
+ context: .
+ push: true
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
+
+ - name: Generate artifact attestation
+ uses: actions/attest-build-provenance@v1
+ with:
+ subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
+ subject-digest: ${{ steps.push.outputs.digest }}
+ push-to-registry: true
diff --git a/lib/mentat/activities.ex b/lib/mentat/activities.ex
new file mode 100644
index 0000000..8feb502
--- /dev/null
+++ b/lib/mentat/activities.ex
@@ -0,0 +1,104 @@
+defmodule Mentat.Activities do
+ @moduledoc """
+ The Activities context.
+ """
+
+ import Ecto.Query, warn: false
+ alias Mentat.Repo
+
+ alias Mentat.Activities.ActivityRecord
+
+ @doc """
+ Returns the list of activity_records.
+
+ ## Examples
+
+ iex> list_activity_records()
+ [%ActivityRecord{}, ...]
+
+ """
+ def list_activity_records do
+ Repo.all(ActivityRecord)
+ end
+
+ @doc """
+ Gets a single activity_record.
+
+ Raises `Ecto.NoResultsError` if the Activity record does not exist.
+
+ ## Examples
+
+ iex> get_activity_record!(123)
+ %ActivityRecord{}
+
+ iex> get_activity_record!(456)
+ ** (Ecto.NoResultsError)
+
+ """
+ def get_activity_record!(id), do: Repo.get!(ActivityRecord, id)
+
+ @doc """
+ Creates a activity_record.
+
+ ## Examples
+
+ iex> create_activity_record(%{field: value})
+ {:ok, %ActivityRecord{}}
+
+ iex> create_activity_record(%{field: bad_value})
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def create_activity_record(attrs \\ %{}) do
+ %ActivityRecord{}
+ |> ActivityRecord.changeset(attrs)
+ |> Repo.insert()
+ end
+
+ @doc """
+ Updates a activity_record.
+
+ ## Examples
+
+ iex> update_activity_record(activity_record, %{field: new_value})
+ {:ok, %ActivityRecord{}}
+
+ iex> update_activity_record(activity_record, %{field: bad_value})
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def update_activity_record(%ActivityRecord{} = activity_record, attrs) do
+ activity_record
+ |> ActivityRecord.changeset(attrs)
+ |> Repo.update()
+ end
+
+ @doc """
+ Deletes a activity_record.
+
+ ## Examples
+
+ iex> delete_activity_record(activity_record)
+ {:ok, %ActivityRecord{}}
+
+ iex> delete_activity_record(activity_record)
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def delete_activity_record(%ActivityRecord{} = activity_record) do
+ Repo.delete(activity_record)
+ end
+
+ @doc """
+ Returns an `%Ecto.Changeset{}` for tracking activity_record changes.
+
+ ## Examples
+
+ iex> change_activity_record(activity_record)
+ %Ecto.Changeset{data: %ActivityRecord{}}
+
+ """
+ def change_activity_record(%ActivityRecord{} = activity_record, attrs \\ %{}) do
+ ActivityRecord.changeset(activity_record, attrs)
+ end
+end
diff --git a/lib/mentat/activities/activity_record.ex b/lib/mentat/activities/activity_record.ex
new file mode 100644
index 0000000..713a247
--- /dev/null
+++ b/lib/mentat/activities/activity_record.ex
@@ -0,0 +1,53 @@
+defmodule Mentat.Activities.ActivityRecord do
+ use Ecto.Schema
+ import Ecto.Changeset
+
+ @required_fields [:start_time, :end_time, :value, :measuring_scale, :user_id, :provider_id]
+ @optional_fields [:tags, :details]
+
+ @primary_key {:id, :binary_id, autogenerate: true}
+ @foreign_key_type :binary_id
+ schema "activity_records" do
+ field :value, :decimal
+ field :details, :map
+ field :start_time, :utc_datetime
+ field :end_time, :utc_datetime
+ field :tags, {:array, :string}
+
+ field :measuring_scale, Ecto.Enum,
+ values: [
+ work_min: 1,
+ side_project_min: 2,
+ steps: 3,
+ steps_distance: 4,
+ floors: 5,
+ workout_min: 6,
+ coffees: 7,
+ alcoholic_drinks: 8,
+ sleep_min: 9,
+ sleep_light_min: 10,
+ sleep_deep_min: 11,
+ sleep_rem_min: 12,
+ sleep_awake_min: 13,
+ sleep_awakenings: 14,
+ meditation_min: 15,
+ weight: 16,
+ heartrate: 17,
+ heartrate_resting: 18,
+ heartrate_variability: 19,
+ reading_min: 20
+ ]
+
+ belongs_to :user, User
+ belongs_to :provider, Provider
+
+ timestamps(type: :utc_datetime)
+ end
+
+ @doc false
+ def changeset(activity_record, attrs) do
+ activity_record
+ |> cast(attrs, @required_fields ++ @optional_fields)
+ |> validate_required(@required_fields)
+ end
+end
diff --git a/lib/mentat_web/live/activity_record_live/form_component.ex b/lib/mentat_web/live/activity_record_live/form_component.ex
new file mode 100644
index 0000000..5ae2cfb
--- /dev/null
+++ b/lib/mentat_web/live/activity_record_live/form_component.ex
@@ -0,0 +1,112 @@
+defmodule MentatWeb.ActivityRecordLive.FormComponent do
+ use MentatWeb, :live_component
+
+ alias Mentat.Integrations
+ alias Mentat.Activities
+
+ @impl true
+ def render(assigns) do
+ ~H"""
+
+ <.header>
+ <%= @title %>
+ <:subtitle>Use this form to manage activity_record records in your database.
+
+
+ <.simple_form
+ for={@form}
+ id="activity_record-form"
+ phx-target={@myself}
+ phx-change="validate"
+ phx-submit="save"
+ >
+ <.input field={@form[:start_time]} type="datetime-local" label="Start time" />
+ <.input field={@form[:end_time]} type="datetime-local" label="End time" />
+ <.input field={@form[:value]} type="number" label="Value" step="any" />
+ <%!-- <.input --%>
+ <%!-- field={@form[:tags]} --%>
+ <%!-- type="select" --%>
+ <%!-- multiple --%>
+ <%!-- label="Tags" --%>
+ <%!-- options={[{"Option 1", "option1"}, {"Option 2", "option2"}]} --%>
+ <%!-- /> --%>
+ <.input
+ field={@form[:measuring_scale]}
+ type="select"
+ label="Measuring scale"
+ prompt="Choose a value"
+ options={Ecto.Enum.values(Mentat.Activities.ActivityRecord, :measuring_scale)}
+ />
+ <.input
+ field={@form[:provider_id]}
+ type="select"
+ label="Provider"
+ prompt="Choose a value"
+ options={Integrations.list_providers() |> Enum.map(&{&1.label, &1.id})}
+ />
+ <:actions>
+ <.button phx-disable-with="Saving...">Save Activity record
+
+
+
+ """
+ end
+
+ @impl true
+ def update(%{activity_record: activity_record} = assigns, socket) do
+ {:ok,
+ socket
+ |> assign(assigns)
+ |> assign_new(:form, fn ->
+ to_form(Activities.change_activity_record(activity_record))
+ end)}
+ end
+
+ @impl true
+ def handle_event("validate", %{"activity_record" => activity_record_params}, socket) do
+ changeset =
+ Activities.change_activity_record(socket.assigns.activity_record, activity_record_params)
+
+ {:noreply, assign(socket, form: to_form(changeset, action: :validate))}
+ end
+
+ def handle_event("save", %{"activity_record" => activity_record_params}, socket) do
+ save_activity_record(socket, socket.assigns.action, activity_record_params)
+ end
+
+ defp save_activity_record(socket, :edit, activity_record_params) do
+ case Activities.update_activity_record(socket.assigns.activity_record, activity_record_params) do
+ {:ok, activity_record} ->
+ notify_parent({:saved, activity_record})
+
+ {:noreply,
+ socket
+ |> put_flash(:info, "Activity record updated successfully")
+ |> push_patch(to: socket.assigns.patch)}
+
+ {:error, %Ecto.Changeset{} = changeset} ->
+ {:noreply, assign(socket, form: to_form(changeset))}
+ end
+ end
+
+ defp save_activity_record(socket, :new, activity_record_params) do
+ case Activities.create_activity_record(
+ Map.merge(activity_record_params, %{
+ "user_id" => socket.assigns.current_user.id
+ })
+ ) do
+ {:ok, activity_record} ->
+ notify_parent({:saved, activity_record})
+
+ {:noreply,
+ socket
+ |> put_flash(:info, "Activity record created successfully")
+ |> push_patch(to: socket.assigns.patch)}
+
+ {:error, %Ecto.Changeset{} = changeset} ->
+ {:noreply, assign(socket, form: to_form(changeset))}
+ end
+ end
+
+ defp notify_parent(msg), do: send(self(), {__MODULE__, msg})
+end
diff --git a/lib/mentat_web/live/activity_record_live/index.ex b/lib/mentat_web/live/activity_record_live/index.ex
new file mode 100644
index 0000000..413ea12
--- /dev/null
+++ b/lib/mentat_web/live/activity_record_live/index.ex
@@ -0,0 +1,47 @@
+defmodule MentatWeb.ActivityRecordLive.Index do
+ use MentatWeb, :live_view
+
+ alias Mentat.Activities
+ alias Mentat.Activities.ActivityRecord
+
+ @impl true
+ def mount(_params, _session, socket) do
+ {:ok, stream(socket, :activity_records, Activities.list_activity_records())}
+ end
+
+ @impl true
+ def handle_params(params, _url, socket) do
+ {:noreply, apply_action(socket, socket.assigns.live_action, params)}
+ end
+
+ defp apply_action(socket, :edit, %{"id" => id}) do
+ socket
+ |> assign(:page_title, "Edit Activity record")
+ |> assign(:activity_record, Activities.get_activity_record!(id))
+ end
+
+ defp apply_action(socket, :new, _params) do
+ socket
+ |> assign(:page_title, "New Activity record")
+ |> assign(:activity_record, %ActivityRecord{})
+ end
+
+ defp apply_action(socket, :index, _params) do
+ socket
+ |> assign(:page_title, "Listing Activity records")
+ |> assign(:activity_record, nil)
+ end
+
+ @impl true
+ def handle_info({MentatWeb.ActivityRecordLive.FormComponent, {:saved, activity_record}}, socket) do
+ {:noreply, stream_insert(socket, :activity_records, activity_record)}
+ end
+
+ @impl true
+ def handle_event("delete", %{"id" => id}, socket) do
+ activity_record = Activities.get_activity_record!(id)
+ {:ok, _} = Activities.delete_activity_record(activity_record)
+
+ {:noreply, stream_delete(socket, :activity_records, activity_record)}
+ end
+end
diff --git a/lib/mentat_web/live/activity_record_live/index.html.heex b/lib/mentat_web/live/activity_record_live/index.html.heex
new file mode 100644
index 0000000..141d58f
--- /dev/null
+++ b/lib/mentat_web/live/activity_record_live/index.html.heex
@@ -0,0 +1,56 @@
+<.header>
+ Listing Activity records
+ <:actions>
+ <.link patch={~p"/activity_records/new"}>
+ <.button>New Activity record
+
+
+
+
+<.table
+ id="activity_records"
+ rows={@streams.activity_records}
+ row_click={
+ fn {_id, activity_record} -> JS.navigate(~p"/activity_records/#{activity_record}") end
+ }
+>
+ <:col :let={{_id, activity_record}} label="Start time"><%= activity_record.start_time %>
+ <:col :let={{_id, activity_record}} label="End time"><%= activity_record.end_time %>
+ <:col :let={{_id, activity_record}} label="Value"><%= activity_record.value %>
+ <:col :let={{_id, activity_record}} label="Details"><%= activity_record.details %>
+ <:col :let={{_id, activity_record}} label="Tags"><%= activity_record.tags %>
+ <:col :let={{_id, activity_record}} label="Measuring scale">
+ <%= activity_record.measuring_scale %>
+
+ <:action :let={{_id, activity_record}}>
+
+ <.link navigate={~p"/activity_records/#{activity_record}"}>Show
+
+ <.link patch={~p"/activity_records/#{activity_record}/edit"}>Edit
+
+ <:action :let={{id, activity_record}}>
+ <.link
+ phx-click={JS.push("delete", value: %{id: activity_record.id}) |> hide("##{id}")}
+ data-confirm="Are you sure?"
+ >
+ Delete
+
+
+
+
+<.modal
+ :if={@live_action in [:new, :edit]}
+ id="activity_record-modal"
+ show
+ on_cancel={JS.patch(~p"/activity_records")}
+>
+ <.live_component
+ module={MentatWeb.ActivityRecordLive.FormComponent}
+ id={@activity_record.id || :new}
+ title={@page_title}
+ action={@live_action}
+ activity_record={@activity_record}
+ patch={~p"/activity_records"}
+ current_user={@current_user}
+ />
+
diff --git a/lib/mentat_web/live/activity_record_live/show.ex b/lib/mentat_web/live/activity_record_live/show.ex
new file mode 100644
index 0000000..a5cf1df
--- /dev/null
+++ b/lib/mentat_web/live/activity_record_live/show.ex
@@ -0,0 +1,21 @@
+defmodule MentatWeb.ActivityRecordLive.Show do
+ use MentatWeb, :live_view
+
+ alias Mentat.Activities
+
+ @impl true
+ def mount(_params, _session, socket) do
+ {:ok, socket}
+ end
+
+ @impl true
+ def handle_params(%{"id" => id}, _, socket) do
+ {:noreply,
+ socket
+ |> assign(:page_title, page_title(socket.assigns.live_action))
+ |> assign(:activity_record, Activities.get_activity_record!(id))}
+ end
+
+ defp page_title(:show), do: "Show Activity record"
+ defp page_title(:edit), do: "Edit Activity record"
+end
diff --git a/lib/mentat_web/live/activity_record_live/show.html.heex b/lib/mentat_web/live/activity_record_live/show.html.heex
new file mode 100644
index 0000000..b829da1
--- /dev/null
+++ b/lib/mentat_web/live/activity_record_live/show.html.heex
@@ -0,0 +1,31 @@
+<.header>
+ Activity record <%= @activity_record.id %>
+ <:subtitle>This is a activity_record record from your database.
+ <:actions>
+ <.link patch={~p"/activity_records/#{@activity_record}/show/edit"} phx-click={JS.push_focus()}>
+ <.button>Edit activity_record
+
+
+
+
+<.list>
+ <:item title="Start time"><%= @activity_record.start_time %>
+ <:item title="End time"><%= @activity_record.end_time %>
+ <:item title="Value"><%= @activity_record.value %>
+ <:item title="Details"><%= @activity_record.details %>
+ <:item title="Tags"><%= @activity_record.tags %>
+ <:item title="Measuring scale"><%= @activity_record.measuring_scale %>
+
+
+<.back navigate={~p"/activity_records"}>Back to activity_records
+
+<.modal :if={@live_action == :edit} id="activity_record-modal" show on_cancel={JS.patch(~p"/activity_records/#{@activity_record}")}>
+ <.live_component
+ module={MentatWeb.ActivityRecordLive.FormComponent}
+ id={@activity_record.id}
+ title={@page_title}
+ action={@live_action}
+ activity_record={@activity_record}
+ patch={~p"/activity_records/#{@activity_record}"}
+ />
+
diff --git a/lib/mentat_web/live/provider_live/form_component.ex b/lib/mentat_web/live/provider_live/form_component.ex
index ce50838..ed2a6bb 100644
--- a/lib/mentat_web/live/provider_live/form_component.ex
+++ b/lib/mentat_web/live/provider_live/form_component.ex
@@ -72,7 +72,11 @@ defmodule MentatWeb.ProviderLive.FormComponent do
end
defp save_provider(socket, :new, provider_params) do
- case Integrations.create_provider(provider_params) do
+ case Integrations.create_provider(
+ Map.merge(provider_params, %{
+ "user_id" => socket.assigns.current_user.id
+ })
+ ) do
{:ok, provider} ->
notify_parent({:saved, provider})
diff --git a/lib/mentat_web/live/provider_live/index.html.heex b/lib/mentat_web/live/provider_live/index.html.heex
index 07ae4c8..59ec2eb 100644
--- a/lib/mentat_web/live/provider_live/index.html.heex
+++ b/lib/mentat_web/live/provider_live/index.html.heex
@@ -31,7 +31,12 @@
-<.modal :if={@live_action in [:new, :edit]} id="provider-modal" show on_cancel={JS.patch(~p"/providers")}>
+<.modal
+ :if={@live_action in [:new, :edit]}
+ id="provider-modal"
+ show
+ on_cancel={JS.patch(~p"/providers")}
+>
<.live_component
module={MentatWeb.ProviderLive.FormComponent}
id={@provider.id || :new}
@@ -39,5 +44,6 @@
action={@live_action}
provider={@provider}
patch={~p"/providers"}
+ current_user={@current_user}
/>
diff --git a/lib/mentat_web/router.ex b/lib/mentat_web/router.ex
index 795af1c..d9ac0e5 100644
--- a/lib/mentat_web/router.ex
+++ b/lib/mentat_web/router.ex
@@ -68,6 +68,20 @@ defmodule MentatWeb.Router do
on_mount: [{MentatWeb.UserAuth, :ensure_authenticated}] do
live "/users/settings", UserSettingsLive, :edit
live "/users/settings/confirm_email/:token", UserSettingsLive, :confirm_email
+
+ live "/providers", ProviderLive.Index, :index
+ live "/providers/new", ProviderLive.Index, :new
+ live "/providers/:id/edit", ProviderLive.Index, :edit
+
+ live "/providers/:id", ProviderLive.Show, :show
+ live "/providers/:id/show/edit", ProviderLive.Show, :edit
+
+ live "/activity_records", ActivityRecordLive.Index, :index
+ live "/activity_records/new", ActivityRecordLive.Index, :new
+ live "/activity_records/:id/edit", ActivityRecordLive.Index, :edit
+
+ live "/activity_records/:id", ActivityRecordLive.Show, :show
+ live "/activity_records/:id/show/edit", ActivityRecordLive.Show, :edit
end
end
diff --git a/priv/repo/migrations/20240807135812_create_activity_records.exs b/priv/repo/migrations/20240807135812_create_activity_records.exs
new file mode 100644
index 0000000..1fd9126
--- /dev/null
+++ b/priv/repo/migrations/20240807135812_create_activity_records.exs
@@ -0,0 +1,23 @@
+defmodule Mentat.Repo.Migrations.CreateActivityRecords do
+ use Ecto.Migration
+
+ def change do
+ create table(:activity_records, primary_key: false) do
+ add :id, :binary_id, primary_key: true
+ add :start_time, :utc_datetime, null: false
+ add :end_time, :utc_datetime, null: false
+ add :value, :decimal, null: false
+ add :details, :map
+ add :tags, {:array, :string}
+ add :measuring_scale, :integer, null: false
+ add :user_id, references(:users, on_delete: :delete_all, type: :binary_id)
+ add :provider_id, references(:providers, on_delete: :nothing, type: :binary_id)
+
+ timestamps(type: :utc_datetime)
+ end
+
+ create index(:activity_records, [:user_id])
+ create index(:activity_records, [:provider_id])
+ create index(:activity_records, [:measuring_scale])
+ end
+end
diff --git a/test/mentat/activities_test.exs b/test/mentat/activities_test.exs
new file mode 100644
index 0000000..93ccbe5
--- /dev/null
+++ b/test/mentat/activities_test.exs
@@ -0,0 +1,69 @@
+defmodule Mentat.ActivitiesTest do
+ use Mentat.DataCase
+
+ alias Mentat.Activities
+
+ describe "activity_records" do
+ alias Mentat.Activities.ActivityRecord
+
+ import Mentat.ActivitiesFixtures
+
+ @invalid_attrs %{value: nil, details: nil, start_time: nil, end_time: nil, tags: nil, measuring_scale: nil}
+
+ test "list_activity_records/0 returns all activity_records" do
+ activity_record = activity_record_fixture()
+ assert Activities.list_activity_records() == [activity_record]
+ end
+
+ test "get_activity_record!/1 returns the activity_record with given id" do
+ activity_record = activity_record_fixture()
+ assert Activities.get_activity_record!(activity_record.id) == activity_record
+ end
+
+ test "create_activity_record/1 with valid data creates a activity_record" do
+ valid_attrs = %{value: "120.5", details: %{}, start_time: ~U[2024-08-06 13:58:00Z], end_time: ~U[2024-08-06 13:58:00Z], tags: ["option1", "option2"], measuring_scale: :duration}
+
+ assert {:ok, %ActivityRecord{} = activity_record} = Activities.create_activity_record(valid_attrs)
+ assert activity_record.value == Decimal.new("120.5")
+ assert activity_record.details == %{}
+ assert activity_record.start_time == ~U[2024-08-06 13:58:00Z]
+ assert activity_record.end_time == ~U[2024-08-06 13:58:00Z]
+ assert activity_record.tags == ["option1", "option2"]
+ assert activity_record.measuring_scale == :duration
+ end
+
+ test "create_activity_record/1 with invalid data returns error changeset" do
+ assert {:error, %Ecto.Changeset{}} = Activities.create_activity_record(@invalid_attrs)
+ end
+
+ test "update_activity_record/2 with valid data updates the activity_record" do
+ activity_record = activity_record_fixture()
+ update_attrs = %{value: "456.7", details: %{}, start_time: ~U[2024-08-07 13:58:00Z], end_time: ~U[2024-08-07 13:58:00Z], tags: ["option1"], measuring_scale: :duration}
+
+ assert {:ok, %ActivityRecord{} = activity_record} = Activities.update_activity_record(activity_record, update_attrs)
+ assert activity_record.value == Decimal.new("456.7")
+ assert activity_record.details == %{}
+ assert activity_record.start_time == ~U[2024-08-07 13:58:00Z]
+ assert activity_record.end_time == ~U[2024-08-07 13:58:00Z]
+ assert activity_record.tags == ["option1"]
+ assert activity_record.measuring_scale == :duration
+ end
+
+ test "update_activity_record/2 with invalid data returns error changeset" do
+ activity_record = activity_record_fixture()
+ assert {:error, %Ecto.Changeset{}} = Activities.update_activity_record(activity_record, @invalid_attrs)
+ assert activity_record == Activities.get_activity_record!(activity_record.id)
+ end
+
+ test "delete_activity_record/1 deletes the activity_record" do
+ activity_record = activity_record_fixture()
+ assert {:ok, %ActivityRecord{}} = Activities.delete_activity_record(activity_record)
+ assert_raise Ecto.NoResultsError, fn -> Activities.get_activity_record!(activity_record.id) end
+ end
+
+ test "change_activity_record/1 returns a activity_record changeset" do
+ activity_record = activity_record_fixture()
+ assert %Ecto.Changeset{} = Activities.change_activity_record(activity_record)
+ end
+ end
+end
diff --git a/test/mentat_web/live/activity_record_live_test.exs b/test/mentat_web/live/activity_record_live_test.exs
new file mode 100644
index 0000000..7106f4f
--- /dev/null
+++ b/test/mentat_web/live/activity_record_live_test.exs
@@ -0,0 +1,108 @@
+defmodule MentatWeb.ActivityRecordLiveTest do
+ use MentatWeb.ConnCase
+
+ import Phoenix.LiveViewTest
+ import Mentat.ActivitiesFixtures
+
+ @create_attrs %{value: "120.5", details: %{}, start_time: "2024-08-06T13:58:00Z", end_time: "2024-08-06T13:58:00Z", tags: ["option1", "option2"], measuring_scale: :duration}
+ @update_attrs %{value: "456.7", details: %{}, start_time: "2024-08-07T13:58:00Z", end_time: "2024-08-07T13:58:00Z", tags: ["option1"], measuring_scale: :duration}
+ @invalid_attrs %{value: nil, details: nil, start_time: nil, end_time: nil, tags: [], measuring_scale: nil}
+
+ defp create_activity_record(_) do
+ activity_record = activity_record_fixture()
+ %{activity_record: activity_record}
+ end
+
+ describe "Index" do
+ setup [:create_activity_record]
+
+ test "lists all activity_records", %{conn: conn} do
+ {:ok, _index_live, html} = live(conn, ~p"/activity_records")
+
+ assert html =~ "Listing Activity records"
+ end
+
+ test "saves new activity_record", %{conn: conn} do
+ {:ok, index_live, _html} = live(conn, ~p"/activity_records")
+
+ assert index_live |> element("a", "New Activity record") |> render_click() =~
+ "New Activity record"
+
+ assert_patch(index_live, ~p"/activity_records/new")
+
+ assert index_live
+ |> form("#activity_record-form", activity_record: @invalid_attrs)
+ |> render_change() =~ "can't be blank"
+
+ assert index_live
+ |> form("#activity_record-form", activity_record: @create_attrs)
+ |> render_submit()
+
+ assert_patch(index_live, ~p"/activity_records")
+
+ html = render(index_live)
+ assert html =~ "Activity record created successfully"
+ end
+
+ test "updates activity_record in listing", %{conn: conn, activity_record: activity_record} do
+ {:ok, index_live, _html} = live(conn, ~p"/activity_records")
+
+ assert index_live |> element("#activity_records-#{activity_record.id} a", "Edit") |> render_click() =~
+ "Edit Activity record"
+
+ assert_patch(index_live, ~p"/activity_records/#{activity_record}/edit")
+
+ assert index_live
+ |> form("#activity_record-form", activity_record: @invalid_attrs)
+ |> render_change() =~ "can't be blank"
+
+ assert index_live
+ |> form("#activity_record-form", activity_record: @update_attrs)
+ |> render_submit()
+
+ assert_patch(index_live, ~p"/activity_records")
+
+ html = render(index_live)
+ assert html =~ "Activity record updated successfully"
+ end
+
+ test "deletes activity_record in listing", %{conn: conn, activity_record: activity_record} do
+ {:ok, index_live, _html} = live(conn, ~p"/activity_records")
+
+ assert index_live |> element("#activity_records-#{activity_record.id} a", "Delete") |> render_click()
+ refute has_element?(index_live, "#activity_records-#{activity_record.id}")
+ end
+ end
+
+ describe "Show" do
+ setup [:create_activity_record]
+
+ test "displays activity_record", %{conn: conn, activity_record: activity_record} do
+ {:ok, _show_live, html} = live(conn, ~p"/activity_records/#{activity_record}")
+
+ assert html =~ "Show Activity record"
+ end
+
+ test "updates activity_record within modal", %{conn: conn, activity_record: activity_record} do
+ {:ok, show_live, _html} = live(conn, ~p"/activity_records/#{activity_record}")
+
+ assert show_live |> element("a", "Edit") |> render_click() =~
+ "Edit Activity record"
+
+ assert_patch(show_live, ~p"/activity_records/#{activity_record}/show/edit")
+
+ assert show_live
+ |> form("#activity_record-form", activity_record: @invalid_attrs)
+ |> render_change() =~ "can't be blank"
+
+ assert show_live
+ |> form("#activity_record-form", activity_record: @update_attrs)
+ |> render_submit()
+
+ assert_patch(show_live, ~p"/activity_records/#{activity_record}")
+
+ html = render(show_live)
+ assert html =~ "Activity record updated successfully"
+ end
+ end
+end
diff --git a/test/support/fixtures/activities_fixtures.ex b/test/support/fixtures/activities_fixtures.ex
new file mode 100644
index 0000000..b42c8d9
--- /dev/null
+++ b/test/support/fixtures/activities_fixtures.ex
@@ -0,0 +1,25 @@
+defmodule Mentat.ActivitiesFixtures do
+ @moduledoc """
+ This module defines test helpers for creating
+ entities via the `Mentat.Activities` context.
+ """
+
+ @doc """
+ Generate a activity_record.
+ """
+ def activity_record_fixture(attrs \\ %{}) do
+ {:ok, activity_record} =
+ attrs
+ |> Enum.into(%{
+ details: %{},
+ end_time: ~U[2024-08-06 13:58:00Z],
+ measuring_scale: :duration,
+ start_time: ~U[2024-08-06 13:58:00Z],
+ tags: ["option1", "option2"],
+ value: "120.5"
+ })
+ |> Mentat.Activities.create_activity_record()
+
+ activity_record
+ end
+end