initial commit
This commit is contained in:
@@ -0,0 +1,218 @@
|
||||
@page
|
||||
@{
|
||||
ViewData["Title"] = "Default Dashboard";
|
||||
}
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<div class="form-card" id="formcard">
|
||||
|
||||
|
||||
|
||||
<div class="container-fluid pt-3 px-3">
|
||||
<div class="row g-3 mb-1 align-items-stretch">
|
||||
<div class="col-6">
|
||||
<div class="row g-3">
|
||||
<div class="col-6">
|
||||
<div class="card overflow-hidden" style="min-width: 12rem">
|
||||
<div class="bg-holder bg-card">
|
||||
</div>
|
||||
<div class="card-body position-relative d-flex flex-column justify-content-center text-center">
|
||||
<h6>Campaign</h6>
|
||||
<div class="display-4 fs-5 mb-2 fw-normal font-sans-serif text-warning" ref="campaignTotalAmountRef" align="center"></div>
|
||||
<a class="fw-semi-bold fs-10 text-nowrap" href="/Campaigns/CampaignList">See all<span class="fas fa-angle-right ms-1" data-fa-transform="down-1"></span></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="card overflow-hidden" style="min-width: 12rem">
|
||||
<div class="bg-holder bg-card">
|
||||
</div>
|
||||
<div class="card-body position-relative d-flex flex-column justify-content-center text-center">
|
||||
<h6>Lead</h6>
|
||||
<div class="display-4 fs-5 mb-2 fw-normal font-sans-serif text-warning" ref="leadTotalAmountRef" align="center"></div>
|
||||
<a class="fw-semi-bold fs-10 text-nowrap" href="/Leads/LeadList">See all<span class="fas fa-angle-right ms-1" data-fa-transform="down-1"></span></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-0 g-3">
|
||||
<div class="col-6">
|
||||
<div class="card overflow-hidden" style="min-width: 12rem">
|
||||
<div class="bg-holder bg-card">
|
||||
</div>
|
||||
<div class="card-body position-relative d-flex flex-column justify-content-center text-center">
|
||||
<h6>Budget</h6>
|
||||
<div class="display-4 fs-5 mb-2 fw-normal font-sans-serif text-warning" ref="budgetTotalAmountRef" align="center"></div>
|
||||
<a class="fw-semi-bold fs-10 text-nowrap" href="/Budgets/BudgetList">See all<span class="fas fa-angle-right ms-1" data-fa-transform="down-1"></span></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="card overflow-hidden" style="min-width: 12rem">
|
||||
<div class="bg-holder bg-card">
|
||||
</div>
|
||||
<div class="card-body position-relative d-flex flex-column justify-content-center text-center">
|
||||
<h6>Expense</h6>
|
||||
<div class="display-4 fs-5 mb-2 fw-normal font-sans-serif text-warning" ref="expenseTotalAmountRef" align="center"></div>
|
||||
<a class="fw-semi-bold fs-10 text-nowrap" href="/Expenses/ExpenseList">See all<span class="fas fa-angle-right ms-1" data-fa-transform="down-1"></span></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="card h-100 overflow-hidden d-flex flex-column" style="min-width: 12rem">
|
||||
<div class="bg-holder bg-card">
|
||||
</div>
|
||||
<div class="card-body position-relative d-flex flex-column justify-content-center text-center">
|
||||
<h6>Closed Won</h6>
|
||||
<div class="display-4 fs-5 mb-2 fw-normal font-sans-serif text-warning" ref="closedTotalAmountRef" align="center"></div>
|
||||
<a class="fw-semi-bold fs-10 text-nowrap" href="/Leads/LeadList">See all<span class="fas fa-angle-right ms-1" data-fa-transform="down-1"></span></a>
|
||||
<p>Lead overview</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid pt-3 px-3">
|
||||
<div class="row g-2">
|
||||
<div class="col-sm-12 col-xl-6">
|
||||
<div class="bg-white text-center rounded p-4">
|
||||
<div class="d-flex align-items-center justify-content-between mb-4">
|
||||
<h6 class="mb-0">Lead Pipeline</h6>
|
||||
<a href="/Leads/LeadList">Leads</a>
|
||||
</div>
|
||||
<div ref="leadPipelineFunnelRef" align="center"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-xl-6">
|
||||
<div class="bg-white text-center rounded p-4">
|
||||
<div class="d-flex align-items-center justify-content-between mb-4">
|
||||
<h6 class="mb-0">Lead Closing</h6>
|
||||
<a href="/Leads/LeadList">Leads</a>
|
||||
</div>
|
||||
<div ref="salesTeamLeadClosingRef" align="center"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid pt-3 px-3">
|
||||
<div class="row g-2">
|
||||
<div class="col-sm-12 col-xl-6">
|
||||
<div class="bg-white text-center rounded p-4">
|
||||
<div class="d-flex align-items-center justify-content-between mb-4">
|
||||
<h6 class="mb-0">Campaign By Status</h6>
|
||||
<a href="/Campaigns/CampaignList">Campaigns</a>
|
||||
</div>
|
||||
<div ref="campaignByStatusRef" align="center"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-xl-6">
|
||||
<div class="bg-white text-center rounded p-4">
|
||||
<div class="d-flex align-items-center justify-content-between mb-4">
|
||||
<h6 class="mb-0">Lead Activity By Type</h6>
|
||||
<a href="/LeadActivities/LeadActivityList">Lead Activities</a>
|
||||
</div>
|
||||
<div ref="leadActivityByTypeRef" align="center"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="container-fluid pt-4 px-4">
|
||||
<div class="row g-4">
|
||||
<div class="col-sm-6 col-xl-6">
|
||||
<div class="bg-white rounded d-flex align-items-center justify-content-between p-4">
|
||||
<i class="fas fa-chart-line fa-3x" style="color: #E94649;"></i>
|
||||
<div class="ms-3">
|
||||
<p class="mb-2">Sales</p>
|
||||
<h6 class="mb-0 text-end"><span ref="cardSalesQtyRef"></span> Qty.</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-xl-6">
|
||||
<div class="bg-white rounded d-flex align-items-center justify-content-between p-4">
|
||||
<i class="fas fa-shopping-cart fa-3x text-primary"></i>
|
||||
<div class="ms-3">
|
||||
<p class="mb-2">Purchase</p>
|
||||
<h6 class="mb-0 text-end"><span ref="cardPurchaseQtyRef"></span> Qty.</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-fluid pt-4 px-4">
|
||||
<div class="row g-4">
|
||||
<div class="col-sm-12 col-xl-6">
|
||||
<div class="bg-white text-center rounded p-4">
|
||||
<div class="d-flex align-items-center justify-content-between mb-4">
|
||||
<h6 class="mb-0">Customer Group</h6>
|
||||
<a href="/SalesReports/SalesReportList">Sales</a>
|
||||
</div>
|
||||
<div ref="customerGroupChartRef" align="center"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-xl-6">
|
||||
<div class="bg-white text-center rounded p-4">
|
||||
<div class="d-flex align-items-center justify-content-between mb-4">
|
||||
<h6 class="mb-0">Vendor Group</h6>
|
||||
<a href="/PurchaseReports/PurchaseReportList">Purchases</a>
|
||||
</div>
|
||||
<div ref="vendorGroupChartRef" align="center"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-fluid pt-4 px-4">
|
||||
<div class="row g-4">
|
||||
<div class="col-sm-12 col-xl-6">
|
||||
<div class="bg-white text-center rounded p-4">
|
||||
<div class="d-flex align-items-center justify-content-between mb-4">
|
||||
<h6 class="mb-0">Customer Category</h6>
|
||||
<a href="/SalesReports/SalesReportList">Sales</a>
|
||||
</div>
|
||||
<div ref="customerCategoryChartRef" align="center"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-xl-6">
|
||||
<div class="bg-white text-center rounded p-4">
|
||||
<div class="d-flex align-items-center justify-content-between mb-4">
|
||||
<h6 class="mb-0">Vendor Category</h6>
|
||||
<a href="/PurchaseReports/PurchaseReportList">Purchases</a>
|
||||
</div>
|
||||
<div ref="vendorCategoryChartRef" align="center"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-fluid pt-4 px-4">
|
||||
<div class="row g-4">
|
||||
<div class="col-sm-12 col-xl-6">
|
||||
<div class="bg-white text-center rounded p-4">
|
||||
<div class="d-flex align-items-center justify-content-between mb-4">
|
||||
<h6 class="mb-0">Latest Sales</h6>
|
||||
<a href="/SalesOrders/SalesOrderList">Sales</a>
|
||||
</div>
|
||||
<div ref="salesOrderGridRef" align="center"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-xl-6">
|
||||
<div class="bg-white text-center rounded p-4">
|
||||
<div class="d-flex align-items-center justify-content-between mb-4">
|
||||
<h6 class="mb-0">Latest Purchase</h6>
|
||||
<a href="/PurchaseOrders/PurchaseOrderList">Purchases</a>
|
||||
</div>
|
||||
<div ref="purchaseOrderGridRef" align="center"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section scripts {
|
||||
<script src="~/FrontEnd/Pages/Dashboards/DefaultDashboard.cshtml.js"></script>
|
||||
}
|
||||
@@ -0,0 +1,514 @@
|
||||
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');
|
||||
Reference in New Issue
Block a user