forked from shibao/cannery
add models, context and liveviews
This commit is contained in:
200
lib/cannery/ammo.ex
Normal file
200
lib/cannery/ammo.ex
Normal file
@ -0,0 +1,200 @@
|
||||
defmodule Cannery.Ammo do
|
||||
@moduledoc """
|
||||
The Ammo context.
|
||||
"""
|
||||
|
||||
import Ecto.Query, warn: false
|
||||
alias Cannery.Repo
|
||||
|
||||
alias Cannery.Ammo.AmmoType
|
||||
|
||||
@doc """
|
||||
Returns the list of ammo_types.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> list_ammo_types()
|
||||
[%AmmoType{}, ...]
|
||||
|
||||
"""
|
||||
def list_ammo_types do
|
||||
Repo.all(AmmoType)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets a single ammo_type.
|
||||
|
||||
Raises `Ecto.NoResultsError` if the Ammo type does not exist.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_ammo_type!(123)
|
||||
%AmmoType{}
|
||||
|
||||
iex> get_ammo_type!(456)
|
||||
** (Ecto.NoResultsError)
|
||||
|
||||
"""
|
||||
def get_ammo_type!(id), do: Repo.get!(AmmoType, id)
|
||||
|
||||
@doc """
|
||||
Creates a ammo_type.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> create_ammo_type(%{field: value})
|
||||
{:ok, %AmmoType{}}
|
||||
|
||||
iex> create_ammo_type(%{field: bad_value})
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def create_ammo_type(attrs \\ %{}) do
|
||||
%AmmoType{}
|
||||
|> AmmoType.changeset(attrs)
|
||||
|> Repo.insert()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Updates a ammo_type.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> update_ammo_type(ammo_type, %{field: new_value})
|
||||
{:ok, %AmmoType{}}
|
||||
|
||||
iex> update_ammo_type(ammo_type, %{field: bad_value})
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def update_ammo_type(%AmmoType{} = ammo_type, attrs) do
|
||||
ammo_type
|
||||
|> AmmoType.changeset(attrs)
|
||||
|> Repo.update()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Deletes a ammo_type.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> delete_ammo_type(ammo_type)
|
||||
{:ok, %AmmoType{}}
|
||||
|
||||
iex> delete_ammo_type(ammo_type)
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def delete_ammo_type(%AmmoType{} = ammo_type) do
|
||||
Repo.delete(ammo_type)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns an `%Ecto.Changeset{}` for tracking ammo_type changes.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> change_ammo_type(ammo_type)
|
||||
%Ecto.Changeset{data: %AmmoType{}}
|
||||
|
||||
"""
|
||||
def change_ammo_type(%AmmoType{} = ammo_type, attrs \\ %{}) do
|
||||
AmmoType.changeset(ammo_type, attrs)
|
||||
end
|
||||
|
||||
alias Cannery.Ammo.AmmoGroup
|
||||
|
||||
@doc """
|
||||
Returns the list of ammo_groups.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> list_ammo_groups()
|
||||
[%AmmoGroup{}, ...]
|
||||
|
||||
"""
|
||||
def list_ammo_groups do
|
||||
Repo.all(AmmoGroup)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets a single ammo_group.
|
||||
|
||||
Raises `Ecto.NoResultsError` if the Ammo group does not exist.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_ammo_group!(123)
|
||||
%AmmoGroup{}
|
||||
|
||||
iex> get_ammo_group!(456)
|
||||
** (Ecto.NoResultsError)
|
||||
|
||||
"""
|
||||
def get_ammo_group!(id), do: Repo.get!(AmmoGroup, id)
|
||||
|
||||
@doc """
|
||||
Creates a ammo_group.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> create_ammo_group(%{field: value})
|
||||
{:ok, %AmmoGroup{}}
|
||||
|
||||
iex> create_ammo_group(%{field: bad_value})
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def create_ammo_group(attrs \\ %{}) do
|
||||
%AmmoGroup{}
|
||||
|> AmmoGroup.changeset(attrs)
|
||||
|> Repo.insert()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Updates a ammo_group.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> update_ammo_group(ammo_group, %{field: new_value})
|
||||
{:ok, %AmmoGroup{}}
|
||||
|
||||
iex> update_ammo_group(ammo_group, %{field: bad_value})
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def update_ammo_group(%AmmoGroup{} = ammo_group, attrs) do
|
||||
ammo_group
|
||||
|> AmmoGroup.changeset(attrs)
|
||||
|> Repo.update()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Deletes a ammo_group.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> delete_ammo_group(ammo_group)
|
||||
{:ok, %AmmoGroup{}}
|
||||
|
||||
iex> delete_ammo_group(ammo_group)
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def delete_ammo_group(%AmmoGroup{} = ammo_group) do
|
||||
Repo.delete(ammo_group)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns an `%Ecto.Changeset{}` for tracking ammo_group changes.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> change_ammo_group(ammo_group)
|
||||
%Ecto.Changeset{data: %AmmoGroup{}}
|
||||
|
||||
"""
|
||||
def change_ammo_group(%AmmoGroup{} = ammo_group, attrs \\ %{}) do
|
||||
AmmoGroup.changeset(ammo_group, attrs)
|
||||
end
|
||||
end
|
25
lib/cannery/ammo/ammo_group.ex
Normal file
25
lib/cannery/ammo/ammo_group.ex
Normal file
@ -0,0 +1,25 @@
|
||||
defmodule Cannery.Ammo.AmmoGroup do
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
|
||||
@primary_key {:id, :binary_id, autogenerate: true}
|
||||
@foreign_key_type :binary_id
|
||||
schema "ammo_groups" do
|
||||
field :count, :integer
|
||||
field :notes, :string
|
||||
field :price_paid, :float
|
||||
field :tag_id, :binary_id
|
||||
field :ammo_type_id, :binary_id
|
||||
field :container_id, :binary_id
|
||||
field :user_id, :binary_id
|
||||
|
||||
timestamps()
|
||||
end
|
||||
|
||||
@doc false
|
||||
def changeset(ammo_group, attrs) do
|
||||
ammo_group
|
||||
|> cast(attrs, [:count, :price_paid, :notes])
|
||||
|> validate_required([:count, :price_paid, :notes])
|
||||
end
|
||||
end
|
24
lib/cannery/ammo/ammo_type.ex
Normal file
24
lib/cannery/ammo/ammo_type.ex
Normal file
@ -0,0 +1,24 @@
|
||||
defmodule Cannery.Ammo.AmmoType do
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
|
||||
@primary_key {:id, :binary_id, autogenerate: true}
|
||||
@foreign_key_type :binary_id
|
||||
schema "ammo_types" do
|
||||
field :bullet_type, :string
|
||||
field :case_material, :string
|
||||
field :desc, :string
|
||||
field :manufacturer, :string
|
||||
field :name, :string
|
||||
field :weight, :float
|
||||
|
||||
timestamps()
|
||||
end
|
||||
|
||||
@doc false
|
||||
def changeset(ammo_type, attrs) do
|
||||
ammo_type
|
||||
|> cast(attrs, [:name, :desc, :case_material, :bullet_type, :weight, :manufacturer])
|
||||
|> validate_required([:name, :desc, :case_material, :bullet_type, :weight, :manufacturer])
|
||||
end
|
||||
end
|
104
lib/cannery/containers.ex
Normal file
104
lib/cannery/containers.ex
Normal file
@ -0,0 +1,104 @@
|
||||
defmodule Cannery.Containers do
|
||||
@moduledoc """
|
||||
The Containers context.
|
||||
"""
|
||||
|
||||
import Ecto.Query, warn: false
|
||||
alias Cannery.Repo
|
||||
|
||||
alias Cannery.Containers.Container
|
||||
|
||||
@doc """
|
||||
Returns the list of containers.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> list_containers()
|
||||
[%Container{}, ...]
|
||||
|
||||
"""
|
||||
def list_containers do
|
||||
Repo.all(Container)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets a single container.
|
||||
|
||||
Raises `Ecto.NoResultsError` if the Container does not exist.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_container!(123)
|
||||
%Container{}
|
||||
|
||||
iex> get_container!(456)
|
||||
** (Ecto.NoResultsError)
|
||||
|
||||
"""
|
||||
def get_container!(id), do: Repo.get!(Container, id)
|
||||
|
||||
@doc """
|
||||
Creates a container.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> create_container(%{field: value})
|
||||
{:ok, %Container{}}
|
||||
|
||||
iex> create_container(%{field: bad_value})
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def create_container(attrs \\ %{}) do
|
||||
%Container{}
|
||||
|> Container.changeset(attrs)
|
||||
|> Repo.insert()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Updates a container.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> update_container(container, %{field: new_value})
|
||||
{:ok, %Container{}}
|
||||
|
||||
iex> update_container(container, %{field: bad_value})
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def update_container(%Container{} = container, attrs) do
|
||||
container
|
||||
|> Container.changeset(attrs)
|
||||
|> Repo.update()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Deletes a container.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> delete_container(container)
|
||||
{:ok, %Container{}}
|
||||
|
||||
iex> delete_container(container)
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def delete_container(%Container{} = container) do
|
||||
Repo.delete(container)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns an `%Ecto.Changeset{}` for tracking container changes.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> change_container(container)
|
||||
%Ecto.Changeset{data: %Container{}}
|
||||
|
||||
"""
|
||||
def change_container(%Container{} = container, attrs \\ %{}) do
|
||||
Container.changeset(container, attrs)
|
||||
end
|
||||
end
|
23
lib/cannery/containers/container.ex
Normal file
23
lib/cannery/containers/container.ex
Normal file
@ -0,0 +1,23 @@
|
||||
defmodule Cannery.Containers.Container do
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
|
||||
@primary_key {:id, :binary_id, autogenerate: true}
|
||||
@foreign_key_type :binary_id
|
||||
schema "containers" do
|
||||
field :desc, :string
|
||||
field :location, :string
|
||||
field :name, :string
|
||||
field :type, :string
|
||||
field :user_id, :binary_id
|
||||
|
||||
timestamps()
|
||||
end
|
||||
|
||||
@doc false
|
||||
def changeset(container, attrs) do
|
||||
container
|
||||
|> cast(attrs, [:name, :desc, :type, :location])
|
||||
|> validate_required([:name, :desc, :type, :location])
|
||||
end
|
||||
end
|
104
lib/cannery/tags.ex
Normal file
104
lib/cannery/tags.ex
Normal file
@ -0,0 +1,104 @@
|
||||
defmodule Cannery.Tags do
|
||||
@moduledoc """
|
||||
The Tags context.
|
||||
"""
|
||||
|
||||
import Ecto.Query, warn: false
|
||||
alias Cannery.Repo
|
||||
|
||||
alias Cannery.Tags.Tag
|
||||
|
||||
@doc """
|
||||
Returns the list of tags.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> list_tags()
|
||||
[%Tag{}, ...]
|
||||
|
||||
"""
|
||||
def list_tags do
|
||||
Repo.all(Tag)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets a single tag.
|
||||
|
||||
Raises `Ecto.NoResultsError` if the Tag does not exist.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_tag!(123)
|
||||
%Tag{}
|
||||
|
||||
iex> get_tag!(456)
|
||||
** (Ecto.NoResultsError)
|
||||
|
||||
"""
|
||||
def get_tag!(id), do: Repo.get!(Tag, id)
|
||||
|
||||
@doc """
|
||||
Creates a tag.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> create_tag(%{field: value})
|
||||
{:ok, %Tag{}}
|
||||
|
||||
iex> create_tag(%{field: bad_value})
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def create_tag(attrs \\ %{}) do
|
||||
%Tag{}
|
||||
|> Tag.changeset(attrs)
|
||||
|> Repo.insert()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Updates a tag.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> update_tag(tag, %{field: new_value})
|
||||
{:ok, %Tag{}}
|
||||
|
||||
iex> update_tag(tag, %{field: bad_value})
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def update_tag(%Tag{} = tag, attrs) do
|
||||
tag
|
||||
|> Tag.changeset(attrs)
|
||||
|> Repo.update()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Deletes a tag.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> delete_tag(tag)
|
||||
{:ok, %Tag{}}
|
||||
|
||||
iex> delete_tag(tag)
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def delete_tag(%Tag{} = tag) do
|
||||
Repo.delete(tag)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns an `%Ecto.Changeset{}` for tracking tag changes.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> change_tag(tag)
|
||||
%Ecto.Changeset{data: %Tag{}}
|
||||
|
||||
"""
|
||||
def change_tag(%Tag{} = tag, attrs \\ %{}) do
|
||||
Tag.changeset(tag, attrs)
|
||||
end
|
||||
end
|
22
lib/cannery/tags/tag.ex
Normal file
22
lib/cannery/tags/tag.ex
Normal file
@ -0,0 +1,22 @@
|
||||
defmodule Cannery.Tags.Tag do
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
|
||||
@primary_key {:id, :binary_id, autogenerate: true}
|
||||
@foreign_key_type :binary_id
|
||||
schema "tags" do
|
||||
field :"bg-color", :string
|
||||
field :name, :string
|
||||
field :"text-color", :string
|
||||
field :user_id, :binary_id
|
||||
|
||||
timestamps()
|
||||
end
|
||||
|
||||
@doc false
|
||||
def changeset(tag, attrs) do
|
||||
tag
|
||||
|> cast(attrs, [:name, :"bg-color", :"text-color"])
|
||||
|> validate_required([:name, :"bg-color", :"text-color"])
|
||||
end
|
||||
end
|
@ -46,7 +46,7 @@ defmodule CanneryWeb do
|
||||
quote do
|
||||
use Phoenix.LiveView,
|
||||
layout: {CanneryWeb.LayoutView, "live.html"}
|
||||
|
||||
|
||||
unquote(view_helpers())
|
||||
end
|
||||
end
|
||||
@ -83,6 +83,7 @@ defmodule CanneryWeb do
|
||||
|
||||
# Import LiveView helpers (live_render, live_component, live_patch, etc)
|
||||
import Phoenix.LiveView.Helpers
|
||||
import CanneryWeb.LiveHelpers
|
||||
|
||||
# Import basic rendering functionality (render, render_layout, etc)
|
||||
import Phoenix.View
|
||||
|
@ -9,7 +9,7 @@ defmodule CanneryWeb.UserSocket do
|
||||
# verification, you can put default assigns into
|
||||
# the socket that will be set for all channels, ie
|
||||
#
|
||||
# {:ok, assign(socket, :user_id, verified_user_id)}
|
||||
# {:ok, socket |> assign(:user_id, verified_user_id)}
|
||||
#
|
||||
# To deny connection, return `:error`.
|
||||
#
|
||||
|
@ -20,5 +20,5 @@ defmodule CanneryWeb.Gettext do
|
||||
|
||||
See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage.
|
||||
"""
|
||||
use Gettext, otp_app: :cannery
|
||||
# use Gettext, otp_app: :cannery
|
||||
end
|
||||
|
55
lib/cannery_web/live/ammo_group_live/form_component.ex
Normal file
55
lib/cannery_web/live/ammo_group_live/form_component.ex
Normal file
@ -0,0 +1,55 @@
|
||||
defmodule CanneryWeb.AmmoGroupLive.FormComponent do
|
||||
use CanneryWeb, :live_component
|
||||
|
||||
alias Cannery.Ammo
|
||||
|
||||
@impl true
|
||||
def update(%{ammo_group: ammo_group} = assigns, socket) do
|
||||
changeset = Ammo.change_ammo_group(ammo_group)
|
||||
|
||||
{:ok,
|
||||
socket
|
||||
|> assign(assigns)
|
||||
|> assign(:changeset, changeset)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("validate", %{"ammo_group" => ammo_group_params}, socket) do
|
||||
changeset =
|
||||
socket.assigns.ammo_group
|
||||
|> Ammo.change_ammo_group(ammo_group_params)
|
||||
|> Map.put(:action, :validate)
|
||||
|
||||
{:noreply, socket |> assign(:changeset, changeset)}
|
||||
end
|
||||
|
||||
def handle_event("save", %{"ammo_group" => ammo_group_params}, socket) do
|
||||
save_ammo_group(socket, socket.assigns.action, ammo_group_params)
|
||||
end
|
||||
|
||||
defp save_ammo_group(socket, :edit, ammo_group_params) do
|
||||
case Ammo.update_ammo_group(socket.assigns.ammo_group, ammo_group_params) do
|
||||
{:ok, _ammo_group} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:info, "Ammo group updated successfully")
|
||||
|> push_redirect(to: socket.assigns.return_to)}
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
{:noreply, socket |> assign(:changeset, changeset)}
|
||||
end
|
||||
end
|
||||
|
||||
defp save_ammo_group(socket, :new, ammo_group_params) do
|
||||
case Ammo.create_ammo_group(ammo_group_params) do
|
||||
{:ok, _ammo_group} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:info, "Ammo group created successfully")
|
||||
|> push_redirect(to: socket.assigns.return_to)}
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
{:noreply, socket |> assign(changeset: changeset)}
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,22 @@
|
||||
<h2><%= @title %></h2>
|
||||
|
||||
<%= f = form_for @changeset, "#",
|
||||
id: "ammo_group-form",
|
||||
phx_target: @myself,
|
||||
phx_change: "validate",
|
||||
phx_submit: "save" %>
|
||||
|
||||
<%= label f, :count %>
|
||||
<%= number_input f, :count %>
|
||||
<%= error_tag f, :count %>
|
||||
|
||||
<%= label f, :price_paid %>
|
||||
<%= number_input f, :price_paid, step: "any" %>
|
||||
<%= error_tag f, :price_paid %>
|
||||
|
||||
<%= label f, :notes %>
|
||||
<%= textarea f, :notes %>
|
||||
<%= error_tag f, :notes %>
|
||||
|
||||
<%= submit "Save", phx_disable_with: "Saving..." %>
|
||||
</form>
|
46
lib/cannery_web/live/ammo_group_live/index.ex
Normal file
46
lib/cannery_web/live/ammo_group_live/index.ex
Normal file
@ -0,0 +1,46 @@
|
||||
defmodule CanneryWeb.AmmoGroupLive.Index do
|
||||
use CanneryWeb, :live_view
|
||||
|
||||
alias Cannery.Ammo
|
||||
alias Cannery.Ammo.AmmoGroup
|
||||
|
||||
@impl true
|
||||
def mount(_params, _session, socket) do
|
||||
{:ok, socket |> assign(:ammo_groups, list_ammo_groups())}
|
||||
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 Ammo group")
|
||||
|> assign(:ammo_group, Ammo.get_ammo_group!(id))
|
||||
end
|
||||
|
||||
defp apply_action(socket, :new, _params) do
|
||||
socket
|
||||
|> assign(:page_title, "New Ammo group")
|
||||
|> assign(:ammo_group, %AmmoGroup{})
|
||||
end
|
||||
|
||||
defp apply_action(socket, :index, _params) do
|
||||
socket
|
||||
|> assign(:page_title, "Listing Ammo groups")
|
||||
|> assign(:ammo_group, nil)
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("delete", %{"id" => id}, socket) do
|
||||
ammo_group = Ammo.get_ammo_group!(id)
|
||||
{:ok, _} = Ammo.delete_ammo_group(ammo_group)
|
||||
|
||||
{:noreply, socket |> assign(:ammo_groups, list_ammo_groups())}
|
||||
end
|
||||
|
||||
defp list_ammo_groups do
|
||||
Ammo.list_ammo_groups()
|
||||
end
|
||||
end
|
39
lib/cannery_web/live/ammo_group_live/index.html.leex
Normal file
39
lib/cannery_web/live/ammo_group_live/index.html.leex
Normal file
@ -0,0 +1,39 @@
|
||||
<h1>Listing Ammo groups</h1>
|
||||
|
||||
<%= if @live_action in [:new, :edit] do %>
|
||||
<%= live_modal CanneryWeb.AmmoGroupLive.FormComponent,
|
||||
id: @ammo_group.id || :new,
|
||||
title: @page_title,
|
||||
action: @live_action,
|
||||
ammo_group: @ammo_group,
|
||||
return_to: Routes.ammo_group_index_path(@socket, :index) %>
|
||||
<% end %>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Count</th>
|
||||
<th>Price paid</th>
|
||||
<th>Notes</th>
|
||||
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="ammo_groups">
|
||||
<%= for ammo_group <- @ammo_groups do %>
|
||||
<tr id="ammo_group-<%= ammo_group.id %>">
|
||||
<td><%= ammo_group.count %></td>
|
||||
<td><%= ammo_group.price_paid %></td>
|
||||
<td><%= ammo_group.notes %></td>
|
||||
|
||||
<td>
|
||||
<span><%= live_redirect "Show", to: Routes.ammo_group_show_path(@socket, :show, ammo_group) %></span>
|
||||
<span><%= live_patch "Edit", to: Routes.ammo_group_index_path(@socket, :edit, ammo_group) %></span>
|
||||
<span><%= link "Delete", to: "#", phx_click: "delete", phx_value_id: ammo_group.id, data: [confirm: "Are you sure?"] %></span>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<span><%= live_patch "New Ammo group", to: Routes.ammo_group_index_path(@socket, :new) %></span>
|
21
lib/cannery_web/live/ammo_group_live/show.ex
Normal file
21
lib/cannery_web/live/ammo_group_live/show.ex
Normal file
@ -0,0 +1,21 @@
|
||||
defmodule CanneryWeb.AmmoGroupLive.Show do
|
||||
use CanneryWeb, :live_view
|
||||
|
||||
alias Cannery.Ammo
|
||||
|
||||
@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(:ammo_group, Ammo.get_ammo_group!(id))}
|
||||
end
|
||||
|
||||
defp page_title(:show), do: "Show Ammo group"
|
||||
defp page_title(:edit), do: "Edit Ammo group"
|
||||
end
|
32
lib/cannery_web/live/ammo_group_live/show.html.leex
Normal file
32
lib/cannery_web/live/ammo_group_live/show.html.leex
Normal file
@ -0,0 +1,32 @@
|
||||
<h1>Show Ammo group</h1>
|
||||
|
||||
<%= if @live_action in [:edit] do %>
|
||||
<%= live_modal CanneryWeb.AmmoGroupLive.FormComponent,
|
||||
id: @ammo_group.id,
|
||||
title: @page_title,
|
||||
action: @live_action,
|
||||
ammo_group: @ammo_group,
|
||||
return_to: Routes.ammo_group_show_path(@socket, :show, @ammo_group) %>
|
||||
<% end %>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<strong>Count:</strong>
|
||||
<%= @ammo_group.count %>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<strong>Price paid:</strong>
|
||||
<%= @ammo_group.price_paid %>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<strong>Notes:</strong>
|
||||
<%= @ammo_group.notes %>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<span><%= live_patch "Edit", to: Routes.ammo_group_show_path(@socket, :edit, @ammo_group), class: "button" %></span>
|
||||
<span><%= live_redirect "Back", to: Routes.ammo_group_index_path(@socket, :index) %></span>
|
55
lib/cannery_web/live/ammo_type_live/form_component.ex
Normal file
55
lib/cannery_web/live/ammo_type_live/form_component.ex
Normal file
@ -0,0 +1,55 @@
|
||||
defmodule CanneryWeb.AmmoTypeLive.FormComponent do
|
||||
use CanneryWeb, :live_component
|
||||
|
||||
alias Cannery.Ammo
|
||||
|
||||
@impl true
|
||||
def update(%{ammo_type: ammo_type} = assigns, socket) do
|
||||
changeset = Ammo.change_ammo_type(ammo_type)
|
||||
|
||||
{:ok,
|
||||
socket
|
||||
|> assign(assigns)
|
||||
|> assign(:changeset, changeset)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("validate", %{"ammo_type" => ammo_type_params}, socket) do
|
||||
changeset =
|
||||
socket.assigns.ammo_type
|
||||
|> Ammo.change_ammo_type(ammo_type_params)
|
||||
|> Map.put(:action, :validate)
|
||||
|
||||
{:noreply, socket |> assign(:changeset, changeset)}
|
||||
end
|
||||
|
||||
def handle_event("save", %{"ammo_type" => ammo_type_params}, socket) do
|
||||
save_ammo_type(socket, socket.assigns.action, ammo_type_params)
|
||||
end
|
||||
|
||||
defp save_ammo_type(socket, :edit, ammo_type_params) do
|
||||
case Ammo.update_ammo_type(socket.assigns.ammo_type, ammo_type_params) do
|
||||
{:ok, _ammo_type} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:info, "Ammo type updated successfully")
|
||||
|> push_redirect(to: socket.assigns.return_to)}
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
{:noreply, socket |> assign(:changeset, changeset)}
|
||||
end
|
||||
end
|
||||
|
||||
defp save_ammo_type(socket, :new, ammo_type_params) do
|
||||
case Ammo.create_ammo_type(ammo_type_params) do
|
||||
{:ok, _ammo_type} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:info, "Ammo type created successfully")
|
||||
|> push_redirect(to: socket.assigns.return_to)}
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
{:noreply, socket |> assign(changeset: changeset)}
|
||||
end
|
||||
end
|
||||
end
|
34
lib/cannery_web/live/ammo_type_live/form_component.html.leex
Normal file
34
lib/cannery_web/live/ammo_type_live/form_component.html.leex
Normal file
@ -0,0 +1,34 @@
|
||||
<h2><%= @title %></h2>
|
||||
|
||||
<%= f = form_for @changeset, "#",
|
||||
id: "ammo_type-form",
|
||||
phx_target: @myself,
|
||||
phx_change: "validate",
|
||||
phx_submit: "save" %>
|
||||
|
||||
<%= label f, :name %>
|
||||
<%= text_input f, :name %>
|
||||
<%= error_tag f, :name %>
|
||||
|
||||
<%= label f, :desc %>
|
||||
<%= text_input f, :desc %>
|
||||
<%= error_tag f, :desc %>
|
||||
|
||||
<%= label f, :case_material %>
|
||||
<%= text_input f, :case_material %>
|
||||
<%= error_tag f, :case_material %>
|
||||
|
||||
<%= label f, :bullet_type %>
|
||||
<%= text_input f, :bullet_type %>
|
||||
<%= error_tag f, :bullet_type %>
|
||||
|
||||
<%= label f, :weight %>
|
||||
<%= number_input f, :weight, step: "any" %>
|
||||
<%= error_tag f, :weight %>
|
||||
|
||||
<%= label f, :manufacturer %>
|
||||
<%= text_input f, :manufacturer %>
|
||||
<%= error_tag f, :manufacturer %>
|
||||
|
||||
<%= submit "Save", phx_disable_with: "Saving..." %>
|
||||
</form>
|
46
lib/cannery_web/live/ammo_type_live/index.ex
Normal file
46
lib/cannery_web/live/ammo_type_live/index.ex
Normal file
@ -0,0 +1,46 @@
|
||||
defmodule CanneryWeb.AmmoTypeLive.Index do
|
||||
use CanneryWeb, :live_view
|
||||
|
||||
alias Cannery.Ammo
|
||||
alias Cannery.Ammo.AmmoType
|
||||
|
||||
@impl true
|
||||
def mount(_params, _session, socket) do
|
||||
{:ok, socket |> assign(:ammo_types, list_ammo_types())}
|
||||
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 Ammo type")
|
||||
|> assign(:ammo_type, Ammo.get_ammo_type!(id))
|
||||
end
|
||||
|
||||
defp apply_action(socket, :new, _params) do
|
||||
socket
|
||||
|> assign(:page_title, "New Ammo type")
|
||||
|> assign(:ammo_type, %AmmoType{})
|
||||
end
|
||||
|
||||
defp apply_action(socket, :index, _params) do
|
||||
socket
|
||||
|> assign(:page_title, "Listing Ammo types")
|
||||
|> assign(:ammo_type, nil)
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("delete", %{"id" => id}, socket) do
|
||||
ammo_type = Ammo.get_ammo_type!(id)
|
||||
{:ok, _} = Ammo.delete_ammo_type(ammo_type)
|
||||
|
||||
{:noreply, socket |> assign(:ammo_types, list_ammo_types())}
|
||||
end
|
||||
|
||||
defp list_ammo_types do
|
||||
Ammo.list_ammo_types()
|
||||
end
|
||||
end
|
45
lib/cannery_web/live/ammo_type_live/index.html.leex
Normal file
45
lib/cannery_web/live/ammo_type_live/index.html.leex
Normal file
@ -0,0 +1,45 @@
|
||||
<h1>Listing Ammo types</h1>
|
||||
|
||||
<%= if @live_action in [:new, :edit] do %>
|
||||
<%= live_modal CanneryWeb.AmmoTypeLive.FormComponent,
|
||||
id: @ammo_type.id || :new,
|
||||
title: @page_title,
|
||||
action: @live_action,
|
||||
ammo_type: @ammo_type,
|
||||
return_to: Routes.ammo_type_index_path(@socket, :index) %>
|
||||
<% end %>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Desc</th>
|
||||
<th>Case material</th>
|
||||
<th>Bullet type</th>
|
||||
<th>Weight</th>
|
||||
<th>Manufacturer</th>
|
||||
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="ammo_types">
|
||||
<%= for ammo_type <- @ammo_types do %>
|
||||
<tr id="ammo_type-<%= ammo_type.id %>">
|
||||
<td><%= ammo_type.name %></td>
|
||||
<td><%= ammo_type.desc %></td>
|
||||
<td><%= ammo_type.case_material %></td>
|
||||
<td><%= ammo_type.bullet_type %></td>
|
||||
<td><%= ammo_type.weight %></td>
|
||||
<td><%= ammo_type.manufacturer %></td>
|
||||
|
||||
<td>
|
||||
<span><%= live_redirect "Show", to: Routes.ammo_type_show_path(@socket, :show, ammo_type) %></span>
|
||||
<span><%= live_patch "Edit", to: Routes.ammo_type_index_path(@socket, :edit, ammo_type) %></span>
|
||||
<span><%= link "Delete", to: "#", phx_click: "delete", phx_value_id: ammo_type.id, data: [confirm: "Are you sure?"] %></span>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<span><%= live_patch "New Ammo type", to: Routes.ammo_type_index_path(@socket, :new) %></span>
|
21
lib/cannery_web/live/ammo_type_live/show.ex
Normal file
21
lib/cannery_web/live/ammo_type_live/show.ex
Normal file
@ -0,0 +1,21 @@
|
||||
defmodule CanneryWeb.AmmoTypeLive.Show do
|
||||
use CanneryWeb, :live_view
|
||||
|
||||
alias Cannery.Ammo
|
||||
|
||||
@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(:ammo_type, Ammo.get_ammo_type!(id))}
|
||||
end
|
||||
|
||||
defp page_title(:show), do: "Show Ammo type"
|
||||
defp page_title(:edit), do: "Edit Ammo type"
|
||||
end
|
47
lib/cannery_web/live/ammo_type_live/show.html.leex
Normal file
47
lib/cannery_web/live/ammo_type_live/show.html.leex
Normal file
@ -0,0 +1,47 @@
|
||||
<h1>Show Ammo type</h1>
|
||||
|
||||
<%= if @live_action in [:edit] do %>
|
||||
<%= live_modal CanneryWeb.AmmoTypeLive.FormComponent,
|
||||
id: @ammo_type.id,
|
||||
title: @page_title,
|
||||
action: @live_action,
|
||||
ammo_type: @ammo_type,
|
||||
return_to: Routes.ammo_type_show_path(@socket, :show, @ammo_type) %>
|
||||
<% end %>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<strong>Name:</strong>
|
||||
<%= @ammo_type.name %>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<strong>Desc:</strong>
|
||||
<%= @ammo_type.desc %>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<strong>Case material:</strong>
|
||||
<%= @ammo_type.case_material %>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<strong>Bullet type:</strong>
|
||||
<%= @ammo_type.bullet_type %>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<strong>Weight:</strong>
|
||||
<%= @ammo_type.weight %>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<strong>Manufacturer:</strong>
|
||||
<%= @ammo_type.manufacturer %>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<span><%= live_patch "Edit", to: Routes.ammo_type_show_path(@socket, :edit, @ammo_type), class: "button" %></span>
|
||||
<span><%= live_redirect "Back", to: Routes.ammo_type_index_path(@socket, :index) %></span>
|
@ -1,12 +1,12 @@
|
||||
defmodule CanneryWeb.Live.Component.Topbar do
|
||||
use CanneryWeb, :live_component
|
||||
|
||||
|
||||
alias CanneryWeb.{PageLive}
|
||||
|
||||
|
||||
def mount(socket) do
|
||||
{:ok, socket |> assign(results: [], title_content: nil)}
|
||||
end
|
||||
|
||||
|
||||
def update(assigns, socket) do
|
||||
{:ok, socket |> assign(assigns)}
|
||||
end
|
||||
@ -41,7 +41,7 @@ defmodule CanneryWeb.Live.Component.Topbar do
|
||||
</form>
|
||||
|
||||
<%# user settings %>
|
||||
<%= if assigns |> Map.has_key?(:current_user) do %>
|
||||
<%= if @current_user do %>
|
||||
<li>
|
||||
<%= @current_user.email %></li>
|
||||
<li>
|
||||
@ -89,4 +89,4 @@ defmodule CanneryWeb.Live.Component.Topbar do
|
||||
</header>
|
||||
"""
|
||||
end
|
||||
end
|
||||
end
|
||||
|
55
lib/cannery_web/live/container_live/form_component.ex
Normal file
55
lib/cannery_web/live/container_live/form_component.ex
Normal file
@ -0,0 +1,55 @@
|
||||
defmodule CanneryWeb.ContainerLive.FormComponent do
|
||||
use CanneryWeb, :live_component
|
||||
|
||||
alias Cannery.Containers
|
||||
|
||||
@impl true
|
||||
def update(%{container: container} = assigns, socket) do
|
||||
changeset = Containers.change_container(container)
|
||||
|
||||
{:ok,
|
||||
socket
|
||||
|> assign(assigns)
|
||||
|> assign(:changeset, changeset)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("validate", %{"container" => container_params}, socket) do
|
||||
changeset =
|
||||
socket.assigns.container
|
||||
|> Containers.change_container(container_params)
|
||||
|> Map.put(:action, :validate)
|
||||
|
||||
{:noreply, socket |> assign(:changeset, changeset)}
|
||||
end
|
||||
|
||||
def handle_event("save", %{"container" => container_params}, socket) do
|
||||
save_container(socket, socket.assigns.action, container_params)
|
||||
end
|
||||
|
||||
defp save_container(socket, :edit, container_params) do
|
||||
case Containers.update_container(socket.assigns.container, container_params) do
|
||||
{:ok, _container} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:info, "Container updated successfully")
|
||||
|> push_redirect(to: socket.assigns.return_to)}
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
{:noreply, socket |> assign(:changeset, changeset)}
|
||||
end
|
||||
end
|
||||
|
||||
defp save_container(socket, :new, container_params) do
|
||||
case Containers.create_container(container_params) do
|
||||
{:ok, _container} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:info, "Container created successfully")
|
||||
|> push_redirect(to: socket.assigns.return_to)}
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
{:noreply, socket |> assign(changeset: changeset)}
|
||||
end
|
||||
end
|
||||
end
|
26
lib/cannery_web/live/container_live/form_component.html.leex
Normal file
26
lib/cannery_web/live/container_live/form_component.html.leex
Normal file
@ -0,0 +1,26 @@
|
||||
<h2><%= @title %></h2>
|
||||
|
||||
<%= f = form_for @changeset, "#",
|
||||
id: "container-form",
|
||||
phx_target: @myself,
|
||||
phx_change: "validate",
|
||||
phx_submit: "save" %>
|
||||
|
||||
<%= label f, :name %>
|
||||
<%= text_input f, :name %>
|
||||
<%= error_tag f, :name %>
|
||||
|
||||
<%= label f, :desc %>
|
||||
<%= text_input f, :desc %>
|
||||
<%= error_tag f, :desc %>
|
||||
|
||||
<%= label f, :type %>
|
||||
<%= text_input f, :type %>
|
||||
<%= error_tag f, :type %>
|
||||
|
||||
<%= label f, :location %>
|
||||
<%= text_input f, :location %>
|
||||
<%= error_tag f, :location %>
|
||||
|
||||
<%= submit "Save", phx_disable_with: "Saving..." %>
|
||||
</form>
|
46
lib/cannery_web/live/container_live/index.ex
Normal file
46
lib/cannery_web/live/container_live/index.ex
Normal file
@ -0,0 +1,46 @@
|
||||
defmodule CanneryWeb.ContainerLive.Index do
|
||||
use CanneryWeb, :live_view
|
||||
|
||||
alias Cannery.Containers
|
||||
alias Cannery.Containers.Container
|
||||
|
||||
@impl true
|
||||
def mount(_params, _session, socket) do
|
||||
{:ok, socket |> assign(:containers, list_containers())}
|
||||
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 Container")
|
||||
|> assign(:container, Containers.get_container!(id))
|
||||
end
|
||||
|
||||
defp apply_action(socket, :new, _params) do
|
||||
socket
|
||||
|> assign(:page_title, "New Container")
|
||||
|> assign(:container, %Container{})
|
||||
end
|
||||
|
||||
defp apply_action(socket, :index, _params) do
|
||||
socket
|
||||
|> assign(:page_title, "Listing Containers")
|
||||
|> assign(:container, nil)
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("delete", %{"id" => id}, socket) do
|
||||
container = Containers.get_container!(id)
|
||||
{:ok, _} = Containers.delete_container(container)
|
||||
|
||||
{:noreply, socket |> assign(:containers, list_containers())}
|
||||
end
|
||||
|
||||
defp list_containers do
|
||||
Containers.list_containers()
|
||||
end
|
||||
end
|
41
lib/cannery_web/live/container_live/index.html.leex
Normal file
41
lib/cannery_web/live/container_live/index.html.leex
Normal file
@ -0,0 +1,41 @@
|
||||
<h1>Listing Containers</h1>
|
||||
|
||||
<%= if @live_action in [:new, :edit] do %>
|
||||
<%= live_modal CanneryWeb.ContainerLive.FormComponent,
|
||||
id: @container.id || :new,
|
||||
title: @page_title,
|
||||
action: @live_action,
|
||||
container: @container,
|
||||
return_to: Routes.container_index_path(@socket, :index) %>
|
||||
<% end %>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Desc</th>
|
||||
<th>Type</th>
|
||||
<th>Location</th>
|
||||
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="containers">
|
||||
<%= for container <- @containers do %>
|
||||
<tr id="container-<%= container.id %>">
|
||||
<td><%= container.name %></td>
|
||||
<td><%= container.desc %></td>
|
||||
<td><%= container.type %></td>
|
||||
<td><%= container.location %></td>
|
||||
|
||||
<td>
|
||||
<span><%= live_redirect "Show", to: Routes.container_show_path(@socket, :show, container) %></span>
|
||||
<span><%= live_patch "Edit", to: Routes.container_index_path(@socket, :edit, container) %></span>
|
||||
<span><%= link "Delete", to: "#", phx_click: "delete", phx_value_id: container.id, data: [confirm: "Are you sure?"] %></span>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<span><%= live_patch "New Container", to: Routes.container_index_path(@socket, :new) %></span>
|
21
lib/cannery_web/live/container_live/show.ex
Normal file
21
lib/cannery_web/live/container_live/show.ex
Normal file
@ -0,0 +1,21 @@
|
||||
defmodule CanneryWeb.ContainerLive.Show do
|
||||
use CanneryWeb, :live_view
|
||||
|
||||
alias Cannery.Containers
|
||||
|
||||
@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(:container, Containers.get_container!(id))}
|
||||
end
|
||||
|
||||
defp page_title(:show), do: "Show Container"
|
||||
defp page_title(:edit), do: "Edit Container"
|
||||
end
|
37
lib/cannery_web/live/container_live/show.html.leex
Normal file
37
lib/cannery_web/live/container_live/show.html.leex
Normal file
@ -0,0 +1,37 @@
|
||||
<h1>Show Container</h1>
|
||||
|
||||
<%= if @live_action in [:edit] do %>
|
||||
<%= live_modal CanneryWeb.ContainerLive.FormComponent,
|
||||
id: @container.id,
|
||||
title: @page_title,
|
||||
action: @live_action,
|
||||
container: @container,
|
||||
return_to: Routes.container_show_path(@socket, :show, @container) %>
|
||||
<% end %>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<strong>Name:</strong>
|
||||
<%= @container.name %>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<strong>Desc:</strong>
|
||||
<%= @container.desc %>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<strong>Type:</strong>
|
||||
<%= @container.type %>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<strong>Location:</strong>
|
||||
<%= @container.location %>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<span><%= live_patch "Edit", to: Routes.container_show_path(@socket, :edit, @container), class: "button" %></span>
|
||||
<span><%= live_redirect "Back", to: Routes.container_index_path(@socket, :index) %></span>
|
36
lib/cannery_web/live/live_helpers.ex
Normal file
36
lib/cannery_web/live/live_helpers.ex
Normal file
@ -0,0 +1,36 @@
|
||||
defmodule CanneryWeb.LiveHelpers do
|
||||
import Phoenix.LiveView.Helpers
|
||||
import Phoenix.LiveView, only: [assign_new: 3]
|
||||
alias Cannery.{Accounts}
|
||||
|
||||
@doc """
|
||||
Renders a component inside the `CanneryWeb.ModalComponent` component.
|
||||
|
||||
The rendered modal receives a `:return_to` option to properly update
|
||||
the URL when the modal is closed.
|
||||
|
||||
## Examples
|
||||
|
||||
<%= live_modal CanneryWeb.TagLive.FormComponent,
|
||||
id: @tag.id || :new,
|
||||
action: @live_action,
|
||||
tag: @tag,
|
||||
return_to: Routes.tag_index_path(@socket, :index) %>
|
||||
"""
|
||||
def live_modal(component, opts) do
|
||||
path = Keyword.fetch!(opts, :return_to)
|
||||
modal_opts = [id: :modal, return_to: path, component: component, opts: opts]
|
||||
live_component(CanneryWeb.ModalComponent, modal_opts)
|
||||
end
|
||||
|
||||
def assign_defaults(socket, %{"user_token" => user_token} = _session) do
|
||||
socket
|
||||
|> assign_new(:current_user, fn ->
|
||||
Accounts.get_user_by_session_token(user_token)
|
||||
end)
|
||||
end
|
||||
|
||||
def assign_defaults(socket, _session) do
|
||||
socket
|
||||
end
|
||||
end
|
26
lib/cannery_web/live/modal_component.ex
Normal file
26
lib/cannery_web/live/modal_component.ex
Normal file
@ -0,0 +1,26 @@
|
||||
defmodule CanneryWeb.ModalComponent do
|
||||
use CanneryWeb, :live_component
|
||||
|
||||
@impl true
|
||||
def render(assigns) do
|
||||
~L"""
|
||||
<div id="<%= @id %>" class="phx-modal"
|
||||
phx-capture-click="close"
|
||||
phx-window-keydown="close"
|
||||
phx-key="escape"
|
||||
phx-target="#<%= @id %>"
|
||||
phx-page-loading>
|
||||
|
||||
<div class="phx-modal-content">
|
||||
<%= live_patch raw("×"), to: @return_to, class: "phx-modal-close" %>
|
||||
<%= live_component @socket, @component, @opts %>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("close", _, socket) do
|
||||
{:noreply, push_patch(socket, to: socket.assigns.return_to)}
|
||||
end
|
||||
end
|
@ -2,13 +2,13 @@ defmodule CanneryWeb.PageLive do
|
||||
use CanneryWeb, :live_view
|
||||
|
||||
@impl true
|
||||
def mount(_params, _session, socket) do
|
||||
{:ok, assign(socket, query: "", results: %{})}
|
||||
def mount(_params, session, socket) do
|
||||
{:ok, socket |> assign_defaults(session) |> assign(query: "", results: %{})}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("suggest", %{"q" => query}, socket) do
|
||||
{:noreply, assign(socket, results: search(query), query: query)}
|
||||
{:noreply, socket |> assign(results: search(query), query: query)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
|
55
lib/cannery_web/live/tag_live/form_component.ex
Normal file
55
lib/cannery_web/live/tag_live/form_component.ex
Normal file
@ -0,0 +1,55 @@
|
||||
defmodule CanneryWeb.TagLive.FormComponent do
|
||||
use CanneryWeb, :live_component
|
||||
|
||||
alias Cannery.Tags
|
||||
|
||||
@impl true
|
||||
def update(%{tag: tag} = assigns, socket) do
|
||||
changeset = Tags.change_tag(tag)
|
||||
|
||||
{:ok,
|
||||
socket
|
||||
|> assign(assigns)
|
||||
|> assign(:changeset, changeset)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("validate", %{"tag" => tag_params}, socket) do
|
||||
changeset =
|
||||
socket.assigns.tag
|
||||
|> Tags.change_tag(tag_params)
|
||||
|> Map.put(:action, :validate)
|
||||
|
||||
{:noreply, socket |> assign(:changeset, changeset)}
|
||||
end
|
||||
|
||||
def handle_event("save", %{"tag" => tag_params}, socket) do
|
||||
save_tag(socket, socket.assigns.action, tag_params)
|
||||
end
|
||||
|
||||
defp save_tag(socket, :edit, tag_params) do
|
||||
case Tags.update_tag(socket.assigns.tag, tag_params) do
|
||||
{:ok, _tag} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:info, "Tag updated successfully")
|
||||
|> push_redirect(to: socket.assigns.return_to)}
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
{:noreply, socket |> assign(:changeset, changeset)}
|
||||
end
|
||||
end
|
||||
|
||||
defp save_tag(socket, :new, tag_params) do
|
||||
case Tags.create_tag(tag_params) do
|
||||
{:ok, _tag} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:info, "Tag created successfully")
|
||||
|> push_redirect(to: socket.assigns.return_to)}
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
{:noreply, socket |> assign(changeset: changeset)}
|
||||
end
|
||||
end
|
||||
end
|
22
lib/cannery_web/live/tag_live/form_component.html.leex
Normal file
22
lib/cannery_web/live/tag_live/form_component.html.leex
Normal file
@ -0,0 +1,22 @@
|
||||
<h2><%= @title %></h2>
|
||||
|
||||
<%= f = form_for @changeset, "#",
|
||||
id: "tag-form",
|
||||
phx_target: @myself,
|
||||
phx_change: "validate",
|
||||
phx_submit: "save" %>
|
||||
|
||||
<%= label f, :name %>
|
||||
<%= text_input f, :name %>
|
||||
<%= error_tag f, :name %>
|
||||
|
||||
<%= label f, :"bg-color" %>
|
||||
<%= text_input f, :"bg-color" %>
|
||||
<%= error_tag f, :"bg-color" %>
|
||||
|
||||
<%= label f, :"text-color" %>
|
||||
<%= text_input f, :"text-color" %>
|
||||
<%= error_tag f, :"text-color" %>
|
||||
|
||||
<%= submit "Save", phx_disable_with: "Saving..." %>
|
||||
</form>
|
46
lib/cannery_web/live/tag_live/index.ex
Normal file
46
lib/cannery_web/live/tag_live/index.ex
Normal file
@ -0,0 +1,46 @@
|
||||
defmodule CanneryWeb.TagLive.Index do
|
||||
use CanneryWeb, :live_view
|
||||
|
||||
alias Cannery.Tags
|
||||
alias Cannery.Tags.Tag
|
||||
|
||||
@impl true
|
||||
def mount(_params, _session, socket) do
|
||||
{:ok, socket |> assign(:tags, list_tags())}
|
||||
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 Tag")
|
||||
|> assign(:tag, Tags.get_tag!(id))
|
||||
end
|
||||
|
||||
defp apply_action(socket, :new, _params) do
|
||||
socket
|
||||
|> assign(:page_title, "New Tag")
|
||||
|> assign(:tag, %Tag{})
|
||||
end
|
||||
|
||||
defp apply_action(socket, :index, _params) do
|
||||
socket
|
||||
|> assign(:page_title, "Listing Tags")
|
||||
|> assign(:tag, nil)
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("delete", %{"id" => id}, socket) do
|
||||
tag = Tags.get_tag!(id)
|
||||
{:ok, _} = Tags.delete_tag(tag)
|
||||
|
||||
{:noreply, socket |> assign(:tags, list_tags())}
|
||||
end
|
||||
|
||||
defp list_tags do
|
||||
Tags.list_tags()
|
||||
end
|
||||
end
|
39
lib/cannery_web/live/tag_live/index.html.leex
Normal file
39
lib/cannery_web/live/tag_live/index.html.leex
Normal file
@ -0,0 +1,39 @@
|
||||
<h1>Listing Tags</h1>
|
||||
|
||||
<%= if @live_action in [:new, :edit] do %>
|
||||
<%= live_modal CanneryWeb.TagLive.FormComponent,
|
||||
id: @tag.id || :new,
|
||||
title: @page_title,
|
||||
action: @live_action,
|
||||
tag: @tag,
|
||||
return_to: Routes.tag_index_path(@socket, :index) %>
|
||||
<% end %>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Bg-color</th>
|
||||
<th>Text-color</th>
|
||||
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tags">
|
||||
<%= for tag <- @tags do %>
|
||||
<tr id="tag-<%= tag.id %>">
|
||||
<td><%= tag.name %></td>
|
||||
<td><%= tag.bg_color %></td>
|
||||
<td><%= tag.text_color %></td>
|
||||
|
||||
<td>
|
||||
<span><%= live_redirect "Show", to: Routes.tag_show_path(@socket, :show, tag) %></span>
|
||||
<span><%= live_patch "Edit", to: Routes.tag_index_path(@socket, :edit, tag) %></span>
|
||||
<span><%= link "Delete", to: "#", phx_click: "delete", phx_value_id: tag.id, data: [confirm: "Are you sure?"] %></span>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<span><%= live_patch "New Tag", to: Routes.tag_index_path(@socket, :new) %></span>
|
21
lib/cannery_web/live/tag_live/show.ex
Normal file
21
lib/cannery_web/live/tag_live/show.ex
Normal file
@ -0,0 +1,21 @@
|
||||
defmodule CanneryWeb.TagLive.Show do
|
||||
use CanneryWeb, :live_view
|
||||
|
||||
alias Cannery.Tags
|
||||
|
||||
@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(:tag, Tags.get_tag!(id))}
|
||||
end
|
||||
|
||||
defp page_title(:show), do: "Show Tag"
|
||||
defp page_title(:edit), do: "Edit Tag"
|
||||
end
|
32
lib/cannery_web/live/tag_live/show.html.leex
Normal file
32
lib/cannery_web/live/tag_live/show.html.leex
Normal file
@ -0,0 +1,32 @@
|
||||
<h1>Show Tag</h1>
|
||||
|
||||
<%= if @live_action in [:edit] do %>
|
||||
<%= live_modal CanneryWeb.TagLive.FormComponent,
|
||||
id: @tag.id,
|
||||
title: @page_title,
|
||||
action: @live_action,
|
||||
tag: @tag,
|
||||
return_to: Routes.tag_show_path(@socket, :show, @tag) %>
|
||||
<% end %>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<strong>Name:</strong>
|
||||
<%= @tag.name %>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<strong>Bg-color:</strong>
|
||||
<%= @tag.bg_color %>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<strong>Text-color:</strong>
|
||||
<%= @tag.text_color %>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<span><%= live_patch "Edit", to: Routes.tag_show_path(@socket, :edit, @tag), class: "button" %></span>
|
||||
<span><%= live_redirect "Back", to: Routes.tag_index_path(@socket, :index) %></span>
|
@ -60,6 +60,34 @@ defmodule CanneryWeb.Router do
|
||||
get "/users/settings", UserSettingsController, :edit
|
||||
put "/users/settings", UserSettingsController, :update
|
||||
get "/users/settings/confirm_email/:token", UserSettingsController, :confirm_email
|
||||
|
||||
live "/tags", TagLive.Index, :index
|
||||
live "/tags/new", TagLive.Index, :new
|
||||
live "/tags/:id/edit", TagLive.Index, :edit
|
||||
|
||||
live "/tags/:id", TagLive.Show, :show
|
||||
live "/tags/:id/show/edit", TagLive.Show, :edit
|
||||
|
||||
live "/ammo_types", AmmoTypeLive.Index, :index
|
||||
live "/ammo_types/new", AmmoTypeLive.Index, :new
|
||||
live "/ammo_types/:id/edit", AmmoTypeLive.Index, :edit
|
||||
|
||||
live "/ammo_types/:id", AmmoTypeLive.Show, :show
|
||||
live "/ammo_types/:id/show/edit", AmmoTypeLive.Show, :edit
|
||||
|
||||
live "/containers", ContainerLive.Index, :index
|
||||
live "/containers/new", ContainerLive.Index, :new
|
||||
live "/containers/:id/edit", ContainerLive.Index, :edit
|
||||
|
||||
live "/containers/:id", ContainerLive.Show, :show
|
||||
live "/containers/:id/show/edit", ContainerLive.Show, :edit
|
||||
|
||||
live "/ammo_groups", AmmoGroupLive.Index, :index
|
||||
live "/ammo_groups/new", AmmoGroupLive.Index, :new
|
||||
live "/ammo_groups/:id/edit", AmmoGroupLive.Index, :edit
|
||||
|
||||
live "/ammo_groups/:id", AmmoGroupLive.Show, :show
|
||||
live "/ammo_groups/:id/show/edit", AmmoGroupLive.Show, :edit
|
||||
end
|
||||
|
||||
scope "/", CanneryWeb do
|
||||
|
@ -1,5 +1,5 @@
|
||||
<main role="main" class="container min-w-full min-h-full">
|
||||
<%= live_component CanneryWeb.Live.Component.Topbar %>
|
||||
<%= live_component CanneryWeb.Live.Component.Topbar, current_user: assigns[:current_user] %>
|
||||
|
||||
<%= @inner_content %>
|
||||
</main>
|
||||
|
Reference in New Issue
Block a user