JSFiddle - React, Tailwind, and code Playground

by helgatheviking

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/accounting.js/0.4.1/accounting.min.js"></script>
<form class="cart" action="http://sandbox.test/product/simple-nyp/" method="post" enctype="multipart/form-data">

  <div class="nyp" data-minimum-error="Please enter at least %%MINIMUM%%." data-hide-minimum="" data-hide-minimum-error="Please enter a higher amount." data-max-price="99999" data-maximum-error="Please enter less than or equal to %%MAXIMUM%%." data-empty-error="Please enter an amount." data-min-price="49">

    <p class="price suggested-price"><span class="suggested-text">Suggested price: <span class="woocommerce-Price-amount amount"><span class="woocommerce-Price-currencySymbol">$</span>100.00</span></span></p>
    <label id="nyp-label-1" for="nyp-1">Name your price ( $ )</label><input id="nyp-1" name="nyp" type="text" value="" title="Name your price ( $ )" class="input-text amount nyp-input text" aria-describedby="nyp-description-amount-1" aria-labelledby="nyp-error-1 nyp-label-1">
    <div id="nyp-description-amount-1" class="nyp-screen-reader-text screen-reader-text">Suggested price: $100.00. Minimum price: $49.00</div>
    <p class="minimum-price nyp-terms">Minimum price: <span class="woocommerce-Price-amount amount"><span class="woocommerce-Price-currencySymbol">$</span>49.00</span></p>
    <div id="nyp-error-1" class="woocommerce-nyp-message" aria-live="assertive" style="display: none;">
      <ul class="woocommerce-error">
        <li>Please enter at least $49.00.</li>
      </ul>
    </div>
  </div>

  <div class="quantity">
    <label class="screen-reader-text" for="quantity_5e84fed5353fe">Simple NYP quantity</label>
    <input type="hidden" id="quantity_5e84fed5353fe" class="input-text qty text" value="1" name="quantity" value="1" title="Qty">
  </div>

  <button type="submit" name="add-to-cart" value="36" class="single_add_to_cart_button button alt">Add to cart</button>

</form>

CSS

.screen-reader-text { display: none }
label { display: block; }
.minimum-price { font-size: .75em; opacity: .6 }
.woocommerce-error { background: red; color: white; list-style: none; }
.quantity

JavaScript

var woocommerce_nyp_params = {
  "currency_format_num_decimals": "2",
  "currency_format_symbol": "$",
  "currency_format_decimal_sep": ".",
  "currency_format_thousand_sep": ",",
  "currency_format": "%s%v",
  "annual_price_factors": {
    "day": "365",
    "week": "52",
    "month": "12",
    "year": "1"
  }
};



// Format the price with accounting.js.
function woocommerce_nyp_format_price(price, currency_symbol, format) {

  if (typeof currency_symbol === 'undefined') {
    currency_symbol = '';
  }

  if (typeof format === 'undefined') {
    format = false;
  }

  var currency_format = format ? woocommerce_nyp_params.currency_format : '%v';

  return accounting.formatMoney(price, {
    symbol: currency_symbol,
    decimal: woocommerce_nyp_params.currency_format_decimal_sep,
    thousand: woocommerce_nyp_params.currency_format_thousand_sep,
    precision: woocommerce_nyp_params.currency_format_num_decimals,
    format: currency_format
  }).trim();

}

// Get absolute value of price and turn price into float decimal.
function woocommerce_nyp_unformat_price(price) {
  return Math.abs(parseFloat(accounting.unformat(price, woocommerce_nyp_params.currency_format_decimal_sep)));
}



$('form').on('click', '.single_add_to_cart_button', function(e) {

  e.preventDefault();

  var valid = true;

  $('form').find('.nyp').each(function() {
    if ($(this).hasClass('nyp-error')) {
      valid = false;
      return true;
    }
  });

  if (!valid) {
    alert('not submitted');
  } else {
    alert('submit');
  }

});


$('form').on('change', '.nyp-input', function(e) {

  var $nyp = $(this).closest('.nyp');
  $nyp.trigger( 'wc-nyp-update ');

});

$('form').on('wc-nyp-update', function(e) {

  var $nyp = $(this).find('.nyp');
  var $error = $nyp.find('.woocommerce-nyp-message');

  var user_price = woocommerce_nyp_unformat_price($(this).val());
  var min_price = $nyp.data('min-price');
  
  if (user_price < min_price) {
    $nyp.addClass('nyp-error');
   ...