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"