Skip to main content

SOURCE CODE: TO DO LIST SUMMARY (Made by ChatGPT)

 <!--CHILD FINAL SNIPPET (webAppData)-->

<!--======================================-->

<!--1. GLOBAL STYLES (CSS)-->

<!--======================================-->

<style>

body {

    font-family: Arial, sans-serif;

}

.section-title {

    text-align: center;

    font-size: 26px;

    margin-bottom: 25px;

}

.res-box {

    margin: auto;

    max-width: 900px;

    padding-bottom: 40px;

}

.search-bar {

    width: 100%;

    padding: 10px;

    border-radius: 6px;

    border: 1px solid #aaa;

    margin-bottom: 15px;

}

.sort-box {

    display: flex;

    gap: 10px;

    margin-bottom: 15px;

}

.sort-box select {

    padding: 8px;

    border-radius: 6px;

    border: 1px solid #999;

}

.responsive-table {

    width: 100%;

    display: block;

}

.responsive-row {

    display: flex;

    flex-wrap: wrap;

    border-bottom: 1px solid #ccc;

    padding: 10px 0;

}

.responsive-head {

    background: #eee;

    font-weight: bold;

}

.col-date   { flex: 0 0 18%; max-width: 18%; padding: 5px; }

.col-status { flex: 0 0 10%; max-width: 10%; padding: 5px; text-align:center; }

.col-auto   { flex: 0 0 26%; max-width: 26%; padding: 5px; }

.col-my     { flex: 0 0 26%; max-width: 26%; padding: 5px; }

.col-url    { flex: 0 0 10%; max-width: 10%; padding: 5px; text-align:center; }

.col-act    { flex: 0 0 10%; max-width: 10%; padding: 5px; text-align:center; }

.link-btn {

    background: #0078ff;

    color: white;

    padding: 6px 12px;

    border-radius: 6px;

    text-decoration: none;

    display: inline-block;

}

.icon-btn {

    background: none;

    border: none;

    cursor: pointer;

    font-size: 20px;

    margin: 6px;

}

.icon-edit  { color: #ffaa00; }

.icon-del   { color: #ff4444; }

.done-row {

    background: #c2e6c2;

}

.inline-edit-row {

    display: none;

    width: 100%;

    box-sizing: border-box;

}

.inline-edit-inner {

    background: #f4f4f4;

    border: 1px solid #ccc;

    border-radius: 8px;

    padding: 10px;

    margin: 8px 0 4px 0;

}

.inline-edit-inner b {

    display: block;

    margin-bottom: 6px;

}

.inline-edit-inner input,

.inline-edit-inner textarea,

.inline-edit-inner select {

    width: 100%;

    padding: 6px;

    margin: 4px 0 10px 0;

    box-sizing: border-box;

    border-radius: 5px;

    border: 1px solid #aaa;

}

.inline-btn-row {

    display: flex;

    gap: 10px;

    flex-wrap: wrap;

}

.status-box {

    display: flex;

    align-items: center;

    gap: 25px;

    padding: 8px 14px;

    border: 1px solid #ccc;

    border-radius: 10px;

    background: #f5f5f5;

    width: max-content;

    margin: 6px 0;

}

.status-box label {

    display: flex;

    align-items: center;

    gap: 6px;

    font-size: 15px;

    white-space: nowrap;

}

.inline-edit-inner .status-box {

    margin-top: 10px;

}

@media (max-width: 768px) {

    .col-date,

    .col-status,

    .col-auto,

    .col-my,

    .col-url,

    .col-act {

        flex: 0 0 100%;

        max-width: 100%;

        text-align: left;

    }

}

</style>


<!--======================================-->

<!--2. FIREBASE CDN-->

<!--======================================-->

<script src="https://www.gstatic.com/firebasejs/9.22.2/firebase-app-compat.js"></script>

<script src="https://www.gstatic.com/firebasejs/9.22.2/firebase-database-compat.js"></script>


<!--======================================-->

<!--3. FIREBASE CONFIG + HELPERS-->

<!--======================================-->

<script>

const firebaseConfig = {

    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"

};

if (!firebase.apps.length) firebase.initializeApp(firebaseConfig);


const rdb     = firebase.database();

const refCRUD = rdb.ref("urlCrudData");

const refAPP  = rdb.ref("webAppData");


function nowDateTime() {

    const d  = new Date();

    const yy = d.getFullYear();

    const mm = String(d.getMonth() + 1).padStart(2, "0");

    const dd = String(d.getDate()).padStart(2, "0");

    const hh = String(d.getHours()).padStart(2, "0");

    const mi = String(d.getMinutes()).padStart(2, "0");

    const ss = String(d.getSeconds()).padStart(2, "0");

    return yy + "-" + mm + "-" + dd + " " + hh + ":" + mi + ":" + ss;

}

function todayLong() {

    return new Date().toLocaleString("en-US", {

        month: "short",

        day: "2-digit",

        year: "numeric"

    });

}

function formatDateWithFallback(val) {

    if (!val) return "";

    if (val.includes(":")) return val;

    return val + " 00:00:00";

}

function parseDateSafe(val) {

    if (!val) return 0;

    const t = Date.parse(val);

    if (!isNaN(t)) return t;

    return 0;

}

function isBlog(url) { 

    return url.includes("ronin1985.blogspot.com");

}

function blogTitle(url) {

    try {

        let last = url.split("/").pop().replace(".html", "");

        return last

            .replace(/[-_]+/g, " ")

            .replace(/\b\w/g, function(m){ return m.toUpperCase(); });

    } catch (e) {

        return url;

    }

}

function guessTitle(url) {

    return url.replace("https://", "").replace("http://", "").split("/")[0];

}

</script>


<!--======================================-->

<!--CHILD MODULE — webAppData (To-Do)-->

<!--======================================-->


<div class="res-box">

    <h2 class="section-title" style="text-align: center;">📝 TO DO LIST SUMMARY</h2>


    <input class="search-bar" id="searchAPP" placeholder="Search header or detail…" />


    <div class="sort-box">

        <select id="sortByAPP">

            <option value="date">Sort by Date</option>

            <option value="header">Sort by Header</option>

            <option value="detail">Sort by Detail</option>

        </select>


        <select id="sortOrderAPP">

            <option value="asc">Ascending</option>

            <option selected="" value="desc">Descending (Newest First)</option>

        </select>

    </div>


    <div style="background: rgb(244, 244, 244); border-radius: 10px; border: 1px solid rgb(204, 204, 204); margin-bottom: 25px; padding: 15px;">

        <b>Header (Title):</b><br />

        <input id="headerInputAPP" style="border-radius: 6px; border: 1px solid rgb(170, 170, 170); margin-top: 5px; padding: 10px; width: 100%;" />


        <br /><br />


        <b>Detail:</b><br />

        <textarea id="detailInputAPP" style="border-radius: 6px; border: 1px solid rgb(170, 170, 170); height: 80px; margin-top: 5px; padding: 10px; width: 100%;"></textarea>


        <br /><br />


        <b>Status:</b><br />

        <div class="status-box">

            <label>

                <input checked="" name="statusAPP" type="radio" value="PENDING" /> Pending

            </label>

            <label>

                <input name="statusAPP" type="radio" value="DONE" /> Done

            </label>

        </div>


        <br />


        <button onclick="addAPP()" style="background: rgb(0, 120, 255); border-radius: 8px; border: none; color: white; padding: 10px 18px;">

            ➕ ADD ENTRY

        </button>


        <button id="saveBtnAPP" onclick="saveAPP()" style="background: rgb(255, 170, 0); border-radius: 8px; border: none; color: white; display: none; padding: 10px 18px;">

            💾 SAVE EDIT (MAIN FORM)

        </button>

    </div>


    <div class="responsive-table">

        <div class="responsive-row responsive-head">

            <div class="col-date">DATE / TIME</div>

            <div class="col-auto">HEADER</div>

            <div class="col-my">DETAIL</div>

            <div class="col-status">STATUS</div>

            <div class="col-act">ACTIONS</div>

        </div>

        <div id="tableBodyAPP"></div>

    </div>

</div>


<script>

let appData           = [];

let currentEditID_APP = null;


refAPP.on("value", function(snap){

    appData = snap.val() ? Object.values(snap.val()) : [];

    renderAPP();

});


document.getElementById("searchAPP").oninput    = renderAPP;

document.getElementById("sortByAPP").onchange   = renderAPP;

document.getElementById("sortOrderAPP").onchange= renderAPP;


function getStatusAPP(){

    const radios = document.querySelectorAll('input[name="statusAPP"]');

    for (const r of radios) {

        if (r.checked) return r.value;

    }

    return "PENDING";

}

function findAPPById(id){

    return appData.find(function(e){ return e.id === id; }) || null;

}

function closeAllInlineAPP(){

    appData.forEach(function(e){

        const box = document.getElementById("inlineAPP-" + e.id);

        if (box) box.style.display = "none";

    });

}

function eVal(obj, key){

    return obj[key];

}


function renderAPP(){

    let search = document.getElementById("searchAPP").value.toLowerCase();

    let sortBy = document.getElementById("sortByAPP").value;

    let order  = document.getElementById("sortOrderAPP").value;


    let data = appData.filter(function(e){

        const h = (e.header || "").toLowerCase();

        const d = (e.detail || "").toLowerCase();

        return h.includes(search) || d.includes(search);

    });


    data.sort(function(a,b){

        if (sortBy === "date") {

            const x = parseDateSafe(a.date);

            const y = parseDateSafe(b.date);

            return (order === "asc") ? (x - y) : (y - x);

        } else {

            let x = (eVal(a, sortBy) || "").toString().toLowerCase();

            let y = (eVal(b, sortBy) || "").toString().toLowerCase();

            return (order === "asc") ? x.localeCompare(y) : y.localeCompare(x);

        }

    });


    let html = "";

    data.forEach(function(e){

        const statusLabel = e.status || "PENDING";

        const rowClass    = (statusLabel === "DONE") ? "responsive-row done-row" : "responsive-row";


        html += ""

        + "<div class='" + rowClass + "'>"

        +   "<div class='col-date'>" + formatDateWithFallback(e.date) + "</div>"

        +   "<div class='col-auto' style='font-weight:bold;'>" + (e.header || "") + "</div>"

        +   "<div class='col-my'>"   + (e.detail || "") + "</div>"

        +   "<div class='col-status'><span>" + statusLabel + "</span></div>"

        +   "<div class='col-act'>"

        +       "<button class='icon-btn icon-edit' onclick=\"openInlineAPP('" + e.id + "')\">✏</button>"

        +       "<button class='icon-btn icon-del'  onclick=\"deleteAPP('" + e.id + "')\">🗑</button>"

        +   "</div>"

        + "</div>"

        + "<div class='inline-edit-row' id='inlineAPP-" + e.id + "'>"

        +   "<div class='inline-edit-inner'>"

        +       "<b>Inline Edit — TO DO ITEM</b>"

        +       "<label>Header (Title):</label>"

        +       "<input id='inlineAPP-header-" + e.id + "' value='" + (e.header || "") + "' />"

        +       "<label>Detail:</label>"

        +       "<textarea id='inlineAPP-detail-" + e.id + "'>" + (e.detail || "") + "</textarea>"

        +       "<label>Status:</label>"

        +       "<div class='status-box'>"

        +         "<label><input type='radio' name='inlineAPP-status-" + e.id + "' value='PENDING'" + (statusLabel === "PENDING" ? " checked" : "") + "> Pending</label>"

        +         "<label><input type='radio' name='inlineAPP-status-" + e.id + "' value='DONE'"    + (statusLabel === "DONE"    ? " checked" : "") + "> Done</label>"

        +       "</div>"

        +       "<div class='inline-btn-row'>"

        +           "<button onclick=\"saveInlineAPP('" + e.id + "')\">💾 Save Inline</button>"

        +           "<button onclick=\"closeInlineAPP('" + e.id + "')\">✖ Cancel</button>"

        +       "</div>"

        +   "</div>"

        + "</div>";

    });


    document.getElementById("tableBodyAPP").innerHTML = html;

}


function addAPP(){

    let h = document.getElementById("headerInputAPP").value.trim();

    let d = document.getElementById("detailInputAPP").value.trim();


    if (!h){

        alert("Header cannot be empty.");

        return;

    }


    let key    = refAPP.push().key;

    let status = getStatusAPP();


    refAPP.child(key).set({

        id:     key,

        date:   nowDateTime(),

        header: h,

        detail: d,

        status: status

    });


    document.getElementById("headerInputAPP").value = "";

    document.getElementById("detailInputAPP").value = "";

}


function openInlineAPP(id){

    const rec = findAPPById(id);

    if (!rec) return;


    currentEditID_APP = id;

    closeAllInlineAPP();


    const box = document.getElementById("inlineAPP-" + id);

    if (box) box.style.display = "block";


    const hInput = document.getElementById("inlineAPP-header-" + id);

    const dInput = document.getElementById("inlineAPP-detail-" + id);

    if (hInput) hInput.value = rec.header || "";

    if (dInput) dInput.value = rec.detail || "";


    const radios = document.querySelectorAll("input[name='inlineAPP-status-" + id + "']");

    radios.forEach(function(r){

        r.checked = (r.value === (rec.status || "PENDING"));

    });


    document.getElementById("headerInputAPP").value = rec.header || "";

    document.getElementById("detailInputAPP").value = rec.detail || "";

    document.getElementById("saveBtnAPP").style.display = "inline-block";


    const mainStatus = rec.status || "PENDING";

    const mainRadios = document.querySelectorAll('input[name="statusAPP"]');

    mainRadios.forEach(function(r){

        r.checked = (r.value === mainStatus);

    });

}


function closeInlineAPP(id){

    const box = document.getElementById("inlineAPP-" + id);

    if (box) box.style.display = "none";

}


function saveAPP(){

    if (!currentEditID_APP){

        alert("No record selected for editing (click ✏ Edit first).");

        return;

    }

    let h      = document.getElementById("headerInputAPP").value.trim();

    let d      = document.getElementById("detailInputAPP").value.trim();

    let status = getStatusAPP();


    refAPP.child(currentEditID_APP).update({

        header: h,

        detail: d,

        status: status

    });


    currentEditID_APP = null;


    document.getElementById("headerInputAPP").value = "";

    document.getElementById("detailInputAPP").value = "";

    document.getElementById("saveBtnAPP").style.display = "none";

    closeAllInlineAPP();

}


function saveInlineAPP(id){

    const hInput = document.getElementById("inlineAPP-header-" + id);

    const dInput = document.getElementById("inlineAPP-detail-" + id);

    if (!hInput || !dInput) return;


    const radios = document.querySelectorAll("input[name='inlineAPP-status-" + id + "']");

    let st = "PENDING";

    radios.forEach(function(r){

        if (r.checked) st = r.value;

    });


    const h = hInput.value.trim();

    const d = dInput.value.trim();


    refAPP.child(id).update({

        header: h,

        detail: d,

        status: st

    });


    currentEditID_APP = null;

    document.getElementById("headerInputAPP").value = "";

    document.getElementById("detailInputAPP").value = "";

    document.getElementById("saveBtnAPP").style.display = "none";

    closeInlineAPP(id);

}


function deleteAPP(id){

    if (confirm("Delete entry?")){

        refAPP.child(id).remove();

    }

}

</script>


Comments

Popular posts from this blog

PART 0.1.0 RAD PROTOTYPE Web-App: Post-Video & Comments [program]

Video List — JP Kanji Ultra Translation CONTROL SECTION — Login (Admin) Username: Password: Login CONTROL SECTION — Admin Panel Enable Comments Disable Comments Logout Activity Log Show Video COMMENTS DISABLED BY ADMIN Leave a Comment: Additional Comment Show Video COMMENTS DISABLED BY ADMIN Leave a Comment: Additional Comment Show Video COMMENTS DISABLED BY ADMIN Leave a Comment: Additional Comment Show Video COMMENTS DISABLED BY ADMIN Leave a Comment: Additional Comment

My Pending and Delayed POSTs SUMMARY [APPs]
MADE by ChatGPT

🔗 My Pending and Delayed POSTs SUMMARY Sort by Date Sort by Auto Title Sort by My Title Ascending Descending (Newest First) Insert URL: Your Own Title (Optional): Status: Pending Done ➕ ADD ENTRY 💾 SAVE EDIT (MAIN FORM) DATE / TIME AUTO TITLE MY TITLE STATUS URL ACTIONS 📝 TO DO LIST SUMMARY Sort by Date Sort by Header Sort by Detail ...

REPOST: Studying WATER PUMP by ROMAN ENGINEERING

*^ Ini yg Asli Gan! Mekanisme pada Concrete Pump: Kok ky Sistem Mekanik Romawi ya?! Tapi malah bisa HANYA pake PER aka bukan "MATA BOR look a like" Mekanisme Drill yg Cost Pembuatan bikin REPOT aka harus Tool SUPER Khusus Dari Material Besi yg digunakan terlihat langsung secara kasat mata Jauh Lebih Banyak drpd Per Biasa seperti yg ditunjukkan pd Video Alternatif dgn Penggunaan PER Video dr Instagram: Source: YouTube Rome's drainage machines #history #romanempire #engineering