Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
160 changes: 158 additions & 2 deletions lib/ares_web/live/app/profile.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
defmodule AresWeb.AppLive.Profile do
use AresWeb, :live_view

alias Ares.Accounts
alias Ares.Accounts.User
alias Ares.Teams
alias AresWeb.Components.CVUploader

@impl true
def render(assigns) do
Expand Down Expand Up @@ -35,7 +38,7 @@ defmodule AresWeb.AppLive.Profile do
<% end %>

<%= if @user.team do %>
<div class="bg-gray rounded-lg p-8 border border-gray-800 font-inter">
<div class="bg-gray rounded-lg p-8 border border-gray-800 font-inter mb-8">
<h2 class="text-3xl font-vt323 uppercase">Member of</h2>

<div class="mb-6 pb-6 border-b border-gray-800">
Expand Down Expand Up @@ -120,6 +123,51 @@ defmodule AresWeb.AppLive.Profile do
</div>
</div>
<% end %>

<div class="bg-gray rounded-lg p-8 border border-gray-800 font-inter">
<h2 class="text-3xl font-vt323 uppercase">Upload your CV</h2>
<%= if @user.cv do %>
<div class="flex items-center gap-4 mt-2">
<p class="text-sm text-gray-400">Current: {@user.cv.file_name}</p>
<button
type="button"
class="text-sm text-primary underline cursor-pointer"
phx-click="remove-cv"
onclick="return confirm('Remove current CV?');"
>
Remove
</button>
</div>
<% end %>

<.form
for={@form}
id="profile_info_form"
phx-submit="save"
phx-change="validate"
class="font-inter mt-8"
>
<.live_component
module={CVUploader}
id="cv-uploader"
uploaders={@uploads}
/>

<.button
phx-disable-with="Saving..."
class="btn btn-primary w-full mt-6"
disabled={@cv_uploading || @cv_upload_error}
>
Save
</.button>

<%= if @cv_upload_error do %>
<p class="text-sm text-primary mt-2">
There was a problem with the uploaded CV. Please remove and re-upload or try a different file.
</p>
<% end %>
</.form>
</div>
</div>
</Layouts.app>
"""
Expand All @@ -135,6 +183,114 @@ defmodule AresWeb.AppLive.Profile do
nil
end

{:ok, assign(socket, user: Map.put(user, :team, team))}
changeset = Accounts.change_user(%User{}, %{}, validate_unique: false)

{:ok,
socket
|> assign(user: Map.put(user, :team, team))
|> assign_form(changeset)
|> assign(:cv_uploading, false)
|> assign(:cv_upload_error, nil)
|> allow_upload(:cv,
accept: ~w(.pdf .doc .docx .txt .md .rtf),
max_entries: 1,
max_file_size: 5_000_000,
auto_upload: true,
progress: &handle_progress/3
)}
end

def handle_event("remove-cv", _params, socket) do
user = socket.assigns.user

case Accounts.update_user_cv(user, %{"cv" => nil}) do
{:ok, %Accounts.User{} = updated_user} ->
{:noreply,
socket
|> assign(user: updated_user)
|> put_flash(:info, "CV removed.")}

{:error, _reason} ->
{:noreply, put_flash(socket, :error, "Could not remove CV.")}
end
end

@impl true
def handle_event("cancel-upload", %{"ref" => ref} = _params, socket) do
{:noreply, socket |> cancel_upload(:cv, ref) |> assign(:cv_upload_error, nil)}
end

@impl true
def handle_event("validate", %{"_target" => _} = _params, socket) do
upload_errors = upload_errors(socket.assigns.uploads.cv) || []
{:noreply, socket |> assign(:cv_upload_error, upload_errors)}
end

def handle_event("save", _params, socket) do
user = socket.assigns.user

if socket.assigns.cv_uploading do
{:noreply, socket |> put_flash(:error, "CV upload still in progress. Please wait.")}
else
case consume_pdf_data(socket, {:ok, user}) do
{:ok, %Accounts.User{} = updated_user} ->
{:noreply,
socket
|> assign(user: updated_user)
|> put_flash(:info, "CV uploaded successfully.")}

{:ok, _} ->
{:noreply, put_flash(socket, :info, "Nothing to upload.")}

{:error, reason} ->
{:noreply, put_flash(socket, :error, "CV upload failed: #{inspect(reason)}")}
end
end
end

defp consume_pdf_data(socket, {:ok, user}) do
result =
consume_uploaded_entries(socket, :cv, fn %{path: path}, entry ->
Accounts.update_user_cv(user, %{
"cv" => %Plug.Upload{
content_type: entry.client_type,
filename: entry.client_name,
path: path
}
})
end)

case result do
[] ->
{:ok, user}

[error: reason] ->
{:error, reason}

[updated_user] ->
{:ok, updated_user}

_ ->
{:ok, socket}
end
end

defp consume_pdf_data(_socket, result) do
result
end

def handle_progress(:cv, entry, socket) do
uploading = entry.progress < 100
errors = upload_errors(socket.assigns.uploads.cv) || []

{:noreply,
socket
|> assign(:cv_uploading, uploading)
|> assign(:cv_upload_error, if(errors == [], do: nil, else: errors))}
end

defp assign_form(socket, %Ecto.Changeset{} = changeset) do
form = to_form(changeset, as: "user")
assign(socket, form: form)
end
end
2 changes: 1 addition & 1 deletion mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"gen_smtp": {:hex, :gen_smtp, "1.3.0", "62c3d91f0dcf6ce9db71bcb6881d7ad0d1d834c7f38c13fa8e952f4104a8442e", [:rebar3], [{:ranch, ">= 1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "0b73fbf069864ecbce02fe653b16d3f35fd889d0fdd4e14527675565c39d84e6"},
"gettext": {:hex, :gettext, "0.26.2", "5978aa7b21fada6deabf1f6341ddba50bc69c999e812211903b169799208f2a8", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "aa978504bcf76511efdc22d580ba08e2279caab1066b76bb9aa81c4a1e0a32a5"},
"hackney": {:hex, :hackney, "1.25.0", "390e9b83f31e5b325b9f43b76e1a785cbdb69b5b6cd4e079aa67835ded046867", [:rebar3], [{:certifi, "~> 2.15.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.4", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "7209bfd75fd1f42467211ff8f59ea74d6f2a9e81cbcee95a56711ee79fd6b1d4"},
"heroicons": {:git, "https://github.com/tailwindlabs/heroicons.git", "0435d4ca364a608cc75e2f8683d374e55abbae26", [tag: "v2.2.0", sparse: "optimized"]},
"heroicons": {:git, "https://github.com/tailwindlabs/heroicons.git", "0435d4ca364a608cc75e2f8683d374e55abbae26", [tag: "v2.2.0", sparse: "optimized", depth: 1]},
"hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"},
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
Expand Down