Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
24c672b
feat: Add migrate for signers
brandaoplaster Oct 14, 2025
5dc0683
feat: Add schema for signers
brandaoplaster Oct 14, 2025
14357eb
feat: Update context contracts with signers functions
brandaoplaster Oct 14, 2025
212695a
test: Add tests for signers
brandaoplaster Oct 14, 2025
22f497f
feat: Update schema with relationship company
brandaoplaster Oct 14, 2025
4da4e86
feat: Add factory signer
brandaoplaster Oct 14, 2025
f5541db
feat: Add factory signer in factory root
brandaoplaster Oct 14, 2025
4ca1913
feat: Update links navbar
brandaoplaster Oct 14, 2025
7584eba
chore: Adjustment signer factory field role
brandaoplaster Oct 14, 2025
b2f6bdf
feat: Add signers listing
brandaoplaster Oct 14, 2025
b4d8eaa
feat: Add SignerDetails component
brandaoplaster Oct 14, 2025
2c88d30
feat: Add signer details page
brandaoplaster Oct 15, 2025
a36e819
chore: Update return mount
brandaoplaster Oct 15, 2025
f6bb8fa
feat: Add form new signer
brandaoplaster Oct 18, 2025
b78be9a
feat: Add routers for signer
brandaoplaster Oct 18, 2025
5aefb4e
feat: Add component form_builder and field_input
brandaoplaster Oct 18, 2025
74b80e1
feat: Add signer modal
brandaoplaster Oct 18, 2025
3d95c64
feat: Add component form_actions and form_header
brandaoplaster Oct 18, 2025
4b6e6fc
feat: Use components form
brandaoplaster Oct 18, 2025
a63373c
chore: Update module name to form_component
brandaoplaster Oct 25, 2025
4c9890c
chore: Remove brachets validate_required
brandaoplaster Oct 25, 2025
0593e2c
feat: Add handle_info to refresh signer table on create, update or de…
brandaoplaster Oct 25, 2025
2340c08
feat: Add handle event for delete signer
brandaoplaster Oct 25, 2025
8037af6
style: Organize code
brandaoplaster Oct 25, 2025
13a7338
chore: Set deafult status to true
brandaoplaster Oct 25, 2025
a82a050
chore: Update function normalize_status_params
brandaoplaster Oct 25, 2025
4bd5083
chore: Remove div
brandaoplaster Oct 25, 2025
d41af96
refactor: Refactor modulo to form componnt and pass current user to l…
brandaoplaster Oct 25, 2025
88efe19
style: Remove unused code
brandaoplaster Oct 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions lib/foedus/contracts.ex
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,100 @@ defmodule Foedus.Contracts do
def change_contract_template(%ContractTemplate{} = contract_template, attrs \\ %{}) do
ContractTemplate.changeset(contract_template, attrs)
end

alias Foedus.Contracts.Signer

@doc """
Returns the list of signers.

## Examples

iex> list_signers()
[%Signer{}, ...]

"""
def list_signers do
Repo.all(Signer)
end

@doc """
Gets a single signer.

Raises `Ecto.NoResultsError` if the Signer does not exist.

## Examples

iex> get_signer!(123)
%Signer{}

iex> get_signer!(456)
** (Ecto.NoResultsError)

"""
def get_signer!(id), do: Repo.get!(Signer, id)

@doc """
Creates a signer.

## Examples

iex> create_signer(%{field: value})
{:ok, %Signer{}}

iex> create_signer(%{field: bad_value})
{:error, %Ecto.Changeset{}}

"""
def create_signer(attrs \\ %{}) do
%Signer{}
|> Signer.changeset(attrs)
|> Repo.insert()
end

@doc """
Updates a signer.

## Examples

iex> update_signer(signer, %{field: new_value})
{:ok, %Signer{}}

iex> update_signer(signer, %{field: bad_value})
{:error, %Ecto.Changeset{}}

"""
def update_signer(%Signer{} = signer, attrs) do
signer
|> Signer.changeset(attrs)
|> Repo.update()
end

@doc """
Deletes a signer.

## Examples

iex> delete_signer(signer)
{:ok, %Signer{}}

iex> delete_signer(signer)
{:error, %Ecto.Changeset{}}

"""
def delete_signer(%Signer{} = signer) do
Repo.delete(signer)
end

@doc """
Returns an `%Ecto.Changeset{}` for tracking signer changes.

## Examples

iex> change_signer(signer)
%Ecto.Changeset{data: %Signer{}}

"""
def change_signer(%Signer{} = signer, attrs \\ %{}) do
Signer.changeset(signer, attrs)
end
end
36 changes: 36 additions & 0 deletions lib/foedus/contracts/signer.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
defmodule Foedus.Contracts.Signer do
use Ecto.Schema
import Ecto.Changeset

alias Foedus.Accounts.Company

@fields_required ~w(name lastname email role company_id)a
@fields_optional ~w(document birthdate status)a

@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "signers" do
field :name, :string
field :status, :boolean, default: true
field :role, :string
field :lastname, :string
field :email, :string
field :document, :string
field :birthdate, :date

belongs_to :company, Company

timestamps(type: :utc_datetime)
end

@doc false
def changeset(signer, attrs) do
signer
|> cast(attrs, @fields_required ++ @fields_optional)
|> validate_required(@fields_required)
|> validate_length(:name, min: 2, max: 100)
|> validate_length(:lastname, min: 2, max: 100)
|> validate_format(:email, ~r/^[^\s]+@[^\s]+\.[^\s]+$/, message: "must be a valid email")
|> foreign_key_constraint(:company_id)
end
end
6 changes: 3 additions & 3 deletions lib/foedus_web/components/layouts.ex
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
<.nav_link navigate={~p"/dashboard"}>Dashboard</.nav_link>
<.nav_link navigate={~p"/contract_templates"}>Contract Templates</.nav_link>
<.nav_link navigate={~p"/contractors"}>Contractors</.nav_link>
<.nav_link href="#">Relatórios</.nav_link>
<.nav_link navigate={~p"/signers"}>Signers</.nav_link>
</nav>
<% end %>
"""
Expand Down Expand Up @@ -108,8 +108,8 @@
<div class="space-y-2">
<.mobile_nav_link navigate={~p"/dashboard"}>Dashboard</.mobile_nav_link>
<.mobile_nav_link navigate={~p"/contract_templates"}>Templates</.mobile_nav_link>
<.mobile_nav_link href="#">Contratos</.mobile_nav_link>
<.mobile_nav_link href="#">Relatórios</.mobile_nav_link>
<.mobile_nav_link navigate={~p"/contractors"}>Contractors</.mobile_nav_link>
<.mobile_nav_link navigate={~p"/signers"}>Signers</.mobile_nav_link>

<hr class="my-2 border-gray-200" />

Expand Down Expand Up @@ -202,7 +202,7 @@
Entrar
</.link>
<.link
href={~p"/users/register"}

Check warning on line 205 in lib/foedus_web/components/layouts.ex

View workflow job for this annotation

GitHub Actions / Run Credo

no route path for FoedusWeb.Router matches "/users/register"
class="bg-indigo-600 text-white px-4 py-2 rounded-md text-sm font-medium hover:bg-indigo-700 transition-colors"
>
Cadastrar
Expand Down
105 changes: 105 additions & 0 deletions lib/foedus_web/components/ui/field_input.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
defmodule FoedusWeb.Components.UI.FieldInput do
use Phoenix.Component

attr :field, :any, required: true
attr :type, :string, default: "text"
attr :label, :string, required: true
attr :placeholder, :string, default: nil
attr :required, :boolean, default: false
attr :options, :list, default: []
attr :prompt, :string, default: nil
attr :class, :string, default: ""

def field_input(%{type: "select"} = assigns) do
~H"""
<div class={@class}>
<label for={@field.id} class="block text-sm font-medium text-gray-700 mb-1">
{@label}<span :if={@required} class="text-red-500">*</span>
</label>
<select
id={@field.id}
name={@field.name}
required={@required}
class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
>
<option :if={@prompt} value="">{@prompt}</option>
<option
:for={{label, value} <- @options}
value={value}
selected={value == @field.value}
>
{label}
</option>
</select>
<p :if={@field.errors != []} class="mt-1 text-sm text-red-600">
{translate_errors(@field.errors)}
</p>
</div>
"""
end

def field_input(%{type: "checkbox"} = assigns) do
~H"""
<div class={["flex items-center", @class]}>
<input
type="checkbox"
id={@field.id}
name={@field.name}
value="true"
checked={@field.value == true}
class="h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
/>
<label for={@field.id} class="ml-2 block text-sm text-gray-700">
{@label}
</label>
</div>
"""
end

def field_input(%{type: "textarea"} = assigns) do
~H"""
<div class={@class}>
<label for={@field.id} class="block text-sm font-medium text-gray-700 mb-1">
{@label}<span :if={@required} class="text-red-500">*</span>
</label>
<textarea
id={@field.id}
name={@field.name}
placeholder={@placeholder}
required={@required}
rows="4"
class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
><%= @field.value %></textarea>
<p :if={@field.errors != []} class="mt-1 text-sm text-red-600">
{translate_errors(@field.errors)}
</p>
</div>
"""
end

def field_input(assigns) do
~H"""
<div class={@class}>
<label for={@field.id} class="block text-sm font-medium text-gray-700 mb-1">
{@label}<span :if={@required} class="text-red-500">*</span>
</label>
<input
type={@type}
id={@field.id}
name={@field.name}
value={@field.value}
placeholder={@placeholder}
required={@required}
class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
/>
<p :if={@field.errors != []} class="mt-1 text-sm text-red-600">
{translate_errors(@field.errors)}
</p>
</div>
"""
end

defp translate_errors(errors) when is_list(errors) do
Enum.map_join(errors, ", ", fn {msg, _opts} -> msg end)
end
end
50 changes: 50 additions & 0 deletions lib/foedus_web/components/ui/form_actions.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
defmodule FoedusWeb.Components.UI.FormActions do
use Phoenix.Component

import FoedusWeb.Components.UI.Button

@doc """
Renders form action buttons (Cancel and Submit).

## Examples

<.form_actions
on_cancel={JS.patch(~p"/signers")}
submit_text="Create Signer"
/>
"""
attr :on_cancel, Phoenix.LiveView.JS, required: true
attr :submit_text, :string, required: true
attr :show_icon, :boolean, default: true

def form_actions(assigns) do
~H"""
<div class="flex items-center justify-end gap-3 pt-6 border-t border-gray-100">
<.button
variant="secondary"
size="lg"
type="button"
phx-click={@on_cancel}
>
Cancel
</.button>

<.button
variant="cta_primary"
size="lg"
type="submit"
>
<svg :if={@show_icon} class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M5 13l4 4L19 7"
/>
</svg>
{@submit_text}
</.button>
</div>
"""
end
end
24 changes: 24 additions & 0 deletions lib/foedus_web/components/ui/form_builder.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
defmodule FoedusWeb.Components.UI.FormBuilder do
use Phoenix.Component

attr :for, :any, required: true
attr :id, :string, required: true
attr :action, :string, default: nil
attr :class, :string, default: ""
attr :rest, :global, include: ~w(phx-change phx-submit phx-target)
slot :inner_block, required: true

def form_builder(assigns) do
~H"""
<.form
for={@for}
id={@id}
action={@action}
class={["space-y-8", @class]}
{@rest}
>
{render_slot(@inner_block)}
</.form>
"""
end
end
Loading
Loading