514 lines
24 KiB
JavaScript
Vendored
514 lines
24 KiB
JavaScript
Vendored
const App = {
|
|
setup() {
|
|
const state = Vue.reactive({
|
|
cardsData: {},
|
|
salesData: {},
|
|
purchaseData: {},
|
|
inventoryData: {},
|
|
crmData: {},
|
|
currency: '...',
|
|
});
|
|
|
|
const cardSalesQtyRef = Vue.ref(null);
|
|
const cardPurchaseQtyRef = Vue.ref(null);
|
|
|
|
const salesOrderGridRef = Vue.ref(null);
|
|
const purchaseOrderGridRef = Vue.ref(null);
|
|
const customerGroupChartRef = Vue.ref(null);
|
|
const vendorGroupChartRef = Vue.ref(null);
|
|
const customerCategoryChartRef = Vue.ref(null);
|
|
const vendorCategoryChartRef = Vue.ref(null);
|
|
|
|
|
|
const campaignTotalAmountRef = Vue.ref(null);
|
|
const leadTotalAmountRef = Vue.ref(null);
|
|
const budgetTotalAmountRef = Vue.ref(null);
|
|
const expenseTotalAmountRef = Vue.ref(null);
|
|
const closedTotalAmountRef = Vue.ref(null);
|
|
|
|
|
|
|
|
const leadPipelineFunnelRef = Vue.ref(null);
|
|
const salesTeamLeadClosingRef = Vue.ref(null);
|
|
const campaignByStatusRef = Vue.ref(null);
|
|
const leadActivityByTypeRef = Vue.ref(null);
|
|
|
|
|
|
const services = {
|
|
getCardsData: async () => {
|
|
try {
|
|
const response = await AxiosManager.get('/Dashboard/GetCardsDashboard', {});
|
|
return response;
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
},
|
|
getSalesData: async () => {
|
|
try {
|
|
const response = await AxiosManager.get('/Dashboard/GetSalesDashboard', {});
|
|
return response;
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
},
|
|
getPurchaseData: async () => {
|
|
try {
|
|
const response = await AxiosManager.get('/Dashboard/GetPurchaseDashboard', {});
|
|
return response;
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
},
|
|
getCRMData: async () => {
|
|
try {
|
|
const response = await AxiosManager.get('/Dashboard/GetCRMDashboard', {});
|
|
return response;
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
},
|
|
getLeadPipelineFunnelData: async () => {
|
|
try {
|
|
const response = await AxiosManager.get('/Dashboard/GetLeadPipelineFunnel', {});
|
|
return response;
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
},
|
|
getSalesTeamLeadClosingData: async () => {
|
|
try {
|
|
const response = await AxiosManager.get('/Dashboard/GetSalesTeamLeadClosing', {});
|
|
return response;
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
},
|
|
getCampaignByStatusData: async () => {
|
|
try {
|
|
const response = await AxiosManager.get('/Dashboard/GetCampaignByStatus', {});
|
|
return response;
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
},
|
|
getLeadActivityByTypeData: async () => {
|
|
try {
|
|
const response = await AxiosManager.get('/Dashboard/GetLeadActivityByType', {});
|
|
return response;
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
},
|
|
};
|
|
|
|
const methods = {
|
|
populateCardsData: async () => {
|
|
const response = await services.getCardsData();
|
|
state.cardsData = response?.data?.content?.data;
|
|
methods.populateCards();
|
|
},
|
|
populateSalesData: async () => {
|
|
const response = await services.getSalesData();
|
|
state.salesData = response?.data?.content?.data;
|
|
methods.populateSalesOrderGrid();
|
|
methods.populateSalesByCustomerGroupChart();
|
|
methods.populateSalesByCustomerCategoryChart();
|
|
},
|
|
populatePurchaseData: async () => {
|
|
const response = await services.getPurchaseData();
|
|
state.purchaseData = response?.data?.content?.data;
|
|
methods.populatePurchaseOrderGrid();
|
|
methods.populatePurchaseByVendorGroupChart();
|
|
methods.populatePurchaseByVendorCategoryChart();
|
|
},
|
|
populateCards: () => {
|
|
const cardsDashboard = state.cardsData?.cardsDashboard;
|
|
|
|
if (cardsDashboard) {
|
|
cardSalesQtyRef.value.textContent = cardsDashboard.salesTotal || 0;
|
|
cardPurchaseQtyRef.value.textContent = cardsDashboard.purchaseTotal || 0;
|
|
} else {
|
|
console.error('CardsDashboard data is not available.');
|
|
}
|
|
},
|
|
populateSalesOrderGrid: () => {
|
|
const salesOrderDashboard = state.salesData?.salesOrderDashboard ?? [];
|
|
new ej.grids.Grid({
|
|
dataSource: salesOrderDashboard,
|
|
allowFiltering: false,
|
|
allowSorting: true,
|
|
allowSelection: false,
|
|
allowGrouping: false,
|
|
allowTextWrap: false,
|
|
allowResizing: false,
|
|
allowPaging: true,
|
|
allowExcelExport: false,
|
|
sortSettings: { columns: [{ field: 'orderDate', direction: 'Descending' }] },
|
|
pageSettings: { currentPage: 1, pageSize: 10 },
|
|
autoFit: false,
|
|
showColumnMenu: false,
|
|
gridLines: 'Horizontal',
|
|
columns: [
|
|
{
|
|
field: 'id', isPrimaryKey: true, headerText: 'Id', visible: false
|
|
},
|
|
{ field: 'salesOrder.orderDate', headerText: 'Order Date', width: 70, type: 'dateTime', format: 'yyyy-MM-dd', textAlign: 'Left' },
|
|
{ field: 'salesOrder.number', headerText: '#Number', width: 90 },
|
|
{ field: 'product.name', headerText: 'Product', width: 150 },
|
|
{ field: 'total', headerText: 'Total', width: 70, type: 'number', format: 'N2', textAlign: 'Right' },
|
|
],
|
|
}, salesOrderGridRef.value);
|
|
},
|
|
populatePurchaseOrderGrid: () => {
|
|
const purchaseOrderDashboard = state.purchaseData?.purchaseOrderDashboard ?? [];
|
|
new ej.grids.Grid({
|
|
dataSource: purchaseOrderDashboard,
|
|
allowFiltering: false,
|
|
allowSorting: true,
|
|
allowSelection: false,
|
|
allowGrouping: false,
|
|
allowTextWrap: false,
|
|
allowResizing: false,
|
|
allowPaging: true,
|
|
allowExcelExport: false,
|
|
sortSettings: { columns: [{ field: 'orderDate', direction: 'Descending' }] },
|
|
pageSettings: { currentPage: 1, pageSize: 10 },
|
|
autoFit: false,
|
|
showColumnMenu: false,
|
|
gridLines: 'Horizontal',
|
|
columns: [
|
|
{
|
|
field: 'id', isPrimaryKey: true, headerText: 'Id', visible: false
|
|
},
|
|
{ field: 'purchaseOrder.orderDate', headerText: 'Order Date', width: 70, type: 'dateTime', format: 'yyyy-MM-dd', textAlign: 'Left' },
|
|
{ field: 'purchaseOrder.number', headerText: '#Number', width: 90 },
|
|
{ field: 'product.name', headerText: 'Product', width: 150 },
|
|
{ field: 'total', headerText: 'Total', width: 70, type: 'number', format: 'N2', textAlign: 'Right' },
|
|
],
|
|
}, purchaseOrderGridRef.value);
|
|
},
|
|
populateSalesByCustomerGroupChart: () => {
|
|
const salesByCustomerGroupDashboard = state.salesData?.salesByCustomerGroupDashboard ?? [];
|
|
new ej.charts.Chart(
|
|
{
|
|
primaryXAxis: {
|
|
valueType: 'Category', interval: 1, majorGridLines: { width: 0 }, majorTickLines: { width: 0 }, labelIntersectAction: 'None', labelRotation: ej.base.Browser.isDevice ? -45 : 0, minorTickLines: { width: 0 }
|
|
},
|
|
chartArea: { border: { width: 0 } },
|
|
primaryYAxis: {
|
|
title: 'Quantity',
|
|
majorTickLines: { width: 0 }, lineStyle: { width: 0 },
|
|
},
|
|
series: salesByCustomerGroupDashboard,
|
|
title: 'Sales by Customer Group',
|
|
tooltip: { enable: true, header: "<b>${point.tooltip}</b>", shared: true },
|
|
legendSettings: { enableHighlight: true },
|
|
palettes: ["#E94649", "#F6B53F", "#009CFF", "#C4C24A"],
|
|
},
|
|
customerGroupChartRef.value);
|
|
},
|
|
populatePurchaseByVendorGroupChart: () => {
|
|
const purchaseByVendorGroupDashboard = state.purchaseData?.purchaseByVendorGroupDashboard ?? [];
|
|
new ej.charts.Chart(
|
|
{
|
|
primaryXAxis: {
|
|
valueType: 'Category', interval: 1, majorGridLines: { width: 0 }, majorTickLines: { width: 0 }, labelIntersectAction: 'None', labelRotation: ej.base.Browser.isDevice ? -45 : 0, minorTickLines: { width: 0 }
|
|
},
|
|
chartArea: { border: { width: 0 } },
|
|
primaryYAxis: {
|
|
title: 'Quantity',
|
|
majorTickLines: { width: 0 }, lineStyle: { width: 0 },
|
|
},
|
|
series: purchaseByVendorGroupDashboard,
|
|
title: 'Purchase by Vendor Group',
|
|
tooltip: { enable: true, header: "<b>${point.tooltip}</b>", shared: true },
|
|
legendSettings: { enableHighlight: true },
|
|
palettes: ["#E94649", "#F6B53F", "#009CFF", "#C4C24A"],
|
|
},
|
|
vendorGroupChartRef.value);
|
|
},
|
|
populateSalesByCustomerCategoryChart: () => {
|
|
const salesByCustomerCategoryDashboard = state.salesData?.salesByCustomerCategoryDashboard ?? [];
|
|
new ej.charts.Chart(
|
|
{
|
|
primaryXAxis: {
|
|
valueType: 'Category', interval: 1, majorGridLines: { width: 0 }, majorTickLines: { width: 0 }, labelIntersectAction: 'None', labelRotation: ej.base.Browser.isDevice ? -45 : 0, minorTickLines: { width: 0 }
|
|
},
|
|
chartArea: { border: { width: 0 } },
|
|
primaryYAxis: {
|
|
title: 'Quantity',
|
|
majorTickLines: { width: 0 }, lineStyle: { width: 0 },
|
|
},
|
|
series: salesByCustomerCategoryDashboard,
|
|
title: 'Sales by Customer Category',
|
|
tooltip: { enable: true, header: "<b>${point.tooltip}</b>", shared: true },
|
|
legendSettings: { enableHighlight: true },
|
|
palettes: ["#E94649", "#F6B53F", "#009CFF", "#C4C24A"],
|
|
},
|
|
customerCategoryChartRef.value);
|
|
},
|
|
populatePurchaseByVendorCategoryChart: () => {
|
|
const purchaseByVendorCategoryDashboard = state.purchaseData?.purchaseByVendorCategoryDashboard ?? [];
|
|
new ej.charts.Chart(
|
|
{
|
|
primaryXAxis: {
|
|
valueType: 'Category', interval: 1, majorGridLines: { width: 0 }, majorTickLines: { width: 0 }, labelIntersectAction: 'None', labelRotation: ej.base.Browser.isDevice ? -45 : 0, minorTickLines: { width: 0 }
|
|
},
|
|
chartArea: { border: { width: 0 } },
|
|
primaryYAxis: {
|
|
title: 'Quantity',
|
|
majorTickLines: { width: 0 }, lineStyle: { width: 0 },
|
|
},
|
|
series: purchaseByVendorCategoryDashboard,
|
|
title: 'Purchase by Vendor Category',
|
|
tooltip: { enable: true, header: "<b>${point.tooltip}</b>", shared: true },
|
|
legendSettings: { enableHighlight: true },
|
|
palettes: ["#E94649", "#F6B53F", "#009CFF", "#C4C24A"],
|
|
},
|
|
vendorCategoryChartRef.value);
|
|
},
|
|
formatWithM: (value) => {
|
|
const formatted = NumberFormatManager.formatToLocaleNoDecimal((value ?? 0) / 1000000);
|
|
return `${formatted}M`;
|
|
},
|
|
populateCRMData: async () => {
|
|
const response = await services.getCRMData();
|
|
state.crmData = response?.data?.content?.data;
|
|
methods.populateCRM();
|
|
},
|
|
populateCRM: () => {
|
|
const crmDashboard = state.crmData?.crmDashboard;
|
|
|
|
if (crmDashboard) {
|
|
campaignTotalAmountRef.value.textContent = methods.formatWithM(crmDashboard.campaignTotalAmount);
|
|
leadTotalAmountRef.value.textContent = methods.formatWithM(crmDashboard.leadTotalAmount);
|
|
budgetTotalAmountRef.value.textContent = methods.formatWithM(crmDashboard.budgetTotalAmount);
|
|
expenseTotalAmountRef.value.textContent = methods.formatWithM(crmDashboard.expenseTotalAmount);
|
|
closedTotalAmountRef.value.textContent = methods.formatWithM(crmDashboard.closedTotalAmount);
|
|
} else {
|
|
console.error('CRMDashboard data is not available.');
|
|
}
|
|
},
|
|
populateLeadPipelineFunnelData: async () => {
|
|
methods.populateLeadPipelineFunnel();
|
|
},
|
|
populateLeadPipelineFunnel: async () => {
|
|
const response = await services.getLeadPipelineFunnelData();
|
|
const leadPipelineFunnelData = response?.data?.content?.data ?? [];
|
|
|
|
new ej.charts.AccumulationChart({
|
|
series: [{
|
|
type: 'Funnel',
|
|
dataSource: leadPipelineFunnelData,
|
|
xName: 'x', yName: 'y',
|
|
dataLabel: { name: 'text', visible: true, position: 'Inside', font: { fontWeight: '600' }, connectorStyle: { length: '20px' } },
|
|
gapRatio: 0.03,
|
|
neckWidth: '50%', neckHeight: '30%',
|
|
width: '100%', height: '100%'
|
|
}
|
|
],
|
|
legendSettings: { visible: false },
|
|
title: 'Lead Pipeline Funnel',
|
|
}, leadPipelineFunnelRef.value);
|
|
},
|
|
populateSalesTeamLeadClosingPie: async () => {
|
|
const response = await services.getSalesTeamLeadClosingData();
|
|
const salesTeamLeadClosingData = response?.data?.content?.data ?? [];
|
|
|
|
new ej.charts.AccumulationChart({
|
|
enableSmartLabels: true,
|
|
selectionMode: 'Point',
|
|
annotations: [{
|
|
content: '<div><strong></strong></div>',
|
|
region: "Series",
|
|
x: "52%",
|
|
y: "50%"
|
|
}],
|
|
series: [
|
|
{
|
|
dataSource: salesTeamLeadClosingData,
|
|
xName: 'x', yName: 'y', startAngle: 30,
|
|
innerRadius: '50%', radius: ej.base.Browser.isDevice ? '80%' : '85%',
|
|
dataLabel: {
|
|
visible: true, position: 'Inside',
|
|
font: { fontWeight: '600', color: '#ffffff' },
|
|
},
|
|
}
|
|
],
|
|
legendSettings: {
|
|
visible: true, toggleVisibility: false,
|
|
position: 'Bottom',
|
|
maximumColumns: ej.base.Browser.isDevice ? 2 : 3,
|
|
fixedWidth: true
|
|
},
|
|
title: 'Sales Team Achievement',
|
|
enableBorderOnMouseMove: false,
|
|
textRender: function (args) {
|
|
args.series.dataLabel.font.size = '13px';
|
|
args.text = args.text + '%';
|
|
},
|
|
pointRender: function (args) {
|
|
var selectedTheme = location.hash.split('/')[1];
|
|
selectedTheme = selectedTheme ? selectedTheme : 'Fluent2';
|
|
if (selectedTheme === 'fluent2') {
|
|
args.fill = fluent2Colors[args.point.index % 10];
|
|
}
|
|
},
|
|
}, salesTeamLeadClosingRef.value);
|
|
},
|
|
populateCampaignByStatus: async () => {
|
|
const response = await services.getCampaignByStatusData();
|
|
const campaignByStatusData = response?.data?.content?.data ?? [];
|
|
|
|
new ej.charts.AccumulationChart({
|
|
series: [{
|
|
type: 'Pie',
|
|
dataSource: campaignByStatusData,
|
|
animation: { enable: true },
|
|
xName: 'x',
|
|
yName: 'y',
|
|
innerRadius: '50%',
|
|
dataLabel: {
|
|
visible: true,
|
|
position: 'Outside',
|
|
name: 'x',
|
|
connectorStyle: { width: 0 },
|
|
},
|
|
borderRadius: 8,
|
|
border: { width: 3 }
|
|
}],
|
|
tooltip: {
|
|
enable: true,
|
|
header: '<b>Campaign Status</b>', format: '${point.x}: <b>${point.y}%</b>',
|
|
enableHighlight: true
|
|
},
|
|
title: 'Campaign By Status',
|
|
enableSmartLabels: true,
|
|
enableBorderOnMouseMove: false,
|
|
legendSettings: {
|
|
visible: false
|
|
},
|
|
annotations: [{
|
|
content: '<div><strong></strong></div>',
|
|
region: "Series",
|
|
x: "52%",
|
|
y: "50%"
|
|
}],
|
|
load: function (args) {
|
|
var selectedTheme = location.hash.split('/')[1];
|
|
selectedTheme = selectedTheme ? selectedTheme : 'Fluent2';
|
|
args.accumulation.theme = (selectedTheme.charAt(0).toUpperCase() +
|
|
selectedTheme.slice(1)).replace(/-dark/i, 'Dark').replace(/contrast/i, 'Contrast').replace(/-highContrast/i, 'HighContrast');
|
|
},
|
|
pointRender: function (args) {
|
|
var selectedTheme = location.hash.split('/')[1];
|
|
selectedTheme = selectedTheme ? selectedTheme : 'Fluent2';
|
|
if (selectedTheme.indexOf('dark') > -1) {
|
|
if (selectedTheme.indexOf('material') > -1) {
|
|
args.border.color = '#303030';
|
|
}
|
|
else if (selectedTheme.indexOf('bootstrap5') > -1) {
|
|
args.border.color = '#212529';
|
|
}
|
|
else if (selectedTheme.indexOf('bootstrap') > -1) {
|
|
args.border.color = '#1A1A1A';
|
|
|
|
}
|
|
else if (selectedTheme.indexOf('fabric') > -1) {
|
|
args.border.color = '#201f1f';
|
|
|
|
}
|
|
else if (selectedTheme.indexOf('fluent') > -1) {
|
|
args.border.color = '#252423';
|
|
|
|
}
|
|
else if (selectedTheme.indexOf('bootstrap') > -1) {
|
|
args.border.color = '#1A1A1A';
|
|
|
|
}
|
|
else if (selectedTheme.indexOf('tailwind') > -1) {
|
|
args.border.color = '#1F2937';
|
|
|
|
}
|
|
else {
|
|
args.border.color = '#222222';
|
|
|
|
}
|
|
}
|
|
else if (selectedTheme.indexOf('highcontrast') > -1) {
|
|
args.border.color = '#000000';
|
|
}
|
|
else {
|
|
args.border.color = '#FFFFFF';
|
|
}
|
|
}
|
|
}, campaignByStatusRef.value);
|
|
},
|
|
populateLeadActivityByType: async () => {
|
|
const response = await services.getLeadActivityByTypeData();
|
|
const leadActivityByTypeData = response?.data?.content?.data ?? [];
|
|
|
|
new ej.charts.AccumulationChart({
|
|
series: [{
|
|
type: 'Pyramid',
|
|
dataSource: leadActivityByTypeData,
|
|
xName: 'x', yName: 'y',
|
|
dataLabel: { name: 'text', visible: true, position: 'Inside', font: { fontWeight: '600' }, connectorStyle: { length: '20px' } },
|
|
gapRatio: 0.03,
|
|
neckWidth: '50%', neckHeight: '30%',
|
|
width: '100%', height: '100%'
|
|
}
|
|
],
|
|
legendSettings: { visible: false },
|
|
title: 'Lead Activity By Type',
|
|
}, leadActivityByTypeRef.value);
|
|
},
|
|
};
|
|
|
|
Vue.onMounted(async () => {
|
|
try {
|
|
await SecurityManager.authorizePage(['Dashboards']);
|
|
await SecurityManager.validateToken();
|
|
|
|
await methods.populateCardsData();
|
|
await methods.populateSalesData();
|
|
await methods.populatePurchaseData();
|
|
|
|
|
|
await methods.populateCRMData();
|
|
await methods.populateLeadPipelineFunnel();
|
|
await methods.populateSalesTeamLeadClosingPie();
|
|
await methods.populateCampaignByStatus();
|
|
await methods.populateLeadActivityByType();
|
|
|
|
|
|
} catch (e) {
|
|
console.error('page init error:', e);
|
|
}
|
|
});
|
|
|
|
return {
|
|
cardSalesQtyRef,
|
|
cardPurchaseQtyRef,
|
|
salesOrderGridRef,
|
|
purchaseOrderGridRef,
|
|
customerGroupChartRef,
|
|
vendorGroupChartRef,
|
|
customerCategoryChartRef,
|
|
vendorCategoryChartRef,
|
|
state,
|
|
methods,
|
|
campaignTotalAmountRef,
|
|
leadTotalAmountRef,
|
|
budgetTotalAmountRef,
|
|
expenseTotalAmountRef,
|
|
closedTotalAmountRef,
|
|
leadPipelineFunnelRef,
|
|
salesTeamLeadClosingRef,
|
|
campaignByStatusRef,
|
|
leadActivityByTypeRef,
|
|
};
|
|
}
|
|
};
|
|
|
|
Vue.createApp(App).mount('#app'); |