JSFiddle - React, Tailwind, and code Playground

HTML

<label><input type="checkbox" data-bind="checked: showInfo"/>Show Info</label>
<label><input type="checkbox" data-bind="checked: showBundleConfig"/>Show Bundle Config</label>
<label><input type="checkbox" data-bind="checked: showCustAssignment"/>Show Customer Assignment</label>
<label><input type="checkbox" data-bind="checked: showWizard"/>Show Wizard</label>
<div data-bind="visible: $root.showInfo">
  Rules
  <ul>
    <li>Round Up Millis to nearest time increment (i.e 6s)</li>
    <li>Then Round to nearest billing fraction (0.1p)</li>
    <li>Then Add Connection Charge</li>
    <li>When free minutes of a type go, it uses total free minutes</li>
    <li>When all free minutes go, it bills</li>
    <li>if a call is split over free minutes threshold, it's partially billed</li>
    <li>And a connection charge added</li>
    <li>Sessions are written every 60 minutes</li>
    <li>Remaining credit is written every 2 seconds</li>
    <li>Free minutes and reset of starts happens 23:59:39 on the last day of the month</li>
  </ul>

  Structure
  <pre>
  Bundle
     |- Price Band
           |- Call Rate
                 |- Price Break
  e.g.
  Bundle 1
     |- Price Band A (0-5000 minutes)
           |- Call Rate (07 mobiles)
                 |- Price Break 1 (0-60min 0.5p)
                 |- Price Break 2 (60+min 0.2p)
           |- Call Rate (00 internaltional)
                 |- Price Break 1 (2.5p)

  </pre>
</div>
<div data-bind="visible: $root.showBundleConfig">
  <h2>Bundles</h2>
  <div data-bind="foreach: bundles">
      <div class="bundle-item">
          <div class="bundle-name" data-bind="text: Name"></div>
          <div data-bind="text: Description"></div>
          <button data-bind="click: $parent.editBundle_click">Edit Bundle</button>
      </div>
  </div>

  <div class="edit-bundle" data-bind="with: editingBundle">
    <div class="formitem">
      <h2>Editing:</h2>
      <div class="title">Bundle</div>
      <label class="name">Name:</label><input...

CSS

.bundle-item {
    height: 100px;
    background-color: #ccccf2;
    border: 1px solid #ccccf2;
    padding: 8px;
    border-radius: 5px;
    width: 160px;
    margin: 5px;
    list-style: none;
    text-align: center;
}

.wizard .bundle-item:hover {
  border: 1px solid black;
  background-color: #e4ffd4;
}

.bundle-name {
    font-weight: bold;
    margin-bottom: 15px;
}


.edit-bundle .formitem {
    background-color: white;
    padding: 10px;
    margin: 5px;
    list-style: none;
}

.edit-bundle .formitem ul {
    list-style: none;
    padding-left:5px;
}

.edit-bundle .formitem label input {
    margin-left: 10px;
}



.edit-bundle .formitem label {
    width: 120px;
    display: inline-block;
    margin-right: 4px;
    margin-bottom: 3px;
}

.edit-bundle .formitem input {
    margin-bottom: 3px;
}

.edit-bundle .formitem .title {
    font-weight: bold;
    margin-bottom: 5px;
}

.edit-bundle .formitem.break {
    background-color: #e0e0e0;
    border-radius: 6px;
    padding-bottom: 10px;
    margin-bottom: 10px;
}

.edit-bundle .formitem.rating ul li {
    background-color: #e7ecff;
    padding: 5px;
    border-radius: 5px;
    margin-bottom: 10px;
}

.edit-bundle .formitem.break ul li {
    background-color: #e2e2ff;
    padding: 8px;
    border-radius: 6px;
    margin-bottom: 10px;
}

JavaScript

var Bundles = [
	{
			Name: ko.observable("Standard Bundle"),
      Description: ko.observable("100 Minutes / Month"),
	},
  {
			Name: ko.observable("Bigger Bundle"),
      Description: ko.observable("0 Minutes / Month, higher rates"),
	}
]

var RatingBands = [
  {
			Name: ko.observable("First 5k"),
      Description: ko.observable("First 5000 Minutes"),
      PriceBreakTotalCallLengthMillis: ko.observable(100000000)
  }
]

var CallRates = [
	{
  		Name: ko.observable("Mobile"),
      Description: ko.observable("Mobile Calls"),
      Prefix: ko.observable("07*"),
      RatingCallType: ko.observable(3),
  },
  {
  		Name: ko.observable("National"),
      Description: ko.observable("National Calls"),
      Prefix: ko.observable("01*"),
      RatingCallType: ko.observable(1),
      ConnectionCharge: ko.observable(0.5),
  }
];

var PriceBreaks = [
	{
			Name: ko.observable("First 20m"),
      Description: ko.observable(""),
      CostPerSecond: ko.observable(0.2),
      MaxBillingLengthMillis: ko.observable(200000)
	}
];


var CustomerPurchaseWizard = function(main) {
		var self = this;
    this.main = main;
    this.chosenBundle = ko.observable();
    this.creditAdd = ko.observable(20);
		this.wizardStep = ko.observable(1);

		this.templateForWiz = ko.pureComputed(function() {
    		return "wiz" + self.wizardStep();
    });

  	this.chooseBundle_click = function(data, event) {
    		self.chosenBundle(data);
    		self.nextStep_click();
    }
    
    this.goToStart_click = function(data, event) {
    		var pre = parseFloat(main.remainingCredit()) + parseFloat(self.creditAdd());
        console.log(pre);
    		main.remainingCredit(pre);
    		self.wizardStep(1);
    }   
    
    this.nextStep_click = function() {
    		self.wizardStep(self.wizardStep() + 1);
    }   
}


var CustomerSelectorViewModel = function(bundles) {
  	this.selectedCustomerBundles = ko.observableArray(bundles || []);
    
}

var ViewModel = function() {
		var self = this;
    // more likely...