diff --git a/app/assets/images/donate-icon.svg b/app/assets/images/donate-icon.svg
new file mode 100644
index 000000000..71d0bb8ce
--- /dev/null
+++ b/app/assets/images/donate-icon.svg
@@ -0,0 +1,7 @@
+
diff --git a/app/assets/images/volunteer-icon.svg b/app/assets/images/volunteer-icon.svg
new file mode 100644
index 000000000..3e7383446
--- /dev/null
+++ b/app/assets/images/volunteer-icon.svg
@@ -0,0 +1,8 @@
+
diff --git a/app/components/map_left_popup/component.html.slim b/app/components/map_left_popup/component.html.slim
index 0a5355738..aaee50f6b 100644
--- a/app/components/map_left_popup/component.html.slim
+++ b/app/components/map_left_popup/component.html.slim
@@ -1,5 +1,5 @@
div class="relative flex flex-col gap-2 p-7 bg-white rounded-6px" id="loc_#{@result.id}_popup" data-places-target="popup"
- div class="flex items-start gap-1"
+ div class="flex items-start gap-1 mb-3"
= image_tag @result.organization.logo, class: "flex-shrink-0 w-1/5 h-1/5 mt-1"
div class="flex flex-col ml-2"
div
@@ -20,7 +20,12 @@ div class="relative flex flex-col gap-2 p-7 bg-white rounded-6px" id="loc_#{@res
button type="button" data-action="click->places#hidePopup" class="absolute top-3 right-3" aria-label="close"
= inline_svg_tag "x-icon.svg", class: "w-3 h-3", aria_hidden: true
- div class=" pt-4 my-4 border-t border-gray-8"
+
+ // Donate and Volunteer buttons
+ - if has_donation_or_volunteer_link?(@result)
+ = render "locations/donate_volunteer_buttons", location: @result, container_styles: "flex gap-x-4 w-full pt-5 pb-3 border-t border-gray-8"
+
+ div class="pt-4 mb-4 border-t border-gray-8"
= render DiscoverNonprofitCard::ActionsMenu::Component.new(user: @current_user, location: @result)
div class="text-left pt-4 border-t border-gray-8"
diff --git a/app/components/map_left_popup/component.rb b/app/components/map_left_popup/component.rb
index d4f49a05f..a7d6709f3 100644
--- a/app/components/map_left_popup/component.rb
+++ b/app/components/map_left_popup/component.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
module MapLeftPopup
class Component < ApplicationViewComponent
+ include LocationsHelper
+
def initialize(result:, current_user: false)
@result = result
@current_user = current_user
diff --git a/app/controllers/organizations_controller.rb b/app/controllers/organizations_controller.rb
index d6af5c89a..91cc9a543 100644
--- a/app/controllers/organizations_controller.rb
+++ b/app/controllers/organizations_controller.rb
@@ -90,7 +90,7 @@ def organization_params
.permit(:name, :second_name, :ein_number, :irs_ntee_code, :website, :scope_of_work,
:mission_statement_en, :mission_statement_es, :vision_statement_en, :logo,
:vision_statement_es, :tagline_en, :tagline_es, :email, :phone_number, :active,
- :verified, :donation_link, :volunteer_availability,
+ :verified, :donation_link, :volunteer_availability, :volunteer_link,
social_media_attributes: %i[facebook instagram twitter linkedin youtube blog id],
tags_attributes: [],
locations_attributes: [:id, :name, :address, :latitude, :longitude, :website, :po_box, :public_address, :youtube_video_link,
diff --git a/app/dashboards/organization_dashboard.rb b/app/dashboards/organization_dashboard.rb
index 2c19e1184..4993b638c 100644
--- a/app/dashboards/organization_dashboard.rb
+++ b/app/dashboards/organization_dashboard.rb
@@ -39,6 +39,7 @@ class OrganizationDashboard < Administrate::BaseDashboard
active: Field::Boolean,
verified: Field::Boolean,
donation_link: Field::String,
+ volunteer_link: Field::String,
volunteer_availability: Field::Boolean,
organization_causes: Field::NestedHasMany
}.freeze
@@ -77,6 +78,7 @@ class OrganizationDashboard < Administrate::BaseDashboard
organization_beneficiaries
tags
donation_link
+ volunteer_link
volunteer_availability
social_media
locations
@@ -105,6 +107,7 @@ class OrganizationDashboard < Administrate::BaseDashboard
tags
donation_link
volunteer_availability
+ volunteer_link
organization_causes
social_media
locations
diff --git a/app/decorators/application_decorator.rb b/app/decorators/application_decorator.rb
index 169db66ad..105d1393a 100644
--- a/app/decorators/application_decorator.rb
+++ b/app/decorators/application_decorator.rb
@@ -9,8 +9,13 @@ class ApplicationDecorator < Draper::Decorator
# end
def website
- return nil if object.website.blank?
- uri = URI(object.website)
+ object.decorate.url(object.website)
+ end
+
+ def url(raw_url)
+ return nil if raw_url.blank?
+
+ uri = URI(raw_url)
if uri.instance_of?(URI::Generic)
split = uri.to_s.split('/')
if split.size > 1
diff --git a/app/decorators/organization_decorator.rb b/app/decorators/organization_decorator.rb
index 0d3eb7df6..5b89f1e66 100644
--- a/app/decorators/organization_decorator.rb
+++ b/app/decorators/organization_decorator.rb
@@ -1,4 +1,11 @@
class OrganizationDecorator < ApplicationDecorator
delegate_all
+ def donation_link
+ object.decorate.url(object.donation_link)
+ end
+
+ def volunteer_link
+ object.decorate.url(object.volunteer_link)
+ end
end
diff --git a/app/helpers/locations_helper.rb b/app/helpers/locations_helper.rb
index 232cee2da..bb390f500 100644
--- a/app/helpers/locations_helper.rb
+++ b/app/helpers/locations_helper.rb
@@ -32,4 +32,9 @@ def title_link(turbo_frame, id, title)
end
end
end
+
+ def has_donation_or_volunteer_link?(location)
+ location.organization.donation_link.present? ||
+ (location.organization.volunteer_availability? && location.organization.volunteer_link.present?)
+ end
end
diff --git a/app/javascript/stylesheets/application.scss b/app/javascript/stylesheets/application.scss
index 35613c5cd..967bc6959 100644
--- a/app/javascript/stylesheets/application.scss
+++ b/app/javascript/stylesheets/application.scss
@@ -8,6 +8,10 @@
.disabled-icon path {
fill: #D3DCE6;
}
+
+ .centered-flex {
+ @apply flex items-center justify-center;
+ }
}
.scroll-mt-25 {
diff --git a/app/models/concerns/organization_validator.rb b/app/models/concerns/organization_validator.rb
index 55a338592..1e0271f4f 100644
--- a/app/models/concerns/organization_validator.rb
+++ b/app/models/concerns/organization_validator.rb
@@ -8,6 +8,8 @@ def validate(record)
single_main_location
at_least_one_main_location
valid_website_url
+ valid_donation_url
+ valid_volunteer_url
end
private
@@ -21,10 +23,22 @@ def at_least_one_main_location
end
def valid_website_url
- return true if record.website.blank?
- url = URI.parse(record.website) rescue false
- unless url.kind_of?(URI::HTTP) || url.kind_of?(URI::HTTPS) || url.kind_of?(URI::Generic)
- record.errors.add(:website, 'URL incorrect format')
+ valid_url(record.website, :website)
+ end
+
+ def valid_donation_url
+ valid_url(record.donation_link, :donation_link)
+ end
+
+ def valid_volunteer_url
+ valid_url(record.volunteer_link, :volunteer_link)
+ end
+
+ def valid_url(raw_url, attribute)
+ return true if raw_url.blank?
+ url = URI.parse(raw_url) rescue false
+ unless url.kind_of?(URI::HTTP) || url.kind_of?(URI::HTTPS) || url.kind_of?(URI::Generic)
+ record.errors.add(attribute, 'URL incorrect format')
end
end
end
diff --git a/app/views/locations/_donate_volunteer_buttons.html.slim b/app/views/locations/_donate_volunteer_buttons.html.slim
new file mode 100644
index 000000000..0f95226d7
--- /dev/null
+++ b/app/views/locations/_donate_volunteer_buttons.html.slim
@@ -0,0 +1,21 @@
+div class=local_assigns[:container_styles]
+ - if local_assigns[:location].organization.donation_link.present?
+ = content_tag(\
+ :a,\
+ href: local_assigns[:location].organization.decorate.donation_link,\
+ class: "centered-flex w-full gap-2 py-3 border-0 rounded-md font-bold transition-colors text-indigo-700 bg-indigo-100 hover:bg-indigo-200",\
+ target: "_blank",\
+ ) do
+ = image_tag "donate-icon.svg", class: "w-7 h-7"
+ | Donate
+
+ - if local_assigns[:location].organization.volunteer_availability? && local_assigns[:location].organization.volunteer_link.present?
+ = content_tag(\
+ :a,\
+ href: local_assigns[:location].organization.decorate.volunteer_link,\
+ class: "centered-flex w-full gap-2 p-3 border-0 rounded-md font-bold transition-colors text-indigo-700 bg-seafoam hover:bg-electric-teal",\
+ target: "_blank"\
+ ) do
+ = image_tag "volunteer-icon.svg", class: "w-7 h-7"
+ | Volunteer
+
diff --git a/app/views/locations/show.html.slim b/app/views/locations/show.html.slim
index 04e0a7b41..9a42a36e9 100644
--- a/app/views/locations/show.html.slim
+++ b/app/views/locations/show.html.slim
@@ -115,10 +115,9 @@ div class=""
- if @location.social_media.present?
div class="border-t border-gray-8 my-7"
= render SocialMedia::Component.new(social_media: @location.social_media)
- - if @location.organization.donation_link.present?
- div class="border-t border-gray-8 my-7"
- a href=@location.organization.donation_link class="flex items-center justify-center px-8 py-3 border border-transparent text-base font-medium rounded-md text-indigo-700 bg-indigo-100 hover:bg-indigo-200" target="_blank"
- | Donate
+ // Donate and volunteer links
+ - if has_donation_or_volunteer_link?(@location)
+ = render "locations/donate_volunteer_buttons", location: @location, container_styles: "flex flex-col gap-y-4 pt-7 border-t border-gray-8"
- if @location.youtube_video_link.present?
div class="flex flex-col items-center p-5 text-center"
@@ -157,8 +156,11 @@ div class=""
| -
| #{@location.decorate.closed_office_hours_display}
-
+ // Aside Section
div class="flex-col flex-grow-0 hidden w-full bg-white rounded h-min-content sm:flex md:max-w-402px px-11 md:p-7"
+ - if has_donation_or_volunteer_link?(@location)
+ = render "locations/donate_volunteer_buttons", location: @location, container_styles: "flex flex-col gap-y-4 pb-7 mb-7 border-b border-gray-8"
+
h3 class="text-sm font-bold uppercase mb-3.5"
| Causes
= render CausesList::Component.new( \
@@ -185,7 +187,3 @@ div class=""
- if @location.social_media.present?
div class="border-t border-gray-8 my-7"
= render SocialMedia::Component.new(social_media: @location.social_media)
- - if @location.organization.donation_link.present?
- div class="border-t border-gray-8 my-7"
- a href=@location.organization.donation_link class="flex items-center justify-center px-8 py-3 border border-transparent text-base font-medium rounded-md text-indigo-700 bg-indigo-100 hover:bg-indigo-200" target="_blank"
- | Donate
diff --git a/app/views/organizations/edit.html.slim b/app/views/organizations/edit.html.slim
index f694a9bef..9356dec57 100644
--- a/app/views/organizations/edit.html.slim
+++ b/app/views/organizations/edit.html.slim
@@ -82,17 +82,28 @@ div class="w-full h-full bg-grey-9"
= f.label :donation_link, class: "block text-sm text-gray-3 font-medium"
= f.text_field :donation_link, { class: "block h-46px mt-1 h-full w-full py-0 px-4 rounded-6px border-gray-5 text-base text-gray-3 focus:ring-blue-medium focus:border-blue-medium" }
- fieldset class="col-span-12 lg:col-span-7 md:col-span-6"
+ div class="hidden col-span-3 md:flex"
+
+ fieldset class="col-span-12 lg:col-span-7 md:col-span-6" data-controller="toggle"
legend class="text-sm font-medium leading-4 text-gray-2"
| Do you have volunteer opportunities available?
div class='flex items-center gap-12 mt-3'
div class="flex items-center gap-2"
- = f.radio_button :volunteer_availability, true, class: "focus:ring-0 focus:ring-transparent"
+ = f.radio_button :volunteer_availability, true, class: "focus:ring-0 focus:ring-transparent", data: { action: "toggle#show" }
= f.label :volunteer_availability_true, "Yes", class: "text-sm text-black"
div class="flex items-center gap-2"
- = f.radio_button :volunteer_availability, false, class: "focus:ring-0 focus:ring-transparent"
+ = f.radio_button :volunteer_availability, false, class: "focus:ring-0 focus:ring-transparent", data: { action: "toggle#hide" }
= f.label :volunteer_availability_false, "No", class: "text-sm text-black"
+ div class="mt-6 #{f.object.volunteer_availability? ? '' : 'hidden'}" data-toggle-target="toggleable"
+ div class="text-sm text-gray-4 mb-1"
+ p class="mb-1"
+ | If "Yes" is indicated but no link is provided, then only the volunteer tag appears (no volunteer button).
+ p If "Yes" is indicated and a link is provided, then both the volunteer tag and button appear.
+ div class="mt-2"
+ = f.label :volunteer_link, class: "block text-sm text-gray-3 font-medium"
+ = f.text_field :volunteer_link, { class: "block h-46px mt-1 h-full w-full py-0 px-4 rounded-6px border-gray-5 text-base text-gray-3 focus:ring-blue-medium focus:border-blue-medium" }
+
div class="my-4 border-t mt-6 border-t-blue-pale"
section class="mt-6 text-gray-2" data-controller="toggle"
h3 class="text-lg font-medium leading-7 text-blue-medium flex items-center"
diff --git a/db/migrate/20231006165935_add_volunteer_link_to_organizations.rb b/db/migrate/20231006165935_add_volunteer_link_to_organizations.rb
new file mode 100644
index 000000000..b3b09c176
--- /dev/null
+++ b/db/migrate/20231006165935_add_volunteer_link_to_organizations.rb
@@ -0,0 +1,5 @@
+class AddVolunteerLinkToOrganizations < ActiveRecord::Migration[6.1]
+ def change
+ add_column :organizations, :volunteer_link, :string
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 925ec252f..ed0020636 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2023_09_22_225804) do
+ActiveRecord::Schema.define(version: 2023_10_06_165935) do
# These are extensions that must be enabled in order to support this database
enable_extension "fuzzystrmatch"
@@ -257,6 +257,7 @@
t.boolean "verified", default: false
t.string "donation_link"
t.boolean "volunteer_availability", default: false, null: false
+ t.string "volunteer_link"
t.index ["creator_type", "creator_id"], name: "index_organizations_on_creator"
t.index ["ein_number"], name: "index_organizations_on_ein_number", unique: true
t.index ["mission_statement_en"], name: "index_organizations_on_mission_statement_en"