{"id":7279,"date":"2025-09-18T10:57:23","date_gmt":"2025-09-18T03:57:23","guid":{"rendered":"https:\/\/labamu.co.id\/events\/"},"modified":"2025-12-08T14:08:46","modified_gmt":"2025-12-08T07:08:46","slug":"events","status":"publish","type":"page","link":"https:\/\/labamu.co.id\/en\/events\/","title":{"rendered":"Events"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"7279\" class=\"elementor elementor-7279 elementor-518\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-dd8a5df e-flex e-con-boxed e-con e-parent\" data-id=\"dd8a5df\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t<div class=\"elementor-element elementor-element-4387920 e-con-full e-flex e-con e-child\" data-id=\"4387920\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-0efbeb2 e-con-full e-flex elementor-invisible e-con e-child\" data-id=\"0efbeb2\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;animation&quot;:&quot;fadeInLeft&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-3dc7c8e elementor-widget elementor-widget-heading\" data-id=\"3dc7c8e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Labamu Exclusive Event Experience<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-f6476b8 elementor-widget elementor-widget-text-editor\" data-id=\"f6476b8\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p class=\"p1\">Join us for an inspiring experience filled with ideas, collaboration, and meaningful connections.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-3395755 e-flex e-con-boxed e-con e-parent\" data-id=\"3395755\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-31e5e9a elementor-widget elementor-widget-html\" data-id=\"31e5e9a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<style>\n    \/* Wrapper *\/\n    \n    .post-grid-wrapper {\n        max-width: 1200px;\n        margin: 0 auto;\n        padding: 20px;\n        font-family: sans-serif;\n    }\n    \/* Dropdown + search *\/\n    \n    .post-filter {\n        margin-bottom: 20px;\n        display: flex;\n        justify-content: space-between;\n        \/* kiri - kanan *\/\n        align-items: center;\n        flex-wrap: wrap;\n        \/* biar turun ke bawah di layar kecil *\/\n        gap: 20px;\n    }\n    \/* Kiri *\/\n    \n    .filter-left {\n        display: flex;\n        align-items: center;\n        gap: 15px;\n    }\n    \/* Kanan *\/\n    \n    .filter-right {\n        display: flex;\n        align-items: center;\n        gap: 10px;\n    }\n    \n    .post-filter label {\n        font-size: 0.95rem;\n        margin: 0;\n        color: #333;\n        white-space: nowrap;\n    }\n    \/* Dropdown *\/\n    \n    .post-filter select {\n        padding: 8px 12px;\n        border-radius: 6px;\n        border: 1px solid #ccc;\n        font-size: 0.95rem;\n        background: #fff;\n    }\n    \n    .search-wrapper {\n    position: relative;\n    display: inline-flex;\n    align-items: center;\n    width: 100%;\n    max-width: 280px; \/* control size *\/\n  }\n  \n  .search-wrapper input {\n    width: 100%;\n    padding: 10px 38px 10px 14px; \/* extra space for icon *\/\n    border-radius: 8px;\n    border: 1px solid #dcdcdc;\n    font-size: 0.95rem;\n    background: #fff;\n    color: #333;\n    transition: all 0.25s ease;\n    box-shadow: 0 1px 2px rgba(0,0,0,0.05);\n  }\n  \n  .search-wrapper input::placeholder {\n    color: #999;\n    font-size: 0.9rem;\n  }\n  \n  .search-wrapper input:hover {\n    border-color: #aaa;\n    background: #fafafa;\n  }\n  \n  .search-wrapper input:focus {\n    border-color: #006bff;\n    background: #fff;\n    box-shadow: 0 0 0 3px rgba(0,107,255,0.2);\n    outline: none;\n  }\n  \n  .search-wrapper .search-icon {\n    position: absolute;\n    right: 12px;\n    top: 50%;\n    transform: translateY(-50%);\n    color: #777;\n    font-size: 1rem;\n    pointer-events: none; \/* so clicks still focus input *\/\n  }\n    \/* Grid layout *\/\n    \n    .post-grid {\n        --gap: 20px;\n        display: grid;\n        gap: var(--gap);\n        grid-template-columns: repeat(1, 1fr);\n    }\n    \n    @media (min-width: 600px) {\n        .post-grid {\n            grid-template-columns: repeat(2, 1fr);\n        }\n    }\n    \n    @media (min-width: 960px) {\n        .post-grid {\n            grid-template-columns: repeat(3, 1fr);\n        }\n    }\n    \/* Card style *\/\n    \n    .post-card {\n        background: #fff;\n        border-radius: 12px;\n        overflow: hidden;\n        box-shadow: 0 4px 4px rgba(0, 0, 0, 0.1);\n        display: flex;\n        flex-direction: column;\n        transition: transform 0.2s ease, box-shadow 0.2s ease;\n    }\n    \n    .post-card:hover {\n        transform: translateY(-4px);\n        box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15);\n    }\n    \n    .post-card img {\n        width: 100%;\n        aspect-ratio: 16\/9;\n        object-fit: cover;\n        display: block;\n    }\n    \n    .post-card .card-body {\n        padding: 18px;\n        text-align: center;\n        flex: 1;\n        display: flex;\n        flex-direction: column;\n        gap: 12px;\n    }\n    \n    .post-card h3 {\n        margin: 0;\n        font-size: 1.2rem;\n        font-weight: 600;\n        color: #111;\n        display: -webkit-box;\n        -webkit-line-clamp: 2;\n        \/* maksimal 2 baris *\/\n        -webkit-box-orient: vertical;\n        overflow: hidden;\n        text-overflow: ellipsis;\n    }\n    \n    .post-card .excerpt {\n        font-size: 0.95rem;\n        color: #444;\n        flex-grow: 1;\n    }\n    \n    .post-card .readmore1 .btn-readmore1 {\n        display: inline-block;\n        padding: 10px 20px;\n        border: 1px solid #ccc;\n        border-radius: 6px;\n        text-decoration: none;\n        color: #111;\n        background: #fff;\n        font-size: 0.9rem;\n        transition: background 0.2s, color 0.2s;\n    }\n    \n    .post-card .readmore1 .btn-readmore1:first-child {\n        background: #fff;\n        color: #111;\n    }\n    \n    .post-card .readmore1 .btn-readmore1:first-child:hover {\n        background: #006bff;\n        color: #fff;\n        border-color: #006bff;\n    }\n    \n    .post-card .readmore1 .btn-readmore1 {\n        background: #006bff;\n        color: #fff;\n        border-color: #006bff;\n    }\n    \n    .post-card .readmore1 .btn-readmore1.disabled {\n        background: #ccc;\n        color: #fff;\n        border-color: #ccc;\n        cursor: not-allowed;\n    }\n\n    .post-card .readmore1 .btn-regis {\n        display: inline-block;\n        padding: 10px 20px;\n        border: 1px solid #ccc;\n        border-radius: 6px;\n        text-decoration: none;\n        color: #fff;\n        background: #006bff;\n        font-size: 0.9rem;\n        transition: background 0.2s, color 0.2s;\n    }\n\n    .post-card .readmore1 .btn-regis.disabled {\n        background: #ccc;\n        color: #fff;\n        border-color: #ccc;\n        cursor: not-allowed;\n    }\n\n    .loading {\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  gap: 6px;\n  padding: 20px;\n  font-size: 16px;\n  font-weight: 500;\n  color: #555;\n}\n\n.loading span {\n  width: 10px;\n  height: 10px;\n  background: #0073e6;\n  border-radius: 50%;\n  display: inline-block;\n  animation: bounce 0.6s infinite alternate;\n}\n\n.loading span:nth-child(2) {\n  animation-delay: 0.2s;\n}\n.loading span:nth-child(3) {\n  animation-delay: 0.4s;\n}\n\n@keyframes bounce {\n  from { transform: translateY(0); opacity: 0.6; }\n  to   { transform: translateY(-8px); opacity: 1; }\n}\n    \n    .error {\n        text-align: center;\n        padding: 20px;\n        color: #666;\n    }\n    \/* Status buttons *\/\n    \n    \/* Label *\/\n  .filter-label {\n    font-size: 14px;\n    color: #333;\n  }\n  \n  \/* Select box *\/\n  .filter-select {\n    padding: 10px 14px;\n    border: 1px solid #ccc;\n    border-radius: 8px;\n    background: #fff;\n    font-size: 14px;\n    color: #333;\n    cursor: pointer;\n    transition: all 0.2s ease;\n    appearance: none; \/* remove default arrow *\/\n    background-image: url(\"data:image\/svg+xml;charset=US-ASCII,%3csvg xmlns='http:\/\/www.w3.org\/2000\/svg' width='12' height='12' viewBox='0 0 24 24'%3e%3cpath fill='none' stroke='%23666' stroke-width='2' d='M6 9l6 6 6-6'\/%3e%3c\/svg%3e\");\n    background-repeat: no-repeat;\n    background-position: right 12px center;\n    background-size: 12px;\n  }\n  \n  .filter-select:hover {\n    border-color: #999;\n  }\n  \n  .filter-select:focus {\n    border-color: #006bff;\n    box-shadow: 0 0 0 3px rgba(0,107,255,0.2);\n    outline: none;\n  }\n  \n    \/* Pagination *\/\n  .pagination {\n  margin-top: 20px;\n  display: flex;\n  justify-content: center;\n  flex-wrap: wrap;\n  gap: 8px;\n  }\n  \n  .pagination button {\n  padding: 8px 14px;\n  border: 1px solid #ccc;\n  background: #fff;\n  color: #000;\n  border-radius: 6px;\n  cursor: pointer;\n  font-size: 0.9rem;\n  transition: background 0.2s, color 0.2s;\n  }\n  \n  .pagination button.active {\n  background: #006bff;\n  color: #fff;\n  border-color: #006bff;\n  }\n  \n  .pagination button:disabled {\n  opacity: 0.5;\n  cursor: default;\n  }\n\n    \/* Filter buttons *\/\n\n    .post-filter button {\n    padding: 8px 14px;\n    border: 1px solid #ccc;\n    background: #fff;\n    color: #000;\n    border-radius: 6px;\n    cursor: pointer;\n    font-size: 0.9rem;\n    transition: background 0.2s, color 0.2s, border-color 0.2s;\n    }\n\n    .post-filter button.active {\n    background: #006bff;\n    color: #fff;\n    border-color: #006bff;\n    }\n  <\/style>\n  \n  <div class=\"post-grid-wrapper\">\n    <!-- Filter -->\n    <div class=\"post-filter\">\n        <div class=\"filter-left\">\n            <label for=\"categoryFilter\" class=\"filter-label\">Filter<\/label>\n            <select id=\"categoryFilter\" class=\"filter-select\">\n                <option value=\"\">All<\/option>\n            <\/select>\n            <button id=\"btnUpcoming\" class=\"active\">Upcoming<\/button>\n            <button id=\"btnDone\">Done<\/button>\n        <\/div>\n  \n        <div class=\"filter-right\">\n            <label for=\"searchBox\">Search Event<\/label>\n            <div class=\"search-wrapper\">\n                <input type=\"text\" id=\"searchBox\" placeholder=\"Search event...\">\n                <span class=\"search-icon\">\ud83d\udd0d<\/span>\n            <\/div>\n        <\/div>\n    <\/div>\n  \n    <!-- Grid -->\n    <div id=\"postGridEvent\">\n        <div class=\"loading\">Loading...<\/div>\n        \n    <\/div>\n    <!-- Pagination -->\n    <div id=\"pagination\" class=\"pagination\"><\/div>\n  <\/div>\n  \n  <script>\n    (function(){\n  const gridContainer = document.getElementById(\"postGridEvent\");\n  const filterSelect = document.getElementById(\"categoryFilter\");\n  const searchBox = document.getElementById(\"searchBox\");\n  const pagination = document.getElementById(\"pagination\");\n  const btnUpcoming = document.getElementById(\"btnUpcoming\");\n  const btnDone = document.getElementById(\"btnDone\");\n  let currentFilter = \"upcoming\";\n  const baseUrl = \"\/wp-json\/wp\/v2\";\n  const postsPerPage = 6;\n  let currentPage = 1;\n  let totalPages = 1;\n  \n  \/\/ helper\n  function stripHtml(html){\n    const tmp = document.createElement(\"div\");\n    tmp.innerHTML = html;\n    return tmp.textContent || tmp.innerText || \"\";\n  }\n  function truncate(str, n){\n    return str.length > n ? str.slice(0, n).trim() + \"\u2026\" : str;\n  }\n  \n  \/\/ fetch categories\n  function loadCategories(){\n    fetch(`${baseUrl}\/categories?parent=46&per_page=50&lang=en`)\n      .then(res => res.json())\n      .then(cats => {\n        cats.forEach(cat => {\n          if (cat.count === 0) return;\n          const opt = document.createElement(\"option\");\n          opt.value = cat.id;\n          opt.textContent = cat.name;\n          filterSelect.appendChild(opt);\n        });\n      });\n  }\n  \n  \/\/ render pagination buttons\n  function renderPagination(){\n    pagination.innerHTML = \"\";\n    if (totalPages <= 1) return;\n  \n    \/\/ prev\n    const prevBtn = document.createElement(\"button\");\n    prevBtn.textContent = \"\u00ab Prev\";\n    prevBtn.disabled = currentPage === 1;\n    prevBtn.onclick = () => { if (currentPage > 1) loadPosts(filterSelect.value, searchBox.value.trim(), currentPage-1); };\n    pagination.appendChild(prevBtn);\n  \n    \/\/ page numbers (sederhana, bisa dibuat versi ellipsis kalau panjang)\n    for (let i=1; i<=totalPages; i++){\n      const btn = document.createElement(\"button\");\n      btn.textContent = i;\n      if (i === currentPage) btn.classList.add(\"active\");\n      btn.onclick = () => loadPosts(filterSelect.value, searchBox.value.trim(), i);\n      pagination.appendChild(btn);\n    }\n  \n    \/\/ next\n    const nextBtn = document.createElement(\"button\");\n    nextBtn.textContent = \"Next \u00bb\";\n    nextBtn.disabled = currentPage === totalPages;\n    nextBtn.onclick = () => { if (currentPage < totalPages) loadPosts(filterSelect.value, searchBox.value.trim(), currentPage+1); };\n    pagination.appendChild(nextBtn);\n  }\n  \n  \/\/ fetch posts\n  async function loadPosts(catId = \"\", searchTerm = \"\", page = 1) {\n    gridContainer.innerHTML = `\n        <div class=\"loading\">\n            <span><\/span><span><\/span><span><\/span>\n        <\/div>\n        `;\n    currentPage = page;\n  \n    let url = `${baseUrl}\/event?per_page=${postsPerPage}&page=${page}&_embed`;\n  \n    if (catId) {\n      url += `&categories=${catId}`;\n    } else {\n      try {\n        const resCats = await fetch(`${baseUrl}\/categories?parent=46&per_page=50&lang=en`);\n        const cats = await resCats.json();\n        const ids = cats.map(c => c.id).join(\",\");\n        if (ids) url += `&categories=${ids}`;\n      } catch (err) {\n        gridContainer.innerHTML = `<div class=\"loading\">\n            <span><\/span><span><\/span><span><\/span>\n        <\/div>`;\n        return;\n      }\n    }\n  \n    if (searchTerm) {\n      url += `&search=${encodeURIComponent(searchTerm)}`;\n    }\n  \n    try {\n      const res = await fetch(url);\n      if (!res.ok) throw new Error(\"Failed to fetch posts\");\n      const posts = await res.json();\n  \n      totalPages = parseInt(res.headers.get(\"X-WP-TotalPages\")) || 1;\n\n      const now = new Date();\n      const filteredPosts = posts.filter(post => {\n        const dtStr = post?.acf?.date_time;\n        if (!dtStr) return currentFilter === \"done\"; \/\/ missing date treated as past\n        const dt = new Date(dtStr);\n        if (isNaN(dt.getTime())) return currentFilter === \"done\"; \/\/ invalid date treated as past\n        return currentFilter === \"upcoming\" ? dt >= now : dt < now;\n      });\n  \n      if (filteredPosts.length === 0) {\n        gridContainer.innerHTML = '<div class=\"error\">No posts found.<\/div>';\n        pagination.innerHTML = \"\";\n        return;\n      }\n  \n      const grid = document.createElement(\"div\");\n      grid.className = \"post-grid\";\n  \n      filteredPosts.forEach(post => {\n        let thumb = \"\";\n        try {\n          const fm = post._embedded[\"wp:featuredmedia\"][0];\n          thumb = fm?.source_url || \"\";\n        } catch (e) {}\n  \n        let excerpt = stripHtml(post.excerpt?.rendered || post.content?.rendered || \"\");\n        excerpt = truncate(excerpt, 100);\n  \n        const card = document.createElement(\"div\");\n        card.className = \"post-card\";\n        card.innerHTML = `\n          ${thumb ? `<img decoding=\"async\" src=\"${thumb}\" alt=\"${post.title.rendered}\">` : \"\"}\n          <div class=\"card-body\">\n            <h3>${post.title.rendered}<\/h3>\n            <div class=\"readmore1\">\n                <a href=\"${post.link}\" class=\"btn-readmore1\">Read more<\/a>\n                ${currentFilter === \"upcoming\" ? `<a href=\"${post.acf.registration_link}\" class=\"btn-regis\">Register<\/a>` : `<a class=\"btn-regis disabled\" aria-disabled=\"true\">Closed<\/a>`}\n            <\/div>\n          <\/div>\n        `;\n        grid.appendChild(card);\n      });\n  \n      gridContainer.innerHTML = \"\";\n      gridContainer.appendChild(grid);\n  \n      renderPagination();\n  \n    } catch (err) {\n      gridContainer.innerHTML = `<<div class=\"loading\">\n            <span><\/span><span><\/span><span><\/span>\n        <\/div>`;\n      pagination.innerHTML = \"\";\n    }\n  }\n  \n  \/\/ init\n  loadCategories();\n  loadPosts();\n  \n  filterSelect.addEventListener(\"change\", () => {\n    loadPosts(filterSelect.value, searchBox.value.trim(), 1);\n  });\n  \n  let typingTimer;\n  searchBox.addEventListener(\"input\", () => {\n    clearTimeout(typingTimer);\n    typingTimer = setTimeout(() => {\n      loadPosts(filterSelect.value, searchBox.value.trim(), 1);\n    }, 500);\n  });\n    \/\/ filter buttons\n    btnUpcoming.addEventListener(\"click\", () => {\n    if (currentFilter === \"upcoming\") return;\n    currentFilter = \"upcoming\";\n    btnUpcoming.classList.add(\"active\");\n    btnDone.classList.remove(\"active\");\n    loadPosts(filterSelect.value, searchBox.value.trim(), 1);\n  });\n  btnDone.addEventListener(\"click\", () => {\n    if (currentFilter === \"done\") return;\n    currentFilter = \"done\";\n    btnDone.classList.add(\"active\");\n    btnUpcoming.classList.remove(\"active\");\n    loadPosts(filterSelect.value, searchBox.value.trim(), 1);\n  });\n  })();\n  <\/script>\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Labamu Exclusive Event Experience Join us for an inspiring experience filled with ideas, collaboration, and meaningful connections. Filter All Upcoming Done Search Event \ud83d\udd0d Loading&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"content-type":"","om_disable_all_campaigns":false,"footnotes":""},"class_list":["post-7279","page","type-page","status-publish","hentry"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/labamu.co.id\/en\/wp-json\/wp\/v2\/pages\/7279","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/labamu.co.id\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/labamu.co.id\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/labamu.co.id\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/labamu.co.id\/en\/wp-json\/wp\/v2\/comments?post=7279"}],"version-history":[{"count":7,"href":"https:\/\/labamu.co.id\/en\/wp-json\/wp\/v2\/pages\/7279\/revisions"}],"predecessor-version":[{"id":13258,"href":"https:\/\/labamu.co.id\/en\/wp-json\/wp\/v2\/pages\/7279\/revisions\/13258"}],"wp:attachment":[{"href":"https:\/\/labamu.co.id\/en\/wp-json\/wp\/v2\/media?parent=7279"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}