diff --git a/html/assets/Rectangle 205.png b/assets/Rectangle 205.png similarity index 100% rename from html/assets/Rectangle 205.png rename to assets/Rectangle 205.png diff --git a/html/assets/logo-header-resized-120px.png b/assets/logo-header-resized-120px.png similarity index 100% rename from html/assets/logo-header-resized-120px.png rename to assets/logo-header-resized-120px.png diff --git a/html/assets/logo-header-resized-180px.png b/assets/logo-header-resized-180px.png similarity index 100% rename from html/assets/logo-header-resized-180px.png rename to assets/logo-header-resized-180px.png diff --git a/html/assets/logo-header-resized-70px.png b/assets/logo-header-resized-70px.png similarity index 100% rename from html/assets/logo-header-resized-70px.png rename to assets/logo-header-resized-70px.png diff --git a/html/assets/logo.png b/assets/logo.png similarity index 100% rename from html/assets/logo.png rename to assets/logo.png diff --git a/html/css/style.css b/css/style.css similarity index 74% rename from html/css/style.css rename to css/style.css index 5397e51..f748e0e 100644 --- a/html/css/style.css +++ b/css/style.css @@ -2,13 +2,16 @@ h1, h2, h3, h4, h5, h6 { font-family: 'Roboto', sans-serif; font-size: 26px; } + .judul{ font-size: 18px !important; } + b{ font-family: 'Roboto', sans-serif; font-size: 17px; } + body{ font-family: 'Roboto', sans-serif; font-size: 12; @@ -21,7 +24,18 @@ body{ padding-top: 1%; margin-bottom: -2%; } +.footer { + background: #f3f3f3; + bottom: 0; + background-color: #222; + color: #fff; + text-align: center; + } +.footer-bottom { + background-color: #222; + padding: 5px 0; +} /*========================================================= HEADER ========================================*/ .image-responsive{ width: 100%; @@ -30,18 +44,9 @@ body{ .topnav-container { background-color: white; overflow: hidden; - } -.navbar-nav .nav-link:hover { - background-color: transparent !important; - color: inherit !important; - pointer-events: none; -} - -.nav-text-disabled .nav-link_judul:hover { - color: black !important; -} + /* Style the links inside the navigation bar */ .topnav-a { @@ -132,7 +137,7 @@ body{ width: 100%; height: auto; text-align: center; - padding: 10px 30px; + padding: 15px 30px; text-decoration: none; font-size: 12px; background-color: rgb(230, 230, 230); @@ -245,8 +250,9 @@ select::-ms-expand { /*========================================================= SLIDER ========================================*/ .skorcard{ position: flex; - width: 100%; + width: 97.8%; left: 0; + align-content: center; } .cards{ width: 100%; @@ -283,6 +289,7 @@ select::-ms-expand { /*========================================================= ========================================*/ .chartContainer{ display: flex; + flex-direction: row; flex: 1; } .left { @@ -309,8 +316,13 @@ canvas { .line-chart{ width: 100%; + margin-bottom: 20px; margin-left: 20px; } +.lineCustom{ + width: 100%; + height: 100%; +} h2 { margin-top: 20px; @@ -359,15 +371,117 @@ th { width: 100% !important; /* Ensure the table takes full width of the modal */ } + /* ----------------------------------Modal styles --------------------------------*/ + body.modal-open { + overflow: hidden; + } + .modal { + display: none; + position: fixed; + z-index: 1; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow: auto; + background-color: rgba(0,0,0,0.5); + } + .modal-dialog { + margin: 2% auto; + padding: 25px; + width: 95%; + background-color: white; + border-radius: 5px; + box-shadow: 0 5px 15px rgba(0,0,0,0.3); + } + .modal-header, .modal-footer { + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 1px solid #e5e5e5; + } + .modal-header { + border-bottom: none; + } + .modal-body { + padding: 5px; + } + .close { + font-size: 1.5rem; + cursor: pointer; + background: none; + border: none; + } + .btn-secondary { + padding: 10px 20px; + background-color: #6c757d; + color: white; + border: none; + cursor: pointer; + border-radius: 5px; + } + @media screen and (max-width: 768px) { /* Ketika lebar layar kurang dari atau sama dengan 768px */ + h1, h2, h3, h4, h5, h6 { + font-family: 'Roboto', sans-serif; + font-size: 20px; + } + .judul{ + font-size: 16px !important; + } + b{ + font-family: 'Roboto', sans-serif; + font-size: 15px; + } + body{ + font-family: 'Roboto', sans-serif; + font-size: 10; + } + .header-cust { + text-align: center; + } + .header-container { + display:flex; + flex-direction: column; + overflow: hidden; + margin-bottom: 2em; + } + .topnav-special { + float: left; + color: black; + text-align: left; + text-decoration: none; + font-size: 17px; + } + .chartContainer{ + display: flex; + flex-direction: column; + overflow: hidden; + flex: 1; + flex-wrap: wrap; + } + .BarChartSalesCategoryCustom{ + height: 50px; + } .cards { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); /* Menyesuaikan jumlah kolom dan lebar kartu */ grid-gap: 10px; /* Mengurangi jarak antara kartu */ + padding: 10px; + } + .skorcard { + width: 95%; } - .topnav-logo { display: none; } + .footer-container { + flex-direction: column; + align-items: center; + } + + .footer-left, .footer-center, .footer-right { + margin: 20px 0; + } } diff --git a/html/javascript/monthlyscript.js b/html/javascript/monthlyscript.js deleted file mode 100644 index 3b084f7..0000000 --- a/html/javascript/monthlyscript.js +++ /dev/null @@ -1,194 +0,0 @@ - //------------------------------ GENERAL FUNCTION ---------------------------------- - const DataUrl = 'http://localhost:3000/data'; - - // 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); - }); - } - - -//------------------------------ SCORE CARD FUNCTION ---------------------------------- -function isiDropdownFilter(selectElement, items) { - if (Array.isArray(items)) { - items.forEach(function(item) { - const option = document.createElement('option'); - option.value = item; - option.textContent = item; - selectElement.appendChild(option); - }); - } else { - console.error('Expected an array but got:', items); - } -} - -// Populasi dropdowns dengan nilai unik dari data -function populateDropdowns(data) { - const states = [...new Set(data.map(row => row.State))]; - const categories = [...new Set(data.map(row => row.Category))]; - const segments = [...new Set(data.map(row => row.Segment))]; - - isiDropdownFilter(document.getElementById('stateSelect'), states); - isiDropdownFilter(document.getElementById('categorySelect'), categories); - isiDropdownFilter(document.getElementById('segmentSelect'), segments); -} - -// Ambil value Filter -function applyFilters(data) { - const selectedState = document.getElementById('stateSelect').value; - const selectedCategory = document.getElementById('categorySelect').value; - const selectedSegment = document.getElementById('segmentSelect').value; - - return data.filter(row => { - return (!selectedState || row.State === selectedState) && - (!selectedCategory || row.Category === selectedCategory) && - (!selectedSegment || row.Segment === selectedSegment); - }); -} - -// Hitung Total Sales -function calculateTotalSales(data) { - let totalSales = 0; - data.forEach(row => { - const sales = parseFloat(row.Sales.replace(/\$/g, '').replace(/,/g, '')); - totalSales += sales; - }); - return totalSales; -} - -// Hitung Total Profit -function calculateTotalProfit(data) { - let totalProfit = 0; - data.forEach(row => { - const profit = parseFloat(row.Profit.replace(/\$/g, '').replace(/,/g, '')); - totalProfit += profit; - }); - return totalProfit; -} - -// Hitung Total Orders -function calculateTotalOrders(data) { - return data.length; -} - -// Post To Card -function postDataCard() { - fetchData(DataUrl).then(data => { - const filteredData = applyFilters(data); - - const totalOrder = calculateTotalOrders(filteredData); - const formattedTotalOrder = totalOrder.toLocaleString('en-US'); - document.getElementById('cardOrder').innerText = `${formattedTotalOrder}`; - - // Total Sales - const totalSales = calculateTotalSales(filteredData); - const formattedTotalSales = totalSales.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); - document.getElementById('cardSales').innerText = `$ ${formattedTotalSales}`; - - // Total Profit - const totalProfit = calculateTotalProfit(filteredData); - const formattedTotalProfit = totalProfit.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); - document.getElementById('cardProfit').innerText = `$ ${formattedTotalProfit}`; - - // Profit Ratio - const profitRatio = (totalProfit / totalSales) * 100; - const formattedTotalProfitRatio = Math.round(profitRatio).toLocaleString('en-US'); - document.getElementById('cardProfitRatio').innerText = `${formattedTotalProfitRatio} %`; - }); -} - -//------------------------------------------------- KALAU MAU TAMBAH CHART DISINI!!!!! ------------------------------------------------ - -// Fungsi untuk memproses data penjualan per negara bagian -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; - } - }); - - return aggregatedData; -} - -// Variabel global untuk chart -let BarChart = null; - -// Fungsi untuk membuat bar chart -function createBarChartSalesState(data) { - const ctx = document.getElementById("BarChartSalesPerState").getContext("2d"); - if (BarChart != null) { - BarChart.destroy(); // Hapus chart sebelumnya jika ada - } - - BarChart = 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(75, 192, 192, 0.2)', - borderColor: 'rgba(75, 192, 192, 1)', - borderWidth: 1, - }, - ], - }, - options: { - responsive: true, - maintainAspectRatio: false, - scales: { - y: { - beginAtZero: true, - ticks: { - callback: function(value) { - return '$' + value.toLocaleString(); // Format angka menjadi dolar - } - } - }, - }, - }, - }); -} - -// Ambil data penjualan dari server, proses, dan buat chart -fetchData(DataUrl) - .then(data => { - const processedData = processSalesData(data); - createBarChartSalesState(processedData); - }); - - - - - - - - -//------------------------------------^^^^^^^ KALAU MAU TAMBAH CHART DISINI (INI BATASNYA)!!!!! ^^^^^----------------------------------------- -//------------------------------------------------ EVENT LISTENER ------------------------------------------------ -// Tambah event listeners ke dropdowns -document.getElementById('stateSelect').addEventListener('change', postDataCard); -document.getElementById('categorySelect').addEventListener('change', postDataCard); -document.getElementById('segmentSelect').addEventListener('change', postDataCard); - -// Fetch data, populate dropdowns, dan lakukan kalkulasi awal -fetchData(DataUrl).then(data => { - populateDropdowns(data); - postDataCard(); -}); \ No newline at end of file diff --git a/html/monthly.html b/html/monthly.html deleted file mode 100644 index fd368a5..0000000 --- a/html/monthly.html +++ /dev/null @@ -1,239 +0,0 @@ - - - - - Document - - - - - - - - - - -
-
- - - - -
- -
- -
- -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
-
- - -
-
-
-
-
Total Order
-
-
-
-
-
-
Sales
-
-
-
-
-
-
Profit
-
-
-
-
-
-
Profit Ratio
-
-
-
-
-
- - -
-
-

Sales by Category

-
-
- -
-

Dummy

-
-
-
- - -
-

YoY Sales Performance

-
-
-
- - - - -
-

YoY Sales Performance

-
+
+
+

YoY Sales Performance

+
+
+
@@ -161,58 +147,62 @@

Top 5 Product Sold based on Quantity Sales

- - -