generated from dxw/rails-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5fec0e4
commit e586354
Showing
18 changed files
with
555 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# frozen_string_literal: true | ||
|
||
class SubscriptionsController < ApplicationController | ||
include Wicked::Wizard | ||
|
||
steps :contact_details, :contact_verification, :zone_selection, :time_selection, :wrap_up | ||
|
||
def show | ||
session[:subscription_form] = nil if params[:reset] | ||
load | ||
render_wizard | ||
end | ||
|
||
def update | ||
load | ||
case step | ||
when :contact_verification | ||
# Do nothing | ||
else | ||
@form.assign_attributes(subscription_params) | ||
end | ||
session[:subscription_form] = @form.attributes | ||
render_wizard @form | ||
end | ||
|
||
private | ||
|
||
def load | ||
@step_number = current_step_index.to_i + 1 | ||
@current_step = step | ||
@form = SubscriptionForm.new(session[:subscription_form]) | ||
end | ||
|
||
def current_step_index | ||
steps.index(step) | ||
end | ||
|
||
def subscription_params | ||
params[:subscription_form].permit! #.permit(:email, :sms_number, :voice_number, :zone, :time) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import { Controller } from "@hotwired/stimulus"; | ||
import { useDebounce } from "stimulus-use"; | ||
import { geocoding } from "@maptiler/client"; | ||
import * as zones from "../zone_boundaries/zone-boundaries"; | ||
import booleanPointInPolygon from "@turf/boolean-point-in-polygon"; | ||
|
||
export default class SubscriptionController extends Controller { | ||
static targets = ["email", "sms", "voice", "searchField", "searchResults"]; | ||
static debounces = ["search"]; | ||
|
||
connect() { | ||
useDebounce(this); | ||
} | ||
|
||
toggleEmail() { | ||
this.emailTarget.classList.toggle("hidden"); | ||
} | ||
|
||
toggleSms() { | ||
this.smsTarget.classList.toggle("hidden"); | ||
} | ||
|
||
toggleVoice() { | ||
this.voiceTarget.classList.toggle("hidden"); | ||
} | ||
|
||
searchFieldTargetConnected() { | ||
this.maptilerApiKey = this.searchFieldTarget.dataset.maptilerApiKey; | ||
} | ||
|
||
async search() { | ||
console.log("searching..."); | ||
const userInput = this.searchFieldTarget.value; | ||
const coordinates = await this.geoCode(userInput); | ||
const zones = this.findZones(coordinates); | ||
this.displaySearchResults(zones); | ||
} | ||
|
||
async geoCode(location) { | ||
console.log("geocoding..."); | ||
const result = await geocoding.forward(location, { | ||
apiKey: this.maptilerApiKey, | ||
country: ["GB"], | ||
proximity: [-0.116773, 51.510357], | ||
types: [ | ||
"region", | ||
"subregion", | ||
"county", | ||
"joint_municipality", | ||
"joint_submunicipality", | ||
"municipality", | ||
"municipal_district", | ||
"locality", | ||
"neighbourhood", | ||
"place", | ||
"postal_code", | ||
"address", | ||
"road", | ||
"poi", | ||
], | ||
}); | ||
|
||
return result?.features[0]?.geometry?.coordinates; | ||
} | ||
|
||
findZones(point) { | ||
console.log(point); | ||
if (!point) { | ||
console.log("No coordinates found"); | ||
return; | ||
} | ||
|
||
console.log("finding zone..."); | ||
const matches = []; | ||
// Point has to be in the format [longitude, latitude] | ||
for (const [, zone] of Object.entries(zones)) { | ||
if (booleanPointInPolygon(point, zone)) { | ||
matches.push(zone); | ||
} | ||
} | ||
|
||
// Sort by zone level so more specific zones are returned first | ||
matches.sort((a, b) => b.properties.level - a.properties.level); | ||
|
||
return matches; | ||
} | ||
|
||
displaySearchResults(results) { | ||
this.searchResultsTarget.innerHTML = ""; | ||
|
||
if (!results) { | ||
this.searchResultsTarget.innerHTML = "No results found"; | ||
return; | ||
} | ||
|
||
results.forEach((result) => { | ||
const li = document.createElement("li"); | ||
li.textContent = result.properties.name; | ||
li.dataset.action = "click->subscription#selectSearchResult"; | ||
this.searchResultsTarget.appendChild(li); | ||
}); | ||
} | ||
|
||
selectSearchResult(event) { | ||
const zoneName = event.target.textContent; | ||
const checkbox = document.querySelector(`input[value="${zoneName}"]`); | ||
console.log(checkbox) | ||
checkbox.checked = true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
class SubscriptionForm | ||
include ActiveModel::Model | ||
include ActiveModel::Attributes | ||
|
||
attribute :current_step | ||
|
||
attribute :receive_email | ||
attribute :receive_sms | ||
attribute :receive_voice | ||
attribute :email | ||
attribute :sms_number | ||
attribute :voice_number | ||
|
||
attribute :zone_search | ||
attribute :zones | ||
|
||
attribute :time | ||
|
||
attribute :reason | ||
attribute :source | ||
attribute :research | ||
attribute :terms | ||
attribute :privacy | ||
|
||
validate :one_contact_method_present?, if: -> { current_step == "contact_details" } | ||
validates :email, presence: true, if: -> { receive_email && current_step == "contact_details" } | ||
validates :sms_number, presence: true, if: -> { receive_sms && current_step == "contact_details" } | ||
validates :voice_number, presence: true, if: -> { receive_voice && current_step == "contact_details" } | ||
|
||
validate :no_more_than_5_zones?, if: -> { current_step == "zone_selection" } | ||
validates :zones, presence: true, if: -> { current_step == "zone_selection" } | ||
|
||
validates :time, presence: true, if: -> { current_step == "time_selection" } | ||
|
||
validates :terms, acceptance: true, if: -> { current_step == "wrap_up" } | ||
validates :privacy, acceptance: true, if: -> { current_step == "wrap_up" } | ||
|
||
TIMES = [ | ||
['AM', 'Morning – 6am'], | ||
['PM', 'Evening – 6pm'], | ||
] | ||
|
||
SOURCES = [ | ||
[:airtext_application_form, 'airTEXT application form'], | ||
[:poster_on_bus, 'Poster on bus'], | ||
[:poster_on_tube, 'Poster on tube'], | ||
[:mayor_of_london, 'Mayor of London'], | ||
[:tfl_air_quality_alerts, 'TfL air quality alerts'], | ||
[:council_website, 'Council website'], | ||
[:council_magazine, 'Council magazine'], | ||
[:breathe_easy_group, 'Breathe Easy group'], | ||
[:barts_health_nhs_trust, 'Barts Health NHS trust'], | ||
[:islington_primary_schools, 'Islington primary schools'], | ||
[:shine, 'SHINE (Seasonal Health Interventions Network)'], | ||
[:merton_cac, "Merton's Clean Air Campaign"], | ||
[:be_air_aware_campaign, 'Be Air Aware Campaign'], | ||
[:my_doctor, 'My doctor'], | ||
[:local_pharmacist, 'Local pharmacist'], | ||
[:local_council_employee, 'Local council employee'], | ||
[:national_newspaper, 'National newspaper'], | ||
[:local_newspaper, 'Local newspaper'], | ||
[:air_quality_workshop, 'Air Quality Workshop'], | ||
[:a_friend, 'A friend'], | ||
[:tv_radio, 'TV/radio'], | ||
[:web_or_search_engine, 'Web or Search Engine'], | ||
[:twitter, 'Twitter'], | ||
[:facebook, 'Facebook'], | ||
[:other, 'Other'], | ||
] | ||
|
||
def one_contact_method_present? | ||
errors.add(:base, 'You must select at least one contact method') if email.blank? && sms_number.blank? && voice_number.blank? | ||
end | ||
|
||
def no_more_than_5_zones? | ||
return false unless zones.present? | ||
|
||
errors.add(:zones, 'You can select no more than 5 zones') if zones.size > 5 | ||
end | ||
|
||
def save | ||
if current_step == "wrap_up" && valid? | ||
create_subscriptions | ||
else | ||
valid? | ||
end | ||
end | ||
|
||
def modes | ||
[ | ||
("email" if receive_email), | ||
("sms" if receive_sms), | ||
("voicemail" if receive_voice), | ||
].compact | ||
end | ||
|
||
def create_subscriptions | ||
zones.compact.each do |zone| | ||
modes.each do |mode| | ||
create_subscription(zone, mode) | ||
end | ||
end | ||
end | ||
|
||
def create_subscription(zone, mode) | ||
CercSubscriberApiClient.create_subscription( | ||
# subscriber_id: subscriber_id, | ||
zone: zone, | ||
mode: mode, | ||
phone: (sms_number if mode == "sms") || (voice_number if mode == "voice"), | ||
email: (email if mode == "email"), | ||
ampm: time, | ||
subscriber_details: { | ||
"whySignup" => reason, | ||
"howHeard" => source, | ||
"allowContact" => research, | ||
} | ||
) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.