migrate to gtea from bistbucket

This commit is contained in:
2026-03-15 17:08:23 +07:00
commit 129ca2260c
3716 changed files with 566316 additions and 0 deletions

View 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);
});
});

View 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);
});

View 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();
}
});

View 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);
}
});
});

View 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:
}
}