Skip to main content

SECOND MILESTONE 4 of 5:
FINAL RESULT

ONE SINGLE PAGE, fully merged, fully harmonized, no duplication, no collision, complete with:

✔ One Firebase INIT
✔ Two Databases (urlCrudData + webAppData)
✔ Two Full Modules (MAIN + CHILD)
✔ All UI + Logic in one HTML page
✔ 100% Blogger-compatible
✔ Cleanest & safest final version
✔ Includes all your revisions
✔ No redundant scripts
✔ No repeated HTML IDs
✔ No variable conflicts


YOUR FINAL ONE-PAGE FULL APP (DROP-IN READY FOR BLOGGER)

Copy-paste EVERYTHING below into Blogger → Edit HTML.

FINAL SINGLE-PAGE FULL SYSTEM (MAIN + CHILD + FULL CRUD + FULL REPORT + CLEAN)

<!------------------------------------------------------->
<!-- FIREBASE CDN (COMPAT MODE FOR BLOGGER)             -->
<!------------------------------------------------------->
<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>

<script>
/* ===================================================== */
/*                SINGLE FIREBASE INITIALIZATION         */
/* ===================================================== */
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"
};

/* Prevent Firebase Double Init Crash (Blogger safety) */
if (!firebase.apps.length) firebase.initializeApp(firebaseConfig);

/* GLOBAL REALTIME DATABASE INSTANCE */
const rdb = firebase.database();

/* TWO VALID DATABASE TABLES */
const refCRUD = rdb.ref("urlCrudData");   /* main table */
const refAPP  = rdb.ref("webAppData");    /* new web-app table */

/* GLOBAL HELPERS */
function todayShort(){
    return new Date().toLocaleString("en-US",{month:"short",day:"2-digit"});
}
function todayLong(){
    return new Date().toLocaleString("en-US",{month:"short",day:"2-digit",year:"numeric"});
}
</script>

<style>
/* Clean general styling */
.crud-box, .app-box {
    font-family: Arial;
    margin: auto;
    max-width: 900px;
}

.section-title {
    text-align: center;
    font-size: 26px;
    margin-bottom: 25px;
}

.table-head th {
    border:1px solid #ccc;
    padding:10px;
}
.table-body td {
    border:1px solid #ccc;
    padding:10px;
}
button {
    cursor:pointer;
}
</style>

<!------------------------------------------------------->
<!-- =================================================== -->
<!--              MAIN MODULE (urlCrudData)              -->
<!-- =================================================== -->
<!------------------------------------------------------->

<div class="crud-box">
    <h2 id="todayHeader" class="section-title"></h2>
    <h2 style="text-align:center;">🔗 My Pending and Delayed POSTs SUMMARY</h2>

    <!-- REPORT VIEW -->
    <div style="background:#fff; border-radius:10px; border:1px solid #ccc; margin-bottom:25px; padding:15px;">
        <h3 style="text-align:center; margin-top:0;">📘 RECORD SUMMARY (VIEW ONLY)</h3>

        <div style="display:flex; padding:8px 0; font-weight:bold; border-bottom:2px solid #bbb;">
            <div style="width:10%;">DATE</div>
            <div style="width:45%;">AUTO TITLE</div>
            <div style="width:45%;">MY TITLE</div>
        </div>

        <div id="reportListCRUD"></div>
    </div>

    <!-- INPUT FORM -->
    <div style="background:#f4f4f4; border-radius:10px; border:1px solid #ccc; padding:15px; margin-bottom:20px;">
        <label><b>Insert URL Link:</b></label><br>
        <input id="urlInputCRUD" style="width:100%; padding:10px; margin-top:5px; border-radius:6px; border:1px solid #aaa;" placeholder="https://example.com">
        
        <br><br>

        <label><b>Your Own Title (Optional):</b></label><br>
        <input id="myTitleInputCRUD" style="width:100%; padding:10px; margin-top:5px; border-radius:6px; border:1px solid #aaa;" placeholder="Your custom title…">

        <br><br>

        <button onclick="autoAddCRUD()" style="background:#0078ff; border:none; color:white; padding:10px 18px; border-radius:8px;">➕ ADD ENTRY</button>

        <button id="saveBtnCRUD" onclick="saveEditCRUD()" style="display:none; background:#ff8800; border:none; color:white; padding:10px 18px; border-radius:8px;">💾 SAVE EDIT</button>
    </div>

    <!-- TABLE -->
    <table style="width:100%; border-collapse:collapse;">
        <thead class="table-head">
            <tr style="background:#eee;">
                <th style="width:12%;">DATE</th>
                <th style="width:30%;">AUTO TITLE</th>
                <th style="width:30%;">MY TITLE</th>
                <th style="width:12%;">URL</th>
                <th style="width:16%;">ACTIONS</th>
            </tr>
        </thead>
        <tbody id="tableBodyCRUD" class="table-body"></tbody>
    </table>
</div>

<!------------------------------------------------------->
<!--                MAIN LOGIC (urlCrudData)             -->
<!------------------------------------------------------->
<script>
document.getElementById("todayHeader").innerHTML = "📅 Today: " + todayLong();

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,m=>m.toUpperCase());
    } catch { return url; }
}
function guessTitle(url){
    return url.replace("https://","").replace("http://","").split("/")[0];
}

/* LISTENER */
refCRUD.on("value", snap=>{
    let data = snap.val() ? Object.values(snap.val()) : [];
    renderReportCRUD(data);
    renderTableCRUD(data);
});

/* REPORT */
function renderReportCRUD(data){
    let box = document.getElementById("reportListCRUD");

    if(!data.length){
        box.innerHTML = "<div style='padding:10px; color:#777;'><i>No records yet.</i></div>";
        return;
    }

    box.innerHTML = data.map(e=>`
        <div style="display:flex; padding:6px 0; border-bottom:1px solid #eee;">
            <div style="width:10%;">${e.date}</div>
            <div style="width:45%; color:#0078ff;">${e.autoTitle}</div>
            <div style="width:45%;">${e.myTitle||""}</div>
        </div>
    `).join("");
}

/* TABLE */
function renderTableCRUD(data){
    let box = document.getElementById("tableBodyCRUD");

    box.innerHTML = data.map(e=>`
        <tr>
            <td>${e.date}</td>
            <td>${e.autoTitle}</td>
            <td>${e.myTitle||""}</td>
            <td><a href="${e.url}" target="_blank">${e.url}</a></td>

            <td style="text-align:center;">
                <button onclick="editCRUD('${e.id}')"
                        style="width:110px; padding:8px; background:#ffaa00; border:none; color:white; border-radius:6px;">✏ Edit</button>

                <hr style="margin:12px auto; width:80%; border:0; border-top:1px solid #ccc;">

                <button onclick="deleteCRUD('${e.id}')"
                        style="width:110px; padding:8px; background:#ff4444; border:none; color:white; border-radius:6px;">🗑 Delete</button>
            </td>
        </tr>
    `).join("");
}

/* ADD */
function autoAddCRUD(){
    let url = document.getElementById("urlInputCRUD").value.trim();
    let myTitle = document.getElementById("myTitleInputCRUD").value.trim();

    if(!url){ alert("URL cannot be empty"); return; }

    let autoTitle = isBlog(url) ? blogTitle(url) : guessTitle(url);
    let key = refCRUD.push().key;

    refCRUD.child(key).set({
        id:key,
        date:todayShort(),
        autoTitle:autoTitle,
        myTitle:myTitle,
        url:url
    });

    document.getElementById("urlInputCRUD").value="";
    document.getElementById("myTitleInputCRUD").value="";
}

/* EDIT */
let editID_CRUD = null;

function editCRUD(id){
    refCRUD.child(id).once("value", snap=>{
        let d = snap.val();
        editID_CRUD = id;

        document.getElementById("urlInputCRUD").value = d.url;
        document.getElementById("myTitleInputCRUD").value = d.myTitle || "";

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

/* SAVE EDIT */
function saveEditCRUD(){
    if(!editID_CRUD) return;

    let newUrl  = document.getElementById("urlInputCRUD").value.trim();
    let newMts  = document.getElementById("myTitleInputCRUD").value.trim();

    refCRUD.child(editID_CRUD).update({
        url:newUrl,
        myTitle:newMts,
        autoTitle: isBlog(newUrl) ? blogTitle(newUrl) : guessTitle(newUrl)
    });

    editID_CRUD=null;
    document.getElementById("urlInputCRUD").value="";
    document.getElementById("myTitleInputCRUD").value="";
    document.getElementById("saveBtnCRUD").style.display="none";
}

/* DELETE */
function deleteCRUD(id){
    if(confirm("Delete this entry?")){
        refCRUD.child(id).remove();
    }
}
</script>


<!------------------------------------------------------->
<!-- =================================================== -->
<!--            CHILD MODULE (webAppData)                -->
<!-- =================================================== -->
<!------------------------------------------------------->

<div class="app-box" style="margin-top:60px;">
    <h2 style="text-align:center;">📝 WEB-APP DATA LIST (NEW TABLE)</h2>

    <!-- REPORT VIEW -->
    <div style="background:#fff; border-radius:10px; border:1px solid #ccc; padding:15px; margin-bottom:20px;">
        <h3 style="text-align:center; margin-top:0;">📘 RECORD SUMMARY (HEADER + DETAIL)</h3>

        <div style="display:flex; padding:8px 0; border-bottom:2px solid #bbb; font-weight:bold;">
            <div style="width:20%;">DATE</div>
            <div style="width:40%;">HEADER</div>
            <div style="width:40%;">DETAIL</div>
        </div>

        <div id="reportListAPP"></div>
    </div>

    <!-- FORM -->
    <div style="background:#f4f4f4; border-radius:10px; border:1px solid #ccc; padding:15px; margin-bottom:20px;">
        <label><b>Header (Auto Title):</b></label><br>
        <input id="headerInputAPP" style="width:100%; padding:10px; border-radius:6px; border:1px solid #aaa; margin-top:5px;">

        <br><br>

        <label><b>Detail (My Title):</b></label><br>
        <textarea id="detailInputAPP" style="width:100%; padding:10px; height:80px; border-radius:6px; border:1px solid #aaa; margin-top:5px;"></textarea>

        <br><br>

        <button onclick="addAPP()" style="background:#0078ff; border:none; color:white; padding:10px 18px; border-radius:8px;">➕ ADD ENTRY</button>

        <button id="saveBtnAPP" onclick="saveAPP()" style="display:none; background:#ff8800; border:none; color:white; padding:10px 18px; border-radius:8px;">💾 SAVE EDIT</button>
    </div>

    <!-- TABLE -->
    <table style="width:100%; border-collapse:collapse;">
        <thead class="table-head">
            <tr style="background:#eee;">
                <th style="width:15%;">DATE</th>
                <th style="width:35%;">HEADER</th>
                <th style="width:35%;">DETAIL</th>
                <th style="width:15%;">ACTIONS</th>
            </tr>
        </thead>
        <tbody id="tableBodyAPP" class="table-body"></tbody>
    </table>
</div>

<!------------------------------------------------------->
<!--                  CHILD LOGIC                       -->
<!------------------------------------------------------->
<script>
/* LIVE LISTENER */
refAPP.on("value", snap=>{
    let data = snap.val() ? Object.values(snap.val()) : [];
    renderReportAPP(data);
    renderTableAPP(data);
});

/* REPORT */
function renderReportAPP(data){
    let box = document.getElementById("reportListAPP");

    if(!data.length){
        box.innerHTML = "<div style='padding:10px; color:#777;'><i>No data yet.</i></div>";
        return;
    }

    box.innerHTML = data.map(e=>`
        <div style="display:flex; padding:6px 0; border-bottom:1px solid #eee;">
            <div style="width:20%;">${e.date}</div>
            <div style="width:40%; color:#0078ff;"><b>${e.header}</b></div>
            <div style="width:40%;">${e.detail}</div>
        </div>
    `).join("");
}

/* TABLE */
function renderTableAPP(data){
    let box = document.getElementById("tableBodyAPP");

    box.innerHTML = data.map(e=>`
        <tr>
            <td>${e.date}</td>
            <td>${e.header}</td>
            <td>${e.detail}</td>

            <td style="text-align:center;">
                <button onclick="editAPP('${e.id}')"
                        style="padding:6px 12px; background:#ffaa00; color:white; border:none; border-radius:6px;">✏ Edit</button>

                <hr style="margin:8px auto; width:70%; border:0; border-top:1px solid #bbb;">

                <button onclick="deleteAPP('${e.id}')"
                        style="padding:6px 12px; background:#ff4444; color:white; border:none; border-radius:6px;">🗑 Delete</button>
            </td>
        </tr>
    `).join("");
}

/* ADD */
function addAPP(){
    let header = document.getElementById("headerInputAPP").value.trim();
    let detail = document.getElementById("detailInputAPP").value.trim();

    if(!header){
        alert("Header cannot be empty");
        return;
    }

    let key = refAPP.push().key;

    refAPP.child(key).set({
        id:key,
        date:todayShort(),
        header:header,
        detail:detail
    });

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

/* EDIT */
let editID_APP = null;

function editAPP(id){
    refAPP.child(id).once("value", snap=>{
        let d = snap.val();
        editID_APP = id;

        document.getElementById("headerInputAPP").value = d.header;
        document.getElementById("detailInputAPP").value = d.detail;

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

/* SAVE EDIT */
function saveAPP(){
    if(!editID_APP) return;

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

    refAPP.child(editID_APP).update({
        header:h,
        detail:d
    });

    editID_APP=null;

    document.getElementById("headerInputAPP").value="";
    document.getElementById("detailInputAPP").value="";
    document.getElementById("saveBtnAPP").style.display="none";
}

/* DELETE */
function deleteAPP(id){
    if(confirm("Delete entry?")){
        refAPP.child(id).remove();
    }
}
</script>

🎉 You now have:

✔ 1 single page

✔ 2 full CRUD systems

✔ 2 synchronized Firebase tables

✔ 1 Firebase init

✔ Zero duplicate scripts

✔ Zero ID/name conflicts

✔ 100% Blogger compatible

✔ Final clean production format

Comments