From ad12ae2ec7e01ecd2a84b698393b73917e859d21 Mon Sep 17 00:00:00 2001
From: Schuwi
Date: Sun, 14 Sep 2025 15:32:16 +0200
Subject: [PATCH] feat(elixir): complete storage location integration
---
README.md | 4 +--
lib/components_elixir/inventory.ex | 8 +++++
lib/components_elixir/inventory/component.ex | 1 +
.../live/components_live.ex | 29 +++++++++++++++----
4 files changed, 34 insertions(+), 8 deletions(-)
diff --git a/README.md b/README.md
index 6caffc1..1710b0a 100644
--- a/README.md
+++ b/README.md
@@ -140,13 +140,13 @@ The application uses a simple password-based authentication system:
## ✅ Recently Implemented Features
-### Storage Location System Foundation 🚧 **PARTIALLY IMPLEMENTED**
+### Storage Location System Foundation ✅ **COMPLETED**
- **Database Schema** ✅ Complete - Hierarchical storage locations with parent-child relationships
- **Storage Location CRUD** ✅ Complete - Full create, read, update, delete operations via web interface
- **QR Code Data Generation** ✅ Complete - Text-based QR codes with format `SL:{level}:{code}:{parent}`
- **Hierarchical Organization** ✅ Complete - Unlimited nesting (shelf → drawer → box)
- **Web Interface** ✅ Complete - Storage locations management page with navigation
-- **Component-Storage Integration** ❌ Missing - Linking components to storage locations not yet implemented correctly
+- **Component-Storage Integration** ✅ Complete - Components can now be assigned to storage locations via dropdown interface
### QR Code System - Still Needed 🚧 **NOT IMPLEMENTED**
- **Visual QR Code Generation** ❌ Missing - No actual QR code images are generated
diff --git a/lib/components_elixir/inventory.ex b/lib/components_elixir/inventory.ex
index e389e1b..0109d9b 100644
--- a/lib/components_elixir/inventory.ex
+++ b/lib/components_elixir/inventory.ex
@@ -170,6 +170,14 @@ defmodule ComponentsElixir.Inventory do
end
end
+ @doc """
+ Computes the path for a storage location (for display purposes).
+ """
+ def compute_storage_location_path(nil), do: nil
+ def compute_storage_location_path(%StorageLocation{} = location) do
+ compute_path_for_single(location)
+ end
+
# Convert string keys to atoms for consistency
defp normalize_string_keys(attrs) when is_map(attrs) do
Enum.reduce(attrs, %{}, fn
diff --git a/lib/components_elixir/inventory/component.ex b/lib/components_elixir/inventory/component.ex
index 52dd70e..c6e71c8 100644
--- a/lib/components_elixir/inventory/component.ex
+++ b/lib/components_elixir/inventory/component.ex
@@ -38,6 +38,7 @@ defmodule ComponentsElixir.Inventory.Component do
|> validate_number(:count, greater_than_or_equal_to: 0)
|> validate_url(:datasheet_url)
|> foreign_key_constraint(:category_id)
+ |> foreign_key_constraint(:storage_location_id)
end
@doc """
diff --git a/lib/components_elixir_web/live/components_live.ex b/lib/components_elixir_web/live/components_live.ex
index 3fb33fd..5f16396 100644
--- a/lib/components_elixir_web/live/components_live.ex
+++ b/lib/components_elixir_web/live/components_live.ex
@@ -13,12 +13,14 @@ defmodule ComponentsElixirWeb.ComponentsLive do
{:ok, socket |> push_navigate(to: ~p"/login")}
else
categories = Inventory.list_categories()
+ storage_locations = Inventory.list_storage_locations()
stats = Inventory.component_stats()
{:ok,
socket
|> assign(:session, session)
|> assign(:categories, categories)
+ |> assign(:storage_locations, storage_locations)
|> assign(:stats, stats)
|> assign(:search, "")
|> assign(:sort_criteria, "all_not_id")
@@ -293,6 +295,13 @@ defmodule ComponentsElixirWeb.ComponentsLive do
end)
end
+ defp storage_location_options(storage_locations) do
+ [{"No storage location", nil}] ++
+ Enum.map(storage_locations, fn location ->
+ {location.path, location.id}
+ end)
+ end
+
@impl true
def render(assigns) do
~H"""
@@ -439,8 +448,12 @@ defmodule ComponentsElixirWeb.ComponentsLive do
<.input field={@form[:keywords]} type="text" />
-
- <.input field={@form[:position]} type="text" />
+
+ <.input
+ field={@form[:storage_location_id]}
+ type="select"
+ options={storage_location_options(@storage_locations)}
+ />
@@ -552,8 +565,12 @@ defmodule ComponentsElixirWeb.ComponentsLive do
<.input field={@form[:keywords]} type="text" />
-
- <.input field={@form[:position]} type="text" />
+
+ <.input
+ field={@form[:storage_location_id]}
+ type="select"
+ options={storage_location_options(@storage_locations)}
+ />
@@ -684,9 +701,9 @@ defmodule ComponentsElixirWeb.ComponentsLive do
- <%= if component.position do %>
+ <%= if component.storage_location do %>
- Position: {component.position}
+ Location: {Inventory.compute_storage_location_path(component.storage_location)}
<% end %>