diff --git a/html/javascript/monthlyscript.js b/html/javascript/monthlyscript.js index a5b00f3..d9ac574 100644 --- a/html/javascript/monthlyscript.js +++ b/html/javascript/monthlyscript.js @@ -106,161 +106,203 @@ function postDataCard() { } //------------------------------------------------- KALAU MAU TAMBAH CHART DISINI!!!!! ------------------------------------------------ - -// ------------------------------------- BARCHART STATE HIGHEST SALES ------------------------------------- -// Fungsi untuk memproses data penjualan dan mendapatkan negara bagian dengan penjualan tertinggi -function processSalesData(data) { - const aggregatedData = {}; - - data.forEach(row => { - const state = row.State; - const sales = parseFloat(row.Sales.replace(/\$/g, '').replace(/,/g, '')); - if (aggregatedData[state]) { - aggregatedData[state] += sales; - } else { - aggregatedData[state] = sales; - } - }); +//------------------------------------------------- CHART TOTAL SALES DAN PROFIT ROW 1 LEFT------------------------------------------------ +// Proses dan buat diagram +fetchData(DataUrl).then(data => { + // Asumsikan data adalah array dari pesanan + let totalPenjualan = 0; + let totalProfit = 0; - // Mengubah objek aggregatedData menjadi array untuk diurutkan - const sortedDataArray = Object.entries(aggregatedData).sort((a, b) => b[1] - a[1]); + data.forEach(pesanan => { + // Hapus '$' dan ',' dari string penjualan dan profit, lalu konversi ke float + let penjualan = parseFloat(pesanan.Sales.replace(/[$,]/g, '')); + let profit = parseFloat(pesanan.Profit.replace(/[$,]/g, '')); - // Mengembalikan objek yang diurutkan - const sortedData = {}; - sortedDataArray.forEach(([state, sales]) => { - sortedData[state] = sales; + totalPenjualan += penjualan; + totalProfit += profit; }); - return sortedData; -} - -// Variabel global untuk chart -let BarChartSales = null; - -// Fungsi untuk membuat bar chart -function createBarChartSalesState(data) { - const ctx = document.getElementById("BarChartSalesPerState").getContext("2d"); - if (BarChartSales != null) { - BarChartSales.destroy(); // Hapus chart sebelumnya jika ada - } - - BarChartSales = new Chart(ctx, { - type: "bar", + // Buat diagram batang + const ctx = document.getElementById('totalChart').getContext('2d'); + const totalChart = new Chart(ctx, { + type: 'bar', data: { - labels: Object.keys(data), // Label adalah nama negara bagian - datasets: [ - { - label: "Total Sales by State", - data: Object.values(data), // Data adalah total penjualan - backgroundColor: 'rgba(255, 143, 0, 1)', - borderColor: 'rgba(255, 143, 0, 1)', - borderWidth: 1, - }, - ], + labels: ['Total Penjualan', 'Total Profit'], + datasets: [{ + label: 'Penjualan', + data: [totalPenjualan, 0], // Penjualan pada label pertama + backgroundColor: 'orange', + borderColor: 'orange', + borderWidth: 1 + }, { + label: 'Profit', + data: [0, totalProfit], // Profit pada label kedua + backgroundColor: 'black', + borderColor: 'black', + borderWidth: 1 + }] }, options: { - responsive: true, - maintainAspectRatio: false, scales: { - y: { - beginAtZero: true, - ticks: { - callback: function(value) { - return '$' + value.toLocaleString(); // Format angka menjadi dolar - } - } + x: { + stacked: true, }, + y: { + beginAtZero: true + } }, - }, + plugins: { + legend: { + display: true, + labels: { + color: 'black' + } + } + } + } }); -} +}); -// Ambil data sales dari server, proses, dan buat chart -fetchData(DataUrl) - .then(data => { - const processedData = processSalesData(data); - createBarChartSalesState(processedData); - }); +// ------------------------------------- BARCHART 10 STATE HIGHEST SALES ROW 1 RIGHT ------------------------------------- +// Fungsi untuk memproses data penjualan dan mendapatkan negara bagian dengan penjualan tertinggi +// Fetch data from the URL +fetchData(DataUrl).then(data => { + if (!data) return; -// ------------------------------------- BARCHART STATE HIGHEST PROFIT ------------------------------------- -// Fungsi untuk memproses data profit dan mendapatkan profit per negara bagian -function processProfitData(data) { - const aggregatedData = {}; + // Process data to aggregate sales by state + const stateSales = {}; - data.forEach(row => { - const state = row.State; - const profit = parseFloat(row.Profit.replace(/\$/g, '').replace(/,/g, '')); + data.forEach(order => { + const state = order.State; + const sales = parseFloat(order.Sales.replace(/[^0-9.-]+/g, "")); - if (aggregatedData[state]) { - aggregatedData[state] += profit; - } else { - aggregatedData[state] = profit; + if (!stateSales[state]) { + stateSales[state] = 0; } - }); - // Mengubah objek aggregatedData menjadi array untuk diurutkan - const sortedDataArray = Object.entries(aggregatedData).sort((a, b) => b[1] - a[1]); - - // Mengembalikan objek yang diurutkan - const sortedData = {}; - sortedDataArray.forEach(([state, profit]) => { - sortedData[state] = profit; + stateSales[state] += sales; }); - return sortedData; -} + // Convert the stateSales object into an array of [state, sales] pairs + const salesArray = Object.entries(stateSales); -// Variabel global untuk chart -let BarChartProfit = null; + // Sort the array by sales in descending order and take the top 10 states + const top10Sales = salesArray.sort((a, b) => b[1] - a[1]).slice(0, 10); -// Fungsi untuk membuat bar chart -function createBarChartProfitState(data) { - const ctx = document.getElementById("BarChartProfitPerState").getContext("2d"); - if (BarChartProfit != null) { - BarChartProfit.destroy(); // Hapus chart sebelumnya jika ada - } + // Separate the top 10 states and their sales into separate arrays + const states = top10Sales.map(item => item[0]); + const sales = top10Sales.map(item => item[1]); - BarChartProfit = new Chart(ctx, { - type: "bar", + // Create the bar chart using Chart.js + const ctx = document.getElementById('salesChart').getContext('2d'); + new Chart(ctx, { + type: 'bar', data: { - labels: Object.keys(data), // Label adalah nama negara bagian - datasets: [ - { - label: "Total Profit by State", - data: Object.values(data), // Data adalah total profit - backgroundColor: 'rgba(0, 0, 0, 1)', - borderColor: 'rgba(0, 0, 0, 1)', - borderWidth: 1, - }, - ], + labels: states, + datasets: [{ + label: 'Sales by State', + data: sales, + backgroundColor: 'orange', + borderColor: 'orange', + borderWidth: 1 + }] }, options: { - responsive: true, - maintainAspectRatio: false, scales: { y: { - beginAtZero: true, - ticks: { - callback: function(value) { - return '$' + value.toLocaleString(); // Format angka menjadi dolar - } - } - }, - }, - }, + beginAtZero: true + } + } + } + }); +}); + +//-------------------------------- TABEL SHIPMODE ---------------------------------- +let totalProfitTable = {}; // Define totalProfitTable globally +let sortedShipModes = []; +let sortDirection = 'desc'; // Initialize sort direction + +// Fungsi untuk memproses data profit berdasarkan kategori dan ship mode +function calculateTotalProfitTable(orders) { + const totalProfit = {}; + + orders.forEach(order => { + const category = order["Category"]; + const shipMode = order["Ship Mode"]; + const profit = parseFloat(order.Profit.replace(/[^0-9.-]+/g, '')); + + if (!totalProfit[shipMode]) { + totalProfit[shipMode] = { "Office Supplies": 0, "Technology": 0, "Furniture": 0 }; + } + + if (category === "Technology" || category === "Office Supplies" || category === "Furniture") { + totalProfit[shipMode][category] += profit; + } }); + + return totalProfit; } +// Fungsi untuk menampilkan data pada tabel +function displayProfitTable(totalProfitTable) { + const tableBody = document.getElementById('profitpercategory-body'); + + // Kosongkan isi tabel sebelum menambahkan data baru + tableBody.innerHTML = ''; + + // Tambahkan baris untuk setiap ship mode + sortedShipModes.forEach(shipMode => { + const row = ` + ${shipMode} + ${totalProfitTable[shipMode]["Office Supplies"].toLocaleString('en-US', { style: 'currency', currency: 'USD' })} + ${totalProfitTable[shipMode]["Technology"].toLocaleString('en-US', { style: 'currency', currency: 'USD' })} + ${totalProfitTable[shipMode]["Furniture"].toLocaleString('en-US', { style: 'currency', currency: 'USD' })} + `; + tableBody.innerHTML += row; + }); +} -// Ambil data profit dari server, proses, dan buat chart -fetchData(DataUrl) - .then(data => { - const processedData = processProfitData(data); - createBarChartProfitState(processedData); - }) +// Fungsi untuk mengurutkan data berdasarkan total profit +function sortShipModes(totalProfitTable, direction) { + const shipModes = Object.keys(totalProfitTable); + + shipModes.sort((a, b) => { + const totalProfitA = totalProfitTable[a]["Technology"] + totalProfitTable[a]["Office Supplies"] + totalProfitTable[a]["Furniture"]; + const totalProfitB = totalProfitTable[b]["Technology"] + totalProfitTable[b]["Office Supplies"] + totalProfitTable[b]["Furniture"]; + return direction === 'asc' ? totalProfitA - totalProfitB : totalProfitB - totalProfitA; + }); + + return shipModes; +} + +// Fungsi untuk mengambil data dan memperbarui tabel +function fetchDataAndRenderTable() { + fetch(DataUrl) + .then(response => response.json()) + .then(data => { + totalProfitTable = calculateTotalProfitTable(data); + sortedShipModes = sortShipModes(totalProfitTable, sortDirection); + displayProfitTable(totalProfitTable); + }) + .catch(error => console.error('Error fetching data:', error)); +} -//-------------------------------- LINE CHART MONTHLY SALES PERFORMANCE ---------------------------------- +// Inisialisasi data dan render tabel saat halaman dimuat +document.addEventListener('DOMContentLoaded', () => { + fetchDataAndRenderTable(); +}); + +// Fungsi Filter Tabel +function filterTable() { + fetchData(DataUrl).then(data => { + const filteredData = applyFilters(data); + // Use the global total Profit Table variable + totalProfitTable = calculateTotalProfitTable(filteredData); + displayProfitTable(totalProfitTable); + }); +} +//-------------------------------- LINE CHART MONTHLY SALES PERFORMANCE ROW 2 ---------------------------------- // Fungsi untuk memproses data penjualan bulanan const preprocessData = (data) => { const result = {}; @@ -344,8 +386,279 @@ fetch(DataUrl) }) .catch(error => console.error('Error fetching data:', error)); + //------------------------------------------------ Most Profitable Category ROW 3 LEFT ------------------------------------------------ +// Proses dan buat diagram +fetchData(DataUrl).then(data => { + // Objek untuk menyimpan total penjualan dan profit per kategori + const categories = {}; + + data.forEach(pesanan => { + const category = pesanan.Category; + + // Hapus '$' dan ',' dari string penjualan dan profit, lalu konversi ke float + const penjualan = parseFloat(pesanan.Sales.replace(/[$,]/g, '')); + const profit = parseFloat(pesanan.Profit.replace(/[$,]/g, '')); + + // Jika kategori belum ada, inisialisasi dengan nilai awal + if (!categories[category]) { + categories[category] = { totalPenjualan: 0, totalProfit: 0 }; + } + + // Tambahkan penjualan dan profit ke kategori + categories[category].totalPenjualan += penjualan; + categories[category].totalProfit += profit; + }); + + // Ekstraksi kategori, total penjualan dan total profit ke dalam array terpisah + const categoryLabels = Object.keys(categories); + const totalPenjualanData = categoryLabels.map(category => categories[category].totalPenjualan); + const totalProfitData = categoryLabels.map(category => categories[category].totalProfit); + + // Buat diagram batang horizontal + const ctx = document.getElementById('totalCategory').getContext('2d'); + const totalCategory = new Chart(ctx, { + type: 'bar', + data: { + labels: categoryLabels, + datasets: [ + { + label: 'Total Penjualan', + data: totalPenjualanData, + backgroundColor: 'orange', + borderColor: 'range', + borderWidth: 1 + }, + { + label: 'Total Profit', + data: totalProfitData, + backgroundColor: 'black', + borderColor: 'black', + borderWidth: 1 + } + ] + }, + options: { + indexAxis: 'y', + scales: { + x: { + beginAtZero: true + } + } + } + }); +}); + + + + +//------------------------------------------------ The most Profitable and Highest Sales ROW 3 RIGHT------------------------------------------------ +// Ambil data dari JSON +function fetchData(url) { + return fetch(url) + .then(response => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.json(); + }) + .catch(error => { + console.error('There was a problem with the fetch operation:', error); + }); +} + +// Fungsi untuk mengubah format data +function processData(data) { + const products = {}; + + // Loop melalui setiap item dalam data + data.forEach(item => { + const productName = item["Product Name"]; + const profit = parseFloat(item["Profit"].replace("$", "").replace(",", "")); + const sales = parseFloat(item["Sales"].replace("$", "").replace(",", "")); + + // Jika nama produk sudah ada dalam objek products, tambahkan profit dan sales + if (products[productName]) { + products[productName].profit += profit; + products[productName].sales += sales; + } else { // Jika tidak, buat entri baru untuk produk tersebut + products[productName] = { + profit: profit, + sales: sales + }; + } + }); + + // Mengurutkan produk berdasarkan profit tertinggi + const sortedProducts = Object.entries(products).sort((a, b) => b[1].profit - a[1].profit).slice(0, 10); + + return sortedProducts; +} + +// Membuat chart +async function createChart() { + const data = await fetchData(DataUrl); + const processedData = processData(data); + + const productNames = processedData.map(item => item[0]); + const profits = processedData.map(item => item[1].profit); + const sales = processedData.map(item => item[1].sales); + + const ctx = document.getElementById('myChart').getContext('2d'); + const myChart = new Chart(ctx, { + type: 'bar', + data: { + labels: productNames, + datasets: [{ + label: 'Profit', + data: profits, + backgroundColor: 'orange', + borderColor: 'black', + borderWidth: 1 + }, { + label: 'Sales', + data: sales, + backgroundColor: 'black', + borderColor: 'black', + borderWidth: 1 + }] + }, + options: { + scales: { + xAxes: [{ + ticks: { + display: false // Menyembunyikan label di sumbu x + } + }], + yAxes: [{ + ticks: { + beginAtZero: true + } + }] + } + } + }); +} + +// Panggil fungsi untuk membuat chart +createChart(); + +//------------------------------------------------ BARCHART SUB CATEGORY TERTINGGI SALES ROW 4 LEFT ------------------------------------------------ +// Fetch data from the URL + // Fetch data from the URL + fetchData(DataUrl).then(data => { + if (!data) return; + + // Process data to aggregate sales by sub-category + const subCategorySales = {}; + + data.forEach(order => { + const subCategory = order["Sub-Category"]; + const sales = parseFloat(order.Sales.replace(/[^0-9.-]+/g, "")); + + if (!subCategorySales[subCategory]) { + subCategorySales[subCategory] = 0; + } + + subCategorySales[subCategory] += sales; + }); + + // Convert the subCategorySales object into an array of [subCategory, sales] pairs + const salesArray = Object.entries(subCategorySales); + + // Sort the array by sales in descending order and take the top 10 sub-categories + const top10Sales = salesArray.sort((a, b) => b[1] - a[1]).slice(0, 10); + + // Separate the top 10 sub-categories and their sales into separate arrays + const subCategories = top10Sales.map(item => item[0]); + const sales = top10Sales.map(item => item[1]); + + // Create the horizontal bar chart using Chart.js + const ctx = document.getElementById('SubsalesChart').getContext('2d'); + new Chart(ctx, { + type: 'bar', + data: { + labels: subCategories, + datasets: [{ + label: 'Sales by Sub-Category', + data: sales, + backgroundColor: 'orange', + borderColor: 'orange', + borderWidth: 1 + }] + }, + options: { + indexAxis: 'y', + scales: { + x: { + beginAtZero: true + } + } + } + }); +}); + +fetch(DataUrl) + .then(response => response.json()) + .then(data => { + const processedDataLineChart = preprocessData(data); + createLineChart(processedDataLineChart); + }) + .catch(error => console.error('Error fetching data:', error)); + + +// ------------------------------------- BARCHART STATE HIGHEST PROFIT ROW 4 RIGHT------------------------------------- +// Fungsi untuk memproses data profit dan mendapatkan profit per negara bagian +// Fetch data from the URL +fetchData(DataUrl).then(data => { + if (!data) return; + + // Process data to aggregate profit by state + const stateProfit = {}; + + data.forEach(order => { + const state = order.State; + const profit = parseFloat(order.Profit.replace(/[^0-9.-]+/g, "")); + + if (!stateProfit[state]) { + stateProfit[state] = 0; + } + + stateProfit[state] += profit; + }); + + // Convert the stateProfit object into an array of [state, profit] pairs + const profitArray = Object.entries(stateProfit); + + // Sort the array by profit in descending order and take the top 10 states + const top10Profit = profitArray.sort((a, b) => b[1] - a[1]).slice(0, 10); + // Separate the top 10 states and their profit into separate arrays + const states = top10Profit.map(item => item[0]); + const profits = top10Profit.map(item => item[1]); + // Create the bar chart using Chart.js + const ctx = document.getElementById('profitChart').getContext('2d'); + new Chart(ctx, { + type: 'bar', + data: { + labels: states, + datasets: [{ + label: 'Profit by State', + data: profits, + backgroundColor: 'black', + borderColor: 'black', + borderWidth: 1 + }] + }, + options: { + scales: { + y: { + beginAtZero: true + } + } + } + }); +}); diff --git a/html/monthly.html b/html/monthly.html index 9630876..6b0db42 100644 --- a/html/monthly.html +++ b/html/monthly.html @@ -110,23 +110,16 @@

-

Sales by Category

-
+

Total Sales and Profit

+
-
-

State with the Highest Profit

-
+

State with the Higest Sales

+
-
-

Monthly Sales Performance

-
-
- -

Profit Per Category

@@ -144,17 +137,37 @@

Profit Per Category

- +
+
+

Monthly Sales Performance

+
+
+
+ +
+ +
+
+

The most Profitable and Highest Sales

+
+
+
+

The most Profitable and Highest Sales

+
+
+
+ +
-

Most Profitable Category

-
+

Top 10 Sub Category Sales

+
-
-

Top 5 Sub Category Sales

-
+

State with the Highest Profit

+
+ diff --git a/testfitur.html b/testfitur.html index 0353fd4..0acff55 100644 --- a/testfitur.html +++ b/testfitur.html @@ -1,84 +1,109 @@ - - - Choropleth Map Chart - - + + + Grafik Garis Penjualan Bulanan + - + + + + - - - + y: { + beginAtZero: true + } + }, + plugins: { + legend: { + display: true + } + } + } + }); +}).catch(error => { + console.error('Error fetching or processing data:', error); +}); + + \ No newline at end of file