<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body class="d-flex flex-column h-100 font-sans antialiased fs-7">
<main class="flex-shrink-0">
<div x-data="getProduct()">
<h1 x-text="product.name"></h1>
<div x-data="{
currentProduct: product,
}">
<div x-data="{
currentStep: 1,
totalSteps: currentProduct.sub_products.length
}">
<div class="row" x-init="$watch('currentProduct', value => {
totalSteps = value.sub_products.length;
key++; // Increment key to force re-render
})">
<div class="col-12 mb-2">
<h4 x-text="currentProduct.name"></h4>
Steps: <span x-text="totalSteps"></span>
Current Step: <span x-text="currentStep"></span>
</div>
<div class="col-12 mb-2">
<nav class="nav nav-pills flex-column flex-sm-row gap-1">
<template x-for="(sub_product, index) in currentProduct.sub_products">
<button
type="button"
class="flex-sm-fill text-sm-center nav-link border"
:class="{ 'active': currentStep === index+1 }"
@click.prevent="currentStep = index+1"
>
<span x-text="sub_product.name"></span>
</button>
</template>
</nav>
</div>
<div class="col-12">
<!-- Back Button -->
<button x-show="trail.length > 0" @click="
let lastStep = trail.pop();
currentProduct = lastStep.product;
currentStep = lastStep.step;
" class="btn btn-warning mb-2">
Back
</button>
<!-- Tab panes -->
<div>
<template x-for="(sub_product, index) in currentProduct.sub_products" :key="key + '-' + index">
<div
x-show="currentStep === index+1"
>
<div class="border rounded bg-light p-2">
<div class="d-flex justify-content-between mb-2">
<div>
<h5 class="mb-0"><span x-text="sub_product.name"></span></h5>
</div>
</div>
<ul class="list-group list-group-flush mb-0">
<template x-for="(deep_sub_product, index) in sub_product.sub_products" :key="key + '-' + deep_sub_product.id">
<li class="list-group-item d-flex justify-content-between align-items-center py-3">
<label class="stretched-link" x-bind:for="deep_sub_product.id"><span x-text="deep_sub_product.name"></span></label>
<input @change="
let isChecked = $event.target.checked;
if(isChecked) {
if(deep_sub_product.sub_products && deep_sub_product.sub_products.length) {
trail.push({ product: currentProduct, step: currentStep });
currentProduct = deep_sub_product;
currentStep = 1;
}
}"
class="form-check-input ms-1" type="checkbox" value="" x-bind:id="deep_sub_product.id">
</li>
</template>
</ul>
</div>
</div>
</template>
</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
function getProduct() {
return {
product: {
"id": "01j51xtwmcm4bmz2jpd2x8d1j0",
"type": 1,
"name": "Pizza",
"plu": "PROD-PIZ-IVUAW",
"min": null,
"max": null,
"multi_max": null,
"price": {
"amount": "500",
"currency": "GBP",
"formatted": "£5.00"
},
"sub_products": [
{
"id": "01j51xw86mj4zpw71qzd23yxkt",
"type": 3,
"name": "Pizza Size",
"plu": "MG-PIZ-GKNDC",
"min": 1,
"max": 1,
"multi_max": null,
"sub_products": [
{
"id": "01j51xxbrqyj6v0bs71503pvhz",
"type": 2,
"name": "9 inch",
"plu": "MOD-9IN-4O5B2",
"min": null,
"max": null,
"multi_max": null,
"price": {
"amount": "0",
"currency": "GBP",
"formatted": "£0.00"
},
"sub_products": []
},
{
"id": "01j51xxx0vaejrdnx80e2sc44m",
"type": 2,
"name": "12 inch",
"plu": "MOD-12I-LGK4P",
"min": null,
"max": null,
"multi_max": null,
"price": {
"amount": "200",
"currency": "GBP",
"formatted": "£2.00"
},
"sub_products": [
{
"id": "01j51xz2qhze0synfzwbg8qkyp",
"type": 3,
"name": "12 inch pizza crust",
"plu": "MG-12I-PTYOS",
"min": null,
"max": 1,
"multi_max": null,
"sub_products": [
{
"id": "01j51y0n1dfa1eech6rc4avx5f",
"type": 2,
"name": "Stuffed Crust",
"plu": "MOD-STU-9H2BP",
"min": null,
"max": null,
"multi_max": null,
"price": {
"amount": "100",
"currency": "GBP",
"formatted": "£1.00"
},
"sub_products": [
{
"id": "01j51xz2qhze0synfzwbg8qkyp",
"type": 3,
"name": "12 inch pizza crust DEPTH TEST",
"plu": "MG-12I-PTYOS",
"min": null,
"max": 1,
"multi_max": null,
"sub_products": [
{
"id": "01j51y0n1dfa1eech6rc4avx5f",
"type": 2,
"name": "Stuffed Crust DEPTH TEST",
"plu": "MOD-STU-9H2BP",
"min": null,
"max": null,
"multi_max": null,
"price": {
"amount": "100",
"currency": "GBP",
"formatted": "£1.00"
},
"sub_products": []
},
{
"id": "01j51y1crn99gg2evy2b96ytev",
"type": 2,
"name": "Thin Crust DEPTH TEST",
"plu": "MOD-THI-0TYVD",
"min": null,
"max": null,
"multi_max": null,
"price": {
"amount": "50",
"currency": "GBP",
"formatted": "£0.50"
},
"sub_products": []
}
]
}
]
},
{
"id": "01j51y1crn99gg2evy2b96ytev",
"type": 2,
"name": "Thin Crust",
"plu": "MOD-THI-0TYVD",
"min": null,
"max": null,
"multi_max": null,
"price": {
"amount": "50",
"currency": "GBP",
"formatted": "£0.50"
},
"sub_products": []
}
]
}
]
}
]
},
{
"id": "01j51zcdww6ekes424wse5w689",
"type": 3,
"name": "Pizza Additional Toppings",
"plu": "MG-PIZ-3VQTI",
"min": null,
"max": 3,
"multi_max": 3,
"sub_products": [
{
"id": "01j51zap82spt05ysm3m2fj9t4",
"type": 2,
"name": "Pepperoni",
"plu": "MOD-PEP-HDPL0",
"min": null,
"max": null,
"multi_max": null,
"price": {
"amount": "50",
"currency": "GBP",
"formatted": "£0.50"
},
"sub_products": []
},
{
"id": "01j51zb90ptzkb7d5w92sphx1g",
"type": 2,
"name": "Pineapple",
"plu": "MOD-PIN-K7ZEV",
"min": null,
"max": null,
"multi_max": null,
"price": {
"amount": "50",
"currency": "GBP",
"formatted": "£0.50"
},
"sub_products": []
},
{
"id": "01j51zbrajdmx0hz4136e41n8p",
"type": 2,
"name": "Tomato",
"plu": "MOD-TOM-ERSMC",
"min": null,
"max": null,
"multi_max": null,
"price": {
"amount": "50",
"currency": "GBP",
"formatted": "£0.50"
},
"sub_products": []
}
]
}
]
},
trail: [],
key: 0
}
}
</script>
</main>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script>
</body>
</html>