diff --git a/lib/control-panel/routers/main.js b/lib/control-panel/routers/main.js index 6143421..7ef7a87 100644 --- a/lib/control-panel/routers/main.js +++ b/lib/control-panel/routers/main.js @@ -22,11 +22,21 @@ async function pageIndex(req, res) { limitedList[i].value = value; } + const products = limitedList.map((item) => item.product); + const maxValuesArray = await redisUtil.getMaxValuesForIndicator(products, xid); + const maxValues = {}; + const productCount = products.length; + for (let i = 0; i < productCount; i += 1) { + const product = products[i]; + maxValues[product] = Number(maxValuesArray[i]) || 0; + } + res.render( 'main.njk', { pageTitle: 'Produk dan Limit', limitedList, + maxValues, }, ); } @@ -86,6 +96,25 @@ async function pageAddProductQuota(req, res) { res.redirect(req.baseUrl); } +async function pageEditMaxValueForIndicator(req, res) { + const { xid } = res.locals; + const { product, maxValue } = req.body; + + try { + logger.info(`${MODULE_NAME}: Saving max value`, { + xid, product, maxValue, + }); + + await redisUtil.setMaxValueForIndicator(product, Number(maxValue), xid); + } catch (e) { + logger.warn(`${MODULE_NAME}: Exception on saving max value for indicator`, { + xid, product, maxValue, eCode: e.code, eMessage: e.message, + }); + } + + res.redirect(req.baseUrl); +} + router.use((req, res, next) => { res.locals.baseUrl = req.baseUrl; next(); @@ -98,3 +127,5 @@ router.get('/delete/:suplier/:product', pageDelete); router.post('/edit-product', express.urlencoded({ extended: false }), pageEditProductSubmit); router.post('/add-quota', express.urlencoded({ extended: false }), pageAddProductQuota); + +router.post('/edit-max-value-for-indicator', express.urlencoded({ extended: false }), pageEditMaxValueForIndicator); diff --git a/lib/control-panel/views/main.njk b/lib/control-panel/views/main.njk index e53c019..578b19c 100644 --- a/lib/control-panel/views/main.njk +++ b/lib/control-panel/views/main.njk @@ -5,18 +5,34 @@ <table class="table"> <thead> <tr> - <th>Produk</th> - <th class="text-right">Sisa Kuota</th> - <th> </th> + <th style="white-space: nowrap; width: 1%;">Produk</th> + <th class="text-right">Sisa</th> + <th style="white-space: nowrap; width: 1%;"> </th> </tr> </thead> <tbody> {% for item in limitedList %} <tr> - <td><strong>{{ item.product }}</strong></td> - <td class="text-right">{{ item.value }}</td> + <td style="white-space: nowrap; width: 1%;"> + <strong>{{ item.product }}</strong> + </td> + + <td class="text-right"> + {% set maxValue = maxValues[item.product] %} + {% if maxValue %} + <div class="progress"> + <div class="progress-bar" role="progressbar" style="width: {{ 100 * item.value / (maxValue or item.value) }}%;" aria-valuenow="25" aria-valuemin="0" aria-valuemax="{{ maxValue }}"></div> + </div> + <br> + {% endif %} - <td> + <a href="#" title="klik untuk edit nilai maksimal pada grafik indikator" data-toggle="modal" data-target="#editMaxValueModal" data-product="{{ item.product }}" data-maxvalue="{{ item.value }}"> + {{ item.value }} + {% if maxValue %} dari {{ maxValue }} {% endif %} + </a> + </td> + + <td style="white-space: nowrap; width: 1%;"> <button type="button" class="btn btn-primary btn-sm" data-toggle="modal" data-target="#editQuotaModal" data-product="{{ item.product }}"> Edit </button> @@ -117,6 +133,34 @@ </div> </form> +<form method="POST" action="{{ baseUrl }}/edit-max-value-for-indicator"> +<div class="modal fade" id="editMaxValueModal" tabindex="-1" role="dialog" aria-labelledby="editMaxValueModalLabel" aria-hidden="true"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title" id="editMaxValueModalLabel">Edit nilai maksimal pada indikator</h5> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"> + <span aria-hidden="true">×</span> + </button> + </div> + <div class="modal-body"> + <input type="hidden" name="product" id="inputProduct"> + <div class="form-group"> + <label for="raiseValue">Nilai maksimal</label> + <input name="maxValue" type="number" class="form-control" id="maxValue" aria-describedby="maxValueHelp" required> + <small id="maxValueHelp" class="form-text text-muted">Masukkan nilai maksimal (untuk tampilan grafik).</small> + </div> + </div> + + <div class="modal-footer"> + <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> + <input type="submit" class="btn btn-primary" value="Simpan"> + </div> + </div> + </div> +</div> +</form> + {% endblock %} {% block postScriptOnBody %} @@ -139,6 +183,17 @@ $('#addQuotaModal').on('show.bs.modal', function (event) { modal.find('.modal-title').text(`Tambah Kuota ${product}`); modal.find('.modal-body #inputProduct').val(product); }); + +$('#editMaxValueModal').on('show.bs.modal', function (event) { + var button = $(event.relatedTarget); + var product = button.data('product'); + var maxvalue = button.data('maxvalue'); + + var modal = $(this) + modal.find('.modal-title').text(`Edit nilai maksimal ${product}`); + modal.find('.modal-body #inputProduct').val(product); + modal.find('.modal-body #maxValue').val(maxvalue); +}); </script> {% endblock %} \ No newline at end of file diff --git a/lib/redis-util.js b/lib/redis-util.js index 945ab7a..80d709c 100644 --- a/lib/redis-util.js +++ b/lib/redis-util.js @@ -240,3 +240,47 @@ const limitedList = (xid) => new Promise((resolve, reject) => { }); }); exports.limitedList = limitedList; + +const setMaxValueForIndicator = (product, val, xid) => new Promise((resolve) => { + if (!(product || '').trim()) { + logger.warn(`${MODULE_NAME}: Skip saving max value for empty product`, { + xid, product, val, + }); + resolve(); + return; + } + + const keyword = `${composeKeyword(product)}_MAX_VALUE`; + logger.info(`${MODULE_NAME}: Saving max value`, { + xid, product, val, keyword, + }); + + redisClient.set(keyword, Number(val), 'EX', DEFAULT_TTL, (err) => { + if (err) { + logger.warn(`9E4965F4 ${MODULE_NAME}: Error on set max value on redis`, { + xid, product, val, eCode: err.code, eMessage: err.message, + }); + resolve(); + return; + } + + resolve(val); + }); +}); +exports.setMaxValueForIndicator = setMaxValueForIndicator; + +const getMaxValuesForIndicator = (products, xid) => new Promise((resolve, reject) => { + const keywords = products.map((item) => `${composeKeyword(item)}_MAX_VALUE`); + redisClient.mget(...keywords, (err, reply) => { + if (err) { + logger.warn(`63BE7706 ${MODULE_NAME}: Error on getting max values on redis`, { + xid, eCode: err.code, eMessage: err.message, + }); + reject(err); + return; + } + + resolve(reply); + }); +}); +exports.getMaxValuesForIndicator = getMaxValuesForIndicator;