Skip to content

Commit

Permalink
Merge branch 'main' into feature/LGA-3554-HLPAS-user-journey
Browse files Browse the repository at this point in the history
  • Loading branch information
BenMillar-MOJ committed Mar 11, 2025
2 parents 4aaf3e3 + 5099801 commit c58c3dc
Show file tree
Hide file tree
Showing 24 changed files with 1,252 additions and 66 deletions.
37 changes: 17 additions & 20 deletions app/contact/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
ContactRadioInput,
ContactCheckboxInput,
ContactSelectField,
ContactTextInput,
)
from wtforms.fields import SubmitField
from app.categories.widgets import CategoryCheckboxInput
Expand Down Expand Up @@ -560,26 +561,6 @@ def get_callback_time(self) -> datetime | None:

return None

@staticmethod
def format_callback_time(
start_time: datetime, callback_duration: timedelta = timedelta(minutes=30)
) -> str | None:
"""Helper function to format the callback time string.
Returns:
str | None: formatted callback time string in the form of "Friday, 3 January at 09:00 - 09:30"
"""
if not start_time or not isinstance(start_time, datetime):
return None
end_time = start_time + callback_duration

formatted_start_date = start_time.strftime(
"%A, %d %B at %H:%M"
) # E.g. Monday, 1 January at 09:00
formatted_end_time = end_time.strftime("%H:%M") # E.g. 09:30

return f"{formatted_start_date} - {formatted_end_time}"

def get_payload(self) -> dict:
"""Returns the contact payload."""

Expand Down Expand Up @@ -635,3 +616,19 @@ def get_payload(self) -> dict:
payload["requires_action_at"] = requires_action_at

return payload


class ConfirmationEmailForm(FlaskForm):
email = StringField(
_("Receive this confirmation by email"),
widget=ContactTextInput(
heading_class="govuk-fieldset__legend--s",
hint_text=_("We will use this to send your reference number."),
),
validators=[
Length(max=255, message=_("Your address must be 255 characters or less")),
Email(message=_("Enter a valid email address")),
InputRequired(message=_("Tell us what email address to send to")),
],
)
submit = SubmitField(_("Send"), widget=GovSubmitInput())
23 changes: 23 additions & 0 deletions app/contact/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from datetime import datetime, timedelta
from app.contact import bp


@bp.app_template_filter("format_callback_time")
def format_callback_time(
start_time: datetime, callback_duration: timedelta = timedelta(minutes=30)
) -> str | None:
"""Helper function to format the callback time string.
Returns:
str | None: formatted callback time string in the form of "Friday, 3 January at 09:00 - 09:30"
"""
if not start_time or not isinstance(start_time, datetime):
return None
end_time = start_time + callback_duration

formatted_start_date = start_time.strftime(
"%A, %-d %B at %H:%M"
) # E.g. Monday, 1 January at 09:00
formatted_end_time = end_time.strftime("%H:%M") # E.g. 09:30

return f"{formatted_start_date} - {formatted_end_time}"
4 changes: 2 additions & 2 deletions app/contact/notify/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from app import get_locale
from app.contact.notify.templates import GOVUK_NOTIFY_TEMPLATES
from app.contact.forms import ContactUsForm
from app.contact.helpers import format_callback_time

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -92,7 +92,7 @@ def generate_confirmation_email_data(
third_party_phone_number: str | None = None,
) -> (str, str):
"""Generates the data used in the sending of the confirmation Gov Notify emails."""
formatted_callback_time = ContactUsForm.format_callback_time(callback_time)
formatted_callback_time = format_callback_time(callback_time)
callback_requested = callback_time is not None

template_id = ""
Expand Down
10 changes: 4 additions & 6 deletions app/contact/urls.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from app.contact import bp
from app.contact.address_finder.widgets import FormattedAddressLookup
from app.contact.views import ContactUs, ReasonForContacting
from flask import render_template, jsonify
from flask import jsonify
import logging
from app.contact.views import ConfirmationPage

logger = logging.getLogger(__name__)

Expand All @@ -13,11 +14,6 @@
)


@bp.route("/confirmation", methods=["GET"])
def confirmation():
return render_template("contact/confirmation.html")


@bp.route("/addresses/<postcode>", methods=["GET"])
def geocode(postcode):
"""Lookup addresses with the specified postcode"""
Expand All @@ -39,3 +35,5 @@ def geocode(postcode):
"eligible", template="contact/eligible.html", attach_eligiblity_data=True
),
)

bp.add_url_rule("/confirmation", view_func=ConfirmationPage.as_view("confirmation"))
44 changes: 43 additions & 1 deletion app/contact/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
from flask.views import View
from app.contact.forms import ContactUsForm, ReasonsForContactingForm
from app.contact.forms import (
ContactUsForm,
ReasonsForContactingForm,
ConfirmationEmailForm,
)
import logging
from flask import session, render_template, request, redirect, url_for
from app.api import cla_backend
Expand Down Expand Up @@ -79,10 +83,12 @@ def dispatch_request(self):
case_ref = session.get("case_reference")
callback_time = session.get("callback_time")
contact_type = session.get("contact_type")
category = session.get("category")
session.clear()
session["case_reference"] = case_ref
session["callback_time"] = callback_time
session["contact_type"] = contact_type
session["category"] = category
return redirect(url_for("contact.confirmation"))
return render_template(self.template, form=form, form_progress=form_progress)

Expand All @@ -101,3 +107,39 @@ def _attach_rfc_to_case(case_ref: str, rfc_ref: str):
"case": case_ref,
},
)


class ConfirmationPage(View):
template = "contact/confirmation.html"
methods = ["GET", "POST"]

@classmethod
def get_context(cls):
return {
"case_reference": session.get("case_reference"),
"callback_time": session.get("callback_time"),
"contact_type": session.get("contact_type"),
"category": session.get("category", {}),
}

def dispatch_request(self):
form = ConfirmationEmailForm()
context = self.get_context()
email_sent = False

if form.validate_on_submit():
notify.create_and_send_confirmation_email(
email_address=form.email.data,
case_reference=context["case_reference"],
callback_time=context["callback_time"],
contact_type=context["contact_type"],
)
email_sent = True

return render_template(
self.template,
form=form,
confirmation_email=form.email.data if email_sent else None,
email_sent=email_sent,
**context,
)
10 changes: 9 additions & 1 deletion app/contact/widgets.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
from govuk_frontend_wtf.wtforms_widgets import GovRadioInput, GovCheckboxesInput
from govuk_frontend_wtf.wtforms_widgets import (
GovRadioInput,
GovCheckboxesInput,
GovTextInput,
)
from app.means_test.widgets import MeansTestInputField
from wtforms import SelectField

Expand All @@ -15,3 +19,7 @@ class ContactSelectField(SelectField):
def pre_validate(self, form):
"""Override to prevent WTForms' internal choice validation"""
pass


class ContactTextInput(MeansTestInputField, GovTextInput):
pass
7 changes: 6 additions & 1 deletion app/main/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,12 @@ def cookies():

@bp.route("/privacy", methods=["GET"])
def privacy():
return render_template("privacy.html")
return render_template("main/privacy.html")


@bp.route("/online-safety")
def online_safety():
return render_template("main/online-safety.html")


@bp.route("/session-expired", methods=["GET"])
Expand Down
5 changes: 4 additions & 1 deletion app/means_test/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ def map_gov_params(self, field, **kwargs):
item["checked"] = True

label_class = self.heading_class
params["fieldset"]["legend"]["classes"] = label_class
if "fieldset" in params:
params["fieldset"]["legend"]["classes"] = label_class
else:
params["label"]["classes"] = label_class
return params


Expand Down
27 changes: 27 additions & 0 deletions app/static/src/scss/confirmation.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.confirmation-inset {
background: govuk-colour("white");
color: $govuk-text-colour;
padding: 20px;
margin: 20px 0 0;
}

@media print {
.confirmation-actions,
.confirmation-email-form {
display: none;
}
}

.confirmation-button-link {
cursor: pointer;
background: none;
border: none;
color: govuk-colour("white");
text-decoration: underline;
&:hover{
color: govuk-colour("light-grey");
&:focus{
color: $govuk-text-colour;
}
}
}
1 change: 1 addition & 0 deletions app/static/src/scss/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
@import "./modal-dialog";
@import "./progress_bar";
@import "./back-link";
@import "./confirmation";
4 changes: 4 additions & 0 deletions app/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@
'href': language.switch.href,
'text': language.switch.text,
'attributes': {'x-data': 'language-switcher'},
},
{
'href': url_for('main.online_safety'),
'text': _("Staying safe online")
},
{
'href': url_for('main.accessibility'),
Expand Down
7 changes: 5 additions & 2 deletions app/templates/categories/in-scope.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ <h2 class="govuk-heading-m">{% trans %}What you need to check if you qualify fin

<h2 class="govuk-heading-m">{% trans %}When you do not need to complete the financial assessment{% endtrans %}</h2>

<p class="govuk-body">{% trans %}You should <a class="govuk-link" href="/contact">contact CLA</a> without completing the financial assessment if you are:{% endtrans %}</p>
{% set contact_us_link %}
<a class="govuk-link" href={{ url_for('contact.contact_us') }}>contact CLA</a>
{% endset %}
<p class="govuk-body">{% trans %}You should {{ contact_us_link }} without completing the financial assessment if you are:{% endtrans %}</p>

<ul class="govuk-list govuk-list--bullet">
<li>{% trans %}under 18{% endtrans %}</li>
Expand All @@ -48,7 +51,7 @@ <h3 class="govuk-heading-s">{% trans %}If you use British Sign Language (BSL){%

<p class="govuk-body">{% trans %}You can choose not to complete the financial assessment online, and instead ask for a call with a BSL interpreter.{% endtrans %}</p>

<p class="govuk-body">{% trans %}Fill in the '<a class="govuk-link" href="/contact">Contact CLA</a>' page. Select 'BSL' under 'Communication needs'.{% endtrans %}</p>
<p class="govuk-body">{% trans %}Fill in the '{{ contact_us_link }}' page. Select 'BSL' under 'Communication needs'.{% endtrans %}</p>

{{ govukButton(params={
"text": _("Check if you qualify financially"),
Expand Down
Loading

0 comments on commit c58c3dc

Please sign in to comment.