Spaces:
Sleeping
Sleeping
Aryanshh commited on
Commit ·
fbf9261
1
Parent(s): c547cb1
style: Clean enterprise look and dynamic quantity estimator
Browse files- dashboard/app.js +8 -4
- dashboard/index.html +13 -12
- dashboard/style.css +14 -4
dashboard/app.js
CHANGED
|
@@ -111,18 +111,21 @@ async function updateState() {
|
|
| 111 |
|
| 112 |
// UI Controls
|
| 113 |
const modeSelect = document.getElementById('mode-select');
|
|
|
|
| 114 |
|
| 115 |
function updatePreview() {
|
| 116 |
const mode = modeSelect.value;
|
| 117 |
const s = SPECS[mode];
|
| 118 |
-
const
|
| 119 |
-
const
|
|
|
|
| 120 |
|
| 121 |
document.getElementById('preview-cost').textContent = `$${cost.toFixed(0)}`;
|
| 122 |
document.getElementById('preview-carbon').textContent = `+${carbon.toFixed(1)}kg CO2`;
|
| 123 |
}
|
| 124 |
|
| 125 |
modeSelect.addEventListener('change', updatePreview);
|
|
|
|
| 126 |
|
| 127 |
function spawnFeedback(text, x, y) {
|
| 128 |
const el = document.createElement('div');
|
|
@@ -149,10 +152,11 @@ window.execute = async function(type, event, shipment_id = null) {
|
|
| 149 |
let actionObj = { action_type: type };
|
| 150 |
if (type === 'order_parts') {
|
| 151 |
const part = document.getElementById('part-select').value;
|
| 152 |
-
|
|
|
|
| 153 |
actionObj.part_type = part;
|
| 154 |
actionObj.mode = document.getElementById('mode-select').value;
|
| 155 |
-
actionObj.quantity =
|
| 156 |
} else if (type === 'produce') {
|
| 157 |
actionObj.product = document.getElementById('product-select').value;
|
| 158 |
} else if (type === 'offset') {
|
|
|
|
| 111 |
|
| 112 |
// UI Controls
|
| 113 |
const modeSelect = document.getElementById('mode-select');
|
| 114 |
+
const qtyInput = document.getElementById('qty-input');
|
| 115 |
|
| 116 |
function updatePreview() {
|
| 117 |
const mode = modeSelect.value;
|
| 118 |
const s = SPECS[mode];
|
| 119 |
+
const qty = parseInt(qtyInput.value) || 1;
|
| 120 |
+
const cost = 10 * qty * s.cost;
|
| 121 |
+
const carbon = qty * s.carbon;
|
| 122 |
|
| 123 |
document.getElementById('preview-cost').textContent = `$${cost.toFixed(0)}`;
|
| 124 |
document.getElementById('preview-carbon').textContent = `+${carbon.toFixed(1)}kg CO2`;
|
| 125 |
}
|
| 126 |
|
| 127 |
modeSelect.addEventListener('change', updatePreview);
|
| 128 |
+
qtyInput.addEventListener('input', updatePreview);
|
| 129 |
|
| 130 |
function spawnFeedback(text, x, y) {
|
| 131 |
const el = document.createElement('div');
|
|
|
|
| 152 |
let actionObj = { action_type: type };
|
| 153 |
if (type === 'order_parts') {
|
| 154 |
const part = document.getElementById('part-select').value;
|
| 155 |
+
const qty = parseInt(document.getElementById('qty-input').value) || 1;
|
| 156 |
+
spawnFeedback(`+${qty} ${part} ordered`, event.clientX, event.clientY);
|
| 157 |
actionObj.part_type = part;
|
| 158 |
actionObj.mode = document.getElementById('mode-select').value;
|
| 159 |
+
actionObj.quantity = qty;
|
| 160 |
} else if (type === 'produce') {
|
| 161 |
actionObj.product = document.getElementById('product-select').value;
|
| 162 |
} else if (type === 'offset') {
|
dashboard/index.html
CHANGED
|
@@ -11,8 +11,8 @@
|
|
| 11 |
<div class="container">
|
| 12 |
<header>
|
| 13 |
<div class="logo">
|
| 14 |
-
<span class="icon">
|
| 15 |
-
<h1>
|
| 16 |
<button id="info-btn" class="help-circle">?</button>
|
| 17 |
</div>
|
| 18 |
<div id="connection-status" class="status-badge">Connecting...</div>
|
|
@@ -35,18 +35,19 @@
|
|
| 35 |
<main>
|
| 36 |
<div class="main-grid">
|
| 37 |
<section class="control-panel card">
|
| 38 |
-
<h3>
|
| 39 |
|
| 40 |
<div class="operation-sections">
|
| 41 |
<!-- Section 1: Logistics -->
|
| 42 |
<div id="section-order" class="op-section">
|
| 43 |
-
<h4>
|
| 44 |
<div class="op-row">
|
| 45 |
<div class="op-inputs">
|
| 46 |
<select id="part-select">
|
| 47 |
<option value="chips">Order Microchips</option>
|
| 48 |
<option value="sensors">Order Sensors</option>
|
| 49 |
</select>
|
|
|
|
| 50 |
<select id="mode-select">
|
| 51 |
<option value="sea">SEA ($50, 10d, 0.5kg)</option>
|
| 52 |
<option value="rail">RAIL ($125, 5d, 2.5kg)</option>
|
|
@@ -63,7 +64,7 @@
|
|
| 63 |
|
| 64 |
<!-- Section 2: Manufacturing -->
|
| 65 |
<div id="section-produce" class="op-section">
|
| 66 |
-
<h4>
|
| 67 |
<div class="op-row">
|
| 68 |
<div class="op-inputs">
|
| 69 |
<select id="product-select">
|
|
@@ -81,7 +82,7 @@
|
|
| 81 |
|
| 82 |
<!-- Section 3: ESG / Offsetting -->
|
| 83 |
<div id="section-offset" class="op-section">
|
| 84 |
-
<h4>
|
| 85 |
<div class="op-row">
|
| 86 |
<div class="op-inputs">
|
| 87 |
<span class="op-text">Carbon Offset Purchase (100 units)</span>
|
|
@@ -106,7 +107,7 @@
|
|
| 106 |
<button id="reset-btn" class="btn btn-outline">Reset Sim</button>
|
| 107 |
</div>
|
| 108 |
<div id="news-alert" class="news-alert hidden">
|
| 109 |
-
<span class="warning-icon">
|
| 110 |
<div class="news-content">
|
| 111 |
<div class="news-label">EMERGENCY ALERT</div>
|
| 112 |
<div id="news-text"></div>
|
|
@@ -116,7 +117,7 @@
|
|
| 116 |
|
| 117 |
<section class="shipment-cart-section">
|
| 118 |
<div class="card full-width h-100">
|
| 119 |
-
<h3>
|
| 120 |
<div id="cart-container" class="cart-list">
|
| 121 |
<p class="placeholder">No active shipments in transit.</p>
|
| 122 |
</div>
|
|
@@ -176,15 +177,15 @@
|
|
| 176 |
|
| 177 |
<section class="guide-section">
|
| 178 |
<div class="card full-width mission-card">
|
| 179 |
-
<h3>
|
| 180 |
<div class="guide-content">
|
| 181 |
<div class="guide-grid">
|
| 182 |
<div class="guide-item">
|
| 183 |
-
<h4>
|
| 184 |
<p>Fulfill "EcoPhone" and "GreenTab" orders by managing a global supply chain. You must keep <strong>Carbon Footprint</strong> below the quota while maximizing <strong>Capital Balance</strong>.</p>
|
| 185 |
</div>
|
| 186 |
<div class="guide-item">
|
| 187 |
-
<h4>
|
| 188 |
<ul class="guide-list">
|
| 189 |
<li><strong>SEA:</strong> Cheapest ($50), cleanest (0.5kg CO2), but very slow (10 days).</li>
|
| 190 |
<li><strong>RAIL:</strong> Balanced cost ($125), low CO2 (2.5kg), medium speed (5 days).</li>
|
|
@@ -192,7 +193,7 @@
|
|
| 192 |
</ul>
|
| 193 |
</div>
|
| 194 |
<div class="guide-item">
|
| 195 |
-
<h4>
|
| 196 |
<p>Clicking <strong>Trigger Suez Jam</strong> simulates a real-world blockade. Sea routes become unavailable for 7 days, forcing you to pivot to expensive Rail/Air routes to meet your deadlines.</p>
|
| 197 |
</div>
|
| 198 |
</div>
|
|
|
|
| 11 |
<div class="container">
|
| 12 |
<header>
|
| 13 |
<div class="logo">
|
| 14 |
+
<span class="icon">NETZERO</span>
|
| 15 |
+
<h1>NAV</h1>
|
| 16 |
<button id="info-btn" class="help-circle">?</button>
|
| 17 |
</div>
|
| 18 |
<div id="connection-status" class="status-badge">Connecting...</div>
|
|
|
|
| 35 |
<main>
|
| 36 |
<div class="main-grid">
|
| 37 |
<section class="control-panel card">
|
| 38 |
+
<h3>Command Console</h3>
|
| 39 |
|
| 40 |
<div class="operation-sections">
|
| 41 |
<!-- Section 1: Logistics -->
|
| 42 |
<div id="section-order" class="op-section">
|
| 43 |
+
<h4>Supply Logistics</h4>
|
| 44 |
<div class="op-row">
|
| 45 |
<div class="op-inputs">
|
| 46 |
<select id="part-select">
|
| 47 |
<option value="chips">Order Microchips</option>
|
| 48 |
<option value="sensors">Order Sensors</option>
|
| 49 |
</select>
|
| 50 |
+
<input type="number" id="qty-input" value="1" min="1" max="100" class="qty-select" onchange="updatePreview()">
|
| 51 |
<select id="mode-select">
|
| 52 |
<option value="sea">SEA ($50, 10d, 0.5kg)</option>
|
| 53 |
<option value="rail">RAIL ($125, 5d, 2.5kg)</option>
|
|
|
|
| 64 |
|
| 65 |
<!-- Section 2: Manufacturing -->
|
| 66 |
<div id="section-produce" class="op-section">
|
| 67 |
+
<h4>Manufacturing</h4>
|
| 68 |
<div class="op-row">
|
| 69 |
<div class="op-inputs">
|
| 70 |
<select id="product-select">
|
|
|
|
| 82 |
|
| 83 |
<!-- Section 3: ESG / Offsetting -->
|
| 84 |
<div id="section-offset" class="op-section">
|
| 85 |
+
<h4>ESG Strategy</h4>
|
| 86 |
<div class="op-row">
|
| 87 |
<div class="op-inputs">
|
| 88 |
<span class="op-text">Carbon Offset Purchase (100 units)</span>
|
|
|
|
| 107 |
<button id="reset-btn" class="btn btn-outline">Reset Sim</button>
|
| 108 |
</div>
|
| 109 |
<div id="news-alert" class="news-alert hidden">
|
| 110 |
+
<span class="warning-icon"></span>
|
| 111 |
<div class="news-content">
|
| 112 |
<div class="news-label">EMERGENCY ALERT</div>
|
| 113 |
<div id="news-text"></div>
|
|
|
|
| 117 |
|
| 118 |
<section class="shipment-cart-section">
|
| 119 |
<div class="card full-width h-100">
|
| 120 |
+
<h3>Your Orders</h3>
|
| 121 |
<div id="cart-container" class="cart-list">
|
| 122 |
<p class="placeholder">No active shipments in transit.</p>
|
| 123 |
</div>
|
|
|
|
| 177 |
|
| 178 |
<section class="guide-section">
|
| 179 |
<div class="card full-width mission-card">
|
| 180 |
+
<h3>Mission Briefing (Operator's Manual)</h3>
|
| 181 |
<div class="guide-content">
|
| 182 |
<div class="guide-grid">
|
| 183 |
<div class="guide-item">
|
| 184 |
+
<h4>Objective</h4>
|
| 185 |
<p>Fulfill "EcoPhone" and "GreenTab" orders by managing a global supply chain. You must keep <strong>Carbon Footprint</strong> below the quota while maximizing <strong>Capital Balance</strong>.</p>
|
| 186 |
</div>
|
| 187 |
<div class="guide-item">
|
| 188 |
+
<h4>Logistics Trade-offs</h4>
|
| 189 |
<ul class="guide-list">
|
| 190 |
<li><strong>SEA:</strong> Cheapest ($50), cleanest (0.5kg CO2), but very slow (10 days).</li>
|
| 191 |
<li><strong>RAIL:</strong> Balanced cost ($125), low CO2 (2.5kg), medium speed (5 days).</li>
|
|
|
|
| 193 |
</ul>
|
| 194 |
</div>
|
| 195 |
<div class="guide-item">
|
| 196 |
+
<h4>Crisis Handling</h4>
|
| 197 |
<p>Clicking <strong>Trigger Suez Jam</strong> simulates a real-world blockade. Sea routes become unavailable for 7 days, forcing you to pivot to expensive Rail/Air routes to meet your deadlines.</p>
|
| 198 |
</div>
|
| 199 |
</div>
|
dashboard/style.css
CHANGED
|
@@ -273,7 +273,7 @@ header {
|
|
| 273 |
font-size: 0.85rem;
|
| 274 |
}
|
| 275 |
|
| 276 |
-
select {
|
| 277 |
padding: 0.7rem 1rem;
|
| 278 |
border-radius: 10px;
|
| 279 |
border: 1.5px solid var(--border-tan);
|
|
@@ -283,17 +283,27 @@ select {
|
|
| 283 |
color: var(--text-main);
|
| 284 |
cursor: pointer;
|
| 285 |
transition: all 0.2s ease;
|
| 286 |
-
min-width: 220px;
|
| 287 |
outline: none;
|
| 288 |
box-shadow: 0 2px 5px rgba(0,0,0,0.03);
|
| 289 |
}
|
| 290 |
|
| 291 |
-
select
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 292 |
border-color: var(--sage-green);
|
| 293 |
box-shadow: 0 4px 10px rgba(0,0,0,0.05);
|
| 294 |
}
|
| 295 |
|
| 296 |
-
select:focus {
|
| 297 |
border-color: var(--primary-green);
|
| 298 |
}
|
| 299 |
|
|
|
|
| 273 |
font-size: 0.85rem;
|
| 274 |
}
|
| 275 |
|
| 276 |
+
select, .qty-select {
|
| 277 |
padding: 0.7rem 1rem;
|
| 278 |
border-radius: 10px;
|
| 279 |
border: 1.5px solid var(--border-tan);
|
|
|
|
| 283 |
color: var(--text-main);
|
| 284 |
cursor: pointer;
|
| 285 |
transition: all 0.2s ease;
|
|
|
|
| 286 |
outline: none;
|
| 287 |
box-shadow: 0 2px 5px rgba(0,0,0,0.03);
|
| 288 |
}
|
| 289 |
|
| 290 |
+
select {
|
| 291 |
+
min-width: 220px;
|
| 292 |
+
}
|
| 293 |
+
|
| 294 |
+
.qty-select {
|
| 295 |
+
width: 65px;
|
| 296 |
+
padding: 0.7rem 0.5rem;
|
| 297 |
+
text-align: center;
|
| 298 |
+
cursor: text;
|
| 299 |
+
}
|
| 300 |
+
|
| 301 |
+
select:hover, .qty-select:hover {
|
| 302 |
border-color: var(--sage-green);
|
| 303 |
box-shadow: 0 4px 10px rgba(0,0,0,0.05);
|
| 304 |
}
|
| 305 |
|
| 306 |
+
select:focus, .qty-select:focus {
|
| 307 |
border-color: var(--primary-green);
|
| 308 |
}
|
| 309 |
|