migrate to gtea from bistbucket
This commit is contained in:
111
public/assets/js/auth.js
Normal file
111
public/assets/js/auth.js
Normal file
@@ -0,0 +1,111 @@
|
||||
"use strict";
|
||||
|
||||
$(".hide-pass").on("click", function () {
|
||||
var model = $("#auth").data("model");
|
||||
$(this).toggleClass("show-pass");
|
||||
|
||||
// LOGIN
|
||||
if (model === "Login") {
|
||||
let passwordInput = $(".password");
|
||||
if (passwordInput.attr("type") === "password") {
|
||||
passwordInput.attr("type", "text");
|
||||
} else {
|
||||
passwordInput.attr("type", "password");
|
||||
}
|
||||
}
|
||||
// REGISTRATION & RESET PASSWORD
|
||||
else {
|
||||
let passwordInput = $(this).siblings("input");
|
||||
let passwordType = passwordInput.attr("type");
|
||||
if (passwordType === "password") {
|
||||
passwordInput.attr("type", "text");
|
||||
} else {
|
||||
passwordInput.attr("type", "password");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Fill email and password fields
|
||||
function fillup(email, password) {
|
||||
$(".email").val(email);
|
||||
$(".password").val(password);
|
||||
}
|
||||
|
||||
// OTP countdown------------------->
|
||||
let countdownInterval;
|
||||
function startCountdown(timeLeft) {
|
||||
const countdownElement = $("#countdown");
|
||||
const resendButton = $("#otp-resend");
|
||||
|
||||
// Function to format time as MM:SS
|
||||
function formatTime(seconds) {
|
||||
const minutes = Math.floor(seconds / 60);
|
||||
const remainingSeconds = seconds % 60;
|
||||
return `${String(minutes).padStart(2, "0")}:${String(remainingSeconds).padStart(2, "0")}`;
|
||||
}
|
||||
|
||||
// Clear any existing countdown interval
|
||||
if (countdownInterval) {
|
||||
clearInterval(countdownInterval);
|
||||
}
|
||||
|
||||
// Initialize countdown display
|
||||
countdownElement.text(formatTime(timeLeft));
|
||||
resendButton.addClass("disabled").attr("disabled", true); // Disable the button during countdown
|
||||
|
||||
// Start the new countdown interval
|
||||
countdownInterval = setInterval(() => {
|
||||
timeLeft--;
|
||||
|
||||
// Update the countdown text
|
||||
countdownElement.text(formatTime(timeLeft));
|
||||
|
||||
// Stop the countdown when timeLeft reaches zero
|
||||
if (timeLeft <= 0) {
|
||||
clearInterval(countdownInterval);
|
||||
countdownElement.text("00:00");
|
||||
|
||||
// Enable the resend button
|
||||
resendButton.removeClass("disabled").removeAttr("disabled");
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// Resend OTP
|
||||
$('#otp-resend').on('click', function () {
|
||||
const resendButton = $(this);
|
||||
|
||||
// Prevent action if the button is disabled
|
||||
if (resendButton.hasClass("disabled")) {
|
||||
return;
|
||||
}
|
||||
|
||||
const route = resendButton.data("route");
|
||||
const originalText = resendButton.text();
|
||||
const email = $("#dynamicEmail").text();
|
||||
|
||||
// Ensure email is available
|
||||
if (!email) {
|
||||
Notify("error", "Email is missing. Please try again.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Temporarily disable the button during the request
|
||||
resendButton.text("Sending...").addClass("disabled").attr("disabled", true);
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: route,
|
||||
data: { email: email },
|
||||
dataType: "json",
|
||||
success: function (response) {
|
||||
resendButton.text(originalText).addClass("disabled").attr("disabled", true);
|
||||
startCountdown(response.otp_expiration);
|
||||
},
|
||||
error: function (e) {
|
||||
resendButton.text(originalText).removeClass("disabled").removeAttr("disabled");
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
6
public/assets/js/bootstrap.bundle.min.js
vendored
Normal file
6
public/assets/js/bootstrap.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
36
public/assets/js/buttons.html5.min.js
vendored
Normal file
36
public/assets/js/buttons.html5.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
9
public/assets/js/buttons.print.min.js
vendored
Normal file
9
public/assets/js/buttons.print.min.js
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
/*!
|
||||
Print button for Buttons and DataTables.
|
||||
2016 SpryMedia Ltd - datatables.net/license
|
||||
*/
|
||||
(function(b){"function"===typeof define&&define.amd?define(["jquery","datatables.net","datatables.net-buttons"],function(d){return b(d,window,document)}):"object"===typeof exports?module.exports=function(d,h){d||(d=window);h&&h.fn.dataTable||(h=require("datatables.net")(d,h).$);h.fn.dataTable.Buttons||require("datatables.net-buttons")(d,h);return b(h,d,d.document)}:b(jQuery,window,document)})(function(b,d,h,y){var u=b.fn.dataTable,n=h.createElement("a"),v=function(a){n.href=a;a=n.host;-1===a.indexOf("/")&&
|
||||
0!==n.pathname.indexOf("/")&&(a+="/");return n.protocol+"//"+a+n.pathname+n.search};u.ext.buttons.print={className:"buttons-print",text:function(a){return a.i18n("buttons.print","Print")},action:function(a,e,p,k){a=e.buttons.exportData(b.extend({decodeEntities:!1},k.exportOptions));p=e.buttons.exportInfo(k);var w=e.columns(k.exportOptions.columns).flatten().map(function(f){return e.settings()[0].aoColumns[e.column(f).index()].sClass}).toArray(),r=function(f,g){for(var x="<tr>",l=0,z=f.length;l<z;l++)x+=
|
||||
"<"+g+" "+(w[l]?'class="'+w[l]+'"':"")+">"+(null===f[l]||f[l]===y?"":f[l])+"</"+g+">";return x+"</tr>"},m='<table class="'+e.table().node().className+'">';k.header&&(m+="<thead>"+r(a.header,"th")+"</thead>");m+="<tbody>";for(var t=0,A=a.body.length;t<A;t++)m+=r(a.body[t],"td");m+="</tbody>";k.footer&&a.footer&&(m+="<tfoot>"+r(a.footer,"th")+"</tfoot>");m+="</table>";var c=d.open("","");if(c){c.document.close();var q="<title>"+p.title+"</title>";b("style, link").each(function(){var f=q,g=b(this).clone()[0];
|
||||
"link"===g.nodeName.toLowerCase()&&(g.href=v(g.href));q=f+g.outerHTML});try{c.document.head.innerHTML=q}catch(f){b(c.document.head).html(q)}c.document.body.innerHTML="<h1>"+p.title+"</h1><div>"+(p.messageTop||"")+"</div>"+m+"<div>"+(p.messageBottom||"")+"</div>";b(c.document.body).addClass("dt-print-view");b("img",c.document.body).each(function(f,g){g.setAttribute("src",v(g.getAttribute("src")))});k.customize&&k.customize(c,k,e);a=function(){k.autoPrint&&(c.print(),c.close())};navigator.userAgent.match(/Trident\/\d.\d/)?
|
||||
a():c.setTimeout(a,1E3)}else e.buttons.info(e.i18n("buttons.printErrorTitle","Unable to open print view"),e.i18n("buttons.printErrorMsg","Please allow popups in your browser for this site to be able to view the print view."),5E3)},title:"*",messageTop:"*",messageBottom:"*",exportOptions:{},header:!0,footer:!1,autoPrint:!0,customize:null};return u.Buttons});
|
||||
13
public/assets/js/chart.min.js
vendored
Normal file
13
public/assets/js/chart.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
4296
public/assets/js/choices.min.js
vendored
Normal file
4296
public/assets/js/choices.min.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
264
public/assets/js/custom-ajax.js
Normal file
264
public/assets/js/custom-ajax.js
Normal file
@@ -0,0 +1,264 @@
|
||||
"use strict";
|
||||
|
||||
/** confirm modal start */
|
||||
$.ajaxSetup({
|
||||
headers: {
|
||||
"X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"),
|
||||
},
|
||||
});
|
||||
|
||||
$(document).on("click", ".confirm-action", function (event) {
|
||||
event.preventDefault();
|
||||
let url = $(this).data("action") ?? $(this).attr("href");
|
||||
let method = $(this).data("method") ?? "POST";
|
||||
let icon = $(this).data("icon") ?? "fas fa-warning";
|
||||
|
||||
$.confirm({
|
||||
title: "Are you sure?",
|
||||
icon: icon,
|
||||
theme: "modern",
|
||||
closeIcon: true,
|
||||
animation: "scale",
|
||||
type: "red",
|
||||
scrollToPreviousElement: false,
|
||||
scrollToPreviousElementAnimate: false,
|
||||
buttons: {
|
||||
confirm: {
|
||||
btnClass: "btn-red",
|
||||
action: function () {
|
||||
event.preventDefault();
|
||||
$.ajax({
|
||||
type: method,
|
||||
url: url,
|
||||
success: function (response) {
|
||||
if (response.redirect) {
|
||||
window.sessionStorage.hasPreviousMessage = true;
|
||||
window.sessionStorage.previousMessage =
|
||||
response.message ?? null;
|
||||
|
||||
location.href = response.redirect;
|
||||
} else {
|
||||
Notify("success", response);
|
||||
}
|
||||
},
|
||||
error: function (xhr, status, error) {
|
||||
Notify("error", xhr);
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
close: {
|
||||
action: function () {
|
||||
this.buttons.close.hide();
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
/**confirm modal end */
|
||||
|
||||
$('.filter-form').on('input', function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
let $form = $(this);
|
||||
let table = $form.attr('table');
|
||||
let method = $form.attr('method') || "GET";
|
||||
let url = $form.attr('action') + '?' + $form.serialize();
|
||||
|
||||
$.ajax({
|
||||
type: method,
|
||||
url: url,
|
||||
dataType: "json",
|
||||
success: function (res) {
|
||||
$(table).html(res.data);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/** filter all from end */
|
||||
|
||||
/** DELETE ACTION */
|
||||
$(document).on("click", ".delete-confirm", function (e) {
|
||||
e.preventDefault();
|
||||
let t = $(this),
|
||||
o = t.attr("href") ?? t.data("action"),
|
||||
i = t.html();
|
||||
|
||||
// Create modal dynamically
|
||||
let confirmationModal = `
|
||||
<div class="modal fade" id="delete-confirmation-modal" tabindex="-1" aria-labelledby="delete-confirmation-modal-label" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="text-end">
|
||||
<button type="button" class="btn-close m-3 mb-0" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="delete-modal text-center mb-lg-4">
|
||||
<h5>Are You Sure?</h5>
|
||||
<p>You won't be able to revert this!</p>
|
||||
</div>
|
||||
<div class="d-flex justify-content-center">
|
||||
<div class="button-group">
|
||||
<button class="btn reset-btn border rounded" data-bs-dismiss="modal">Cancel</button>
|
||||
<button class="btn theme-btn border rounded delete-confirmation-button">Yes, Delete It!</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
$("body").append(confirmationModal); // Append modal to the body
|
||||
$("#delete-confirmation-modal").modal("show");
|
||||
|
||||
// handle dynamic modal
|
||||
$(".delete-confirmation-button").on("click", function () {
|
||||
$.ajax({
|
||||
url: o,
|
||||
data: { _token: CSRF_TOKEN },
|
||||
type: "DELETE",
|
||||
beforeSend: function () {
|
||||
t.html($savingLoader).attr("disabled", true);
|
||||
},
|
||||
success: function (e) {
|
||||
t.html(i).removeClass("disabled").attr("disabled", false);
|
||||
ajaxSuccess(e, t);
|
||||
},
|
||||
error: function (e) {
|
||||
t.html(i).removeClass("disabled").attr("disabled", false);
|
||||
Notify(e);
|
||||
},
|
||||
});
|
||||
|
||||
// Hide and remove modal
|
||||
$("#delete-confirmation-modal").modal("hide");
|
||||
$("#delete-confirmation-modal").remove();
|
||||
});
|
||||
});
|
||||
|
||||
// Listen for input changes and update feature values accordingly
|
||||
$("#words_limit").on("input", function () {
|
||||
$("#word_feature").val($("#words_limit").val() + " Word Limit");
|
||||
});
|
||||
|
||||
$("#images_limit").on("input", function () {
|
||||
$("#image_feature").val($("#images_limit").val() + " images Limit");
|
||||
});
|
||||
|
||||
$(".exit-branch-btn").on("click", function () {
|
||||
$(".exit-title").text($(this).data("title"));
|
||||
$(".exit-branch").attr("href", $(this).data("exit-url"));
|
||||
$("#exitModal").modal("show");
|
||||
});
|
||||
|
||||
$(document).ready(function () {
|
||||
$(".logoutButton").on("click", function () {
|
||||
document.getElementById("logoutForm").submit();
|
||||
});
|
||||
|
||||
$(document).on('change', '.custom-reports-checkbox', function() {
|
||||
if ($('.custom-reports-checkbox:checked').length === $('.custom-reports-checkbox').length) {
|
||||
$('#selectAll').prop('checked', true);
|
||||
} else {
|
||||
$('#selectAll').prop('checked', false);
|
||||
}
|
||||
});
|
||||
|
||||
var reportType = $("#reportType").val();
|
||||
var reportFields = JSON.parse($("#reportFields").val() || "[]");
|
||||
var prevFields = JSON.parse($("#prevFields").val() || "[]");
|
||||
|
||||
$("#type").on("change", function () {
|
||||
var type = $(this).val();
|
||||
generateCheckboxes(type);
|
||||
});
|
||||
|
||||
if (reportType) {
|
||||
generateCheckboxes(reportType);
|
||||
}
|
||||
|
||||
// Recursive function to flatten nested fields
|
||||
function flattenFields(obj, prefix = "") {
|
||||
var flat = {};
|
||||
$.each(obj, function (key, value) {
|
||||
if (value.label !== undefined) {
|
||||
flat[prefix + key] = value;
|
||||
} else {
|
||||
$.extend(flat, flattenFields(value, prefix + key + "."));
|
||||
}
|
||||
});
|
||||
return flat;
|
||||
}
|
||||
|
||||
function generateCheckboxes(type) {
|
||||
if (!type) {
|
||||
$(".select-type-text").text("Select a report type to load fields");
|
||||
$("#fieldsContainer").empty();
|
||||
return;
|
||||
}
|
||||
|
||||
var fields = reportFields[type] || {};
|
||||
var multibranch_active = $('#multibranch_active').val();
|
||||
|
||||
// 🔹 Remove branch if multibranch is not active
|
||||
if (multibranch_active != 1 && fields.branch) {
|
||||
delete fields.branch;
|
||||
}
|
||||
|
||||
var flatFields = flattenFields(fields);
|
||||
|
||||
// Create lookup map from prevFields
|
||||
var prevMap = {};
|
||||
prevFields.forEach(function (item) {
|
||||
prevMap[item.field] = item.order;
|
||||
});
|
||||
|
||||
var entries = Object.entries(flatFields);
|
||||
var half = Math.ceil(entries.length / 2);
|
||||
|
||||
// Helper to build checkbox grid
|
||||
function buildColumn(items) {
|
||||
var html = `<div class="col-lg-6">`;
|
||||
$.each(items, function (_, [key, row]) {
|
||||
var checked = prevMap[key] !== undefined ? "checked" : "";
|
||||
var orderVal = prevMap[key] !== undefined ? prevMap[key] : "";
|
||||
html += `
|
||||
<div class="custom-report-grid custom-report-check">
|
||||
<div class="d-flex align-items-center mb-2 mt-2">
|
||||
<input type="checkbox" id="field_${key}" class="delete-checkbox-item multi-delete custom-reports-checkbox" name="fields[]" value="${key}" ${checked}>
|
||||
<label for="field_${key}" class="custom-top-label">${row.label}</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" name="order[]" placeholder="Enter order no" class="custom-input" value="${orderVal}">
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
html += `</div>`;
|
||||
return html;
|
||||
}
|
||||
|
||||
var html =
|
||||
`<div class="row">` +
|
||||
buildColumn(entries.slice(0, half)) +
|
||||
buildColumn(entries.slice(half)) +
|
||||
`</div>`;
|
||||
|
||||
$(".select-type-text").text("");
|
||||
$("#fieldsContainer").html(html);
|
||||
|
||||
if ($('.custom-reports-checkbox:checked').length === $('.custom-reports-checkbox').length && $('.custom-reports-checkbox').length > 0) {
|
||||
$('#selectAll').prop('checked', true);
|
||||
} else {
|
||||
$('#selectAll').prop('checked', false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$("#selectAll").on("change", function () {
|
||||
const isChecked = $(this).is(":checked");
|
||||
$(".delete-checkbox-item").prop("checked", isChecked);
|
||||
});
|
||||
413
public/assets/js/custom/account.js
Normal file
413
public/assets/js/custom/account.js
Normal file
@@ -0,0 +1,413 @@
|
||||
"use strict";
|
||||
|
||||
// Toggle extra input fields in the "Add New Bank" modal
|
||||
$(".more-field-btn").on("click", function () {
|
||||
const $extraFields = $(".extra-fields");
|
||||
const $toggleBtn = $(this);
|
||||
|
||||
if ($extraFields.hasClass("hidden-fields")) {
|
||||
$extraFields.removeClass("hidden-fields");
|
||||
$toggleBtn.text("- Hide fields");
|
||||
} else {
|
||||
$extraFields.addClass("hidden-fields");
|
||||
$toggleBtn.text("+ Add more fields");
|
||||
}
|
||||
});
|
||||
|
||||
/** Dynamically Bank Transaction Modal Open start */
|
||||
// Fetch banks
|
||||
function fetchBanks(callback) {
|
||||
var url = $('#get_banks').val();
|
||||
$.get(url, function(data) {
|
||||
var options = '<option value="">Select one</option>';
|
||||
data.forEach(function(bank) {
|
||||
options += `<option value="${bank.id}">${bank.name}</option>`;
|
||||
});
|
||||
callback(options);
|
||||
});
|
||||
}
|
||||
|
||||
// Open modal dynamically & build From/To fields based on type
|
||||
function openTransactionModal(type, transaction = null, route = null) {
|
||||
var $modal = $('#bankTransactionModal');
|
||||
var $title = $('#transactionModalTitle');
|
||||
var $modalBody = $modal.find('.modal-body .row');
|
||||
var $form = $modal.find('form');
|
||||
|
||||
// Remove old dynamic fields
|
||||
$modalBody.find('.dynamic-field').remove();
|
||||
|
||||
// transaction_type input field
|
||||
$modal.find('input[name="transaction_type"]').remove();
|
||||
$form.append(`<input type="hidden" name="transaction_type" value="${type}">`);
|
||||
|
||||
// Set form action & method
|
||||
if (transaction && route) {
|
||||
// Edit mode
|
||||
$form.attr('action', route);
|
||||
if ($form.find('input[name="_method"]').length === 0) {
|
||||
$form.append('<input type="hidden" name="_method" value="PUT">');
|
||||
} else {
|
||||
$form.find('input[name="_method"]').val('PUT');
|
||||
}
|
||||
} else {
|
||||
// Create mode
|
||||
$form.attr('action', route);
|
||||
$form.find('input[name="_method"]').remove();
|
||||
}
|
||||
|
||||
// Fetch banks and build fields
|
||||
fetchBanks(function(options){
|
||||
var content = '';
|
||||
var titleText = '';
|
||||
|
||||
if (type === 'bank_to_bank') {
|
||||
titleText = 'Bank to Bank Transfer';
|
||||
content = `
|
||||
<div class="col-lg-6 mb-2 dynamic-field">
|
||||
<label>From</label>
|
||||
<select name="from" class="form-control table-select w-100 from" required>${options}</select>
|
||||
</div>
|
||||
<div class="col-lg-6 mb-2 dynamic-field">
|
||||
<label>To</label>
|
||||
<select name="to" class="form-control table-select w-100 to" required>${options}</select>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
if (type === 'bank_to_cash') {
|
||||
titleText = 'Bank to Cash Transfer';
|
||||
content = `
|
||||
<div class="col-lg-6 mb-2 dynamic-field">
|
||||
<label>From</label>
|
||||
<select name="from" class="form-control table-select w-100 from" required>${options}</select>
|
||||
</div>
|
||||
<div class="col-lg-6 mb-2 dynamic-field">
|
||||
<label>To</label>
|
||||
<input type="text" readonly value="Cash" class="form-control to">
|
||||
</div>`;
|
||||
}
|
||||
|
||||
if (type === 'adjust_bank') {
|
||||
titleText = 'Adjust Bank Balance';
|
||||
content = `
|
||||
<div class="col-lg-6 mb-2 dynamic-field">
|
||||
<label>Account Name</label>
|
||||
<select name="from" class="form-control table-select w-100 from" required>${options}</select>
|
||||
</div>
|
||||
<div class="col-lg-6 mb-2 dynamic-field">
|
||||
<label>Type</label>
|
||||
<select name="type" class="form-control table-select w-100 type" required>
|
||||
<option value="credit">Increase balance</option>
|
||||
<option value="debit">Decrease balance</option>
|
||||
</select>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
if (type === 'cash_to_bank') {
|
||||
titleText = 'Cash To Bank Transfer';
|
||||
content = `
|
||||
<div class="col-lg-6 mb-2 dynamic-field">
|
||||
<label>From</label>
|
||||
<input type="text" readonly name="from" value="Cash" class="form-control from">
|
||||
</div>
|
||||
<div class="col-lg-6 mb-2 dynamic-field">
|
||||
<label>To</label>
|
||||
<select name="to" class="form-control table-select w-100 to" required>${options}</select>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
if (type === 'adjust_cash') {
|
||||
titleText = 'Adjust Cash Balance';
|
||||
|
||||
var creditChecked = transaction && transaction.type === 'credit' ? 'checked' : '';
|
||||
var debitChecked = transaction && transaction.type === 'debit' ? 'checked' : '';
|
||||
|
||||
content = `
|
||||
<div class="col-lg-12 mb-3 dynamic-field">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="type" id="addCash" value="credit" ${creditChecked}>
|
||||
<label class="form-check-label cash-label" for="addCash">
|
||||
Add Cash
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="type" id="reduceCash" value="debit" ${debitChecked}>
|
||||
<label class="form-check-label cash-label" for="reduceCash">
|
||||
Reduce Cash
|
||||
</label>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
// Insert dynamic fields
|
||||
$modalBody.prepend(content);
|
||||
|
||||
// Set modal title
|
||||
$title.text(titleText);
|
||||
|
||||
if (transaction) {
|
||||
$modal.find('.from').val(transaction.from);
|
||||
$modal.find('.type').val(transaction.type);
|
||||
$modal.find('.amount').val(transaction.amount);
|
||||
$modal.find('.date').val(transaction.date);
|
||||
$modal.find('.note').val(transaction.note);
|
||||
|
||||
// Special handling for To field
|
||||
if (type === 'bank_to_cash') {
|
||||
$modal.find('.to').val('Cash');
|
||||
} else if (type === 'cash_to_bank') {
|
||||
$modal.find('.to').val(transaction.to);
|
||||
} else {
|
||||
$modal.find('.to').val(transaction.to);
|
||||
}
|
||||
|
||||
if(transaction.image) {
|
||||
$('#customPreviewImg').attr('src', transaction.image).show();
|
||||
$('#customUploadContent').hide();
|
||||
} else {
|
||||
$('#customPreviewImg').hide();
|
||||
$('#customUploadContent').show();
|
||||
}
|
||||
}
|
||||
|
||||
// Show modal
|
||||
new bootstrap.Modal($modal[0]).show();
|
||||
});
|
||||
}
|
||||
|
||||
// Create buttons
|
||||
$('#bank_to_bank, #bank_to_cash, #adjust_bank, #cash_to_bank, #adjust_cash').on('click', function() {
|
||||
var type = this.id;
|
||||
var route = $(this).data('route');
|
||||
|
||||
openTransactionModal(type, null, route);
|
||||
});
|
||||
|
||||
// Edit buttons
|
||||
$(document).on('click', '.edit-transaction', function() {
|
||||
var transactionType = $(this).data('transaction_type');
|
||||
var transaction = {
|
||||
amount: $(this).data('amount'),
|
||||
date: $(this).data('date'),
|
||||
note: $(this).data('note'),
|
||||
type: $(this).data('type'),
|
||||
image: $(this).data('image')
|
||||
};
|
||||
|
||||
// handling for cash transactions
|
||||
if(transactionType === 'cash_to_bank') {
|
||||
transaction.from = 'Cash';
|
||||
transaction.to = $(this).data('to'); // bank id
|
||||
} else if(transactionType === 'adjust_cash') {
|
||||
transaction.type = $(this).data('type'); // credit/debit
|
||||
} else {
|
||||
// bank transactions
|
||||
transaction.from = $(this).data('from');
|
||||
transaction.to = $(this).data('to');
|
||||
}
|
||||
|
||||
var route = $(this).data('route');
|
||||
|
||||
openTransactionModal(transactionType, transaction, route);
|
||||
});
|
||||
|
||||
/** Dynamically Bank Transaction Modal Open end */
|
||||
|
||||
// Cheque transfer start
|
||||
$(document).on("click", ".cheque-transfer-btn", function () {
|
||||
var received_from = $(this).data("received-from");
|
||||
var cheque_amount = $(this).data("cheque-amount");
|
||||
var cheque_no = $(this).data("cheque-no");
|
||||
var cheque_date = $(this).data("cheque-date");
|
||||
var ref_no = $(this).data("ref-no");
|
||||
var transaction_id = $(this).data("transaction-id");
|
||||
|
||||
$("#received_from").text(received_from);
|
||||
$("#cheque_amount").text(cheque_amount);
|
||||
$("#cheque_no").text(cheque_no);
|
||||
$("#cheque_date").text(cheque_date);
|
||||
$("#ref_no").text(ref_no);
|
||||
$("#deposit_transaction_id").val(transaction_id);
|
||||
});
|
||||
// Cheque transfer end
|
||||
|
||||
// When clicking Re-Open button
|
||||
$(document).on("click", ".reopen-btn", function () {
|
||||
|
||||
let transaction_id = $(this).data("transaction-id");
|
||||
|
||||
$("#reopen_transaction_id").val(transaction_id);
|
||||
|
||||
let $modalEl = $("#reopen");
|
||||
let modal = new bootstrap.Modal($modalEl[0]);
|
||||
modal.show();
|
||||
});
|
||||
|
||||
// Bank Accounts Img upload ----------->
|
||||
// Bank Accounts Img upload ----------->
|
||||
$(document).ready(function () {
|
||||
const $fileInput = $("#customFileInput");
|
||||
const $previewImg = $("#customPreviewImg");
|
||||
const $content = $("#customUploadContent");
|
||||
|
||||
$fileInput.on("change", function () {
|
||||
const file = this.files[0];
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
$previewImg.attr("src", e.target.result).show();
|
||||
$content.hide();
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Bank edit start
|
||||
$(document).on("click", ".bank-edit-btn", function () {
|
||||
var url = $(this).data("url");
|
||||
var name = $(this).data("name");
|
||||
var opening_balance = $(this).data("opening-balance");
|
||||
var opening_date = $(this).data("opening-date");
|
||||
var account_number = $(this).data("account-number");
|
||||
var routing_number = $(this).data("routing-number");
|
||||
var upi_id = $(this).data("upi-id");
|
||||
var bank_name = $(this).data("bank-name");
|
||||
var branch_name = $(this).data("branch-name");
|
||||
var account_holder = $(this).data("account-holder");
|
||||
var show_in_invoice = $(this).data("show-in-invoice");
|
||||
|
||||
$("#name").val(name);
|
||||
$("#opening_balance").val(opening_balance);
|
||||
$("#opening_date").val(opening_date);
|
||||
$("#account_number").val(account_number);
|
||||
$("#routing_number").val(routing_number);
|
||||
$("#upi_id").val(upi_id);
|
||||
$("#bank_name").val(bank_name);
|
||||
$("#branch_name").val(branch_name);
|
||||
$("#account_holder").val(account_holder);
|
||||
$("#show_in_invoice").prop('checked', show_in_invoice === 1);
|
||||
|
||||
$(".bankUpdateForm").attr("action", url);
|
||||
});
|
||||
// Bank edit end
|
||||
|
||||
// Bank view start
|
||||
$(document).on("click", ".bank-view-btn", function () {
|
||||
var name = $(this).data("name");
|
||||
var balance = $(this).data("balance");
|
||||
var opening_date = $(this).data("opening-date");
|
||||
var account_number = $(this).data("account-number");
|
||||
var bank_name = $(this).data("bank-name");
|
||||
var branch_name = $(this).data("branch-name");
|
||||
var routing_number = $(this).data("routing-number");
|
||||
var upi_id = $(this).data("upi-id");
|
||||
var account_holder = $(this).data("account-holder");
|
||||
var show_in_invoice = $(this).data("show-in-invoice");
|
||||
|
||||
$("#view_account_name").text(name);
|
||||
$("#view_balance").text(balance);
|
||||
$("#view_opening_date").text(opening_date);
|
||||
$("#view_account_number").text(account_number);
|
||||
$("#view_bank_name").text(bank_name);
|
||||
$("#view_branch_name").text(branch_name);
|
||||
$("#view_routing_number").text(routing_number);
|
||||
$("#view_upi_id").text(upi_id);
|
||||
$("#view_account_holder").text(account_holder);
|
||||
$("#view_show_in_invoice").text(show_in_invoice == 1 ? 'Yes' : 'No');
|
||||
});
|
||||
// Bank view end
|
||||
|
||||
// Bank Delete Start
|
||||
$(document).on("click", ".delete-bank-action", function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
let url = $(this).data("action") ?? $(this).attr("href");
|
||||
let method = $(this).data("method") ?? "DELETE";
|
||||
let icon = $(this).data("icon") ?? "fas fa-trash-alt";
|
||||
|
||||
$.confirm({
|
||||
title: "Are you sure?",
|
||||
icon: icon,
|
||||
theme: "modern",
|
||||
closeIcon: true,
|
||||
animation: "scale",
|
||||
type: "red",
|
||||
buttons: {
|
||||
confirm: {
|
||||
btnClass: "btn-red",
|
||||
action: function () {
|
||||
$.ajax({
|
||||
type: method,
|
||||
url: url,
|
||||
success: function (response) {
|
||||
if (response === false) {
|
||||
$("#warning-modal").modal("show");
|
||||
}
|
||||
else if (response.redirect) {
|
||||
window.sessionStorage.hasPreviousMessage = true;
|
||||
window.sessionStorage.previousMessage =
|
||||
response.message ?? null;
|
||||
location.href = response.redirect;
|
||||
}
|
||||
else {
|
||||
Notify("success", response.message || response);
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
Notify(
|
||||
"error",
|
||||
xhr.responseJSON?.message || "Something went wrong!"
|
||||
);
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
close: {
|
||||
action: function () {
|
||||
this.buttons.close.hide();
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
// Bank Delete Start
|
||||
|
||||
// Transaction view start
|
||||
$(document).on("click", ".transaction-view-btn", function () {
|
||||
var img = $(this).data("img");
|
||||
var user = $(this).data("user");
|
||||
var transaction_type = $(this).data("transaction-type");
|
||||
var amount = $(this).data("amount");
|
||||
var date = $(this).data("date");
|
||||
var note = $(this).data("note");
|
||||
|
||||
$("#view_img").attr("src", img);
|
||||
$("#view_user").text(user);
|
||||
$("#view_transaction_type").text(transaction_type);
|
||||
$("#view_amount").text(amount);
|
||||
$("#view_date").text(date);
|
||||
$("#view_note").text(note);
|
||||
});
|
||||
// Transaction view end
|
||||
|
||||
// Cash Transaction view start
|
||||
$(document).on("click", ".cash-view-btn", function () {
|
||||
var img = $(this).data("img");
|
||||
var user = $(this).data("user");
|
||||
var transaction_type = $(this).data("transaction-type");
|
||||
var platform = $(this).data("platform");
|
||||
var amount = $(this).data("amount");
|
||||
var note = $(this).data("note");
|
||||
var date = $(this).data("date");
|
||||
|
||||
$("#view_img").attr("src", img);
|
||||
$("#view_user").text(user);
|
||||
$("#view_transaction_type").text(transaction_type);
|
||||
$("#view_platform").text(platform);
|
||||
$("#view_amount").text(amount);
|
||||
$("#view_note").text(note);
|
||||
$("#view_date").text(date);
|
||||
});
|
||||
// Cash Transaction view end
|
||||
|
||||
80
public/assets/js/custom/calculator.js
Normal file
80
public/assets/js/custom/calculator.js
Normal file
@@ -0,0 +1,80 @@
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const display = document.getElementById("display");
|
||||
let currentExpression = "";
|
||||
|
||||
|
||||
function buttonClickHandler(event) {
|
||||
const buttonValue = event.target.innerText;
|
||||
|
||||
|
||||
if (buttonValue === "C") {
|
||||
currentExpression = "";
|
||||
}
|
||||
|
||||
else if (buttonValue === "⌫") {
|
||||
currentExpression = currentExpression.slice(0, -1);
|
||||
}
|
||||
|
||||
else if (buttonValue === "=") {
|
||||
try {
|
||||
currentExpression = calculate(currentExpression).toString();
|
||||
} catch {
|
||||
currentExpression = "Error";
|
||||
}
|
||||
}
|
||||
|
||||
else if (buttonValue === "√") {
|
||||
if (!currentExpression) {
|
||||
currentExpression = "Error";
|
||||
} else {
|
||||
currentExpression = Math.sqrt(parseFloat(currentExpression)).toString();
|
||||
}
|
||||
}
|
||||
|
||||
else if (buttonValue === "x²") {
|
||||
if (!currentExpression) {
|
||||
currentExpression = "Error";
|
||||
} else {
|
||||
currentExpression = Math.pow(parseFloat(currentExpression), 2).toString();
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
if (currentExpression === "Error") {
|
||||
currentExpression = "";
|
||||
}
|
||||
currentExpression += buttonValue;
|
||||
}
|
||||
|
||||
|
||||
display.value = currentExpression;
|
||||
}
|
||||
|
||||
|
||||
function calculate(expression) {
|
||||
|
||||
expression = expression
|
||||
.replace(/×/g, "*")
|
||||
.replace(/÷/g, "/")
|
||||
.replace(/−/g, "-");
|
||||
|
||||
|
||||
try {
|
||||
const result = Function(`return (${expression})`)();
|
||||
if (result === Infinity || result === -Infinity || isNaN(result)) {
|
||||
throw new Error("Math Error");
|
||||
}
|
||||
return result;
|
||||
} catch {
|
||||
return "Error";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const calculatorButtons = document.querySelectorAll(".button-row button");
|
||||
calculatorButtons.forEach(button => {
|
||||
button.addEventListener("click", buttonClickHandler);
|
||||
});
|
||||
});
|
||||
8
public/assets/js/custom/custom-alart.js
Normal file
8
public/assets/js/custom/custom-alart.js
Normal file
@@ -0,0 +1,8 @@
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const alertBox = document.getElementById("alertBox");
|
||||
const closeBtn = document.querySelector(".alert-close-btn");
|
||||
|
||||
closeBtn.addEventListener("click", () => {
|
||||
alertBox.style.display = "none";
|
||||
});
|
||||
});
|
||||
3032
public/assets/js/custom/custom.js
Normal file
3032
public/assets/js/custom/custom.js
Normal file
File diff suppressed because it is too large
Load Diff
33
public/assets/js/custom/custome-dropdown.js
Normal file
33
public/assets/js/custom/custome-dropdown.js
Normal file
@@ -0,0 +1,33 @@
|
||||
const dropdown = document.getElementById("myDropdown");
|
||||
|
||||
if (dropdown) {
|
||||
const selected = dropdown.querySelector("#selectedOption");
|
||||
const options = dropdown.querySelector("#dropdownOptions");
|
||||
const arrow = dropdown.querySelector("#dropdownArrow");
|
||||
const items = dropdown.querySelectorAll(".dropdown-option");
|
||||
|
||||
const batchInput = document.getElementById("selected_batch_no");
|
||||
|
||||
selected.addEventListener("click", () => {
|
||||
const isOpen = options.style.display === "block";
|
||||
options.style.display = isOpen ? "none" : "block";
|
||||
dropdown.classList.toggle("open", !isOpen);
|
||||
});
|
||||
|
||||
items.forEach((item) => {
|
||||
item.addEventListener("click", () => {
|
||||
selected.querySelector("span").innerHTML = item.innerHTML;
|
||||
batchInput.value = item.getAttribute("data-batch-no");
|
||||
|
||||
options.style.display = "none";
|
||||
dropdown.classList.remove("open");
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener("click", function (e) {
|
||||
if (!dropdown.contains(e.target)) {
|
||||
options.style.display = "none";
|
||||
dropdown.classList.remove("open");
|
||||
}
|
||||
});
|
||||
}
|
||||
55
public/assets/js/custom/math.min.js
vendored
Normal file
55
public/assets/js/custom/math.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1103
public/assets/js/custom/product.js
Normal file
1103
public/assets/js/custom/product.js
Normal file
File diff suppressed because it is too large
Load Diff
620
public/assets/js/custom/purchase.js
Normal file
620
public/assets/js/custom/purchase.js
Normal file
@@ -0,0 +1,620 @@
|
||||
$(document).ready(function () {
|
||||
var $sidebarPlan = $(".lg-sub-plan");
|
||||
var $subPlan = $(".sub-plan");
|
||||
var isActive = $(window).width() >= 1150;
|
||||
|
||||
$(".side-bar, .section-container").toggleClass("active", isActive);
|
||||
|
||||
if (isActive) {
|
||||
$sidebarPlan.hide();
|
||||
$subPlan.show();
|
||||
|
||||
$(".side-bar-addon, .side-bar-addon-2, .side-bar-addon-3").hide();
|
||||
} else {
|
||||
$sidebarPlan.show();
|
||||
$subPlan.hide();
|
||||
|
||||
$(".side-bar-addon, .side-bar-addon-2, .side-bar-addon-3").show();
|
||||
}
|
||||
});
|
||||
|
||||
// get number only
|
||||
function getNumericValue(value) {
|
||||
return parseFloat(value.replace(/[^0-9.-]+/g, "")) || 0;
|
||||
}
|
||||
|
||||
// Update the cart list and call the callback once complete
|
||||
function fetchUpdatedCart(callback) {
|
||||
let url = $("#purchase-cart").val();
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: "GET",
|
||||
success: function (response) {
|
||||
$("#purchase_cart_list").html(response);
|
||||
if (typeof callback === "function") callback(); // Call the callback after updating the cart
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
//increase quantity
|
||||
$(document).on("click", ".plus-btn", function (e) {
|
||||
e.preventDefault();
|
||||
let $row = $(this).closest("tr");
|
||||
let rowId = $row.data("row_id");
|
||||
let updateRoute = $row.data("update_route");
|
||||
let $qtyInput = $row.find(".cart-qty");
|
||||
let currentQty = parseFloat($qtyInput.val());
|
||||
|
||||
let newQty = currentQty + 1;
|
||||
$qtyInput.val(newQty);
|
||||
updateCartQuantity(rowId, newQty, updateRoute);
|
||||
});
|
||||
|
||||
//decrease quantity
|
||||
$(document).on("click", ".minus-btn", function (e) {
|
||||
e.preventDefault();
|
||||
let $row = $(this).closest("tr");
|
||||
let rowId = $row.data("row_id");
|
||||
let updateRoute = $row.data("update_route");
|
||||
let $qtyInput = $row.find(".cart-qty");
|
||||
let currentQty = parseFloat($qtyInput.val());
|
||||
|
||||
// Ensure quantity does not go below 1
|
||||
if (currentQty > 1) {
|
||||
let newQty = currentQty - 1;
|
||||
$qtyInput.val(newQty);
|
||||
updateCartQuantity(rowId, newQty, updateRoute);
|
||||
}
|
||||
});
|
||||
|
||||
// Cart quantity input field change event
|
||||
$(document).on("change", ".cart-qty", function () {
|
||||
let $row = $(this).closest("tr");
|
||||
let rowId = $row.data("row_id");
|
||||
let updateRoute = $row.data("update_route");
|
||||
let newQty = parseFloat($(this).val());
|
||||
|
||||
// Ensure quantity does not go below 1
|
||||
if (newQty >= 0) {
|
||||
updateCartQuantity(rowId, newQty, updateRoute);
|
||||
}
|
||||
});
|
||||
|
||||
// Remove item from the cart
|
||||
$(document).on("click", ".remove-btn", function (e) {
|
||||
e.preventDefault();
|
||||
var $row = $(this).closest("tr");
|
||||
var destroyRoute = $row.data("destroy_route");
|
||||
|
||||
$.ajax({
|
||||
url: destroyRoute,
|
||||
type: "DELETE",
|
||||
success: function (response) {
|
||||
if (response.success) {
|
||||
// Item was successfully removed, fade out and remove the row from DOM
|
||||
$row.fadeOut(400, function () {
|
||||
$(this).remove();
|
||||
});
|
||||
// Recalculate and update cart totals
|
||||
fetchUpdatedCart(calTotalAmount);
|
||||
} else {
|
||||
toastr.error(response.message || "Failed to remove item");
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
toastr.error("Error removing item from cart");
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// Function to update cart item with the new quantity
|
||||
function updateCartQuantity(rowId, newQty, updateRoute) {
|
||||
$.ajax({
|
||||
url: updateRoute,
|
||||
type: "PUT",
|
||||
data: {
|
||||
rowId: rowId,
|
||||
qty: newQty,
|
||||
},
|
||||
success: function (response) {
|
||||
if (response.success) {
|
||||
fetchUpdatedCart(calTotalAmount); // Re-fetch the cart and recalculate the total amount
|
||||
} else {
|
||||
toastr.error(response.message || "Failed to update quantity");
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
toastr.error("Error updating cart quantity");
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Clear the cart and then refresh the UI with updated values
|
||||
function clearCart(cartType) {
|
||||
let route = $("#clear-cart").val();
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: route,
|
||||
data: {
|
||||
type: cartType,
|
||||
},
|
||||
dataType: "json",
|
||||
success: function (response) {
|
||||
fetchUpdatedCart(calTotalAmount); // Call calTotalAmount after cart fetch completes
|
||||
},
|
||||
error: function () {
|
||||
console.error("There was an issue clearing the cart.");
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/** Add to cart start **/
|
||||
|
||||
let selectedProduct = {};
|
||||
|
||||
$(document).on("click", "#single-product", function () {
|
||||
showProductModal($(this));
|
||||
});
|
||||
|
||||
function autoOpenModal(id) {
|
||||
let element = $("#products-list").find(".single-product." + id);
|
||||
showProductModal(element);
|
||||
}
|
||||
|
||||
function showProductModal(element) {
|
||||
selectedProduct = {
|
||||
product_id: element.data("product_id"),
|
||||
product_code: element.data("product_code"),
|
||||
product_unit_id: element.data("product_unit_id"),
|
||||
product_unit_name: element.data("product_unit_name"),
|
||||
product_image: element.data("product_image"),
|
||||
product_name: element.find(".product_name").text(),
|
||||
brand: element.data("brand"),
|
||||
stock: element.data("stock"),
|
||||
purchase_price: element.data("purchase_price"),
|
||||
sales_price: element.data("sales_price"),
|
||||
whole_sale_price: element.data("whole_sale_price"),
|
||||
dealer_price: element.data("dealer_price"),
|
||||
product_type: element.data("product_type"),
|
||||
vat_id: element.data("vat_id"),
|
||||
vat_rate: element.data("vat_rate"),
|
||||
};
|
||||
|
||||
// Set modal display values
|
||||
$("#product_name").text(selectedProduct.product_name);
|
||||
$("#brand").text(selectedProduct.brand);
|
||||
$("#stock").text(selectedProduct.stock);
|
||||
$("#purchase_price").val(selectedProduct.purchase_price);
|
||||
$("#sales_price").val(selectedProduct.sales_price);
|
||||
$("#whole_sale_price").val(selectedProduct.whole_sale_price);
|
||||
$("#dealer_price").val(selectedProduct.dealer_price);
|
||||
$("#batch_no").val("");
|
||||
|
||||
// show/hide variant field according to Product Type
|
||||
if (selectedProduct.product_type === "variant") {
|
||||
$("#variant_name").closest(".col-lg-6").removeClass("d-none");
|
||||
$("#variant_name").prop("disabled", false);
|
||||
loadVariantOptions(selectedProduct.product_id);
|
||||
} else {
|
||||
$("#variant_name").closest(".col-lg-6").addClass("d-none");
|
||||
$("#variant_name").prop("disabled", true);
|
||||
$("#variant_name").html('<option value="">Select Variant</option>');
|
||||
}
|
||||
|
||||
// Read expire_date_type safely from hidden input
|
||||
const settingExpireType = $("#setting_expire_type").val() || "dmy";
|
||||
const $expireInput = $("#expire_date");
|
||||
|
||||
if ($expireInput.length) {
|
||||
if (settingExpireType === "my") {
|
||||
$expireInput.attr("type", "month");
|
||||
} else {
|
||||
$expireInput.attr("type", "date");
|
||||
}
|
||||
}
|
||||
|
||||
$("#product-modal").modal("show");
|
||||
}
|
||||
|
||||
$(".product-filter").on("submit", function (e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
let savingLoader = '<div class="spinner-border spinner-border-sm custom-text-primary" role="status"><span class="visually-hidden">Loading...</span></div>',
|
||||
$purchase_modal_reload = $("#purchase_modal");
|
||||
$purchase_modal_reload.initFormValidation(),
|
||||
// item modal action
|
||||
$("#purchase_modal").on("submit", function (e) {
|
||||
e.preventDefault();
|
||||
let t = $(this).find(".submit-btn"),
|
||||
a = t.html();
|
||||
let url = $(this).data("route");
|
||||
let quantity = parseFloat($("#product_qty").val());
|
||||
$purchase_modal_reload.valid() &&
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: "POST",
|
||||
data: {
|
||||
type: "purchase",
|
||||
id: selectedProduct.product_id,
|
||||
name: selectedProduct.product_name,
|
||||
quantity: quantity,
|
||||
price: parseFloat($("#purchase_price").val()) || selectedProduct.purchase_price,
|
||||
sales_price: parseFloat($("#sales_price").val()),
|
||||
whole_sale_price: parseFloat($("#whole_sale_price").val()),
|
||||
dealer_price: parseFloat($("#dealer_price").val()),
|
||||
batch_no: $("#batch_no").val(),
|
||||
expire_date: $("#expire_date").val(),
|
||||
product_code: selectedProduct.product_code,
|
||||
product_unit_id: selectedProduct.product_unit_id,
|
||||
product_unit_name: selectedProduct.product_unit_name,
|
||||
product_image: selectedProduct.product_image,
|
||||
warehouse_id: $("#warehouse_id").val(),
|
||||
variant_name: $("#variant_name").val(),
|
||||
vat_id: selectedProduct.vat_id,
|
||||
vat_rate: selectedProduct.vat_rate
|
||||
},
|
||||
beforeSend: function () {
|
||||
t.html(savingLoader).attr("disabled", !0);
|
||||
},
|
||||
success: function (response) {
|
||||
t.html(a).removeClass("disabled").attr("disabled", !1);
|
||||
|
||||
if (response.success) {
|
||||
fetchUpdatedCart(calTotalAmount); // Update totals after cart fetch completes
|
||||
$("#product-modal").modal("hide");
|
||||
$("#product_qty").val("");
|
||||
$("#variant_name").val("");
|
||||
$("#warehouse_id").val("");
|
||||
$("#expire_date").val("");
|
||||
} else {
|
||||
toastr.error(
|
||||
response.message || "Failed to add product to cart."
|
||||
);
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
toastr.error(
|
||||
"An error occurred while adding product to cart."
|
||||
);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
/** Add to cart End **/
|
||||
|
||||
// Function to load variant options
|
||||
function loadVariantOptions(product_id) {
|
||||
let url = $("#get-product-variants").val() + '/' + product_id;
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: "GET",
|
||||
success: function (res) {
|
||||
let options = '<option value="">Select Variant</option>';
|
||||
res.forEach(function (variant) {
|
||||
// Store batch_no as data attribute
|
||||
options += `<option value="${variant.variant_name}" data-batch="${variant.batch_no || ''}" data-expire_date="${variant.expire_date || ''}">
|
||||
${variant.variant_name} (${variant.batch_no || '-'})
|
||||
</option>`;
|
||||
});
|
||||
$("#variant_name").html(options);
|
||||
|
||||
// Clear field when product modal opens
|
||||
$("#batch_no").val('');
|
||||
$("#expire_date").val('');
|
||||
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// variant options on change event
|
||||
$(document).on("change", "#variant_name", function () {
|
||||
let selectedOption = $(this).find(":selected");
|
||||
|
||||
let batchNo = selectedOption.data("batch") || '';
|
||||
$("#batch_no").val(batchNo);
|
||||
|
||||
let expireDate = selectedOption.data("expire_date") || '';
|
||||
|
||||
// Adjust format if type=month
|
||||
const $expireInput = $("#expire_date");
|
||||
if ($expireInput.attr("type") === "month" && expireDate) {
|
||||
expireDate = expireDate.slice(0, 7); // yyyy-MM
|
||||
}
|
||||
|
||||
$expireInput.val(expireDate);
|
||||
});
|
||||
|
||||
// Trigger calculation whenever Discount, or Receive Amount fields change
|
||||
$("#discount_amount, #receive_amount, #shipping_charge").on(
|
||||
"input",
|
||||
function () {
|
||||
calTotalAmount();
|
||||
}
|
||||
);
|
||||
|
||||
// vat calculation
|
||||
$(".vat_select").on("change", function () {
|
||||
let vatRate = parseFloat($(this).find(":selected").data("rate")) || 0;
|
||||
let subtotal = getNumericValue($("#sub_total").text()) || 0;
|
||||
|
||||
let vatAmount = (subtotal * vatRate) / 100;
|
||||
|
||||
$("#vat_amount").val(vatAmount.toFixed(2));
|
||||
calTotalAmount();
|
||||
});
|
||||
|
||||
// discount calculation
|
||||
$(".discount_type").on("change", function () {
|
||||
calTotalAmount();
|
||||
});
|
||||
|
||||
// Function to calculate the total amount
|
||||
function calTotalAmount() {
|
||||
let subtotal = 0;
|
||||
let vat_amount = 0;
|
||||
|
||||
// Calculate subtotal and VAT from cart list
|
||||
$("#purchase_cart_list tr").each(function () {
|
||||
let cart_qty = getNumericValue($(this).find(".cart-qty").val()) || 0;
|
||||
let cart_price = getNumericValue($(this).find(".price").val()) || 0;
|
||||
let cart_subtotal = cart_qty * cart_price;
|
||||
subtotal += cart_subtotal;
|
||||
|
||||
let cart_vat_rate = parseFloat($(this).data("vat_rate")) || 0;
|
||||
let cart_vat_amount = (cart_subtotal * cart_vat_rate) / 100;
|
||||
vat_amount += cart_vat_amount;
|
||||
|
||||
// Update line total on the UI
|
||||
$(this).find(".cart-subtotal").text(currencyFormat(cart_subtotal));
|
||||
$(this).find(".cart-vat-value").text(currencyFormat(cart_vat_amount));
|
||||
});
|
||||
|
||||
$("#sub_total").text(currencyFormat(subtotal));
|
||||
|
||||
// Display total VAT
|
||||
$("#vat_amount").val(vat_amount.toFixed(2));
|
||||
|
||||
// Subtotal with VAT
|
||||
let subtotal_with_vat = subtotal + vat_amount;
|
||||
|
||||
// Discount
|
||||
let discount_amount = getNumericValue($("#discount_amount").val()) || 0;
|
||||
let discount_type = $(".discount_type").val();
|
||||
|
||||
if (discount_type == "percent") {
|
||||
discount_amount = (subtotal_with_vat * discount_amount) / 100;
|
||||
|
||||
if (discount_amount > subtotal_with_vat) {
|
||||
toastr.error(
|
||||
"Discount cannot be more than 100% of the amount after VAT!"
|
||||
);
|
||||
discount_amount = subtotal_with_vat;
|
||||
$("#discount_amount").val(100);
|
||||
}
|
||||
} else {
|
||||
if (discount_amount > subtotal_with_vat) {
|
||||
toastr.error("Discount cannot be more than the amount after VAT!");
|
||||
discount_amount = subtotal_with_vat;
|
||||
$("#discount_amount").val(discount_amount);
|
||||
}
|
||||
}
|
||||
|
||||
// Shipping Charge
|
||||
let shipping_charge = getNumericValue($("#shipping_charge").val()) || 0;
|
||||
|
||||
// Total Amount (after VAT + shipping, then discount)
|
||||
let total_amount = subtotal_with_vat + shipping_charge - discount_amount;
|
||||
$("#total_amount").text(currencyFormat(total_amount));
|
||||
|
||||
// Receive Amount
|
||||
let receive_amount = getNumericValue($("#receive_amount").val()) || 0;
|
||||
if (receive_amount < 0) {
|
||||
toastr.error("Receive amount cannot be less than 0!");
|
||||
receive_amount = 0;
|
||||
$("#receive_amount").val(receive_amount);
|
||||
}
|
||||
|
||||
// Change Amount
|
||||
let change_amount =
|
||||
receive_amount > total_amount ? receive_amount - total_amount : 0;
|
||||
$("#change_amount").val(change_amount.toFixed(2));
|
||||
|
||||
// Due Amount
|
||||
let due_amount =
|
||||
total_amount > receive_amount ? total_amount - receive_amount : 0;
|
||||
$("#due_amount").val(due_amount.toFixed(2));
|
||||
}
|
||||
calTotalAmount();
|
||||
|
||||
// Cancel btn action
|
||||
$(".cancel-sale-btn").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
clearCart("purchase");
|
||||
});
|
||||
|
||||
$(".product-filter").on("input", ".search-input", function (e) {
|
||||
fetchProducts();
|
||||
});
|
||||
|
||||
let autoOpenedForSearch = false; // Prevent repeated modal open per search
|
||||
function fetchProducts() {
|
||||
var form = $("form.product-filter")[0];
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: $(form).attr("action"),
|
||||
data: new FormData(form),
|
||||
dataType: "json",
|
||||
contentType: false,
|
||||
cache: false,
|
||||
processData: false,
|
||||
success: function (res) {
|
||||
// Show products
|
||||
$("#products-list").html(res.data);
|
||||
|
||||
// Open modal if one product found and not opened yet
|
||||
const searchTerm = $("#purchase_product_search").val().trim();
|
||||
if (
|
||||
res.total_products &&
|
||||
res.product_id &&
|
||||
searchTerm !== "" &&
|
||||
!autoOpenedForSearch
|
||||
) {
|
||||
autoOpenedForSearch = true;
|
||||
autoOpenModal(res.product_id);
|
||||
$("#purchase_product_search").val("");
|
||||
|
||||
// Reset when modal closes and reload list
|
||||
$("#product-modal").one("hidden.bs.modal", function () {
|
||||
autoOpenedForSearch = false;
|
||||
fetchProducts();
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
$(document).on("click", ".category-content", function () {
|
||||
let url = $("#category-filter").val();
|
||||
const categoryId = $(this).data("id");
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: url,
|
||||
data: { category_id: categoryId },
|
||||
success: function (response) {
|
||||
$(".product-list-container").html(response.data);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on("click", ".brand-search", function () {
|
||||
let url = $("#brand-filter").val();
|
||||
const brandId = $(this).data("id");
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: url,
|
||||
data: { brand_id: brandId },
|
||||
success: function (response) {
|
||||
$(".product-list-container").html(response.data);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// Category Filter
|
||||
$(".category-search").on("input", function (e) {
|
||||
e.preventDefault();
|
||||
// Get search query
|
||||
const search = $(this).val();
|
||||
const route = $(this).closest("form").data("route");
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: route,
|
||||
data: {
|
||||
search: search,
|
||||
},
|
||||
success: function (response) {
|
||||
$("#category-data").html(response.categories);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// brand Filter
|
||||
$(".brand-search").on("input", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Get search query
|
||||
const search = $(this).val();
|
||||
|
||||
const route = $(this).closest("form").data("route");
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: route,
|
||||
data: {
|
||||
search: search,
|
||||
},
|
||||
success: function (response) {
|
||||
$("#brand-data").html(response.brands);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on("submit", "#categorySearchForm, #brandSearchForm", function (e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
// When select brand or product
|
||||
$(document).on("click", ".category-list, .brand-list", function () {
|
||||
const isCategory = $(this).hasClass("category-list");
|
||||
const filterType = isCategory ? "category_id" : "brand_id";
|
||||
const filterId = $(this).data("id");
|
||||
const route = $(this).data("route"); // product filter route
|
||||
|
||||
const searchTerm = $("#purchase_product_search").val();
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: route,
|
||||
data: {
|
||||
search: searchTerm,
|
||||
[filterType]: filterId, // Dynamically set category_id or brand_id
|
||||
},
|
||||
success: function (response) {
|
||||
$("#products-list").html(response.data);
|
||||
$("#category-list").html(response.categories);
|
||||
$("#brand-list").html(response.brands);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// Update cart
|
||||
$(document).on("change", ".batch_no, .expire_date, .price", function () {
|
||||
let $row = $(this).closest("tr");
|
||||
let updateRoute = $row.data("update_route");
|
||||
|
||||
// Get values
|
||||
let expire_date = $row.find(".expire_date").val();
|
||||
let priceVal = $row.find(".price").val();
|
||||
let batch_no = $row.find(".batch_no").val();
|
||||
|
||||
// Parse and validate price
|
||||
let price = parseFloat(priceVal);
|
||||
if (isNaN(price) || price < 0) {
|
||||
toastr.error("Price cannot be negative or empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Optional: clean batch_no
|
||||
if (batch_no === null || batch_no === undefined) {
|
||||
batch_no = "";
|
||||
}
|
||||
|
||||
// Prepare data
|
||||
let data = {
|
||||
batch_no: batch_no,
|
||||
expire_date: expire_date,
|
||||
price: price,
|
||||
};
|
||||
|
||||
// Call update function
|
||||
updateCart(data, updateRoute);
|
||||
});
|
||||
|
||||
// Function to update cart item with the new quantity
|
||||
function updateCart(data, updateRoute) {
|
||||
$.ajax({
|
||||
url: updateRoute,
|
||||
type: "PUT",
|
||||
data: data,
|
||||
success: function (response) {
|
||||
if (response.success) {
|
||||
fetchUpdatedCart(calTotalAmount); // Refresh the cart and recalculate totals
|
||||
} else {
|
||||
toastr.error(response.message || "Failed to update cart");
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
89
public/assets/js/custom/sale-purchase-return.js
Normal file
89
public/assets/js/custom/sale-purchase-return.js
Normal file
@@ -0,0 +1,89 @@
|
||||
// Get numeric value from string
|
||||
function getNumericValue(value) {
|
||||
return parseFloat(value.replace(/[^0-9.-]+/g, "")) || 0;
|
||||
}
|
||||
|
||||
updateTotalAmount();
|
||||
|
||||
// Update quantity on manual change
|
||||
$(document).on('change', '.return-qty', function() {
|
||||
var row = $(this).closest('tr');
|
||||
var currentQtyInput = $(this);
|
||||
var currentQty = getNumericValue(currentQtyInput.val());
|
||||
var maxQty = parseFloat(row.data('max_qty'));
|
||||
|
||||
// Validate the entered quantity
|
||||
if (currentQty > maxQty) {
|
||||
toastr.error('You cannot return more than the ordered quantity.');
|
||||
currentQtyInput.val(0);
|
||||
} else if (currentQty < 0) {
|
||||
toastr.error('Return quantity cannot be less than 0.');
|
||||
currentQtyInput.val(0);
|
||||
}
|
||||
|
||||
updateSubTotal(row);
|
||||
});
|
||||
|
||||
|
||||
// Increase quantity
|
||||
$(document).on('click', '.add-btn', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Find the closest row and get current quantity and max quantity
|
||||
var row = $(this).closest('tr');
|
||||
var currentQtyInput = row.find('.return-qty');
|
||||
var currentQty = getNumericValue(currentQtyInput.val());
|
||||
var maxQty = parseFloat(row.data('max_qty'));
|
||||
|
||||
// Check if increment will exceed maxQty
|
||||
if ((currentQty + 1) <= maxQty) {
|
||||
currentQtyInput.val(currentQty + 1);
|
||||
updateSubTotal(row);
|
||||
} else {
|
||||
toastr.error('You cannot return more than the ordered quantity.');
|
||||
}
|
||||
});
|
||||
|
||||
// Decrease quantity
|
||||
$(document).on('click', '.sub-btn', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Find the closest row and get current quantity
|
||||
var row = $(this).closest('tr');
|
||||
var currentQtyInput = row.find('.return-qty');
|
||||
var currentQty = getNumericValue(currentQtyInput.val());
|
||||
|
||||
// return quantity cannot negative
|
||||
if ((currentQty - 1) >= 0) {
|
||||
currentQtyInput.val(currentQty - 1);
|
||||
updateSubTotal(row);
|
||||
} else {
|
||||
toastr.error('Return quantity cannot be negative.');
|
||||
}
|
||||
});
|
||||
|
||||
// Update the subtotal for each row based on the return quantity
|
||||
function updateSubTotal(row) {
|
||||
let priceText = row.find(".price").text();
|
||||
let price = getNumericValue(String(priceText || ""))
|
||||
|| getNumericValue(String(row.data("discounted_price_per_unit") || "0"));
|
||||
|
||||
let quantity = getNumericValue(String(row.find(".return-qty").val() || "0"));
|
||||
let subTotal = price * quantity;
|
||||
|
||||
row.find(".subtotal").text(currencyFormat(subTotal));
|
||||
updateTotalAmount();
|
||||
}
|
||||
|
||||
|
||||
// Update total return amount
|
||||
function updateTotalAmount() {
|
||||
var totalReturn = 0;
|
||||
$('.subtotal').each(function() {
|
||||
totalReturn += getNumericValue($(this).text());
|
||||
});
|
||||
|
||||
var returnText = $('.return_amount').data('return-text');
|
||||
|
||||
$('.return_amount').text(returnText + ' ' + currencyFormat(totalReturn));
|
||||
}
|
||||
1129
public/assets/js/custom/sale.js
Normal file
1129
public/assets/js/custom/sale.js
Normal file
File diff suppressed because it is too large
Load Diff
41
public/assets/js/custom/tab.js
Normal file
41
public/assets/js/custom/tab.js
Normal file
@@ -0,0 +1,41 @@
|
||||
function showTab(tabId) {
|
||||
// Activate selected tab
|
||||
document
|
||||
.querySelectorAll(".tab-item")
|
||||
.forEach((tab) => tab.classList.remove("active"));
|
||||
document
|
||||
.querySelectorAll(".tab-content")
|
||||
.forEach((content) => content.classList.remove("active"));
|
||||
|
||||
document.getElementById(tabId).classList.add("active");
|
||||
document
|
||||
.querySelector(`[onclick="showTab('${tabId}')"]`)
|
||||
.classList.add("active");
|
||||
|
||||
// Get the base URL from the hidden input fields
|
||||
const csvBaseUrl = document.getElementById("csvBaseUrl").value;
|
||||
const excelBaseUrl = document.getElementById("excelBaseUrl").value;
|
||||
const pdfBaseUrl = document.getElementById("pdfBaseUrl").value;
|
||||
|
||||
// Set correct export type
|
||||
let type = tabId == "sales" ? "sales" : "purchases";
|
||||
|
||||
// Update export URLs dynamically
|
||||
const csv = document.getElementById("csvExportLink");
|
||||
const excel = document.getElementById("excelExportLink");
|
||||
const pdf = document.getElementById("pdfExportLink");
|
||||
|
||||
if (csv) {
|
||||
csv.href = `${csvBaseUrl}?type=${type}`;
|
||||
}
|
||||
if (excel) {
|
||||
excel.href = `${excelBaseUrl}?type=${type}`;
|
||||
}
|
||||
if (pdf) {
|
||||
pdf.href = `${pdfBaseUrl}?type=${type}`;
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
showTab("sales");
|
||||
});
|
||||
29
public/assets/js/custom/tagify.js
Normal file
29
public/assets/js/custom/tagify.js
Normal file
File diff suppressed because one or more lines are too long
414
public/assets/js/custom/transfer.js
Normal file
414
public/assets/js/custom/transfer.js
Normal file
@@ -0,0 +1,414 @@
|
||||
"use strict";
|
||||
|
||||
let allProducts = [];
|
||||
|
||||
// Asset path helper
|
||||
function assetPath(path) {
|
||||
let baseUrl = $("#asset_base_url").val() || "";
|
||||
return baseUrl.replace(/\/$/, "") + "/" + path.replace(/^\/+/, "");
|
||||
}
|
||||
|
||||
// renders product dropdown list
|
||||
function populateProducts(products) {
|
||||
const $dropdownList = $("#dropdownList");
|
||||
$dropdownList.empty();
|
||||
|
||||
if (products.length === 0) {
|
||||
$dropdownList.append(
|
||||
'<div class="product-option-item">No products available</div>'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const cartRoute = $("#cart-store-url").val();
|
||||
|
||||
$.each(products, function (index, product) {
|
||||
const imageUrl = assetPath(
|
||||
product.productPicture ?? "assets/images/products/box.svg"
|
||||
);
|
||||
let html = "";
|
||||
|
||||
// if multiple stocks
|
||||
if (product.stocks && product.stocks.length > 1) {
|
||||
html += `<div class="product-option-item single-product"
|
||||
data-product_id="${product.id}"
|
||||
data-route="${cartRoute}"
|
||||
data-product_name="${product.productName}"
|
||||
data-product_code="${product.productCode}"
|
||||
data-product_unit_id="${product.unit_id}"
|
||||
data-product_unit_name="${product.unit?.unitName ?? ""}"
|
||||
data-product_image="${product.productPicture}">
|
||||
<div class="product-left">
|
||||
<img src="${imageUrl}" alt="">
|
||||
<div class="product-text">
|
||||
<div class="d-flex align-items-center justify-content-between w-100">
|
||||
<div class="product-title">${
|
||||
product.productName
|
||||
}</div>
|
||||
<p>Code : ${product.productCode}</p>
|
||||
</div>`;
|
||||
|
||||
product.stocks.forEach((stock) => {
|
||||
html += `<div class="d-flex align-items-center justify-content-between w-100 multi-items add-batch-item"
|
||||
data-product_stock_id="${stock.id}"
|
||||
data-product_id="${product.id}"
|
||||
data-product_expire_date="${stock.expire_date ?? ""}"
|
||||
data-product_name="${product.productName}"
|
||||
data-product_code="${product.productCode}"
|
||||
data-default_price="${stock.productSalePrice}"
|
||||
data-product_unit_id="${product.unit_id}"
|
||||
data-product_unit_name="${product.unit?.unitName ?? ""}"
|
||||
data-purchase_price="${stock.productPurchasePrice}"
|
||||
data-product_image="${product.productPicture}"
|
||||
data-route="${cartRoute}"
|
||||
data-batch_no="${stock.batch_no ?? ''}"
|
||||
>
|
||||
|
||||
<div class="product-des">
|
||||
Batch: ${stock.batch_no ?? "N/A"} ${
|
||||
product.color ? ", Color: " + product.color : ""
|
||||
}
|
||||
<span class="product-in-stock">In Stock: ${
|
||||
stock.productStock
|
||||
}</span>
|
||||
</div>
|
||||
<div class="product-price product_price">${currencyFormat(
|
||||
stock.productSalePrice
|
||||
)}</div>
|
||||
</div>`;
|
||||
});
|
||||
|
||||
html += `</div></div></div>`;
|
||||
} else {
|
||||
const singleStock =
|
||||
Array.isArray(product.stocks) && product.stocks.length > 0
|
||||
? product.stocks[0]
|
||||
: {};
|
||||
|
||||
html += `<div class="product-option-item single-product ${
|
||||
product.id
|
||||
} add-batch-item"
|
||||
data-product_stock_id="${singleStock.id ?? ""}"
|
||||
data-product_id="${product.id}"
|
||||
data-default_price="${singleStock.productSalePrice ?? 0}"
|
||||
data-product_name="${product.productName}"
|
||||
data-product_code="${product.productCode}"
|
||||
data-product_unit_id="${product.unit_id}"
|
||||
data-product_unit_name="${product.unit?.unitName ?? ""}"
|
||||
data-purchase_price="${singleStock.productPurchasePrice ?? 0}"
|
||||
data-product_image="${product.productPicture}"
|
||||
data-product_expire_date="${singleStock.expire_date ?? ""}"
|
||||
data-route="${cartRoute}"
|
||||
data-batch_no="${singleStock.batch_no ?? ''}">
|
||||
|
||||
<div class="product-left">
|
||||
<img src="${imageUrl}" alt="">
|
||||
<div class="product-text">
|
||||
<div class="d-flex align-items-center justify-content-between w-100">
|
||||
<div class="product-title">${
|
||||
product.productName
|
||||
}</div>
|
||||
<p>Code : ${product.productCode}</p>
|
||||
</div>
|
||||
<div class="d-flex align-items-center justify-content-between w-100">
|
||||
<div class="product-des">
|
||||
Batch: ${singleStock.batch_no ?? "N/A"} ${
|
||||
product.color ? ", Color: " + product.color : ""
|
||||
}
|
||||
<span class="product-in-stock">In Stock: ${
|
||||
Array.isArray(product.stocks)
|
||||
? product.stocks.reduce(
|
||||
(sum, stock) =>
|
||||
sum + stock.productStock,
|
||||
0
|
||||
)
|
||||
: 0
|
||||
}</span>
|
||||
</div>
|
||||
<div class="product-price product_price">${currencyFormat(
|
||||
singleStock.productSalePrice ?? 0
|
||||
)}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
$dropdownList.append(html);
|
||||
});
|
||||
}
|
||||
|
||||
// load all products initially
|
||||
const allProductsUrl = $("#all-products").val();
|
||||
if (allProductsUrl) {
|
||||
$.get(allProductsUrl, function (products) {
|
||||
allProducts = products; // store globally
|
||||
populateProducts(allProducts);
|
||||
});
|
||||
}
|
||||
|
||||
// Filter products based on branch & warehouse
|
||||
function filterProducts() {
|
||||
const branchId = $("#from_branch").val();
|
||||
const warehouseId = $("#from_warehouse").val();
|
||||
|
||||
const filtered = allProducts
|
||||
.map((product) => {
|
||||
if (!product.stocks || product.stocks.length === 0) return null;
|
||||
|
||||
// filter stocks by selected branch & warehouse
|
||||
const filteredStocks = product.stocks.filter((stock) => {
|
||||
const branchMatch = !branchId || stock.branch_id == branchId;
|
||||
const warehouseMatch = !warehouseId || stock.warehouse_id == warehouseId;
|
||||
return branchMatch && warehouseMatch && stock.productStock > 0;
|
||||
});
|
||||
|
||||
if (filteredStocks.length === 0) return null;
|
||||
|
||||
return {
|
||||
...product, // copy product data, keep only filtered stocks
|
||||
stocks: filteredStocks,
|
||||
};
|
||||
})
|
||||
.filter(Boolean); // remove nulls
|
||||
|
||||
populateProducts(filtered);
|
||||
}
|
||||
|
||||
// toggle product dropdown visibility
|
||||
const $dropdown = $("#dropdownList");
|
||||
const $searchContainer = $("#searchContainer");
|
||||
const $productSearch = $("#productSearch");
|
||||
const $arrow = $("#arrow");
|
||||
|
||||
$("#productDropdown .product-selected").on("click", function (e) {
|
||||
e.stopPropagation();
|
||||
$dropdown.toggle();
|
||||
$searchContainer.toggleClass("hidden");
|
||||
$arrow.toggleClass("product-rotate");
|
||||
});
|
||||
|
||||
// Close dropdown if clicked outside
|
||||
$(document).on("click", function (e) {
|
||||
if (!$(e.target).closest("#productDropdown").length) {
|
||||
$dropdown.hide();
|
||||
$searchContainer.addClass("hidden");
|
||||
$arrow.removeClass("product-rotate");
|
||||
}
|
||||
});
|
||||
|
||||
// product search also respects filter
|
||||
$productSearch.on("keyup", function () {
|
||||
const searchTerm = $(this).val().toLowerCase();
|
||||
$("#dropdownList .product-option-item").each(function () {
|
||||
const name = String($(this).data("product_name") || "").toLowerCase();
|
||||
const code = String($(this).data("product_code") || "").toLowerCase();
|
||||
$(this).toggle(name.includes(searchTerm) || code.includes(searchTerm));
|
||||
});
|
||||
});
|
||||
|
||||
// Add to cart on batch click
|
||||
$("#dropdownList").on("click", ".add-batch-item", function (e) {
|
||||
e.stopPropagation();
|
||||
|
||||
const $item = $(this);
|
||||
$dropdown.hide();
|
||||
$searchContainer.addClass("hidden");
|
||||
$arrow.removeClass("product-rotate");
|
||||
|
||||
let stockId = $item.data("product_stock_id");
|
||||
let productId = $item.data("product_id");
|
||||
|
||||
let name = $item.data("product_name");
|
||||
let code = $item.data("product_code");
|
||||
let price = parseFloat($item.data("default_price") || 0);
|
||||
let batchNo = $item.data("batch_no") || "";
|
||||
let image = $item.data("product_image") || assetPath("assets/images/products/box.svg");
|
||||
|
||||
// If row exists increment qty
|
||||
let existingRow = $("#product-row-" + stockId);
|
||||
if (existingRow.length) {
|
||||
let qtyInput = existingRow.find(".dynamic-qty");
|
||||
qtyInput.val((parseInt(qtyInput.val()) || 1) + 1).trigger("input");
|
||||
return;
|
||||
}
|
||||
|
||||
let rowHtml = `
|
||||
<tr id="product-row-${stockId}">
|
||||
<td><img src="${assetPath(image)}" width="40"></td>
|
||||
<td>${name}</td>
|
||||
<td>${code}</td>
|
||||
<td>${batchNo}</td>
|
||||
<td class="text-start">
|
||||
<div class="d-flex align-items-center justify-content-center">
|
||||
<button type="button" class="incre-decre subtract-btn btn btn-sm btn-outline-secondary"><i class="fas fa-minus"></i></button>
|
||||
<input type="number" name="products[${stockId}][quantity]" class="custom-number-input dynamic-qty form-control form-control-sm mx-1 text-center" value="1" min="1" step="1" style="width: 60px;">
|
||||
<button type="button" class="incre-decre adding-btn btn btn-sm btn-outline-secondary"><i class="fas fa-plus"></i></button>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<input type="number" name="products[${stockId}][unit_price]" class="form-control unit-price text-center" value="${price}" min="0">
|
||||
</td>
|
||||
<td><input type="number" name="products[${stockId}][tax]" class="form-control tax text-center" value="0" min="0"></td>
|
||||
<td><input type="number" name="products[${stockId}][discount]" class="form-control discount text-center" value="0" min="0"></td>
|
||||
<td class="sub-total text-center">${price.toFixed(2)}</td>
|
||||
<td>
|
||||
<button type="button" class="x-btn remove-btn" data-id="${stockId}">
|
||||
<svg width="25" height="24" viewBox="0 0 25 24" fill="none">
|
||||
<path d="M18.5 6L6.5 18" stroke="#E13F3D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M6.5 6L18.5 18" stroke="#E13F3D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
</td>
|
||||
<input type="hidden" name="products[${stockId}][product_id]" value="${productId}">
|
||||
</tr>
|
||||
`;
|
||||
$("#product-list").append(rowHtml);
|
||||
updateTotals();
|
||||
});
|
||||
|
||||
// Cart qty, price, discount, tax change
|
||||
$("#product-list").on(
|
||||
"input",
|
||||
".dynamic-qty, .unit-price, .discount, .tax",
|
||||
function () {
|
||||
let $row = $(this).closest("tr");
|
||||
let qty = parseFloat($row.find(".dynamic-qty").val()) || 0;
|
||||
let price = parseFloat($row.find(".unit-price").val()) || 0;
|
||||
let discount = parseFloat($row.find(".discount").val()) || 0;
|
||||
let tax = parseFloat($row.find(".tax").val()) || 0;
|
||||
|
||||
let subtotal = qty * price + tax - discount;
|
||||
$row.find(".sub-total").text(subtotal.toFixed(2));
|
||||
updateTotals();
|
||||
}
|
||||
);
|
||||
|
||||
// increment / decrement buttons
|
||||
$("#product-list").on("click", ".adding-btn", function () {
|
||||
let $row = $(this).closest("tr");
|
||||
let $qty = $row.find(".dynamic-qty");
|
||||
$qty.val((parseInt($qty.val()) || 0) + 1).trigger("input");
|
||||
});
|
||||
$("#product-list").on("click", ".subtract-btn", function () {
|
||||
let $row = $(this).closest("tr");
|
||||
let $qty = $row.find(".dynamic-qty");
|
||||
let current = parseInt($qty.val()) || 1;
|
||||
if (current > 1) $qty.val(current - 1).trigger("input");
|
||||
});
|
||||
|
||||
// remove row
|
||||
$("#product-list").on("click", ".remove-btn", function () {
|
||||
$(this).closest("tr").remove();
|
||||
updateTotals();
|
||||
});
|
||||
|
||||
// update totals function
|
||||
function updateTotals() {
|
||||
let subTotal = 0,
|
||||
totalDiscount = 0,
|
||||
totalTax = 0,
|
||||
grandTotal = 0;
|
||||
|
||||
$("#product-list tr").each(function () {
|
||||
let qty = parseFloat($(this).find(".dynamic-qty").val()) || 0;
|
||||
let price = parseFloat($(this).find(".unit-price").val()) || 0;
|
||||
let discount = parseFloat($(this).find(".discount").val()) || 0;
|
||||
let tax = parseFloat($(this).find(".tax").val()) || 0;
|
||||
|
||||
let lineBase = qty * price;
|
||||
let lineWithTax = lineBase + tax;
|
||||
let lineSubtotal = lineWithTax - discount;
|
||||
|
||||
$(this).find(".sub-total").text(lineSubtotal.toFixed(2));
|
||||
|
||||
subTotal += lineBase;
|
||||
totalTax += tax;
|
||||
totalDiscount += discount;
|
||||
grandTotal += lineSubtotal;
|
||||
});
|
||||
|
||||
let shipping = parseFloat($("#shipping_amount").val()) || 0;
|
||||
grandTotal += shipping;
|
||||
|
||||
$("#total_amount").text(subTotal.toFixed(2));
|
||||
$("#tax_amount").text(totalTax.toFixed(2));
|
||||
$("#discount_amount").text(totalDiscount.toFixed(2));
|
||||
$("#grand_total_amount").text(grandTotal.toFixed(2));
|
||||
}
|
||||
|
||||
// Trigger totals update on shipping change
|
||||
$("#shipping_amount").on("input", function () {
|
||||
updateTotals();
|
||||
});
|
||||
|
||||
const allWarehousesUrl = $("#branch_wise_warehouses").val();
|
||||
|
||||
function loadWarehouses(branchId, warehouseSelect) {
|
||||
if (!allWarehousesUrl) return;
|
||||
|
||||
$.ajax({
|
||||
url: allWarehousesUrl,
|
||||
type: "GET",
|
||||
data: { branch_id: branchId },
|
||||
success: function (warehouses) {
|
||||
let options = '<option value="">Select one</option>';
|
||||
|
||||
if (warehouses.length > 0) {
|
||||
$.each(warehouses, function (i, wh) {
|
||||
options += `<option value="${wh.id}">${wh.name}</option>`;
|
||||
});
|
||||
} else {
|
||||
options += `<option value="">No warehouse available</option>`;
|
||||
}
|
||||
|
||||
$(warehouseSelect).html(options);
|
||||
},
|
||||
error: function () {
|
||||
$(warehouseSelect).html('<option value="">Error loading warehouses</option>');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Load all warehouses initially
|
||||
loadWarehouses("", "#from_warehouse");
|
||||
loadWarehouses("", "#to_warehouse");
|
||||
|
||||
// When "from_branch" changes
|
||||
$("#from_branch").on("change", function () {
|
||||
let branchId = $(this).val();
|
||||
|
||||
// Clear cart and update totals
|
||||
$("#product-list").empty();
|
||||
updateTotals();
|
||||
|
||||
// Reload "from_warehouse" options based on selected branch
|
||||
loadWarehouses(branchId, "#from_warehouse");
|
||||
|
||||
// Filter products based on new branch & warehouse
|
||||
filterProducts();
|
||||
});
|
||||
|
||||
// When "to_branch" changes
|
||||
$("#to_branch").on("change", function () {
|
||||
let branchId = $(this).val();
|
||||
let hasActiveBranch = $("#hasActiveBranch").val() == "1";
|
||||
|
||||
// Only reload "to_warehouse" if no active branch
|
||||
if (!hasActiveBranch) {
|
||||
loadWarehouses(branchId, "#to_warehouse");
|
||||
}
|
||||
});
|
||||
|
||||
// When "from_warehouse" changes
|
||||
$("#from_warehouse").on("change", function () {
|
||||
// Clear cart and update totals
|
||||
$("#product-list").empty();
|
||||
updateTotals();
|
||||
|
||||
// Filter products based on new warehouse
|
||||
filterProducts();
|
||||
});
|
||||
|
||||
|
||||
|
||||
7
public/assets/js/imagesloaded.pkgd.min.js
vendored
Normal file
7
public/assets/js/imagesloaded.pkgd.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
24
public/assets/js/installer.js
Normal file
24
public/assets/js/installer.js
Normal file
@@ -0,0 +1,24 @@
|
||||
function checkEnvironment(val) {
|
||||
var element = document.getElementById('environment_text_input');
|
||||
if (val == 'other') {
|
||||
element.classList.remove('d-none');
|
||||
} else {
|
||||
element.classList.add('d-none');
|
||||
}
|
||||
}
|
||||
|
||||
function showDatabaseSettings() {
|
||||
document.getElementById('tab2').checked = true;
|
||||
}
|
||||
|
||||
function showApplicationSettings() {
|
||||
document.getElementById('tab3').checked = true;
|
||||
}
|
||||
|
||||
var x = document.getElementById('error_alert');
|
||||
var y = document.getElementById('close_alert');
|
||||
if (x || y) {
|
||||
y.onclick = function() {
|
||||
x.style.display = "none";
|
||||
};
|
||||
}
|
||||
12
public/assets/js/isotope.pkgd.min.js
vendored
Normal file
12
public/assets/js/isotope.pkgd.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
public/assets/js/jquery-3.7.1.min.js
vendored
Normal file
2
public/assets/js/jquery-3.7.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/assets/js/jquery.counterup.min.js
vendored
Normal file
1
public/assets/js/jquery.counterup.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
(function($){"use strict";$.fn.counterUp=function(options){var settings=$.extend({time:400,delay:10,offset:100,beginAt:0,formatter:false,context:"window",callback:function(){}},options),s;return this.each(function(){var $this=$(this),counter={time:$(this).data("counterup-time")||settings.time,delay:$(this).data("counterup-delay")||settings.delay,offset:$(this).data("counterup-offset")||settings.offset,beginAt:$(this).data("counterup-beginat")||settings.beginAt,context:$(this).data("counterup-context")||settings.context};var counterUpper=function(){var nums=[];var divisions=counter.time/counter.delay;var num=$(this).attr("data-num")?$(this).attr("data-num"):$this.text();var isComma=/[0-9]+,[0-9]+/.test(num);num=num.replace(/,/g,"");var decimalPlaces=(num.split(".")[1]||[]).length;if(counter.beginAt>num)counter.beginAt=num;var isTime=/[0-9]+:[0-9]+:[0-9]+/.test(num);if(isTime){var times=num.split(":"),m=1;s=0;while(times.length>0){s+=m*parseInt(times.pop(),10);m*=60}}for(var i=divisions;i>=counter.beginAt/num*divisions;i--){var newNum=parseFloat(num/divisions*i).toFixed(decimalPlaces);if(isTime){newNum=parseInt(s/divisions*i);var hours=parseInt(newNum/3600)%24;var minutes=parseInt(newNum/60)%60;var seconds=parseInt(newNum%60,10);newNum=(hours<10?"0"+hours:hours)+":"+(minutes<10?"0"+minutes:minutes)+":"+(seconds<10?"0"+seconds:seconds)}if(isComma){while(/(\d+)(\d{3})/.test(newNum.toString())){newNum=newNum.toString().replace(/(\d+)(\d{3})/,"$1"+","+"$2")}}if(settings.formatter){newNum=settings.formatter.call(this,newNum)}nums.unshift(newNum)}$this.data("counterup-nums",nums);$this.text(counter.beginAt);var f=function(){if(!$this.data("counterup-nums")){settings.callback.call(this);return}$this.html($this.data("counterup-nums").shift());if($this.data("counterup-nums").length){setTimeout($this.data("counterup-func"),counter.delay)}else{$this.data("counterup-nums",null);$this.data("counterup-func",null);settings.callback.call(this)}};$this.data("counterup-func",f);setTimeout($this.data("counterup-func"),counter.delay)};$this.waypoint(function(direction){counterUpper();this.destroy()},{offset:counter.offset+"%",context:counter.context})})}})(jQuery);
|
||||
7
public/assets/js/jquery.waypoints.min.js
vendored
Normal file
7
public/assets/js/jquery.waypoints.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
638
public/assets/js/lity.js
Normal file
638
public/assets/js/lity.js
Normal file
@@ -0,0 +1,638 @@
|
||||
/*! Lity - v2.4.1 - 2020-04-26
|
||||
* http://sorgalla.com/lity/
|
||||
* Copyright (c) 2015-2020 Jan Sorgalla; Licensed MIT */
|
||||
(function(window, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(['jquery'], function($) {
|
||||
return factory(window, $);
|
||||
});
|
||||
} else if (typeof module === 'object' && typeof module.exports === 'object') {
|
||||
module.exports = factory(window, require('jquery'));
|
||||
} else {
|
||||
window.lity = factory(window, window.jQuery || window.Zepto);
|
||||
}
|
||||
}(typeof window !== "undefined" ? window : this, function(window, $) {
|
||||
'use strict';
|
||||
|
||||
var document = window.document;
|
||||
|
||||
var _win = $(window);
|
||||
var _deferred = $.Deferred;
|
||||
var _html = $('html');
|
||||
var _instances = [];
|
||||
|
||||
var _attrAriaHidden = 'aria-hidden';
|
||||
var _dataAriaHidden = 'lity-' + _attrAriaHidden;
|
||||
|
||||
var _focusableElementsSelector = 'a[href],area[href],input:not([disabled]),select:not([disabled]),textarea:not([disabled]),button:not([disabled]),iframe,object,embed,[contenteditable],[tabindex]:not([tabindex^="-"])';
|
||||
|
||||
var _defaultOptions = {
|
||||
esc: true,
|
||||
handler: null,
|
||||
handlers: {
|
||||
image: imageHandler,
|
||||
inline: inlineHandler,
|
||||
youtube: youtubeHandler,
|
||||
vimeo: vimeoHandler,
|
||||
googlemaps: googlemapsHandler,
|
||||
facebookvideo: facebookvideoHandler,
|
||||
iframe: iframeHandler
|
||||
},
|
||||
template: '<div class="lity" role="dialog" aria-label="Dialog Window (Press escape to close)" tabindex="-1"><div class="lity-wrap" data-lity-close role="document"><div class="lity-loader" aria-hidden="true">Loading...</div><div class="lity-container"><div class="lity-content"></div><button class="lity-close" type="button" aria-label="Close (Press escape to close)" data-lity-close>×</button></div></div></div>'
|
||||
};
|
||||
|
||||
var _imageRegexp = /(^data:image\/)|(\.(png|jpe?g|gif|svg|webp|bmp|ico|tiff?)(\?\S*)?$)/i;
|
||||
var _youtubeRegex = /(youtube(-nocookie)?\.com|youtu\.be)\/(watch\?v=|v\/|u\/|embed\/?)?([\w-]{11})(.*)?/i;
|
||||
var _vimeoRegex = /(vimeo(pro)?.com)\/(?:[^\d]+)?(\d+)\??(.*)?$/;
|
||||
var _googlemapsRegex = /((maps|www)\.)?google\.([^\/\?]+)\/?((maps\/?)?\?)(.*)/i;
|
||||
var _facebookvideoRegex = /(facebook\.com)\/([a-z0-9_-]*)\/videos\/([0-9]*)(.*)?$/i;
|
||||
|
||||
var _transitionEndEvent = (function() {
|
||||
var el = document.createElement('div');
|
||||
|
||||
var transEndEventNames = {
|
||||
WebkitTransition: 'webkitTransitionEnd',
|
||||
MozTransition: 'transitionend',
|
||||
OTransition: 'oTransitionEnd otransitionend',
|
||||
transition: 'transitionend'
|
||||
};
|
||||
|
||||
for (var name in transEndEventNames) {
|
||||
if (el.style[name] !== undefined) {
|
||||
return transEndEventNames[name];
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
})();
|
||||
|
||||
function transitionEnd(element) {
|
||||
var deferred = _deferred();
|
||||
|
||||
if (!_transitionEndEvent || !element.length) {
|
||||
deferred.resolve();
|
||||
} else {
|
||||
element.one(_transitionEndEvent, deferred.resolve);
|
||||
setTimeout(deferred.resolve, 500);
|
||||
}
|
||||
|
||||
return deferred.promise();
|
||||
}
|
||||
|
||||
function settings(currSettings, key, value) {
|
||||
if (arguments.length === 1) {
|
||||
return $.extend({}, currSettings);
|
||||
}
|
||||
|
||||
if (typeof key === 'string') {
|
||||
if (typeof value === 'undefined') {
|
||||
return typeof currSettings[key] === 'undefined'
|
||||
? null
|
||||
: currSettings[key];
|
||||
}
|
||||
|
||||
currSettings[key] = value;
|
||||
} else {
|
||||
$.extend(currSettings, key);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
function parseQueryParams(params) {
|
||||
var pairs = decodeURI(params.split('#')[0]).split('&');
|
||||
var obj = {}, p;
|
||||
|
||||
for (var i = 0, n = pairs.length; i < n; i++) {
|
||||
if (!pairs[i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
p = pairs[i].split('=');
|
||||
obj[p[0]] = p[1];
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function appendQueryParams(url, params) {
|
||||
return url + (url.indexOf('?') > -1 ? '&' : '?') + $.param(params);
|
||||
}
|
||||
|
||||
function transferHash(originalUrl, newUrl) {
|
||||
var pos = originalUrl.indexOf('#');
|
||||
|
||||
if (-1 === pos) {
|
||||
return newUrl;
|
||||
}
|
||||
|
||||
if (pos > 0) {
|
||||
originalUrl = originalUrl.substr(pos);
|
||||
}
|
||||
|
||||
return newUrl + originalUrl;
|
||||
}
|
||||
|
||||
function error(msg) {
|
||||
return $('<span class="lity-error"></span>').append(msg);
|
||||
}
|
||||
|
||||
function imageHandler(target, instance) {
|
||||
var desc = (instance.opener() && instance.opener().data('lity-desc')) || 'Image with no description';
|
||||
var img = $('<img src="' + target + '" alt="' + desc + '"/>');
|
||||
var deferred = _deferred();
|
||||
var failed = function() {
|
||||
deferred.reject(error('Failed loading image'));
|
||||
};
|
||||
|
||||
img
|
||||
.on('load', function() {
|
||||
if (this.naturalWidth === 0) {
|
||||
return failed();
|
||||
}
|
||||
|
||||
deferred.resolve(img);
|
||||
})
|
||||
.on('error', failed)
|
||||
;
|
||||
|
||||
return deferred.promise();
|
||||
}
|
||||
|
||||
imageHandler.test = function(target) {
|
||||
return _imageRegexp.test(target);
|
||||
};
|
||||
|
||||
function inlineHandler(target, instance) {
|
||||
var el, placeholder, hasHideClass;
|
||||
|
||||
try {
|
||||
el = $(target);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!el.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
placeholder = $('<i style="display:none !important"></i>');
|
||||
hasHideClass = el.hasClass('lity-hide');
|
||||
|
||||
instance
|
||||
.element()
|
||||
.one('lity:remove', function() {
|
||||
placeholder
|
||||
.before(el)
|
||||
.remove()
|
||||
;
|
||||
|
||||
if (hasHideClass && !el.closest('.lity-content').length) {
|
||||
el.addClass('lity-hide');
|
||||
}
|
||||
})
|
||||
;
|
||||
|
||||
return el
|
||||
.removeClass('lity-hide')
|
||||
.after(placeholder)
|
||||
;
|
||||
}
|
||||
|
||||
function youtubeHandler(target) {
|
||||
var matches = _youtubeRegex.exec(target);
|
||||
|
||||
if (!matches) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return iframeHandler(
|
||||
transferHash(
|
||||
target,
|
||||
appendQueryParams(
|
||||
'https://www.youtube' + (matches[2] || '') + '.com/embed/' + matches[4],
|
||||
$.extend(
|
||||
{
|
||||
autoplay: 1
|
||||
},
|
||||
parseQueryParams(matches[5] || '')
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function vimeoHandler(target) {
|
||||
var matches = _vimeoRegex.exec(target);
|
||||
|
||||
if (!matches) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return iframeHandler(
|
||||
transferHash(
|
||||
target,
|
||||
appendQueryParams(
|
||||
'https://player.vimeo.com/video/' + matches[3],
|
||||
$.extend(
|
||||
{
|
||||
autoplay: 1
|
||||
},
|
||||
parseQueryParams(matches[4] || '')
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function facebookvideoHandler(target) {
|
||||
var matches = _facebookvideoRegex.exec(target);
|
||||
|
||||
if (!matches) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0 !== target.indexOf('http')) {
|
||||
target = 'https:' + target;
|
||||
}
|
||||
|
||||
return iframeHandler(
|
||||
transferHash(
|
||||
target,
|
||||
appendQueryParams(
|
||||
'https://www.facebook.com/plugins/video.php?href=' + target,
|
||||
$.extend(
|
||||
{
|
||||
autoplay: 1
|
||||
},
|
||||
parseQueryParams(matches[4] || '')
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function googlemapsHandler(target) {
|
||||
var matches = _googlemapsRegex.exec(target);
|
||||
|
||||
if (!matches) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return iframeHandler(
|
||||
transferHash(
|
||||
target,
|
||||
appendQueryParams(
|
||||
'https://www.google.' + matches[3] + '/maps?' + matches[6],
|
||||
{
|
||||
output: matches[6].indexOf('layer=c') > 0 ? 'svembed' : 'embed'
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function iframeHandler(target) {
|
||||
return '<div class="lity-iframe-container"><iframe frameborder="0" allowfullscreen allow="autoplay; fullscreen" src="' + target + '"/></div>';
|
||||
}
|
||||
|
||||
function winHeight() {
|
||||
return document.documentElement.clientHeight
|
||||
? document.documentElement.clientHeight
|
||||
: Math.round(_win.height());
|
||||
}
|
||||
|
||||
function keydown(e) {
|
||||
var current = currentInstance();
|
||||
|
||||
if (!current) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ESC key
|
||||
if (e.keyCode === 27 && !!current.options('esc')) {
|
||||
current.close();
|
||||
}
|
||||
|
||||
// TAB key
|
||||
if (e.keyCode === 9) {
|
||||
handleTabKey(e, current);
|
||||
}
|
||||
}
|
||||
|
||||
function handleTabKey(e, instance) {
|
||||
var focusableElements = instance.element().find(_focusableElementsSelector);
|
||||
var focusedIndex = focusableElements.index(document.activeElement);
|
||||
|
||||
if (e.shiftKey && focusedIndex <= 0) {
|
||||
focusableElements.get(focusableElements.length - 1).focus();
|
||||
e.preventDefault();
|
||||
} else if (!e.shiftKey && focusedIndex === focusableElements.length - 1) {
|
||||
focusableElements.get(0).focus();
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
function resize() {
|
||||
$.each(_instances, function(i, instance) {
|
||||
instance.resize();
|
||||
});
|
||||
}
|
||||
|
||||
function registerInstance(instanceToRegister) {
|
||||
if (1 === _instances.unshift(instanceToRegister)) {
|
||||
_html.addClass('lity-active');
|
||||
|
||||
_win
|
||||
.on({
|
||||
resize: resize,
|
||||
keydown: keydown
|
||||
})
|
||||
;
|
||||
}
|
||||
|
||||
$('body > *').not(instanceToRegister.element())
|
||||
.addClass('lity-hidden')
|
||||
.each(function() {
|
||||
var el = $(this);
|
||||
|
||||
if (undefined !== el.data(_dataAriaHidden)) {
|
||||
return;
|
||||
}
|
||||
|
||||
el.data(_dataAriaHidden, el.attr(_attrAriaHidden) || null);
|
||||
})
|
||||
.attr(_attrAriaHidden, 'true')
|
||||
;
|
||||
}
|
||||
|
||||
function removeInstance(instanceToRemove) {
|
||||
var show;
|
||||
|
||||
instanceToRemove
|
||||
.element()
|
||||
.attr(_attrAriaHidden, 'true')
|
||||
;
|
||||
|
||||
if (1 === _instances.length) {
|
||||
_html.removeClass('lity-active');
|
||||
|
||||
_win
|
||||
.off({
|
||||
resize: resize,
|
||||
keydown: keydown
|
||||
})
|
||||
;
|
||||
}
|
||||
|
||||
_instances = $.grep(_instances, function(instance) {
|
||||
return instanceToRemove !== instance;
|
||||
});
|
||||
|
||||
if (!!_instances.length) {
|
||||
show = _instances[0].element();
|
||||
} else {
|
||||
show = $('.lity-hidden');
|
||||
}
|
||||
|
||||
show
|
||||
.removeClass('lity-hidden')
|
||||
.each(function() {
|
||||
var el = $(this), oldAttr = el.data(_dataAriaHidden);
|
||||
|
||||
if (!oldAttr) {
|
||||
el.removeAttr(_attrAriaHidden);
|
||||
} else {
|
||||
el.attr(_attrAriaHidden, oldAttr);
|
||||
}
|
||||
|
||||
el.removeData(_dataAriaHidden);
|
||||
})
|
||||
;
|
||||
}
|
||||
|
||||
function currentInstance() {
|
||||
if (0 === _instances.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return _instances[0];
|
||||
}
|
||||
|
||||
function factory(target, instance, handlers, preferredHandler) {
|
||||
var handler = 'inline', content;
|
||||
|
||||
var currentHandlers = $.extend({}, handlers);
|
||||
|
||||
if (preferredHandler && currentHandlers[preferredHandler]) {
|
||||
content = currentHandlers[preferredHandler](target, instance);
|
||||
handler = preferredHandler;
|
||||
} else {
|
||||
// Run inline and iframe handlers after all other handlers
|
||||
$.each(['inline', 'iframe'], function(i, name) {
|
||||
delete currentHandlers[name];
|
||||
|
||||
currentHandlers[name] = handlers[name];
|
||||
});
|
||||
|
||||
$.each(currentHandlers, function(name, currentHandler) {
|
||||
// Handler might be "removed" by setting callback to null
|
||||
if (!currentHandler) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
currentHandler.test &&
|
||||
!currentHandler.test(target, instance)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
content = currentHandler(target, instance);
|
||||
|
||||
if (false !== content) {
|
||||
handler = name;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {handler: handler, content: content || ''};
|
||||
}
|
||||
|
||||
function Lity(target, options, opener, activeElement) {
|
||||
var self = this;
|
||||
var result;
|
||||
var isReady = false;
|
||||
var isClosed = false;
|
||||
var element;
|
||||
var content;
|
||||
|
||||
options = $.extend(
|
||||
{},
|
||||
_defaultOptions,
|
||||
options
|
||||
);
|
||||
|
||||
element = $(options.template);
|
||||
|
||||
// -- API --
|
||||
|
||||
self.element = function() {
|
||||
return element;
|
||||
};
|
||||
|
||||
self.opener = function() {
|
||||
return opener;
|
||||
};
|
||||
|
||||
self.options = $.proxy(settings, self, options);
|
||||
self.handlers = $.proxy(settings, self, options.handlers);
|
||||
|
||||
self.resize = function() {
|
||||
if (!isReady || isClosed) {
|
||||
return;
|
||||
}
|
||||
|
||||
content
|
||||
.css('max-height', winHeight() + 'px')
|
||||
.trigger('lity:resize', [self])
|
||||
;
|
||||
};
|
||||
|
||||
self.close = function() {
|
||||
if (!isReady || isClosed) {
|
||||
return;
|
||||
}
|
||||
|
||||
isClosed = true;
|
||||
|
||||
removeInstance(self);
|
||||
|
||||
var deferred = _deferred();
|
||||
|
||||
// We return focus only if the current focus is inside this instance
|
||||
if (
|
||||
activeElement &&
|
||||
(
|
||||
document.activeElement === element[0] ||
|
||||
$.contains(element[0], document.activeElement)
|
||||
)
|
||||
) {
|
||||
try {
|
||||
activeElement.focus();
|
||||
} catch (e) {
|
||||
// Ignore exceptions, eg. for SVG elements which can't be
|
||||
// focused in IE11
|
||||
}
|
||||
}
|
||||
|
||||
content.trigger('lity:close', [self]);
|
||||
|
||||
element
|
||||
.removeClass('lity-opened')
|
||||
.addClass('lity-closed')
|
||||
;
|
||||
|
||||
transitionEnd(content.add(element))
|
||||
.always(function() {
|
||||
content.trigger('lity:remove', [self]);
|
||||
element.remove();
|
||||
element = undefined;
|
||||
deferred.resolve();
|
||||
})
|
||||
;
|
||||
|
||||
return deferred.promise();
|
||||
};
|
||||
|
||||
// -- Initialization --
|
||||
|
||||
result = factory(target, self, options.handlers, options.handler);
|
||||
|
||||
element
|
||||
.attr(_attrAriaHidden, 'false')
|
||||
.addClass('lity-loading lity-opened lity-' + result.handler)
|
||||
.appendTo('body')
|
||||
.focus()
|
||||
.on('click', '[data-lity-close]', function(e) {
|
||||
if ($(e.target).is('[data-lity-close]')) {
|
||||
self.close();
|
||||
}
|
||||
})
|
||||
.trigger('lity:open', [self])
|
||||
;
|
||||
|
||||
registerInstance(self);
|
||||
|
||||
$.when(result.content)
|
||||
.always(ready)
|
||||
;
|
||||
|
||||
function ready(result) {
|
||||
content = $(result)
|
||||
.css('max-height', winHeight() + 'px')
|
||||
;
|
||||
|
||||
element
|
||||
.find('.lity-loader')
|
||||
.each(function() {
|
||||
var loader = $(this);
|
||||
|
||||
transitionEnd(loader)
|
||||
.always(function() {
|
||||
loader.remove();
|
||||
})
|
||||
;
|
||||
})
|
||||
;
|
||||
|
||||
element
|
||||
.removeClass('lity-loading')
|
||||
.find('.lity-content')
|
||||
.empty()
|
||||
.append(content)
|
||||
;
|
||||
|
||||
isReady = true;
|
||||
|
||||
content
|
||||
.trigger('lity:ready', [self])
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
function lity(target, options, opener) {
|
||||
if (!target.preventDefault) {
|
||||
opener = $(opener);
|
||||
} else {
|
||||
target.preventDefault();
|
||||
opener = $(this);
|
||||
target = opener.data('lity-target') || opener.attr('href') || opener.attr('src');
|
||||
}
|
||||
|
||||
var instance = new Lity(
|
||||
target,
|
||||
$.extend(
|
||||
{},
|
||||
opener.data('lity-options') || opener.data('lity'),
|
||||
options
|
||||
),
|
||||
opener,
|
||||
document.activeElement
|
||||
);
|
||||
|
||||
if (!target.preventDefault) {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
lity.version = '2.4.1';
|
||||
lity.options = $.proxy(settings, lity, _defaultOptions);
|
||||
lity.handlers = $.proxy(settings, lity, _defaultOptions.handlers);
|
||||
lity.current = currentInstance;
|
||||
|
||||
$(document).on('click.lity', '[data-lity]', lity);
|
||||
|
||||
return lity;
|
||||
}));
|
||||
6
public/assets/js/math.js
Normal file
6
public/assets/js/math.js
Normal file
File diff suppressed because one or more lines are too long
47
public/assets/js/razorpay.js
Normal file
47
public/assets/js/razorpay.js
Normal file
@@ -0,0 +1,47 @@
|
||||
/*------------------------------
|
||||
Razorpay Intergration
|
||||
--------------------------------*/
|
||||
var logo = document.getElementById('logo');
|
||||
var options = {
|
||||
"key": $('#razorpayId').val(), // Enter the Key ID generated from the Dashboard
|
||||
"amount": $('#amount')
|
||||
.val(), // Amount is in currency subunits. Default currency is INR. Hence, 50000 refers to 50000 paise
|
||||
"currency": $('#currency').val(),
|
||||
"name": $('#name').val(),
|
||||
"description": $('#description').val(),
|
||||
"image": logo, // You can give your logo url
|
||||
"order_id": $('#orderId')
|
||||
.val(), //This is a sample Order ID. Pass the `id` obtained in the response of Step 1
|
||||
"handler": function (response) {
|
||||
// After payment successfully made response will come here
|
||||
// send this response to Controller for update the payment response
|
||||
// Create a form for send this data
|
||||
// Set the data in form
|
||||
document.getElementById('rzp_paymentid').value = response.razorpay_payment_id;
|
||||
document.getElementById('rzp_orderid').value = response.razorpay_order_id;
|
||||
document.getElementById('rzp_signature').value = response.razorpay_signature;
|
||||
|
||||
// // Let's submit the form automatically
|
||||
document.getElementById('rzp-paymentresponse').click();
|
||||
},
|
||||
"prefill": {
|
||||
"name": $('#name').val(),
|
||||
"email": $('#email').val(),
|
||||
"contact": $('#contactNumber').val()
|
||||
},
|
||||
"notes": {
|
||||
"address": $('#address').val()
|
||||
},
|
||||
"theme": {
|
||||
"color": "#F37254"
|
||||
}
|
||||
};
|
||||
var rzp1 = new Razorpay(options);
|
||||
window.onload = function () {
|
||||
document.getElementById('rzp-button1').click();
|
||||
};
|
||||
|
||||
document.getElementById('rzp-button1').onclick = function (e) {
|
||||
rzp1.open();
|
||||
e.preventDefault();
|
||||
}
|
||||
2
public/assets/js/select2.min.js
vendored
Normal file
2
public/assets/js/select2.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/assets/js/slick.min.js
vendored
Normal file
1
public/assets/js/slick.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
10786
public/assets/js/summernote-lite.js
Normal file
10786
public/assets/js/summernote-lite.js
Normal file
File diff suppressed because it is too large
Load Diff
13
public/assets/js/swiper-bundle.min.js
vendored
Normal file
13
public/assets/js/swiper-bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
178
public/assets/js/theme.js
Normal file
178
public/assets/js/theme.js
Normal file
@@ -0,0 +1,178 @@
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
sideManu();
|
||||
|
||||
function sideManu() {
|
||||
let manuStor = $(".side-bar").html();
|
||||
|
||||
$(".side-bar").html("<div class='overlay'></div>" + manuStor);
|
||||
$(".sidebar-opner").on("click ", function () {
|
||||
$(".side-bar, .section-container").toggleClass("active");
|
||||
});
|
||||
$(".side-bar .close-btn, .side-bar .overlay").on("click ", function () {
|
||||
$(".side-bar, .section-container").toggleClass("active");
|
||||
});
|
||||
|
||||
$("li>ul").toggleClass("dropdown-menu");
|
||||
|
||||
let animationSpeed = 300;
|
||||
|
||||
let subMenuSelector = ".dropdown-menu";
|
||||
|
||||
$(".side-bar-manu > ul").on("click", ".dropdown a", function (e) {
|
||||
let $this = $(this);
|
||||
let checkElement = $this.next();
|
||||
|
||||
if (
|
||||
checkElement.is(subMenuSelector) &&
|
||||
checkElement.is(":visible")
|
||||
) {
|
||||
checkElement.slideUp(animationSpeed, function () {
|
||||
checkElement.removeClass("menu-open");
|
||||
});
|
||||
checkElement.parent("li").removeClass("active");
|
||||
}
|
||||
|
||||
//If the menu is not visible
|
||||
else if (
|
||||
checkElement.is(subMenuSelector) &&
|
||||
!checkElement.is(":visible")
|
||||
) {
|
||||
//Get the parent menu
|
||||
let parent = $this.parents("ul").first();
|
||||
//Close all open menus within the parent
|
||||
let ul = parent.find("ul:visible").slideUp(animationSpeed);
|
||||
//Remove the menu-open class from the parent
|
||||
ul.removeClass("menu-open");
|
||||
//Get the parent li
|
||||
let parent_li = $this.parent("li");
|
||||
|
||||
//Open the target menu and add the menu-open class
|
||||
checkElement.slideDown(animationSpeed, function () {
|
||||
//Add the class active to the parent li
|
||||
checkElement.addClass("menu-open");
|
||||
parent.find("li.active").removeClass("active");
|
||||
parent_li.addClass("active");
|
||||
});
|
||||
}
|
||||
//if this isn't a link, prevent the page from being redirected
|
||||
if (checkElement.is(subMenuSelector)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
// show sidebar in previous menu
|
||||
var sidebar = $(".side-bar");
|
||||
|
||||
// Restore scroll position on page load
|
||||
var savedScroll = localStorage.getItem("sidebar-scroll");
|
||||
if (savedScroll !== null) {
|
||||
sidebar.scrollTop(savedScroll);
|
||||
}
|
||||
|
||||
// Save scroll position before leaving the page
|
||||
$(window).on("beforeunload", function () {
|
||||
localStorage.setItem("sidebar-scroll", sidebar.scrollTop());
|
||||
});
|
||||
}
|
||||
|
||||
// photo upload preview
|
||||
function readURL(input) {
|
||||
if (input.files && input.files[0]) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
$(".image-preview").attr("src", e.target.result);
|
||||
$(".image-preview").hide();
|
||||
$(".image-preview").fadeIn(650);
|
||||
};
|
||||
reader.readAsDataURL(input.files[0]);
|
||||
}
|
||||
}
|
||||
|
||||
$("#add-profile").on("change", function () {
|
||||
readURL(this);
|
||||
$(".image-preview-icon").addClass("d-none");
|
||||
});
|
||||
|
||||
$("#feature-btn").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
let value = $(".add-feature").val();
|
||||
let featureCount = $(".feature-list").children().length;
|
||||
|
||||
if (value !== "") {
|
||||
$(".feature-list").append(`
|
||||
<div class="col-lg-6 mt-4 remove-list">
|
||||
<div class="feature-wrp">
|
||||
<div class="form-control d-flex justify-content-between align-items-center">
|
||||
<input name="features[features_${featureCount}][]" required class="border-none" type="text" value="${value}">
|
||||
<label class="switch m-0">
|
||||
<input type="checkbox" checked value="1" name="features[features_${featureCount}][]">
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
</div>
|
||||
<button type="button" class="remove-one d-none"><i class="fal fa-times"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
$(".add-feature").val("");
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const toggleBtn = document.querySelector(".menu-opener");
|
||||
const sidebarPlan = document.querySelector(".lg-sub-plan");
|
||||
const subPlan = document.querySelector(".sub-plan");
|
||||
const sidebarAddOn = document.querySelector(".side-bar-addon");
|
||||
const sidebarAddOn2 = document.querySelector(".side-bar-addon-2");
|
||||
const sidebarAddOn3 = document.querySelector(".side-bar-addon-3");
|
||||
|
||||
toggleBtn.addEventListener("click", function () {
|
||||
if (sidebarPlan.style.display === "none") {
|
||||
sidebarPlan.style.display = "block";
|
||||
subPlan.style.display = "none";
|
||||
sidebarAddOn.style.display = "block";
|
||||
sidebarAddOn2.style.display = "block";
|
||||
sidebarAddOn3.style.display = "block";
|
||||
} else {
|
||||
sidebarPlan.style.display = "none";
|
||||
subPlan.style.display = "block";
|
||||
sidebarAddOn.style.display = "none";
|
||||
sidebarAddOn2.style.display = "none";
|
||||
sidebarAddOn3.style.display = "none";
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelector(".sidebar-opner").addEventListener("click", function () {
|
||||
const sidebar = document.querySelector(".side-bar-addon");
|
||||
if (
|
||||
sidebar.style.display === "none" ||
|
||||
getComputedStyle(sidebar).display === "none"
|
||||
) {
|
||||
sidebar.style.display = "block";
|
||||
} else {
|
||||
sidebar.style.display = "none";
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on("click", "#openUserSignupTab", function (e) {
|
||||
e.preventDefault();
|
||||
var $otpTabTrigger = $("#otp-tab");
|
||||
if ($otpTabTrigger.length) {
|
||||
var tab = new bootstrap.Tab($otpTabTrigger[0]);
|
||||
tab.show();
|
||||
}
|
||||
});
|
||||
|
||||
function cartSelectVariant(selectedBox) {
|
||||
const allBoxes = document.querySelectorAll(".cart-variant-box");
|
||||
allBoxes.forEach((box) => box.classList.remove("cart-active"));
|
||||
selectedBox.classList.add("cart-active");
|
||||
|
||||
const radios = document.querySelectorAll('input[name="variant"]');
|
||||
radios.forEach((radio) => (radio.checked = false));
|
||||
selectedBox.querySelector('input[type="radio"]').checked = true;
|
||||
}
|
||||
1
public/assets/js/toastr.js.map
Normal file
1
public/assets/js/toastr.js.map
Normal file
File diff suppressed because one or more lines are too long
7
public/assets/js/toastr.min.js
vendored
Normal file
7
public/assets/js/toastr.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user