Download index.html from tayy786/Project1: direct link, hf CLI and curl.
- Browser
- Download file 20.1 kB
-
https://huggingface.co/spaces/tayy786/Project1/resolve/main/index.html
- Command line
-
hf download hf://spaces/tayy786/Project1/index.html
-
curl -L -o index.html https://huggingface.co/spaces/tayy786/Project1/resolve/main/index.html
20.1 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Super Store Debug Dashboard</title> | |
| <script src="https://cdn.jsdelivr.net/npm/papaparse@5.4.3/papaparse.min.js"></script> | |
| <style> | |
| * { | |
| box-sizing: border-box; | |
| } | |
| body { | |
| margin: 0; | |
| font-family: Arial, sans-serif; | |
| background: #f1f5f9; | |
| color: #0f172a; | |
| } | |
| .container { | |
| max-width: 1400px; | |
| margin: auto; | |
| padding: 25px; | |
| } | |
| header { | |
| background: #0f172a; | |
| color: white; | |
| padding: 30px; | |
| border-radius: 15px; | |
| margin-bottom: 20px; | |
| } | |
| header h1 { | |
| margin: 0 0 10px; | |
| } | |
| header p { | |
| margin: 0; | |
| color: #cbd5e1; | |
| } | |
| .card { | |
| background: white; | |
| padding: 22px; | |
| border-radius: 12px; | |
| margin-bottom: 20px; | |
| box-shadow: 0 3px 12px rgba(0,0,0,0.08); | |
| } | |
| button { | |
| padding: 12px 20px; | |
| margin-top: 10px; | |
| border: none; | |
| border-radius: 8px; | |
| background: #2563eb; | |
| color: white; | |
| cursor: pointer; | |
| font-size: 15px; | |
| } | |
| button:hover { | |
| background: #1d4ed8; | |
| } | |
| button.secondary { | |
| background: #475569; | |
| } | |
| .success { | |
| background: #dcfce7; | |
| color: #166534; | |
| padding: 15px; | |
| border-radius: 8px; | |
| } | |
| .error { | |
| background: #fee2e2; | |
| color: #991b1b; | |
| padding: 15px; | |
| border-radius: 8px; | |
| } | |
| .warning { | |
| background: #fef3c7; | |
| color: #92400e; | |
| padding: 15px; | |
| border-radius: 8px; | |
| } | |
| .info { | |
| background: #dbeafe; | |
| color: #1e40af; | |
| padding: 15px; | |
| border-radius: 8px; | |
| } | |
| pre { | |
| background: #0f172a; | |
| color: #e2e8f0; | |
| padding: 15px; | |
| border-radius: 8px; | |
| overflow-x: auto; | |
| white-space: pre-wrap; | |
| } | |
| .columns { | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 8px; | |
| } | |
| .column { | |
| background: #e0f2fe; | |
| color: #075985; | |
| padding: 8px 12px; | |
| border-radius: 20px; | |
| font-size: 13px; | |
| } | |
| .missing { | |
| background: #fee2e2; | |
| color: #991b1b; | |
| } | |
| .question { | |
| border-left: 5px solid #2563eb; | |
| background: #f8fafc; | |
| padding: 15px; | |
| margin-bottom: 12px; | |
| border-radius: 6px; | |
| } | |
| .question.ok { | |
| border-left-color: #16a34a; | |
| } | |
| .question.fail { | |
| border-left-color: #dc2626; | |
| } | |
| .question h3 { | |
| margin-top: 0; | |
| } | |
| .answer { | |
| font-weight: bold; | |
| color: #2563eb; | |
| } | |
| table { | |
| border-collapse: collapse; | |
| width: 100%; | |
| overflow-x: auto; | |
| } | |
| th, | |
| td { | |
| padding: 10px; | |
| border: 1px solid #cbd5e1; | |
| text-align: left; | |
| white-space: nowrap; | |
| } | |
| th { | |
| background: #e2e8f0; | |
| } | |
| .table-wrapper { | |
| overflow-x: auto; | |
| } | |
| .hidden { | |
| display: none; | |
| } | |
| .kpi-grid { | |
| display: grid; | |
| grid-template-columns: repeat(4, 1fr); | |
| gap: 15px; | |
| } | |
| .kpi { | |
| background: #eff6ff; | |
| padding: 18px; | |
| border-radius: 10px; | |
| } | |
| .kpi small { | |
| color: #475569; | |
| } | |
| .kpi strong { | |
| display: block; | |
| font-size: 25px; | |
| margin-top: 8px; | |
| color: #1d4ed8; | |
| } | |
| @media(max-width:800px) { | |
| .kpi-grid { | |
| grid-template-columns: repeat(2,1fr); | |
| } | |
| } | |
| @media(max-width:500px) { | |
| .kpi-grid { | |
| grid-template-columns: 1fr; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <header> | |
| <h1>π Super Store Debug Dashboard</h1> | |
| <p> | |
| This version shows exactly what happens when your CSV is uploaded. | |
| </p> | |
| </header> | |
| <!-- UPLOAD --> | |
| <div class="card"> | |
| <h2>1οΈβ£ Upload CSV</h2> | |
| <input | |
| type="file" | |
| id="csvFile" | |
| accept=".csv" | |
| > | |
| <br> | |
| <button onclick="debugCSV()"> | |
| π Analyze CSV | |
| </button> | |
| <button | |
| class="secondary" | |
| onclick="clearDebug()" | |
| > | |
| Clear | |
| </button> | |
| </div> | |
| <!-- STATUS --> | |
| <div class="card"> | |
| <h2>2οΈβ£ System Status</h2> | |
| <div id="status"> | |
| Waiting for CSV... | |
| </div> | |
| </div> | |
| <!-- COLUMNS --> | |
| <div class="card"> | |
| <h2>3οΈβ£ Detected CSV Columns</h2> | |
| <div id="columns"> | |
| No CSV loaded. | |
| </div> | |
| </div> | |
| <!-- REQUIRED COLUMNS --> | |
| <div class="card"> | |
| <h2>4οΈβ£ Required Columns Check</h2> | |
| <div id="requiredCheck"> | |
| Not checked yet. | |
| </div> | |
| </div> | |
| <!-- DATASET INFO --> | |
| <div class="card"> | |
| <h2>5οΈβ£ Dataset Information</h2> | |
| <div class="kpi-grid"> | |
| <div class="kpi"> | |
| <small>Total Rows</small> | |
| <strong id="rowCount">0</strong> | |
| </div> | |
| <div class="kpi"> | |
| <small>Total Columns</small> | |
| <strong id="columnCount">0</strong> | |
| </div> | |
| <div class="kpi"> | |
| <small>Valid Quantity</small> | |
| <strong id="validQuantity">0</strong> | |
| </div> | |
| <div class="kpi"> | |
| <small>Valid Price</small> | |
| <strong id="validPrice">0</strong> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- CALCULATION TEST --> | |
| <div class="card"> | |
| <h2>6οΈβ£ Sales Calculation Test</h2> | |
| <p> | |
| The dashboard calculates: | |
| </p> | |
| <pre> | |
| Sales = quantiy Γ prce | |
| </pre> | |
| <div id="calculationTest"> | |
| Waiting for data... | |
| </div> | |
| </div> | |
| <!-- RAW DATA --> | |
| <div class="card"> | |
| <h2>7οΈβ£ First 5 Rows of Your CSV</h2> | |
| <div | |
| class="table-wrapper" | |
| id="rawData" | |
| > | |
| No data loaded. | |
| </div> | |
| </div> | |
| <!-- QUESTIONS --> | |
| <div class="card"> | |
| <h2>8οΈβ£ Ten Questions Debug</h2> | |
| <div id="questions"> | |
| No questions processed yet. | |
| </div> | |
| </div> | |
| <!-- ERRORS --> | |
| <div class="card"> | |
| <h2>9οΈβ£ Errors & Warnings</h2> | |
| <div id="errors"> | |
| No errors detected. | |
| </div> | |
| </div> | |
| <!-- JAVASCRIPT LOG --> | |
| <div class="card"> | |
| <h2>π JavaScript Debug Log</h2> | |
| <pre id="debugLog"> | |
| Waiting... | |
| </pre> | |
| </div> | |
| </div> | |
| <script> | |
| /* ===================================================== | |
| CONFIGURATION | |
| ===================================================== */ | |
| const REQUIRED_COLUMNS = [ | |
| "transaction_id", | |
| "customer_id", | |
| "customer_name", | |
| "customer_age", | |
| "gender", | |
| "product_id", | |
| "product_name", | |
| "product_category", | |
| "quantiy", | |
| "prce", | |
| "payment_mode", | |
| "purchase_date", | |
| "time_of_purchase", | |
| "status" | |
| ]; | |
| let debugMessages = []; | |
| let errorMessages = []; | |
| /* ===================================================== | |
| LOGGING | |
| ===================================================== */ | |
| function log(message) { | |
| const time = | |
| new Date().toLocaleTimeString(); | |
| debugMessages.push( | |
| "[" + time + "] " + message | |
| ); | |
| document.getElementById( | |
| "debugLog" | |
| ).textContent = | |
| debugMessages.join("\n"); | |
| console.log(message); | |
| } | |
| function addError(message) { | |
| errorMessages.push(message); | |
| renderErrors(); | |
| console.error(message); | |
| } | |
| function renderErrors() { | |
| const box = | |
| document.getElementById("errors"); | |
| if (errorMessages.length === 0) { | |
| box.innerHTML = | |
| '<div class="success">β No errors detected.</div>'; | |
| return; | |
| } | |
| box.innerHTML = | |
| errorMessages | |
| .map( | |
| e => | |
| `<div class="error">β ${escapeHTML(e)}</div>` | |
| ) | |
| .join(""); | |
| } | |
| /* ===================================================== | |
| ESCAPE HTML | |
| ===================================================== */ | |
| function escapeHTML(value) { | |
| return String(value) | |
| .replace(/&/g, "&") | |
| .replace(/</g, "<") | |
| .replace(/>/g, ">") | |
| .replace(/"/g, """) | |
| .replace(/'/g, "'"); | |
| } | |
| /* ===================================================== | |
| CLEAR | |
| ===================================================== */ | |
| function clearDebug() { | |
| location.reload(); | |
| } | |
| /* ===================================================== | |
| START CSV ANALYSIS | |
| ===================================================== */ | |
| function debugCSV() { | |
| debugMessages = []; | |
| errorMessages = []; | |
| renderErrors(); | |
| const file = | |
| document.getElementById( | |
| "csvFile" | |
| ).files[0]; | |
| if (!file) { | |
| addError( | |
| "No CSV file selected." | |
| ); | |
| document.getElementById( | |
| "status" | |
| ).innerHTML = | |
| '<div class="error">β Please select a CSV file.</div>'; | |
| return; | |
| } | |
| log( | |
| "Selected file: " + | |
| file.name | |
| ); | |
| log( | |
| "File size: " + | |
| file.size + | |
| " bytes" | |
| ); | |
| document.getElementById( | |
| "status" | |
| ).innerHTML = | |
| '<div class="info">β³ Reading CSV...</div>'; | |
| Papa.parse( | |
| file, | |
| { | |
| header: true, | |
| skipEmptyLines: true, | |
| dynamicTyping: false, | |
| complete: function(results) { | |
| log( | |
| "Papa Parse completed." | |
| ); | |
| log( | |
| "Rows returned: " + | |
| results.data.length | |
| ); | |
| if ( | |
| results.errors && | |
| results.errors.length > 0 | |
| ) { | |
| results.errors.forEach( | |
| error => { | |
| addError( | |
| "CSV Parser: " + | |
| JSON.stringify(error) | |
| ); | |
| } | |
| ); | |
| } | |
| try { | |
| processData( | |
| results.data, | |
| results.meta | |
| ); | |
| } | |
| catch(error) { | |
| addError( | |
| "MAIN ERROR: " + | |
| error.message | |
| ); | |
| document.getElementById( | |
| "status" | |
| ).innerHTML = | |
| `<div class="error"> | |
| β Application error:<br> | |
| ${escapeHTML(error.message)} | |
| </div>`; | |
| console.error(error); | |
| } | |
| }, | |
| error: function(error) { | |
| addError( | |
| "Papa Parse error: " + | |
| JSON.stringify(error) | |
| ); | |
| } | |
| } | |
| ); | |
| } | |
| /* ===================================================== | |
| CLEAN COLUMN NAME | |
| ===================================================== */ | |
| function cleanColumnName(name) { | |
| return String(name) | |
| .replace(/^\uFEFF/, "") | |
| .trim() | |
| .toLowerCase(); | |
| } | |
| /* ===================================================== | |
| PROCESS DATA | |
| ===================================================== */ | |
| function processData( | |
| data, | |
| meta | |
| ) { | |
| log( | |
| "Starting data processing..." | |
| ); | |
| if (!data || data.length === 0) { | |
| throw new Error( | |
| "CSV contains zero data rows." | |
| ); | |
| } | |
| /* --------------------------------------------- | |
| ORIGINAL COLUMNS | |
| --------------------------------------------- */ | |
| const originalColumns = | |
| meta.fields || Object.keys(data[0]); | |
| log( | |
| "Original columns detected: " + | |
| JSON.stringify(originalColumns) | |
| ); | |
| /* --------------------------------------------- | |
| NORMALIZE COLUMN NAMES | |
| --------------------------------------------- */ | |
| const normalizedMap = {}; | |
| originalColumns.forEach( | |
| original => { | |
| const clean = | |
| cleanColumnName( | |
| original | |
| ); | |
| normalizedMap[clean] = | |
| original; | |
| } | |
| ); | |
| const columns = | |
| Object.keys(normalizedMap); | |
| log( | |
| "Normalized columns: " + | |
| JSON.stringify(columns) | |
| ); | |
| showColumns(columns); | |
| /* --------------------------------------------- | |
| REQUIRED COLUMN CHECK | |
| --------------------------------------------- */ | |
| const missing = | |
| REQUIRED_COLUMNS.filter( | |
| required => | |
| !columns.includes(required) | |
| ); | |
| if (missing.length > 0) { | |
| log( | |
| "Missing columns detected: " + | |
| missing.join(", ") | |
| ); | |
| showRequiredCheck( | |
| missing | |
| ); | |
| throw new Error( | |
| "Required columns are missing: " + | |
| missing.join(", ") | |
| ); | |
| } | |
| showRequiredCheck([]); | |
| log( | |
| "All required columns found." | |
| ); | |
| /* --------------------------------------------- | |
| RENAME DATA | |
| --------------------------------------------- */ | |
| const cleanData = | |
| data.map( | |
| originalRow => { | |
| const row = {}; | |
| Object.keys( | |
| normalizedMap | |
| ).forEach( | |
| cleanName => { | |
| const originalName = | |
| normalizedMap[ | |
| cleanName | |
| ]; | |
| row[cleanName] = | |
| originalRow[ | |
| originalName | |
| ]; | |
| } | |
| ); | |
| return row; | |
| } | |
| ); | |
| log( | |
| "Data normalization complete." | |
| ); | |
| /* --------------------------------------------- | |
| ROW COUNT | |
| --------------------------------------------- */ | |
| document.getElementById( | |
| "rowCount" | |
| ).innerText = | |
| cleanData.length.toLocaleString(); | |
| document.getElementById( | |
| "columnCount" | |
| ).innerText = | |
| columns.length.toLocaleString(); | |
| /* --------------------------------------------- | |
| NUMERIC TEST | |
| --------------------------------------------- */ | |
| let validQuantity = 0; | |
| let validPrice = 0; | |
| cleanData.forEach( | |
| row => { | |
| const quantity = | |
| parseNumber( | |
| row.quantiy | |
| ); | |
| const price = | |
| parseNumber( | |
| row.prce | |
| ); | |
| if ( | |
| !isNaN(quantity) && | |
| quantity !== 0 | |
| ) { | |
| validQuantity++; | |
| } | |
| if ( | |
| !isNaN(price) && | |
| price !== 0 | |
| ) { | |
| validPrice++; | |
| } | |
| row.quantityValue = | |
| quantity; | |
| row.priceValue = | |
| price; | |
| row.salesAmount = | |
| quantity * price; | |
| } | |
| ); | |
| document.getElementById( | |
| "validQuantity" | |
| ).innerText = | |
| validQuantity.toLocaleString(); | |
| document.getElementById( | |
| "validPrice" | |
| ).innerText = | |
| validPrice.toLocaleString(); | |
| log( | |
| "Valid quantity values: " + | |
| validQuantity | |
| ); | |
| log( | |
| "Valid price values: " + | |
| validPrice | |
| ); | |
| /* --------------------------------------------- | |
| CALCULATION TEST | |
| --------------------------------------------- */ | |
| calculationTest( | |
| cleanData | |
| ); | |
| /* --------------------------------------------- | |
| RAW DATA | |
| --------------------------------------------- */ | |
| showRawData( | |
| cleanData | |
| ); | |
| /* --------------------------------------------- | |
| QUESTIONS | |
| --------------------------------------------- */ | |
| answerQuestions( | |
| cleanData | |
| ); | |
| document.getElementById( | |
| "status" | |
| ).innerHTML = | |
| `<div class="success"> | |
| β CSV successfully processed.<br> | |
| ${cleanData.length.toLocaleString()} | |
| rows detected. | |
| </div>`; | |
| log( | |
| "Processing completed successfully." | |
| ); | |
| } | |
| /* ===================================================== | |
| PARSE NUMBER | |
| ===================================================== */ | |
| function parseNumber(value) { | |
| if ( | |
| value === undefined || | |
| value === null || | |
| String(value).trim() === "" | |
| ) { | |
| return NaN; | |
| } | |
| const cleaned = | |
| String(value) | |
| .replace(/[$,\s]/g, "") | |
| .trim(); | |
| return Number( | |
| cleaned | |
| ); | |
| } | |
| /* ===================================================== | |
| SHOW COLUMNS | |
| ===================================================== */ | |
| function showColumns( | |
| columns | |
| ) { | |
| const container = | |
| document.getElementById( | |
| "columns" | |
| ); | |
| container.innerHTML = | |
| columns | |
| .map( | |
| column => | |
| `<span class="column"> | |
| ${escapeHTML(column)} | |
| </span>` | |
| ) | |
| .join(""); | |
| } | |
| /* ===================================================== | |
| REQUIRED COLUMN CHECK | |
| ===================================================== */ | |
| function showRequiredCheck( | |
| missing | |
| ) { | |
| const box = | |
| document.getElementById( | |
| "requiredCheck" | |
| ); | |
| if ( | |
| missing.length === 0 | |
| ) { | |
| box.innerHTML = | |
| `<div class="success"> | |
| β All ${REQUIRED_COLUMNS.length} | |
| required columns are present. | |
| </div>`; | |
| return; | |
| } | |
| box.innerHTML = | |
| `<div class="error"> | |
| β Missing columns: | |
| <br><br> | |
| <strong> | |
| ${missing.join(", ")} | |
| </strong> | |
| </div>`; | |
| } | |
| /* ===================================================== | |
| CALCULATION TEST | |
| ===================================================== */ | |
| function calculationTest( | |
| data | |
| ) { | |
| const box = | |
| document.getElementById( | |
| "calculationTest" | |
| ); | |
| if ( | |
| data.length === 0 | |
| ) { | |
| box.innerHTML = | |
| '<div class="error">No rows.</div>'; | |
| return; | |
| } | |
| const first = | |
| data[0]; | |
| const quantity = | |
| first.quantityValue; | |
| const price = | |
| first.priceValue; | |
| const sales = | |
| first.salesAmount; | |
| log( | |
| "First quantity = " + | |
| quantity | |
| ); | |
| log( | |
| "First price = " + | |
| price | |
| ); | |
| log( | |
| "First calculated sales = " + | |
| sales | |
| ); | |
| if ( | |
| isNaN(quantity) || | |
| isNaN(price) | |
| ) { | |
| box.innerHTML = | |
| `<div class="error"> | |
| β Numeric conversion failed. | |
| <br><br> | |
| Raw quantity: | |
| <strong> | |
| ${escapeHTML(first.quantiy)} | |
| </strong> | |
| <br> | |
| Raw price: | |
| <strong> | |
| ${escapeHTML(first.prce)} | |
| </strong> | |
| </div>`; | |
| addError( | |
| "quantiy or prce could not be converted into numbers." | |
| ); | |
| return; | |
| } | |
| box.innerHTML = | |
| `<div class="success"> | |
| β Calculation works. | |
| <br><br> | |
| Quantity: | |
| <strong>${quantity}</strong> | |
| Γ | |
| Price: | |
| <strong>${price}</strong> | |
| = | |
| Sales: | |
| <strong>${sales.toFixed(2)}</strong> | |
| </div>`; | |
| } | |
| /* ===================================================== | |
| RAW DATA TABLE | |
| ===================================================== */ | |
| function showRawData( | |
| data | |
| ) { | |
| const box = | |
| document.getElementById( | |
| "rawData" | |
| ); | |
| const columns = [ | |
| "transaction_id", | |
| "customer_id", | |
| "customer_name", | |
| "product_name", | |
| "product_category", | |
| "quantiy", | |
| "prce", | |
| "payment_mode", | |
| "purchase_date", | |
| "status" | |
| ]; | |
| let html = | |
| "<table><thead><tr>"; | |
| columns.forEach( | |
| column => { | |
| html += | |
| `<th>${column}</th>`; | |
| } | |
| ); | |
| html += | |
| "</tr></thead><tbody>"; | |
| data.slice(0,5).forEach( | |
| row => { | |
| html += "<tr>"; | |
| columns.forEach( | |
| column => { | |
| html += | |
| `<td> | |
| ${escapeHTML( | |
| row[column] ?? "" | |
| )} | |
| </td>`; | |
| } | |
| ); | |
| html += "</tr>"; | |
| } | |
| ); | |
| html += | |
| "</tbody></table>"; | |
| box.innerHTML = | |
| html; | |
| } | |
| /* ===================================================== | |
| GROUP SALES | |
| ===================================================== */ | |
| function groupSales( | |
| data, | |
| column | |
| ) { | |
| const result = {}; | |
| data.forEach( | |
| row => { | |
| let key = | |
| ro |