ChatGPT Session in the Making and Source-Code of "[MAIN PROGRAM] UNDONE HOUSEHOLD WORKs WEB-PROGRAM v2/MAIN" POST
ChatGPT SESSION in Making "[MAIN PROGRAM] UNDONE HOUSEHOLD WORKs WEB-PROGRAM v2/MAIN" POST
CLICK HERE !!
CLICK HERE !!
SOURCE CODE
<!-- ========================================================= -->
<!-- ========== HELLO FIREBASE TESTER (REMOVABLE BLOCK) ====== -->
<!-- ========== You can delete everything in this box ========= -->
<!-- ========================================================= -->
<div id="test_status" style="
padding:10px;
margin:10px 0;
border:1px solid #aaa;
border-radius:8px;
background:#f4f4f4;">
Waiting to test Firebase…
</div>
<button onclick="testWrite()"
style="padding:8px 12px; border-radius:6px; background:#1976d2; color:white;">
Write Test Data
</button>
<button onclick="testRead()"
style="padding:8px 12px; border-radius:6px; background:#4caf50; color:white;">
Read Test Data
</button>
<button onclick="deleteTester()"
style="padding:8px 12px; border-radius:6px; background:#c62828; color:white;">
Delete Tester Data
</button>
<!-- ========================================================= -->
<!-- ========== END OF HELLO FIREBASE TESTER BLOCK =========== -->
<!-- ========== MAIN APP (CRUD) STARTS BELOW ================= -->
<!-- ========================================================= -->
<!-- ================================ -->
<!-- SIMPLE STYLE (BOX + TABLE) -->
<!-- ================================ -->
<style>
.box {
border:1px solid #aaa;
padding:15px;
border-radius:10px;
margin:15px 0;
background:#f7f7f7;
}
.label {
font-weight:bold;
margin-top:10px;
display:block;
}
.btn {
background:#1976d2;
color:#fff;
padding:6px 12px;
border-radius:5px;
cursor:pointer;
margin-top:8px;
display:inline-block;
text-decoration:none;
font-size:14px;
}
.btn-red {
background:#c62828;
color:#fff;
}
input, select, textarea {
width:100%;
padding:5px;
margin-top:6px;
border:1px solid #888;
border-radius:6px;
box-sizing:border-box;
}
table {
width:100%;
border-collapse:collapse;
margin-top:20px;
}
th, td {
border:1px solid #aaa;
padding:8px;
font-size:14px;
vertical-align:top;
}
th {
background:#e0e0e0;
}
</style>
<!-- ================================ -->
<!-- CATEGORY MANAGER (CRUD) -->
<!-- ================================ -->
<div class="box">
<h3>Category Manager (CRUD)</h3>
<label class="label">ADD NEW Category:</label>
<input id="cat_new_name" placeholder="Example: Household, Maintenance, etc." />
<div class="btn" onclick="addCategory()">Add Category</div>
<h4>Existing Categories</h4>
<table id="cat_table">
<tr>
<th>Category</th>
<th>Actions</th>
</tr>
</table>
</div>
<!-- ================================ -->
<!-- TASK CREATOR -->
<!-- ================================ -->
<div class="box">
<h3>Create New Task</h3>
<label class="label">Task Title:</label>
<input id="task_title" />
<label class="label">Category:</label>
<select id="task_category_select" onchange="onCategorySelectChange('create')">
<!-- options filled by JS from Categories table -->
</select>
<div id="task_category_custom_wrapper" style="display:none;">
<label class="label">ADD NEW:</label>
<input id="task_category_custom" placeholder="Custom category name" />
</div>
<div class="btn" onclick="createTask()">Create Task</div>
</div>
<!-- ================================ -->
<!-- TASK LIST + CATEGORY FILTER -->
<!-- ================================ -->
<div class="box">
<h3>Task List</h3>
<label class="label">Filter by Category:</label>
<select id="category_filter" onchange="categoryFilterChanged()">
<option value="">(All Categories)</option>
</select>
<table id="task_table">
<tr>
<th>Task ID</th>
<th>Title</th>
<th>Category</th>
<th>Overall Status</th>
<th>Manage</th>
</tr>
</table>
</div>
<!-- ================================ -->
<!-- PHASE MANAGER -->
<!-- ================================ -->
<div class="box" id="phase_box" style="display:none;">
<h3>Phase Manager</h3>
<div id="phase_task_id"></div>
<label class="label">Category for this Task:</label>
<select id="task_category_edit_select" onchange="onCategorySelectChange('edit')">
<!-- options filled by JS from Categories table -->
</select>
<div id="task_category_edit_custom_wrapper" style="display:none;">
<label class="label">ADD NEW:</label>
<input id="task_category_edit_custom" placeholder="Custom category name" />
</div>
<div class="btn" onclick="saveTaskCategory()">Save Category</div>
<hr />
<label class="label">Phase Number:</label>
<select id="phase_number"></select>
<label class="label">Phase Status:</label>
<select id="phase_status"></select>
<label class="label">Phase Description:</label>
<textarea id="phase_desc" rows="3"></textarea>
<div class="btn" onclick="addPhase()">Add Phase</div>
<h4>Existing Phases:</h4>
<table id="phase_table">
<tr>
<th>Phase</th>
<th>Status</th>
<th>Description</th>
</tr>
</table>
</div>
<!-- ================================ -->
<!-- SPREADSHEET IMPORTER -->
<!-- ================================ -->
<div class="box">
<h3>Upload Spreadsheet → Import to Firebase</h3>
<p style="font-size:13px;margin-bottom:8px;">
Expected columns in sheet: <b>Title</b>, <b>Phase Number</b>, <b>Phase Status</b>,
<b>Description</b>, and optional <b>Category</b>.<br/>
Value <code>na</code> or <code>not available</code> in Category will be stored as blank.
</p>
<input type="file" id="file_input" />
<div class="btn" onclick="importSheet()">Upload & Import</div>
</div>
<!-- ================================ -->
<!-- SCRIPT LOADING (Firebase + XLSX)-->
<!-- ================================ -->
<script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-database.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
<!-- ================================ -->
<!-- MAIN APP SCRIPT (CDATA WRAPPED)-->
<!-- ================================ -->
<script type="text/javascript">
//<![CDATA[
(function () {
var rdb = null;
var CURRENT_TASK = null;
var CURRENT_FILTER_CATEGORY = ""; // ""=all, "__blank__"=no category, others=exact value
var CATEGORIES = []; // {id: "...", name: "Household"}
var statusBox = document.getElementById("test_status");
// ---- INITIALIZE FIREBASE ----
var config = {
apiKey: "AIzaSyAF5r6Rvu-DmoV-vf47wYTZfarpVGmNYR0",
authDomain: "ronin-11938.firebaseapp.com",
databaseURL: "https://ronin-11938-default-rtdb.firebaseio.com",
projectId: "ronin-11938",
storageBucket: "ronin-11938.firebasestorage.app",
messagingSenderId: "823368889742",
appId: "1:823368889742:web:609e16ace214b94a0df"
};
try {
if (firebase.apps && firebase.apps.length > 0) {
firebase.app();
} else {
firebase.initializeApp(config);
}
} catch (e) {}
rdb = firebase.database();
if (statusBox) {
statusBox.innerHTML = "<b>Firebase initialized!</b><br>Try writing or reading.";
}
// ---- TEST WRITE ----
window.testWrite = function () {
if (!rdb) { alert("Firebase not ready yet."); return; }
var testId = "hello_" + new Date().getTime();
rdb.ref("TESTER/" + testId).set({
msg: "Hello from Blogger!",
time: new Date().toString()
}).then(function () {
if (statusBox) {
statusBox.innerHTML = "<b>Write Success!</b><br>Data written under: TESTER/" + testId;
} else {
alert("Write Success: TESTER/" + testId);
}
}).catch(function (err) {
if (statusBox) {
statusBox.innerHTML = "<b>Write Error:</b> " + err;
} else {
alert("Write Error: " + err);
}
});
};
// ---- TEST READ ----
window.testRead = function () {
if (!rdb) { alert("Firebase not ready yet."); return; }
rdb.ref("TESTER").limitToLast(1).once("value").then(function (snap) {
var data = snap.val();
if (statusBox) {
statusBox.innerHTML = "<b>Read Success!</b><br>Latest entry:<br>"
+ JSON.stringify(data, null, 2);
} else {
alert("Read Success: " + JSON.stringify(data));
}
}).catch(function (err) {
if (statusBox) {
statusBox.innerHTML = "<b>Read Error:</b> " + err;
} else {
alert("Read Error: " + err);
}
});
};
// ---- TEST DELETE ----
window.deleteTester = function () {
if (!rdb) { alert("Firebase not ready yet."); return; }
if (!confirm("Delete all TESTER data?")) return;
rdb.ref("TESTER").remove().then(function () {
if (statusBox) {
statusBox.innerHTML = "<b>TESTER data deleted.</b>";
} else {
alert("TESTER data deleted.");
}
}).catch(function (err) {
if (statusBox) {
statusBox.innerHTML = "<b>Delete Error:</b> " + err;
} else {
alert("Delete Error: " + err);
}
});
};
// ------------------------------
// Normalize category (handles "na" / "not available")
// ------------------------------
function normalizeCategory(value) {
if (!value) return "";
var v = ("" + value).replace(/^\s+|\s+$/g, "").toLowerCase();
if (v === "na" || v === "not available") return "";
return ("" + value).replace(/^\s+|\s+$/g, "");
}
// ------------------------------
// Phase dropdown generators
// ------------------------------
function setupPhaseDropdowns() {
var phaseSelect = document.getElementById("phase_number");
var statusSelect = document.getElementById("phase_status");
if (!phaseSelect || !statusSelect) return;
var i, suffix;
for (i = 1; i <= 20; i++) {
if (i === 1) suffix = "1st phase";
else if (i === 2) suffix = "2nd phase";
else if (i === 3) suffix = "3rd phase";
else suffix = i + "th phase";
var opt = document.createElement("option");
opt.value = suffix;
opt.appendChild(document.createTextNode(suffix));
phaseSelect.appendChild(opt);
}
var optDone = document.createElement("option");
optDone.value = "done!";
optDone.appendChild(document.createTextNode("done!"));
statusSelect.appendChild(optDone);
var optNY = document.createElement("option");
optNY.value = "not yet";
optNY.appendChild(document.createTextNode("not yet"));
statusSelect.appendChild(optNY);
}
// ------------------------------
// CATEGORY CRUD
// ------------------------------
function loadCategories() {
if (!rdb) return;
rdb.ref("Categories").once("value").then(function (snap) {
var data = snap.val() || {};
CATEGORIES = [];
var id;
for (id in data) {
if (!data.hasOwnProperty(id)) continue;
var name = normalizeCategory(data[id].name || "");
if (name) {
CATEGORIES.push({ id: id, name: name });
}
}
// If no categories yet, create defaults once
if (CATEGORIES.length === 0) {
var defaults = ["Household", "Maintenance", "Office", "Personal"];
for (var i = 0; i < defaults.length; i++) {
var ref = rdb.ref("Categories").push();
ref.set({ name: defaults[i] });
}
loadCategories();
return;
}
buildCategoryManagerTable();
rebuildCategoryDropdowns();
loadTasks();
});
}
function buildCategoryManagerTable() {
var table = document.getElementById("cat_table");
if (!table) return;
table.innerHTML =
"<tr>" +
"<th>Category</th>" +
"<th>Actions</th>" +
"</tr>";
for (var i = 0; i < CATEGORIES.length; i++) {
var cat = CATEGORIES[i];
var row = table.insertRow(-1);
var c1 = row.insertCell(0);
var c2 = row.insertCell(1);
c1.appendChild(document.createTextNode(cat.name));
var btnDel = document.createElement("span");
btnDel.className = "btn btn-red";
btnDel.appendChild(document.createTextNode("Delete"));
btnDel.setAttribute("onclick", "deleteCategory('" + cat.id + "')");
c2.appendChild(btnDel);
}
}
function addCategory() {
if (!rdb) { alert("Firebase not ready yet."); return; }
var input = document.getElementById("cat_new_name");
if (!input) return;
var name = normalizeCategory(input.value || "");
if (!name) {
alert("Category name is empty or invalid.");
return;
}
var ref = rdb.ref("Categories").push();
ref.set({ name: name }).then(function () {
input.value = "";
loadCategories();
}).catch(function (err) {
alert("Error adding category: " + err);
});
}
function deleteCategory(catId) {
if (!rdb) return;
if (!confirm("Delete this category? This will NOT change existing tasks' category strings.")) return;
rdb.ref("Categories/" + catId).remove().then(function () {
loadCategories();
}).catch(function (err) {
alert("Error deleting category: " + err);
});
}
function rebuildCategoryDropdowns() {
var selCreate = document.getElementById("task_category_select");
var selEdit = document.getElementById("task_category_edit_select");
function fillDropdown(sel, includeCustom) {
if (!sel) return;
sel.innerHTML = "";
var optNone = document.createElement("option");
optNone.value = "__none__";
optNone.appendChild(document.createTextNode("(none)"));
sel.appendChild(optNone);
for (var i = 0; i < CATEGORIES.length; i++) {
var cat = CATEGORIES[i];
var o = document.createElement("option");
o.value = cat.name;
o.appendChild(document.createTextNode(cat.name));
sel.appendChild(o);
}
if (includeCustom) {
var optCustom = document.createElement("option");
optCustom.value = "__custom__";
optCustom.appendChild(document.createTextNode("Custom (ADD NEW)"));
sel.appendChild(optCustom);
}
}
fillDropdown(selCreate, true);
fillDropdown(selEdit, true);
}
// ------------------------------
// Category dropdown change (show/hide custom input)
// ------------------------------
function onCategorySelectChange(mode) {
if (mode === "create") {
var sel = document.getElementById("task_category_select");
var wrap = document.getElementById("task_category_custom_wrapper");
if (!sel || !wrap) return;
if (sel.value === "__custom__") {
wrap.style.display = "block";
} else {
wrap.style.display = "none";
var inp = document.getElementById("task_category_custom");
if (inp) inp.value = "";
}
} else if (mode === "edit") {
var sel2 = document.getElementById("task_category_edit_select");
var wrap2 = document.getElementById("task_category_edit_custom_wrapper");
if (!sel2 || !wrap2) return;
if (sel2.value === "__custom__") {
wrap2.style.display = "block";
} else {
wrap2.style.display = "none";
var inp2 = document.getElementById("task_category_edit_custom");
if (inp2) inp2.value = "";
}
}
}
// ------------------------------
// Get final category from dropdown + custom input
// ------------------------------
function resolveCategory(mode) {
if (mode === "create") {
var sel = document.getElementById("task_category_select");
var inp = document.getElementById("task_category_custom");
var val = sel ? sel.value : "__none__";
if (val === "__custom__") {
var custom = inp ? normalizeCategory(inp.value || "") : "";
return custom;
} else if (val === "__none__") {
return "";
} else {
return normalizeCategory(val);
}
} else if (mode === "edit") {
var sel2 = document.getElementById("task_category_edit_select");
var inp2 = document.getElementById("task_category_edit_custom");
var val2 = sel2 ? sel2.value : "__none__";
if (val2 === "__custom__") {
var custom2 = inp2 ? normalizeCategory(inp2.value || "") : "";
return custom2;
} else if (val2 === "__none__") {
return "";
} else {
return normalizeCategory(val2);
}
}
return "";
}
function setEditCategoryUI(catVal) {
var sel = document.getElementById("task_category_edit_select");
var wrap = document.getElementById("task_category_edit_custom_wrapper");
var inp = document.getElementById("task_category_edit_custom");
if (!sel || !wrap || !inp) return;
var clean = normalizeCategory(catVal || "");
if (!clean) {
sel.value = "__none__";
wrap.style.display = "none";
inp.value = "";
return;
}
var found = false;
for (var i = 0; i < CATEGORIES.length; i++) {
if (CATEGORIES[i].name === clean) {
sel.value = clean;
found = true;
break;
}
}
if (found) {
wrap.style.display = "none";
inp.value = "";
} else {
sel.value = "__custom__";
wrap.style.display = "block";
inp.value = clean;
}
}
// ------------------------------
// Create Task (global)
// ------------------------------
function createTask() {
if (!rdb) { alert("Firebase not ready yet."); return; }
var titleInput = document.getElementById("task_title");
var title = titleInput ? titleInput.value : "";
title = title.replace(/^\s+|\s+$/g, "");
if (!title) {
alert("Task title is empty.");
return;
}
var category = resolveCategory("create");
var taskId = (new Date().getTime()).toString();
rdb.ref("Tasks/" + taskId).set({
task_title: title,
category: category,
overall_status: "ongoing"
}).then(function () {
alert("Task created!");
if (titleInput) titleInput.value = "";
var inpCustom = document.getElementById("task_category_custom");
if (inpCustom) inpCustom.value = "";
var sel = document.getElementById("task_category_select");
if (sel) sel.value = "__none__";
onCategorySelectChange("create");
loadTasks();
}).catch(function (err) {
alert("Error creating task: " + err);
});
}
// ------------------------------
// Load Tasks
// ------------------------------
function loadTasks() {
var table = document.getElementById("task_table");
var selFilter = document.getElementById("category_filter");
if (!table || !rdb) return;
table.innerHTML =
"<tr>" +
"<th>Task ID</th>" +
"<th>Title</th>" +
"<th>Category</th>" +
"<th>Overall Status</th>" +
"<th>Manage</th>" +
"</tr>";
rdb.ref("Tasks").once("value").then(function (snap) {
var data = snap.val() || {};
if (selFilter) {
var existing = {};
var id;
for (id in data) {
if (!data.hasOwnProperty(id)) continue;
var catVal = normalizeCategory(data[id].category || "");
if (catVal) existing[catVal] = true;
}
selFilter.innerHTML = "";
var optAll = document.createElement("option");
optAll.value = "";
optAll.appendChild(document.createTextNode("(All Categories)"));
selFilter.appendChild(optAll);
var optBlank = document.createElement("option");
optBlank.value = "__blank__";
optBlank.appendChild(document.createTextNode("(No Category)"));
selFilter.appendChild(optBlank);
var catsList = [];
var c;
for (c in existing) {
if (existing.hasOwnProperty(c)) catsList.push(c);
}
catsList.sort();
for (var i = 0; i < catsList.length; i++) {
var o = document.createElement("option");
o.value = catsList[i];
o.appendChild(document.createTextNode(catsList[i]));
selFilter.appendChild(o);
}
var j;
for (j = 0; j < selFilter.options.length; j++) {
if (selFilter.options[j].value === CURRENT_FILTER_CATEGORY) {
selFilter.selectedIndex = j;
break;
}
}
}
var tid;
for (tid in data) {
if (!data.hasOwnProperty(tid)) continue;
var t = data[tid];
var catClean = normalizeCategory(t.category || "");
if (CURRENT_FILTER_CATEGORY === "__blank__") {
if (catClean) continue;
} else if (CURRENT_FILTER_CATEGORY) {
if (catClean !== CURRENT_FILTER_CATEGORY) continue;
}
var row = table.insertRow(-1);
var c1 = row.insertCell(0);
var c2 = row.insertCell(1);
var c3 = row.insertCell(2);
var c4 = row.insertCell(3);
var c5 = row.insertCell(4);
c1.appendChild(document.createTextNode(tid));
c2.appendChild(document.createTextNode(t.task_title || ""));
c3.appendChild(document.createTextNode(catClean || ""));
c4.appendChild(document.createTextNode(t.overall_status || ""));
var btn = document.createElement("span");
btn.className = "btn";
btn.appendChild(document.createTextNode("Phases"));
btn.setAttribute("onclick", "openPhaseEditor('" + tid + "')");
c5.appendChild(btn);
}
});
}
function categoryFilterChanged() {
var sel = document.getElementById("category_filter");
if (!sel) return;
CURRENT_FILTER_CATEGORY = sel.value || "";
loadTasks();
}
function loadTaskCategory(taskId) {
if (!rdb) return;
rdb.ref("Tasks/" + taskId).once("value").then(function (snap) {
var t = snap.val() || {};
var cat = normalizeCategory(t.category || "");
setEditCategoryUI(cat);
});
}
function saveTaskCategory() {
if (!rdb) { alert("Firebase not ready yet."); return; }
if (!CURRENT_TASK) { alert("No task selected."); return; }
var cat = resolveCategory("edit");
rdb.ref("Tasks/" + CURRENT_TASK).update({
category: cat
}).then(function () {
alert("Category updated.");
loadTasks();
}).catch(function (err) {
alert("Error updating category: " + err);
});
}
function openPhaseEditor(taskId) {
CURRENT_TASK = taskId;
var infoDiv = document.getElementById("phase_task_id");
if (infoDiv) {
infoDiv.innerHTML = "<b>Task ID:</b> " + taskId;
}
var box = document.getElementById("phase_box");
if (box) {
box.style.display = "block";
}
loadTaskCategory(taskId);
loadPhases(taskId);
}
function addPhase() {
if (!rdb) { alert("Firebase not ready yet."); return; }
if (!CURRENT_TASK) { alert("No task selected."); return; }
var pnEl = document.getElementById("phase_number");
var psEl = document.getElementById("phase_status");
var descEl = document.getElementById("phase_desc");
var pn = pnEl ? pnEl.value : "";
var ps = psEl ? psEl.value : "";
var desc = descEl ? descEl.value : "";
if (!pn) { alert("Choose phase number."); return; }
if (!ps) { alert("Choose phase status."); return; }
var phaseId = (new Date().getTime()).toString();
var updates = {};
updates["TaskPhases/" + CURRENT_TASK + "/" + phaseId] = true;
updates["PhaseDetails/" + phaseId] = {
task_id: CURRENT_TASK,
phase_number: pn,
phase_status: ps,
phase_description: desc
};
rdb.ref().update(updates).then(function () {
updateOverallStatus(CURRENT_TASK);
loadPhases(CURRENT_TASK);
alert("Phase added.");
if (descEl) descEl.value = "";
}).catch(function (err) {
alert("Error adding phase: " + err);
});
}
function loadPhases(taskId) {
var table = document.getElementById("phase_table");
if (!table || !rdb) return;
table.innerHTML =
"<tr>" +
"<th>Phase</th>" +
"<th>Status</th>" +
"<th>Description</th>" +
"</tr>";
rdb.ref("TaskPhases/" + taskId).once("value").then(function (snap) {
var map = snap.val();
if (!map) return;
var pid;
for (pid in map) {
if (!map.hasOwnProperty(pid)) continue;
(function (pidCopy) {
rdb.ref("PhaseDetails/" + pidCopy).once("value").then(function (psnap) {
var ph = psnap.val();
if (!ph) return;
var row = table.insertRow(-1);
var c1 = row.insertCell(0);
var c2 = row.insertCell(1);
var c3 = row.insertCell(2);
c1.appendChild(document.createTextNode(ph.phase_number || ""));
c2.appendChild(document.createTextNode(ph.phase_status || ""));
c3.appendChild(document.createTextNode(ph.phase_description || ""));
});
})(pid);
}
});
}
function updateOverallStatus(taskId) {
if (!rdb) return;
var phaseListRef = rdb.ref("TaskPhases/" + taskId);
phaseListRef.once("value").then(function (snapshot) {
var phaseIds = snapshot.val();
if (!phaseIds) return;
var total = 0;
var doneCount = 0;
var promises = [];
var pid;
for (pid in phaseIds) {
if (!phaseIds.hasOwnProperty(pid)) continue;
(function (pidCopy) {
var p = rdb.ref("PhaseDetails/" + pidCopy).once("value").then(function (ps) {
var v = ps.val();
total++;
if (v && v.phase_status === "done!") {
doneCount++;
}
});
promises.push(p);
})(pid);
}
Promise.all(promises).then(function () {
var newStatus = (total > 0 && total === doneCount) ? "finished" : "ongoing";
rdb.ref("Tasks/" + taskId).update({ overall_status: newStatus }).then(function () {
loadTasks();
});
});
});
}
function importSheet() {
if (!rdb) { alert("Firebase not ready yet."); return; }
var input = document.getElementById("file_input");
if (!input || !input.files || input.files.length === 0) {
alert("Please choose a file first.");
return;
}
var file = input.files[0];
var reader = new FileReader();
reader.onload = function (e) {
var data = new Uint8Array(e.target.result);
var workbook = XLSX.read(data, { type: "array" });
var firstSheetName = workbook.SheetNames[0];
var ws = workbook.Sheets[firstSheetName];
var rows = XLSX.utils.sheet_to_json(ws, { defval: "" });
if (!rows || rows.length === 0) {
alert("Sheet is empty or headers are missing.");
return;
}
var i;
for (i = 0; i < rows.length; i++) {
var row = rows[i];
var title = row["Title"] || "";
if (!title) continue;
var phaseNumber = row["Phase Number"] || "1st phase";
var phaseStatus = row["Phase Status"] || "not yet";
var desc = row["Description"] || "";
var categoryRaw = row["Category"] || "";
var category = normalizeCategory(categoryRaw);
var taskId = (new Date().getTime()).toString() + "_" + i;
var phaseId = (new Date().getTime() + i + 1).toString();
var updates = {};
updates["Tasks/" + taskId] = {
task_title: title,
category: category,
overall_status: "ongoing"
};
updates["TaskPhases/" + taskId + "/" + phaseId] = true;
updates["PhaseDetails/" + phaseId] = {
task_id: taskId,
phase_number: phaseNumber,
phase_status: phaseStatus,
phase_description: desc
};
rdb.ref().update(updates);
updateOverallStatus(taskId);
}
alert("Import finished. Check Task List.");
loadTasks();
};
reader.readAsArrayBuffer(file);
}
window.createTask = createTask;
window.openPhaseEditor = openPhaseEditor;
window.addPhase = addPhase;
window.importSheet = importSheet;
window.categoryFilterChanged = categoryFilterChanged;
window.addCategory = addCategory;
window.deleteCategory = deleteCategory;
window.onCategorySelectChange = onCategorySelectChange;
window.saveTaskCategory = saveTaskCategory;
function initApp() {
setupPhaseDropdowns();
loadCategories();
}
if (document.readyState === "complete" || document.readyState === "interactive") {
setTimeout(initApp, 0);
} else {
document.addEventListener("DOMContentLoaded", initApp);
}
})();
//]]>
</script>
Comments
Post a Comment