feat(15): dynamic rendering of plan types
currently only on page revisit. for dynamic - need to use htmx swapping, with separate endpoing getting updates value from whole element being a fragment
This commit is contained in:
parent
f9c32fd7dc
commit
6d827365ac
|
@ -109,27 +109,38 @@
|
|||
<p class="py-3 text-cool-gray">
|
||||
You have the option of monthly or yearly billing.
|
||||
</p>
|
||||
<div
|
||||
class="flex flex-col w-full md:flex-row"
|
||||
<div class="flex flex-col w-full md:flex-row">
|
||||
<label
|
||||
for="ArcadePlanType"
|
||||
class="relative h-20 md:w-32"
|
||||
th:each="planType: ${formData.availablePlans}"
|
||||
th:for="${planType}"
|
||||
>
|
||||
<label for="ArcadePlanType" class="relative h-20 md:w-32">
|
||||
<input
|
||||
id="ArcadePlanType"
|
||||
th:id="${planType}"
|
||||
type="radio"
|
||||
name="plan-type"
|
||||
value="Arcade"
|
||||
th:value="${planType}"
|
||||
class="hidden peer"
|
||||
th:checked="${formData.userAnswers.step2.planType.toString()} == 'Arcade'"
|
||||
th:checked="${formData.userAnswers.step2.planType.toString()} == ${planType.toString()}"
|
||||
checked
|
||||
/>
|
||||
<div
|
||||
class="absolute inset-y-0 inset-x-0 rounded-lg border border-cool-gray peer-checked:border-purplish-blue peer-checked:bg-magnolia"
|
||||
>
|
||||
<h2 class="">Arcade</h2>
|
||||
<h2 th:text="${planType}" class="">Arcade</h2>
|
||||
<p th:text="|${formData.planCost(planType)}/${formData.periodCostLabel}|">$90/yr</p>
|
||||
<p th:if="${formData.userAnswers.step2.isYearly}">2 months free</p>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label for="AdvancedPlanType" class="relative h-20 md:w-32">
|
||||
<label
|
||||
for="AdvancedPlanType"
|
||||
class="relative h-20 md:w-32"
|
||||
th:remove="all"
|
||||
>
|
||||
<input
|
||||
id="AdvancedPlanType"
|
||||
type="radio"
|
||||
|
@ -145,7 +156,11 @@
|
|||
</div>
|
||||
</label>
|
||||
|
||||
<label for="ProPlanType" class="relative h-20 md:w-32">
|
||||
<label
|
||||
for="ProPlanType"
|
||||
class="relative h-20 md:w-32"
|
||||
th:remove="all"
|
||||
>
|
||||
<input
|
||||
id="ProPlanType"
|
||||
type="radio"
|
||||
|
@ -162,7 +177,9 @@
|
|||
</label>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-flow-col-dense place-content-center w-full rounded-lg bg-magnolia">
|
||||
<div
|
||||
class="grid grid-flow-col-dense place-content-center w-full rounded-lg bg-magnolia"
|
||||
>
|
||||
<div
|
||||
class="inline-grid grid-cols-3 place-items-center h-12 text-sm font-bold"
|
||||
>
|
||||
|
@ -174,8 +191,16 @@
|
|||
id="packageDuration"
|
||||
th:checked="${formData.userAnswers.step2.isYearly}"
|
||||
/>
|
||||
<p class="row-start-1 text-marine-blue peer-checked:text-cool-gray">Monthly</p>
|
||||
<p class="row-start-1 text-cool-gray peer-checked:text-marine-blue">Yearly</p>
|
||||
<p
|
||||
class="row-start-1 text-marine-blue peer-checked:text-cool-gray"
|
||||
>
|
||||
Monthly
|
||||
</p>
|
||||
<p
|
||||
class="row-start-1 text-cool-gray peer-checked:text-marine-blue"
|
||||
>
|
||||
Yearly
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -199,7 +224,7 @@
|
|||
type="submit"
|
||||
class="grid place-content-center mr-3 w-24 h-10 text-sm font-semibold text-white rounded md:mr-24 md:w-32 md:h-12 md:text-base md:rounded-lg bg-marine-blue"
|
||||
value="Next Step"
|
||||
>
|
||||
/>
|
||||
<a
|
||||
th:remove="all"
|
||||
href="step3.html"
|
||||
|
|
|
@ -19,9 +19,6 @@ object Models {
|
|||
final case class FormData(
|
||||
userAnswers: Answers
|
||||
) {
|
||||
def planDiscountMessage: Option[String] =
|
||||
if (userAnswers.step2.isYearly) Some("2 monts free") else None
|
||||
|
||||
// yeah, in real world it will not be this simple
|
||||
def yearlyCost(monthlyCost: Int): Int = 10 * monthlyCost
|
||||
|
||||
|
@ -29,8 +26,10 @@ object Models {
|
|||
if (userAnswers.step2.isYearly) "yr" else "mo"
|
||||
}
|
||||
|
||||
def planCost: Int = {
|
||||
val monthlyPlanCost = userAnswers.step2.planType match {
|
||||
def selectedPlanCost: Int = planCost(userAnswers.step2.planType)
|
||||
|
||||
def planCost(plan: PlanType): Int = {
|
||||
val monthlyPlanCost = plan match {
|
||||
case PlanType.Arcade => 9
|
||||
case PlanType.Advanced => 12
|
||||
case PlanType.Pro => 15
|
||||
|
@ -56,8 +55,10 @@ object Models {
|
|||
}
|
||||
|
||||
def fullOrderPrice: Int = {
|
||||
planCost + userAnswers.step3.addons.map(addonCost).sum
|
||||
selectedPlanCost + userAnswers.step3.addons.map(addonCost).sum
|
||||
}
|
||||
|
||||
def availablePlans = PlanType.values.toList.asJava
|
||||
}
|
||||
|
||||
final case class Answers(
|
||||
|
@ -73,6 +74,7 @@ object Models {
|
|||
) {
|
||||
// this is not enforced by compiler, sad, maintain by hand in html template files
|
||||
def fragmentName: String = s"step${currentStep}"
|
||||
|
||||
def updateStep(stepNum: Int, rawData: String, nextStep: Int): Answers = {
|
||||
stepNum match {
|
||||
case 1 =>
|
||||
|
|
Loading…
Reference in New Issue