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
18 changes: 18 additions & 0 deletions app/controllers/projects_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ def set_form_variables
@project.build_logo_image if @project.logo_image.blank?

@project_statuses = ProjectStatus.all
@facilitators_array = Facilitator.joins(:user)
.order(:first_name, :last_name)
.map{|f| [f.name, f.user.id] }
@project.project_users = @project.project_users
.includes(:project)
.sort_by { |pu| pu.user.facilitator&.name.to_s.downcase }
end

def set_index_variables
Expand All @@ -97,6 +103,18 @@ def project_params
:inactive, :notes, :agency_type, :agency_type_other, :website_url,
:project_status_id, :location_id, :windows_type_id,
logo_image_attributes: [:id, :file, :_destroy],
sectorable_items_attributes: [
:id,
:sector_id,
:_destroy,
],
project_users_attributes: [
:id,
:user_id,
:inactive,
:title,
:_destroy,
],
addresses_attributes: [
:id,
:address_type,
Expand Down
20 changes: 20 additions & 0 deletions app/helpers/sector_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module SectorHelper
def sector_button(sector, font_size: "text-md")
link_to authenticated_root_path(sector),
class: "group inline-flex items-center gap-2 px-4 py-2
border border-purple-800 text-purple-500 rounded-lg
hover:bg-purple-800 hover:text-white transition-colors duration-200
#{font_size} shadow-sm leading-none whitespace-nowrap" do

# --- Name: stays one line & turns white on hover ---
content_tag(
:span,
sector.name.to_s.truncate(30),
title: sector.name.to_s,
class: "font-semibold text-gray-900 whitespace-nowrap group-hover:text-white"
)
end
end


end
2 changes: 1 addition & 1 deletion app/models/address.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ class Address < ApplicationRecord
scope :active, -> { where(inactive: false) }

def name
"#{street}, #{city}, #{state} #{zip}"
"#{street_address}, #{city}, #{state} #{zip_code}"
end
end
2 changes: 2 additions & 0 deletions app/models/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class Project < ApplicationRecord
# Nested attributes
accepts_nested_attributes_for :logo_image, allow_destroy: true, reject_if: :all_blank
accepts_nested_attributes_for :addresses, allow_destroy: true, reject_if: :all_blank
accepts_nested_attributes_for :sectorable_items, allow_destroy: true, reject_if: :all_blank
accepts_nested_attributes_for :project_users, allow_destroy: true, reject_if: :all_blank

scope :active, -> { where(inactive: false) }

Expand Down
9 changes: 7 additions & 2 deletions app/views/projects/_address_fields.html.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
<div class="nested-fields bg-grey-50 border-gray-200">
<div class="nested-fields rounded-lg bg-gray-50 border-gray-200 p-6">
<div class="text-lg font-semibold text-gray-800 mb-4">
Address <%= "#" + (f.index.to_i + 1).to_s if f.object.persisted? %><%= ": " + f.object.name if f.object.persisted? %>
</div>

<hr class="mb-6 border-gray-200">

<!-- LOCATION + DISTRICT + LOCALITY -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
Expand Down Expand Up @@ -122,5 +127,5 @@
<!-- Remove button -->
<%= link_to_remove_association "✖ Remove",
f,
class: "btn btn-danger-outline whitespace-nowrap" %>
class: "btn btn-danger-outline whitespace-nowrap" if f.object.persisted? %>
</div>
148 changes: 108 additions & 40 deletions app/views/projects/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -105,47 +105,80 @@
class: "rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring focus:ring-blue-200"
} %>

<%= f.input :project_status_id,
as: :select,
collection: @project_statuses,
include_blank: true,
label: "Status",
required: true,
input_html: {
class: "rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring focus:ring-blue-200"
} %>
<% if current_user.super_user? %>
<div class="admin-only bg-blue-100">
<%= f.input :project_status_id,
as: :select,
collection: @project_statuses,
include_blank: true,
label: "Status",
required: true,
input_html: {
class: "rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring focus:ring-blue-200"
} %>
</div>
<% else %>
<div class="text-md font-semibold">
Project status:
</div>
<%= f.object.project_status&.name %>
<% end %>
</div>

<!-- WINDOWS / STATUS / START / END -->
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-6">
<%= f.input :start_date,
label: "Affiliation start date",
as: :string,
input_html: {
type: 'date',
value: f.object.start_date&.strftime('%Y-%m-%d'),
class: "block w-full rounded-md border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500"
} %>
<% if current_user.super_user? %>
<div class="admin-only bg-blue-100">
<%= f.input :start_date,
label: "Affiliation start date",
as: :string,
input_html: {
type: 'date',
value: f.object.start_date&.strftime('%Y-%m-%d'),
class: "block w-full rounded-md border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500"
} %>
</div>
<div class="admin-only bg-blue-100">
<%= f.input :end_date,
label: "Affiliation end date",
as: :string,
input_html: {
type: 'date',
value: f.object.end_date&.strftime('%Y-%m-%d'),
class: "block w-full rounded-md border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500"
} %>
</div>
<% else %>
<div class="">
<div class="text-md font-semibold">
Affiliation start date:
</div>
<%= f.object.start_date&.strftime('%Y-%m-%d') %>
</div>

<%= f.input :end_date,
label: "Affiliation end date",
as: :string,
input_html: {
type: 'date',
value: f.object.end_date&.strftime('%Y-%m-%d'),
class: "block w-full rounded-md border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500"
} %>
<div class="">
<div class="text-md font-semibold">
Affiliation end date:
</div>
<%= f.object.end_date&.strftime('%Y-%m-%d') %>
</div>

<% end %>
<%= f.input :website_url,
label: "Website URL",
as: :string,
input_html: {
class: "rounded-md border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500"
} %>
<%= f.input :internal_id,
label: "Internal Project ID",
input_html: {
class: "rounded-md border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500"
} %>
<% if current_user.super_user? %>
<div class="admin-only bg-blue-100">
<%= f.input :internal_id,
label: "Internal Project ID",
input_html: {
class: "rounded-md border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500"
} %>
</div>
<% end %>
</div>

<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
Expand All @@ -165,21 +198,25 @@
} %>
</div>

<div class="mb-6">
<%= f.input :notes,
as: :text,
label: "Internal Notes",
input_html: {
rows: 3,
class: "rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-200"
} %>
</div>
<% if current_user.super_user? %>
<div class="admin-only bg-blue-100">
<div class="mb-6">
<%= f.input :notes,
as: :text,
label: "Internal Notes",
input_html: {
rows: 3,
class: "rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-200"
} %>
</div>
</div>
<% end %>

<div class="form-group space-y-4">
<div class="font-semibold text-gray-700">
Addresses
</div>
<div class="rounded-lg border border-gray-200 bg-gray-50 p-4 mb-4 shadow-sm">
<div class="rounded-lg border border-gray-200 bg-yellow-50 p-4 mb-4 shadow-sm">
<div class="flex flex-wrap items-center gap-4 p-3">
<%= f.simple_fields_for :addresses do |sfi| %>
<%= render "address_fields", f: sfi %>
Expand All @@ -197,6 +234,37 @@
</div>
</div>

<div class="form-group space-y-4">
<div class="font-semibold text-gray-700">
Facilitator affiliations
</div>
<div class="rounded-lg border border-gray-200 bg-gray-50 p-4 mb-4 shadow-sm">
<% if current_user.super_user? %>
<div class="admin-only bg-blue-100 p-3">
<%= f.fields_for :project_users do |project_user_form| %>
<%= render "project_user_fields",
f: project_user_form %>
<% end %>

<div class="admin-only bg-blue-100 p-3 mt-6">
<%= link_to_add_association "➕ Add Role",
f,
:project_users,
class: "btn btn-secondary-outline" %>
</div>
</div>
<% else %>
<% f.object.user && f.object.user.project_users.each do |pu| %>
<div class="ps-6 mb-2">
<li><%= pu.title || pu.position %> -
<%= facilitator_profile_button(pu.user.facilitator) if pu.persisted? && pu.user.facilitator %>
</li>
</div>
<% end %>
<% end %>
</div>
</div>

<!-- ACTIONS -->
<div class="flex justify-end gap-3">
<% if @project.persisted? && current_user.super_user? %>
Expand Down
44 changes: 44 additions & 0 deletions app/views/projects/_project_user_fields.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<% if current_user.super_user? %>
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 items-start mb-4">

<div>
<%= f.input :user_id,
as: :select,
label: "Facilitator",
collection: @facilitators_array,
include_blank: true,
selected: f.object&.user_id,
input_html: {
class: "block w-full rounded-md border-gray-300 focus:ring-blue-500 focus:border-blue-500"
} %>
</div>

<div>
<%= f.input :title,
as: :text,
input_html: {
rows: 1,
value: f.object&.title || f.object&.position,
} %>
</div>

<div class="flex items-center justify-between py-3 px-6 gap-6 col-span-2">
<div class="flex items-center pt-6 space-x-2">
<%= f.input :inactive,
as: :boolean,
label: "Inactive?",
wrapper_html: { class: "m-0 p-0" },
label_html: { class: "text-sm font-medium text-gray-700 mb-0" },
input_html: { class: "h-4 w-4 text-blue-600 border-gray-300 rounded" } %>
</div>

<%= link_to_remove_association "✖ Remove",
f,
class: "btn btn-danger-outline whitespace-nowrap" if f.object&.persisted? %>
</div>
</div>
<% else %>
<div class="ps-6 mb-4">
<li><%= f.object.project&.name %> (<%= f.object.title || f.object.position %>)</li>
</div>
<% end %>
63 changes: 30 additions & 33 deletions app/views/projects/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -83,42 +83,39 @@
<!-- Info grid -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
<!-- Organization affiliations -->
<% if true || @project.profile_show_facilitator? %>
<div>
<h2 class="text-lg font-semibold text-gray-800 mb-3">Windows facilitators</h2>
<% if @project.project_users.active.any? %>
<ul class="space-y-2">
<% @project.project_users.active.each do |pu| %>
<li>
<%= link_to pu.user.facilitator.name, facilitator_path(pu.user.facilitator),
class: "text-blue-600 hover:underline font-medium" %>
<% if pu.position.present? %>
<span class="text-gray-600">– <%= pu.title.presence || pu.position.humanize %></span>
<% end %>
</li>
<div>
<h2 class="text-lg font-semibold text-gray-800 mb-3">Windows facilitators</h2>
<% if @project.project_users.active.any? %>
<ul class="space-y-2">
<% @project.project_users.active.each do |pu| %>
<li class="whitespace-nowrap">
<%= pu.user.facilitator ? facilitator_profile_button(pu.user.facilitator) : pu.user.name %>
<% if pu.position.present? %>
<span class="text-gray-600">– <%= pu.title.presence || pu.position.humanize %></span>
<% end %>
</li>
<% end %>
</ul>
<% else %>
<p class="text-gray-500 italic">No facilitators listed.</p>
<% end %>
</div>

<!-- Sectors -->
<div>
<h2 class="text-lg font-semibold text-gray-800 mb-3">Sectors served</h2>
<p>
<% if @project.sectorable_items.any? %>
<div class="flex flex-wrap items-center gap-1">
<% @project.sectorable_items.joins(:sector).order("sectors.name").map do |item| %>
<%= sector_button(item.sector) %>
<% end %>
</ul>
</div>
<% else %>
<p class="text-gray-500 italic">No facilitators listed.</p>
<span class="text-gray-500 italic">No sectors selected.</span>
<% end %>
</div>
<% end %>

<!-- Sectors -->
<% if true || @project.profile_show_sectors? %>
<div>
<h2 class="text-lg font-semibold text-gray-800 mb-3">Sectors served</h2>
<p>
<% if @project.sectorable_items.any? %>
<%= @project.sectorable_items.joins(:sector).order("sectors.name").map do |item| %>
<% "#{item.sector.name}#{ " (Leader)" if item.is_leader? }" %>
<% end.join(", ") %>
<% else %>
<span class="text-gray-500 italic">No sectors selected.</span>
<% end %>
</p>
</div>
<% end %>
</p>
</div>

<!-- Contact info -->
<div>
Expand Down
Loading