Skip to content

Commit

Permalink
Allow users to apply for yearbook class
Browse files Browse the repository at this point in the history
  • Loading branch information
MarioRodrigues10 committed Apr 7, 2023
1 parent acf3389 commit 8269dbb
Show file tree
Hide file tree
Showing 17 changed files with 151 additions and 78 deletions.
29 changes: 29 additions & 0 deletions lib/yearbook/university.ex
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,33 @@ defmodule Yearbook.University do
def change_class(%Class{} = class, attrs \\ %{}) do
Class.changeset(class, attrs)
end

alias Yearbook.University.ClassStudent

def create_class_student(attrs \\ %{}) do
aluno = get_all_classes_students(attrs["student_id"], attrs["class_id"])

if aluno > 0 do
{:error, %Ecto.Changeset{}}
else
%ClassStudent{}
|> ClassStudent.changeset(attrs)
|> Repo.insert()
end
end

def get_all_classes_students(student_id, class_id) do
ClassStudent
|> where(student_id: ^student_id)
|> where(class_id: ^class_id)
|> Repo.all()
|> Enum.count()
end

def get_classes_students(student_id) do
ClassStudent
|> where(student_id: ^student_id)
|> where(accepted: true)
|> Repo.all()
end
end
4 changes: 2 additions & 2 deletions lib/yearbook/university/class_student.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ defmodule Yearbook.University.ClassStudent do
schema "classes_students" do
belongs_to :class, University.Class
belongs_to :student, Accounts.User

field :accepted, :boolean, default: false
timestamps()
end

@doc false
def changeset(class_student, attrs) do
class_student
|> cast(attrs, [:class_id, :student_id])
|> cast(attrs, [:class_id, :student_id, :accepted])
|> validate_required([:class_id, :student_id])
|> unique_constraint([:class_id, :student_id])
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule YearbookWeb.Admin.ClassLive.FormComponent do
defmodule YearbookWeb.ClassLive.FormComponent do
@moduledoc false
use YearbookWeb, :live_component

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule YearbookWeb.Admin.ClassLive.Index do
defmodule YearbookWeb.ClassLive.Index do
@moduledoc false
use YearbookWeb, :live_view

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@
<div class="sm:flex-auto">
<h1 class="text-xl font-semibold text-gray-900">Lista de Turmas</h1>
</div>
<div class="mt-4 sm:mt-0 sm:ml-16 sm:flex-none">
<%= live_patch to: Routes.admin_class_index_path(@socket, :new) do %>
<button type="button" class="inline-flex items-center justify-center rounded-md border border-transparent bg-orange-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-orange-700 focus:outline-none focus:ring-2 focus:ring-orange-500 focus:ring-offset-2 sm:w-auto">
Nova Turma
</button>
<% end %>
</div>
<%= if assigns[:current_user] && (@current_user.permissions == [:admin, :sysadmin] || @current_user.permissions == [:admin] || @current_user.permissions == [:sysadmin]) do %>
<div class="mt-4 sm:mt-0 sm:ml-16 sm:flex-none">
<%= live_patch to: Routes.admin_class_index_path(@socket, :new) do %>
<button type="button" class="inline-flex items-center justify-center rounded-md border border-transparent bg-orange-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-orange-700 focus:outline-none focus:ring-2 focus:ring-orange-500 focus:ring-offset-2 sm:w-auto">
Nova Turma
</button>
<% end %>
</div>
<% end %>
</div>

<%= if @live_action in [:new, :edit] do %>
<.modal return_to={Routes.admin_class_index_path(@socket, :index)}>
<.live_component module={YearbookWeb.Admin.ClassLive.FormComponent} id={@class.id || :new} title={@page_title} action={@live_action} class={@class} return_to={Routes.admin_class_index_path(@socket, :index)} />
<.modal return_to={Routes.class_index_path(@socket, :index)}>
<.live_component module={YearbookWeb.ClassLive.FormComponent} id={@class.id || :new} title={@page_title} action={@live_action} class={@class} return_to={Routes.class_index_path(@socket, :index)} />
</.modal>
<% end %>

Expand Down Expand Up @@ -46,15 +48,16 @@
</td>
<td class="py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6">
<%= live_redirect to: Routes.yearbook_show_path(@socket, :show, class), class: "text-orange-600 hover:text-orange-900" do %>
Show<span class="sr-only"></span>
<% end %>

<%= live_patch to: Routes.admin_class_index_path(@socket, :edit, class), class: "text-orange-600 hover:text-orange-900" do %>
Edit<span class="sr-only"></span>
Ver<span class="sr-only"></span>
<% end %>
<%= if assigns[:current_user] && (@current_user.permissions == [:admin, :sysadmin] || @current_user.permissions == [:admin] || @current_user.permissions == [:sysadmin]) do %>
<%= live_patch to: Routes.admin_class_index_path(@socket, :edit, class), class: "text-orange-600 hover:text-orange-900" do %>
Edit<span class="sr-only"></span>
<% end %>

<%= link to: "#", phx_click: "delete", phx_value_id: class.id, data: [confirm: "Are you sure?"], class: "text-orange-600 hover:text-orange-900" do %>
Delete<span class="sr-only">Delete</span>
<%= link to: "#", phx_click: "delete", phx_value_id: class.id, data: [confirm: "Are you sure?"], class: "text-orange-600 hover:text-orange-900" do %>
Delete<span class="sr-only">Delete</span>
<% end %>
<% end %>
</td>
</tr>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule YearbookWeb.Admin.ClassLive.Show do
defmodule YearbookWeb.ClassLive.Show do
@moduledoc false
use YearbookWeb, :live_view

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

<%= if @live_action in [:edit] do %>
<.modal return_to={Routes.admin_class_show_path(@socket, :show, @class)}>
<.live_component module={YearbookWeb.Admin.ClassLive.FormComponent} id={@class.id} title={@page_title} action={@live_action} class={@class} return_to={Routes.admin_class_show_path(@socket, :show, @class)} />
<.live_component module={YearbookWeb.ClassLive.FormComponent} id={@class.id} title={@page_title} action={@live_action} class={@class} return_to={Routes.admin_class_show_path(@socket, :show, @class)} />
</.modal>
<% end %>

Expand All @@ -14,5 +14,5 @@
</li>
</ul>

<span><%= live_patch("Edit", to: Routes.admin_class_show_path(@socket, :edit, @class), class: "button") %></span> | <span><%= live_redirect("Back", to: Routes.admin_class_index_path(@socket, :index)) %></span>
<span><%= live_patch("Edit", to: Routes.admin_class_show_path(@socket, :edit, @class), class: "button") %></span> | <span><%= live_redirect("Back", to: Routes.class_index_path(@socket, :index)) %></span>
</div>
29 changes: 29 additions & 0 deletions lib/yearbook_web/live/yearbook_live/show.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,29 @@ defmodule YearbookWeb.YearbookLive.Show do
{:ok, socket}
end

@impl true
def handle_event("apply", _payload, socket) do
attrs = %{
"class_id" => socket.assigns.class.id,
"student_id" => socket.assigns.current_user.id,
"accepted" => false
}

case University.create_class_student(attrs) do
{:ok, _class_student} ->
{:noreply,
socket
|> put_flash(:info, "Applied to class successfully")
|> push_redirect(to: Routes.class_index_path(socket, :index))}

{:error, %Ecto.Changeset{} = changeset} ->
{:noreply,
assign(socket, :changeset, changeset)
|> put_flash(:error, "You have already applied to this class")
|> push_redirect(to: Routes.class_index_path(socket, :index))}
end
end

@impl true
def handle_params(%{"class_id" => id}, _, socket) do
class = University.get_class!(id, [:students, :degree, :academic_year])
Expand All @@ -19,4 +42,10 @@ defmodule YearbookWeb.YearbookLive.Show do
|> assign(:page_title, class.degree.name)
|> assign(:class, class)}
end

def is_accepted?(student, class) do
classes = University.get_classes_students(student)

Enum.any?(classes, fn cs -> cs.accepted == true && cs.class_id == class end)
end
end
85 changes: 47 additions & 38 deletions lib/yearbook_web/live/yearbook_live/show.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -10,48 +10,57 @@
</div>
<div class="mx-auto py-12 px-4 text-center sm:px-6 lg:px-8">
<div class="space-y-8 sm:space-y-12">
<%= if @current_user && Yearbook.University.get_classes_students(@current_user.id) == [] && (@current_user.permissions != [:admin, :sysadmin] || @current_user.permissions != [:admin] || @current_user.permissions != [:sysadmin]) do %>
<div class="flex mx-auto max-w-7xl">
<button class="inline-flex items-center justify-center rounded-md border border-transparent bg-orange-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-orange-700 focus:outline-none focus:ring-2 focus:ring-orange-500 focus:ring-offset-2 sm:w-auto" phx-click="apply">
Pertencer
</button>
</div>
<% end %>
<ul role="list" class="mx-auto space-y-16 sm:grid sm:grid-cols-2 sm:gap-16 sm:space-y-0 lg:grid-cols-4 lg:max-w-7xl">
<%= for student <- @class.students do %>
<li>
<div class="space-y-6">
<%= if is_nil(student.avatar) do %>
<div>
<span class="inline-flex justify-center items-center w-40 h-40 xl:w-56 xl:h-56 bg-gray-500 rounded-full">
<span class="text-5xl font-medium leading-none text-white"><%= extract_initials(student.name) %></span>
</span>
<%= if is_accepted?(student.id, @class.id) do %>
<li>
<div class="space-y-6">
<%= if is_nil(student.avatar) do %>
<div>
<span class="inline-flex justify-center items-center w-40 h-40 xl:w-56 xl:h-56 bg-gray-500 rounded-full">
<span class="text-5xl font-medium leading-none text-white"><%= extract_initials(student.name) %></span>
</span>
</div>
<% else %>
<img class="mx-auto h-40 w-40 rounded-full xl:w-56 xl:h-56" src={Uploaders.Avatar.url({student.avatar, student}, :thumb)} alt="" />
<% end %>
<div class="space-y-2">
<div class="text-lg leading-6 font-medium space-y-1">
<h3><%= student.name %></h3>
</div>
<ul role="list" class="flex justify-center space-x-5">
<li>
<a href="#" class="text-gray-400 hover:text-gray-500">
<span class="sr-only">Twitter</span>
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
<path d="M6.29 18.251c7.547 0 11.675-6.253 11.675-11.675 0-.178 0-.355-.012-.53A8.348 8.348 0 0020 3.92a8.19 8.19 0 01-2.357.646 4.118 4.118 0 001.804-2.27 8.224 8.224 0 01-2.605.996 4.107 4.107 0 00-6.993 3.743 11.65 11.65 0 01-8.457-4.287 4.106 4.106 0 001.27 5.477A4.073 4.073 0 01.8 7.713v.052a4.105 4.105 0 003.292 4.022 4.095 4.095 0 01-1.853.07 4.108 4.108 0 003.834 2.85A8.233 8.233 0 010 16.407a11.616 11.616 0 006.29 1.84" />
</svg>
</a>
</li>
<li>
<a href="#" class="text-gray-400 hover:text-gray-500">
<span class="sr-only">LinkedIn</span>
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
<path
fill-rule="evenodd"
d="M16.338 16.338H13.67V12.16c0-.995-.017-2.277-1.387-2.277-1.39 0-1.601 1.086-1.601 2.207v4.248H8.014v-8.59h2.559v1.174h.037c.356-.675 1.227-1.387 2.526-1.387 2.703 0 3.203 1.778 3.203 4.092v4.711zM5.005 6.575a1.548 1.548 0 11-.003-3.096 1.548 1.548 0 01.003 3.096zm-1.337 9.763H6.34v-8.59H3.667v8.59zM17.668 1H2.328C1.595 1 1 1.581 1 2.298v15.403C1 18.418 1.595 19 2.328 19h15.34c.734 0 1.332-.582 1.332-1.299V2.298C19 1.581 18.402 1 17.668 1z"
clip-rule="evenodd"
/>
</svg>
</a>
</li>
</ul>
</div>
<% else %>
<img class="mx-auto h-40 w-40 rounded-full xl:w-56 xl:h-56" src={Uploaders.Avatar.url({student.avatar, student}, :thumb)} alt="" />
<% end %>
<div class="space-y-2">
<div class="text-lg leading-6 font-medium space-y-1">
<h3><%= student.name %></h3>
</div>
<ul role="list" class="flex justify-center space-x-5">
<li>
<a href="#" class="text-gray-400 hover:text-gray-500">
<span class="sr-only">Twitter</span>
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
<path d="M6.29 18.251c7.547 0 11.675-6.253 11.675-11.675 0-.178 0-.355-.012-.53A8.348 8.348 0 0020 3.92a8.19 8.19 0 01-2.357.646 4.118 4.118 0 001.804-2.27 8.224 8.224 0 01-2.605.996 4.107 4.107 0 00-6.993 3.743 11.65 11.65 0 01-8.457-4.287 4.106 4.106 0 001.27 5.477A4.073 4.073 0 01.8 7.713v.052a4.105 4.105 0 003.292 4.022 4.095 4.095 0 01-1.853.07 4.108 4.108 0 003.834 2.85A8.233 8.233 0 010 16.407a11.616 11.616 0 006.29 1.84" />
</svg>
</a>
</li>
<li>
<a href="#" class="text-gray-400 hover:text-gray-500">
<span class="sr-only">LinkedIn</span>
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
<path
fill-rule="evenodd"
d="M16.338 16.338H13.67V12.16c0-.995-.017-2.277-1.387-2.277-1.39 0-1.601 1.086-1.601 2.207v4.248H8.014v-8.59h2.559v1.174h.037c.356-.675 1.227-1.387 2.526-1.387 2.703 0 3.203 1.778 3.203 4.092v4.711zM5.005 6.575a1.548 1.548 0 11-.003-3.096 1.548 1.548 0 01.003 3.096zm-1.337 9.763H6.34v-8.59H3.667v8.59zM17.668 1H2.328C1.595 1 1 1.581 1 2.298v15.403C1 18.418 1.595 19 2.328 19h15.34c.734 0 1.332-.582 1.332-1.299V2.298C19 1.581 18.402 1 17.668 1z"
clip-rule="evenodd"
/>
</svg>
</a>
</li>
</ul>
</div>
</div>
</li>
</li>
<% end %>
<% end %>
</ul>
</div>
Expand Down
15 changes: 9 additions & 6 deletions lib/yearbook_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ defmodule YearbookWeb.Router do

scope "/", YearbookWeb do
pipe_through :browser

get "/", PageController, :index
get "/contacts", PageController, :contacts
get "/terms", PageController, :terms
Expand Down Expand Up @@ -59,6 +58,15 @@ defmodule YearbookWeb.Router do

live_session :logged_in, on_mount: [{YearbookWeb.Hooks, :current_user}] do
live "/yearbook/:class_id", YearbookLive.Show, :show
live "/classes", ClassLive.Index, :index

scope "/admin", as: :admin do
pipe_through :require_admin_user

live "/classes/new", ClassLive.Index, :new
live "/classes/:id/edit", ClassLive.Index, :edit
live "/classes/:id/show/edit", ClassLive.Show, :edit
end

scope "/admin", Admin, as: :admin do
pipe_through :require_admin_user
Expand All @@ -74,11 +82,6 @@ defmodule YearbookWeb.Router do
live "/degrees/:id/edit", DegreeLive.Index, :edit
live "/degrees/:id", DegreeLive.Show, :show
live "/degrees/:id/show/edit", DegreeLive.Show, :edit

live "/classes", ClassLive.Index, :index
live "/classes/new", ClassLive.Index, :new
live "/classes/:id/edit", ClassLive.Index, :edit
live "/classes/:id/show/edit", ClassLive.Show, :edit
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/yearbook_web/templates/layout/_auth_menu.html.heex
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<%= if @current_user do %>
<%= if assigns[:current_user] do %>
<div href="#" class="block flex-shrink-0 group">
<div class="flex items-center">
<%= if is_nil(@current_user.avatar) do %>
Expand Down
2 changes: 1 addition & 1 deletion lib/yearbook_web/templates/layout/_header.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<div class="flex items-center">
<a href="/">
<span class="sr-only">CeSIUM</span>
<%= if @current_user do %>
<%= if assigns[:current_user] do %>
<img class="w-auto h-10" src={Routes.static_path(YearbookWeb.Endpoint, "/images/logo-WHITE.svg")} alt="CeSIUM's Logo" />
<% else %>
<img class="w-auto h-10" src={Routes.static_path(YearbookWeb.Endpoint, "/images/cesium-WHITE.svg")} alt="CeSIUM's Logo" />
Expand Down
2 changes: 1 addition & 1 deletion lib/yearbook_web/views/layout_view.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ defmodule YearbookWeb.LayoutView do
},
%{
title: "Turmas",
path: Routes.admin_class_index_path(@conn, :index)
path: Routes.class_index_path(@conn, :index)
}
]
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ defmodule Yearbook.Repo.Migrations.CreateClassesStudents do
add :id, :binary_id, primary_key: true
add :class_id, references(:classes, on_delete: :nothing, type: :binary_id)
add :student_id, references(:users, on_delete: :nothing, type: :binary_id)

add :accepted, :boolean, default: false
timestamps()
end

Expand Down
2 changes: 1 addition & 1 deletion priv/repo/seeds.exs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ for degree <- [lei, mei, miei, dei],
|> Repo.update!()

%ClassStudent{}
|> ClassStudent.changeset(%{student_id: student.id, class_id: class.id})
|> ClassStudent.changeset(%{student_id: student.id, class_id: class.id, accepted: true})
|> Repo.insert!()
end)
end
Loading

0 comments on commit 8269dbb

Please sign in to comment.