https://t.me/RX1948
Server : Apache/2.4.18 (Ubuntu)
System : Linux canvaswebdesign 3.13.0-71-generic #114-Ubuntu SMP Tue Dec 1 02:34:22 UTC 2015 x86_64
User : oppastar ( 1041)
PHP Version : 7.0.33-0ubuntu0.16.04.15
Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,
Directory :  /var/www/laciasmara.com/public_html/shop/application/views/admin_new/affiliate/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /var/www/laciasmara.com/public_html/shop/application/views/admin_new/affiliate/manage.php
<main class="flex-1 py-4 px-4 bg-purple-50">
    <div class="flex items-center mb-4">
        <h1 class="text-xl font-bold text-[#333]">Daftar Affiliate</h1>

        <div class="ml-auto flex items-center gap-2">
            <button type="button" id="addAffiliate" class="border border-gray-300 text-sm rounded-lg px-4 py-2 bg-white hover:bg-gray-50 gap-4 flex items-center justify-between focus:outline-none focus:ring-1 focus:ring-[#7A4397] hover:bg-[#5a2f73] hover:bg-[#5a2f73] transition duration-300 ease-in-out text-[#333]">
                <i data-feather="plus" class="h-4 w-4"></i>
                <span>Tambah Affiliate</span>
            </button>
            <!-- <div class="relative inline-block text-left">
                <button type="button" id="btnDownloadData" class="border border-gray-300 text-sm rounded-lg px-4 py-2 bg-white hover:bg-gray-50 gap-4 flex items-center justify-between focus:outline-none focus:ring-1 focus:ring-[#7A4397] hover:bg-[#5a2f73] transition duration-300 ease-in-out text-[#333]">
                    <i data-feather="download" class="h-4 w-4"></i>
                    <span>Download</span>
                    <i data-feather="chevron-down" id="chevronDownload" class="h-4 w-4 transition-transform transform duration-300"></i>
                </button>
                <div id="dropdownMenu" class="hidden opacity-0 scale-95 transform transition-all duration-300 absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded-lg shadow-lg z-[999]">
                    <button data-format="csv" class="dropdown-download-item flex items-center gap-2 w-full text-left px-4 py-2 hover:bg-gray-100 transition duration-200">
                        <i data-feather="file-text" class="h-4 w-4"></i> Download as CSV
                    </button>
                    <button data-format="excel" class="dropdown-download-item flex items-center gap-2 w-full text-left px-4 py-2 hover:bg-gray-100 transition duration-200">
                        <i data-feather="table" class="h-4 w-4"></i> Download as Excel
                    </button>
                    <button data-format="pdf" class="dropdown-download-item flex items-center gap-2 w-full text-left px-4 py-2 hover:bg-gray-100 transition duration-200">
                        <i data-feather="file" class="h-4 w-4"></i> Download as PDF
                    </button>
                </div>
            </div> -->
        </div>
    </div>
    <?php if ($this->session->flashdata('message')): ?>
        <div class="alert flex items-center justify-between bg-<?php echo $this->session->flashdata('message_type') === 'success' ? 'green' : 'red'; ?>-100 border-l-4 border-<?php echo $this->session->flashdata('message_type') === 'success' ? 'green' : 'red'; ?>-500 text-<?php echo $this->session->flashdata('message_type') === 'success' ? 'green' : 'red'; ?>-800 px-6 py-4 rounded-lg shadow-lg transition transform duration-300">
            <div class="flex items-center">
                <!-- Ikon Feather sesuai jenis pesan -->
                <i data-feather="<?php echo $this->session->flashdata('message_type') === 'success' ? 'check-circle' : 'x-circle'; ?>" class="h-6 w-6 mr-3"></i>
                <span class="font-semibold"><?php echo $this->session->flashdata('message'); ?></span>
            </div>
            <button class="ml-4 text-<?php echo $this->session->flashdata('message_type') === 'success' ? 'green' : 'red'; ?>-500 hover:text-<?php echo $this->session->flashdata('message_type') === 'success' ? 'green' : 'red'; ?>-700 focus:outline-none" onclick="this.parentElement.style.display='none'">
                <i data-feather="x" class="h-5 w-5"></i>
            </button>
        </div>
        <script>
            feather.replace();
        </script>
    <?php endif; ?>
    <!-- Tabs -->
    <div class="bg-white rounded-lg shadow-sm p-4">
        <!-- Tab Navigation -->
        <nav class="flex space-x-8" aria-label="Order Tabs">
            <button class="tab-btn p-2 text-sm font-medium border-b-2 border-[#7A4397] text-[#7A4397]" data-tab="all">
                Semua Affiliate
            </button>
            <button class="tab-btn p-2 text-sm font-medium text-gray-500 hover:text-gray-700" data-tab="approve">
                Disetujui
            </button>
            <button class="tab-btn p-2 text-sm font-medium text-gray-500 hover:text-gray-700" data-tab="waiting">
                Menunggu Persetujuan
            </button>
            <button class="tab-btn p-2 text-sm font-medium text-gray-500 hover:text-gray-700" data-tab="rejected">
                Ditolak
            </button>
        </nav>
    </div>

    <!-- Search and Filters -->
    <div class="mt-4 flex flex-col gap-4 sm:flex-row sm:flex-wrap text-sm">
        <!-- Filter Dropdowns -->
        <div class="flex flex-wrap gap-2">
            <!-- Filter Dropdown -->
            <div class="relative" id="filterDropdown">
                <button class="border border-gray-300 text-sm rounded-lg px-4 py-2 bg-white hover:bg-gray-50 flex items-center justify-between w-[200px] focus:outline-none focus:ring-1 focus:ring-[#7A4397]">
                    <span id="filterText">Filter</span>
                    <i data-feather="chevron-down" class="w-4 h-4 text-gray-700"></i>
                </button>
                <div class="hidden absolute left-0 top-full mt-1 bg-white border border-gray-200 rounded-lg shadow-lg z-50 min-w-[200px]" id="filterMenu">
                    <!-- Main Menu Items -->
                    <div class="py-1">
                        <!-- Gender -->
                        <div class="px-4 py-2 text-sm hover:bg-gray-100 cursor-pointer flex justify-between items-center group relative">
                            <span>Jenis Kelamin</span>
                            <i data-feather="chevron-right" class="w-4 h-4 text-gray-700"></i>
                            <div class="hidden group-hover:block absolute left-full top-0 bg-white border border-gray-200 rounded-lg shadow-lg min-w-[200px] -mt-1">
                                <div class="py-1">
                                    <label class="flex items-center px-4 py-2 hover:bg-gray-100 cursor-pointer">
                                        <input type="checkbox" class="mr-2 filter-checkbox" data-filter="gender" data-param="isMale" data-value="true">
                                        <span>Male</span>
                                    </label>
                                    <label class="flex items-center px-4 py-2 hover:bg-gray-100 cursor-pointer">
                                        <input type="checkbox" class="mr-2 filter-checkbox" data-filter="gender" data-param="isFemale" data-value="true">
                                        <span>Female</span>
                                    </label>
                                    <label class="flex items-center px-4 py-2 hover:bg-gray-100 cursor-pointer">
                                        <input type="checkbox" class="mr-2 filter-checkbox" data-filter="gender" data-param="isOther" data-value="true">
                                        <span>Others</span>
                                    </label>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="flex flex-wrap gap-2 text-sm">
                <!-- Sort Select -->
                <div class="relative w-[150px]">
                    <select id="sortFilter" name="sort" class="w-full appearance-none border border-gray-300 rounded-lg px-4 py-2 bg-white pr-10 cursor-pointer focus:outline-none focus:ring-1 focus:ring-[#7A4397] truncate">
                        <option value="" class="truncate">Urutkan</option>
                        <option value="paling_baru">Paling Baru</option>
                        <option value="paling_lama">Paling Lama</option>
                        <!-- <option value="klik_banyak">Klik Paling Banyak</option>
                        <option value="klik_dikit">Klik Paling Dikit</option> -->
                        <option value="jual_banyak">Penjualan Terbanyak</option>
                        <option value="jual_dikit">Penjualan Paling Dikit</option>
                    </select>
                    <div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700">
                        <i data-feather="chevron-down" class="w-4 h-4"></i>
                    </div>
                </div>
            </div>
        </div>

        <!-- Search -->
        <div class="w-full sm:flex-1 sm:min-w-[300px]">
            <div class="relative">
                <input
                    id="searchInput"
                    type="text"
                    placeholder="Cari berdasarkan nama, email, atau sosial media mereka."
                    class="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-1 focus:ring-[#7A4397]">
                <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
                    <svg class="h-5 w-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
                    </svg>
                </div>
            </div>
        </div>

    </div>

    <!-- Selected Filters Display -->
    <div id="selectedFilters" class="mt-4 flex flex-wrap gap-2 items-center">
        <span id="resetFilters" class="text-[#7A4397] text-sm mr-2 font-semibold cursor-pointer hidden">Reset Filter</span>
    </div>
    <div id="affiliate-container" class="mt-4"></div>
    <div id="loading-more" class="hidden flex justify-center items-center p-4">
        <div class="animate-spin rounded-full h-6 w-6 border-b-2 border-green-600"></div>
        <span class="ml-2 text-gray-600">Memuat data...</span>
    </div>
</main>
<script>
    let currentPage = 1;
    let hasMoreData = true;
    let isFetching = false;
    let allAffiliates = [];
    let debounceTimer;
    let searchDebounceTimer;

    let currentTab = new URLSearchParams(window.location.search).get('tab') || 'all';
    const tabs = document.querySelectorAll('.tab-btn');
    // Filter
    const filterBtn = document.querySelector('#filterDropdown button');
    const filterMenu = document.querySelector('#filterMenu');
    const filterText = document.getElementById("filterText");
    const selectedFiltersContainer = document.getElementById("selectedFilters");
    const filterCheckboxes = document.querySelectorAll('input[type="checkbox"]');

    const BASE_URL_IMAGE = "<?= base_url('uploads/product') ?>";
    const BASE_URL_PRODUCT = "<?= base_url('product') ?>";
    const BASE_URL_FETCH_DATA = "<?= base_url('admin/affiliator/get_affiliates') ?>";
    const BASE_URL = "<?= base_url('admin/affiliator') ?>";
    const ADD_AFFILIATE_URL = "<?= base_url('admin/affiliate/add') ?>";
    const BASE_URL_DETAIL = "<?= base_url('admin/affiliate/detail/') ?>";

    document.addEventListener("DOMContentLoaded", function() {
        // Set default tab saat halaman dimuat
        tabs.forEach(tab => {
            if (tab.getAttribute('data-tab') === currentTab) {
                tab.classList.add('text-[#7A4397]', 'border-b-2', 'border-[#7A4397]');
                tab.classList.remove('text-gray-500', 'hover:text-gray-700');
                updateURLAndFetch();
            } else {
                tab.classList.remove('text-[#7A4397]', 'border-b-2', 'border-[#7A4397]');
                tab.classList.add('text-gray-500', 'hover:text-gray-700');
            }
        });
        // Handle Tab Clicks
        tabs.forEach(tab => {
            tab.addEventListener('click', () => {
                tabs.forEach(t => {
                    t.classList.remove('text-[#7A4397]', 'border-b-2', 'border-[#7A4397]');
                    t.classList.add('text-gray-500', 'hover:text-gray-700');
                });

                tab.classList.add('text-[#7A4397]', 'border-b-2', 'border-[#7A4397]');
                tab.classList.remove('text-gray-500', 'hover:text-gray-700');

                currentTab = tab.getAttribute('data-tab');
                updateURLAndFetch();
            });
        });

        // Sort
        sortFilter.addEventListener('change', () => {
            updateURLAndFetch();
            updateSelectedFilters();
        });

        // Filter Menu
        filterBtn.addEventListener('click', () => {
            filterMenu.classList.toggle('hidden');
        });
        // Close dropdown when clicking outside
        document.addEventListener('click', (e) => {
            if (!e.target.closest('#filterDropdown')) {
                filterMenu.classList.add('hidden');
            }
        });

        // Handle checkbox changes
        filterCheckboxes.forEach(checkbox => {
            checkbox.addEventListener('change', () => {
                updateURLAndFetch();
                updateFilterText();
                updateSelectedFilters();
            });
        });

        document.getElementById("resetFilters").addEventListener("click", resetAllFilters);

        // Tambahkan event listener untuk search input
        document.getElementById('searchInput').addEventListener('input', function(e) {
            clearTimeout(searchDebounceTimer);
            searchDebounceTimer = setTimeout(() => {
                searchAffiliate(e.target.value);
            }, 250);
        });

        // // Download Data
        // document.getElementById("btnDownloadData").addEventListener("click", function() {
        //     let dropdown = document.getElementById("dropdownMenu");
        //     let iconChevron = document.getElementById("chevronDownload");

        //     if (dropdown.classList.contains("hidden")) {
        //         dropdown.classList.remove("hidden");
        //         setTimeout(() => {
        //             dropdown.classList.remove("opacity-0", "scale-95");
        //         }, 10);
        //         iconChevron.classList.add("rotate-180");
        //     } else {
        //         dropdown.classList.add("opacity-0", "scale-95");
        //         setTimeout(() => {
        //             dropdown.classList.add("hidden");
        //         }, 200);
        //         iconChevron.classList.remove("rotate-180");
        //     }
        // });

        // Handle click opsi
        // document.querySelectorAll(".dropdown-download-item").forEach(item => {
        //     item.addEventListener("click", function() {
        //         let format = this.getAttribute("data-format");
        //         if (format === "csv") {
        //             downloadOrdersCSV(allAffiliates);
        //         } else if (format === "excel") {
        //             downloadOrdersExcel(allAffiliates);
        //         } else if (format === "pdf") {
        //             downloadOrdersPDF(allAffiliates);
        //         }

        //         let dropdown = document.getElementById("dropdownMenu");
        //         dropdown.classList.add("opacity-0", "scale-95");
        //         setTimeout(() => {
        //             dropdown.classList.add("hidden");
        //         }, 200);
        //         document.getElementById("chevronDownload").classList.remove("rotate-180");
        //     });
        // });

        // // Hide dropdown jika klik di luar
        // document.addEventListener("click", function(event) {
        //     let dropdown = document.getElementById("dropdownMenu");
        //     let button = document.getElementById("btnDownloadData");
        //     if (!button.contains(event.target) && !dropdown.contains(event.target)) {
        //         dropdown.classList.add("opacity-0", "scale-95");
        //         setTimeout(() => {
        //             dropdown.classList.add("hidden");
        //         }, 200);
        //         document.getElementById("chevronDownload").classList.remove("rotate-180");
        //     }
        // });

        // Fetch data customer infinite scroll
        window.addEventListener('scroll', () => {
            if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight - 500) {
                fetchAffiliates(new URLSearchParams(window.location.search), true);
            }
        });

        // Add Customer Handler
        const addAffiliateButton = document.querySelector('button[id="addAffiliate"]');
        addAffiliateButton.addEventListener('click', function(event) {
            event.preventDefault();

            window.open(`${ADD_AFFILIATE_URL}`, '_blank');
        });

        // Remove Filter
        window.removeFilter = function(param) {
            if (param === "sort") {
                sortFilter.value = "";
            } else {
                filterCheckboxes.forEach(checkbox => {
                    if (checkbox.dataset.param === param) {
                        checkbox.checked = false;
                    }
                });
            }

            updateSelectedFilters();
            updateURLAndFetch();
            updateFilterText();
        };
        feather.replace();
        updateURLAndFetch();
    });
    // Initialize the scroll listener
    function initInfiniteScroll() {
        window.addEventListener('scroll', function() {
            // Check if we're near the bottom of the page
            if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 500) {
                // If we're within 500px of the bottom, load more data
                if (!isFetching && hasMoreData) {
                    // Get current URL parameters
                    const params = new URLSearchParams(window.location.search);
                    fetchAffiliates(params, true); // true means append instead of replace
                }
            }
        });
    }

    function resetAllFilters() {
        sortFilter.value = "";

        // Reset checkbox filter
        filterCheckboxes.forEach(checkbox => {
            checkbox.checked = false;
        });
        // Hapus parameter date_filter, start_date, dan end_date dari URL
        const urlParams = new URLSearchParams(window.location.search);
        urlParams.delete("date_filter");
        urlParams.delete("start_date");
        urlParams.delete("end_date");
        window.history.replaceState({}, "", window.location.pathname + "?" + urlParams.toString());

        // Update tampilan filter yang dipilih
        updateSelectedFilters();
        updateURLAndFetch();
        updateFilterText();
    }

    function updateFilterText() {
        const checkedCount = document.querySelectorAll(".filter-checkbox:checked").length;
        filterText.textContent = checkedCount > 0 ? `${checkedCount} Filter Terpilih` : "Filter";
    }

    function updateSelectedFilters() {
        const resetFilters = document.getElementById("resetFilters");

        // Menyimpan elemen resetFilters di dalam selectedFiltersContainer
        selectedFiltersContainer.innerHTML = "";

        let hasFilters = false;
        selectedFiltersContainer.appendChild(resetFilters);

        // Menambahkan filter 'sort'
        const selectedSort = sortFilter.value;
        if (selectedSort) {
            hasFilters = true;
            const sortTag = document.createElement("div");
            sortTag.className = "flex items-center border border-[#7A4397] rounded-lg px-3 py-1 bg-gray-100 text-sm";
            sortTag.innerHTML = `
            ${sortFilter.options[sortFilter.selectedIndex].text}
            <button class="ml-2 text-gray-500 hover:text-gray-700" onclick="removeFilter('sort')">&times;</button>
        `;
            selectedFiltersContainer.appendChild(sortTag);
        }

        // Menambahkan filter dari checkbox
        filterCheckboxes.forEach(checkbox => {
            if (checkbox.checked) {
                hasFilters = true;
                const filterTag = document.createElement("div");
                filterTag.className = "flex items-center border border-[#7A4397] rounded-lg px-3 py-1 bg-gray-100 text-sm";
                filterTag.innerHTML = `
                ${checkbox.nextElementSibling.innerText}
                <button class="ml-2 text-gray-500 hover:text-gray-700" onclick="removeFilter('${checkbox.dataset.param}')">&times;</button>
            `;
                selectedFiltersContainer.appendChild(filterTag);
            }
        });

        // Menampilkan atau menyembunyikan tombol reset filter
        if (hasFilters) {
            resetFilters.classList.remove("hidden");
        } else {
            resetFilters.classList.add("hidden");
        }
    }


    function updateURLAndFetch(paramName, value, extraParams = null) {
        clearTimeout(debounceTimer);
        debounceTimer = setTimeout(() => {
            const params = new URLSearchParams(window.location.search);
            params.set('tab', currentTab);

            // Perbarui atau hapus parameter yang ditentukan
            if (paramName) {
                if (value !== null && value !== undefined) {
                    params.set(paramName, value);
                } else {
                    params.delete(paramName);
                }
            }

            // Set parameter sort
            const selectedSort = document.getElementById('sortFilter').value;
            if (selectedSort) {
                params.set('sort', selectedSort);
            } else {
                params.delete('sort');
            }

            // Collect all checkbox state first
            const checkboxParamMap = {};

            // Inisialisasi semua parameter filter sebagai null
            document.querySelectorAll('input[type="checkbox"]').forEach(checkbox => {
                const param = checkbox.dataset.param;
                if (param && !checkboxParamMap[param]) {
                    checkboxParamMap[param] = null;
                }
            });

            // Setel nilai untuk checkbox yang dicentang
            document.querySelectorAll('input[type="checkbox"]:checked').forEach(checkbox => {
                const param = checkbox.dataset.param;
                const value = checkbox.dataset.value;

                if (param && value) {
                    checkboxParamMap[param] = value;
                }
            });

            // Terapkan parameter dari checkboxes
            for (const [param, value] of Object.entries(checkboxParamMap)) {
                if (value !== null) {
                    params.set(param, value);
                } else {
                    params.delete(param);
                }
            }

            // Reset pagination
            currentPage = 1;
            hasMoreData = true;
            allAffiliates = [];

            // Update URL
            const newUrl = `${window.location.pathname}?${params.toString()}`;
            history.pushState(null, '', newUrl);

            // Fetch affiliates with new parameters (replace mode)
            fetchAffiliates(params, false);
        }, 300);
    }

    function fetchAffiliates(params = new URLSearchParams(), append = false) {
        if (isFetching) return;

        // Jika tidak dalam mode append dan tidak ada data lagi, reset hasMoreData
        if (!append) {
            hasMoreData = true;
        } else if (!hasMoreData) {
            return;
        }

        isFetching = true;

        const baseUrl = BASE_URL_FETCH_DATA;
        params.set('page', currentPage);
        params.set('limit', 10);

        const url = `${baseUrl}?${params.toString()}`;
        const progressBar = document.getElementById('progressBar');
        const container = document.getElementById('affiliate-container');

        // Hapus konten sebelum fetch (kecuali jika append = true)
        if (!append) {
            container.innerHTML = `
            <div class="flex flex-col items-center justify-center p-8">
                <div class="animate-spin rounded-full h-12 w-12 border-b-2 border-purple-700 mb-4"></div>
                <p class="text-gray-600 text-center">Ga bakal lama kok, sabar ya...</p>
            </div>
        `;
        }

        progressBar.classList.remove('hidden');

        fetch(url)
            .then(res => res.json())
            .then(data => {
                progressBar.classList.add('hidden');

                if (!append) {
                    container.innerHTML = ''; // Hapus loading setelah data diterima
                }

                if (data.length === 0) {
                    hasMoreData = false;
                    if (!append) {
                        container.innerHTML = '<div class="flex justify-center items-center p-8 text-gray-500">Tidak ada affiliate yang ditemukan</div>';
                    }
                } else {
                    if (!append) {
                        allAffiliates = data;
                    } else {
                        allAffiliates = [...allAffiliates, ...data];
                    }
                    renderAffiliates(data, append);
                    currentPage++;
                }

                isFetching = false;
            })
            .catch(error => {
                progressBar.classList.add('hidden');

                console.error('Error fetching affiliates:', error);
                isFetching = false;

                // Tampilkan pesan error
                container.innerHTML = '<div class="flex justify-center items-center p-8 text-red-500">Terjadi kesalahan saat mengambil data. Silakan coba lagi.</div>';
            });
    }


    function formatNumber(number) {
        return new Intl.NumberFormat('id-ID').format(number);
    }

    function renderAffiliates(affiliates, append = false) {
        const container = document.getElementById('affiliate-container');
        const loadingMore = document.getElementById('loading-more');

        if (!append) {
            container.innerHTML = ''; // Clear existing content
        }

        if (!affiliates || affiliates.length === 0) {
            if (!append) {
                container.innerHTML = '<div class="flex justify-center items-center p-8 text-gray-500">Tidak ada pelanggan yang ditemukan</div>';
            }
            loadingMore.classList.add('hidden');
            return;
        }

        // Jika tidak append, buat struktur tabel baru
        if (!append) {
            const tableWrapper = document.createElement('div');
            tableWrapper.className = 'overflow-x-auto rounded-lg shadow';
            tableWrapper.innerHTML = `
                <table class="min-w-full divide-y divide-gray-200">
                    <thead class="bg-gray-50">
                        <tr>
                            <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Pelanggan</th>
                            <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Sosial Media</th>
                            <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Alamat Lengkap</th>
                            <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Total Penjualan</th>
                            <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Bergabung</th>
                            <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Aksi</th>
                        </tr>
                    </thead>
                    <tbody id="affiliates-table-body" class="bg-white divide-y divide-gray-200">
                    </tbody>
                </table>
            `;
            container.appendChild(tableWrapper);
        }

        const tableBody = document.getElementById('affiliates-table-body') || container.querySelector('tbody');

        affiliates.forEach(affiliate => {
            const row = document.createElement('tr');
            row.className = 'hover:bg-gray-50 transition-colors';

            // Format tanggal lahir
            const birthdate = affiliate.birthday_formatted || '-';

            row.innerHTML = `
                <td class="px-4 py-3">
                    <div class="flex items-center">
                        <div class="flex-shrink-0 h-10 w-10 rounded-full bg-gray-200 flex items-center justify-center">
                            <span class="text-gray-600 font-medium">${affiliate.nama.charAt(0).toUpperCase()}</span>
                        </div>
                        <div class="ml-4">
                            <div class="text-sm font-medium text-gray-900">${affiliate.nama}</div>
                            <div class="text-sm text-gray-500">${affiliate.email}</div>
                            <div class="text-sm text-gray-500">${affiliate.no_telpon}</div>
                        </div>
                    </div>
                </td>
                <td class="px-4 py-3 max-w-xs truncate">
                    <a href="${affiliate.sosial_media}" target="_blank" class="text-sm font-medium text-purple-500 hover:underline">
                        ${affiliate.sosial_media}
                    </a>
                </td>
                <td class="px-4 py-3">
                    <div class="text-sm text-[#333]">${affiliate.shipping_address || '-'}</div>
                </td>
                <td class="px-4 py-3">
                    <div class="text-sm font-medium text-gray-900">${affiliate.total_sales_formatted}</div>
                    <div class="text-sm font-medium text-gray-500">Order: ${affiliate.total_orders || 0}</div>
                </td>
                <td class="px-4 py-3">
                    <span class="text-sm font-medium">${affiliate.created_formatted}</span>
                </td>
                <td class="px-4 py-3 text-right text-sm font-medium space-y-2">
                    <div class="flex flex-col space-y-2">
                        <button data-id="${affiliate.id_daftar}" class="affiliate-detail-btn inline-flex items-center px-3 py-1.5 border border-gray-300 rounded-md text-xs text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[#7A4397]">
                            <i data-feather="file-text" class="w-4 h-4 mr-1"></i> Detail
                        </button>
                        <button data-phone="${affiliate.no_telpon}" data-name="${affiliate.nama}" class="whatsapp-chat-btn inline-flex items-center px-3 py-1.5 border border-transparent rounded-md text-xs text-white bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500">
                            <i data-feather="message-circle" class="w-4 h-4 mr-1"></i> Chat
                        </button>
                    </div>
                </td>
            `;

            tableBody.appendChild(row);
        });

        loadingMore.classList.add('hidden');

        // Inisialisasi Feather Icons
        feather.replace();


        // Event listener untuk WhatsApp chat
        document.querySelectorAll('.whatsapp-chat-btn').forEach(button => {
            button.addEventListener('click', function() {
                let phoneNumber = this.dataset.phone;
                const affiliateName = this.dataset.name;

                if (phoneNumber.startsWith('08')) {
                    phoneNumber = `62${phoneNumber.substring(1)}`;
                } else if (phoneNumber.startsWith('8')) {
                    phoneNumber = `62${phoneNumber}`;
                }

                const whatsappURL = `https://api.whatsapp.com/send?phone=${phoneNumber}&text=Halo kak ${affiliateName}`;
                window.open(whatsappURL, '_blank');
            });
        });

        // Event listener untuk detail pelanggan
        document.querySelectorAll('.affiliate-detail-btn').forEach(button => {
            button.addEventListener('click', function() {
                const affiliateId = this.dataset.id;
                const detailUrl = BASE_URL_DETAIL + affiliateId;
                window.open(detailUrl, '_blank');
            });
        });
    }

    function searchAffiliate(searchTerm) {
        // Reset data pencarian dan pagination
        currentPage = 1;
        hasMoreData = true;
        allAffiliates = [];

        // Ambil parameter URL saat ini
        const params = new URLSearchParams(window.location.search);

        // Tambahkan parameter pencarian atau hapus jika kosong
        if (searchTerm && searchTerm.trim() !== '') {
            params.set('search', searchTerm.trim());
        } else {
            params.delete('search');
        }

        // Update URL
        const newUrl = `${window.location.pathname}?${params.toString()}`;
        history.pushState(null, '', newUrl);

        // Fetch dengan parameter pencarian
        fetchAffiliates(params, false);
    }
</script>

https://t.me/RX1948 - 2025