Skip to content

Commit

Permalink
feat: add basic profile page \w user import
Browse files Browse the repository at this point in the history
  • Loading branch information
zvonimirr committed May 11, 2023
1 parent 2b0da93 commit fe102b3
Show file tree
Hide file tree
Showing 10 changed files with 135 additions and 281 deletions.
3 changes: 1 addition & 2 deletions config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ config :phoenix, :json_library, Jason
config :bolt_sips, Bolt,
url: "bolt://localhost:7687",
basic_auth: [username: "neo4j", password: "swipex-dev"],
pool_size: 10,
max_overflow: 2
pool_size: 10

# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version: '3.8'
services:
neo4j:
container_name: swipex_neo4j
image: neo4j:5.7
image: neo4j/neo4j-arm64-experimental:3.5.32-arm64
environment:
NEO4J_AUTH: 'neo4j/swipex-dev'
ports:
Expand Down
26 changes: 0 additions & 26 deletions lib/swipex_web/components/layouts/app.html.heex
Original file line number Diff line number Diff line change
@@ -1,29 +1,3 @@
<header class="px-4 sm:px-6 lg:px-8">
<div class="flex items-center justify-between border-b border-zinc-100 py-3 text-sm">
<div class="flex items-center gap-4">
<a href="/">
<img src={~p"/images/logo.svg"} width="36" />
</a>
<p class="bg-brand/5 text-brand rounded-full px-2 font-medium leading-6">
v<%= Application.spec(:phoenix, :vsn) %>
</p>
</div>
<div class="flex items-center gap-4 font-semibold leading-6 text-zinc-900">
<a href="https://twitter.com/elixirphoenix" class="hover:text-zinc-700">
@elixirphoenix
</a>
<a href="https://github.com/phoenixframework/phoenix" class="hover:text-zinc-700">
GitHub
</a>
<a
href="https://hexdocs.pm/phoenix/overview.html"
class="rounded-lg bg-zinc-100 px-2 py-1 hover:bg-zinc-200/80"
>
Get Started <span aria-hidden="true">&rarr;</span>
</a>
</div>
</div>
</header>
<main class="px-4 py-20 sm:px-6 lg:px-8">
<div class="mx-auto max-w-2xl">
<.flash_group flash={@flash} />
Expand Down
9 changes: 0 additions & 9 deletions lib/swipex_web/controllers/page_controller.ex

This file was deleted.

5 changes: 0 additions & 5 deletions lib/swipex_web/controllers/page_html.ex

This file was deleted.

237 changes: 0 additions & 237 deletions lib/swipex_web/controllers/page_html/home.html.heex

This file was deleted.

25 changes: 25 additions & 0 deletions lib/swipex_web/controllers/profile.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
defmodule SwipexWeb.Profile do
use SwipexWeb, :verified_routes
import Plug.Conn
import Phoenix.Controller

def on_mount(:current_user, _params, session, socket) do
# Generate user info if not present in the session
if !Map.has_key?(session, :user) do
# Generate a random user from a random number
user_id = System.unique_integer([:positive])

{:cont,
Phoenix.Component.assign_new(socket, :user, fn ->
%{
id: user_id,
name: "User #{user_id}",
avatar: "https://api.dicebear.com/6.x/pixel-art/svg?seed=#{user_id}&background=%23fff",
bio: ""
}
end)}
else
{:cont, Phoenix.Component.assign(socket, :user, session.user)}
end
end
end
92 changes: 92 additions & 0 deletions lib/swipex_web/live/profile_live.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
defmodule SwipexWeb.ProfileLive do
use SwipexWeb, :live_view
alias SwipexWeb.ProfileLive.EditForm

def handle_event("import", %{"id" => id}, socket) do
id = String.to_integer(id)
conn = Bolt.Sips.conn()

case Bolt.Sips.query(conn, "MATCH (u:User {id: $id}) RETURN u", %{id: id}) do
{:ok, response} ->
user = get_user_from_response(response)

if user == %{} do
{:noreply, put_flash(socket, :error, "Invalid user ID.")}
else
{:noreply, assign(socket, :user, user) |> put_flash(:info, "User imported!")}
end

{:error, _error} ->
{:noreply, put_flash(socket, :error, "Invalid user ID.")}
end
end

def handle_event("save", %{"name" => name, "bio" => bio}, socket) do
conn = Bolt.Sips.conn()

Bolt.Sips.transaction(conn, fn conn ->
# Create a new user if one doesn't exist
Bolt.Sips.query(conn, "MERGE (u:User {id: $id}) RETURN u", %{id: socket.assigns.user.id})
# Update the fields
Bolt.Sips.query(conn, "MATCH (u:User {id: $id}) SET u.bio = $bio RETURN u", %{
id: socket.assigns.user.id,
bio: bio
})

Bolt.Sips.query(conn, "MATCH (u:User {id: $id}) SET u.avatar = $avatar RETURN u", %{
id: socket.assigns.user.id,
avatar: socket.assigns.user.avatar
})

Bolt.Sips.query(conn, "MATCH (u:User {id: $id}) SET u.name = $name RETURN u", %{
id: socket.assigns.user.id,
name: name
})
end)

user =
Bolt.Sips.query!(conn, "MATCH (u:User {id: $id}) RETURN u", %{id: socket.assigns.user.id})
|> get_user_from_response()

{:noreply, assign(socket, :user, user) |> put_flash(:info, "User updated!")}
end

def render(assigns) do
~H"""
<div class="py-12 flex flex-col gap-3">
<h1 class="text-4xl"><%= @user.name %></h1>
<img src={@user.avatar} class="w-32 h-32 rounded-full" />
<p>Hey there, <%= @user.name %>, this is your profile page.</p>
<p>Why don't you tell us something about yourself?</p>
<div class="flex flex-col gap-3">
<.live_component id="edit_form" module={EditForm} user={@user} />
</div>
<hr />
<div class="flex flex-col gap-3">
<p>Already have an account?</p>
<form phx-submit="import" class="flex flex-col gap-4">
<input type="number" name="id" placeholder="User ID" />
<button type="submit" class="bg-blue-300 text-white rounded-md p-3">Import</button>
</form>
</div>
</div>
"""
end

defp get_user_from_response(response) do
case response
|> Bolt.Sips.Response.first() do
nil ->
%{}

user ->
user
|> Map.get("u")
|> Map.get(:properties)
|> Map.new(fn {k, v} -> {String.to_atom(k), v} end)
end
end
end
13 changes: 13 additions & 0 deletions lib/swipex_web/live/profile_live/edit_form.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
defmodule SwipexWeb.ProfileLive.EditForm do
use SwipexWeb, :live_component

def render(assigns) do
~H"""
<form phx-submit="save" class="flex flex-col gap-4">
<input type="text" name="name" placeholder="Name" value={@user.name} />
<textarea name="bio" placeholder="Bio"><%= @user.bio %></textarea>
<button type="submit" class="bg-blue-300 text-white rounded-md p-3">Save</button>
</form>
"""
end
end
4 changes: 3 additions & 1 deletion lib/swipex_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ defmodule SwipexWeb.Router do
scope "/", SwipexWeb do
pipe_through :browser

get "/", PageController, :home
live_session :default, on_mount: [{SwipexWeb.Profile, :current_user}] do
live "/", ProfileLive, :index
end
end

# Other scopes may use custom stacks.
Expand Down

0 comments on commit fe102b3

Please sign in to comment.