migrate to gtea from bistbucket
This commit is contained in:
374
public/assets/plugins/custom/branch-overview.js
Normal file
374
public/assets/plugins/custom/branch-overview.js
Normal file
@@ -0,0 +1,374 @@
|
||||
"use strict";
|
||||
|
||||
function currencyFormat(amount, type = "icon", decimals = 2) {
|
||||
let symbol = $("#currency_symbol").val();
|
||||
let position = $("#currency_position").val();
|
||||
let code = $("#currency_code").val();
|
||||
|
||||
let formattedAmount = formatNumber(amount, decimals); // Abbreviate number
|
||||
|
||||
// Apply currency format based on the position and type
|
||||
if (type == "icon" || type == "symbol") {
|
||||
return position == "right"
|
||||
? formattedAmount + symbol
|
||||
: symbol + formattedAmount;
|
||||
} else {
|
||||
return position == "right"
|
||||
? formattedAmount + " " + code
|
||||
: code + " " + formattedAmount;
|
||||
}
|
||||
}
|
||||
|
||||
function formatNumber(number, decimals = 2) {
|
||||
if (number >= 1e9) {
|
||||
return removeTrailingZeros((number / 1e9).toFixed(decimals)) + "B";
|
||||
} else if (number >= 1e6) {
|
||||
return removeTrailingZeros((number / 1e6).toFixed(decimals)) + "M";
|
||||
} else if (number >= 1e3) {
|
||||
return removeTrailingZeros((number / 1e3).toFixed(decimals)) + "K";
|
||||
} else {
|
||||
return removeTrailingZeros(number.toFixed(decimals));
|
||||
}
|
||||
}
|
||||
|
||||
function removeTrailingZeros(value) {
|
||||
return parseFloat(value).toString();
|
||||
}
|
||||
|
||||
let branchRevenueChart;
|
||||
|
||||
$(document).ready(function () {
|
||||
const ctxBranchRevenue = document
|
||||
.getElementById("branchRevenueChart")
|
||||
.getContext("2d");
|
||||
|
||||
function totalEarningExpenseChart(months, incomeData, expenseData) {
|
||||
if (branchRevenueChart) {
|
||||
branchRevenueChart.destroy();
|
||||
}
|
||||
|
||||
const allData = [...incomeData, ...expenseData];
|
||||
const maxValue = Math.max(...allData);
|
||||
|
||||
// Gradient Backgrounds
|
||||
const incomeBgGradient = ctxBranchRevenue.createLinearGradient(0, 0, 0, 400);
|
||||
incomeBgGradient.addColorStop(0, "rgba(42, 180, 249, 0.17)");
|
||||
incomeBgGradient.addColorStop(1, "rgba(34, 201, 177, 0)");
|
||||
|
||||
const expenseBgGradient = ctxBranchRevenue.createLinearGradient(0, 0, 0, 400);
|
||||
expenseBgGradient.addColorStop(0, "rgba(248, 107, 35, 0.12)");
|
||||
expenseBgGradient.addColorStop(1, "rgba(249, 190, 16, 0)");
|
||||
|
||||
// Solid Gradients for border lines
|
||||
const incomeLine = ctxBranchRevenue.createLinearGradient(0, 0, 400, 0);
|
||||
incomeLine.addColorStop(0, "#019934");
|
||||
incomeLine.addColorStop(1, "#019934");
|
||||
|
||||
const expenseLine = ctxBranchRevenue.createLinearGradient(0, 0, 400, 0);
|
||||
expenseLine.addColorStop(0, "#FF9500");
|
||||
expenseLine.addColorStop(1, "#FF9500");
|
||||
|
||||
branchRevenueChart = new Chart(ctxBranchRevenue, {
|
||||
type: "line",
|
||||
data: {
|
||||
labels: months,
|
||||
datasets: [
|
||||
{
|
||||
label: "Profit",
|
||||
data: incomeData,
|
||||
borderColor: incomeLine,
|
||||
backgroundColor: incomeBgGradient,
|
||||
fill: true,
|
||||
tension: 0.4,
|
||||
pointBackgroundColor: "#019934",
|
||||
pointRadius: 0,
|
||||
pointHoverRadius: 5,
|
||||
},
|
||||
{
|
||||
label: "Loss",
|
||||
data: expenseData,
|
||||
borderColor: expenseLine,
|
||||
backgroundColor: expenseBgGradient,
|
||||
fill: true,
|
||||
tension: 0.4,
|
||||
pointBackgroundColor: "#FF9500",
|
||||
pointRadius: 0,
|
||||
pointHoverRadius: 5,
|
||||
},
|
||||
],
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
interaction: { mode: "index", intersect: false },
|
||||
plugins: {
|
||||
tooltip: {
|
||||
backgroundColor: "#ffffff",
|
||||
titleColor: "#000000",
|
||||
bodyColor: "#000000",
|
||||
borderColor: "#e5e7eb",
|
||||
borderWidth: 1,
|
||||
callbacks: {
|
||||
label: function (context) {
|
||||
const value = parseFloat(context.raw);
|
||||
return `${context.dataset.label} : ${(value)}`;
|
||||
},
|
||||
},
|
||||
},
|
||||
legend: { display: false },
|
||||
},
|
||||
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
grid: { drawBorder: false, color: "#C2C6CE", borderDash: [4, 4] },
|
||||
ticks: {
|
||||
callback: function (value) {
|
||||
if (maxValue < 1000) return value;
|
||||
else if (maxValue < 100000) return (value / 1000) + 'k';
|
||||
else return (value / 100000).toFixed(1) + 'M';
|
||||
},
|
||||
},
|
||||
},
|
||||
x: { grid: { display: false } },
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function fetchIncomeExpense(year) {
|
||||
const route = $("#incomeExpenseRoute").val();
|
||||
|
||||
$.ajax({
|
||||
url: route,
|
||||
type: "GET",
|
||||
data: { year: year },
|
||||
success: function (data) {
|
||||
const months = [
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
];
|
||||
|
||||
const incomeData = Array(12).fill(0);
|
||||
const expenseData = Array(12).fill(0);
|
||||
|
||||
data.incomes.forEach((item) => {
|
||||
const monthIndex = item.month_number - 1;
|
||||
incomeData[monthIndex] = parseFloat(item.total);
|
||||
});
|
||||
|
||||
data.expenses.forEach((item) => {
|
||||
const monthIndex = item.month_number - 1;
|
||||
expenseData[monthIndex] = parseFloat(item.total);
|
||||
});
|
||||
|
||||
const totalIncome = incomeData.reduce((a, b) => a + b, 0);
|
||||
const totalExpense = expenseData.reduce((a, b) => a + b, 0);
|
||||
|
||||
$(".profit-value").text(currencyFormat(totalIncome));
|
||||
$(".loss-value").text(currencyFormat(totalExpense));
|
||||
|
||||
totalEarningExpenseChart(months, incomeData, expenseData);
|
||||
},
|
||||
error: function (err) {
|
||||
console.error("Error fetching income/expense data:", err);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Initial load
|
||||
const selectedYear = $(".overview-year").val();
|
||||
fetchIncomeExpense(selectedYear);
|
||||
|
||||
// On year change
|
||||
$(".overview-year").on("change", function () {
|
||||
const year = $(this).val();
|
||||
fetchIncomeExpense(year);
|
||||
});
|
||||
});
|
||||
|
||||
// Profit Loss Reports ----------------------->
|
||||
const profitLossCanvas = document.getElementById("profitLossChart");
|
||||
const ctxProfitLoss = profitLossCanvas.getContext("2d");
|
||||
|
||||
const gradientProfit = ctxProfitLoss.createLinearGradient(0, 0, 0, profitLossCanvas.height);
|
||||
gradientProfit.addColorStop(0, "#05C535");
|
||||
gradientProfit.addColorStop(1, "#36F165");
|
||||
|
||||
const gradientLoss = ctxProfitLoss.createLinearGradient(0, 0, 0, profitLossCanvas.height);
|
||||
gradientLoss.addColorStop(0, "#FF8983");
|
||||
gradientLoss.addColorStop(1, "#FF3B30");
|
||||
|
||||
// Initial static values (will be updated dynamically)
|
||||
let profit = 0;
|
||||
let loss = 0;
|
||||
|
||||
const profitLossData = {
|
||||
labels: ["Income", "Expense"],
|
||||
datasets: [
|
||||
{
|
||||
data: [profit, loss],
|
||||
backgroundColor: [gradientProfit, gradientLoss],
|
||||
hoverOffset: 5,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const profitLossConfig = {
|
||||
type: "pie",
|
||||
data: profitLossData,
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
tooltip: {
|
||||
enabled: true,
|
||||
backgroundColor: "#FFFFFF",
|
||||
titleColor: "#000000",
|
||||
bodyColor: "#000000",
|
||||
borderWidth: 1,
|
||||
displayColors: false,
|
||||
callbacks: {
|
||||
label: function (context) {
|
||||
const label = context.label || '';
|
||||
const value = parseFloat(context.parsed || 0);
|
||||
const formattedValue = value.toFixed(2);
|
||||
return `${label}: ${formattedValue}`;
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const profitLossChart = new Chart(ctxProfitLoss, profitLossConfig);
|
||||
|
||||
// Dynamic update function
|
||||
const chartRoute = document.getElementById("salePurchaseChartRoute").value;
|
||||
const yearSelector = document.querySelector(".overview-loss-profit-year");
|
||||
|
||||
function updateProfitLossChart(year) {
|
||||
fetch(`${chartRoute}?year=${year}`)
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
profit = data.profit ?? 0;
|
||||
loss = data.loss ?? 0;
|
||||
|
||||
// Update chart dataset
|
||||
profitLossChart.data.datasets[0].data = [profit, loss];
|
||||
profitLossChart.update();
|
||||
|
||||
// ✅ Use your currencyFormat for displayed values too
|
||||
document.querySelector(".profit").textContent = currencyFormat(profit);
|
||||
document.querySelector(".loss").textContent = currencyFormat(loss);
|
||||
})
|
||||
.catch(err => {
|
||||
console.error("Error fetching profit/loss data:", err);
|
||||
});
|
||||
}
|
||||
|
||||
// Initial load
|
||||
updateProfitLossChart(yearSelector.value);
|
||||
|
||||
// On year change
|
||||
yearSelector.addEventListener("change", function () {
|
||||
updateProfitLossChart(this.value);
|
||||
});
|
||||
|
||||
// Responsive resize
|
||||
window.addEventListener("resize", function () {
|
||||
profitLossChart.resize();
|
||||
});
|
||||
|
||||
|
||||
// for sale data
|
||||
|
||||
$(document).ready(function() {
|
||||
var route = $('#branchWiseSaleRoute').val();
|
||||
|
||||
// Load current year sales on page load
|
||||
var currentYear = $('.branch-wise-sales-year').val();
|
||||
fetchBranchWiseSales(currentYear);
|
||||
|
||||
// Listen for year change
|
||||
$('.branch-wise-sales-year').on('change', function() {
|
||||
var year = $(this).val();
|
||||
fetchBranchWiseSales(year);
|
||||
});
|
||||
|
||||
function fetchBranchWiseSales(year) {
|
||||
$.ajax({
|
||||
url: route,
|
||||
type: 'GET',
|
||||
data: { year: year },
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
var tbody = $('#sale-data');
|
||||
tbody.empty(); // clear existing table rows
|
||||
|
||||
$.each(data, function(index, branch) {
|
||||
var row = `
|
||||
<tr>
|
||||
<td>${index + 1}</td>
|
||||
<td>${branch.name}</td>
|
||||
<td>${branch.sales_sum_total_amount_formatted}</td>
|
||||
<td>${branch.sales_sum_paid_amount_formatted}</td>
|
||||
<td>${branch.sales_sum_due_amount_formatted}</td>
|
||||
</tr>
|
||||
`;
|
||||
tbody.append(row);
|
||||
});
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('Error fetching branch sales:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// for purchase data
|
||||
|
||||
$(document).ready(function() {
|
||||
function fetchBranchPurchases(year) {
|
||||
let url = $('#branchWisePurchaseRoute').val();
|
||||
|
||||
$.ajax({
|
||||
url: url,
|
||||
method: 'GET',
|
||||
data: { year: year },
|
||||
dataType: 'json',
|
||||
success: function(response) {
|
||||
let tbody = $('#purchase-data');
|
||||
tbody.empty();
|
||||
|
||||
$.each(response, function(index, branch) {
|
||||
let row = `
|
||||
<tr>
|
||||
<td>${index + 1}</td>
|
||||
<td>${branch.name}</td>
|
||||
<td>${branch.purchases_sum_total_amount_formatted}</td>
|
||||
<td>${branch.purchases_sum_paid_amount_formatted}</td>
|
||||
<td>${branch.purchases_sum_due_amount_formatted}</td>
|
||||
</tr>
|
||||
`;
|
||||
tbody.append(row);
|
||||
});
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('Error fetching branch purchases:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Initial load for current year
|
||||
let currentYear = $('.batch-wise-purchases-year').val();
|
||||
fetchBranchPurchases(currentYear);
|
||||
|
||||
// Fetch data on year change
|
||||
$('.batch-wise-purchases-year').on('change', function() {
|
||||
let selectedYear = $(this).val();
|
||||
fetchBranchPurchases(selectedYear);
|
||||
});
|
||||
});
|
||||
|
||||
409
public/assets/plugins/custom/business-dashboard.js
Normal file
409
public/assets/plugins/custom/business-dashboard.js
Normal file
@@ -0,0 +1,409 @@
|
||||
// currency format
|
||||
function currencyFormat(amount, type = "icon", decimals = 2) {
|
||||
let symbol = $("#currency_symbol").val();
|
||||
let position = $("#currency_position").val();
|
||||
let code = $("#currency_code").val();
|
||||
|
||||
let formattedAmount = formatNumber(amount, decimals); // Abbreviate number
|
||||
|
||||
// Apply currency format based on the position and type
|
||||
if (type == "icon" || type == "symbol") {
|
||||
return position == "right"
|
||||
? formattedAmount + symbol
|
||||
: symbol + formattedAmount;
|
||||
} else {
|
||||
return position == "right"
|
||||
? formattedAmount + " " + code
|
||||
: code + " " + formattedAmount;
|
||||
}
|
||||
}
|
||||
// Update design when a single business content exists
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
// Select the container, ensure it exists
|
||||
const container = document.querySelector(".business-stat");
|
||||
if (container) {
|
||||
const businessContents =
|
||||
container.querySelectorAll(".business-content");
|
||||
const customImageBg = document.querySelector(".custom-image-bg");
|
||||
|
||||
// Dynamically set column class based on the number of business content elements
|
||||
container.classList.add(`columns-${businessContents.length}`);
|
||||
|
||||
if (businessContents.length == 1) {
|
||||
businessContents[0].style.padding = "3% 2%";
|
||||
if (customImageBg) {
|
||||
customImageBg.style.padding = "2%";
|
||||
}
|
||||
businessContents[0].style.borderRadius = "0";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
getDashboardData();
|
||||
|
||||
function getDashboardData() {
|
||||
var url = $("#get-dashboard").val();
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: url,
|
||||
dataType: "json",
|
||||
success: function (res) {
|
||||
$("#total_sales").text(res.total_sales);
|
||||
$("#this_month_total_sales").text(res.this_month_total_sales);
|
||||
$("#total_purchase").text(res.total_purchase);
|
||||
$("#this_month_total_purchase").text(res.this_month_total_purchase);
|
||||
$("#total_income").text(res.total_income);
|
||||
$("#this_month_total_income").text(res.this_month_total_income);
|
||||
$("#total_expense").text(res.total_expense);
|
||||
$("#this_month_total_expense").text(res.this_month_total_expense);
|
||||
$("#total_customer").text(res.total_customer);
|
||||
$("#this_month_total_customer").text(res.this_month_total_customer);
|
||||
$("#total_supplier").text(res.total_supplier);
|
||||
$("#this_month_total_supplier").text(res.this_month_total_supplier);
|
||||
$("#total_sales_return").text(res.total_sales_return);
|
||||
$("#this_month_total_sale_return").text(
|
||||
res.this_month_total_sale_return
|
||||
);
|
||||
$("#total_purchase_return").text(res.total_purchase_return);
|
||||
$("#this_month_total_purchase_return").text(
|
||||
res.this_month_total_purchase_return
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Function to abbreviate numbers (K, M, B)
|
||||
function formatNumber(number, decimals = 2) {
|
||||
if (number >= 1e9) {
|
||||
return removeTrailingZeros((number / 1e9).toFixed(decimals)) + "B";
|
||||
} else if (number >= 1e6) {
|
||||
return removeTrailingZeros((number / 1e6).toFixed(decimals)) + "M";
|
||||
} else if (number >= 1e3) {
|
||||
return removeTrailingZeros((number / 1e3).toFixed(decimals)) + "K";
|
||||
} else {
|
||||
return removeTrailingZeros(number.toFixed(decimals));
|
||||
}
|
||||
}
|
||||
|
||||
function removeTrailingZeros(value) {
|
||||
return parseFloat(value).toString();
|
||||
}
|
||||
|
||||
// Revenue chart----------------->
|
||||
let revenueChart;
|
||||
const ctxRevenue = document.getElementById("revenueChart").getContext("2d");
|
||||
function totalEarningExpenseChart(total_loss, total_profit) {
|
||||
if (revenueChart) {
|
||||
revenueChart.destroy();
|
||||
}
|
||||
|
||||
revenueChart = new Chart(ctxRevenue, {
|
||||
type: "line",
|
||||
data: {
|
||||
labels: [
|
||||
"Jan",
|
||||
"Feb",
|
||||
"Mar",
|
||||
"Apr",
|
||||
"May",
|
||||
"Jun",
|
||||
"Jul",
|
||||
"Aug",
|
||||
"Sep",
|
||||
"Oct",
|
||||
"Nov",
|
||||
"Dec",
|
||||
],
|
||||
datasets: [
|
||||
{
|
||||
label: "Profit",
|
||||
data: total_profit,
|
||||
borderColor: "#A507FF",
|
||||
borderWidth: 4,
|
||||
fill: false,
|
||||
pointRadius: 1,
|
||||
pointHoverRadius: 6,
|
||||
tension: 0.4,
|
||||
},
|
||||
{
|
||||
label: "Loss",
|
||||
data: total_loss,
|
||||
borderColor: "#FF3B30",
|
||||
borderWidth: 4,
|
||||
fill: false,
|
||||
pointRadius: 1,
|
||||
pointHoverRadius: 6,
|
||||
tension: 0.4,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
tooltip: {
|
||||
enabled: true,
|
||||
backgroundColor: "white",
|
||||
borderColor: "#ddd",
|
||||
borderWidth: 1,
|
||||
titleColor: "#000",
|
||||
bodyColor: "#000",
|
||||
callbacks: {
|
||||
title: function (context) {
|
||||
const month = context[0].label;
|
||||
return `${month}`;
|
||||
},
|
||||
label: function (context) {
|
||||
const value = context.raw;
|
||||
const label = context.dataset.label;
|
||||
return `${label}: ${Math.abs(
|
||||
value
|
||||
).toLocaleString()}`;
|
||||
},
|
||||
},
|
||||
padding: 8,
|
||||
displayColors: false,
|
||||
},
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
|
||||
scales: {
|
||||
x: {
|
||||
grid: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
ticks: {
|
||||
callback: function (value) {
|
||||
return formatNumber(value);
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
drawBorder: false,
|
||||
color: "#C2C6CE",
|
||||
borderDash: [4, 4],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
layout: {
|
||||
padding: {
|
||||
left: 10,
|
||||
right: 10,
|
||||
top: 10,
|
||||
bottom: 10,
|
||||
},
|
||||
},
|
||||
hover: {
|
||||
mode: "nearest",
|
||||
intersect: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Function to get yearly statistics and update the chart
|
||||
function getYearlyStatistics(year = new Date().getFullYear()) {
|
||||
const url = $("#revenue-statistic").val() + "?year=" + year;
|
||||
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: url,
|
||||
dataType: "json",
|
||||
success: function (res) {
|
||||
const loss = res.loss;
|
||||
const profit = res.profit;
|
||||
const total_loss = [];
|
||||
const total_profit = [];
|
||||
|
||||
for (let i = 1; i <= 12; i++) {
|
||||
const monthName = getMonthNameFromIndex(i);
|
||||
|
||||
total_loss[i - 1] = loss
|
||||
.filter((item) => item.month == monthName)
|
||||
.reduce((sum, item) => sum + item.total, 0);
|
||||
|
||||
total_profit[i - 1] = profit
|
||||
.filter((item) => item.month == monthName)
|
||||
.reduce((sum, item) => sum + item.total, 0);
|
||||
}
|
||||
|
||||
|
||||
// Update chart with the new data
|
||||
totalEarningExpenseChart(total_loss, total_profit);
|
||||
|
||||
const loss_value = total_loss.reduce(
|
||||
(sum, value) => sum + value,
|
||||
0
|
||||
);
|
||||
const profit_value = total_profit.reduce(
|
||||
(sum, value) => sum + value,
|
||||
0
|
||||
);
|
||||
|
||||
document.querySelector(
|
||||
".loss-value"
|
||||
).textContent = `${currencyFormat(loss_value)}`;
|
||||
document.querySelector(
|
||||
".profit-value"
|
||||
).textContent = `${currencyFormat(profit_value)}`;
|
||||
},
|
||||
error: function (err) {
|
||||
console.error("Error fetching data:", err);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Function to convert month index to month name
|
||||
function getMonthNameFromIndex(index) {
|
||||
const months = [
|
||||
"January",
|
||||
"February",
|
||||
"March",
|
||||
"April",
|
||||
"May",
|
||||
"June",
|
||||
"July",
|
||||
"August",
|
||||
"September",
|
||||
"October",
|
||||
"November",
|
||||
"December",
|
||||
];
|
||||
return months[index - 1];
|
||||
}
|
||||
|
||||
// Initial chart load with the current year data
|
||||
getYearlyStatistics();
|
||||
|
||||
// Handle year change event
|
||||
$(".revenue-year").on("change", function () {
|
||||
const year = $(this).val();
|
||||
getYearlyStatistics(year);
|
||||
});
|
||||
|
||||
// Overall Reports ----------------------->
|
||||
const canvas = document.getElementById("Overallreports");
|
||||
const ctxOverallReports = canvas.getContext("2d");
|
||||
|
||||
const gradientSales = ctxOverallReports.createLinearGradient(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
canvas.height
|
||||
);
|
||||
gradientSales.addColorStop(0, "#8554FF");
|
||||
gradientSales.addColorStop(1, "#B8A1FF");
|
||||
|
||||
const gradientPurchase = ctxOverallReports.createLinearGradient(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
canvas.height
|
||||
);
|
||||
gradientPurchase.addColorStop(0, "#FD8D00");
|
||||
gradientPurchase.addColorStop(1, "#FFC694");
|
||||
|
||||
const gradientExpense = ctxOverallReports.createLinearGradient(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
canvas.height
|
||||
);
|
||||
gradientExpense.addColorStop(0, "#FF8983");
|
||||
gradientExpense.addColorStop(1, "#FF3B30");
|
||||
|
||||
const gradientIncome = ctxOverallReports.createLinearGradient(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
canvas.height
|
||||
);
|
||||
gradientIncome.addColorStop(0, "#05C535");
|
||||
gradientIncome.addColorStop(1, "#36F165");
|
||||
|
||||
// Data for the chart
|
||||
const data = {
|
||||
labels: ["Purchase", "Sales", "Income", "Expense"],
|
||||
datasets: [
|
||||
{
|
||||
backgroundColor: [
|
||||
gradientPurchase,
|
||||
gradientSales,
|
||||
gradientIncome,
|
||||
gradientExpense,
|
||||
],
|
||||
hoverOffset: 5,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const config = {
|
||||
type: "pie",
|
||||
data: data,
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
tooltip: {
|
||||
enabled: true,
|
||||
backgroundColor: "#FFFFFF",
|
||||
titleColor: "#000000",
|
||||
bodyColor: "#000000",
|
||||
// borderColor: "#CCCCCC",
|
||||
borderWidth: 1,
|
||||
displayColors: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const Overallreports = new Chart(ctxOverallReports, config);
|
||||
|
||||
window.addEventListener("resize", function () {
|
||||
Overallreports.resize();
|
||||
});
|
||||
|
||||
function fetchTaskData(year = new Date().getFullYear()) {
|
||||
const url = $("#get-overall-report").val() + "?year=" + year;
|
||||
$.ajax({
|
||||
url: url,
|
||||
method: "GET",
|
||||
success: function (response) {
|
||||
Overallreports.data.datasets[0].data = [
|
||||
response.overall_purchase || 0.000001,
|
||||
response.overall_sale || 0.000001,
|
||||
response.overall_income || 0.000001,
|
||||
response.overall_expense || 0.000001,
|
||||
];
|
||||
Overallreports.update();
|
||||
|
||||
$("#overall_purchase").text(
|
||||
currencyFormat(response.overall_purchase)
|
||||
);
|
||||
$("#overall_sale").text(currencyFormat(response.overall_sale));
|
||||
$("#overall_income").text(currencyFormat(response.overall_income));
|
||||
$("#overall_expense").text(
|
||||
currencyFormat(response.overall_expense)
|
||||
);
|
||||
},
|
||||
error: function (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
fetchTaskData();
|
||||
|
||||
$(".overview-year").on("change", function () {
|
||||
const year = $(this).val();
|
||||
fetchTaskData(year);
|
||||
});
|
||||
382
public/assets/plugins/custom/dashboard.js
Normal file
382
public/assets/plugins/custom/dashboard.js
Normal file
@@ -0,0 +1,382 @@
|
||||
// currency format
|
||||
function currencyFormat(amount, type = "icon", decimals = 2) {
|
||||
let symbol = $('#currency_symbol').val();
|
||||
let position = $('#currency_position').val();
|
||||
let code = $('#currency_code').val();
|
||||
|
||||
let formatted_amount = formattedAmount(amount, decimals);
|
||||
|
||||
// Apply currency format based on the position and type
|
||||
if (type === "icon" || type === "symbol") {
|
||||
if (position === "right") {
|
||||
return formatted_amount + symbol;
|
||||
} else {
|
||||
return symbol + formatted_amount;
|
||||
}
|
||||
} else {
|
||||
if (position === "right") {
|
||||
return formatted_amount + ' ' + code;
|
||||
} else {
|
||||
return code + ' ' + formatted_amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
getYearlySubscriptions();
|
||||
bestPlanSubscribes();
|
||||
});
|
||||
|
||||
$(".overview-year").on("change", function () {
|
||||
let year = $(this).val();
|
||||
bestPlanSubscribes(year);
|
||||
});
|
||||
|
||||
$(".yearly-statistics").on("change", function () {
|
||||
let year = $(this).val();
|
||||
getYearlySubscriptions(year);
|
||||
});
|
||||
|
||||
function getYearlySubscriptions(year = new Date().getFullYear()) {
|
||||
var url = $("#yearly-subscriptions-url").val();
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: url + "?year=" + year,
|
||||
dataType: "json",
|
||||
success: function (res) {
|
||||
var subscriptions = [];
|
||||
let totalAmount = 0;
|
||||
|
||||
for (var i = 0; i <= 11; i++) {
|
||||
var monthName = getMonthNameFromIndex(i);
|
||||
var subscriptionsData = res.find((item) => {
|
||||
return item.month === monthName;
|
||||
});
|
||||
|
||||
subscriptions[i] = subscriptionsData
|
||||
? subscriptionsData.total_amount
|
||||
: 0;
|
||||
|
||||
totalAmount += parseFloat(subscriptions[i]); // Add to total amount
|
||||
}
|
||||
|
||||
subscriptionChart(subscriptions);
|
||||
$(".income-value").text(currencyFormat(totalAmount));
|
||||
},
|
||||
error: function (xhr, status, error) {
|
||||
console.error("AJAX Error:", status, error);
|
||||
console.error("Response:", xhr.responseText);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
let userOverView = false;
|
||||
|
||||
// Function to update the User Overview chart
|
||||
function bestPlanSubscribes(year = new Date().getFullYear()) {
|
||||
if (userOverView) {
|
||||
userOverView.destroy();
|
||||
}
|
||||
|
||||
Chart.defaults.datasets.doughnut.cutout = "65%";
|
||||
let url = $("#get-plans-overview").val();
|
||||
$.ajax({
|
||||
url: (url += "?year=" + year),
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function (res) {
|
||||
var labels = [];
|
||||
var data = [];
|
||||
|
||||
$.each(res, function (index, planData) {
|
||||
var label =
|
||||
planData.plan.subscriptionName + ": " + planData.plan_count;
|
||||
labels.push(label);
|
||||
data.push(planData.plan_count);
|
||||
});
|
||||
|
||||
var roundedCornersFor = {
|
||||
start: Array.from({ length: data.length }, (_, i) => i),
|
||||
};
|
||||
Chart.defaults.elements.arc.roundedCornersFor = roundedCornersFor;
|
||||
|
||||
let inMonths = $("#plans-chart");
|
||||
userOverView = new Chart(inMonths, {
|
||||
type: "doughnut",
|
||||
data: {
|
||||
labels: labels.length ? labels : [0, 0],
|
||||
datasets: [
|
||||
{
|
||||
label: "Total Users",
|
||||
borderWidth: 0,
|
||||
data: data.length ? data : [0.0001, 0.0001],
|
||||
backgroundColor: [
|
||||
"#2CE78D",
|
||||
"#0a7cc2",
|
||||
"#C52127",
|
||||
"#2DB0F6",
|
||||
],
|
||||
borderColor: [
|
||||
"#2CE78D",
|
||||
"#0a7cc2",
|
||||
"#2CE78D",
|
||||
"#2DB0F6",
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
{
|
||||
afterUpdate: function (chart) {
|
||||
if (
|
||||
chart.options.elements.arc.roundedCornersFor !==
|
||||
undefined
|
||||
) {
|
||||
var arcValues = Object.values(
|
||||
chart.options.elements.arc.roundedCornersFor
|
||||
);
|
||||
|
||||
arcValues.forEach(function (arcs) {
|
||||
arcs = Array.isArray(arcs) ? arcs : [arcs];
|
||||
arcs.forEach(function (i) {
|
||||
var arc =
|
||||
chart.getDatasetMeta(0).data[i];
|
||||
arc.round = {
|
||||
x:
|
||||
(chart.chartArea.left +
|
||||
chart.chartArea.right) /
|
||||
2,
|
||||
y:
|
||||
(chart.chartArea.top +
|
||||
chart.chartArea.bottom) /
|
||||
2,
|
||||
radius:
|
||||
(arc.outerRadius +
|
||||
arc.innerRadius) /
|
||||
2,
|
||||
thickness:
|
||||
(arc.outerRadius -
|
||||
arc.innerRadius) /
|
||||
2,
|
||||
backgroundColor:
|
||||
arc.options.backgroundColor,
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
afterDraw: (chart) => {
|
||||
if (
|
||||
chart.options.elements.arc.roundedCornersFor !==
|
||||
undefined
|
||||
) {
|
||||
var { ctx, canvas } = chart;
|
||||
var arc,
|
||||
roundedCornersFor =
|
||||
chart.options.elements.arc
|
||||
.roundedCornersFor;
|
||||
for (var position in roundedCornersFor) {
|
||||
var values = Array.isArray(
|
||||
roundedCornersFor[position]
|
||||
)
|
||||
? roundedCornersFor[position]
|
||||
: [roundedCornersFor[position]];
|
||||
values.forEach((p) => {
|
||||
arc = chart.getDatasetMeta(0).data[p];
|
||||
var startAngle =
|
||||
Math.PI / 2 - arc.startAngle;
|
||||
var endAngle =
|
||||
Math.PI / 2 - arc.endAngle;
|
||||
ctx.save();
|
||||
ctx.translate(arc.round.x, arc.round.y);
|
||||
ctx.fillStyle =
|
||||
arc.options.backgroundColor;
|
||||
ctx.beginPath();
|
||||
if (position == "start") {
|
||||
ctx.arc(
|
||||
arc.round.radius *
|
||||
Math.sin(startAngle),
|
||||
arc.round.radius *
|
||||
Math.cos(startAngle),
|
||||
arc.round.thickness,
|
||||
0,
|
||||
2 * Math.PI
|
||||
);
|
||||
} else {
|
||||
ctx.arc(
|
||||
arc.round.radius *
|
||||
Math.sin(endAngle),
|
||||
arc.round.radius *
|
||||
Math.cos(endAngle),
|
||||
arc.round.thickness,
|
||||
0,
|
||||
2 * Math.PI
|
||||
);
|
||||
}
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
ctx.restore();
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
options: {
|
||||
responsive: true,
|
||||
tooltips: {
|
||||
displayColors: true,
|
||||
zIndex: 999999,
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
position: "top",
|
||||
labels: {
|
||||
usePointStyle: true,
|
||||
padding: 10,
|
||||
},
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
display: false,
|
||||
stacked: true,
|
||||
},
|
||||
y: {
|
||||
display: false,
|
||||
stacked: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
error: function (xhr, textStatus, errorThrown) {
|
||||
console.log("Error fetching user overview data: " + textStatus);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// PRINT TOP DATA
|
||||
getDashboardData();
|
||||
function getDashboardData() {
|
||||
var url = $("#get-dashboard").val();
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: url,
|
||||
dataType: "json",
|
||||
success: function (res) {
|
||||
$("#total_businesses").text(res.total_businesses);
|
||||
$("#expired_businesses").text(res.expired_businesses);
|
||||
$("#plan_subscribes").text(res.plan_subscribes);
|
||||
$("#business_categories").text(res.business_categories);
|
||||
$("#total_plans").text(res.total_plans);
|
||||
$("#total_staffs").text(res.total_staffs);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Function to convert month index to month name
|
||||
function getMonthNameFromIndex(index) {
|
||||
const monthNames = [
|
||||
"January", "February", "March", "April", "May", "June",
|
||||
"July", "August", "September", "October", "November", "December"
|
||||
];
|
||||
return monthNames[index];
|
||||
}
|
||||
|
||||
let statiSticsValu = false;
|
||||
|
||||
function subscriptionChart(subscriptions) {
|
||||
if (statiSticsValu) {
|
||||
statiSticsValu.destroy();
|
||||
}
|
||||
|
||||
var ctx = document.getElementById("monthly-statistics").getContext("2d");
|
||||
var gradient = ctx.createLinearGradient(0, 100, 10, 280);
|
||||
gradient.addColorStop(0, "#f2d5d8");
|
||||
gradient.addColorStop(1, "#BC212800");
|
||||
|
||||
var totals = subscriptions.reduce(function (accumulator, currentValue) {
|
||||
return accumulator + currentValue;
|
||||
}, 0);
|
||||
|
||||
statiSticsValu = new Chart(ctx, {
|
||||
type: "line",
|
||||
data: {
|
||||
labels: [
|
||||
"Jan",
|
||||
"Feb",
|
||||
"Mar",
|
||||
"Apr",
|
||||
"May",
|
||||
"Jun",
|
||||
"Jul",
|
||||
"Aug",
|
||||
"Sep",
|
||||
"Oct",
|
||||
"Nov",
|
||||
"Dec",
|
||||
],
|
||||
datasets: [
|
||||
{
|
||||
backgroundColor: gradient,
|
||||
label: "Total Subscription Amount: " + totals,
|
||||
fill: true,
|
||||
borderWidth: 1,
|
||||
borderColor: "#C52127",
|
||||
data: subscriptions,
|
||||
},
|
||||
],
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
tension: 0.4,
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
tooltip: {
|
||||
displayColors: true,
|
||||
backgroundColor: "#FFFFFF",
|
||||
titleColor: "#000000",
|
||||
bodyColor: "#000000",
|
||||
borderColor: "rgba(0, 0, 0, 0.1)",
|
||||
borderWidth: 1,
|
||||
padding: 10,
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
display: true,
|
||||
grid: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
y: {
|
||||
display: true,
|
||||
beginAtZero: true,
|
||||
grid: {
|
||||
color: "#D3D8DD",
|
||||
borderDash: [5, 5],
|
||||
borderDashOffset: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
padding: {
|
||||
top: 10,
|
||||
bottom: 10,
|
||||
left: 10,
|
||||
right: 10,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener("resize", function () {
|
||||
if (statiSticsValu) {
|
||||
statiSticsValu.resize();
|
||||
}
|
||||
});
|
||||
823
public/assets/plugins/custom/form.js
Normal file
823
public/assets/plugins/custom/form.js
Normal file
@@ -0,0 +1,823 @@
|
||||
"use strict";
|
||||
|
||||
const CSRF_TOKEN = $('meta[name="csrf-token"]').attr("content");
|
||||
|
||||
$.ajaxSetup({
|
||||
headers: {
|
||||
"X-CSRF-TOKEN": CSRF_TOKEN,
|
||||
},
|
||||
});
|
||||
|
||||
let $savingLoader = '<div class="spinner-border spinner-border-sm custom-text-primary" role="status"><span class="visually-hidden">Loading...</span></div>',
|
||||
|
||||
$ajaxform = $(".ajaxform");
|
||||
$ajaxform.initFormValidation(),
|
||||
$(document).on("submit", ".ajaxform", function (e) {
|
||||
e.preventDefault();
|
||||
let t = $(this).find(".submit-btn"),
|
||||
a = t.html();
|
||||
$ajaxform.valid() &&
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: this.action,
|
||||
data: new FormData(this),
|
||||
dataType: "json",
|
||||
contentType: !1,
|
||||
cache: !1,
|
||||
processData: !1,
|
||||
beforeSend: function () {
|
||||
t.html($savingLoader).attr("disabled", !0);
|
||||
},
|
||||
success: function (e) {
|
||||
t.html(a).removeClass("disabled").attr("disabled", !1);
|
||||
if (e.redirect) {
|
||||
window.sessionStorage.hasPreviousMessage = true;
|
||||
window.sessionStorage.previousMessage =
|
||||
e.message ?? null;
|
||||
if (e.secondary_redirect_url) {
|
||||
window.open(e.secondary_redirect_url, "_blank");
|
||||
}
|
||||
location.href = e.redirect;
|
||||
} else {
|
||||
Notify("success", null, e ?? 'Operation Successful.');
|
||||
}
|
||||
},
|
||||
error: function (e) {
|
||||
t.html(a).attr("disabled", !1), Notify("error", e);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
let $ajaxform_instant_reload = $(".ajaxform_instant_reload");
|
||||
$ajaxform_instant_reload.initFormValidation(),
|
||||
$(document).on("submit", ".ajaxform_instant_reload", function (e) {
|
||||
e.preventDefault();
|
||||
let t = $(this).find(".submit-btn"),
|
||||
a = t.html();
|
||||
$ajaxform_instant_reload.valid() &&
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: this.action,
|
||||
data: new FormData(this),
|
||||
dataType: "json",
|
||||
contentType: !1,
|
||||
cache: !1,
|
||||
processData: !1,
|
||||
positionClass: "toast-top-left",
|
||||
beforeSend: function () {
|
||||
t.html($savingLoader)
|
||||
.addClass("disabled")
|
||||
.attr("disabled", !0);
|
||||
},
|
||||
success: function (e) {
|
||||
t.html(a).removeClass("disabled").attr("disabled", !1),
|
||||
(window.sessionStorage.hasPreviousMessage = !0),
|
||||
(window.sessionStorage.previousMessage =
|
||||
e.message ?? null),
|
||||
e.redirect && (location.href = e.redirect);
|
||||
},
|
||||
error: function (e) {
|
||||
t.html(a).removeClass("disabled").attr("disabled", false);
|
||||
|
||||
if (e.responseJSON?.redirect) {
|
||||
sessionStorage.hasPreviousMessage = true;
|
||||
sessionStorage.previousMessage = e.responseJSON?.message ?? null;
|
||||
sessionStorage.notifyType = 'warning';
|
||||
location.href = e.responseJSON?.redirect;
|
||||
return;
|
||||
}
|
||||
|
||||
showInputErrors(e.responseJSON);
|
||||
Notify("error", e);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// bulk product upload in cart
|
||||
let $cartUploadform = $(".bulk_cart_upload_form");
|
||||
$cartUploadform.initFormValidation();
|
||||
$(document).on("submit", ".bulk_cart_upload_form", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
let t = $(this).find(".submit-btn"),
|
||||
a = t.html();
|
||||
|
||||
if (!$cartUploadform.valid()) return;
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: this.action,
|
||||
data: new FormData(this),
|
||||
dataType: "json",
|
||||
contentType: false,
|
||||
cache: false,
|
||||
processData: false,
|
||||
beforeSend: function () {
|
||||
t.html($savingLoader).attr("disabled", true);
|
||||
},
|
||||
success: function (response) {
|
||||
t.html(a).removeClass("disabled").attr("disabled", false);
|
||||
|
||||
if (response.success) {
|
||||
fetchUpdatedCart(calTotalAmount);
|
||||
$("#bulk-upload-modal").modal("hide");
|
||||
$cartUploadform[0].reset();
|
||||
toastr.success(response.message);
|
||||
|
||||
} else {
|
||||
toastr.error(response.message || "Some items failed to import.");
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
t.html(a).attr("disabled", false);
|
||||
|
||||
// Show error from server response
|
||||
if (xhr.responseJSON && xhr.responseJSON.message) {
|
||||
toastr.error(xhr.responseJSON.message);
|
||||
} else if (xhr.responseText) {
|
||||
toastr.error(xhr.responseText);
|
||||
} else {
|
||||
toastr.error("Something went wrong.");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// login form
|
||||
const $loginForm = $(".login_form");
|
||||
$loginForm.initFormValidation();
|
||||
$(document).on("submit", ".login_form", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
const $submitButton = $(this).find(".submit-btn");
|
||||
const originalButtonText = $submitButton.html();
|
||||
|
||||
if (!$loginForm.valid()) return;
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: this.action,
|
||||
data: new FormData(this),
|
||||
dataType: "json",
|
||||
contentType: false,
|
||||
cache: false,
|
||||
processData: false,
|
||||
positionClass: "toast-top-left",
|
||||
beforeSend: function () {
|
||||
$submitButton
|
||||
.html($savingLoader)
|
||||
.addClass("disabled")
|
||||
.attr("disabled", true);
|
||||
},
|
||||
success: function (response) {
|
||||
$submitButton
|
||||
.html(originalButtonText)
|
||||
.removeClass("disabled")
|
||||
.attr("disabled", false);
|
||||
|
||||
window.sessionStorage.hasPreviousMessage = true;
|
||||
window.sessionStorage.previousMessage = response.message || null;
|
||||
|
||||
if (response.redirect) {
|
||||
location.href = response.redirect;
|
||||
}
|
||||
},
|
||||
error: function (error) {
|
||||
let response = error.responseJSON;
|
||||
|
||||
$submitButton
|
||||
.html(originalButtonText)
|
||||
.removeClass("disabled")
|
||||
.attr("disabled", false);
|
||||
|
||||
if (response.redirect) {
|
||||
window.sessionStorage.hasPreviousMessage = true;
|
||||
window.sessionStorage.notifyType = "warning";
|
||||
window.sessionStorage.previousMessage = response.message || null;
|
||||
location.href = response.redirect;
|
||||
} else {
|
||||
showInputErrors(error.responseJSON);
|
||||
Notify("error", error);
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// sign up form
|
||||
let $sign_up_form = $(".sign_up_form");
|
||||
$sign_up_form.initFormValidation();
|
||||
|
||||
$(document).on("submit", ".sign_up_form", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
let t = $(this).find(".submit-btn"),
|
||||
a = t.html();
|
||||
|
||||
if ($sign_up_form.valid()) {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: this.action,
|
||||
data: new FormData(this),
|
||||
dataType: "json",
|
||||
contentType: false,
|
||||
cache: false,
|
||||
processData: false,
|
||||
beforeSend: function () {
|
||||
t.html($savingLoader) // Show loader
|
||||
.addClass("disabled")
|
||||
.attr("disabled", true);
|
||||
},
|
||||
success: function (response) {
|
||||
if (response.business_categories.length > 0) {
|
||||
response.business_categories.forEach((category) => {
|
||||
$(".business-categories").append(
|
||||
`<option value="${category.id}">${category.name}</option>`
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
$("#createFreeAccount").modal("hide");
|
||||
|
||||
if (response.otp_expiration) {
|
||||
$("#dynamicEmail").text(response.email);
|
||||
$("#verifymodal").modal("show");
|
||||
startCountdown(response.otp_expiration);
|
||||
} else {
|
||||
$("#setupAccountModal").modal("show");
|
||||
}
|
||||
},
|
||||
error: function (e) {
|
||||
// Handle error response
|
||||
showInputErrors(e.responseJSON);
|
||||
Notify("error", e);
|
||||
},
|
||||
complete: function () {
|
||||
t.html(a).removeClass("disabled").attr("disabled", false);
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Verify OTP submission
|
||||
let $verify_form = $(".verify_form");
|
||||
$verify_form.initFormValidation();
|
||||
|
||||
$(document).on("submit", ".verify_form", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
let t = $(this).find(".submit-btn"),
|
||||
a = t.html();
|
||||
|
||||
const email = $("#dynamicEmail").text();
|
||||
|
||||
// Get the OTP input values from the form
|
||||
const otpInputs = $(this).find(".otp-input");
|
||||
let otpValues = otpInputs
|
||||
.map(function () {
|
||||
return $(this).val();
|
||||
})
|
||||
.get()
|
||||
.join("");
|
||||
|
||||
// Validate OTP and form before submitting
|
||||
if ($verify_form.valid()) {
|
||||
let formData = new FormData(this);
|
||||
formData.append("email", email);
|
||||
formData.append("otp", otpValues);
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: this.action,
|
||||
data: formData,
|
||||
dataType: "json",
|
||||
contentType: false,
|
||||
cache: false,
|
||||
processData: false,
|
||||
beforeSend: function () {
|
||||
t.html($savingLoader).addClass("disabled").attr("disabled", !0);
|
||||
},
|
||||
success: function (res) {
|
||||
t.html(a).removeClass("disabled").attr("disabled", false);
|
||||
$("#verifymodal").modal("hide");
|
||||
$("#setupAccountModal").modal("show");
|
||||
if (res.business_categories.length > 0) {
|
||||
res.business_categories.forEach((category) => {
|
||||
$(".business-categories").append(
|
||||
`<option value="${category.id}">${category.name}</option>`
|
||||
);
|
||||
})
|
||||
}
|
||||
},
|
||||
error: function (response) {
|
||||
t.html(a).removeClass("disabled").attr("disabled", false);
|
||||
toastr.error(
|
||||
response.responseJSON.message || "An error occurred."
|
||||
);
|
||||
},
|
||||
});
|
||||
} else {
|
||||
toastr.error("Please enter all OTP digits.");
|
||||
}
|
||||
});
|
||||
|
||||
// business setup form
|
||||
let $business_setup_form = $(".business_setup_form");
|
||||
$business_setup_form.initFormValidation();
|
||||
|
||||
$(document).on("submit", ".business_setup_form", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
let t = $(this).find(".submit-btn"),
|
||||
a = t.html();
|
||||
|
||||
if ($business_setup_form.valid()) {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: this.action,
|
||||
data: new FormData(this),
|
||||
dataType: "json",
|
||||
contentType: false,
|
||||
cache: false,
|
||||
processData: false,
|
||||
beforeSend: function () {
|
||||
t.html($savingLoader) // Show loader
|
||||
.addClass("disabled")
|
||||
.attr("disabled", true);
|
||||
},
|
||||
success: function (res) {
|
||||
if (res.redirect) {
|
||||
window.sessionStorage.hasPreviousMessage = true;
|
||||
window.sessionStorage.previousMessage = res.message || 'Operation successfully.';
|
||||
location.href = res.redirect;
|
||||
} else {
|
||||
$("#setupAccountModal").modal("hide");
|
||||
$("#successModal").modal("show");
|
||||
Notify("success", null, res.message ?? 'Operation Successful.');
|
||||
}
|
||||
},
|
||||
error: function (e) {
|
||||
// Handle error response
|
||||
showInputErrors(e.responseJSON);
|
||||
Notify("error", e);
|
||||
},
|
||||
complete: function () {
|
||||
t.html(a).removeClass("disabled").attr("disabled", false);
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// OTP input field--------------------->
|
||||
const pinInputs = document.querySelectorAll(".pin-input");
|
||||
|
||||
pinInputs.forEach((inputField, index) => {
|
||||
inputField.addEventListener("input", () => {
|
||||
inputField.value = inputField.value.replace(/[^0-9]/g, "").slice(0, 1);
|
||||
|
||||
if (inputField.value && index < pinInputs.length - 1) {
|
||||
pinInputs[index + 1].focus();
|
||||
}
|
||||
});
|
||||
|
||||
inputField.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Backspace" && !inputField.value && index > 0) {
|
||||
pinInputs[index - 1].focus();
|
||||
}
|
||||
});
|
||||
|
||||
inputField.addEventListener("paste", (e) => {
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
|
||||
function showInputErrors(e) {
|
||||
if (e.errors !== undefined) {
|
||||
$.each(e.errors, function (field, message) {
|
||||
$("#" + field + "-error").remove();
|
||||
|
||||
let errorLabel = `
|
||||
<label id="${field}-error" class="error" for="${field}">${message}</label>
|
||||
`;
|
||||
|
||||
$("#" + field)
|
||||
.parents()
|
||||
.hasClass("form-check")
|
||||
? $("#" + field).parents().find(".form-check").append(errorLabel)
|
||||
: $("#" + field).addClass("error").after(errorLabel);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function ajaxSuccess(response, Notify) {
|
||||
if (response.redirect) {
|
||||
if (response.message) {
|
||||
window.sessionStorage.hasPreviousMessage = true;
|
||||
window.sessionStorage.previousMessage = response.message ?? null;
|
||||
}
|
||||
|
||||
location.href = response.redirect;
|
||||
} else if (response.message) {
|
||||
Notify("success", response);
|
||||
}
|
||||
}
|
||||
|
||||
//PREVIEW IMAGE
|
||||
function previewImage(input) {
|
||||
if (input.files && input.files[0]) {
|
||||
var reader = new FileReader();
|
||||
|
||||
reader.onload = function (e) {
|
||||
var inputId = $(input).attr("id");
|
||||
|
||||
// Select the image element based on the input's ID
|
||||
var imageElement = $("img.product-img").filter(function () {
|
||||
return $(this).closest("label").attr("for") === inputId;
|
||||
});
|
||||
imageElement.attr("src", e.target.result);
|
||||
imageElement.hide().fadeIn(650);
|
||||
};
|
||||
|
||||
reader.readAsDataURL(input.files[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Status button Change
|
||||
$(".change-text").on("change", function () {
|
||||
var $dynamicText = $(this).closest(".form-control").find(".dynamic-text");
|
||||
|
||||
if (this.checked) {
|
||||
$dynamicText.text("Active");
|
||||
} else {
|
||||
$dynamicText.text("Deactive");
|
||||
}
|
||||
});
|
||||
|
||||
// Status button Change
|
||||
$(".cnge-text").on("change", function () {
|
||||
var $test = $(this).closest(".form-control").find(".is-live-text");
|
||||
|
||||
if (this.checked) {
|
||||
$test.text("Yes");
|
||||
} else {
|
||||
$test.text("No");
|
||||
}
|
||||
});
|
||||
|
||||
/** STATUS CHANGE */
|
||||
$(".status").on("change", function () {
|
||||
var checkbox = $(this);
|
||||
var status = checkbox.prop("checked") ? 1 : 0;
|
||||
var url = checkbox.data("url");
|
||||
var method = checkbox.data("method");
|
||||
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: method ?? "POST",
|
||||
data: {
|
||||
status: status,
|
||||
},
|
||||
success: function (res) {
|
||||
if(status === 1){
|
||||
toastr.success(res.message + ' status published');
|
||||
}
|
||||
else{
|
||||
toastr.success(res.message + ' status unpublished');
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
toastr.error(xhr.responseJSON.message);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
$(document).ready(function () {
|
||||
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const success_modal = urlParams.get('success_modal');
|
||||
const setup_business = urlParams.get('setup_business');
|
||||
|
||||
if (success_modal == 1) {
|
||||
$("#successModal").modal("show");
|
||||
}
|
||||
|
||||
if (setup_business == 1) {
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: $("#get-business-categories").val(),
|
||||
success: function (res) {
|
||||
$("#setupAccountModal").modal("show");
|
||||
if (res.length > 0) {
|
||||
res.forEach((category) => {
|
||||
$(".business-categories").append(
|
||||
`<option value="${category.id}">${category.name}</option>`
|
||||
);
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** SEARCH */
|
||||
$(".searchInput").on("input", function (e) {
|
||||
e.preventDefault();
|
||||
const searchText = $(this).val();
|
||||
const url = $(this).attr("action");
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: "GET",
|
||||
data: {
|
||||
search: searchText,
|
||||
},
|
||||
success: function (res) {
|
||||
$(".searchResults").html(res.data);
|
||||
},
|
||||
error: function (xhr) {
|
||||
console.log(xhr.responseText);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// Handle the "x" icon click event
|
||||
$(".clearSearchInput").on("click", function () {
|
||||
$(".searchInput").val(""); // Clear the search input
|
||||
$(".clearSearchInput").addClass("d-none");
|
||||
$(this).closest(".searchForm").submit();
|
||||
});
|
||||
|
||||
// Show/hide "delete" button based on input value
|
||||
$(".searchInput").on("input", function () {
|
||||
if ($(this).val().trim() !== "") {
|
||||
$(".clearSearchInput").removeClass("d-none");
|
||||
} else {
|
||||
$(".clearSearchInput").addClass("d-none");
|
||||
}
|
||||
});
|
||||
|
||||
// Select all checkboxes when the checkbox in the header is clicked
|
||||
$(document).on("click", ".selectAllCheckbox", function () {
|
||||
$(".checkbox-item").prop("checked", this.checked);
|
||||
if (this.checked) {
|
||||
$(".delete-selected").addClass("text-danger");
|
||||
} else {
|
||||
$(".delete-selected").removeClass("text-danger");
|
||||
}
|
||||
});
|
||||
|
||||
// Perform the delete action for selected elements when the delete icon is clicked
|
||||
$(document).on("click", ".delete-selected", function () {
|
||||
var checkedCheckboxes = $(".checkbox-item:checked");
|
||||
if (checkedCheckboxes.length === 0) {
|
||||
toastr.error(
|
||||
"No items selected. Please select at least one item to delete."
|
||||
);
|
||||
} else {
|
||||
$("#multi-delete-modal").modal("show");
|
||||
}
|
||||
});
|
||||
|
||||
$(".multi-delete-btn").on("click", function () {
|
||||
var ids = $(".checkbox-item:checked")
|
||||
.map(function () {
|
||||
return $(this).val();
|
||||
})
|
||||
.get();
|
||||
|
||||
let submitButton = $(this);
|
||||
let originalButtonText = submitButton.html();
|
||||
let del_url = $(".checkbox-item").data("url");
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: del_url,
|
||||
data: {
|
||||
ids,
|
||||
},
|
||||
dataType: "json",
|
||||
beforeSend: function () {
|
||||
submitButton.html($savingLoader).attr("disabled", true);
|
||||
},
|
||||
success: function (res) {
|
||||
submitButton.html(originalButtonText).attr("disabled", false);
|
||||
window.sessionStorage.hasPreviousMessage = true;
|
||||
window.sessionStorage.previousMessage = res.message ?? null;
|
||||
res.redirect && (location.href = res.redirect);
|
||||
},
|
||||
error: function (xhr) {
|
||||
submitButton.html(originalButtonText).attr("disabled", false);
|
||||
Notify("error", xhr);
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/** system setting start */
|
||||
// Initial label text
|
||||
var initialLabelText = $("#mail-driver-type-select option:selected").val();
|
||||
|
||||
$("#mail-driver-type-select").on("change", function () {
|
||||
var selectedOptionValue = $(this).val();
|
||||
$("#mail-driver-label").text(selectedOptionValue);
|
||||
});
|
||||
|
||||
$("#mail-driver-label").text(initialLabelText);
|
||||
|
||||
/** system setting end */
|
||||
|
||||
//Subscriber view modal
|
||||
$(".subscriber-view").on("click", function () {
|
||||
$(".business_name").text($(this).data("name"));
|
||||
$("#image").attr("src", $(this).data("image"));
|
||||
$("#category").text($(this).data("category"));
|
||||
$("#package").text($(this).data("package"));
|
||||
$("#gateway").text($(this).data("gateway"));
|
||||
$("#enroll_date").text($(this).data("enroll"));
|
||||
$("#expired_date").text($(this).data("expired"));
|
||||
|
||||
var gateway_img = $(this).data("manul-attachment");
|
||||
|
||||
if (gateway_img) {
|
||||
var img = new Image();
|
||||
img.onload = function () {
|
||||
$("#manual_img").removeClass('d-none');
|
||||
$("#manul_attachment").attr("src", gateway_img);
|
||||
};
|
||||
img.onerror = function () {
|
||||
$("#manual_img").addClass('d-none');
|
||||
};
|
||||
img.src = gateway_img;
|
||||
} else {
|
||||
$("#manual_img").addClass('d-none');
|
||||
}
|
||||
});
|
||||
|
||||
$('.subscribe-plan').on('click', function(e) {
|
||||
$('#createFreeAccount').modal('show');
|
||||
|
||||
$('#plan_id').val($(this).data('plan-id'));
|
||||
$('.google-login').attr('href', $(this).data('google-url'));
|
||||
$('.x-login').attr('href', $(this).data('twitter-url'));
|
||||
})
|
||||
|
||||
|
||||
// Affilite part
|
||||
let $afl_sign_up_form = $(".afl_sign_up_form");
|
||||
$afl_sign_up_form.initFormValidation();
|
||||
|
||||
$(document).on("submit", ".afl_sign_up_form", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
let t = $(this).find(".submit-btn"),
|
||||
a = t.html();
|
||||
|
||||
if ($afl_sign_up_form.valid()) {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: this.action,
|
||||
data: new FormData(this),
|
||||
dataType: "json",
|
||||
contentType: false,
|
||||
cache: false,
|
||||
processData: false,
|
||||
beforeSend: function () {
|
||||
t.html($savingLoader) // Show loader
|
||||
.addClass("disabled")
|
||||
.attr("disabled", true);
|
||||
},
|
||||
success: function (response) {
|
||||
$("#dynamicEmail").text(response.email);
|
||||
$("#verifymodal").modal("show");
|
||||
startCountdown(response.otp_expiration);
|
||||
},
|
||||
error: function (e) {
|
||||
showInputErrors(e.responseJSON);
|
||||
Notify("error", e);
|
||||
},
|
||||
complete: function () {
|
||||
t.html(a).removeClass("disabled").attr("disabled", false);
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
let $afl_verify_form = $(".afl_verify_form");
|
||||
$afl_verify_form.initFormValidation();
|
||||
|
||||
$(document).on("submit", ".afl_verify_form", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
let t = $(this).find(".submit-btn"),
|
||||
a = t.html();
|
||||
|
||||
const email = $("#dynamicEmail").text();
|
||||
|
||||
const otpInputs = $(this).find(".otp-input");
|
||||
let otpValues = otpInputs
|
||||
.map(function () {
|
||||
return $(this).val();
|
||||
})
|
||||
.get()
|
||||
.join("");
|
||||
|
||||
if ($afl_verify_form.valid()) {
|
||||
let formData = new FormData(this);
|
||||
formData.append("email", email);
|
||||
formData.append("otp", otpValues);
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: this.action,
|
||||
data: formData,
|
||||
dataType: "json",
|
||||
contentType: false,
|
||||
cache: false,
|
||||
processData: false,
|
||||
beforeSend: function () {
|
||||
t.html($savingLoader).addClass("disabled").attr("disabled", !0);
|
||||
},
|
||||
success: function (res) {
|
||||
t.html(a).removeClass("disabled").attr("disabled", false);
|
||||
if (res.redirect) {
|
||||
window.sessionStorage.hasPreviousMessage = true;
|
||||
window.sessionStorage.previousMessage = res.message || 'Operation successfully.';
|
||||
location.href = res.redirect;
|
||||
} else {
|
||||
$("#setupAccountModal").modal("hide");
|
||||
Notify("success", null, res.message ?? 'Operation Successful.');
|
||||
}
|
||||
|
||||
},
|
||||
error: function (response) {
|
||||
t.html(a).removeClass("disabled").attr("disabled", false);
|
||||
toastr.error(
|
||||
response.responseJSON.message || "An error occurred."
|
||||
);
|
||||
},
|
||||
});
|
||||
} else {
|
||||
toastr.error("Please enter all OTP digits.");
|
||||
}
|
||||
});
|
||||
|
||||
$("#payout_type").on("change", function () {
|
||||
var type = $(this).val();
|
||||
$('.payout-bank, .payout-mfs').addClass('d-none');
|
||||
|
||||
if (type == 'bank') {
|
||||
$('.payout-bank').removeClass('d-none');
|
||||
} else if (type == 'mfs') {
|
||||
$('.payout-mfs').removeClass('d-none');
|
||||
}
|
||||
});
|
||||
|
||||
// invoice setting done
|
||||
|
||||
$(".invoice-size-radio").on("change", function () {
|
||||
let $form = $(this).closest('.invoice_form');
|
||||
let submitUrl = $form.attr('action');
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: submitUrl,
|
||||
data: new FormData($form[0]),
|
||||
dataType: "json",
|
||||
contentType: false,
|
||||
cache: false,
|
||||
processData: false,
|
||||
beforeSend: function () {
|
||||
Notify("info", null, "Updating invoice setting...");
|
||||
},
|
||||
success: function (response) {
|
||||
Notify("success", null, response ?? 'Invoice setting updated successfully.');
|
||||
},
|
||||
error: function (xhr) {
|
||||
let errorMsg = xhr.responseJSON?.message || 'Something went wrong!';
|
||||
Notify("error", null, errorMsg);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('change', '.serial-update', function () {
|
||||
// Get the checkbox value (1 if checked, 0 if unchecked)
|
||||
let show_serial = $(this).is(':checked') ? 1 : 0;
|
||||
|
||||
// Update hidden input value (optional, keeps DOM in sync)
|
||||
$('#hidden_show_serial').val(show_serial);
|
||||
|
||||
// Get the route from hidden input
|
||||
let route = $('#serial_route').val();
|
||||
|
||||
// Send AJAX request
|
||||
$.ajax({
|
||||
url: route,
|
||||
type: 'POST',
|
||||
data: {
|
||||
show_serial: show_serial
|
||||
},
|
||||
success: function (res) {
|
||||
Notify('success', null, res.message ?? 'IMEI/Serial updated successfully.');
|
||||
},
|
||||
error: function (err) {
|
||||
Notify('error', err);
|
||||
}
|
||||
});
|
||||
});
|
||||
20
public/assets/plugins/custom/notification.js
Normal file
20
public/assets/plugins/custom/notification.js
Normal file
@@ -0,0 +1,20 @@
|
||||
function Notify(type, res, msg = null) {
|
||||
var type;
|
||||
var message;
|
||||
|
||||
switch (type) {
|
||||
case "error":
|
||||
message = msg ?? res.responseJSON.message ?? res.responseText ?? 'Oops! Something went wrong';
|
||||
toastr.error(message);
|
||||
break;
|
||||
case "success":
|
||||
message = msg ?? res.message ?? 'Congratulate! Operation Successful.';
|
||||
toastr.success(message);
|
||||
break;
|
||||
case "warning":
|
||||
message = msg ?? res.message ?? res.responseJSON.message ?? 'Warning! Operation Failed.';
|
||||
toastr.warning(message);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
1009
public/assets/plugins/jquery-confirm/jquery-confirm.min.css
vendored
Normal file
1009
public/assets/plugins/jquery-confirm/jquery-confirm.min.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
10
public/assets/plugins/jquery-confirm/jquery-confirm.min.js
vendored
Normal file
10
public/assets/plugins/jquery-confirm/jquery-confirm.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
4
public/assets/plugins/jquery-validation/jquery.validate.min.js
vendored
Normal file
4
public/assets/plugins/jquery-validation/jquery.validate.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
138
public/assets/plugins/validation-setup/validation-setup.js
Normal file
138
public/assets/plugins/validation-setup/validation-setup.js
Normal file
@@ -0,0 +1,138 @@
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Checkbox: Select All
|
||||
*/
|
||||
$(".checkAll").on("click", function () {
|
||||
$("input:checkbox").not(this).prop("checked", this.checked);
|
||||
});
|
||||
|
||||
/**
|
||||
* Toggle Period Duration
|
||||
*/
|
||||
$("#is_period").on("change", function () {
|
||||
if ($(this).val() == 1) {
|
||||
$(".period_duration").removeClass("d-none");
|
||||
} else {
|
||||
$(".period_duration").addClass("d-none");
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Dismiss Notification
|
||||
*/
|
||||
$(".anna-dismiss").on("click", function () {
|
||||
$(".top-header-area").fadeOut();
|
||||
});
|
||||
|
||||
/**
|
||||
* Form Validation Initialization
|
||||
*/
|
||||
$.fn.initFormValidation = function () {
|
||||
let validator = $(this).validate({
|
||||
errorClass: "error",
|
||||
highlight: function (element, errorClass) {
|
||||
let $element = $(element);
|
||||
|
||||
if ($element.hasClass("select2-hidden-accessible")) {
|
||||
$("#select2-" + $element.attr("id") + "-container").parent().addClass(errorClass);
|
||||
} else if ($element.parents().hasClass("image-checkbox")) {
|
||||
Notify("error", null, $element.parent().data("required"));
|
||||
} else {
|
||||
$element.addClass(errorClass);
|
||||
}
|
||||
},
|
||||
unhighlight: function (element, errorClass) {
|
||||
let $element = $(element);
|
||||
|
||||
if ($element.hasClass("select2-hidden-accessible")) {
|
||||
$("#select2-" + $element.attr("id") + "-container").parent().removeClass(errorClass);
|
||||
} else {
|
||||
$element.removeClass(errorClass);
|
||||
}
|
||||
},
|
||||
errorPlacement: function (error, element) {
|
||||
let $element = $(element);
|
||||
|
||||
if ($element.hasClass("select2-hidden-accessible")) {
|
||||
let container = $("#select2-" + $element.attr("id") + "-container").parent();
|
||||
error.insertAfter(container);
|
||||
} else if ($element.parent().hasClass("form-floating")) {
|
||||
error.insertAfter($element.parent().css("color", "text-danger"));
|
||||
} else if ($element.parent().hasClass("input-group")) {
|
||||
error.insertAfter($element.parent());
|
||||
} else {
|
||||
error.insertAfter($element);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
$(this).on("select2:select", function () {
|
||||
if (!$.isEmptyObject(validator.submitted)) {
|
||||
validator.form();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Select2 Initialization
|
||||
*/
|
||||
function initializeSelect2() {
|
||||
if (typeof jQuery !== "undefined" && $.fn.select2 !== undefined) {
|
||||
document
|
||||
.querySelectorAll('[data-control="select2"]')
|
||||
.forEach((element) => {
|
||||
let options = {
|
||||
dir: document.body.getAttribute("direction"),
|
||||
};
|
||||
|
||||
if (element.getAttribute("data-hide-search") === "true") {
|
||||
options.minimumResultsForSearch = Infinity;
|
||||
}
|
||||
|
||||
if (element.hasAttribute("data-placeholder")) {
|
||||
options.placeholder = element.getAttribute("data-placeholder");
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$(element).select2(options);
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on("select2:open", function () {
|
||||
let searchFields = document.querySelectorAll(".select2-container--open .select2-search__field");
|
||||
if (searchFields.length > 0) {
|
||||
searchFields[searchFields.length - 1].focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Session Message on Page Load
|
||||
*/
|
||||
$(document).ready(function () {
|
||||
if (window.sessionStorage.hasPreviousMessage === "true") {
|
||||
Notify(window.sessionStorage?.notifyType ?? "success", null, window.sessionStorage.previousMessage, window.sessionStorage.redirect);
|
||||
window.sessionStorage.hasPreviousMessage = false;
|
||||
window.sessionStorage.notifyType = "success";
|
||||
}
|
||||
|
||||
initializeSelect2();
|
||||
});
|
||||
|
||||
/**
|
||||
* Select All Checkbox Functionality
|
||||
*/
|
||||
if ($("#selectAll").length > 0) {
|
||||
let selectAll = document.querySelector("#selectAll");
|
||||
let checkboxes = document.querySelectorAll('[type="checkbox"]');
|
||||
|
||||
selectAll.addEventListener("change", (event) => {
|
||||
checkboxes.forEach((checkbox) => {
|
||||
checkbox.checked = event.target.checked;
|
||||
});
|
||||
});
|
||||
}
|
||||
})(jQuery);
|
||||
Reference in New Issue
Block a user