Jobs
@@ -7,10 +7,10 @@
<%= if @current_user.role in [:attendee] do %>
<%= live_patch to: "?tab=all", class: "#{@current_tab == "all" && "border-b-2 border-red-500 text-gray-900" || "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300"} py-4 px-1 text-sm font-medium text-gray-500 whitespace-nowrap border-b-2 border-transparent hover:text-gray-700 hover:border-gray-300" do %>
- <%= "All" %>
+ All
<% end %>
<%= live_patch to: "?tab=mine", class: "#{@current_tab == "mine" && "border-b-2 border-red-500 text-gray-900" || "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300"} py-4 px-1 text-sm font-medium text-gray-500 whitespace-nowrap border-b-2 border-transparent hover:text-gray-700 hover:border-gray-300" do %>
- <%= "Mine" %>
+ Mine
<% end %>
<% end %>
diff --git a/lib/parzival_web/live/app/store/boost_live/index.ex b/lib/parzival_web/live/app/store/boost_live/index.ex
new file mode 100644
index 00000000..d9527ce0
--- /dev/null
+++ b/lib/parzival_web/live/app/store/boost_live/index.ex
@@ -0,0 +1,34 @@
+defmodule ParzivalWeb.App.BoostLive.Index do
+ @moduledoc false
+ use ParzivalWeb, :live_view
+
+ import ParzivalWeb.Components.Pagination
+
+ alias Parzival.Store
+ alias Parzival.Uploaders
+
+ @impl true
+ def mount(_params, _session, socket) do
+ {:ok, socket}
+ end
+
+ @impl true
+ def handle_params(params, _url, socket) do
+ {:noreply,
+ socket
+ |> assign(:current_page, :store)
+ |> assign(:page_title, "Store")
+ |> assign(:params, params)
+ |> assign(list_boosts(params))}
+ end
+
+ defp list_boosts(params) do
+ case Store.list_boosts(params) do
+ {:ok, {boosts, meta}} ->
+ %{boosts: boosts, meta: meta}
+
+ {:error, flop} ->
+ %{boosts: [], meta: flop}
+ end
+ end
+end
diff --git a/lib/parzival_web/live/app/store/boost_live/index.html.heex b/lib/parzival_web/live/app/store/boost_live/index.html.heex
new file mode 100644
index 00000000..ec39372f
--- /dev/null
+++ b/lib/parzival_web/live/app/store/boost_live/index.html.heex
@@ -0,0 +1,49 @@
+
+
+
Store
+
+
+
+
+ <%= live_patch to: Routes.product_index_path(@socket, :index), class: "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 py-4 px-1 text-sm font-medium text-gray-500 whitespace-nowrap border-b-2 border-transparent hover:text-gray-700 hover:border-gray-300" do %>
+ Merch
+ <% end %>
+ <%= live_patch to: "", class: "border-b-2 border-red-500 text-gray-900 py-4 px-1 text-sm font-medium text-gray-500 whitespace-nowrap border-b-2 border-transparent hover:text-gray-700 hover:border-gray-300" do %>
+ Boosts
+ <% end %>
+
+
+ <%= if @current_user.role in [:admin] do %>
+
+ <%= live_patch("New", to: Routes.offer_new_path(@socket, :new), class: "inline-flex items-center justify-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-secondary hover:bg-primary xl:w-full") %>
+
+ <% end %>
+
+
+
+
+ <%= for boost <- @boosts do %>
+ <%= live_patch to: Routes.boost_show_path(@socket, :show, boost) do %>
+
+
+
+
+
+
+
+ <%= boost.name %>
+
+
+ <%= boost.description %>
+
+
+ 💰 <%= boost.price %>
+
+
+
+ <% end %>
+ <% end %>
+
+ <.pagination items={@boosts} meta={@meta} params={@params} class="flex justify-between items-center w-full" />
+
+
diff --git a/lib/parzival_web/live/app/store/boost_live/show.ex b/lib/parzival_web/live/app/store/boost_live/show.ex
new file mode 100644
index 00000000..9f04cfb0
--- /dev/null
+++ b/lib/parzival_web/live/app/store/boost_live/show.ex
@@ -0,0 +1,85 @@
+defmodule ParzivalWeb.App.BoostLive.Show do
+ @moduledoc false
+ use ParzivalWeb, :live_view
+
+ alias Parzival.Accounts
+ alias Parzival.Store
+ alias Parzival.Uploaders
+
+ @impl true
+ def mount(%{"id" => id}, _session, socket) do
+ {:ok, assign(socket, :id, id)}
+ end
+
+ @impl true
+ def handle_params(%{"id" => id}, _, socket) do
+ {:noreply, reload(socket)}
+ end
+
+ @impl true
+ def handle_event("delete", _payload, socket) do
+ case Store.delete_product(socket.assigns.product) do
+ {:ok, _product} ->
+ {:noreply,
+ socket
+ |> put_flash(:success, "Product deleted successfully!")
+ |> push_redirect(to: Routes.product_index_path(socket, :index))}
+
+ {:error, %Ecto.Changeset{} = changeset} ->
+ {:noreply,
+ socket
+ |> put_flash(:error, elem(changeset.errors[:orders], 0))
+ |> assign(:changeset, changeset)}
+ end
+ end
+
+ @impl true
+ def handle_event("purchase", _payload, socket) do
+ boost = socket.assigns.boost
+ current_user = socket.assigns.current_user
+
+ case Store.purchase_boost(current_user, boost) do
+ {:ok, _boost} ->
+ {:noreply,
+ socket
+ |> put_flash(:success, "Boost purchased successfully!")
+ |> reload()}
+
+ {:error, %Ecto.Changeset{} = changeset} ->
+ {:noreply, assign(socket, :changeset, changeset)}
+ end
+ end
+
+ @impl true
+ def handle_info({event, _changes}, socket) when event in [:boost_purchased, :boost_updated] do
+ {:noreply, reload(socket)}
+ end
+
+ def handle_info({event, _changes}, socket) when event in [:boost_deleted] do
+ {:noreply, push_redirect(socket, to: Routes.product_index_path(socket, :index))}
+ end
+
+ defp reload(socket) do
+ id = socket.assigns.id
+
+ socket
+ |> assign(:current_page, :store)
+ |> assign(
+ inventory:
+ Store.list_inventory(where: [user_id: socket.assigns.current_user.id], preloads: [:boost])
+ )
+ |> assign(:page_title, page_title(socket.assigns.live_action))
+ |> assign(:boost, Store.get_boost!(id))
+ |> assign(
+ current_user:
+ Accounts.get_user!(socket.assigns.current_user.id, [
+ :company,
+ :missions,
+ inventory: [:boost]
+ ])
+ )
+ end
+
+ defp page_title(:show), do: "Show Boost"
+ defp page_title(:edit), do: "Edit Boost"
+end
diff --git a/lib/parzival_web/live/app/store/boost_live/show.html.heex b/lib/parzival_web/live/app/store/boost_live/show.html.heex
new file mode 100644
index 00000000..f5e576b9
--- /dev/null
+++ b/lib/parzival_web/live/app/store/boost_live/show.html.heex
@@ -0,0 +1,68 @@
+
+
+
+
Store
+
+ <%= if @current_user.role in [:admin] do %>
+
+
+
+ Edit
+
+ <%= link("Delete", to: "#", phx_click: "delete", data: [confirm: "Are you sure?"], class: "inline-flex items-center justify-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-secondary hover:bg-primary xl:w-full") %>
+
+ <% end %>
+
+
+
+
+
+ <%= live_redirect("< Back", to: Routes.boost_index_path(@socket, :index), class: "hover:underline inline-flex items-center justify-center whitespace-nowrap") %>
+
+
+
+
+
+
+
+
+
+
+ 💰 <%= @boost.price %>
+
+
+
+
+ <%= @boost.description %>
+
+
+
+
+
+
+
+
+
+
+
+ boost options
+
+ <%= if @current_user.role == :attendee do %>
+ <%= if @current_user.balance >= @boost.price && length(@inventory) < 5 do %>
+
+ Purchase
+
+ <% else %>
+
+ Purchase
+
+ <% end %>
+ <% end %>
+
+
+
+
+
+
diff --git a/lib/parzival_web/live/app/store/product_live/index.html.heex b/lib/parzival_web/live/app/store/product_live/index.html.heex
index 91dfb521..8badb0b5 100644
--- a/lib/parzival_web/live/app/store/product_live/index.html.heex
+++ b/lib/parzival_web/live/app/store/product_live/index.html.heex
@@ -1,38 +1,49 @@
-
-
-
-
Store
-
- <%= if @current_user.role == :admin do %>
+
+
+
Store
+
+
+
+
+ <%= live_patch to: "", class: "border-b-2 border-red-500 text-gray-900 py-4 px-1 text-sm font-medium text-gray-500 whitespace-nowrap border-b-2 border-transparent hover:text-gray-700 hover:border-gray-300" do %>
+ Merch
+ <% end %>
+ <%= live_patch to: Routes.boost_index_path(@socket, :index), class: "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 py-4 px-1 text-sm font-medium text-gray-500 whitespace-nowrap border-b-2 border-transparent hover:text-gray-700 hover:border-gray-300" do %>
+ Boosts
+ <% end %>
+
+
+ <%= if @current_user.role in [:admin] do %>
<%= live_patch("New", to: Routes.admin_product_new_path(@socket, :new), class: "inline-flex items-center justify-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-secondary hover:bg-primary xl:w-full") %>
<% end %>
-
-
diff --git a/lib/parzival_web/live/app/store/product_live/show.ex b/lib/parzival_web/live/app/store/product_live/show.ex
index 67bc4152..2664aef9 100644
--- a/lib/parzival_web/live/app/store/product_live/show.ex
+++ b/lib/parzival_web/live/app/store/product_live/show.ex
@@ -9,9 +9,9 @@ defmodule ParzivalWeb.App.ProductLive.Show do
@impl true
def mount(%{"id" => id}, _session, socket) do
if connected?(socket) do
- Store.subscribe("purchased")
- Store.subscribe("updated")
- Store.subscribe("deleted")
+ Store.subscribe("product_purchased")
+ Store.subscribe("product_updated")
+ Store.subscribe("product_deleted")
end
{:ok, assign(socket, :id, id)}
@@ -60,7 +60,7 @@ defmodule ParzivalWeb.App.ProductLive.Show do
product = socket.assigns.product
current_user = socket.assigns.current_user
- case Store.purchase(current_user, product) do
+ case Store.purchase_product(current_user, product) do
{:ok, _product} ->
{:noreply,
socket
@@ -73,11 +73,12 @@ defmodule ParzivalWeb.App.ProductLive.Show do
end
@impl true
- def handle_info({event, _changes}, socket) when event in [:purchased, :updated] do
+ def handle_info({event, _changes}, socket)
+ when event in [:product_purchased, :product_updated] do
{:noreply, reload(socket)}
end
- def handle_info({event, _changes}, socket) when event in [:deleted] do
+ def handle_info({event, _changes}, socket) when event in [:product_deleted] do
{:noreply, push_redirect(socket, to: Routes.product_index_path(socket, :index))}
end
@@ -90,7 +91,12 @@ defmodule ParzivalWeb.App.ProductLive.Show do
|> assign(:redeem_quantity, redeem_quantity(socket.assigns.current_user.id, id))
|> assign(:product, Store.get_product!(id))
|> assign(
- current_user: Accounts.get_user!(socket.assigns.current_user.id, [:company, :missions])
+ current_user:
+ Accounts.get_user!(socket.assigns.current_user.id, [
+ :company,
+ :missions,
+ inventory: [:boost]
+ ])
)
end
diff --git a/lib/parzival_web/live/app/vault/order_live/index.html.heex b/lib/parzival_web/live/app/vault/order_live/index.html.heex
index bca71058..a0fdb411 100644
--- a/lib/parzival_web/live/app/vault/order_live/index.html.heex
+++ b/lib/parzival_web/live/app/vault/order_live/index.html.heex
@@ -97,19 +97,6 @@
-
-
<% end %>
diff --git a/lib/parzival_web/live/backoffice/store/item_live/form_component.ex b/lib/parzival_web/live/backoffice/store/item_live/form_component.ex
new file mode 100644
index 00000000..3c367c33
--- /dev/null
+++ b/lib/parzival_web/live/backoffice/store/item_live/form_component.ex
@@ -0,0 +1,55 @@
+defmodule ParzivalWeb.ItemLive.FormComponent do
+ use ParzivalWeb, :live_component
+
+ alias Parzival.Store
+
+ @impl true
+ def update(%{item: item} = assigns, socket) do
+ changeset = Store.change_item(item)
+
+ {:ok,
+ socket
+ |> assign(assigns)
+ |> assign(:changeset, changeset)}
+ end
+
+ @impl true
+ def handle_event("validate", %{"item" => item_params}, socket) do
+ changeset =
+ socket.assigns.item
+ |> Store.change_item(item_params)
+ |> Map.put(:action, :validate)
+
+ {:noreply, assign(socket, :changeset, changeset)}
+ end
+
+ def handle_event("save", %{"item" => item_params}, socket) do
+ save_item(socket, socket.assigns.action, item_params)
+ end
+
+ defp save_item(socket, :edit, item_params) do
+ case Store.update_item(socket.assigns.item, item_params) do
+ {:ok, _item} ->
+ {:noreply,
+ socket
+ |> put_flash(:info, "Item updated successfully")
+ |> push_redirect(to: socket.assigns.return_to)}
+
+ {:error, %Ecto.Changeset{} = changeset} ->
+ {:noreply, assign(socket, :changeset, changeset)}
+ end
+ end
+
+ defp save_item(socket, :new, item_params) do
+ case Store.create_item(item_params) do
+ {:ok, _item} ->
+ {:noreply,
+ socket
+ |> put_flash(:info, "Item created successfully")
+ |> push_redirect(to: socket.assigns.return_to)}
+
+ {:error, %Ecto.Changeset{} = changeset} ->
+ {:noreply, assign(socket, changeset: changeset)}
+ end
+ end
+end
diff --git a/lib/parzival_web/live/backoffice/store/item_live/form_component.html.heex b/lib/parzival_web/live/backoffice/store/item_live/form_component.html.heex
new file mode 100644
index 00000000..618cc958
--- /dev/null
+++ b/lib/parzival_web/live/backoffice/store/item_live/form_component.html.heex
@@ -0,0 +1,9 @@
+
+
<%= @title %>
+
+ <.form let={f} for={@changeset} id="item-form" phx-target={@myself} phx-change="validate" phx-submit="save">
+
+ <%= submit("Save", phx_disable_with: "Saving...") %>
+
+
+
diff --git a/lib/parzival_web/live/hooks.ex b/lib/parzival_web/live/hooks.ex
index 0b1bbd4b..eee88bca 100644
--- a/lib/parzival_web/live/hooks.ex
+++ b/lib/parzival_web/live/hooks.ex
@@ -5,12 +5,13 @@ defmodule ParzivalWeb.Hooks do
import Phoenix.LiveView
alias Parzival.Accounts
+ alias Parzival.Store
def on_mount(:default, _params, _session, socket) do
{:cont, assign(socket, :page_title, "JOIN")}
end
- def on_mount(:current_user, _params, %{"user_token" => user_token}, socket) do
+ def on_mount(:current_user, params, %{"user_token" => user_token}, socket) do
current_user = Accounts.get_user_by_session_token(user_token)
if is_nil(current_user) do
@@ -18,6 +19,9 @@ defmodule ParzivalWeb.Hooks do
else
{:cont,
socket
+ |> assign(
+ inventory: Store.list_inventory(where: [user_id: current_user.id], preloads: [:boost])
+ )
|> assign(current_user: Accounts.load_user_fields(current_user, [:company, :missions]))}
end
end
diff --git a/lib/parzival_web/router.ex b/lib/parzival_web/router.ex
index 0f26bace..9694f1a6 100644
--- a/lib/parzival_web/router.ex
+++ b/lib/parzival_web/router.ex
@@ -70,6 +70,9 @@ defmodule ParzivalWeb.Router do
live "/store/", ProductLive.Index, :index
live "/store/:id", ProductLive.Show, :show
+ live "/boosts/", BoostLive.Index, :index
+ live "/boosts/:id", BoostLive.Show, :show
+
live "/vault", OrderLive.Index, :index
live "/vault/:id", OrderLive.Show, :show
diff --git a/lib/parzival_web/templates/layout/live.html.heex b/lib/parzival_web/templates/layout/live.html.heex
index c09c5cc2..3ee033fa 100644
--- a/lib/parzival_web/templates/layout/live.html.heex
+++ b/lib/parzival_web/templates/layout/live.html.heex
@@ -120,12 +120,32 @@
<% end %>
- <% end %>
-
- <%= for i <- 1..12 do %>
-
+
+ <%= "Inventory (#{length(@inventory)}/5)" %>
+
+
+ <%= for item <- @inventory do %>
+ <.live_component module={ParzivalWeb.Components.Boost} id={item.id} item={item} />
+ <% end %>
+ <%= if length(@inventory) < 5 do %>
+ <%= for i <- 1..5-length(@inventory) do %>
+
+ <% end %>
+ <% end %>
+
+ <%= for item <- @inventory do %>
+ <%= if item.expires_at do %>
+
+
+ <%= item.boost.name %>
+
+
+ <%= relative_datetime_in_digital_clock_format(item.expires_at) %>
+
+
+ <% end %>
<% end %>
-
+ <% end %>
diff --git a/lib/parzival_web/views/view_utils.ex b/lib/parzival_web/views/view_utils.ex
index af48eb38..98dbaa89 100644
--- a/lib/parzival_web/views/view_utils.ex
+++ b/lib/parzival_web/views/view_utils.ex
@@ -39,6 +39,13 @@ defmodule ParzivalWeb.ViewUtils do
Relative.lformat!(datetime, "{relative}", Gettext.get_locale())
end
+ def relative_datetime_in_digital_clock_format(datetime) do
+ time_in_microseconds = Timex.diff(datetime, NaiveDateTime.utc_now())
+
+ Time.add(~T[00:00:00], time_in_microseconds, :microsecond)
+ |> Timex.format!("{h24}:{m}:{s}")
+ end
+
def display_date(nil), do: ""
def display_date(""), do: ""
diff --git a/priv/fake/recruiters.txt b/priv/fake/recruiters.txt
index 563efd12..44851c22 100644
--- a/priv/fake/recruiters.txt
+++ b/priv/fake/recruiters.txt
@@ -1,3 +1,4 @@
+David Machado
Miguel Freitas
Tiago Carriço
Simão Quintela
diff --git a/priv/repo/migrations/20220619010759_create_boosts.exs b/priv/repo/migrations/20220619010759_create_boosts.exs
new file mode 100644
index 00000000..0109a12a
--- /dev/null
+++ b/priv/repo/migrations/20220619010759_create_boosts.exs
@@ -0,0 +1,19 @@
+defmodule Parzival.Repo.Migrations.CreateBoosts do
+ use Ecto.Migration
+
+ def change do
+ create table(:boosts, primary_key: false) do
+ add :id, :binary_id, primary_key: true
+
+ add :name, :string
+ add :description, :string
+ add :price, :integer
+ add :type, :string
+ add :multiplier, :float
+
+ add :image, :string
+
+ timestamps()
+ end
+ end
+end
diff --git a/priv/repo/migrations/20220620001713_create_items.exs b/priv/repo/migrations/20220620001713_create_items.exs
new file mode 100644
index 00000000..1806b6ee
--- /dev/null
+++ b/priv/repo/migrations/20220620001713_create_items.exs
@@ -0,0 +1,19 @@
+defmodule Parzival.Repo.Migrations.CreateItems do
+ use Ecto.Migration
+
+ def change do
+ create table(:items, primary_key: false) do
+ add :id, :binary_id, primary_key: true
+
+ add :expires_at, :naive_datetime
+
+ add :boost_id, references(:boosts, on_delete: :nothing, type: :binary_id)
+ add :user_id, references(:users, on_delete: :delete_all, type: :binary_id)
+
+ timestamps()
+ end
+
+ create index(:items, [:boost_id])
+ create index(:items, [:user_id])
+ end
+end
diff --git a/priv/repo/seeds/store.exs b/priv/repo/seeds/store.exs
index d94fa246..a617cd96 100644
--- a/priv/repo/seeds/store.exs
+++ b/priv/repo/seeds/store.exs
@@ -1,10 +1,12 @@
defmodule Parzival.Repo.Seeds.Store do
alias Parzival.Repo
+ alias Parzival.Store.Boost
alias Parzival.Store.Product
def run do
seed_products()
+ seed_boosts()
end
def seed_products do
@@ -45,6 +47,73 @@ defmodule Parzival.Repo.Seeds.Store do
|> Product.changeset(data)
|> Repo.insert!()
end
+
+ def seed_boosts do
+ case Repo.all(Boost) do
+ [] ->
+ [
+ %{
+ name: "2x EXP",
+ description: "Este boost, quando ativado, duplica a EXP ganha durante 1 hora.",
+ price: 200,
+ type: :exp,
+ multiplier: 2.0
+ },
+ %{
+ name: "1.5x EXP",
+ description: "Este boost, quando ativado, aumenta em 50% a EXP ganha durante 1 hora.",
+ price: 150,
+ type: :exp,
+ multiplier: 1.5
+ },
+ %{
+ name: "1.25x EXP",
+ description: "Este boost, quando ativado, aumenta em 25% a EXP ganha durante 1 hora.",
+ price: 125,
+ type: :exp,
+ multiplier: 1.25
+ },
+ %{
+ name: "2x 💰",
+ description: "Este boost, quando ativado, duplica os 💰 ganhos durante 1 hora.",
+ price: 200,
+ type: :exp,
+ multiplier: 2.0
+ },
+ %{
+ name: "1.5x 💰",
+ description: "Este boost, quando ativado, aumenta em 50% os 💰 ganhos durante 1 hora.",
+ price: 150,
+ type: :exp,
+ multiplier: 1.5
+ },
+ %{
+ name: "1.25x 💰",
+ description: "Este boost, quando ativado, aumenta em 25% os 💰 ganhos durante 1 hora.",
+ price: 125,
+ type: :exp,
+ multiplier: 2.0
+ },
+ %{
+ name: "Skip Task",
+ description:
+ "Este boost, quando ativado, permite saltar uma task, completando a automaticamente.",
+ price: 200,
+ type: :skip_task
+ }
+ ]
+ |> Enum.each(&insert_boost/1)
+
+ _ ->
+ Mix.shell().error("Found boosts, aborting seeding boosts.")
+ end
+ end
+
+ defp insert_boost(data) do
+ %Boost{}
+ |> Boost.changeset(data)
+ |> Repo.insert!()
+ end
end
Parzival.Repo.Seeds.Store.run()
diff --git a/priv/static/images/defaults/store/boost_image_original.png b/priv/static/images/defaults/store/boost_image_original.png
new file mode 100644
index 00000000..7f226a85
Binary files /dev/null and b/priv/static/images/defaults/store/boost_image_original.png differ
diff --git a/priv/static/images/defaults/store/product_image_original.png b/priv/static/images/defaults/store/product_image_original.png
index e16e1f26..7f226a85 100644
Binary files a/priv/static/images/defaults/store/product_image_original.png and b/priv/static/images/defaults/store/product_image_original.png differ
diff --git a/test/parzival/store_test.exs b/test/parzival/store_test.exs
index b29051dd..b6ef7a1c 100644
--- a/test/parzival/store_test.exs
+++ b/test/parzival/store_test.exs
@@ -133,4 +133,110 @@ defmodule Parzival.StoreTest do
assert %Ecto.Changeset{} = Store.change_order(order)
end
end
+
+ describe "boosts" do
+ alias Parzival.Store.Boost
+
+ import Parzival.StoreFixtures
+
+ @invalid_attrs %{finish: nil}
+
+ test "list_boosts/0 returns all boosts" do
+ boost = boost_fixture()
+ assert Store.list_boosts() == [boost]
+ end
+
+ test "get_boost!/1 returns the boost with given id" do
+ boost = boost_fixture()
+ assert Store.get_boost!(boost.id) == boost
+ end
+
+ test "create_boost/1 with valid data creates a boost" do
+ valid_attrs = %{finish: ~N[2022-06-18 01:07:00]}
+
+ assert {:ok, %Boost{} = boost} = Store.create_boost(valid_attrs)
+ assert boost.finish == ~N[2022-06-18 01:07:00]
+ end
+
+ test "create_boost/1 with invalid data returns error changeset" do
+ assert {:error, %Ecto.Changeset{}} = Store.create_boost(@invalid_attrs)
+ end
+
+ test "update_boost/2 with valid data updates the boost" do
+ boost = boost_fixture()
+ update_attrs = %{finish: ~N[2022-06-19 01:07:00]}
+
+ assert {:ok, %Boost{} = boost} = Store.update_boost(boost, update_attrs)
+ assert boost.finish == ~N[2022-06-19 01:07:00]
+ end
+
+ test "update_boost/2 with invalid data returns error changeset" do
+ boost = boost_fixture()
+ assert {:error, %Ecto.Changeset{}} = Store.update_boost(boost, @invalid_attrs)
+ assert boost == Store.get_boost!(boost.id)
+ end
+
+ test "delete_boost/1 deletes the boost" do
+ boost = boost_fixture()
+ assert {:ok, %Boost{}} = Store.delete_boost(boost)
+ assert_raise Ecto.NoResultsError, fn -> Store.get_boost!(boost.id) end
+ end
+
+ test "change_boost/1 returns a boost changeset" do
+ boost = boost_fixture()
+ assert %Ecto.Changeset{} = Store.change_boost(boost)
+ end
+ end
+
+ describe "items" do
+ alias Parzival.Store.Item
+
+ import Parzival.StoreFixtures
+
+ @invalid_attrs %{}
+
+ test "list_items/0 returns all items" do
+ item = item_fixture()
+ assert Store.list_items() == [item]
+ end
+
+ test "get_item!/1 returns the item with given id" do
+ item = item_fixture()
+ assert Store.get_item!(item.id) == item
+ end
+
+ test "create_item/1 with valid data creates a item" do
+ valid_attrs = %{}
+
+ assert {:ok, %Item{} = item} = Store.create_item(valid_attrs)
+ end
+
+ test "create_item/1 with invalid data returns error changeset" do
+ assert {:error, %Ecto.Changeset{}} = Store.create_item(@invalid_attrs)
+ end
+
+ test "update_item/2 with valid data updates the item" do
+ item = item_fixture()
+ update_attrs = %{}
+
+ assert {:ok, %Item{} = item} = Store.update_item(item, update_attrs)
+ end
+
+ test "update_item/2 with invalid data returns error changeset" do
+ item = item_fixture()
+ assert {:error, %Ecto.Changeset{}} = Store.update_item(item, @invalid_attrs)
+ assert item == Store.get_item!(item.id)
+ end
+
+ test "delete_item/1 deletes the item" do
+ item = item_fixture()
+ assert {:ok, %Item{}} = Store.delete_item(item)
+ assert_raise Ecto.NoResultsError, fn -> Store.get_item!(item.id) end
+ end
+
+ test "change_item/1 returns a item changeset" do
+ item = item_fixture()
+ assert %Ecto.Changeset{} = Store.change_item(item)
+ end
+ end
end
diff --git a/test/parzival_web/live/boost_live_test.exs b/test/parzival_web/live/boost_live_test.exs
new file mode 100644
index 00000000..64f5715a
--- /dev/null
+++ b/test/parzival_web/live/boost_live_test.exs
@@ -0,0 +1,105 @@
+defmodule ParzivalWeb.BoostLiveTest do
+ use ParzivalWeb.ConnCase
+
+ import Phoenix.LiveViewTest
+ import Parzival.StoreFixtures
+
+ @create_attrs %{finish: %{day: 18, hour: 1, minute: 7, month: 6, year: 2022}}
+ @update_attrs %{finish: %{day: 19, hour: 1, minute: 7, month: 6, year: 2022}}
+ @invalid_attrs %{finish: %{day: 30, hour: 1, minute: 7, month: 2, year: 2022}}
+
+ defp create_boost(_) do
+ boost = boost_fixture()
+ %{boost: boost}
+ end
+
+ describe "Index" do
+ setup [:create_boost]
+
+ test "lists all boosts", %{conn: conn} do
+ {:ok, _index_live, html} = live(conn, Routes.boost_index_path(conn, :index))
+
+ assert html =~ "Listing Boosts"
+ end
+
+ test "saves new boost", %{conn: conn} do
+ {:ok, index_live, _html} = live(conn, Routes.boost_index_path(conn, :index))
+
+ assert index_live |> element("a", "New Boost") |> render_click() =~
+ "New Boost"
+
+ assert_patch(index_live, Routes.boost_index_path(conn, :new))
+
+ assert index_live
+ |> form("#boost-form", boost: @invalid_attrs)
+ |> render_change() =~ "is invalid"
+
+ {:ok, _, html} =
+ index_live
+ |> form("#boost-form", boost: @create_attrs)
+ |> render_submit()
+ |> follow_redirect(conn, Routes.boost_index_path(conn, :index))
+
+ assert html =~ "Boost created successfully"
+ end
+
+ test "updates boost in listing", %{conn: conn, boost: boost} do
+ {:ok, index_live, _html} = live(conn, Routes.boost_index_path(conn, :index))
+
+ assert index_live |> element("#boost-#{boost.id} a", "Edit") |> render_click() =~
+ "Edit Boost"
+
+ assert_patch(index_live, Routes.boost_index_path(conn, :edit, boost))
+
+ assert index_live
+ |> form("#boost-form", boost: @invalid_attrs)
+ |> render_change() =~ "is invalid"
+
+ {:ok, _, html} =
+ index_live
+ |> form("#boost-form", boost: @update_attrs)
+ |> render_submit()
+ |> follow_redirect(conn, Routes.boost_index_path(conn, :index))
+
+ assert html =~ "Boost updated successfully"
+ end
+
+ test "deletes boost in listing", %{conn: conn, boost: boost} do
+ {:ok, index_live, _html} = live(conn, Routes.boost_index_path(conn, :index))
+
+ assert index_live |> element("#boost-#{boost.id} a", "Delete") |> render_click()
+ refute has_element?(index_live, "#boost-#{boost.id}")
+ end
+ end
+
+ describe "Show" do
+ setup [:create_boost]
+
+ test "displays boost", %{conn: conn, boost: boost} do
+ {:ok, _show_live, html} = live(conn, Routes.boost_show_path(conn, :show, boost))
+
+ assert html =~ "Show Boost"
+ end
+
+ test "updates boost within modal", %{conn: conn, boost: boost} do
+ {:ok, show_live, _html} = live(conn, Routes.boost_show_path(conn, :show, boost))
+
+ assert show_live |> element("a", "Edit") |> render_click() =~
+ "Edit Boost"
+
+ assert_patch(show_live, Routes.boost_show_path(conn, :edit, boost))
+
+ assert show_live
+ |> form("#boost-form", boost: @invalid_attrs)
+ |> render_change() =~ "is invalid"
+
+ {:ok, _, html} =
+ show_live
+ |> form("#boost-form", boost: @update_attrs)
+ |> render_submit()
+ |> follow_redirect(conn, Routes.boost_show_path(conn, :show, boost))
+
+ assert html =~ "Boost updated successfully"
+ end
+ end
+end
diff --git a/test/parzival_web/live/item_live_test.exs b/test/parzival_web/live/item_live_test.exs
new file mode 100644
index 00000000..fbe9458d
--- /dev/null
+++ b/test/parzival_web/live/item_live_test.exs
@@ -0,0 +1,105 @@
+defmodule ParzivalWeb.ItemLiveTest do
+ use ParzivalWeb.ConnCase
+
+ import Phoenix.LiveViewTest
+ import Parzival.StoreFixtures
+
+ @create_attrs %{}
+ @update_attrs %{}
+ @invalid_attrs %{}
+
+ defp create_item(_) do
+ item = item_fixture()
+ %{item: item}
+ end
+
+ describe "Index" do
+ setup [:create_item]
+
+ test "lists all items", %{conn: conn} do
+ {:ok, _index_live, html} = live(conn, Routes.item_index_path(conn, :index))
+
+ assert html =~ "Listing Items"
+ end
+
+ test "saves new item", %{conn: conn} do
+ {:ok, index_live, _html} = live(conn, Routes.item_index_path(conn, :index))
+
+ assert index_live |> element("a", "New Item") |> render_click() =~
+ "New Item"
+
+ assert_patch(index_live, Routes.item_index_path(conn, :new))
+
+ assert index_live
+ |> form("#item-form", item: @invalid_attrs)
+ |> render_change() =~ "can't be blank"
+
+ {:ok, _, html} =
+ index_live
+ |> form("#item-form", item: @create_attrs)
+ |> render_submit()
+ |> follow_redirect(conn, Routes.item_index_path(conn, :index))
+
+ assert html =~ "Item created successfully"
+ end
+
+ test "updates item in listing", %{conn: conn, item: item} do
+ {:ok, index_live, _html} = live(conn, Routes.item_index_path(conn, :index))
+
+ assert index_live |> element("#item-#{item.id} a", "Edit") |> render_click() =~
+ "Edit Item"
+
+ assert_patch(index_live, Routes.item_index_path(conn, :edit, item))
+
+ assert index_live
+ |> form("#item-form", item: @invalid_attrs)
+ |> render_change() =~ "can't be blank"
+
+ {:ok, _, html} =
+ index_live
+ |> form("#item-form", item: @update_attrs)
+ |> render_submit()
+ |> follow_redirect(conn, Routes.item_index_path(conn, :index))
+
+ assert html =~ "Item updated successfully"
+ end
+
+ test "deletes item in listing", %{conn: conn, item: item} do
+ {:ok, index_live, _html} = live(conn, Routes.item_index_path(conn, :index))
+
+ assert index_live |> element("#item-#{item.id} a", "Delete") |> render_click()
+ refute has_element?(index_live, "#item-#{item.id}")
+ end
+ end
+
+ describe "Show" do
+ setup [:create_item]
+
+ test "displays item", %{conn: conn, item: item} do
+ {:ok, _show_live, html} = live(conn, Routes.item_show_path(conn, :show, item))
+
+ assert html =~ "Show Item"
+ end
+
+ test "updates item within modal", %{conn: conn, item: item} do
+ {:ok, show_live, _html} = live(conn, Routes.item_show_path(conn, :show, item))
+
+ assert show_live |> element("a", "Edit") |> render_click() =~
+ "Edit Item"
+
+ assert_patch(show_live, Routes.item_show_path(conn, :edit, item))
+
+ assert show_live
+ |> form("#item-form", item: @invalid_attrs)
+ |> render_change() =~ "can't be blank"
+
+ {:ok, _, html} =
+ show_live
+ |> form("#item-form", item: @update_attrs)
+ |> render_submit()
+ |> follow_redirect(conn, Routes.item_show_path(conn, :show, item))
+
+ assert html =~ "Item updated successfully"
+ end
+ end
+end
diff --git a/test/support/fixtures/store_fixtures.ex b/test/support/fixtures/store_fixtures.ex
index 5a11ce7e..5ea9369b 100644
--- a/test/support/fixtures/store_fixtures.ex
+++ b/test/support/fixtures/store_fixtures.ex
@@ -36,4 +36,30 @@ defmodule Parzival.StoreFixtures do
order
end
+
+ @doc """
+ Generate a boost.
+ """
+ def boost_fixture(attrs \\ %{}) do
+ {:ok, boost} =
+ attrs
+ |> Enum.into(%{
+ finish: ~N[2022-06-18 01:07:00]
+ })
+ |> Parzival.Store.create_boost()
+
+ boost
+ end
+
+ @doc """
+ Generate a item.
+ """
+ def item_fixture(attrs \\ %{}) do
+ {:ok, item} =
+ attrs
+ |> Enum.into(%{})
+ |> Parzival.Store.create_item()
+
+ item
+ end
end