feat(15): route to get previous form step

This commit is contained in:
efim 2023-07-15 03:48:04 +00:00
parent 6ed489835f
commit bf33858e41
5 changed files with 75 additions and 10 deletions

View File

@ -183,6 +183,9 @@
class="flex flex-row items-center py-4 w-full bg-white md:items-end md:h-full" class="flex flex-row items-center py-4 w-full bg-white md:items-end md:h-full"
> >
<a <a
hx-get="/get-form/1"
hx-target="#form-step"
hx-swap="outerHTML"
href="step1.html" href="step1.html"
class="ml-6 text-sm font-semibold md:pb-3 md:ml-20 md:text-base text-cool-gray" class="ml-6 text-sm font-semibold md:pb-3 md:ml-20 md:text-base text-cool-gray"
>Go Back</a >Go Back</a

View File

@ -188,6 +188,9 @@
class="flex flex-row items-center py-4 w-full bg-white md:items-end md:h-full" class="flex flex-row items-center py-4 w-full bg-white md:items-end md:h-full"
> >
<a <a
hx-get="/get-form/2"
hx-target="#form-step"
hx-swap="outerHTML"
href="step2.html" href="step2.html"
class="ml-6 text-sm font-semibold md:pb-3 md:ml-20 md:text-base text-cool-gray" class="ml-6 text-sm font-semibold md:pb-3 md:ml-20 md:text-base text-cool-gray"
>Go Back</a >Go Back</a

View File

@ -134,6 +134,9 @@
class="flex flex-row items-center py-4 w-full bg-white md:items-end md:h-full" class="flex flex-row items-center py-4 w-full bg-white md:items-end md:h-full"
> >
<a <a
hx-get="/get-form/3"
hx-target="#form-step"
hx-swap="outerHTML"
href="step3.html" href="step3.html"
class="ml-6 text-sm font-semibold md:pb-3 md:ml-20 md:text-base text-cool-gray" class="ml-6 text-sm font-semibold md:pb-3 md:ml-20 md:text-base text-cool-gray"
>Go Back</a >Go Back</a

View File

@ -8,7 +8,8 @@ object Models {
currentStep: Int = 1, currentStep: Int = 1,
step1: StepAnswers.Step1 = StepAnswers.Step1(), step1: StepAnswers.Step1 = StepAnswers.Step1(),
step2: StepAnswers.Step2 = StepAnswers.Step2(), step2: StepAnswers.Step2 = StepAnswers.Step2(),
step3: StepAnswers.Step3 = StepAnswers.Step3() step3: StepAnswers.Step3 = StepAnswers.Step3(),
step4: StepAnswers.Step4 = StepAnswers.Step4()
) { ) {
// this is not enforced by compiler, sad, maintain by hand in html template files // this is not enforced by compiler, sad, maintain by hand in html template files
def fragmentName: String = s"step${currentStep}" def fragmentName: String = s"step${currentStep}"
@ -31,7 +32,8 @@ object Models {
) )
case 4 => case 4 =>
this.copy( this.copy(
currentStep = stepNum + 1 currentStep = stepNum + 1,
step4 = this.step4
) )
case _ => this case _ => this
} }
@ -46,12 +48,14 @@ object Models {
sealed trait StepAnswers { sealed trait StepAnswers {
def fromFormData(rawData: String): StepAnswers def fromFormData(rawData: String): StepAnswers
def submitted: Boolean
} }
object StepAnswers { object StepAnswers {
final case class Step1( final case class Step1(
name: String = "", name: String = "",
email: String = "", email: String = "",
phone: String = "" phone: String = "",
override val submitted: Boolean = false
) extends StepAnswers { ) extends StepAnswers {
override def fromFormData(rawData: String): Step1 = { override def fromFormData(rawData: String): Step1 = {
println(s"parsing step 1 data $rawData") println(s"parsing step 1 data $rawData")
@ -67,12 +71,13 @@ object Models {
val email = fieldValues.getOrElse("email", "") val email = fieldValues.getOrElse("email", "")
val phone = fieldValues.getOrElse("phone", "") val phone = fieldValues.getOrElse("phone", "")
Step1(name, email, phone) Step1(name, email, phone, submitted = true)
} }
} }
final case class Step2( final case class Step2(
planType: PlanType = PlanType.Arcade, planType: PlanType = PlanType.Arcade,
isYearly: Boolean = false isYearly: Boolean = false,
override val submitted: Boolean = false
) extends StepAnswers { ) extends StepAnswers {
override def fromFormData(rawData: String): Step2 = { override def fromFormData(rawData: String): Step2 = {
println(s"parsing step 2 data $rawData") println(s"parsing step 2 data $rawData")
@ -88,11 +93,13 @@ object Models {
PlanType.valueOf(fieldValues.getOrElse("plan-type", "Arcade")) PlanType.valueOf(fieldValues.getOrElse("plan-type", "Arcade"))
val isYearly = fieldValues.get("isPackageYearly").contains("on") val isYearly = fieldValues.get("isPackageYearly").contains("on")
Step2(planType, isYearly) Step2(planType, isYearly, submitted = true)
} }
} }
final case class Step3(addons: Set[Addons] = Set.empty) final case class Step3(
extends StepAnswers { addons: Set[Addons] = Set.empty,
override val submitted: Boolean = false
) extends StepAnswers {
override def fromFormData(rawData: String): Step3 = { override def fromFormData(rawData: String): Step3 = {
println(s"parsing step 3 data $rawData") println(s"parsing step 3 data $rawData")
// for multiple checkboxes data comes in form of // for multiple checkboxes data comes in form of
@ -104,13 +111,19 @@ object Models {
name -> value name -> value
} }
val addonsStrings = fieldValues.groupMap(_._1)(_._2) val addonsStrings = fieldValues
.groupMap(_._1)(_._2)
.getOrElse("addon-services", Array.empty[String]) .getOrElse("addon-services", Array.empty[String])
println(s"in step 3 got strings $addonsStrings") println(s"in step 3 got strings $addonsStrings")
val addons = addonsStrings.map(Addons.valueOf(_)).toSet val addons = addonsStrings.map(Addons.valueOf(_)).toSet
Step3(addons) Step3(addons, submitted = true)
} }
}
final case class Step4(
override val submitted: Boolean = false
) extends StepAnswers {
override def fromFormData(rawData: String): Step4 = Step4(true)
} }
} }
} }

View File

@ -85,6 +85,49 @@ case class Routes()(implicit cc: castor.Context, log: cask.Logger)
) )
} }
@cask.get("/get-form/:stepNum")
def getFormByStep(stepNum: Int, sessionId: cask.Cookie) = {
val id = sessionId.value
val answersData = Sessions.sessionReplies.get(id)
println(s"returning to step $stepNum with data $answersData")
answersData match {
case Some(state) => {
val stepData = stepNum match {
case 1 => state.step1
case 2 => state.step2
case 3 => state.step3
case 4 => state.step4
}
if (!stepData.submitted) {
cask.Response(
s"Your previous answer for step $stepNum not found, please reload the page"
)
} else {
val context = new Context()
val updatedState = state.copy(currentStep = stepNum)
Sessions.sessionReplies.update(id, updatedState)
context.setVariable(formDataContextVarName, updatedState)
val formFragment = templateEngine.process(
updatedState.fragmentName,
Set("formFragment").asJava,
context
)
cask.Response(
formFragment,
headers = Seq("Content-Type" -> "text/html;charset=UTF-8")
)
}
}
case None =>
cask.Response(
"Your previous answers not found, please reload the page",
404
)
}
}
// i guess let's make step a hidden input? // i guess let's make step a hidden input?
@cask.post("/submit-step/:stepNum") @cask.post("/submit-step/:stepNum")
def submitStep( def submitStep(