Skip to content

Commit

Permalink
Create routes wizard logic (#4443)
Browse files Browse the repository at this point in the history
* WIP routes wizard logic

* Completed matching logic for each route into teaching

* Lint and exclude from orphan variables check

* Ammend logic to support multiple answers to a question

* WIP move logic to routes class

* WIP adding tests

* WIP adding tests

* Add results box component

* Add basic layout to completed page and add results boxes

* Remove substitute values from most fields in results box

* Amend routes mapping

* Added not yet answers for routes mapping

* Remove two routes
  • Loading branch information
spencerldixon authored Jan 15, 2025
1 parent 2bf0f62 commit cd6ba50
Show file tree
Hide file tree
Showing 10 changed files with 257 additions and 15 deletions.
10 changes: 5 additions & 5 deletions app/components/content/results_box_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ class ResultsBoxComponent < ViewComponent::Base
def initialize(heading:, fee:, course_length:, funding:, text:, link_text:, link_target:, title: nil, border_color: :grey)
super

@title = substitute_values(title)
@heading = substitute_values(heading)
@fee = substitute_values(fee)
@course_length = substitute_values(course_length)
@funding = substitute_values(funding)
@title = title
@heading = heading
@fee = fee
@course_length = course_length
@funding = funding
@text = substitute_values(text)
@link_text = link_text
@link_target = link_target
Expand Down
10 changes: 9 additions & 1 deletion app/controllers/routes_into_teaching/steps_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ class StepsController < ApplicationController
before_action :set_step_page_title, only: %i[show update]
before_action :noindex, if: :noindex?

layout "registration"
layout :resolve_layout

def completed
@results = RoutesIntoTeaching::Routes.recommended(session[:routes_into_teaching])
end

private

Expand Down Expand Up @@ -45,5 +49,9 @@ def set_step_page_title
@page_title += ", #{@current_step.title.downcase} step"
end
end

def resolve_layout
action_name == "completed" ? "minimal" : "registration"
end
end
end
20 changes: 20 additions & 0 deletions app/models/routes_into_teaching/routes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module RoutesIntoTeaching
class Routes
def self.all
YAML.load_file(Rails.root.join("config/routes_into_teaching.yml"))["routes"]
end

def self.recommended(answers_hash = {})
all.select do |teaching_route|
next false if teaching_route["matches"].blank?

teaching_route["matches"].all? do |matching_rule|
question_id = matching_rule["question"]
matching_answers = matching_rule["answers"]

matching_answers.include?("*") || matching_answers.include?(answers_hash[question_id])
end
end
end
end
end
4 changes: 2 additions & 2 deletions app/models/routes_into_teaching/steps/undergraduate_degree.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
module RoutesIntoTeaching::Steps
class UndergraduateDegree < GITWizard::Step
attribute :has_undergraduate_degree
attribute :undergraduate_degree

validates :has_undergraduate_degree, presence: true
validates :undergraduate_degree, presence: true

def options
option_struct = Struct.new(:answer, :text, keyword_init: true)
Expand Down
4 changes: 2 additions & 2 deletions app/models/routes_into_teaching/steps/unqualified_teacher.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
module RoutesIntoTeaching::Steps
class UnqualifiedTeacher < GITWizard::Step
attribute :has_worked_as_unqualified_teacher
attribute :unqualified_teacher

validates :has_worked_as_unqualified_teacher, presence: true
validates :unqualified_teacher, presence: true

def seen?
false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<% @page_title = "Do you have an undergraduate degree?" %>

<%= f.govuk_collection_radio_buttons :has_undergraduate_degree, @wizard.find_current_step.options, :answer, :text,
<%= f.govuk_collection_radio_buttons :undergraduate_degree, @wizard.find_current_step.options, :answer, :text,
legend: { tag: "h1", text: @page_title },
hint: { text: "You'll find routes into teaching based on your circumstances" }
%>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<% @page_title = "Have you worked as an unqualified teacher?" %>

<%= f.govuk_collection_radio_buttons :has_worked_as_unqualified_teacher, [["Yes"], ["No"]], :first, :first,
<%= f.govuk_collection_radio_buttons :unqualified_teacher, [["Yes"], ["No"]], :first, :first,
legend: { tag: "h1", text: @page_title },
hint: { text: "You'll find routes into teaching based on your circumstances" }
%>
29 changes: 26 additions & 3 deletions app/views/routes_into_teaching/steps/completed.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
<h2>You told us that you:</h2>
<%= render Content::LandingHeroComponent.new(
title: "Routes into teaching",
colour: "pastel yellow-yellow",
) %>

<p>You can <%= link_to "change your answers", routes_into_teaching_steps_path %> if you need to.</p>
<section class="container">
<div class="row">
<h2>You told us that you:</h2>

<%= session[:routes_into_teaching].inspect %>
<p>You can <%= link_to "change your answers", routes_into_teaching_steps_path %> if you need to.</p>
</div>

<div class="row">
<% @results.each do |result| %>
<div class="col-space-s">
<%= render Content::ResultsBoxComponent.new(
heading: result["title"],
fee: result["course_fee"],
course_length: result["course_length"],
funding: result["funding"],
text: result["description"],
link_text: "Find out more",
link_target: "/steps-to-become-a-teacher",
) %>
</div>
<% end %>
</div>
</section>
104 changes: 104 additions & 0 deletions config/routes_into_teaching.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
routes:
- title: Postgraduate initial teacher training with fees
course_length: 9 months (full time) or up to 2 years (part time)
course_fee: "Yes"
funding: Scholarships or bursaries, as well as student loans, are available if you’re eligible
description: Postgraduate teacher training combines theoretical learning with at least 2 classroom placements in schools. Over your course, you’ll get the experience and knowledge you need to get qualified teacher status (QTS). On some courses, you can also combine QTS with a postgraduate certificate in education (PGCE).
matches:
- question: undergraduate_degree
answers: ["Yes", "Not yet"]
- question: unqualified_teacher
answers: ["*"]
- question: location
answers: ["*"]

- title: Postgraduate initial teacher training with a salary
course_length: 9 months
course_fee: Varies
funding: Not available
description: Salaried teacher training allows you to earn an unqualified teacher’s salary while you train towards qualified teacher status (QTS). You’ll still do some theoretical learning, but most of your time will be spent in school placements. These courses are in high demand and very competitive, and training providers may want you to have significant teaching or school experience. The main salaried courses include School Direct salaried and postgraduate teaching apprenticeships (PGTA
matches:
- question: undergraduate_degree
answers: ["Yes", "Not yet"]
- question: unqualified_teacher
answers: ["*"]
- question: location
answers: ["*"]

- title: Teach First Training Programme
course_length: 24 months
course_fee: "No"
funding: Not available
description: Teach First is a charitable organisation that delivers an employment-based route to teaching for high performing graduates and career changers. You’ll earn a salary while working towards qualified teacher status (QTS) with a postgraduate certificate in education (PGCE).
matches:
- question: undergraduate_degree
answers: ["Yes", "Not yet"]
- question: unqualified_teacher
answers: ["*"]
- question: location
answers: ["*"]

- title: Assessment only route
course_length: 12 weeks
course_fee: "Yes"
funding: Not available
description: If you’ve worked as an unqualified teacher, you may be able to get qualified teacher status (QTS) through an assessment only programme. With this route, you do not need to do any further training. Instead, you’ll undertake a series of assessments. This may include lesson observations, providing a portfolio of evidence to show you meet the teachers’ standards, or written assessments. This will vary by your provider
matches:
- question: undergraduate_degree
answers: ["Yes", "Not yet"]
- question: unqualified_teacher
answers: ["Yes"]
- question: location
answers: ["*"]

- title: Undergraduate initial teacher training
course_length: up to 4 years
course_fee: "Yes"
funding: "No"
description: These courses are in high demand and very competitive, so it’s important to apply as soon as you can if you’re eligible.standards, or written assessments. This will vary by your provider.
matches:
- question: undergraduate_degree
answers: ["No"]
- question: unqualified_teacher
answers: ["*"]
- question: location
answers: ["*"]

- title: International qualified teacher status (iQTS)
course_length: 4 months
course_fee: "Yes"
funding: "No"
description: International qualified teacher status (iQTS) is a teaching qualification backed by the UK government. iQTS meets the same high standards as English qualified teacher status (QTS) and leads to the automatic award of QTS. You can train where you live and work, with no need to visit the UK.
matches:
- question: undergraduate_degree
answers: ["Yes", "Not yet"]
- question: unqualified_teacher
answers: ["*"]
- question: location
answers: ["No"]

- title: Teacher degree apprenticeship
course_length: 4 years
course_fee: No - you will be paid a salary
funding: "No"
description: These courses are in high demand and very competitive, so it’s important to apply as soon as you can if you’re eligible.
matches:
- question: undergraduate_degree
answers: ["No"]
- question: unqualified_teacher
answers: ["*"]
- question: location
answers: ["*"]

- title: Undergraduate degree (followed by postgraduate teacher training)
course_length: 4 years
course_fee: "Yes"
funding: "No"
description:
matches:
- question: undergraduate_degree
answers: ["No"]
- question: unqualified_teacher
answers: ["*"]
- question: location
answers: ["*"]
87 changes: 87 additions & 0 deletions spec/models/routes_into_teaching/routes_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
require "rails_helper"

RSpec.describe RoutesIntoTeaching::Routes, type: :model do
let(:yaml) do
{
"routes" => [
{
"title" => "Route 1",
"matches" => [
{ "question" => "undergraduate_degree", "answers" => %w[Yes] },
{ "question" => "unqualified_teacher", "answers" => ["*"] },
{ "question" => "location", "answers" => %w[Yes] },
],
},
{
"title" => "Route 2",
"matches" => [
{ "question" => "undergraduate_degree", "answers" => %w[Yes] },
{ "question" => "unqualified_teacher", "answers" => %w[No] },
{ "question" => "location", "answers" => %w[No] },
],
},
],
}
end

let(:answers) do
{
"undergraduate_degree" => "Yes",
"unqualified_teacher" => "Yes",
"location" => "Yes",
}
end

before { allow(YAML).to receive(:load_file).and_return(yaml) }

describe ".all" do
subject { described_class.all }

it "returns all routes from the YAML configuration" do
expect(subject.size).to eq(2)
expect(subject).to eq(yaml["routes"])
end
end

describe ".recommended" do
subject { described_class.recommended(answers) }

context "when all matching rules are satisfied" do
it "returns routes that match all criteria" do
expect(subject.size).to eq(1)
expect(subject.map { |r| r["title"] }).to contain_exactly(
"Route 1",
)
end
end

context "when some matching rules are not satisfied" do
it "filters out routes that do not match all criteria" do
answers["location"] = "No"
expect(subject).to be_empty
end
end

context "with a wildcard matching rule" do
it "matches Yes answers" do
answers["unqualified_teacher"] = "Yes"
expect(subject.size).to eq(1)
expect(subject.first["title"]).to eq("Route 1")
end

it "matches No answers" do
answers["unqualified_teacher"] = "No"
expect(subject.size).to eq(1)
expect(subject.first["title"]).to eq("Route 1")
end
end

context "with missing answers" do
let(:answers) { { "location" => "Yes" } }

it "does not recommend routes with missing required answers" do
expect(subject).to be_empty
end
end
end
end

0 comments on commit cd6ba50

Please sign in to comment.