Skip to content
71 changes: 71 additions & 0 deletions app/controllers/organizations_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
class OrganizationsController < ApplicationController
before_action :authenticate_user!, except: [ :index, :show ]
before_action :set_organization, only: [ :show, :edit, :update, :destroy, :annual_evaluations ]

def index
@organizations = Organization.all
end

def show
end

def new
@organization = Organization.new
end

def edit
end

def create
@organization = Organization.new(organization_params)

if @organization.save
redirect_to @organization, notice: "Organization was successfully created."
else
render :new, status: :unprocessable_entity
end
end

def update
if @organization.update(organization_params)
redirect_to @organization, notice: "Organization was successfully updated."
else
render :edit, status: :unprocessable_entity
end
end

def destroy
@organization.destroy!
redirect_to organizations_url, notice: "Organization was successfully destroyed."
end

def annual_evaluations
@year = params[:year]&.to_i || Date.current.year
@aggregated_responses = @organization.aggregated_annual_evaluation_responses(@year)

# Get available years that have evaluations
all_evaluations = @organization.reports
.joins(form: :form_builder)
.where(form_builders: { name: "Annual Evaluation" })
.distinct

@available_years = all_evaluations.pluck(:created_at).map(&:year).uniq.sort.reverse
end

private

def set_organization
@organization = Organization.find(params[:id])
end

def organization_params
params.require(:organization).permit(
:name, :description, :website_url, :start_date, :end_date,
:agency_type, :agency_type_other, :mission_vision_values,
:internal_id, :filemaker_code, :inactive, :notes,
:project_status_id, :windows_type_id, :location_id,
addresses_attributes: [ :id, :street_address, :city, :state, :zip_code, :country, :_destroy ],
sectorable_items_attributes: [ :id, :sector_id, :_destroy ]
)
end
end
42 changes: 42 additions & 0 deletions app/models/organization.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
class Organization < Project
# Organization is an alias for Project
# This provides a semantic interface for organization-specific functionality

# Get all annual evaluation responses for a specific year
def annual_evaluations_for_year(year)
return Report.none unless year.present?

start_date = Date.new(year.to_i, 1, 1)
end_date = Date.new(year.to_i, 12, 31).end_of_day

reports
.joins(form: :form_builder)
.where(form_builders: { name: "Annual Evaluation" })
.where(created_at: start_date..end_date)
.distinct
end

# Get aggregated responses by form field for a year
def aggregated_annual_evaluation_responses(year)
evaluations = annual_evaluations_for_year(year)
return {} if evaluations.empty?

form_builder = FormBuilder.find_by(name: "Annual Evaluation")
return {} unless form_builder

form = form_builder.forms.first
return {} unless form

# Group responses by form field
form.form_fields.active.order(position: :desc).map do |field|
responses = ReportFormFieldAnswer
.where(report_id: evaluations.pluck(:id), form_field_id: field.id)
.includes(:answer_option, report: :user)

{
form_field: field,
responses: responses
}
end
end
end
66 changes: 66 additions & 0 deletions app/views/organizations/_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<%= form_with(model: organization, local: true) do |form| %>
<% if organization.errors.any? %>
<div class="alert alert-danger">
<h4><%= pluralize(organization.errors.count, "error") %> prohibited this organization from being saved:</h4>
<ul>
<% organization.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>

<div class="form-group mb-3">
<%= form.label :name, class: "form-label" %>
<%= form.text_field :name, class: "form-control", required: true %>
</div>

<div class="form-group mb-3">
<%= form.label :description, class: "form-label" %>
<%= form.text_area :description, class: "form-control", rows: 5 %>
</div>

<div class="form-group mb-3">
<%= form.label :website_url, "Website", class: "form-label" %>
<%= form.url_field :website_url, class: "form-control" %>
</div>

<div class="row">
<div class="col-md-6">
<div class="form-group mb-3">
<%= form.label :start_date, class: "form-label" %>
<%= form.date_field :start_date, class: "form-control" %>
</div>
</div>
<div class="col-md-6">
<div class="form-group mb-3">
<%= form.label :end_date, class: "form-label" %>
<%= form.date_field :end_date, class: "form-control" %>
</div>
</div>
</div>

<div class="form-group mb-3">
<%= form.label :project_status_id, "Status", class: "form-label" %>
<%= form.collection_select :project_status_id, ProjectStatus.all, :id, :name, { prompt: "Select Status" }, { class: "form-control", required: true } %>
</div>

<div class="form-group mb-3">
<%= form.label :agency_type, class: "form-label" %>
<%= form.text_field :agency_type, class: "form-control" %>
</div>

<div class="form-group mb-3">
<%= form.label :notes, class: "form-label" %>
<%= form.text_area :notes, class: "form-control", rows: 3 %>
</div>

<div class="form-group mb-3">
<%= form.check_box :inactive, class: "form-check-input" %>
<%= form.label :inactive, class: "form-check-label ms-2" %>
</div>

<div class="actions mt-4">
<%= form.submit "Save Organization", class: "btn btn-primary" %>
</div>
<% end %>
108 changes: 108 additions & 0 deletions app/views/organizations/annual_evaluations.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<div class="container-fluid">
<div class="row">
<div class="col-12">
<h1 class="mb-4">Annual Evaluations - <%= @organization.name %></h1>

<% if @available_years.any? %>
<div class="mb-4">
<%= form_with url: annual_evaluations_organization_path(@organization), method: :get, local: true do |form| %>
<%= form.label :year, "Select Year:", class: "form-label" %>
<%= form.select :year, @available_years.map { |y| [y, y] }, { selected: @year }, { class: "form-select", style: "max-width: 200px;", onchange: "this.form.submit();" } %>
<% end %>
</div>
<% end %>

<% if @aggregated_responses.present? %>
<div class="card mb-4">
<div class="card-body">
<h2 class="card-title">Responses for <%= @year %></h2>
<p class="text-muted">
Total Evaluations: <%= @organization.annual_evaluations_for_year(@year).count %>
</p>
</div>
</div>

<% @aggregated_responses.each do |data| %>
<% field = data[:form_field] %>
<% responses = data[:responses] %>

<div class="card mb-4">
<div class="card-header bg-light">
<h3 class="h5 mb-0">
<%= field.question %>
<% if field.is_required %>
<span class="text-danger">*</span>
<% end %>
</h3>
<% if field.instructional_hint.present? %>
<small class="text-muted"><%= field.instructional_hint %></small>
<% end %>
</div>

<div class="card-body">
<% if responses.any? %>
<% if field.answer_type&.to_s&.include?("multiple_choice") %>
<%# Multiple choice - show aggregated counts %>
<div class="mb-3">
<strong>Response Summary:</strong>
<ul class="list-group mt-2">
<% response_counts = responses.group_by { |r| r.answer_option&.name || r.response }.transform_values(&:count) %>
<% response_counts.each do |answer, count| %>
<li class="list-group-item d-flex justify-content-between align-items-center">
<%= answer %>
<span class="badge bg-primary rounded-pill"><%= count %></span>
</li>
<% end %>
</ul>
</div>
<% else %>
<%# Free form responses - show all responses %>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>Respondent</th>
<th>Response</th>
<th>Submitted</th>
</tr>
</thead>
<tbody>
<% responses.each do |response| %>
<tr>
<td>
<%= response.report.user.full_name %>
</td>
<td>
<%= simple_format(response.response) %>
</td>
<td>
<%= response.report.created_at.strftime("%m/%d/%Y") %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
<% end %>
<% else %>
<p class="text-muted">No responses for this question.</p>
<% end %>
</div>
</div>
<% end %>
<% else %>
<div class="alert alert-info">
<h4>No Annual Evaluations Found</h4>
<p>There are no annual evaluation responses for <%= @year %> yet.</p>
<% if @available_years.empty? %>
<p>No evaluations have been submitted for this organization.</p>
<% end %>
</div>
<% end %>

<div class="mt-4">
<%= link_to "Back to Organization", @organization, class: "btn btn-secondary" %>
</div>
</div>
</div>
</div>
12 changes: 12 additions & 0 deletions app/views/organizations/edit.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<div class="container-fluid">
<div class="row">
<div class="col-12">
<h1>Edit Organization</h1>

<%= render "form", organization: @organization %>

<%= link_to "Show", @organization, class: "btn btn-secondary mt-3" %>
<%= link_to "Back to Organizations", organizations_path, class: "btn btn-secondary mt-3" %>
</div>
</div>
</div>
41 changes: 41 additions & 0 deletions app/views/organizations/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<div class="container-fluid">
<div class="row">
<div class="col-12">
<h1>Organizations</h1>
<p>Organizations in the AWBW network.</p>

<% if user_signed_in? && current_user.super_user? %>
<%= link_to "New Organization", new_organization_path, class: "btn btn-primary mb-3" %>
<% end %>

<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Status</th>
<th>Start Date</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% @organizations.each do |organization| %>
<tr>
<td><%= link_to organization.name, organization %></td>
<td><%= organization.project_status&.name %></td>
<td><%= organization.start_date&.strftime("%m/%d/%Y") %></td>
<td>
<%= link_to "View", organization, class: "btn btn-sm btn-secondary" %>
<%= link_to "Annual Evaluations", annual_evaluations_organization_path(organization), class: "btn btn-sm btn-info" %>
<% if user_signed_in? && current_user.super_user? %>
<%= link_to "Edit", edit_organization_path(organization), class: "btn btn-sm btn-warning" %>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
</div>
</div>
11 changes: 11 additions & 0 deletions app/views/organizations/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<div class="container-fluid">
<div class="row">
<div class="col-12">
<h1>New Organization</h1>

<%= render "form", organization: @organization %>

<%= link_to "Back to Organizations", organizations_path, class: "btn btn-secondary mt-3" %>
</div>
</div>
</div>
36 changes: 36 additions & 0 deletions app/views/organizations/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<div class="container-fluid">
<div class="row">
<div class="col-12">
<h1><%= @organization.name %></h1>

<div class="card mb-3">
<div class="card-body">
<h5 class="card-title">Organization Details</h5>

<% if @organization.description.present? %>
<p><strong>Description:</strong> <%= simple_format(@organization.description) %></p>
<% end %>

<% if @organization.website_url.present? %>
<p><strong>Website:</strong> <%= link_to @organization.website_url, @organization.website_url, target: "_blank" %></p>
<% end %>

<% if @organization.start_date.present? %>
<p><strong>Start Date:</strong> <%= @organization.start_date.strftime("%m/%d/%Y") %></p>
<% end %>

<p><strong>Status:</strong> <%= @organization.project_status&.name %></p>
</div>
</div>

<div class="mt-3">
<%= link_to "Annual Evaluations", annual_evaluations_organization_path(@organization), class: "btn btn-primary" %>
<% if user_signed_in? && current_user.super_user? %>
<%= link_to "Edit", edit_organization_path(@organization), class: "btn btn-warning" %>
<%= button_to "Delete", @organization, method: :delete, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" }, class: "btn btn-danger" %>
<% end %>
<%= link_to "Back to Organizations", organizations_path, class: "btn btn-secondary" %>
</div>
</div>
</div>
</div>
Loading