Skip to main content

SOURCE CODE: JOBs DONE REPORT versi MOBILE-PURPOSE aka +Bootstrap

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

<!-- BOOTSTRAP CSS (BLOGGER-SAFE VERSION) -->

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

<link rel="stylesheet"

 href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"/>


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

<!-- FIREBASE (BLOGGER-SAFE VERSION) -->

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

<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.initializeApp({

  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"

});

var dbRef = firebase.database().ref("JobDoneData");

</script>


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

<!-- MOBILE-FIRST RESPONSIVE CSS (BLOGGER SAFE) -->

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

<style>

@media (max-width: 575px) {

  .desktop-view { display:none !important; }

  .mobile-view { display:block !important; }

}

@media (min-width: 576px) {

  .desktop-view { display:block !important; }

  .mobile-view { display:none !important; }

}


.date-month {

  font-weight: bold;

  font-size: 1.05rem;

  display: block;

}

.date-year {

  display: block;

  margin-top: -4px;

  font-size: 0.85rem;

  color: #666;

}


.icon-btn {

  font-size: 22px;

  cursor: pointer;

  margin-right: 10px;

}


.glass-modal {

  position:fixed; left:0; top:0;

  width:100%; height:100%;

  background:rgba(0,0,0,0.55);

  display:none; justify-content:center; align-items:center;

  z-index:9999;

}

.glass-modal-content {

  background:white;

  padding:20px; border-radius:12px;

  width:90%; max-width:420px;

}

</style>


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

<!-- ADD NEW RECORD (BOOTSTRAP FORM) -->

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

<div class="container my-3">

  <div class="card shadow-sm">

    <div class="card-body">

      <h4 class="mb-3">➕ Add Job Done</h4>


      <label class="form-label fw-bold">Month</label>

      <select id="monthSelect" class="form-select mb-3"></select>


      <label class="form-label fw-bold">Year</label>

      <select id="yearSelect" class="form-select mb-3"></select>


      <label class="form-label fw-bold">Description</label>

      <textarea id="jobDesc" class="form-control mb-3" rows="3"></textarea>


      <button onclick="addRecord()" class="btn btn-primary w-100">💾 Save</button>

    </div>

  </div>

</div>


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

<!-- SEARCH + SORT -->

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

<div class="container my-3">

  <div class="card shadow-sm">

    <div class="card-body">


      <label class="form-label fw-bold">Search</label>

      <input id="searchInput" onkeyup="renderAll()" class="form-control mb-3" placeholder="Search…"/>


      <label class="form-label fw-bold">Sort</label>

      <select id="sortSelect" onchange="renderAll()" class="form-select">

        <option value="desc">Newest First</option>

        <option value="asc">Oldest First</option>

      </select>


    </div>

  </div>

</div>


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

<!-- DESKTOP TABLE -->

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

<div class="container desktop-view my-3">

  <div class="card shadow-sm">

    <div class="card-body">


      <table class="table table-striped align-middle">

        <thead>

          <tr>

            <th width="150">Date</th>

            <th>Description</th>

            <th width="100">Action</th>

          </tr>

        </thead>

        <tbody id="tableList"></tbody>

      </table>


    </div>

  </div>

</div>


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

<!-- MOBILE CARD VIEW -->

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

<div class="container mobile-view my-3" id="cardList"></div>


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

<!-- MODAL -->

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

<div id="modalGlass" class="glass-modal">

  <div class="glass-modal-content">

    <h4 id="modalTitle"></h4>

    <div id="modalBody" class="mt-2"></div>

    <button onclick="closeModal()" class="btn btn-secondary w-100 mt-3">Close</button>

  </div>

</div>


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

<!-- LOGIC SCRIPT -->

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

<script>

var allData = [];

var monthNames = [

  "January","February","March","April","May","June",

  "July","August","September","October","November","December"

];


function loadMonthYear() {

  var mSel = document.getElementById("monthSelect");

  var ySel = document.getElementById("yearSelect");


  var now = new Date();

  var curM = now.getMonth() + 1;

  var curY = now.getFullYear();


  for (var i=1;i<=12;i++) {

    var opt = document.createElement("option");

    opt.value = i;

    opt.text = monthNames[i-1];

    if (i === curM) opt.selected = true;

    mSel.appendChild(opt);

  }


  for (var y=2023;y<=curY+5;y++) {

    var opt2 = document.createElement("option");

    opt2.value = y;

    opt2.text = y;

    if (y === curY) opt2.selected = true;

    ySel.appendChild(opt2);

  }

}

loadMonthYear();


function addRecord() {

  var m = document.getElementById("monthSelect").value;

  var y = document.getElementById("yearSelect").value;

  var d = document.getElementById("jobDesc").value.trim();


  if (!m || !y || !d) { alert("Please fill all fields"); return; }


  var id = dbRef.push().key;


  dbRef.child(id).set({

    id:id,

    month:parseInt(m),

    year:parseInt(y),

    description:d,

    sortKey:(parseInt(y)*100)+parseInt(m)

  });


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

}


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

  allData = [];

  snap.forEach(function(c){ allData.push(c.val()); });

  renderAll();

});


function renderAll(){

  renderTable();

  renderCards();

}


function renderTable(){

  var tbody = document.getElementById("tableList");

  tbody.innerHTML = "";

  var list = filteredSorted();


  for (var i=0;i<list.length;i++){

    var r=list[i];

    var tr=document.createElement("tr");


    tr.innerHTML = `

      <td>

        <span class="date-month">${monthNames[r.month-1]}</span>

        <span class="date-year">${r.year}</span>

      </td>

      <td>${r.description.replace(/\n/g,"<br>")}</td>

      <td>

        <span class="icon-btn" onclick="viewRec('${r.id}')">👁️</span>

        <span class="icon-btn" onclick="editRec('${r.id}')">✏️</span>

        <span class="icon-btn" onclick="delRec('${r.id}')">🗑️</span>

      </td>

    `;


    tbody.appendChild(tr);

  }

}


function renderCards(){

  var wrap = document.getElementById("cardList");

  wrap.innerHTML = "";

  var list = filteredSorted();


  for (var i=0;i<list.length;i++){

    var r=list[i];

    var card=document.createElement("div");

    card.className="card p-3 mb-3 shadow-sm";


    card.innerHTML = `

      <h6><b>${monthNames[r.month-1]} ${r.year}</b></h6>

      <p>${r.description.replace(/\n/g,"<br>")}</p>

      <span class="icon-btn" onclick="viewRec('${r.id}')">👁️</span>

      <span class="icon-btn" onclick="editRec('${r.id}')">✏️</span>

      <span class="icon-btn" onclick="delRec('${r.id}')">🗑️</span>

    `;


    wrap.appendChild(card);

  }

}


function filteredSorted(){

  var s=document.getElementById("searchInput").value.toLowerCase();

  var st=document.getElementById("sortSelect").value;


  var arr=allData.filter(function(d){

    return (monthNames[d.month-1] + " " + d.year + " " + d.description)

      .toLowerCase().includes(s);

  });


  arr.sort(function(a,b){

    return st==="desc" ? b.sortKey-a.sortKey : a.sortKey-b.sortKey;

  });


  return arr;

}


/* RECORD ACTIONS */

function viewRec(id){

  var r=allData.find(function(x){return x.id===id;});

  if (!r) return;


  openModal(

    "View Record",

    monthNames[r.month-1]+" "+r.year+"\n\n"+r.description

  );

}


function editRec(id){

  var r=allData.find(function(x){return x.id===id;});

  if (!r) return;


  var newDesc = prompt("Edit description:", r.description);

  if (newDesc!==null){

    dbRef.child(id).update({description:newDesc});

  }

}


function delRec(id){

  if (confirm("Delete this record?")){

    dbRef.child(id).remove();

  }

}


/* MODAL CONTROL */

function openModal(t,b){

  document.getElementById("modalTitle").textContent=t;

  document.getElementById("modalBody").textContent=b;

  document.getElementById("modalGlass").style.display="flex";

}

function closeModal(){

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

}

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

ONLINE TOOL to Create CUSTOM_PWA ANDROID-APP

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 top alternatives, especially for no-code or low-code users: 🔧 Best Tools Like Median.co to Convert Website to Android Apps 1. WebViewGold Platform: Windows/macOS (Xcode/Android Studio) Key Feature: Converts any website into iOS/Android app via WebView. Pros: One-time purchase Custom splash screen, push notifications ...

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