JSFiddle - React, Tailwind, and code Playground

by moob

HTML

<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js?integrity=sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU"></script>
     I aready have an item on load
     
     <div id="qoBuilder">
    <div id="rfqs">
        <div class='rfqItem' data-rfqid="1" data-pc="6.1725"><div>Janet</div><div>20%</div><div>£123.45</div></div>
        <div class='rfqItem' data-rfqid="2" data-pc="7.44833333333"><div>John</div><div>30%</div><div>£223.45</div></div>
        <div class='rfqItem' data-rfqid="3" data-pc="8.08625"><div>Jamie</div><div>40%</div><div>£323.45</div></div>
    </div>

   
    <form class="qo">
        <div class="selectedRfqs">
          <div class='selectedRfqItem' data-rfqid="1" data-pc="6.1725"><div>Janet</div><div><input type="number" value="20" /></div><div>£123.45</div></div>
        </div>
    </form>
    <form class="qo qo_empty"></form>
</div>

CSS

#qoBuilder {
    border: 1px solid black;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
}
#rfqs, .selectedRfqs {
  width:100%;
}
.rfqItem, .selectedRfqItem {
  display:flex;
  margin:2px;
  background-color:#eee;
}
.rfqItem div, .selectedRfqItem div {
  border:1px solid black;
  padding:2px 5px;
}
input[type=number] {width:40px;}

.qo, .newqo {
    display: block;
    width: 200px;
    min-height: 100px;
    margin: 10px;
    background: #cccccc;
    border:2px solid #ccc;
}

.qo_empty {
    background: #eee;
    border:2px dotted #ccc;
    position:relative;
}

.qo_empty:after {
    content:"+";
    position:absolute;
    width:60px;
    height:60px;
    margin:auto;
    top:0; right:0; bottom:0; left:0;
    font-size:60px;
    line-height:60px;
    text-align:center;
}

.ui-droppable-hover {
 background: #ee6666;
}
.ui-draggable-dragging {
  z-index:999;
}

JavaScript

/* QuoteBuilder */
var QuoteBuilder = function($this, settings) {
    "use strict";
    console.log("QuoteBuilder",settings);
    var $builder = $this,
        $newqo = $this.find(settings.newQuoteOptionSelector)//.newqo
    var attachEvents = function() {
        $builder.on("createQuoteOption", createQuoteOption); //add another quote option
    };
    var createQuoteOption = function() {
    		console.log("createQuoteOption");
        var $newQoInstance = $("<form class='"+settings.quoteOptionsClassName+" qo_empty' />");
        var quoteOption = new QuoteOption($newQoInstance,$builder);
        $builder.append($newQoInstance);
        //$newQoInstance.trigger("drop",event, ui);//wrong
    };
    var init = function() {
        //init each rfqItem
        $builder.find(settings.rfqItemsSelector).each(function() {//"#rfqs li"
            var rfqItem = new RfqItem($(this),$builder);
        });
        //init each quoteOption
        $builder.find("."+settings.quoteOptionsClassName).each(function() {
            var quoteOption = new QuoteOption($(this),$builder);
        });
        //attach whatever 'events' that are specific to thei quoteBuilder instance
        attachEvents();
        //call optional onready callback
        if (typeof settings.onready === "function") {
        	settings.onready.call();
        }
        //testing
        console.log("$builder ready");        
    };
		//initialise this
    init();
};


/* RfqItem */
var RfqItem = function($this) {
    "use strict";
    console.log("RfqItem");
    var $rfqItem = $this;

    var init = function() {
        console.log("$rfqItem ready");
        $rfqItem.draggable({
            helper: 'clone'
        });
    };

    init();
};


/* QuoteOption */
var QuoteOption = function($this, $builder) {
    "use strict";
    console.log("QuoteOption");
    var $quoteOption = $this,
        rfqItems,
        iptAmount,
        total,
        title;

    var init = function() {
       ...