index_html
Products at a Glance
Products at a Glance
---------------------
app_js
let productData = JSON.parse(localStorage.getItem("productData") || "null") || {};
let editingKey = null;
function init() {
const stateSel = document.getElementById("stateSelect");
stateSel.innerHTML = '';
Object.keys(productData).forEach(state => {
const opt = document.createElement("option");
opt.value = state;
opt.textContent = state;
stateSel.appendChild(opt);
});
stateSel.addEventListener("change", () => {
const categorySel = document.getElementById("categorySelect");
const state = stateSel.value;
categorySel.innerHTML = '';
if (productData[state]) {
Object.keys(productData[state]).forEach(cat => {
const opt = document.createElement("option");
opt.value = cat;
opt.textContent = cat;
categorySel.appendChild(opt);
});
}
document.getElementById("itemSelectBox").innerHTML = "";
document.getElementById("horizontalDisplay").innerHTML = "";
});
document.getElementById("categorySelect").addEventListener("change", () => {
const state = stateSel.value;
const category = document.getElementById("categorySelect").value;
const box = document.getElementById("itemSelectBox");
box.innerHTML = "";
if (productData[state] && productData[state][category]) {
productData[state][category].forEach(prod => {
const label = document.createElement("label");
const cb = document.createElement("input");
cb.type = "checkbox";
cb.value = prod.title;
label.appendChild(cb);
label.append(` ${prod.title}`);
box.appendChild(label);
});
}
});
}
function renderSelected() {
const state = document.getElementById("stateSelect").value;
const category = document.getElementById("categorySelect").value;
const selected = Array.from(document.querySelectorAll("#itemSelectBox input:checked")).map(cb => cb.value);
const display = document.getElementById("horizontalDisplay");
display.innerHTML = "";
if (productData[state] && productData[state][category]) {
productData[state][category].filter(p => selected.includes(p.title)).forEach(product => {
const div = document.createElement("div");
div.innerHTML = `${product.title}
${product.content}
`;
display.appendChild(div);
});
}
}
function saveProduct() {
const state = document.getElementById("stateEntry").value.trim() || document.getElementById("stateEntrySelect").value;
const category = document.getElementById("categoryEntry").value.trim() || document.getElementById("categoryEntrySelect").value;
const title = document.getElementById("productTitle").value.trim();
const content = document.getElementById("productContent").value.trim();
if (!state || !category || !title || !content) {
alert("All fields required.");
return;
}
if (!productData[state]) productData[state] = {};
if (!productData[state][category]) productData[state][category] = [];
const list = productData[state][category];
const index = list.findIndex(p => p.title === title);
if (index >= 0) {
list[index].content = content;
} else {
list.push({ title, content });
}
localStorage.setItem("productData", JSON.stringify(productData));
alert("Product saved.");
editingKey = null;
location.reload();
}
function editProduct(state, category, title) {
const product = productData[state][category].find(p => p.title === title);
if (!product) return;
document.getElementById("stateEntry").value = state;
document.getElementById("categoryEntry").value = category;
document.getElementById("productTitle").value = title;
document.getElementById("productContent").value = product.content;
editingKey = { state, category, title };
}
document.addEventListener("DOMContentLoaded", init);
window.exportDataToFile = function () {
const content = `const seedData = ${JSON.stringify(productData, null, 2)};
if (!localStorage.getItem("productData")) {
localStorage.setItem("productData", JSON.stringify(seedData));
}`;
const blob = new Blob([content], { type: "application/javascript" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "product_data.js";
a.click();
URL.revokeObjectURL(url);
document.getElementById("editorStatus").textContent = "Exported to JS file.";
};
window.exportDataAsTxt = function () {
const content = JSON.stringify(productData, null, 2);
const blob = new Blob([content], { type: "text/plain" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "product_data.txt";
a.click();
URL.revokeObjectURL(url);
document.getElementById("editorStatus").textContent = "Exported to TXT file.";
};
window.importDataFromFile = function (input) {
const file = input.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function (e) {
let text = e.target.result;
try {
if (text.trim().startsWith("const productData")) {
text = text.replace(/const productData\s*=\s*/, "").replace(/;\s*$/, "");
}
const parsed = JSON.parse(text);
if (parsed && typeof parsed === "object") {
productData = parsed;
localStorage.setItem("productData", JSON.stringify(productData));
alert("Data imported successfully.");
document.getElementById("editorStatus").textContent = "Import successful.";
location.reload();
} else {
alert("Invalid data format.");
}
} catch (err) {
alert("Failed to import data.");
}
};
reader.readAsText(file);
};
function populateEditorDropdowns() {
const stateDropdown = document.getElementById("stateEntrySelect");
stateDropdown.innerHTML = '';
Object.keys(productData).forEach(state => {
const opt = document.createElement("option");
opt.value = state;
opt.textContent = state;
stateDropdown.appendChild(opt);
});
stateDropdown.addEventListener("change", () => {
const selectedState = stateDropdown.value;
const catDropdown = document.getElementById("categoryEntrySelect");
catDropdown.innerHTML = '';
if (productData[selectedState]) {
Object.keys(productData[selectedState]).forEach(cat => {
const opt = document.createElement("option");
opt.value = cat;
opt.textContent = cat;
catDropdown.appendChild(opt);
});
}
});
}
document.addEventListener("DOMContentLoaded", () => {
init();
populateEditorDropdowns();
});
function deleteProduct() {
const state = document.getElementById("stateEntry").value.trim() || document.getElementById("stateEntrySelect").value;
const category = document.getElementById("categoryEntry").value.trim() || document.getElementById("categoryEntrySelect").value;
const title = document.getElementById("productTitle").value.trim();
if (!state || !category || !title) return alert("Provide state, category, and product title");
if (productData[state] && productData[state][category]) {
productData[state][category] = productData[state][category].filter(p => p.title !== title);
if (productData[state][category].length === 0) delete productData[state][category];
localStorage.setItem("productData", JSON.stringify(productData));
alert("Product deleted.");
location.reload();
}
}
function deleteCategory() {
const state = document.getElementById("stateEntry").value.trim() || document.getElementById("stateEntrySelect").value;
const category = document.getElementById("categoryEntry").value.trim() || document.getElementById("categoryEntrySelect").value;
if (!state || !category) return alert("Provide state and category");
if (confirm(`Delete category "${category}" from ${state}?`)) {
if (productData[state]) {
delete productData[state][category];
localStorage.setItem("productData", JSON.stringify(productData));
alert("Category deleted.");
location.reload();
}
}
}
function deleteState() {
const state = document.getElementById("stateEntry").value.trim() || document.getElementById("stateEntrySelect").value;
if (!state) return alert("Provide a state");
if (confirm(`Delete state "${state}" and all its contents?`)) {
delete productData[state];
localStorage.setItem("productData", JSON.stringify(productData));
alert("State deleted.");
location.reload();
}
}
---------------------
product_data_js
const seedData = {
"Arizona": {
"Category 1": [{ "title": "Product A", "content": "Info on Product A
" }]
},
"Texas": {
"Category 2": [{ "title": "Product B", "content": "Details on Product B
" }]
}
};
if (!localStorage.getItem("productData")) {
localStorage.setItem("productData", JSON.stringify(seedData));
}
---------------------
styles_css
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 0;
background-color: #f0f2f5;
color: #333;
}
main.content {
max-width: 1200px;
margin: auto;
padding: 40px;
background: #ffffff;
border-radius: 10px;
box-shadow: 0 4px 10px rgba(0,0,0,0.05);
}
h1 {
font-size: 32px;
color: #1a1a2e;
margin-bottom: 30px;
}
label {
font-weight: bold;
margin-top: 20px;
display: block;
}
select {
width: 100%;
padding: 12px;
font-size: 16px;
margin-top: 6px;
border: 1px solid #ccc;
border-radius: 6px;
margin-bottom: 20px;
}
.checkbox-group {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-bottom: 20px;
}
.checkbox-group label {
background: #fefefe;
padding: 10px 15px;
border: 1px solid #ccc;
border-radius: 6px;
cursor: pointer;
transition: all 0.2s ease;
}
.checkbox-group label:hover {
background-color: #eef1f4;
}
button {
background-color: #0066cc;
color: white;
padding: 12px 24px;
font-size: 16px;
border: none;
border-radius: 6px;
cursor: pointer;
transition: background-color 0.2s ease-in-out;
margin-bottom: 30px;
}
button:hover {
background-color: #004999;
}
.scroll-container {
display: flex;
overflow-x: auto;
gap: 20px;
padding: 20px;
background-color: #fafafa;
border: 1px solid #ddd;
border-radius: 8px;
}
.scroll-container > div {
flex: 0 0 auto;
min-width: 250px;
max-width: 500px;
background-color: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 6px rgba(0,0,0,0.05);
border: 1px solid #e0e0e0;
}
.scroll-container h3 {
margin-top: 0;
color: #00509e;
}
#editorSection {
background-color: #fdfdfd;
border: 1px solid #ddd;
border-radius: 8px;
padding: 30px;
margin-top: 50px;
box-shadow: 0 2px 10px rgba(0,0,0,0.03);
}
#editorSection h2 {
margin-bottom: 20px;
color: #1a1a2e;
}
#editorForm label {
font-weight: bold;
margin-top: 15px;
display: block;
}
#editorForm input[type="text"],
#editorForm textarea,
#editorForm select {
width: 100%;
padding: 12px;
font-size: 14px;
border: 1px solid #ccc;
border-radius: 6px;
margin-top: 6px;
margin-bottom: 20px;
}
#editorForm button {
margin-right: 10px;
margin-top: 10px;
}
#saveItem {
background-color: #28a745;
}
#saveItem:hover {
background-color: #218838;
}
#deleteItem {
background-color: #dc3545;
}
#deleteItem:hover {
background-color: #c82333;
}
#exportJsButton {
background-color: #007bff;
}
#exportJsButton:hover {
background-color: #0069d9;
}
#exportTxtButton {
background-color: #6f42c1;
}
#exportTxtButton:hover {
background-color: #5936a2;
}
#fileInput {
background-color: #ffcc00;
font-weight: bold;
}
#fileInput:hover {
background-color: #e0b800;
}