diff --git a/index.html b/index.html
index 20f5119..74df471 100644
--- a/index.html
+++ b/index.html
@@ -3,6 +3,7 @@
Freight Calculator Pro
+
-
-
+
+
@@ -124,7 +167,7 @@
Freight Class
--
-
Density: 0.00 lb/ft³
+
Density: 0.00 lb/ft³
@@ -138,20 +181,58 @@
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+ #2563eb
+
+
+
+
+
+
![Logo preview]()
+
+
+
+
+
+
+
-
+
+
+
+
@@ -167,67 +248,159 @@
{ min: 3, class: 250, desc: "Mattresses" }, { min: 2, class: 300, desc: "Cabinets" },
{ min: 1, class: 400, desc: "Deer antlers" }, { min: -1, class: 500, desc: "Gold dust" }
];
+
let appState = JSON.parse(localStorage.getItem('freightCalcState')) || { theme: 'light', branding: { name:'', color:'#2563eb', logo:'' }, history:[] };
+ let pendingBranding = null;
function saveState() { localStorage.setItem('freightCalcState', JSON.stringify(appState)); }
-
+
// Init
window.onload = () => {
document.body.className = appState.theme === 'dark' ? 'dark-mode' : '';
- document.getElementById('theme-toggle').innerText = appState.theme === 'dark' ? '☀️' : '🌙';
+ document.getElementById('theme-toggle').innerHTML = appState.theme === 'dark' ? '' : '';
document.documentElement.style.setProperty('--primary', appState.branding.color);
- applyBranding();
+ applyBrandingToPage();
renderHistory();
densityRanges.forEach(r => {
- const row = document.createElement('tr'); row.id=`row-${r.class}`;
+ const row = document.createElement('tr'); row.id = `row-${r.class}`;
row.innerHTML = `Class ${r.class} | ${r.min}+ lbs/ft³ | ${r.desc} | `;
document.getElementById('ref-table-body').appendChild(row);
});
+ lucide.createIcons();
};
// Theme
document.getElementById('theme-toggle').onclick = () => {
document.body.classList.toggle('dark-mode');
appState.theme = document.body.classList.contains('dark-mode') ? 'dark' : 'light';
- document.getElementById('theme-toggle').innerText = appState.theme === 'dark' ? '☀️' : '🌙';
+ document.getElementById('theme-toggle').innerHTML = appState.theme === 'dark' ? '' : '';
+ lucide.createIcons();
saveState();
};
- // Branding
- function applyBranding() {
+ // Apply branding visuals to page (header logo/name)
+ function applyBrandingToPage() {
+ const b = appState.branding;
+ const header = document.querySelector('.branding-header');
+ const logo = document.getElementById('business-logo');
+ const nameEl = document.getElementById('business-name-display');
+ logo.src = b.logo || '';
+ logo.style.display = b.logo ? 'block' : 'none';
+ nameEl.textContent = b.name;
+ nameEl.style.display = b.name ? 'block' : 'none';
+ header.style.display = (b.logo || b.name) ? 'flex' : 'none';
+ }
+
+ // Populate settings form fields from appState
+ function populateSettingsForm() {
const b = appState.branding;
document.getElementById('setting-name').value = b.name;
document.getElementById('setting-color').value = b.color;
-
- const logo = document.getElementById('business-logo');
- const name = document.getElementById('business-name-display');
-
- logo.src = b.logo; logo.style.display = b.logo ? 'block' : 'none';
- name.innerText = b.name; name.style.display = b.name ? 'block' : 'none';
+ document.getElementById('color-hex-label').textContent = b.color;
+ const preview = document.getElementById('logo-preview');
+ if (b.logo) { preview.src = b.logo; preview.style.display = 'block'; }
+ else { preview.src = ''; preview.style.display = 'none'; }
}
- document.getElementById('setting-name').oninput = (e) => { appState.branding.name = e.target.value; applyBranding(); saveState(); };
- document.getElementById('setting-color').oninput = (e) => { appState.branding.color = e.target.value; document.documentElement.style.setProperty('--primary', e.target.value); saveState(); };
+
+ // Live input handlers — update appState and preview but don't persist
+ document.getElementById('setting-name').oninput = (e) => {
+ appState.branding.name = e.target.value;
+ applyBrandingToPage();
+ };
+ document.getElementById('setting-color').oninput = (e) => {
+ appState.branding.color = e.target.value;
+ document.getElementById('color-hex-label').textContent = e.target.value;
+ document.documentElement.style.setProperty('--primary', e.target.value);
+ };
document.getElementById('setting-logo').onchange = (e) => {
- const reader = new FileReader(); reader.onload = evt => { appState.branding.logo = evt.target.result; applyBranding(); saveState(); };
+ if (!e.target.files[0]) return;
+ const reader = new FileReader();
+ reader.onload = evt => {
+ appState.branding.logo = evt.target.result;
+ const preview = document.getElementById('logo-preview');
+ preview.src = evt.target.result;
+ preview.style.display = 'block';
+ applyBrandingToPage();
+ };
reader.readAsDataURL(e.target.files[0]);
};
- function clearBranding() { appState.branding = {name:'',color:'#2563eb',logo:''}; applyBranding(); saveState(); }
+
+ // Reset branding (staged — requires Save to persist)
+ document.getElementById('reset-branding-btn').onclick = () => {
+ appState.branding = { name: '', color: '#2563eb', logo: '' };
+ document.documentElement.style.setProperty('--primary', '#2563eb');
+ applyBrandingToPage();
+ populateSettingsForm();
+ };
+
+ // Clear history (immediate)
+ document.getElementById('clear-history-btn').onclick = () => {
+ appState.history = [];
+ saveState();
+ renderHistory();
+ };
+
+ // Modal open
+ document.getElementById('settings-btn').onclick = () => {
+ pendingBranding = JSON.parse(JSON.stringify(appState.branding));
+ populateSettingsForm();
+ switchTab('branding');
+ document.getElementById('settings-modal').classList.add('open');
+ lucide.createIcons();
+ };
+
+ // Cancel / close — revert unsaved changes
+ function revertAndClose() {
+ if (pendingBranding) {
+ appState.branding = pendingBranding;
+ document.documentElement.style.setProperty('--primary', pendingBranding.color);
+ applyBrandingToPage();
+ pendingBranding = null;
+ }
+ document.getElementById('settings-modal').classList.remove('open');
+ }
+ document.getElementById('modal-close-btn').onclick = revertAndClose;
+ document.getElementById('modal-cancel-btn').onclick = revertAndClose;
+
+ // Save — persist to localStorage
+ document.getElementById('modal-save-btn').onclick = () => {
+ saveState();
+ pendingBranding = null;
+ document.getElementById('settings-modal').classList.remove('open');
+ };
+
+ // Tabs
+ function switchTab(t, e) {
+ document.querySelectorAll('.tab-content').forEach(el => el.classList.remove('active'));
+ document.querySelectorAll('.tab-btn').forEach(el => el.classList.remove('active'));
+ document.getElementById('tab-' + t).classList.add('active');
+ const btn = e ? e.target : document.querySelector(`.tab-btn[data-tab="${t}"]`);
+ if (btn) btn.classList.add('active');
+ document.getElementById('modal-footer').style.display = t === 'branding' ? 'flex' : 'none';
+ }
// History
function renderHistory() {
- const list = document.getElementById('history-list'); list.innerHTML = '';
+ const list = document.getElementById('history-list');
+ list.innerHTML = '';
+ if (appState.history.length === 0) {
+ list.innerHTML = 'No calculations yet
';
+ return;
+ }
appState.history.forEach(item => {
- const div = document.createElement('div'); div.className='history-item';
- div.innerHTML = `${item.L}"x${item.W}"x${item.H}" | ${item.Weight}lbsClass ${item.Class}`;
+ const div = document.createElement('div'); div.className = 'history-item';
+ div.innerHTML = `${item.L}"×${item.W}"×${item.H}" · ${item.Weight} lbsClass ${item.Class}`;
div.onclick = () => {
- document.getElementById('length').value=item.L; document.getElementById('width').value=item.W;
- document.getElementById('height').value=item.H; document.getElementById('weight').value=item.Weight;
- document.getElementById('density-result').innerText=item.Density;
- document.getElementById('class-result').innerText=item.Class;
+ document.getElementById('length').value = item.L;
+ document.getElementById('width').value = item.W;
+ document.getElementById('height').value = item.H;
+ document.getElementById('weight').value = item.Weight;
+ document.getElementById('density-result').textContent = item.Density;
+ document.getElementById('class-result').textContent = item.Class;
document.getElementById('results-area').classList.add('active');
- document.querySelectorAll('tbody tr').forEach(r=>r.classList.remove('highlight-row'));
+ document.querySelectorAll('tbody tr').forEach(r => r.classList.remove('highlight-row'));
document.getElementById(`row-${item.Class}`).classList.add('highlight-row');
- document.getElementById('settings-modal').classList.remove('open');
+ revertAndClose();
};
list.appendChild(div);
});
@@ -239,33 +412,22 @@
const W = parseFloat(document.getElementById('width').value);
const H = parseFloat(document.getElementById('height').value);
const WT = parseFloat(document.getElementById('weight').value);
-
- if(!L || !W || !H || !WT) return;
+ if (!L || !W || !H || !WT) return;
- const density = WT / ((L*W*H)/1728);
+ const density = WT / ((L * W * H) / 1728);
let cls = 500;
- for(let r of densityRanges) if(density >= r.min) { cls = r.class; break; }
+ for (let r of densityRanges) if (density >= r.min) { cls = r.class; break; }
- appState.history.unshift({L, W, H, Weight: WT, Density: density.toFixed(2), Class: cls});
- if(appState.history.length > 20) appState.history.pop();
+ appState.history.unshift({ L, W, H, Weight: WT, Density: density.toFixed(2), Class: cls });
+ if (appState.history.length > 20) appState.history.pop();
saveState(); renderHistory();
- document.getElementById('density-result').innerText = density.toFixed(2);
- document.getElementById('class-result').innerText = cls;
+ document.getElementById('density-result').textContent = density.toFixed(2);
+ document.getElementById('class-result').textContent = cls;
document.getElementById('results-area').classList.add('active');
-
- document.querySelectorAll('tbody tr').forEach(r=>r.classList.remove('highlight-row'));
+ document.querySelectorAll('tbody tr').forEach(r => r.classList.remove('highlight-row'));
document.getElementById(`row-${cls}`).classList.add('highlight-row');
}
-
- // Modal
- document.getElementById('settings-btn').onclick = () => document.getElementById('settings-modal').classList.add('open');
- function switchTab(t) {
- document.querySelectorAll('.tab-content').forEach(e=>e.classList.remove('active'));
- document.querySelectorAll('.tab-btn').forEach(e=>e.classList.remove('active'));
- document.getElementById('tab-'+t).classList.add('active');
- event.target.classList.add('active');
- }
-