refactoring folders
Some checks failed
CI/CD Pipeline / build (push) Failing after 8s

This commit is contained in:
2026-03-25 12:05:56 -06:00
parent d857e91241
commit 0041c25f19
32 changed files with 139 additions and 78 deletions

View File

@@ -0,0 +1,56 @@
defmodule ElixirAiWeb.FormComponents do
use Phoenix.Component
@doc """
Renders a styled input field with label.
## Examples
<.input type="text" name="email" value={@email} label="Email" />
<.input type="password" name="password" label="Password" />
"""
attr :type, :string, default: "text"
attr :name, :string, required: true
attr :value, :string, default: ""
attr :label, :string, required: true
attr :autocomplete, :string, default: "off"
attr :rest, :global
def input(assigns) do
~H"""
<div>
<label for={@name} class="block text-sm text-seafoam-300 mb-1">{@label}</label>
<input
type={@type}
name={@name}
id={@name}
value={@value}
autocomplete={@autocomplete}
class="w-full rounded px-3 py-2 text-sm bg-seafoam-950/20 border border-seafoam-900/40 text-seafoam-100 focus:outline-none focus:ring-1 focus:ring-seafoam-700"
{@rest}
/>
</div>
"""
end
@doc """
Renders a centered overlay modal. Pass content via the `:inner_block` slot.
## Examples
<.modal>
<p>Are you sure?</p>
</.modal>
"""
slot :inner_block, required: true
def modal(assigns) do
~H"""
<div class="fixed inset-0 z-50 flex items-center justify-center bg-black/60">
<div class="w-full max-w-sm rounded-lg border border-seafoam-900/40 bg-seafoam-950 p-6 shadow-xl">
{render_slot(@inner_block)}
</div>
</div>
"""
end
end

View File

@@ -0,0 +1,14 @@
defmodule ElixirAiWeb.Layouts do
@moduledoc """
This module holds different layouts used by your application.
See the `layouts` directory for all templates available.
The "root" layout is a skeleton rendered as part of the
application router. The "app" layout is set as the default
layout on both `use ElixirAiWeb, :controller` and
`use ElixirAiWeb, :live_view`.
"""
use ElixirAiWeb, :html
embed_templates "layouts/*"
end

View File

@@ -0,0 +1,3 @@
<main class="px-4 py-8 sm:px-6 lg:px-8 h-screen w-screen">
{@inner_content}
</main>

View File

@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en" class="[scrollbar-gutter:stable]">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="csrf-token" content={get_csrf_token()} />
<.live_title default="ElixirAi" suffix=" · Phoenix Framework">
{assigns[:page_title]}
</.live_title>
<link phx-track-static rel="stylesheet" href={~p"/assets/app.css"} />
<script defer phx-track-static type="text/javascript" src={~p"/assets/app.js"}>
</script>
<script type="module">
import * as smd from "https://cdn.jsdelivr.net/npm/streaming-markdown/smd.min.js"
import DOMPurify from "https://cdn.jsdelivr.net/npm/dompurify/+esm"
window.smd = smd
window.DOMPurify = DOMPurify
</script>
</head>
<body class="bg-seafoam-900 text-seafoam-50">
{live_render(@conn, ElixirAiWeb.VoiceLive, id: "voice-control")}
{@inner_content}
</body>
</html>

View File

@@ -0,0 +1,16 @@
defmodule ElixirAi.LiveViewPG do
@moduledoc """
Named :pg scope for tracking LiveView processes across the cluster.
Each LiveView joins {:liveview, ViewModule} on connect; :pg syncs membership
automatically and removes dead processes without any additional cleanup.
"""
def child_spec(_opts) do
%{
id: __MODULE__,
start: {:pg, :start_link, [__MODULE__]},
type: :worker,
restart: :permanent
}
end
end

View File

@@ -0,0 +1,15 @@
defmodule ElixirAi.PageToolsPG do
@moduledoc """
Named :pg scope for tracking LiveViews that implement AiControllable.
Group key is `{:page, voice_session_id}` — one group per browser session.
"""
def child_spec(_opts) do
%{
id: __MODULE__,
start: {:pg, :start_link, [__MODULE__]},
type: :worker,
restart: :permanent
}
end
end

View File

@@ -0,0 +1,11 @@
defmodule ElixirAiWeb.Spinner do
use Phoenix.Component
attr :class, :string, default: nil
def spinner(assigns) do
~H"""
<span class={["loader", @class]}></span>
"""
end
end