Create new project–>when user select a company and select it’s contact , after that if user change the company, it should shows blank contact filed for change company, and should not save the previous contact of company
I want to remove the selection from contacts and buildings when selecting other company contact. What will be the solution?
form_component.html.heex
<div class="contacts_newcom_m">
<h1><%= page_title(@action) %></h1>
<div class="a_asside_account_c_first_ss mt-20">
<.form let={f} for={@changeset} phx-target={@myself} phx-change="validate" phx-submit="save" phx-update="replace">
<span>
<%= if entry = List.first(@uploads.image.entries) do%>
<%= live_img_preview entry %>
<% else %>
<%= if @project.project_image do%>
<img src={@project.project_image}/>
<% else %>
<img src={Routes.static_path(@socket, System.get_env("DEFAULT_AVATAR"))} alt="img"/>
<% end %>
<% end %>
<span class="account_add_img" phx-drop-target={@uploads.image.ref} onclick={"document.getElementById('#{@uploads.image.ref}').click()"}>
<img src={Routes.static_path(@socket, "/images/Frame 811261 (1).svg")} alt=""/>
<%= gettext("add image") %>
<%= live_file_input @uploads.image, hidden: true %>
<%= if entry = List.first(@uploads.image.entries) do%>
<%= for err <- upload_errors(@uploads.image, entry) do %>
<span><%= image_errors(err) %></span>
<% end %>
<% end %>
</span>
</span>
<div class="form-control">
<p><%= gettext("name") %></p>
<%= text_input f, :name %>
<%= error_tag f, :name %>
</div>
<div class="form-control ">
<p><%= gettext("description") %></p>
<%= text_input f, :description %>
<%= error_tag f, :description %>
</div>
<div class="form-control ">
<p><%= gettext("Estimated Time") %></p>
<%= text_input f, :estimated_time, type: "number", min: 0, oninput: "this.value = Math.abs(this.value)" %>
<%= error_tag f, :estimated_time %>
</div>
<div class="form-control ">
<p><%= gettext("Project Start Date") %></p>
<%= datetime_local_input f, :project_start_date %>
<%= error_tag f, :project_start_date %>
</div>
<div class="form-control ">
<p><%= gettext("Company Contact") %></p>
<%= select f, :company_contact_id, @company_contacts_options, options(:company_contact, assigns[:parent]) %>
<%= error_tag f, :company_contact_id %>
</div>
<%= inputs_for f, :project_contacts, fn a -> %>
<%= hidden_input a, :contact_id %>
<%= hidden_input a, :company_id %>
<% end %>
<%= inputs_for f, :project_buildings, fn a -> %>
<%= hidden_input a, :building_id %>
<%= hidden_input a, :company_id %>
<% end %>
<%= hidden_input f, :stage, value: "pending" %>
<%= error_tag f, :stage %>
<%= hidden_input f, :lead_column_id %>
<%= error_tag f, :lead_column_id %>
<%= hidden_input f, :company_id, value: @current_user.company_id %>
<%= error_tag f, :company_id %>
<div class="form-control ">
<p><%= gettext("Contacts") %></p>
<%= live_component AppeoWeb.TagDropdown,
id: :project_contacts,
ex_tags: @ex_contact_taggings,
module: %{name: __MODULE__, id: @id, field: :contact_id},
tags: @contact_options,
disabled: options(:contact, assigns[:parent])
%>
<%= error_tag f, :project_contacts %>
</div>
<div class="form-control">
<p><%= gettext("Buildings") %></p>
<%= live_component AppeoWeb.TagDropdown,
id: :project_buildings,
ex_tags: @ex_building_taggings,
module: %{name: __MODULE__, id: @id, field: :building_id},
tags: @building_options
%>
<%= error_tag f, :project_buildings %>
</div>
<div class="form-control ">
<p><%= gettext("Project Type") %></p>
<%= select f, :project_type, ["Roofing": "roofing", "Any Name": "any name"] %>
<%= error_tag f, :project_type %>
</div>
<div class="form-control ">
<button class="btn" type="submit"><%= gettext("save") %></button>
<div class="btn"><%= live_patch gettext("Cancel"), to: @return_to %></div>
</div>
</.form>
</div>
</div>
defmodule AppeoWeb.LeadsLive.FormComponent do
use AppeoWeb, :live_component
alias Appeo.Leads
alias Appeo.Leads.Project
alias Appeo.Contacts
alias Ecto.Changeset
alias Appeo.ProjectPermissions
@bucket_dir_name "projects"
@impl true
def update(%{current_user: _, project: project} = assigns, socket) do
params = default_params(project.id, assigns)
changeset = Leads.change_project(project, params)
company_contacts = Contacts.list_company_contacts_for_project()
company_contacts_options = Enum.map(company_contacts, &{&1.name, &1.id})
company_contact_id =
project.company_contact_id ||
company_contacts
|> Enum.at(0, %{})
|> Map.get(:id, "")
company_contact_id = to_string(company_contact_id)
building_options = building_options(company_contact_id, company_contacts)
contact_options = contacts_options(company_contact_id, company_contacts)
{ex_contact_taggings, ex_building_taggings} =
if project.id do
building_tags = Map.new(building_options, &{&1.id, &1})
contact_tags = Map.new(contact_options, &{&1.id, &1})
{
Enum.map(project.project_contacts, &Map.get(contact_tags, &1.contact_id)),
Enum.map(project.project_buildings, &Map.get(building_tags, &1.building_id))
}
else
{[], []}
end
socket =
socket
|> assign(assigns)
|> assign(:changeset, changeset)
|> assign(:project, project)
|> assign(:contact_options, contact_options)
|> assign(:building_options, building_options)
|> assign(:company_contacts_options, company_contacts_options)
|> assign(:company_contacts, company_contacts)
|> assign(:uploaded_files, [])
|> assign(:ex_contact_taggings, ex_contact_taggings)
|> assign(:ex_building_taggings, ex_building_taggings)
|> allow_upload(:image,
accept: ~w(.jpg .jpeg .png),
max_entries: 1,
max_file_size: 3_145_726
)
{:ok, socket}
end
def update(assigns, socket) do
socket =
case assigns do
%{field: :contact_id, taggings: taggings} ->
changeset = build_changeset(:contact_id, taggings, socket.assigns)
assign(socket, changeset: changeset, ex_contact_taggings: taggings)
%{field: :building_id, taggings: taggings} ->
changeset = build_changeset(:building_id, taggings, socket.assigns)
assign(socket, changeset: changeset, ex_building_taggings: taggings)
end
{:ok, socket}
end
@impl true
def handle_event("validate", %{"project" => project}, socket) do
changeset =
socket.assigns.project
|> Leads.change_project(project)
|> Map.put(:action, :validate)
company_contacts = socket.assigns.company_contacts
contacts_options = contacts_options(project["company_contact_id"] || "", company_contacts)
building_options = building_options(project["company_contact_id"] || "", company_contacts)
socket =
socket
|> assign(:contact_options, contacts_options)
|> assign(:building_options, building_options)
{:noreply, assign(socket, :changeset, changeset)}
end
def handle_event("save", %{"project" => project_params}, socket) do
socket
|> upload_image(@bucket_dir_name)
|> save_project(socket, socket.assigns.action, project_params)
end
def handle_event("project_contact", %{"index" => index}, socket) do
changeset = socket.assigns.changeset
project_contacts = remove_field(changeset.changes.project_contacts, index)
changeset = put_in(changeset.changes.project_contacts, project_contacts)
{:noreply, assign(socket, :changeset, changeset)}
end
def build_changeset(:contact_id, taggings, assigns) do
company_id = assigns.current_user.company_id
project_contacts = Enum.map(taggings, &%{company_id: company_id, contact_id: &1.id})
assigns.changeset
|> Changeset.put_assoc(:project_contacts, project_contacts)
|> Changeset.apply_changes()
|> Project.changeset()
|> Map.put(:action, :validate)
end
def build_changeset(:building_id, taggings, assigns) do
company_id = assigns.current_user.company_id
project_buildings = Enum.map(taggings, &%{company_id: company_id, building_id: &1.id})
assigns.changeset
|> Changeset.put_assoc(:project_buildings, project_buildings)
|> Changeset.apply_changes()
|> Project.changeset()
|> Map.put(:action, :validate)
end
defp save_project({:error, error}, socket, _, _) do
{:noreply, put_flash(socket, :error, error)}
end
defp save_project({:ok, path}, socket, :edit_project, project_params) do
path = path || socket.assigns.project.project_image
project_params = Map.put(project_params, "project_image", path)
case Leads.update_project(socket.assigns.project, project_params) do
{:ok, _contact} ->
{:noreply,
socket
|> put_flash(:info, gettext("Project updated successfully"))
|> push_patch(to: socket.assigns.return_to)}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, :changeset, changeset)}
end
end
defp save_project({:ok, path}, socket, :new_project, project_params) do
project_params =
project_params
|> Map.put("project_image", path)
|> Map.put(
"project_permission_joined_users",
[
%{
"company_id" => socket.assigns.current_user.company_id,
"user_id" => socket.assigns.current_user.id,
"project_permission_id" => ProjectPermissions.get_permission_with_name("Owner").id
}
]
)
case Leads.create_project(project_params) do
{:ok, _project} ->
{:noreply,
socket
|> put_flash(:info, gettext("Project created successfully"))
|> push_redirect(to: socket.assigns.return_to)}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, changeset: changeset)}
end
end
defp default_params(nil, %{current_user: current_user} = assigns) do
%{
lead_column_id: assigns.lead_column_id,
company_id: current_user.company_id
}
end
defp default_params(_, _assigns), do: %{}
defp contacts_options("", _assigns), do: []
defp contacts_options(company_contact_id, company_contacts) do
company_contacts
|> Enum.find(&(to_string(&1.id) == company_contact_id))
|> Map.get(:contacts)
|> Enum.map(&%{name: &1.first_name, id: &1.id})
end
defp building_options("", _assigns), do: []
defp building_options(company_contact_id, company_contacts) do
company_contacts
|> Enum.find(&(to_string(&1.id) == company_contact_id))
|> Map.get(:buildings)
|> Enum.map(&%{name: &1.building_name, id: &1.id})
end
defp remove_field(changeset_list, index) do
changeset_list
|> Enum.with_index()
|> Enum.reduce([], fn {value, i}, acc -> if "#{i}" == index, do: acc, else: acc ++ [value] end)
end
defp page_title(:new_project), do: gettext("Create New Project")
defp page_title(:edit_project), do: gettext("Update Project")
defp options(:company_contact, [:contact, contact]),
do: buid_options(contact.company_contact_id)
defp options(:company_contact, [:company_contact, %{id: id}]), do: buid_options(id)
defp options(:contact, [:contact, _]), do: true
defp options(:contact, _), do: false
defp options(_, _), do: []
defp buid_options(id), do: [disabled: true, selected: id]
end