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
72 changes: 72 additions & 0 deletions app/controllers/sectors_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
class SectorsController < ApplicationController
before_action :set_sector, only: [:show, :edit, :update, :destroy]

def index
per_page = params[:number_of_items_per_page].presence || 25
unpaginated = Sector.all
filtered = unpaginated.sector_name(params[:sector_name])
.published_search(params[:published_search])
.order(:name)
@sectors = filtered.paginate(page: params[:page], per_page: per_page)

@count_display = if @sectors.total_entries == unpaginated.count
unpaginated.count
else
"#{@sectors.total_entries}/#{unpaginated.count}"
end
end

def show
end

def new
@sector = Sector.new
set_form_variables
end

def edit
set_form_variables
end

def create
@sector = Sector.new(sector_params)

if @sector.save
redirect_to sectors_path, notice: "Sector was successfully created."
else
set_form_variables
render :new, status: :unprocessable_content
end
end

def update
if @sector.update(sector_params)
redirect_to sectors_path, notice: "Sector was successfully updated.", status: :see_other
else
set_form_variables
render :edit, status: :unprocessable_content
end
end

def destroy
@sector.destroy!
redirect_to sectors_path, notice: "Sector was successfully destroyed."
end

# Optional hooks for setting variables for forms or index
def set_form_variables
end

private

def set_sector
@sector = Sector.find(params[:id])
end

# Strong parameters
def sector_params
params.require(:sector).permit(
:name, :published
)
end
end
13 changes: 9 additions & 4 deletions app/helpers/admin_dashboard_cards_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,13 @@ def user_content_cards
# -----------------------------
def reference_cards
[
model_card(:categories, icon: "🗂️", intensity: 100),
custom_card("Service populations", authenticated_root_path, icon: "🏭", color: :lime, intensity: 100),
model_card(:categories, icon: "🗂️",
intensity: 100,
params: { published_search: true }),
model_card(:sectors, icon: "🏭",
intensity: 100,
title: "Service populations",
params: { published_search: true }),
custom_card("Project statuses", authenticated_root_path, icon: "🧮", color: :emerald, intensity: 100),
custom_card("Windows types", windows_types_path, icon: "🪟"),
]
Expand All @@ -50,10 +55,10 @@ def reference_cards
# ============================================================
# CARD BUILDERS
# ============================================================
def model_card(key, title: nil, icon:, intensity: 50)
def model_card(key, title: nil, icon:, intensity: 50, params: {})
{
title: title || key.to_s.humanize,
path: polymorphic_path(key.to_s.classify.constantize),
path: polymorphic_path(key.to_s.classify.constantize, params),
icon: icon,
bg_color: DomainTheme.bg_class_for(key, intensity: intensity),
hover_bg_color: DomainTheme.bg_class_for(key, intensity: intensity == 50 ? 100 : intensity + 100, hover: true),
Expand Down
8 changes: 6 additions & 2 deletions app/models/sector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ class Sector < ApplicationRecord
validates_presence_of :name, uniqueness: true

# Scopes
scope :published, -> { where(published: true).
order(Arel.sql("CASE WHEN name = 'Other' THEN 1 ELSE 0 END, LOWER(name) ASC")) }
scope :published, ->(published=nil) {
["true", "false"].include?(published) ? where(published: published) : where(published: true) }
scope :published_search, ->(published_search) { published_search.present? ? published(published_search) : all }
scope :sector_name, ->(sector_name) {
sector_name.present? ? where("sectors.name LIKE ?", "%#{sector_name}%") : all }
scope :has_taggings, -> { joins(:sectorable_items).distinct }

end
3 changes: 1 addition & 2 deletions app/views/categories/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@

<%= f.button :submit,
"Save Category",
class: "bg-blue-600 text-white px-6 py-2 rounded-lg hover:bg-blue-700
transition-colors duration-150" %>
class: "btn btn-primary" %>
</div>

</div>
Expand Down
48 changes: 48 additions & 0 deletions app/views/sectors/_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<%= simple_form_for(@sector) do |f| %>
<div class="space-y-6">

<!-- Errors -->
<%= f.error_notification %>
<%= render "shared/errors", resource: @sector if @sector.errors.any? %>

<!-- One-line Flex Fields -->
<div class="flex flex-wrap gap-6">

<!-- Name -->
<div class="flex-1 min-w-[220px]">
<%= f.input :name,
label: "Name",
input_html: { class: "form-control" } %>
</div>

<div class="flex items-center min-w-[150px] pt-6">
<%= f.input :published,
as: :boolean,
label: "Published?",
wrapper_html: { class: "flex items-center gap-2" },
input_html: { class: "form-checkbox" } %>
</div>

</div>

<!-- Actions -->
<div class="flex flex-wrap justify-end gap-3 pt-6">

<% if @sector.persisted? && current_user.super_user? %>
<%= link_to "Delete",
@sector,
method: :delete,
data: { confirm: "Are you sure you want to delete this category?" },
class: "btn btn-danger-outline" %>
<% end %>

<%= link_to "Cancel", sectors_path,
class: "btn btn-secondary-outline" %>

<%= f.button :submit,
"Save Sector",
class: "btn btn-primary" %>
</div>

</div>
<% end %>
39 changes: 39 additions & 0 deletions app/views/sectors/_search_boxes.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<!-- Filters -->
<div class="mb-6 p-4 bg-white border border-gray-200 rounded-lg">
<%= form_with url: sectors_path,
method: :get,
local: true,
class: "grid grid-cols-1 md:grid-cols-5 gap-4 items-end" do |f| %>

<!-- Name Search -->
<div>
<%= f.label :sector_name, "Name Contains",
class: "block text-sm font-medium text-gray-700" %>

<%= f.text_field :sector_name,
value: params[:sector_name],
class: "mt-1 block w-full rounded-md border border-gray-300 p-2",
oninput: "this.form.requestSubmit()" %>
</div>

<!-- Published -->
<div>
<%= f.label :published_search, "Published",
class: "block text-sm font-medium text-gray-700" %>

<%= f.select :published_search,
options_for_select([["All", ""], ["Published", "true"], ["Hidden", "false"]], params[:published_search]),
{},
class: "mt-1 block w-full rounded-md border border-gray-300 p-2",
onchange: "this.form.requestSubmit()" %>
</div>

<!-- Clear -->
<div>
<%= link_to "Clear",
sectors_path,
class: "btn btn-utility-outline whitespace-nowrap" %>
</div>

<% end %>
</div>
17 changes: 17 additions & 0 deletions app/views/sectors/edit.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<div class="min-h-screen py-8">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="max-w-5xl mx-auto bg-white border border-gray-200 rounded-xl shadow-lg hover:shadow-xl transition-shadow duration-200 p-6">
<div class="flex items-center justify-between mb-6">
<h1 class="text-2xl font-semibold text-gray-900">Edit Service population</h1>
<%= link_to "Taggings", taggings_path(sector_names: @sector.name),
class: "btn btn-secondary-outline" %>
</div>

<div class="space-y-6">
<div class="mt-4">
<%= render "form", sector: @sector %>
</div>
</div>
</div>
</div>
</div>
91 changes: 91 additions & 0 deletions app/views/sectors/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<div class="min-h-screen">
<div class="max-w-full mx-auto px-4 sm:px-6 lg:px-8">
<div class="max-w-7xl mx-auto <%= DomainTheme.bg_class_for(:sectors) %> border border-gray-200 rounded-xl shadow-lg p-6">
<div class="space-y-6">

<!-- Header -->
<div class="flex items-center justify-between mb-6">
<h1 class="text-2xl font-semibold text-gray-900">
Service populations (<%= @count_display %>)
</h1>
<%= link_to "New #{Sector.model_name.human.downcase}",
new_sector_path,
class: "btn btn-primary-outline" %>
</div>

<%= render "search_boxes" %>

<!-- Table -->
<div class="bg-white rounded">
<div class="overflow-x-auto">
<% if @sectors.any? %>
<table class="w-full table-fixed border-collapse border border-gray-200">
<thead class="bg-gray-100">
<tr>
<th class="px-4 py-2 text-left text-sm font-semibold text-gray-700 w-1/3">
Name
</th>

<th class="px-4 py-2 text-center text-sm font-semibold text-gray-700 w-1/6">
Published
</th>

<th class="px-4 py-2 text-center text-sm font-semibold text-gray-700 w-[80px]">
Actions
</th>
</tr>
</thead>

<tbody class="divide-y divide-gray-200">
<% @sectors.each do |sector| %>
<tr class=" <%= "bg-gray-200" unless sector.published %>
<%= sector.published ? "hover:bg-gray-50" : "hover:bg-gray-100" %> transition-colors duration-150">

<td class="px-4 py-2 text-md text-gray-800 truncate font-bold">
<%= sector.name %>
</td>

<td class="px-4 py-2 text-center">
<% if sector.published? %>
<span class="inline-block px-2 py-1 text-xs font-semibold text-green-800 bg-green-100 rounded">
Yes
</span>
<% else %>
<span class="inline-block px-2 py-1 text-xs font-semibold text-gray-700 bg-gray-200 rounded">
No
</span>
<% end %>
</td>

<!-- Actions -->
<td class="px-4 py-2 text-center">
<%= link_to "Edit",
edit_sector_path(sector),
class: "btn btn-secondary-outline whitespace-nowrap" %>
<%= link_to "Taggings",
taggings_path(sector_names: sector.name),
class: "btn btn-secondary-outline whitespace-nowrap" %>
</td>

</tr>
<% end %>
</tbody>
</table>
<% else %>
<!-- Empty state -->
<p class="text-gray-500 text-center py-6">
No <%= Sector.model_name.human.pluralize %> found.
</p>
<% end %>
</div>
</div>

<!-- Pagination -->
<div class="pagination flex justify-center mt-12">
<%= tailwind_paginate @sectors %>
</div>

</div>
</div>
</div>
</div>
17 changes: 17 additions & 0 deletions app/views/sectors/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<div class="min-h-screen py-8">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="max-w-5xl mx-auto bg-white border border-gray-200 rounded-xl shadow-lg hover:shadow-xl transition-shadow duration-200 p-6">
<div class="flex items-center justify-between mb-3">
<h1 class="text-2xl font-semibold text-gray-900">New service population</h1>
</div>

<div class="border-b border-gray-300 mb-6"></div>

<div class="space-y-6">
<div class="mt-4">
<%= render "form", sector: @sector %>
</div>
</div>
</div>
</div>
</div>
37 changes: 37 additions & 0 deletions app/views/sectors/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<div class="min-h-screen py-8">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="max-w-5xl mx-auto bg-white border border-gray-200 rounded-xl shadow-lg hover:shadow-xl transition-shadow duration-200 p-6">
<div class="flex items-center justify-between mb-6">
<!-- Title -->
<h1 class="text-2xl font-semibold text-gray-900">
Service population details
</h1>

<!-- Buttons Group -->
<div class="flex items-center gap-2">
<%= link_to("Index", sectors_path, class: "btn btn-secondary-outline") %>
<% if current_user.super_user? %>
<%= link_to("Edit", edit_sector_path(@sector), class: "btn btn-primary-outline") %>
<% end %>
</div>
</div>

<div class="space-y-6">
<div class="mt-4">
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-3">

<div class="mb-3">
<p class="font-bold text-gray-700">Name:</p>
<p class="text-gray-900"><%= @sector.name %></p>
</div>
<div class="mb-3">
<p class="font-bold text-gray-700">Published:</p>
<p class="text-gray-900"><%= @sector.published %></p>
</div>

</div>
</div>
</div>
</div>
</div>
</div>
Loading