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/customers/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /var/www/laciasmara.com/public_html/shop/application/views/admin_new/customers/manage_customer.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 Pelanggan</h1>

        <div class="ml-auto flex items-center gap-2">
            <button type="button" id="addCustomer" 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 Pelanggan</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> -->
            <!-- Filter Date -->
            <!-- Date Filter Dropdown -->
            <div class="relative" id="dateFilterDropdown">
                <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-[350px] focus:outline-none focus:ring-1 focus:ring-[#7A4397]">
                    <div class="flex items-center">
                        <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2 text-[#333]" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
                        </svg>
                        <span id="dateFilterText">Pilih Tanggal</span>
                    </div>
                    <i data-feather="chevron-down" class="w-4 h-4 text-gray-700"></i>
                </button>
                <div class="hidden absolute right-0 top-full mt-2 bg-white border border-gray-200 rounded-lg shadow-lg z-50 w-[650px]" id="dateFilterMenu">
                    <div class="p-4">
                        <!-- Two-column layout with fixed left column -->
                        <div class="flex">
                            <!-- Left Column - Fixed options -->
                            <div class="w-1/2 border-r border-gray-200 pr-2">
                                <h3 class="text-gray-700 font-medium mb-2">Rentang waktu</h3>

                                <div class="flex flex-col">
                                    <!-- Hari ini -->
                                    <div class="py-3 hover:bg-gray-50 cursor-pointer date-option" data-option="today">
                                        <div class="text-gray-800 pl-2">Hari ini</div>
                                    </div>

                                    <!-- Kemarin -->
                                    <div class="py-3 hover:bg-gray-50 cursor-pointer date-option" data-option="yesterday">
                                        <div class="text-gray-800 pl-2">Kemarin</div>
                                    </div>

                                    <!-- 7 hari terakhir -->
                                    <div class="py-3 hover:bg-gray-50 cursor-pointer date-option" data-option="last7days">
                                        <div class="text-gray-800 pl-2">7 hari terakhir</div>
                                    </div>

                                    <!-- 30 hari terakhir -->
                                    <div class="py-3 hover:bg-gray-50 cursor-pointer date-option" data-option="last30days">
                                        <div class="text-gray-800 pl-2">30 hari terakhir</div>
                                    </div>

                                    <!-- Bulan ini -->
                                    <div class="py-3 hover:bg-gray-50 cursor-pointer date-option" data-option="thisMonth">
                                        <div class="text-gray-800 pl-2">Bulan ini</div>
                                    </div>

                                    <!-- Tahun ini -->
                                    <div class="py-3 hover:bg-gray-50 cursor-pointer date-option" data-option="thisYear">
                                        <div class="text-gray-800 pl-2">Tahun ini</div>
                                    </div>

                                    <!-- Separator -->
                                    <div class="my-2 border-t border-gray-200"></div>

                                    <!-- Pilih Tanggal with active indicator -->
                                    <div id="customDateOption" class="py-3 hover:bg-gray-50 cursor-pointer date-option relative" data-option="customDate">
                                        <div class="text-gray-800 pl-2 flex items-center">
                                            <span>Pilih Tanggal</span>
                                            <div id="customDateIndicator" class="hidden absolute left-0 top-0 bottom-0 w-1 bg-green-500"></div>
                                        </div>
                                    </div>
                                </div>
                            </div>

                            <!-- Right Column - Dynamic content -->
                            <div class="w-1/2 pl-2">
                                <!-- Date display for predefined options -->
                                <div id="predefinedDateInfo">
                                    <h3 class="text-gray-700 font-medium mb-2" id="currentMonthTitle">Februari 2025</h3>

                                    <div id="dateDisplays">
                                        <div class="py-3" id="todayDateDisplay">
                                            <div class="text-gray-600" id="todayDate">28 Feb 2025 (00:00 - 11:00)</div>
                                        </div>

                                        <div class="py-3 hidden" id="yesterdayDateDisplay">
                                            <div class="text-gray-600" id="yesterdayDate">27 Feb 2025</div>
                                        </div>

                                        <div class="py-3 hidden" id="last7daysDateDisplay">
                                            <div class="text-gray-600" id="last7daysDate">21 Feb - 27 Feb 2025</div>
                                        </div>

                                        <div class="py-3 hidden" id="last30daysDateDisplay">
                                            <div class="text-gray-600" id="last30daysDate">29 Jan - 27 Feb 2025</div>
                                        </div>

                                        <div class="py-3 hidden" id="thisMonthDateDisplay">
                                            <div class="text-gray-600" id="thisMonthDate">01 Feb - 28 Feb 2025</div>
                                        </div>

                                        <div class="py-3 hidden" id="perDayDateDisplay">
                                            <div class="text-gray-600">Filter per hari</div>
                                        </div>

                                        <div class="py-3 hidden" id="perWeekDateDisplay">
                                            <div class="text-gray-600">Filter per minggu</div>
                                        </div>

                                        <div class="py-3 hidden" id="perMonthDateDisplay">
                                            <div class="text-gray-600">Filter per bulan</div>
                                        </div>
                                    </div>
                                </div>

                                <!-- Calendar for custom date -->
                                <div id="calendarContainer" class="hidden">
                                    <div class="text-center mb-2">
                                        <div id="customDateMessage" class="text-gray-500 text-sm">Kamu belum pilih tanggal</div>
                                    </div>
                                    <div id="flatpickrContainer"></div>
                                </div>
                            </div>
                        </div>
                    </div>
                </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">
                <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>
    <?php endif; ?>

    <!-- 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>
                        <!-- Ulang Tahun -->
                        <div class="px-4 py-2 text-sm hover:bg-gray-100 cursor-pointer flex justify-between items-center group relative">
                            <span>Ulang Tahun</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="birthday" data-param="bornJan" data-value="true">
                                        <span>Januari</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="birthday" data-param="bornFeb" data-value="true">
                                        <span>Februari</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="birthday" data-param="bornMar" data-value="true">
                                        <span>Maret</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="birthday" data-param="bornApr" data-value="true">
                                        <span>April</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="birthday" data-param="bornMay" data-value="true">
                                        <span>Mei</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="birthday" data-param="bornJun" data-value="true">
                                        <span>Juni</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="birthday" data-param="bornJul" data-value="true">
                                        <span>Juli</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="birthday" data-param="bornAug" data-value="true">
                                        <span>Agustus</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="birthday" data-param="bornSep" data-value="true">
                                        <span>September</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="birthday" data-param="bornOct" data-value="true">
                                        <span>Oktober</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="birthday" data-param="bornNov" data-value="true">
                                        <span>November</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="birthday" data-param="bornDec" data-value="true">
                                        <span>Desember</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="loyal">Pelanggan Loyal</option>
                        <option value="royal">Pelanggan Royal</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 alamat pelanggan"
                    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="customers-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 allCustomers = [];
    let debounceTimer;
    let searchDebounceTimer;


    // 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"]');

    // Date Filter
    const dateFilterDropdown = document.getElementById('dateFilterDropdown');
    const dateFilterButton = dateFilterDropdown.querySelector('button');
    const dateFilterMenu = document.getElementById('dateFilterMenu');
    const dateFilterText = document.getElementById('dateFilterText');
    const dateOptions = document.querySelectorAll('.date-option');
    const customDateOption = document.getElementById('customDateOption');
    const customDateIndicator = document.getElementById('customDateIndicator');
    const calendarContainer = document.getElementById('calendarContainer');
    const predefinedDateInfo = document.getElementById('predefinedDateInfo');
    const dateDisplays = document.querySelectorAll('#dateDisplays > div');
    // Current active option
    let activeOption = 'today';
    // Initialize flatpickr calendar
    let flatpickrInstance = null;

    const BASE_URL_IMAGE = "<?= base_url('uploads/product') ?>";
    const BASE_URL_PRODUCT = "<?= base_url('product') ?>";
    const BASE_URL_FETCH_DATA = "<?= base_url('admin/customers/get_customers') ?>";
    const BASE_URL = "<?= base_url('admin/customers') ?>";
    const ADD_CUSTOMER_URL = "<?= base_url('admin/customers/add') ?>";
    const BASE_URL_DETAIL = "<?= base_url('admin/customers/detail/') ?>";

    document.addEventListener("DOMContentLoaded", function() {
        // 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(() => {
                searchCustomers(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(allCustomers);
        //         } else if (format === "excel") {
        //             downloadOrdersExcel(allCustomers);
        //         } else if (format === "pdf") {
        //             downloadOrdersPDF(allCustomers);
        //         }

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

        // Date Filter
        // Toggle dropdown
        dateFilterButton.addEventListener('click', function() {
            dateFilterMenu.classList.toggle('hidden');
        });

        // Close dropdown when clicking outside
        document.addEventListener('click', function(event) {
            if (!dateFilterDropdown.contains(event.target)) {
                dateFilterMenu.classList.add('hidden');
            }
        });

        // Handle date option selection
        dateOptions.forEach(option => {
            option.addEventListener('click', function() {
                const optionType = this.getAttribute('data-option');
                // Set this as the active option
                activeOption = optionType;
                // Update visual indicators
                dateOptions.forEach(opt => {
                    opt.classList.remove('bg-gray-100');
                });
                this.classList.add('bg-gray-100');
                // Hide all date displays first
                dateDisplays.forEach(display => {
                    display.classList.add('hidden');
                });
                if (optionType === 'customDate') {
                    // Show calendar for custom date
                    predefinedDateInfo.classList.add('hidden');
                    calendarContainer.classList.remove('hidden');
                    customDateIndicator.classList.remove('hidden');
                    // Initialize calendar if not already
                    initializeCalendar();
                } else {
                    // Show the relevant date display
                    predefinedDateInfo.classList.remove('hidden');
                    calendarContainer.classList.add('hidden');
                    customDateIndicator.classList.add('hidden');
                    // Show corresponding date info
                    const correspondingDisplay = document.getElementById(`${optionType}DateDisplay`);
                    if (correspondingDisplay) {
                        correspondingDisplay.classList.remove('hidden');
                    }
                    // Get date text to update the main button
                    const dateInfo = document.getElementById(`${optionType}Date`);
                    if (dateInfo) {
                        const optionText = this.querySelector('div').innerText;
                        dateFilterText.innerText = `${optionText} (${dateInfo.innerText})`;
                    } else {
                        dateFilterText.innerText = this.querySelector('div').innerText;
                    }
                    // Close dropdown after a slight delay to show the selection
                    setTimeout(() => {
                        dateFilterMenu.classList.add('hidden');
                    }, 300);

                    // Tambahkan param date_filter ke URL dan fetch data
                    updateURLAndFetch('date_filter', optionType);
                }
            });
        });

        function initializeCalendar() {
            if (flatpickrInstance === null && typeof flatpickr !== 'undefined') {
                // Create an input element for flatpickr
                if (!document.getElementById('dateRangePicker')) {
                    const input = document.createElement('input');
                    input.type = 'text';
                    input.id = 'dateRangePicker';
                    input.className = 'hidden';
                    document.getElementById('flatpickrContainer').appendChild(input);
                }

                // Initialize flatpickr
                flatpickrInstance = flatpickr("#dateRangePicker", {
                    mode: "range",
                    inline: true,
                    dateFormat: "d M Y",
                    maxDate: "today",
                    locale: {
                        rangeSeparator: " - ",
                        firstDayOfWeek: 1,
                        weekdays: {
                            shorthand: ['Min', 'Sen', 'Sel', 'Rab', 'Kam', 'Jum', 'Sab'],
                            longhand: ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu']
                        },
                        months: {
                            shorthand: ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agu', 'Sep', 'Okt', 'Nov', 'Des'],
                            longhand: ['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember']
                        }
                    },
                    onChange: function(selectedDates, dateStr) {
                        if (selectedDates.length === 2) {
                            document.getElementById('customDateMessage').innerText = dateStr;
                        } else if (selectedDates.length === 1) {
                            document.getElementById('customDateMessage').innerText = 'Pilih tanggal akhir';
                        } else {
                            document.getElementById('customDateMessage').innerText = 'Kamu belum pilih tanggal';
                        }
                    },
                    onClose: function(selectedDates, dateStr) {
                        if (selectedDates.length === 2) {
                            // Update the custom date message
                            document.getElementById('customDateMessage').innerText = dateStr;
                            // Update the main filter text
                            dateFilterText.innerText = `Pilih Tanggal (${dateStr})`;
                            // Close the dropdown
                            dateFilterMenu.classList.add('hidden');

                            // Simpan tanggal yang dipilih untuk digunakan dalam updateURLAndFetch
                            const startDate = formatDateForApi(selectedDates[0]);
                            const endDate = formatDateForApi(selectedDates[1]);

                            // Update URL and fetch data dengan custom date
                            updateURLAndFetch('date_filter', 'custom', {
                                start_date: startDate,
                                end_date: endDate
                            });
                        }
                    }
                });

                // Customize calendar appearance
                const calendarElement = document.querySelector('.flatpickr-calendar');
                if (calendarElement) {
                    calendarElement.classList.add('shadow-none', 'border-0');
                }
            }
        }

        // Helper function to format date for API
        function formatDateForApi(date) {
            return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`;
        }

        // Update date values on page load
        updateDateLabels();

        // Set today as active by default
        const todayOption = document.querySelector('[data-option="today"]');
        if (todayOption) {
            todayOption.classList.add('bg-gray-100');
            document.getElementById('todayDateDisplay').classList.remove('hidden');
        }
        // Fetch data customer infinite scroll
        window.addEventListener('scroll', () => {
            if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight - 500) {
                fetchCustomers(new URLSearchParams(window.location.search), true);
            }
        });

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

            window.open(`${ADD_CUSTOMER_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();
    });

    function updateDateLabels() {
        const now = new Date();
        const today = new Date(now);
        const yesterday = new Date(now);
        yesterday.setDate(yesterday.getDate() - 1);

        // Update the month title
        document.getElementById('currentMonthTitle').innerText =
            today.toLocaleDateString('id-ID', {
                month: 'long',
                year: 'numeric'
            });

        // Format function for dates
        function formatDate(date) {
            return date.toLocaleDateString('id-ID', {
                day: '2-digit',
                month: 'short',
                year: 'numeric'
            }).replace('.', '');
        }

        function formatDateRange(start, end) {
            return `${formatDate(start)} - ${formatDate(end)}`;
        }

        // Today with real time
        const hour = now.getHours();
        const minute = now.getMinutes();
        document.getElementById('todayDate').innerText =
            `${formatDate(today)} (00:00 - ${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')})`;

        // Yesterday
        document.getElementById('yesterdayDate').innerText = formatDate(yesterday);

        // Last 7 days
        const last7Start = new Date(now);
        last7Start.setDate(last7Start.getDate() - 7);
        const last7End = new Date(yesterday);
        document.getElementById('last7daysDate').innerText = formatDateRange(last7Start, last7End);

        // Last 30 days
        const last30Start = new Date(now);
        last30Start.setDate(last30Start.getDate() - 30);
        const last30End = new Date(yesterday);
        document.getElementById('last30daysDate').innerText = formatDateRange(last30Start, last30End);

        // This month
        const thisMonthStart = new Date(now.getFullYear(), now.getMonth(), 1);
        const thisMonthEnd = new Date(now.getFullYear(), now.getMonth() + 1, 0);
        document.getElementById('thisMonthDate').innerText = formatDateRange(thisMonthStart, thisMonthEnd);
    }

    // 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);
                    fetchCustomers(params, true); // true means append instead of replace
                }
            }
        });
    }

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

        // Reset checkbox filter
        filterCheckboxes.forEach(checkbox => {
            checkbox.checked = false;
        });

        // Reset filter tanggal
        document.getElementById("dateFilterText").innerText = "Hari ini (" + new Date().toLocaleDateString('id-ID') + ")";

        // 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);

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

            // Handle parameter date
            if (paramName === 'date_filter') {
                // Jika date_filter adalah custom, tambahkan extraParams
                if (value === 'custom' && extraParams) {
                    for (const [key, val] of Object.entries(extraParams)) {
                        params.set(key, val);
                    }
                } else if (value !== 'custom') {
                    // Hapus parameter start_date dan end_date jika bukan custom
                    params.delete('start_date');
                    params.delete('end_date');
                }
            }

            // 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;
            allCustomers = [];

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

            // Fetch customers with new parameters (replace mode)
            fetchCustomers(params, false);
        }, 300);
    }

    function fetchCustomers(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');
        progressBar.classList.remove('hidden');
        fetch(url)
            .then(res => res.json())
            .then(data => {
                progressBar.classList.add('hidden');
                if (data.length === 0) {
                    hasMoreData = false;

                    if (!append) {
                        const container = document.getElementById('customers-container');
                        container.innerHTML = '<div class="flex justify-center items-center p-8 text-gray-500">Tidak ada pelanggan yang ditemukan</div>';
                    }
                } else {
                    if (!append) {
                        allCustomers = data;
                    } else {
                        allCustomers = [...allCustomers, ...data];
                    }
                    console.log(allCustomers);
                    renderCustomers(data, append);
                    currentPage++;
                }

                isFetching = false;
            })
            .catch(error => {
                progressBar.classList.add('hidden');
                console.error('Error fetching customers:', error);
                isFetching = false;

                // Tampilkan pesan error
                const container = document.getElementById('customers-container');
                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 renderCustomers(customers, append = false) {
        const container = document.getElementById('customers-container');
        const loadingMore = document.getElementById('loading-more');

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

        if (!customers || customers.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 = 'my-6';
            tableWrapper.innerHTML = `
            <table class="min-w-full">
                <thead>
                    <tr class="bg-gray-50 border-b border-gray-200">
                        <th scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Pelanggan</th>
                        <th scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Umur</th>
                        <th scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Bergabung</th>
                        <th scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Alamat Lengkap</th>
                        <th scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Total Pembelian</th>
                        <th scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Aksi</th>
                    </tr>
                </thead>
                <tbody id="customers-table-body" class="bg-white divide-y divide-gray-200">
                </tbody>
            </table>
        `;
            container.appendChild(tableWrapper);
        }

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

        customers.forEach(customer => {
            const row = document.createElement('tr');
            row.className = 'border-b hover:bg-gray-50 transition-all duration-200';

            // Persiapkan alamat lengkap
            const address = [
                customer.address,
                customer.shipping_subdistrict,
                customer.shipping_district,
                customer.shipping_province
            ].filter(Boolean).join(', ');

            // Format tanggal lahir
            const birthdate = customer.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">${customer.name.charAt(0).toUpperCase()}</span>
                        </div>
                        <div class="ml-4">
                            <div class="text-sm font-medium text-gray-900">${customer.name}</div>
                            <div class="text-sm text-gray-500">${customer.email}</div>
                            <div class="text-sm text-gray-500 mt-4 mb-2">
                                <span class="${customer.sex_type_class} text-xs">${customer.sex_type_text}</span>
                                <span class="${customer.sex_type_class} text-xs">${birthdate}</span>
                            </div>
                        </div>
                    </div>
                </td>
                <td class="px-4 py-3">
                    <span class="text-sm font-medium">${customer.age ?? '-'}</span>
                </td>
                <td class="px-4 py-3">
                    <div class="text-sm text-gray-900">${customer.join_date_formatted}</div>
                </td>
                <td class="px-4 py-3">
                    <div class="text-sm text-[#333] max-w-xs">${address || '-'}</div>
                </td>
                <td class="px-4 py-3">
                    <div class="text-sm font-medium text-gray-900">${customer.total_spent_formatted}</div>
                    <div class="text-sm text-gray-500">Order: ${customer.total_orders || 0}</div>
                </td>
                <td class="px-4 py-3 text-right text-sm font-medium space-y-2">
                    <div class="flex space-x-2">
                        <button data-id="${customer.id_customers}" class="customer-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="${customer.phone}" data-name="${customer.name}" 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 customerName = 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 ${customerName}`;
                window.open(whatsappURL, '_blank');
            });
        });

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

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

        // 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
        fetchCustomers(params, false);
    }
</script>

https://t.me/RX1948 - 2025