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

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /var/www/laciasmara.com/public_html/shop/application/views/admin_new/layouts/footer.php
</div>
<div id="sidebar-overlay" class="fixed inset-0 bg-black bg-opacity-50 z-[96] hidden md:hidden">
</div>
<!-- Tour Guide JS -->
<script src="<?= base_url('assets/admin/js/tour-guide.js') ?>"></script>
</body>

<!-- jsPDF -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/3.5.31/jspdf.plugin.autotable.min.js"></script>

<!-- Feather Icon -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/feather-icons/4.29.0/feather.min.js"></script>

<!-- Tom Select -->
<link href="https://cdn.jsdelivr.net/npm/tom-select@2.2.2/dist/css/tom-select.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/tom-select@2.2.2/dist/js/tom-select.complete.min.js"></script>

<!-- Text Editor -->
<script src="https://cdn.ckeditor.com/ckeditor5/36.0.1/classic/ckeditor.js"></script>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

<script src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.2/Sortable.min.js"></script>

<!-- Tambahkan SweetAlert2 -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>

<!-- Flatpickr CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
<script src="https://cdn.jsdelivr.net/npm/flatpickr/dist/l10n/id.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>

<script>
    const notyf = new Notyf({
        duration: 2000,
        position: {
            x: 'center',
            y: 'top'
        },
        ripple: false,
        types: [{
                type: 'success',
                background: '#2e3137',
                className: 'custom-notification',
                icon: false
            },
            {
                type: 'error',
                background: '#2e3137',
                className: 'custom-notification',
                icon: false
            }
        ]
    });

    document.addEventListener('DOMContentLoaded', function() {
        // Initialize Feather Icons
        feather.replace();
        // Handle collapsible menus
        document.querySelectorAll(".menu-item button").forEach(button => {
            button.addEventListener("click", function() {
                const submenu = this.nextElementSibling;
                const iconContainer = this.querySelector(".transform");
                const menuItem = this.closest(".menu-item");

                if (submenu) {
                    const isOpen = submenu.classList.contains("open");

                    // Close all other submenus
                    document.querySelectorAll(".submenu").forEach(menu => {
                        if (menu !== submenu) {
                            menu.classList.remove("open");
                            const menuButton = menu.previousElementSibling;
                            menuButton.querySelector(".transform")?.classList.remove("rotate-180");
                            menuButton.classList.remove("text-[#7A4397]");
                        }
                    });

                    // Toggle current submenu
                    submenu.classList.toggle("open", !isOpen);

                    // Toggle chevron rotation
                    if (iconContainer) {
                        iconContainer.classList.toggle("rotate-180", !isOpen);
                    }

                    // Toggle active color on button
                    button.classList.toggle("text-[#7A4397]", !isOpen);
                }
            });
        });

        // Make sure active menu stays open when page loads
        document.querySelectorAll(".menu-item.active").forEach(menuItem => {
            const submenu = menuItem.querySelector(".submenu");
            const button = menuItem.querySelector("button");
            const iconContainer = button?.querySelector(".transform");

            if (submenu && button) {
                submenu.classList.add("open");

                if (iconContainer) {
                    iconContainer.classList.add("rotate-180");
                }

                button.classList.add("text-[#7A4397]");
            }
        });

        const notificationBell = document.getElementById('notification-bell');
        const notificationCount = document.getElementById('notification-count');
        const notificationModal = document.getElementById('notification-modal');
        const notificationList = document.getElementById('notification-list');
        const markAllReadBtn = document.getElementById('mark-all-read');

        function loadNotificationCount() {
            fetch('<?= base_url('admin/dashboard/count_notification') ?>')
                .then(response => response.json())
                .then(data => {
                    if (data.count > 0) {
                        notificationCount.textContent = data.count > 9 ? '9+' : data.count;
                        notificationCount.style.display = 'block';
                    } else {
                        notificationCount.style.display = 'none';
                    }
                })
                .catch(error => console.error('Error loading notification count:', error));
        }

        // Fungsi untuk memuat daftar notifikasi
        function loadNotifications() {
            fetch('<?= base_url('admin/dashboard/list_notification') ?>')
                .then(response => response.json())
                .then(data => {
                    if (data.notifications && data.notifications.length > 0) {
                        let notificationHTML = '';

                        data.notifications.forEach(notification => {
                            const isUnread = notification.is_read == 0 ? 'unread' : '';
                            const timeAgo = getTimeAgo(new Date(notification.created_at));

                            notificationHTML += `
                                <div class="notification-item ${isUnread}" data-id="${notification.notification_id}" data-url="${notification.reference_url}">
                                    <div class="flex justify-between items-start">
                                        <div class="flex-1 pr-4">
                                            <p class="text-sm mb-1">${notification.message}</p>
                                            <span class="text-xs text-gray-500">${timeAgo}</span>
                                        </div>
                                        ${notification.is_read == 0 ? '<div class="w-2 h-2 bg-blue-500 rounded-full"></div>' : ''}
                                    </div>
                                </div>
                            `;
                        });

                        notificationList.innerHTML = notificationHTML;

                        // Tambahkan event listener untuk setiap notifikasi
                        document.querySelectorAll('.notification-item').forEach(item => {
                            item.addEventListener('click', function() {
                                const notifId = this.getAttribute('data-id');
                                markAsRead(notifId, this);
                            });
                        });

                    } else {
                        notificationList.innerHTML = '<div class="notification-empty">Tidak ada notifikasi baru</div>';
                    }
                })
                .catch(error => console.error('Error loading notifications:', error));
        }


        // Fungsi untuk menandai notifikasi sudah dibaca
        function markAsRead(notificationId, element) {
            let csrfToken = '<?= $this->security->get_csrf_hash(); ?>';
            const csrfName = '<?= $this->security->get_csrf_token_name(); ?>';
            const formData = new FormData();
            formData.append('notification_id', notificationId);
            formData.append(csrfName, csrfToken); // Tambahkan CSRF token

            fetch('<?= base_url('admin/dashboard/mark_read') ?>', {
                    method: 'POST',
                    body: formData,
                    headers: {
                        'X-Requested-With': 'XMLHttpRequest' // Pastikan ini agar dikenali sebagai AJAX request
                    }
                })
                .then(response => response.json())
                .then(data => {
                    if (data.success) {
                        let refUrl = element.getAttribute('data-url');

                        // Update UI
                        element.classList.remove('unread');
                        const blueIndicator = element.querySelector('.bg-blue-500');
                        if (blueIndicator) {
                            blueIndicator.remove();
                        }

                        loadNotificationCount();

                        // Redirect jika ada URL referensi
                        if (refUrl) {
                            window.location.href = refUrl;
                        }

                        // Update CSRF token setelah request berhasil
                        csrfToken = data.csrf_token;
                    }
                })
                .catch(error => console.error('Error marking notification as read:', error));
        }


        // console.log(<?= $this->session->userdata('user_id') ?>)
        // Fungsi untuk menandai semua notifikasi sudah dibaca
        function markAllAsRead() {
            let csrfToken = '<?= $this->security->get_csrf_hash(); ?>';
            const csrfName = '<?= $this->security->get_csrf_token_name(); ?>';
            const formData = new FormData();
            formData.append(csrfName, csrfToken);

            fetch('<?= base_url('admin/dashboard/mark_all_read') ?>', {
                    method: 'POST',
                    body: formData
                })
                .then(response => response.json())
                .then(data => {
                    if (data.success) {
                        // Perbarui UI
                        document.querySelectorAll('.notification-item.unread').forEach(item => {
                            item.classList.remove('unread');
                            const blueIndicator = item.querySelector('.bg-blue-500');
                            if (blueIndicator) {
                                blueIndicator.remove();
                            }
                        });

                        // Perbarui jumlah notifikasi
                        const notificationCount = document.getElementById('notification-count');
                        if (notificationCount) {
                            notificationCount.style.display = 'none';
                        }
                    }
                })
                .catch(error => console.error('Error marking all notifications as read:', error));
        }

        // Fungsi helper untuk format waktu relatif (time ago)
        function getTimeAgo(date) {
            const seconds = Math.floor((new Date() - date) / 1000);

            let interval = Math.floor(seconds / 31536000);
            if (interval > 1) return interval + ' tahun yang lalu';

            interval = Math.floor(seconds / 2592000);
            if (interval > 1) return interval + ' bulan yang lalu';

            interval = Math.floor(seconds / 86400);
            if (interval > 1) return interval + ' hari yang lalu';

            interval = Math.floor(seconds / 3600);
            if (interval > 1) return interval + ' jam yang lalu';

            interval = Math.floor(seconds / 60);
            if (interval > 1) return interval + ' menit yang lalu';

            return 'Baru saja';
        }

        // Event listener untuk toggle modal notifikasi
        notificationBell.addEventListener('click', function(e) {
            e.stopPropagation();
            const isVisible = notificationModal.style.display === 'block';

            if (!isVisible) {
                notificationModal.style.display = 'block';
                loadNotifications();
            } else {
                notificationModal.style.display = 'none';
            }
        });

        // Event listener untuk tombol "tandai semua dibaca"
        markAllReadBtn.addEventListener('click', function(e) {
            e.stopPropagation();
            markAllAsRead();
        });

        // Tutup modal saat klik di luar
        document.addEventListener('click', function(e) {
            if (notificationModal.style.display === 'block' &&
                !notificationModal.contains(e.target) &&
                !notificationBell.contains(e.target)) {
                notificationModal.style.display = 'none';
            }
        });

        // Muat jumlah notifikasi saat halaman dimuat
        loadNotificationCount();

        // Polling untuk memperbarui jumlah notifikasi setiap 30 detik
        setInterval(loadNotificationCount, 30000);

        initializeSearchContainer();

        const sidebar = document.getElementById('sidebar');
        const sidebarToggle = document.getElementById('sidebar-toggle');
        const sidebarOverlay = document.getElementById('sidebar-overlay');

        const originalSidebarClasses = sidebar.className;

        // Track sidebar state without localStorage
        let sidebarCollapsed = false;

        // Function to toggle mobile sidebar
        function toggleMobileSidebar() {
            if (isMobile()) {
                sidebar.classList.toggle('-translate-x-full');
                sidebarOverlay.classList.toggle('hidden');
            }
        }
        // Definisi yang jelas untuk deteksi mobile
        function isMobile() {
            return window.innerWidth < 768; // 768px adalah breakpoint md di Tailwind
        }

        // Apply initial sidebar state
        function initSidebar() {
            // Cek apakah di mobile atau desktop
            if (isMobile()) {
                // Hanya atur sidebar di mobile
                sidebar.classList.add('-translate-x-full'); // Sembunyikan sidebar di mobile secara default

                // Pastikan overlay tersembunyi
                if (sidebarOverlay) {
                    sidebarOverlay.classList.add('hidden');
                }
            } else {
                sidebar.classList.remove('-translate-x-full');
                sidebar.classList.add('md:translate-x-0');

                sidebarCollapsed = false;
            }
        }

        // Toggle sidebar on click
        if (sidebarToggle) {
            sidebarToggle.addEventListener('click', (e) => {
                e.preventDefault();
                if (isMobile()) {
                    toggleMobileSidebar();
                }
            });
        }

        // Hide sidebar when clicking overlay
        if (sidebarOverlay) {
            sidebarOverlay.addEventListener('click', toggleMobileSidebar);
        }

        // Toggle mobile search
        if (mobileSearchToggle && mobileSearch) {
            mobileSearchToggle.addEventListener('click', () => {
                mobileSearch.classList.toggle('hidden');
            });
        }

        // Toggle notification modal
        if (notificationBell && notificationModal) {
            notificationBell.addEventListener('click', (e) => {
                e.stopPropagation();
                notificationModal.classList.toggle('hidden');
            });

            // Close notification modal when clicking outside
            document.addEventListener('click', (event) => {
                if (notificationModal && notificationBell &&
                    !notificationBell.contains(event.target) &&
                    !notificationModal.contains(event.target)) {
                    notificationModal.classList.add('hidden');
                }
            });
        }

        document.querySelectorAll('.menu-item > button').forEach(btn => {
            btn.addEventListener('click', () => {
                if (isMobile()) {
                    const submenu = btn.nextElementSibling;

                    // Safely get arrow element
                    const arrowEl = btn.querySelector('.sidebar-arrow i');
                    if (!submenu || !arrowEl) return;

                    const arrow = arrowEl.parentElement;

                    // Toggle submenu visibility
                    submenu.classList.toggle('hidden');
                    arrow.classList.toggle('rotate-180');

                    // Close other submenus
                    document.querySelectorAll('.menu-item > button').forEach(otherBtn => {
                        if (otherBtn !== btn) {
                            const otherSubmenu = otherBtn.nextElementSibling;
                            const otherArrowEl = otherBtn.querySelector('.sidebar-arrow i');

                            if (!otherSubmenu || !otherArrowEl) return;

                            const otherArrow = otherArrowEl.parentElement;
                            const otherMenuItem = otherBtn.parentElement;

                            if (!otherSubmenu.classList.contains('hidden') &&
                                !otherMenuItem.classList.contains('active')) {
                                otherSubmenu.classList.add('hidden');
                                otherArrow.classList.remove('rotate-180');
                            }
                        }
                    });
                }
            });
        });

        // Handle window resize
        window.addEventListener('resize', () => {
            initSidebar();
        });
    });

    // Search
    const barSearchInput = document.getElementById('globalSearch');
    const mobileSearchInput = document.querySelector('#mobile-search input');
    const searchOverlay = document.getElementById('search-overlay');
    const searchBody = document.body;
    const mobileSearchToggle = document.getElementById('mobile-search-toggle');
    const mobileSearch = document.getElementById('mobile-search');

    const isMobile = () => window.innerWidth <= 768;

    function getActiveSearchInput() {
        return isMobile() ? mobileSearchInput : barSearchInput;
    }

    // Initialize search container and ensure it's responsive
    function initializeSearchContainer() {
        let suggestionsContainer = document.getElementById('search-suggestions');

        if (!suggestionsContainer) {
            suggestionsContainer = document.createElement('div');
            suggestionsContainer.id = 'search-suggestions';

            // Styling dasar
            suggestionsContainer.className = `
                bg-white border border-gray-200 
                rounded-md shadow-lg max-h-64 overflow-y-auto hidden z-50
            `;

            // Styling berbeda untuk mobile vs desktop
            if (isMobile()) {
                suggestionsContainer.classList.add('fixed', 'left-0', 'right-0', 'top-[120px]', 'max-w-full', 'mx-4', 'my-2');
                // Tambahkan ke mobile search container
                document.getElementById('mobile-search').appendChild(suggestionsContainer);
            } else {
                suggestionsContainer.classList.add('absolute', 'left-0', 'right-0', 'top-full', 'mt-2', 'w-full');
                // Tambahkan ke desktop search container
                barSearchInput.parentElement.classList.add('relative');
                barSearchInput.parentElement.appendChild(suggestionsContainer);
            }
        }

        return suggestionsContainer;
    }


    // Responsive search focus handling
    barSearchInput.addEventListener('focus', () => {
        searchOverlay.classList.remove('opacity-0', 'pointer-events-none');
        searchOverlay.classList.add('opacity-100', 'pointer-events-auto');
        searchBody.classList.add('overflow-hidden');

        // Special handling for mobile
        if (isMobile()) {
            // Expand search input on mobile when focused
            barSearchInput.classList.add('w-full');
            barSearchInput.parentElement.classList.add('w-full', 'absolute', 'left-0', 'px-4');
        }
    });

    barSearchInput.addEventListener('blur', () => {
        searchOverlay.classList.remove('opacity-100', 'pointer-events-auto');
        searchOverlay.classList.add('opacity-0', 'pointer-events-none');
        searchBody.classList.remove('overflow-hidden');

        // Reset mobile-specific classes with slight delay to allow for click actions
        if (isMobile()) {
            setTimeout(() => {
                if (!barSearchInput.matches(':focus')) {
                    barSearchInput.classList.remove('w-full');
                    barSearchInput.parentElement.classList.remove('w-full', 'absolute', 'left-0', 'px-4');
                }
            }, 150);
        }
    });

    // Keyboard shortcut for search
    document.addEventListener('keydown', function(event) {
        if ((event.ctrlKey || event.metaKey) && event.key === '/') {
            event.preventDefault();
            barSearchInput.focus();
        }
    });

    // Overlay click handling
    searchOverlay.addEventListener('click', () => {
        barSearchInput.blur();
        const suggestionsContainer = document.getElementById('search-suggestions');
        if (suggestionsContainer) {
            suggestionsContainer.classList.add('hidden');
        }
    });

    // Debounce function
    function debounce(func, delay) {
        let timeoutId;
        return function() {
            const context = this;
            const args = arguments;
            clearTimeout(timeoutId);
            timeoutId = setTimeout(() => func.apply(context, args), delay);
        };
    }

    // Fetch suggestions
    async function fetchSuggestions(query) {
        const BASE_URL = '<?= base_url() ?>';
        try {
            const response = await fetch(`${BASE_URL}admin/search/get_suggestions?query=${encodeURIComponent(query)}`);
            return await response.json();
        } catch (error) {
            console.error('Error fetching suggestions:', error);
            return [];
        }
    }

    // Render suggestions with responsive design
    function renderSuggestions(suggestions) {
        const suggestionsContainer = initializeSearchContainer();

        // Clear previous suggestions
        suggestionsContainer.innerHTML = '';

        if (suggestions.length === 0) {
            suggestionsContainer.classList.add('hidden');
            return;
        }

        // Add a header for mobile
        if (isMobile()) {
            const header = document.createElement('div');
            header.className = 'px-4 py-2 bg-gray-50 border-b font-medium text-[#333]';
            header.textContent = 'Hasil Pencarian';
            suggestionsContainer.appendChild(header);
        }

        suggestions.forEach((suggestion, index) => {
            const suggestionItem = document.createElement('div');

            // Enhanced responsive styling
            suggestionItem.className = `
                px-4 py-3 md:py-2 cursor-pointer hover:bg-gray-100
                flex items-center gap-2
                ${index === 0 ? 'bg-gray-50' : ''}
                transition duration-200 ease-in-out
                border-b border-gray-100 last:border-0
            `;

            // Create icon container (optional)
            const iconContainer = document.createElement('div');
            iconContainer.className = 'text-gray-400';
            iconContainer.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><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>';

            // Text container
            const textContainer = document.createElement('div');
            textContainer.className = 'flex-1';

            // Highlight matching text
            const query = barSearchInput.value.toLowerCase();
            const title = suggestion.title;
            const matchIndex = title.toLowerCase().indexOf(query);

            if (matchIndex !== -1) {
                const beforeMatch = title.slice(0, matchIndex);
                const match = title.slice(matchIndex, matchIndex + query.length);
                const afterMatch = title.slice(matchIndex + query.length);

                textContainer.innerHTML = `
                ${beforeMatch}<span class="font-bold text-purple-600">${match}</span>${afterMatch}
            `;
            } else {
                textContainer.textContent = title;
            }

            // For mobile, add a subtitle/category if available
            if (isMobile() && suggestion.category) {
                const subtitle = document.createElement('div');
                subtitle.className = 'text-xs text-gray-500 mt-1';
                subtitle.textContent = suggestion.category;
                textContainer.appendChild(subtitle);
            }

            suggestionItem.appendChild(iconContainer);
            suggestionItem.appendChild(textContainer);

            suggestionItem.addEventListener('click', () => {
                window.location.href = suggestion.link;
            });

            suggestionsContainer.appendChild(suggestionItem);
        });

        suggestionsContainer.classList.remove('hidden');
    }

    // Search handler with debounce
    const handleSearch = debounce(async function() {
        const activeInput = getActiveSearchInput();
        const query = activeInput.value.trim();

        if (query.length < 2) {
            const suggestionsContainer = document.getElementById('search-suggestions');
            if (suggestionsContainer) {
                suggestionsContainer.classList.add('hidden');
            }
            return;
        }

        const suggestions = await fetchSuggestions(query);
        renderSuggestions(suggestions);
    }, 300);

    // Event listeners
    barSearchInput.addEventListener('input', handleSearch);

    // Close suggestions when clicking outside
    document.addEventListener('click', (event) => {
        const suggestionsContainer = document.getElementById('search-suggestions');
        if (suggestionsContainer &&
            !barSearchInput.contains(event.target) &&
            !suggestionsContainer.contains(event.target)) {
            suggestionsContainer.classList.add('hidden');
        }
    });

    // Handle window resize for responsive adjustments
    window.addEventListener('resize', debounce(() => {
        // Reposisi suggestion container saat ukuran layar berubah
        const suggestionsContainer = document.getElementById('search-suggestions');
        if (suggestionsContainer) {
            // Hapus container lama dan buat ulang dengan posisi yang tepat
            suggestionsContainer.remove();
            initializeSearchContainer();
        }
    }, 250));

    mobileSearchInput.addEventListener('input', handleSearch);
    mobileSearchInput.addEventListener('focus', () => {
        // Logika focus untuk mobile
        searchOverlay.classList.remove('opacity-0', 'pointer-events-none');
        searchOverlay.classList.add('opacity-100', 'pointer-events-auto');
        searchBody.classList.add('overflow-hidden');
    });

    mobileSearchInput.addEventListener('blur', () => {
        // Logika blur untuk mobile
        searchOverlay.classList.remove('opacity-100', 'pointer-events-auto');
        searchOverlay.classList.add('opacity-0', 'pointer-events-none');
        searchBody.classList.remove('overflow-hidden');
    });
</script>

</html>

https://t.me/RX1948 - 2025