Skip to content

Commit

Permalink
[FS-8] Add attendances admin panel (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
beetlegius-jt authored Jan 22, 2025
1 parent 27c8892 commit c582c14
Show file tree
Hide file tree
Showing 10 changed files with 155 additions and 0 deletions.
24 changes: 24 additions & 0 deletions app/controllers/admin/attendances_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module Admin
class AttendancesController < BaseController
before_action :set_attendance, only: [ :destroy ]

def index
@attendances = authorize policy_scope(Current.company.attendances).order(created_at: :desc)
end

def destroy
@attendance.destroy!

respond_to do |format|
format.turbo_stream { render turbo_stream: turbo_stream.remove(dom_id(@attendance)) }
format.html { redirect_to admin_attendances_path, notice: notice_message }
end
end

private

def set_attendance
@attendance = authorize policy_scope(Current.company.attendances).find(params[:id])
end
end
end
24 changes: 24 additions & 0 deletions app/policies/admin/attendance_policy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module Admin
class AttendancePolicy < ApplicationPolicy
# NOTE: Up to Pundit v2.3.1, the inheritance was declared as
# `Scope < Scope` rather than `Scope < ApplicationPolicy::Scope`.
# In most cases the behavior will be identical, but if updating existing
# code, beware of possible changes to the ancestors:
# https://gist.github.com/Burgestrand/4b4bc22f31c8a95c425fc0e30d7ef1f5

def index?
owner?
end

def destroy?
owner? && record.company == user.company
end

class Scope < ApplicationPolicy::Scope
# NOTE: Be explicit about which records you allow access to!
def resolve
scope.all
end
end
end
end
6 changes: 6 additions & 0 deletions app/views/admin/attendances/_attendance.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<%= tag.tr id: dom_id(attendance) do %>
<td><%= attendance.customer.name %></td>
<td><%= l attendance.attended_at %></td>

<td><%= link_to t(:delete), [:admin, attendance], data: { turbo_method: :delete, turbo_confirm: t(:confirm) } if policy([:admin, attendance]).destroy? %></td>
<% end %>
15 changes: 15 additions & 0 deletions app/views/admin/attendances/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<div class="card">
<div class="card-header"><%= Attendance.model_name.human %></div>
<div class="card-body">
<table class='table'>
<thead>
<th><%= Attendance.human_attribute_name :customer %></th>
<th><%= Attendance.human_attribute_name :attended_at %></th>
<th></th>
</thead>
<tbody>
<%= render @attendances %>
</tbody>
</table>
</div>
</div>
1 change: 1 addition & 0 deletions app/views/admin/base/_navigation_links.html.erb
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
<%= nav_item t(".edit_company"), edit_admin_company_path if Current.user.company? %>
<%= nav_item Activity, admin_activities_path if policy([:admin, Activity]).index? %>
<%= nav_item Attendance, admin_attendances_path if policy([:admin, Attendance]).index? %>
3 changes: 3 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ en:
name: Activity name
duration_minutes: Duration (minutes)
max_capacity: Max capacity
attendance:
customer: Customer
attended_at: Date
company:
name: Company name
subdomain: Company subdomain
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
constraints CompanyConstraint.new do
namespace :admin do
resources :activities
resources :attendances, only: [ :index, :destroy ]
resource :company, only: [ :edit, :update ]

root to: "companies#show"
Expand Down
52 changes: 52 additions & 0 deletions spec/policies/admin/attendance_policy_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
require 'rails_helper'

RSpec.describe Admin::AttendancePolicy, type: :policy do
let(:company) { build(:company) }

subject { described_class }

before { Current.company = company }

permissions :index? do
context "when the user is not logged in" do
let(:user) { nil }

it { is_expected.not_to permit(user, Attendance) }
end

context "when the user is not the owner" do
let(:user) { build(:user, :company) }

it { is_expected.not_to permit(user, Attendance) }
end

context "when the user is the owner" do
let(:user) { build(:user, :company, owner: company) }

it { is_expected.to permit(user, Attendance) }
end
end

permissions :destroy? do
let(:attendance) { build(:attendance, company:) }

context "when the user is not logged in" do
let(:user) { nil }

it { is_expected.not_to permit(user, attendance) }
end

context "when the attendance is from a different company" do
let(:user) { build(:user, :company, owner: company) }
let(:attendance) { build(:attendance) }

it { is_expected.not_to permit(user, attendance) }
end

context "when the attendance is from the user company" do
let(:user) { build(:user, :company, owner: company) }

it { is_expected.to permit(user, attendance) }
end
end
end
2 changes: 2 additions & 0 deletions spec/support/system_tests.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@
config.before(:each, type: :system, js: true) do
driven_by :selenium_chrome_headless
end

config.include ActionView::RecordIdentifier, type: :system
end
27 changes: 27 additions & 0 deletions spec/system/admin/admin_attendances_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
require 'rails_helper'

RSpec.describe "Admin::Attendances", type: :system do
let(:subdomain) { "something" }
let(:company) { create(:company, subdomain:) }
let(:user) { create(:user, :company, owner: company) }

before { sign_in(user) }

let!(:attendance) { create(:attendance, company:) }

it "can list all and delete the attendances" do
visit admin_root_url(subdomain:)

within("#web-nav") do
find("a[href='#{admin_attendances_path}']").click
end

expect(page).to have_content attendance.customer.name
expect(page).to have_content I18n.l(attendance.attended_at)

within("##{dom_id(attendance)}") { click_on I18n.t(:delete) }

expect(page).not_to have_content attendance.customer.name
expect(page).not_to have_content I18n.l(attendance.attended_at)
end
end

0 comments on commit c582c14

Please sign in to comment.