Skip to main content

FIRST MILESTONE: My Pending and Delayed POSTs SUMMARY [SOURCE CODE]

<!------------------------------------------------------->
<!--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>
/* ===================================================== */
/*                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"
};
if (!firebase.apps.length) firebase.initializeApp(firebaseConfig);

const rdb      = firebase.database();
const refCRUD  = rdb.ref("urlCrudData");
const refAPP   = rdb.ref("webAppData");

/* DATE 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"}); }

/* TITLE HELPERS */
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];
}
</script>

<!------------------------------------------------------->
<!--GLOBAL STYLES (RESPONSIVE FLEX GRID)-->
<!------------------------------------------------------->
<style>
body { font-family: Arial; }

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

.res-box {
    margin: auto; max-width: 900px;
    padding-bottom: 40px;
}

/* SEARCH BAR */
.search-bar {
    width: 100%; padding: 10px; border-radius: 6px;
    border:1px solid #aaa; margin-bottom: 15px;
}

/* SORT CONTROLS */
.sort-box {
    display: flex; gap: 10px; margin-bottom: 15px;
}
.sort-box select {
    padding: 8px; border-radius: 6px; border:1px solid #999;
}

/* FLEX TABLE */
.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;
}

/* COLUMN WIDTHS */
.col-date { flex: 0 0 12%; max-width: 12%; padding: 5px; }
.col-auto { flex: 0 0 30%; max-width: 30%; padding: 5px; }
.col-my   { flex: 0 0 30%; max-width: 30%; padding: 5px; }
.col-url  { flex: 0 0 12%; max-width: 12%; padding: 5px; text-align:center; }
.col-act  { flex: 0 0 16%; max-width: 16%; padding: 5px; text-align:center; }

/* LINK BUTTON */
.link-btn {
    background:#0078ff; color:white; padding:6px 12px;
    border-radius:6px; text-decoration:none; display:inline-block;
}

/* ICON BUTTONS */
.icon-btn {
    background:none; border:none; cursor:pointer;
    font-size:20px; margin:6px;
}
.icon-edit  { color:#ffaa00; }
.icon-del   { color:#ff4444; }

/* MOBILE */
@media(max-width:768px){
    .col-date,.col-auto,.col-my,.col-url,.col-act {
        flex:0 0 100%; max-width:100%; text-align:left;
    }
}
</style>

<!------------------------------------------------------->
<!--===================================================-->
<!--PARENT MODULE — urlCrudData-->
<!--===================================================-->
<!------------------------------------------------------->

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

    <!--SEARCH + SORT-->
    <input class="search-bar" id="searchCRUD" placeholder="Search title or URL…" />

    <div class="sort-box">
        <select id="sortByCRUD">
            <option value="date">Sort by Date</option>
            <option value="autoTitle">Sort by Auto Title</option>
            <option value="myTitle">Sort by My Title</option>
        </select>

        <select id="sortOrderCRUD">
            <option value="asc">Ascending</option>
            <option value="desc">Descending</option>
        </select>
    </div>

    <!--INPUT FORM-->
    <div style="background: rgb(244, 244, 244); border-radius: 10px; border: 1px solid rgb(204, 204, 204); margin-bottom: 25px; padding: 15px;">
        <b>Insert URL:</b><br />
        <input id="urlInputCRUD" style="border-radius: 6px; border: 1px solid rgb(170, 170, 170); margin-top: 5px; padding: 10px; width: 100%;" />

        <br /><br />

        <b>Your Own Title (Optional):</b><br />
        <input id="myTitleInputCRUD" style="border-radius: 6px; border: 1px solid rgb(170, 170, 170); margin-top: 5px; padding: 10px; width: 100%;" />

        <br /><br />

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

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

    <!--FLEX TABLE-->
    <div class="responsive-table">
        <div class="responsive-row responsive-head">
            <div class="col-date">DATE</div>
            <div class="col-auto">AUTO TITLE</div>
            <div class="col-my">MY TITLE</div>
            <div class="col-url">URL</div>
            <div class="col-act">ACTIONS</div>
        </div>

        <div id="tableBodyCRUD"></div>
    </div>
</div>

<!------------------------------------------------------->
<!--PARENT LOGIC-->
<!------------------------------------------------------->

<script>
document.getElementById("todayHeader").innerHTML = "📅 Today: " + todayLong();

let crudData = [];

/* REALTIME LISTENER */
refCRUD.on("value", snap=>{
    crudData = snap.val() ? Object.values(snap.val()) : [];
    renderCRUD();
});

/* SEARCH + SORT HANDLER */
document.getElementById("searchCRUD").oninput = renderCRUD;
document.getElementById("sortByCRUD").onchange = renderCRUD;
document.getElementById("sortOrderCRUD").onchange = renderCRUD;

/* MASTER RENDER FUNCTION */
function renderCRUD(){
    let search = document.getElementById("searchCRUD").value.toLowerCase();
    let sortBy = document.getElementById("sortByCRUD").value;
    let order  = document.getElementById("sortOrderCRUD").value;

    let data = crudData.filter(e =>
        (e.autoTitle.toLowerCase().includes(search) ||
         (e.myTitle||"").toLowerCase().includes(search) ||
         e.url.toLowerCase().includes(search))
    );

    data.sort((a,b)=>{
        let x=a[sortBy]||"", y=b[sortBy]||"";
        return order==="asc" ? x.localeCompare(y) : y.localeCompare(x);
    });

    document.getElementById("tableBodyCRUD").innerHTML =
        data.map(e=>`
        <div class="responsive-row">

            <div class="col-date">${e.date}</div>
            <div class="col-auto" style="font-weight:bold;">${e.autoTitle}</div>
            <div class="col-my">${e.myTitle||""}</div>

            <div class="col-url">
                <a href="${e.url}" target="_blank" class="link-btn">LINK</a>
            </div>

            <div class="col-act">
                <button class="icon-btn icon-edit" onclick="editCRUD('${e.id}')">✏</button>
                <button class="icon-btn icon-del" onclick="deleteCRUD('${e.id}')">🗑</button>
            </div>

        </div>`).join("");
}

/* ADD */
function autoAddCRUD(){
    let url = document.getElementById("urlInputCRUD").value.trim();
    let myT = document.getElementById("myTitleInputCRUD").value.trim();
    if(!url){ alert("URL cannot be empty."); return; }

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

    refCRUD.child(key).set({
        id:key, date:todayShort(),
        autoTitle:autoT, myTitle:myT,
        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";
    });
}
function saveEditCRUD(){
    if(!editID_CRUD) return;

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

    refCRUD.child(editID_CRUD).update({
        url:newUrl,
        myTitle:newMyT,
        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="res-box">
    <h2 class="section-title" style="text-align: center;">📝 TO DO LIST SUMMARY&nbsp;</h2>

    <!--SEARCH + SORT-->
    <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 value="desc">Descending</option>
        </select>
    </div>

    <!--FORM-->
    <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 />

        <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
        </button>
    </div>

    <!--FLEX TABLE-->
    <div class="responsive-table">
        <div class="responsive-row responsive-head">
            <div class="col-date">DATE</div>
            <div class="col-auto">HEADER</div>
            <div class="col-my">DETAIL</div>
            <div class="col-act">ACTIONS</div>
        </div>

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

<!------------------------------------------------------->
<!--CHILD LOGIC-->
<!------------------------------------------------------->

<script>
let appData=[];

/* LIVE LISTENER */
refAPP.on("value", snap=>{
    appData = snap.val()? Object.values(snap.val()) : [];
    renderAPP();
});

/* SEARCH + SORT LISTENERS */
document.getElementById("searchAPP").oninput=renderAPP;
document.getElementById("sortByAPP").onchange=renderAPP;
document.getElementById("sortOrderAPP").onchange=renderAPP;

/* MAIN RENDER */
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(e =>
        (e.header.toLowerCase().includes(search) ||
         e.detail.toLowerCase().includes(search))
    );

    data.sort((a,b)=>{
        let x=a[sortBy]||"", y=b[sortBy]||"";
        return order==="asc"? x.localeCompare(y) : y.localeCompare(x);
    });

    document.getElementById("tableBodyAPP").innerHTML =
        data.map(e=>`
        <div class="responsive-row">

            <div class="col-date">${e.date}</div>
            <div class="col-auto" style="font-weight:bold;">${e.header}</div>          
            <div class="col-my">${e.detail}</div>

            <div class="col-act">
                <button class="icon-btn icon-edit" onclick="editAPP('${e.id}')">✏</button>
                <button class="icon-btn icon-del" onclick="deleteAPP('${e.id}')">🗑</button>
            </div>

        </div>
    `).join("");
}

/* ADD */
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;

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

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

/* EDIT */
let editID_APP=null;
function editAPP(id){
    refAPP.child(id).once("value", snap=>{
        let v=snap.val();
        editID_APP=id;

        document.getElementById("headerInputAPP").value=v.header;
        document.getElementById("detailInputAPP").value=v.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>

Comments

Popular posts from this blog

Utk yg mo Bantu2 Keuangan saya
..monggo ke Bank Central Asia BCA 5520166779 a.n. Andreas Tparlaungan Manurung (Indonesia)


For those who would like to help support my finances
..please feel free to send it to Bank Central Asia (BCA) account number 5520166779 under the name Andreas Tparlaungan Manurung (Indonesia)

ANDREAS TOMMY PARLAUNGAN MANURUNG SHARED POOLING ACCOUNT MY ANDROID APKs PAGE please download here! REFRESH PAGE aka CHECK LATEST UPDATE! DOWNLOAD "SHOWING" POOL OF MY ANDROID-APK(s) aka APK CONTAINING LIST OF ALL MY ANDROID-APK(s) APP CLICK HERE FOR ALWAYS BEING UPDATED FOR MY LATEST APK! CONTOH HASIL "PROGRAM" App: Prompts' Guide aka TEMPLATE-HELPERs click here to download! Youtube and Instagram EMBEDded to Blogger/Blogspot.com SOURCE CODE Click this box to download 📥 TikTok EMBEDded to Blogger/Blogspot.com SOURCE CODE Input: BrowserLINK (mandatory) Click this box to download SHORTCUT-APPs note :  "precise" click to download R8: ronin1985.blogspot.com R2M: ronin-manu.blogspot.com Helping Download(ing) OnlineVIDEO! ...

Donation Account + CustomAPPs

Utk yg mo Bantu2 Keuangan saya ..monggo ke Bank Central Asia BCA 5520166779 a.n. Andreas Tparlaungan Manurung (Indonesia) For those who would like to help support my finances ..please feel free to send it to Bank Central Asia (BCA) account number 5520166779 under the name Andreas Tparlaungan Manurung (Indonesia). Web-Based to Android Apps Convertion (MEDIAN.CO etc.) CONTOH HASIL Android APK "PROGRAM" SAMPLE: Youtube and Instagram EMBEDded to Blogger/Blogspot.com SOURCE CODE Click this box to download Contoh Sample SHORTCUT-APPs "precise" click to download : median.co R8: ronin1985.blogspot.com R2M: ronin-manu.blogspot.com Gw udah coba Median.co utk mengubah Website gw menjadi Aplikasi Android Keren bet!! Median.co Cekidot Software lain yg mirip! ChatGPT : If you're looking for tools similar to Median.co to convert websites into Android apps, here are some...

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