Skip to content

Commit

Permalink
Add layout
Browse files Browse the repository at this point in the history
  • Loading branch information
MarioRodrigues10 committed Jul 16, 2023
1 parent 30a4206 commit 4e3e06a
Show file tree
Hide file tree
Showing 27 changed files with 802 additions and 516 deletions.
3 changes: 3 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ config :tailwind,
cd: Path.expand("../assets", __DIR__)
]

config :icons,
collection: [Heroicons, Ionicons]

config :atomic, Atomic.Scheduler,
jobs: [
# Runs every midnight:
Expand Down
13 changes: 13 additions & 0 deletions lib/atomic/activities.ex
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,19 @@ defmodule Atomic.Activities do
end
end

def get_user_enrollments(user) do
Enrollment
|> where(user_id: ^user.id)
|> Repo.all()
end

def get_user_activities(user) do
enrollments = get_user_enrollments(user)
activities = for enrollment <- enrollments, do: get_activity!(enrollment.activity_id)

activities |> Repo.preload([:enrollments, :activity_sessions, :speakers])
end

@doc """
Creates an enrollment.
Expand Down
7 changes: 7 additions & 0 deletions lib/atomic/organizations.ex
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,13 @@ defmodule Atomic.Organizations do
|> Repo.preload(preloads)
end

def get_membership_role!(user_id, organization_id) do
case Repo.get_by(Membership, user_id: user_id, organization_id: organization_id) do
nil -> nil
membership -> membership.role
end
end

@doc """
Creates an user organization.
Expand Down
4 changes: 3 additions & 1 deletion lib/atomic_web.ex
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,10 @@ defmodule AtomicWeb do

import AtomicWeb.ErrorHelpers
import AtomicWeb.Gettext
import AtomicWeb.ViewUtils
import AtomicWeb.UtilsView
alias AtomicWeb.Router.Helpers, as: Routes

alias Icons.{Heroicons, Ionicons}
end
end

Expand Down
60 changes: 60 additions & 0 deletions lib/atomic_web/config.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
defmodule AtomicWeb.Config do
@moduledoc """
Web configuration for our pages.
"""
alias AtomicWeb.Router.Helpers, as: Routes

def pages(conn) do
[
%{
key: :activities,
title: "Home",
icon: :home,
url: Routes.activity_index_path(conn, :index),
tabs: []
},
%{
key: :departments,
title: "Departments",
icon: :calendar,
url: Routes.department_index_path(conn, :index, :org),
tabs: []
},
%{
key: :instructors,
title: "Activities",
icon: :academic_cap,
url: Routes.activity_index_path(conn, :index),
tabs: []
},
%{
key: :partners,
title: "Partners",
icon: :user_group,
url: Routes.partner_index_path(conn, :index),
tabs: []
},
%{
key: :memberships,
title: "Memberships",
icon: :user_add,
url: Routes.membership_index_path(conn, :index, :org),
tabs: []
},
%{
key: :board,
title: "Board",
icon: :users,
url: Routes.board_index_path(conn, :index, :org),
tabs: []
},
%{
key: :scanner,
title: "Scanner",
icon: :qrcode,
url: Routes.scanner_index_path(conn, :index),
tabs: []
}
]
end
end
13 changes: 13 additions & 0 deletions lib/atomic_web/live/activity_live/edit.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,21 @@ defmodule AtomicWeb.ActivityLive.Edit do

@impl true
def handle_params(%{"id" => id} = _params, _url, socket) do
entries = [
%{
name: gettext("Activities"),
route: Routes.activity_index_path(socket, :index)
},
%{
name: gettext("Edit Activity"),
route: Routes.activity_edit_path(socket, :edit, id)
}
]

{:noreply,
socket
|> assign(:breadcrumb_entries, entries)
|> assign(:current_page, :activities)
|> assign(:page_title, gettext("Edit Activity"))
|> assign(
:activity,
Expand Down
26 changes: 24 additions & 2 deletions lib/atomic_web/live/activity_live/index.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,18 @@ defmodule AtomicWeb.ActivityLive.Index do

@impl true
def handle_params(params, _url, socket) do
{:noreply, apply_action(socket, socket.assigns.live_action, params)}
entries = [
%{
name: gettext("Activities"),
route: Routes.activity_index_path(socket, :index)
}
]

{:noreply,
socket
|> assign(:current_page, :activities)
|> assign(:breadcrumb_entries, entries)
|> apply_action(socket.assigns.live_action, params)}
end

defp apply_action(socket, :edit, %{"id" => id}) do
Expand Down Expand Up @@ -40,7 +51,18 @@ defmodule AtomicWeb.ActivityLive.Index do
{:noreply, assign(socket, :activies, list_activities())}
end

def handle_event("open-enrollments", _payload, socket) do
{:noreply, assign(socket, :activities, list_activities())}
end

def handle_event("activities-enrolled", _payload, socket) do
user = socket.assigns.current_user
activities = Activities.get_user_activities(user)

{:noreply, assign(socket, :activities, activities)}
end

defp list_activities do
Activities.list_activities(preloads: [:activity_sessions])
Activities.list_activities(preloads: [:activity_sessions, :enrollments, :speakers])
end
end
118 changes: 88 additions & 30 deletions lib/atomic_web/live/activity_live/index.html.heex
Original file line number Diff line number Diff line change
@@ -1,32 +1,90 @@
<h1>Listing Activities</h1>
<div class="inline-block min-w-full align-middle">
<div x-data="{ view: 'list' }">
<div class="bg-white">
<div class="pt-4 px-4">
<div class="flex items-center justify-between">
<div class="min-w-0 flex-1">
<h2 class="text-xl font-bold leading-7 text-zinc-900 sm:truncate sm:text-4xl">
<%= gettext("Activities") %>
</h2>
</div>
</div>
<div class="flex flex-col-reverse border-b border-zinc-200 xl:flex-row">
<div class="flex w-full items-center justify-between">
<nav class="-mb-px flex flex-1 space-x-6 overflow-x-auto xl:space-x-8" aria-label="Tabs">
<div x-on:click="open = ! open" x-bind:class="! open ? 'border-transparent' : 'border-zinc-800'" phx-click="open-enrollments" class="text-zinc-500 hover:text-zinc-700 hover:border-zinc-300 whitespace-nowrap border-b-2 px-1 py-4 text-sm font-medium">
<%= gettext("Open Enrollments") %>
</div>

<table>
<thead>
<tr>
<th>Title</th>
<th>Date</th>
<th>Location</th>
<th>Minimum entries</th>
<th>Maximum entries</th>
<div x-on:click="open = ! open" x-bind:class="! open ? 'border-zinc-800' : 'border-transparent'" phx-click="activities-enrolled" class="text-zinc-500 hover:text-zinc-700 hover:border-zinc-300 whitespace-nowrap border-b-2 px-1 py-4 text-sm font-medium">
<%= gettext("Activities Enrolled") %>
</div>
</nav>
<div>
<%= live_patch("New", to: Routes.activity_new_path(@socket, :new), class: "rounded-md bg-orange-500 py-2 px-3.5 text-sm font-medium text-white shadow-sm hover:bg-orange-600 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600") %>
</div>
</div>
</div>
</div>
</div>

<th></th>
</tr>
</thead>
<tbody id="activities">
<%= for activity <- @activities do %>
<tr id={"activity-#{activity.id}"}>
<td><%= activity.title %></td>
<td><%= hd(activity.activity_sessions).start %></td>
<td><%= hd(activity.activity_sessions).location.name %></td>
<td><%= activity.minimum_entries %></td>
<td><%= activity.maximum_entries %></td>

<td>
<span><%= live_redirect("Show", to: Routes.activity_show_path(@socket, :show, activity)) %></span>
</td>
</tr>
<% end %>
</tbody>
</table>

<span><%= live_patch("New Activity", to: Routes.activity_new_path(@socket, :new)) %></span>
<div x-bind:class="view =='list' ? 'hidden lg:block' : 'hidden'">
<div class="overflow-hidden bg-white">
<ul role="list" class="divide-y divide-zinc-200">
<%= for activity <- @activities do %>
<li>
<%= live_redirect to: Routes.activity_show_path(@socket, :show, activity), class: "block hover:bg-zinc-50", replace: false do %>
<div class="px-4 py-4 lg:px-6">
<div class="flex items-center justify-between">
<p class="truncate text-sm font-medium text-zinc-900">
<%= activity.title %>
</p>
</div>
<div class="mt-2 lg:flex lg:justify-between">
<div class="lg:flex lg:space-x-3">
<p class="mt-2 flex items-center text-sm text-zinc-500 lg:mt-0">
<Heroicons.Solid.users class="flex-shrink-0 mr-1.5 w-5 h-5 text-zinc-400" />
<%= Enum.count(activity.enrollments) %> / <%= activity.maximum_entries %>
</p>
<p class="mt-2 flex items-center text-sm text-zinc-500 lg:mt-0">
<Heroicons.Solid.calendar class="flex-shrink-0 mr-1.5 w-5 h-5 text-zinc-400" />
<%= if hd(activity.activity_sessions) do %>
<%= display_date(hd(activity.activity_sessions).start) %>
<% end %>
</p>
<%= if not is_nil(hd(activity.activity_sessions).location) do %>
<p class="mt-2 flex items-center text-sm text-zinc-500 lg:mt-0">
<Heroicons.Solid.location_marker class="flex-shrink-0 mr-1.5 w-5 h-5 text-zinc-400" />
<%= if hd(activity.activity_sessions).location do %>
<%= hd(activity.activity_sessions).location && hd(activity.activity_sessions).location.name %>
<% end %>
</p>
<% end %>
</div>
</div>
<div class="flex flex-col-reverse lg:flex-row-reverse lg:items-center lg:justify-between">
<div class="mt-2 flex items-center text-sm text-zinc-500 lg:mt-0">
<Heroicons.Solid.bell class="flex-shrink-0 mr-1.5 w-5 h-5 text-zinc-400" /> Closing
</div>
<%= for speaker <- activity.speakers do %>
<div class="mt-2 flex items-center">
<span class="inline-flex justify-center items-center mr-1.5 w-6 h-6 bg-zinc-500 rounded-full">
<span class="text-xs font-medium leading-none text-white">
<%= extract_initials(speaker.name) %>
</span>
</span>
<p class="text-sm text-zinc-500">
<%= extract_first_last_name(speaker.name) %>
</p>
</div>
<% end %>
</div>
</div>
<% end %>
</li>
<% end %>
</ul>
</div>
</div>
</div>
</div>
13 changes: 13 additions & 0 deletions lib/atomic_web/live/activity_live/new.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,22 @@ defmodule AtomicWeb.ActivityLive.New do

@impl true
def handle_params(_params, _url, socket) do
entries = [
%{
name: gettext("Activities"),
route: Routes.activity_index_path(socket, :index)
},
%{
name: gettext("New Activity"),
route: Routes.activity_new_path(socket, :new)
}
]

{:noreply,
socket
|> assign(:page_title, gettext("New Activity"))
|> assign(:breadcrumb_entries, entries)
|> assign(:current_page, :activities)
|> assign(:activity, %Activity{
activity_sessions: [%Session{}],
speakers: []
Expand Down
28 changes: 23 additions & 5 deletions lib/atomic_web/live/activity_live/show.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ defmodule AtomicWeb.ActivityLive.Show do
use AtomicWeb, :live_view

alias Atomic.Activities
alias Atomic.Organizations

@impl true
def mount(%{"id" => id}, _session, socket) do
Expand All @@ -17,10 +18,23 @@ defmodule AtomicWeb.ActivityLive.Show do
def handle_params(%{"id" => id}, _, socket) do
activity = Activities.get_activity!(id, [:activity_sessions, :departments, :speakers])

entries = [
%{
name: gettext("Activities"),
route: Routes.activity_index_path(socket, :index)
},
%{
name: activity.title,
route: Routes.activity_show_path(socket, :show, activity)
}
]

{:noreply,
socket
|> assign(:enrolled?, Activities.is_user_enrolled?(activity, socket.assigns.current_user))
|> assign(:page_title, page_title(socket.assigns.live_action))
|> assign(:breadcrumb_entries, entries)
|> assign(:current_page, :activities)
|> assign(:activity, %{activity | enrolled: Activities.get_total_enrolled(activity)})}
end

Expand Down Expand Up @@ -54,13 +68,12 @@ defmodule AtomicWeb.ActivityLive.Show do
{:noreply,
socket
|> put_flash(:success, gettext("Unenrolled successufully!"))
|> set_enrolled(activity, current_user)}
|> assign(:enrolled?, false)}

{_, nil} ->
{:noreply,
socket
|> put_flash(:error, gettext("Unable to unenroll"))
|> set_enrolled(activity, current_user)}
|> put_flash(:error, gettext("Unable to unenroll"))}
end
end

Expand Down Expand Up @@ -91,8 +104,8 @@ defmodule AtomicWeb.ActivityLive.Show do
assign(socket, :activity, %{activity | enrolled: Activities.get_total_enrolled(activity)})}
end

defp draw_qr_code(session, user, _socket) do
internal_route = "/redeem/#{session.activity_id}/#{user.id}/confirm"
defp draw_qr_code(activity, user, _socket) do
internal_route = "/redeem/#{activity.id}/#{user.id}/confirm"

url = build_url() <> internal_route

Expand All @@ -117,4 +130,9 @@ defmodule AtomicWeb.ActivityLive.Show do
"https://#{Application.fetch_env(:atomic, AtomicWeb.Endpoint)[:url][:host]}"
end
end

def is_admin?(user, activity) do
department = activity.departments |> Enum.at(0)
Organizations.get_membership_role!(user.id, department.organization_id) in [:admin, :owner]
end
end
Loading

0 comments on commit 4e3e06a

Please sign in to comment.