refactor(elixir): hierarchical refactor

to extract common code patterns from
category/storage location systems
This commit is contained in:
Schuwi
2025-09-17 23:56:56 +02:00
parent 963c9a3770
commit 264adbfb98
12 changed files with 415 additions and 1173 deletions

View File

@@ -2,7 +2,7 @@ defmodule ComponentsElixirWeb.ComponentsLive do
use ComponentsElixirWeb, :live_view
alias ComponentsElixir.{Inventory, Auth}
alias ComponentsElixir.Inventory.Component
alias ComponentsElixir.Inventory.{Component, Category, StorageLocation, Hierarchical}
@items_per_page 20
@@ -430,31 +430,15 @@ defmodule ComponentsElixirWeb.ComponentsLive do
end
defp category_options(categories) do
[{"Select a category", nil}] ++
Enum.map(categories, fn category ->
{category.name, category.id}
end)
Hierarchical.select_options(categories, &(&1.parent), "Select a category")
end
defp storage_location_display_name(location) do
# Use the computed path from Inventory context for full hierarchy, or fall back to location.path
path = Inventory.compute_storage_location_path(location) || location.path
if path do
# Convert path from "Shelf A/Drawer 2/Box 1" to "Shelf A > Drawer 2 > Box 1"
path
|> String.split("/")
|> Enum.join(" > ")
else
location.name
end
StorageLocation.full_path(location)
end
defp storage_location_options(storage_locations) do
[{"No storage location", nil}] ++
Enum.map(storage_locations, fn location ->
{storage_location_display_name(location), location.id}
end)
Hierarchical.select_options(storage_locations, &(&1.parent), "No storage location")
end
@impl true
@@ -503,7 +487,7 @@ defmodule ComponentsElixirWeb.ComponentsLive do
</div>
</div>
</div>
<!-- Filters -->
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
<div class="flex flex-col sm:flex-row gap-4">
@@ -525,13 +509,9 @@ defmodule ComponentsElixirWeb.ComponentsLive do
class="block w-full px-3 py-2 border border-base-300 rounded-md shadow-sm bg-base-100 text-base-content focus:outline-none focus:ring-primary focus:border-primary sm:text-sm"
>
<option value="" selected={is_nil(@selected_category)}>All Categories</option>
<%= for category <- @categories do %>
<option value={category.id} selected={@selected_category == category.id}>
<%= if category.parent do %>
{category.parent.name} > {category.name}
<% else %>
{category.name}
<% end %>
<%= for {category_name, category_id} <- Hierarchical.select_options(@categories, &(&1.parent)) do %>
<option value={category_id} selected={@selected_category == category_id}>
{category_name}
</option>
<% end %>
</select>
@@ -580,7 +560,7 @@ defmodule ComponentsElixirWeb.ComponentsLive do
</div>
</div>
</div>
<!-- Add Component Modal -->
<%= if @show_add_form do %>
<div class="fixed inset-0 bg-base-content/50 overflow-y-auto h-full w-full z-50">
@@ -714,7 +694,7 @@ defmodule ComponentsElixirWeb.ComponentsLive do
</div>
</div>
<% end %>
<!-- Edit Component Modal -->
<%= if @show_edit_form do %>
<div class="fixed inset-0 bg-base-content/50 overflow-y-auto h-full w-full z-50">
@@ -858,7 +838,7 @@ defmodule ComponentsElixirWeb.ComponentsLive do
</div>
</div>
<% end %>
<!-- Components List -->
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pb-6">
<div class="bg-base-100 shadow overflow-hidden sm:rounded-md">
@@ -918,7 +898,7 @@ defmodule ComponentsElixirWeb.ComponentsLive do
</button>
</div>
</div>
<!-- Content area with image and details -->
<div class="flex gap-6">
<!-- Large Image -->
@@ -944,7 +924,7 @@ defmodule ComponentsElixirWeb.ComponentsLive do
</div>
<% end %>
</div>
<!-- Details -->
<div class="flex-1 space-y-4 select-text">
<!-- Full Description -->
@@ -956,7 +936,7 @@ defmodule ComponentsElixirWeb.ComponentsLive do
</p>
</div>
<% end %>
<!-- Metadata Grid -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 text-sm">
<%= if component.storage_location do %>
@@ -1013,7 +993,7 @@ defmodule ComponentsElixirWeb.ComponentsLive do
</div>
</div>
</div>
<!-- Action Buttons -->
<div class="flex justify-end items-center space-x-2 pt-4 border-t border-base-300">
<button
@@ -1098,7 +1078,7 @@ defmodule ComponentsElixirWeb.ComponentsLive do
</span>
</div>
</div>
<!-- Middle row: Description -->
<%= if component.description do %>
<div class="mt-1">
@@ -1107,7 +1087,7 @@ defmodule ComponentsElixirWeb.ComponentsLive do
</p>
</div>
<% end %>
<!-- Bottom row: Metadata -->
<div class="mt-2 grid grid-cols-1 sm:grid-cols-3 gap-x-4 gap-y-1 text-sm text-base-content/60">
<%= if component.storage_location do %>
@@ -1135,7 +1115,7 @@ defmodule ComponentsElixirWeb.ComponentsLive do
</div>
<% end %>
</div>
<!-- Keywords row -->
<%= if component.keywords do %>
<div class="mt-2">
@@ -1218,7 +1198,7 @@ defmodule ComponentsElixirWeb.ComponentsLive do
>
<!-- Background overlay -->
<div class="absolute inset-0 bg-black bg-opacity-75"></div>
<!-- Modal content -->
<div
class="relative bg-base-100 rounded-lg shadow-xl max-w-4xl w-full max-h-full overflow-auto"
@@ -1236,7 +1216,7 @@ defmodule ComponentsElixirWeb.ComponentsLive do
×
</button>
</div>
<!-- Content -->
<div class="p-6 bg-base-100 rounded-b-lg">
<div class="text-center">