Skip to content

Commit 228ccc1

Browse files
authored
[NGR-981] Adding HasAnythingElseAffectedTheRent Page (#91)
* [NGR-981] Adding HasAnythingElseAffectedTheRent Page * [NGR-981] Adding navigation * [NGR-981] Adding ConfirmBreakClausePage navigation for no
1 parent c915cb2 commit 228ccc1

21 files changed

+679
-24
lines changed

app/uk/gov/hmrc/ngrraldfrontend/controllers/CheckRentFreePeriodController.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,12 @@ package uk.gov.hmrc.ngrraldfrontend.controllers
1818

1919
import play.api.i18n.I18nSupport
2020
import play.api.mvc.{Action, AnyContent, MessagesControllerComponents}
21-
import uk.gov.hmrc.http.NotFoundException
2221
import uk.gov.hmrc.ngrraldfrontend.actions.{AuthRetrievals, DataRetrievalAction}
2322
import uk.gov.hmrc.ngrraldfrontend.config.AppConfig
2423
import uk.gov.hmrc.ngrraldfrontend.models.components.NGRRadio.{buildRadios, simpleNgrRadio}
2524
import uk.gov.hmrc.ngrraldfrontend.models.forms.CheckRentFreePeriodForm
2625
import uk.gov.hmrc.ngrraldfrontend.models.forms.CheckRentFreePeriodForm.form
27-
import uk.gov.hmrc.ngrraldfrontend.models.{Landlord, Mode, NormalMode, UserAnswers}
26+
import uk.gov.hmrc.ngrraldfrontend.models.{Mode, UserAnswers}
2827
import uk.gov.hmrc.ngrraldfrontend.navigation.Navigator
2928
import uk.gov.hmrc.ngrraldfrontend.pages.CheckRentFreePeriodPage
3029
import uk.gov.hmrc.ngrraldfrontend.repo.SessionRepository
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright 2025 HM Revenue & Customs
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package uk.gov.hmrc.ngrraldfrontend.controllers
18+
19+
20+
import play.api.data.Form
21+
import play.api.i18n.{I18nSupport, Messages}
22+
import play.api.mvc.{Action, AnyContent, MessagesControllerComponents}
23+
import play.twirl.api.Html
24+
import uk.gov.hmrc.govukfrontend.views.Aliases.{Label, Text}
25+
import uk.gov.hmrc.ngrraldfrontend.actions.{AuthRetrievals, DataRetrievalAction}
26+
import uk.gov.hmrc.ngrraldfrontend.config.AppConfig
27+
import uk.gov.hmrc.ngrraldfrontend.models.components.NGRCharacterCount
28+
import uk.gov.hmrc.ngrraldfrontend.models.components.NGRRadio.{buildRadios, simpleNgrRadio}
29+
import uk.gov.hmrc.ngrraldfrontend.models.forms.HasAnythingElseAffectedTheRentForm
30+
import uk.gov.hmrc.ngrraldfrontend.models.forms.HasAnythingElseAffectedTheRentForm.form
31+
import uk.gov.hmrc.ngrraldfrontend.models.{HasAnythingElseAffectedTheRent, Mode, UserAnswers}
32+
import uk.gov.hmrc.ngrraldfrontend.navigation.Navigator
33+
import uk.gov.hmrc.ngrraldfrontend.pages.HasAnythingElseAffectedTheRentPage
34+
import uk.gov.hmrc.ngrraldfrontend.repo.SessionRepository
35+
import uk.gov.hmrc.ngrraldfrontend.views.html.HasAnythingElseAffectedTheRentView
36+
import uk.gov.hmrc.ngrraldfrontend.views.html.components.NGRCharacterCountComponent
37+
import uk.gov.hmrc.play.bootstrap.frontend.controller.FrontendController
38+
39+
import javax.inject.{Inject, Singleton}
40+
import scala.concurrent.{ExecutionContext, Future}
41+
42+
@Singleton
43+
class HasAnythingElseAffectedTheRentController @Inject()(hasAnythingElseAffectedTheRentView: HasAnythingElseAffectedTheRentView,
44+
authenticate : AuthRetrievals,
45+
ngrCharacterCountComponent: NGRCharacterCountComponent,
46+
getData: DataRetrievalAction,
47+
navigator: Navigator,
48+
sessionRepository: SessionRepository,
49+
mcc: MessagesControllerComponents)(implicit appConfig: AppConfig, ec: ExecutionContext) extends FrontendController(mcc) with I18nSupport {
50+
51+
52+
private def reasonConditionalHtml(form: Form[HasAnythingElseAffectedTheRentForm])(implicit messages: Messages): Option[Html] =
53+
Some(ngrCharacterCountComponent(form,
54+
NGRCharacterCount(
55+
id = HasAnythingElseAffectedTheRentForm.reasonInput,
56+
name = HasAnythingElseAffectedTheRentForm.reasonInput,
57+
maxLength = Some(250),
58+
label = Label(
59+
classes = "govuk-label govuk-label--s",
60+
content = Text(Messages("hasAnythingElseAffectedTheRent.reason.label"))
61+
)
62+
)))
63+
64+
def show(mode: Mode): Action[AnyContent] = {
65+
(authenticate andThen getData).async { implicit request =>
66+
val preparedForm = request.userAnswers.getOrElse(UserAnswers(request.credId)).get(HasAnythingElseAffectedTheRentPage) match {
67+
case None => form
68+
case Some(value) => form.fill(HasAnythingElseAffectedTheRentForm(value.radio.toString, value.reason))
69+
}
70+
Future.successful(Ok(hasAnythingElseAffectedTheRentView(
71+
form = preparedForm,
72+
radios = buildRadios(preparedForm, simpleNgrRadio(HasAnythingElseAffectedTheRentForm.hasAnythingElseAffectedTheRentRadio, yesConditionalHtml = reasonConditionalHtml(preparedForm))),
73+
propertyAddress = request.property.addressFull,
74+
mode = mode
75+
)))
76+
}
77+
}
78+
79+
def submit(mode: Mode): Action[AnyContent] =
80+
(authenticate andThen getData).async { implicit request =>
81+
form.bindFromRequest().fold(
82+
formWithErrors => {
83+
Future.successful(BadRequest(hasAnythingElseAffectedTheRentView(
84+
form = formWithErrors,
85+
radios = buildRadios(formWithErrors, simpleNgrRadio(HasAnythingElseAffectedTheRentForm.hasAnythingElseAffectedTheRentRadio, yesConditionalHtml = reasonConditionalHtml(formWithErrors))),
86+
propertyAddress = request.property.addressFull,
87+
mode = mode
88+
)))
89+
},
90+
radioValue =>
91+
for {
92+
updatedAnswers <- Future.fromTry(request.userAnswers.getOrElse(UserAnswers(request.credId))
93+
.set(HasAnythingElseAffectedTheRentPage, HasAnythingElseAffectedTheRent(radioValue.radioValue.toBoolean, radioValue.reason)))
94+
_ <- sessionRepository.set(updatedAnswers)
95+
} yield Redirect(navigator.nextPage(HasAnythingElseAffectedTheRentPage, mode, updatedAnswers))
96+
)
97+
}
98+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2025 HM Revenue & Customs
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package uk.gov.hmrc.ngrraldfrontend.models
18+
19+
import play.api.libs.json.{Json, OFormat}
20+
21+
case class HasAnythingElseAffectedTheRent(
22+
radio: Boolean,
23+
reason: Option[String]
24+
)
25+
26+
object HasAnythingElseAffectedTheRent {
27+
implicit val format: OFormat[HasAnythingElseAffectedTheRent] = Json.format[HasAnythingElseAffectedTheRent]
28+
}

app/uk/gov/hmrc/ngrraldfrontend/models/components/NGRCharacterCount.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ case class NGRCharacterCount(
2525
name: String = "",
2626
maxWords: Option[Int] = None,
2727
maxLength: Option[Int] = None,
28+
value: Option[String] = None,
2829
label: Label = Label(),
2930
classes: String = "",
3031
hint: Option[Hint] = None,

app/uk/gov/hmrc/ngrraldfrontend/models/components/NGRRadio.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,10 @@ object NGRRadio {
7979
def noButton(radioContent: String = "service.no", conditionalHtml: Option[Html] = None): NGRRadioButtons =
8080
NGRRadioButtons(radioContent = radioContent, radioValue = `false`, conditionalHtml = conditionalHtml)
8181

82-
def simpleNgrRadio(radioName: String, hint: Option[String] = None)(implicit messages: Messages): NGRRadio =
82+
def simpleNgrRadio(radioName: String, hint: Option[String] = None, yesConditionalHtml: Option[Html] = None, noConditionalHtml: Option[Html] = None)(implicit messages: Messages): NGRRadio =
8383
NGRRadio(
8484
radioGroupName = NGRRadioName(radioName),
85-
NGRRadioButtons = Seq(NGRRadio.yesButton(), NGRRadio.noButton()),
85+
NGRRadioButtons = Seq(NGRRadio.yesButton(conditionalHtml = yesConditionalHtml), NGRRadio.noButton(conditionalHtml = noConditionalHtml)),
8686
hint = hint
8787
)
8888

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright 2025 HM Revenue & Customs
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package uk.gov.hmrc.ngrraldfrontend.models.forms
18+
19+
import play.api.data.Forms.*
20+
import play.api.data.format.Formatter
21+
import play.api.data.{Form, FormError}
22+
import play.api.i18n.*
23+
import play.api.libs.json.{Json, OFormat}
24+
import uk.gov.hmrc.ngrraldfrontend.models.*
25+
import uk.gov.hmrc.ngrraldfrontend.models.forms.mappings.Mappings
26+
27+
final case class HasAnythingElseAffectedTheRentForm(radioValue: String, reason: Option[String])
28+
29+
object HasAnythingElseAffectedTheRentForm extends Mappings {
30+
implicit val format: OFormat[HasAnythingElseAffectedTheRentForm] = Json.format[HasAnythingElseAffectedTheRentForm]
31+
val hasAnythingElseAffectedTheRentRadio = "hasAnythingElseAffectedTheRent"
32+
val reasonInput = "reason"
33+
34+
val messagesApi: MessagesApi = new DefaultMessagesApi()
35+
val lang: Lang = Lang.defaultLang
36+
val messages: Messages = MessagesImpl(lang, messagesApi)
37+
38+
def unapply(hasAnythingElseAffectedTheRentForm: HasAnythingElseAffectedTheRentForm): Option[(String, Option[String])] =
39+
Some((hasAnythingElseAffectedTheRentForm.radioValue, hasAnythingElseAffectedTheRentForm.reason))
40+
41+
private def reasonFormatter(args: Seq[String] = Seq.empty): Formatter[Option[String]] = new Formatter[Option[String]] {
42+
override def bind(key: String, data: Map[String, String]): Either[Seq[FormError], Option[String]] =
43+
val isYesSelected: Boolean = data.get(hasAnythingElseAffectedTheRentRadio).exists(_ == "true")
44+
data.get(key) match {
45+
case None if isYesSelected => Left(Seq(FormError(key, "hasAnythingElseAffectedTheRent.reason.error.required", args)))
46+
case Some(s) if isYesSelected => isReasonValid(s.trim, key, args)
47+
case Some(s) => Right(Some(s.trim))
48+
case None => Right(None)
49+
}
50+
51+
override def unbind(key: String, value: Option[String]): Map[String, String] =
52+
Map(key -> value.getOrElse(""))
53+
}
54+
55+
private def isReasonValid(reasonStr: String, key: String, args: Seq[String]): Either[Seq[FormError], Option[String]] =
56+
if (reasonStr.isEmpty)
57+
Left(Seq(FormError(key, "hasAnythingElseAffectedTheRent.reason.error.required", args)))
58+
else if (reasonStr.length > 250)
59+
Left(Seq(FormError(key, "hasAnythingElseAffectedTheRent.reason.error.maxLength", args)))
60+
else
61+
Right(Some(reasonStr))
62+
63+
def form: Form[HasAnythingElseAffectedTheRentForm] = {
64+
Form(
65+
mapping(
66+
hasAnythingElseAffectedTheRentRadio -> radioText("hasAnythingElseAffectedTheRent.required.error"),
67+
reasonInput -> of(reasonFormatter())
68+
)(HasAnythingElseAffectedTheRentForm.apply)(HasAnythingElseAffectedTheRentForm.unapply)
69+
)
70+
}
71+
}

app/uk/gov/hmrc/ngrraldfrontend/navigation/Navigator.scala

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ class Navigator @Inject()() {
157157
answers.get(ConfirmBreakClausePage) match {
158158
case Some(value) => value match {
159159
case true => uk.gov.hmrc.ngrraldfrontend.controllers.routes.DidYouGetIncentiveForNotTriggeringBreakClauseController.show(NormalMode)
160-
case _ => uk.gov.hmrc.ngrraldfrontend.controllers.routes.LandlordController.show(NormalMode) //TODO This needs to be amended when the journey is completed
160+
case _ => uk.gov.hmrc.ngrraldfrontend.controllers.routes.HasAnythingElseAffectedTheRentController.show(NormalMode)
161161
}
162162
case None => throw new NotFoundException("Failed to find answers - ConfirmBreakClausePage")
163163
}
@@ -167,7 +167,7 @@ class Navigator @Inject()() {
167167
case Some(value) => value match {
168168
case value if value.checkBox.size == 1 && value.checkBox.contains(YesRentFreePeriod) => uk.gov.hmrc.ngrraldfrontend.controllers.routes.AboutTheRentFreePeriodController.show(NormalMode)
169169
case value if value.checkBox.contains(YesLumpSum) => uk.gov.hmrc.ngrraldfrontend.controllers.routes.HowMuchWasTheLumpSumController.show(NormalMode)
170-
case value => uk.gov.hmrc.ngrraldfrontend.controllers.routes.HowMuchWasTheLumpSumController.show(NormalMode)
170+
case value => uk.gov.hmrc.ngrraldfrontend.controllers.routes.HasAnythingElseAffectedTheRentController.show(NormalMode)
171171
}
172172
}
173173
case DidYouGetMoneyFromLandlordPage => answers =>
@@ -204,11 +204,11 @@ class Navigator @Inject()() {
204204

205205
case AboutRepairsAndFittingOutPage => _ => uk.gov.hmrc.ngrraldfrontend.controllers.routes.DidYouGetMoneyFromLandlordController.show(NormalMode)
206206

207-
case HowMuchWasTheLumpSumPage => answers => //TODO This needs to be amended when the journey is completed - Page that dictates navigation is not yet completed
207+
case HowMuchWasTheLumpSumPage => answers =>
208208
answers.get(DidYouGetIncentiveForNotTriggeringBreakClausePage) match {
209209
case Some(value) => value match {
210-
case value if value.checkBox.size == 1 && value.checkBox.contains(YesLumpSum) => uk.gov.hmrc.ngrraldfrontend.controllers.routes.HowMuchWasTheLumpSumController.show(NormalMode) //TODO This needs to be amended when the journey is completed case value if value.checkBox.contains(YesLumpSum) && value.checkBox.contains(YesRentFreePeriod) => uk.gov.hmrc.ngrraldfrontend.controllers.routes.AboutTheRentFreePeriodController.show(NormalMode)
211-
case value => uk.gov.hmrc.ngrraldfrontend.controllers.routes.HowMuchWasTheLumpSumController.show(NormalMode)
210+
case value if value.checkBox.size == 1 && value.checkBox.contains(YesLumpSum) => uk.gov.hmrc.ngrraldfrontend.controllers.routes.HasAnythingElseAffectedTheRentController.show(NormalMode)
211+
case value => uk.gov.hmrc.ngrraldfrontend.controllers.routes.AboutTheRentFreePeriodController.show(NormalMode)
212212
}
213213
}
214214

@@ -217,18 +217,20 @@ class Navigator @Inject()() {
217217
answers.get(DidYouPayAnyMoneyToLandlordPage) match {
218218
case Some(value) => value match {
219219
case true => uk.gov.hmrc.ngrraldfrontend.controllers.routes.DidYouPayAnyMoneyToLandlordController.show(NormalMode) //TODO Needs to go to money you got from landlord or previous tenant when this is made
220-
case _ => uk.gov.hmrc.ngrraldfrontend.controllers.routes.MoneyYouPaidInAdvanceToLandlordController.show(NormalMode)
220+
case _ => uk.gov.hmrc.ngrraldfrontend.controllers.routes.HasAnythingElseAffectedTheRentController.show(NormalMode)
221221
}
222222
case None => throw new NotFoundException("Failed to find answers - DidYouPayAnyMoneyToLandlordPage")
223223
}
224-
case AboutTheRentFreePeriodPage => _ => uk.gov.hmrc.ngrraldfrontend.controllers.routes.AboutTheRentFreePeriodController.show(NormalMode) //TODO Needs to go to has-anything-else-affected-the-rent when this is made
224+
case AboutTheRentFreePeriodPage => _ => uk.gov.hmrc.ngrraldfrontend.controllers.routes.HasAnythingElseAffectedTheRentController.show(NormalMode)
225225
case RepairsAndInsurancePage => answers =>
226226
answers.get(TellUsAboutRentPage) match {
227227
case Some(value) => uk.gov.hmrc.ngrraldfrontend.controllers.routes.ConfirmBreakClauseController.show(NormalMode)
228228
case _ => uk.gov.hmrc.ngrraldfrontend.controllers.routes.RentReviewController.show(NormalMode)
229229
}
230230

231-
case MoneyYouPaidInAdvanceToLandlordPage => _ => uk.gov.hmrc.ngrraldfrontend.controllers.routes.MoneyYouPaidInAdvanceToLandlordController.show(NormalMode) //TODO Needs to go to Has Anything Else Affected The Rent
231+
case MoneyYouPaidInAdvanceToLandlordPage => _ => uk.gov.hmrc.ngrraldfrontend.controllers.routes.HasAnythingElseAffectedTheRentController.show(NormalMode)
232+
233+
case HasAnythingElseAffectedTheRentPage => _ => uk.gov.hmrc.ngrraldfrontend.controllers.routes.MoneyYouPaidInAdvanceToLandlordController.show(NormalMode) //TODO check your answers page
232234
}
233235

234236
//TODO change to check your answers page
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2025 HM Revenue & Customs
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package uk.gov.hmrc.ngrraldfrontend.pages
18+
19+
import play.api.libs.json.JsPath
20+
import uk.gov.hmrc.ngrraldfrontend.models._
21+
22+
case object HasAnythingElseAffectedTheRentPage extends QuestionPage[HasAnythingElseAffectedTheRent]{
23+
24+
override def path: JsPath = JsPath \ toString
25+
26+
override def toString: String = "hasAnythingElseAffectedTheRent"
27+
28+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
@*
2+
* Copyright 2025 HM Revenue & Customs
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*@
16+
17+
@import uk.gov.hmrc.govukfrontend.views.html.components._
18+
@import uk.gov.hmrc.govukfrontend.views.Aliases._
19+
@import uk.gov.hmrc.ngrraldfrontend.views.html.components._
20+
@import uk.gov.hmrc.ngrraldfrontend.viewmodels.govuk.all._
21+
@import uk.gov.hmrc.ngrraldfrontend.config.AppConfig
22+
@import uk.gov.hmrc.ngrraldfrontend.models.components.NavigationBarContent
23+
@import uk.gov.hmrc.ngrraldfrontend.models.forms.HasAnythingElseAffectedTheRentForm
24+
25+
26+
@this(
27+
layout: Layout,
28+
govukRadios : GovukRadios,
29+
formHelper: FormWithCSRF,
30+
govukErrorSummary: GovukErrorSummary,
31+
saveAndContinueButton: saveAndContinueButton)
32+
33+
@(form:Form[HasAnythingElseAffectedTheRentForm], radios: Radios, propertyAddress: String,mode: Mode)(implicit request: RequestHeader, messages: Messages, appConfig: AppConfig)
34+
35+
@layout(pageTitle = Some(messages("hasAnythingElseAffectedTheRent.title")), showBackLink = true, fullWidth = false) {
36+
@formHelper(action = uk.gov.hmrc.ngrraldfrontend.controllers.routes.HasAnythingElseAffectedTheRentController.submit(mode), Symbol("autoComplete") -> "off") {
37+
@if(form.errors.nonEmpty) {
38+
@govukErrorSummary(ErrorSummaryViewModel(form))
39+
}
40+
<span class="govuk-caption-m">@propertyAddress</span>
41+
<h1 class="govuk-heading-l">@messages("hasAnythingElseAffectedTheRent.title")</h1>
42+
@govukRadios(radios)
43+
@saveAndContinueButton(msg = messages("service.continue"), isStartButton = false)
44+
}
45+
}

0 commit comments

Comments
 (0)