Skip to content

Commit

Permalink
Updated to add in the error summary list and show the error message p…
Browse files Browse the repository at this point in the history
…er question
  • Loading branch information
sam-c-dfe committed Jul 24, 2024
1 parent dacea08 commit b10a159
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ public class CheckAdditionalRequirementsPage
public string QuestionSectionHeading { get; init; } = string.Empty;

public string ErrorMessage { get; init; } = string.Empty;

public string ErrorSummaryHeading { get; init; } = string.Empty;
}
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ public Task<List<Qualification>> GetQualifications()
QualificationLevelLabel = "Qualification level",
InformationMessage = "Your result is dependent on the accuracy of the answers you have provided",
ErrorMessage = "This is a test error message",
ErrorSummaryHeading = "There was a problem",
QuestionSectionHeading = "This is the question section heading"
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ private async Task<IActionResult> GetResponse(string qualificationId,
}

var mappedModel = await MapModel(content, qualification, model);
if (mappedModel.HasErrors)
{
SetQuestionErrorFlag(mappedModel);
}

return View("Index", mappedModel);
}
Expand All @@ -93,8 +97,10 @@ private async Task<CheckAdditionalRequirementsPageModel> MapModel(CheckAdditiona
mappedModel.BackButton = content.BackButton;
mappedModel.AdditionalRequirementQuestions =
await MapAdditionalRequirementQuestions(qualification.AdditionalRequirementQuestions!);
mappedModel.Answers = MapQuestionsToDictionary(qualification.AdditionalRequirementQuestions!);
mappedModel.Answers = MapQuestionsToDictionary(qualification.AdditionalRequirementQuestions!, model);
mappedModel.ErrorMessage = content.ErrorMessage;
mappedModel.ErrorSummaryHeading = content.ErrorSummaryHeading;
mappedModel.QuestionCount = mappedModel.AdditionalRequirementQuestions.Count;
return mappedModel;
}

Expand Down Expand Up @@ -122,8 +128,24 @@ private static List<OptionModel> MapOptions(List<Option> options)
return options.Select(option => new OptionModel { Label = option.Label, Value = option.Value }).ToList();
}

private static Dictionary<string, string> MapQuestionsToDictionary(List<AdditionalRequirementQuestion> additionalRequirementQuestions)
private static Dictionary<string, string> MapQuestionsToDictionary(List<AdditionalRequirementQuestion> additionalRequirementQuestions, CheckAdditionalRequirementsPageModel? previousModel)
{
return additionalRequirementQuestions.ToDictionary(additionalRequirementQuestion => additionalRequirementQuestion.Question, additionalRequirementQuestion => string.Empty);
var result = additionalRequirementQuestions.ToDictionary(additionalRequirementQuestion => additionalRequirementQuestion.Question, _ => string.Empty);
if (previousModel is null) return result;

foreach (var answer in previousModel.Answers.Where(answer => !string.IsNullOrEmpty(answer.Value)))
{
result[answer.Key] = answer.Value;
}

return result;
}

private static void SetQuestionErrorFlag(CheckAdditionalRequirementsPageModel model)
{
foreach (var answer in model.Answers.Where(answer => string.IsNullOrEmpty(answer.Value)))
{
model.AdditionalRequirementQuestions.First(x => x.Question == answer.Key).HasError = true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ namespace Dfe.EarlyYearsQualification.Web.Models.Content;

public class AdditionalRequirementQuestionModel
{
public string Question { get; set; } = string.Empty;
public string Question { get; init; } = string.Empty;

public string HintText { get; set; } = string.Empty;
public string HintText { get; init; } = string.Empty;

public string DetailsHeading { get; set; } = string.Empty;
public string DetailsHeading { get; init; } = string.Empty;

public string DetailsContent { get; set; } = string.Empty;
public string DetailsContent { get; init; } = string.Empty;

public List<OptionModel> Options { get; init; } = [];

public bool HasError { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,19 @@ public class CheckAdditionalRequirementsPageModel
public NavigationLink? BackButton { get; set; }

public List<AdditionalRequirementQuestionModel> AdditionalRequirementQuestions { get; set; } = [];

[AnswerValidation]
// ReSharper disable once PropertyCanBeMadeInitOnly.Global
public Dictionary<string, string> Answers { get; set; } = [];

public bool HasErrors { get; set; }

public string ErrorMessage { get; set; } = string.Empty;

public string ErrorSummaryHeading { get; set; } = string.Empty;

public int SpecifiedAnswersCount => Answers.Count;

[Required, Compare("SpecifiedAnswersCount")]
public int QuestionCount { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,32 @@

<div class="govuk-grid-row">
<div class="govuk-grid-column-full govuk-grid-column-two-thirds-from-desktop">
@if (Model.HasErrors)
{
<div id="error-banner" class="govuk-error-summary" data-module="govuk-error-summary">
<div role="alert">
<h2 class="govuk-error-summary__title">
@Model.ErrorSummaryHeading
</h2>
<div class="govuk-error-summary__body">
<ul class="govuk-list govuk-error-summary__list">
@for (var i = 0; i < Model.AdditionalRequirementQuestions.Count; i++)
{
var question = Model.AdditionalRequirementQuestions[i];
if (question.HasError)
{
var href = $"#question-choice-error_{i}";
<li>
<a id="error-banner-link" href="@href">@Model.ErrorMessage</a>
</li>
}
}

</ul>
</div>
</div>
</div>
}
<h1 class="govuk-heading-xl" id="heading">@Model.Heading</h1>
<dl class="govuk-summary-list">
<div class="govuk-summary-list__row">
Expand Down Expand Up @@ -41,24 +67,23 @@
</dl>
<form id="check-additional-requirements" asp-controller="CheckAdditionalRequirements" asp-action="Post" method="post">
<input type="hidden" name="qualificationId" value="@Model.QualificationId">
<div id="confirm-qualification-form-group" class="govuk-form-group @(Model.HasErrors ? "govuk-form-group--error" : "")">
<fieldset class="govuk-fieldset" role="group" aria-describedby="confirm-qualification-choice-error">
<legend class="govuk-fieldset__legend govuk-fieldset__legend--l">
<h4 id="radio-heading" class="govuk-heading-m">@Model.QuestionSectionHeading</h4>
</legend>

@if (Model.HasErrors)
{
<p id="question-choice-error" class="govuk-error-message">
<span class="govuk-visually-hidden">Error:</span> @Model.ErrorMessage
</p>
}

@for (var qi = 0; qi < Model.AdditionalRequirementQuestions.Count; qi++)
{
var question = Model.AdditionalRequirementQuestions[qi];
var questionId = $"question_{qi}";
<div class="govuk-form-group">
<div id="additional-requirements-form-group" class="govuk-form-group">
<h4 id="radio-heading" class="govuk-heading-m">@Model.QuestionSectionHeading</h4>
<input type="hidden" name="QuestionCount" value="@Model.QuestionCount"/>
@for (var qi = 0; qi < Model.AdditionalRequirementQuestions.Count; qi++)
{
var question = Model.AdditionalRequirementQuestions[qi];
var questionId = $"question_{qi}";
<div class="govuk-form-group @(Model.AdditionalRequirementQuestions[qi].HasError ? "govuk-form-group--error" : "")">
<fieldset class="govuk-fieldset">
@if (Model.AdditionalRequirementQuestions[qi].HasError)
{
var errorId = $"question-choice-error_{qi}";
<p id="@errorId" class="govuk-error-message">
<span class="govuk-visually-hidden">Error:</span> @Model.ErrorMessage
</p>
}

<h3 class="govuk-heading-s" id="@questionId">@question.Question</h3>
@if (!string.IsNullOrEmpty(question.HintText))
{
Expand All @@ -84,16 +109,17 @@
{
var option = question.Options[i];
var id = $"{option.Value}_{qi}_{i}";
var @checked = Model.Answers.GetValueOrDefault(question.Question) == option.Value ? "checked" : "";
<div class="govuk-radios__item">
@Html.RadioButtonFor(x => x.Answers[question.Question], option.Value, new { @class = "govuk-radios__input", id })
@Html.RadioButtonFor(x => x.Answers[question.Question], option.Value, new { @class = "govuk-radios__input", id, @checked })
<label class="govuk-label govuk-radios__label" for="@id">
@option.Label
</label>
</div>
}
</div>
}
</fieldset>
</fieldset>
</div>
}
</div>
<div class="govuk-warning-text">
<span class="govuk-warning-text__icon" aria-hidden="true">!</span>
Expand All @@ -109,4 +135,4 @@
</div>
</form>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ public async Task Index_PageContentIsReturned_MapsModelAndReturnsView()
model.Answers.Should().NotBeNull();
model.Answers.Count.Should().Be(qualification.AdditionalRequirementQuestions!.Count);
model.ErrorMessage.Should().BeSameAs(pageContent.ErrorMessage);
model.ErrorSummaryHeading.Should().BeSameAs(pageContent.ErrorSummaryHeading);
model.InformationMessage.Should().BeSameAs(pageContent.InformationMessage);
model.QualificationId.Should().BeSameAs(qualification.QualificationId);
model.QualificationLevel.Should().Be(qualification.QualificationLevel);
Expand Down Expand Up @@ -265,7 +266,7 @@ public async Task Post_PageContentIsNull_RedirectsToErrorPage()
mockLogger.VerifyError("No content for the check additional requirements page");
}

[TestMethod]
[TestMethod]
public async Task Post_PageContentIsReturned_MapsModelAndReturnsView()
{
var mockLogger = new Mock<ILogger<CheckAdditionalRequirementsController>>();
Expand Down Expand Up @@ -301,6 +302,7 @@ public async Task Post_PageContentIsReturned_MapsModelAndReturnsView()
model.Answers.Should().NotBeNull();
model.Answers.Count.Should().Be(qualification.AdditionalRequirementQuestions!.Count);
model.ErrorMessage.Should().BeSameAs(pageContent.ErrorMessage);
model.ErrorSummaryHeading.Should().BeSameAs(pageContent.ErrorSummaryHeading);
model.InformationMessage.Should().BeSameAs(pageContent.InformationMessage);
model.QualificationId.Should().BeSameAs(qualification.QualificationId);
model.QualificationLevel.Should().Be(qualification.QualificationLevel);
Expand Down Expand Up @@ -367,7 +369,8 @@ private static CheckAdditionalRequirementsPage CreatePageContent()
InformationMessage = "This is the information message",
CtaButtonText = "Get result",
QualificationLevelLabel = "Qualification level",
QuestionSectionHeading = "Answer the following questions"
QuestionSectionHeading = "Answer the following questions",
ErrorSummaryHeading = "There was a problem"
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,7 @@ public async Task GetCheckAdditionalRequirementsPageContent_ReturnsExpectedDetai
Href = "/"
});
result.ErrorMessage.Should().NotBeNullOrEmpty();
result.ErrorSummaryHeading.Should().NotBeNullOrEmpty();
result.Heading.Should().NotBeNullOrEmpty();
result.InformationMessage.Should().NotBeNullOrEmpty();
result.QualificationLabel.Should().NotBeNullOrEmpty();
Expand Down

0 comments on commit b10a159

Please sign in to comment.