Replace alert/confirm with modals, hide sector numbers on cramped layout, enforce 2/3/6 grid for All Sectors
This commit is contained in:
parent
638947f04c
commit
21cb0aeb50
4 changed files with 151 additions and 14 deletions
|
|
@ -66,6 +66,23 @@
|
|||
}
|
||||
}
|
||||
|
||||
/* Cramped / Mobile viewport: Hide sector pill numbers so only icons are displayed */
|
||||
@media (max-width: 640px) {
|
||||
.sector-pill .sector-pill-rate {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.sector-pill {
|
||||
padding: 8px 4px;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.sector-pill iconify-icon {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ==========================================================================
|
||||
TOASTS & MODALS
|
||||
========================================================================== */
|
||||
|
|
@ -232,3 +249,20 @@
|
|||
.btn-text-close:hover {
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.modal-error-box {
|
||||
background: #fef2f2;
|
||||
border: 1px solid #fecaca;
|
||||
color: #b91c1c;
|
||||
padding: 8px 12px;
|
||||
border-radius: var(--radius-sm);
|
||||
font-size: 0.78rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.modal-body-text {
|
||||
font-size: 0.88rem;
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -216,13 +216,33 @@
|
|||
color: var(--emerald-dark);
|
||||
}
|
||||
|
||||
/* All Sectors Overview Grid */
|
||||
/* All Sectors Overview Grid (Strict 6, 3, or 2 grid for 6 sectors) */
|
||||
.all-sectors-summary-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
@media (min-width: 1400px) {
|
||||
.all-sectors-summary-grid {
|
||||
grid-template-columns: repeat(6, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.all-sectors-summary-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.all-sectors-summary-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.sector-mini-card {
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-color);
|
||||
|
|
|
|||
|
|
@ -213,6 +213,9 @@
|
|||
<input type="password" id="auth-password" class="modal-input" placeholder="••••••••" autocomplete="current-password">
|
||||
</div>
|
||||
|
||||
<!-- In-modal Error Feedback (Replacing alert()) -->
|
||||
<div id="auth-error-msg" class="modal-error-box" style="display: none;"></div>
|
||||
|
||||
<!-- Honeypot field for bot protection -->
|
||||
<div style="display: none;" aria-hidden="true">
|
||||
<input type="text" id="auth-website-hp" name="website_hp" tabindex="-1" autocomplete="off">
|
||||
|
|
@ -227,6 +230,24 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Universal Corporate Confirmation & Prompt Modal (No browser alert() / confirm()) -->
|
||||
<div id="confirm-modal" class="modal-overlay">
|
||||
<div class="modal-card">
|
||||
<div class="modal-header">
|
||||
<iconify-icon icon="lucide:alert-triangle" class="modal-icon text-warning" id="confirm-modal-icon"></iconify-icon>
|
||||
<div>
|
||||
<h3 class="modal-title" id="confirm-modal-title">Executive Action Required</h3>
|
||||
<p class="modal-subtitle" id="confirm-modal-subtitle">Corporate Board Authorization</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body-text" id="confirm-modal-text"></div>
|
||||
<div class="modal-actions-row">
|
||||
<button id="btn-confirm-cancel" class="btn-corp-secondary">Cancel</button>
|
||||
<button id="btn-confirm-ok" class="btn-primary-corp">Confirm Authorization</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Application Entry Point (Native ES Module) -->
|
||||
|
|
|
|||
|
|
@ -275,7 +275,14 @@ class ProductionApp {
|
|||
}
|
||||
|
||||
case 'TRIGGER_IPO': {
|
||||
const confirmed = confirm('Confirm Corporate Initial Public Offering (IPO)?\n\nYour factories and cash will reset in exchange for permanent Venture Shares ($V-Shares) and corporate equity!');
|
||||
this.showConfirmModal({
|
||||
title: 'Authorize Initial Public Offering (IPO)',
|
||||
subtitle: 'Corporate Equity Transition',
|
||||
icon: 'lucide:trending-up',
|
||||
text: 'Confirm Corporate Initial Public Offering (IPO)?<br><br>All factory floors and cash will be liquidated in exchange for permanent <strong>Venture Shares ($V-Shares)</strong> and corporate prestige bonuses!',
|
||||
okText: 'Execute IPO',
|
||||
cancelText: 'Abort'
|
||||
}).then(confirmed => {
|
||||
if (confirmed) {
|
||||
const success = this.sm.performIPO();
|
||||
if (success) {
|
||||
|
|
@ -284,6 +291,7 @@ class ProductionApp {
|
|||
this.mountInspectorPane();
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -468,8 +476,52 @@ class ProductionApp {
|
|||
}, 3200);
|
||||
}
|
||||
|
||||
showConfirmModal({ title = 'Executive Authorization', subtitle = 'Board Confirmation', icon = 'lucide:alert-triangle', text = '', okText = 'Confirm', cancelText = 'Cancel' } = {}) {
|
||||
return new Promise((resolve) => {
|
||||
const modal = document.getElementById('confirm-modal');
|
||||
const elTitle = document.getElementById('confirm-modal-title');
|
||||
const elSub = document.getElementById('confirm-modal-subtitle');
|
||||
const elIcon = document.getElementById('confirm-modal-icon');
|
||||
const elText = document.getElementById('confirm-modal-text');
|
||||
const btnOk = document.getElementById('btn-confirm-ok');
|
||||
const btnCancel = document.getElementById('btn-confirm-cancel');
|
||||
|
||||
if (!modal) return resolve(false);
|
||||
|
||||
if (elTitle) elTitle.textContent = title;
|
||||
if (elSub) elSub.textContent = subtitle;
|
||||
if (elIcon) elIcon.setAttribute('icon', icon);
|
||||
if (elText) elText.innerHTML = text;
|
||||
if (btnOk) btnOk.textContent = okText;
|
||||
if (btnCancel) btnCancel.textContent = cancelText;
|
||||
|
||||
const cleanup = () => {
|
||||
modal.classList.remove('open');
|
||||
btnOk.onclick = null;
|
||||
btnCancel.onclick = null;
|
||||
};
|
||||
|
||||
btnOk.onclick = () => {
|
||||
cleanup();
|
||||
resolve(true);
|
||||
};
|
||||
|
||||
btnCancel.onclick = () => {
|
||||
cleanup();
|
||||
resolve(false);
|
||||
};
|
||||
|
||||
modal.classList.add('open');
|
||||
});
|
||||
}
|
||||
|
||||
openAuthModal() {
|
||||
const modal = document.getElementById('auth-modal');
|
||||
const errBox = document.getElementById('auth-error-msg');
|
||||
if (errBox) {
|
||||
errBox.style.display = 'none';
|
||||
errBox.textContent = '';
|
||||
}
|
||||
if (modal) modal.classList.add('open');
|
||||
}
|
||||
|
||||
|
|
@ -478,10 +530,20 @@ class ProductionApp {
|
|||
if (modal) modal.classList.remove('open');
|
||||
}
|
||||
|
||||
showAuthError(msg) {
|
||||
const errBox = document.getElementById('auth-error-msg');
|
||||
if (errBox) {
|
||||
errBox.textContent = msg;
|
||||
errBox.style.display = 'block';
|
||||
} else {
|
||||
this.showToast(msg, 'warning');
|
||||
}
|
||||
}
|
||||
|
||||
async handleLogin() {
|
||||
const u = document.getElementById('auth-username')?.value.trim();
|
||||
const p = document.getElementById('auth-password')?.value;
|
||||
if (!u || !p) return alert('Please enter username and password');
|
||||
if (!u || !p) return this.showAuthError('Please enter username and password');
|
||||
|
||||
try {
|
||||
await this.sync.login(u, p);
|
||||
|
|
@ -489,7 +551,7 @@ class ProductionApp {
|
|||
this.closeAuthModal();
|
||||
this.updateHud();
|
||||
} catch (err) {
|
||||
alert(err.message || 'Login failed');
|
||||
this.showAuthError(err.message || 'Login failed');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -497,7 +559,7 @@ class ProductionApp {
|
|||
const u = document.getElementById('auth-username')?.value.trim();
|
||||
const p = document.getElementById('auth-password')?.value;
|
||||
const hp = document.getElementById('auth-website-hp')?.value;
|
||||
if (!u || !p) return alert('Please enter username and password');
|
||||
if (!u || !p) return this.showAuthError('Please enter username and password');
|
||||
|
||||
try {
|
||||
await this.sync.register(u, p, hp);
|
||||
|
|
@ -505,7 +567,7 @@ class ProductionApp {
|
|||
this.closeAuthModal();
|
||||
this.updateHud();
|
||||
} catch (err) {
|
||||
alert(err.message || 'Registration failed');
|
||||
this.showAuthError(err.message || 'Registration failed');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue