// SNAPSHOT import './bootstrap'; import { createPopper } from "@popperjs/core"; import focus from "@alpinejs/focus"; import tagifyMin from "@yaireo/tagify"; import Echo from 'laravel-echo'; import Pusher from 'pusher-js'; import { Chart, registerables } from 'chart.js'; import './presence-tracker.js'; import './return-ratio-chart.js'; import './account-balances-chart.js'; Alpine.plugin(focus); // Register Chart.js globally Chart.register(...registerables); window.Chart = Chart; window.createPopper = createPopper; window.Tagify = tagifyMin; // Needs to be loaded after Alpine // Lazy-load JSZip (used by backup restore chunked upload) window.loadJSZip = () => import('jszip').then(m => m.default); // Alpine component for the call tag picker (livewire:calls.call-skill-input) // Registered via Alpine.data() so Alpine can resolve it when Livewire morphs in new DOM nodes. document.addEventListener('alpine:init', () => { Alpine.data('callTagPicker', () => ({ callTagify: null, init() { const input = this.$refs.callTagsInput; const suggestions = JSON.parse(input.dataset.suggestions || '[]'); this.callTagify = new Tagify(input, { maxTags: 1, whitelist: suggestions, enforceWhiteList: false, backspace: false, editTags: false, addTagOn: ['enter', 'tab'], addTagOnBlur: false, dropdown: { maxItems: 10, enabled: 2, closeOnSelect: true, highlightFirst: true, }, }); // Pre-populate with initial value from server (e.g. edit modal) const initialTags = this.$wire.get('tagsArray'); if (initialTags && initialTags !== '[]') { this.callTagify.loadOriginalValues(initialTags); } this.callTagify.on('change', () => { // Read from the actual input element — e.target can be a #text node in Tagify const rawValue = this.$refs.callTagsInput.value; const tags = JSON.parse(rawValue || '[]'); if (tags.length === 0) { this.$wire.set('tagsArray', '[]', false); this.$wire.call('notifyTagCleared'); return; } const tag = tags[0]; if (tag.tag_id) { // Known tag — sync and notify parent this.$wire.set('tagsArray', rawValue, false); this.$wire.call('notifyTagSelected', tag.tag_id); } else { // Unknown tag — open creation modal (no set() to avoid re-render race) this.$wire.call('openNewTagModal', tag.value); } }); // Server asks us to remove the pending unconfirmed tag (cancel modal) window.addEventListener('removeLastCallTag', () => { if (this.callTagify && this.callTagify.value.length > 0) { this.callTagify.removeTag( this.callTagify.value[this.callTagify.value.length - 1].value ); } }); // Server pushes a new tagsArray after createTag — reload Tagify with colored badge Livewire.on('callTagifyReload', (data) => { this.callTagify.loadOriginalValues(data.tagsArray); }); } })); }); window.Pusher = Pusher; // Get the current locale from the URL (e.g., /en/, /nl/, etc.) const getLocalePrefix = () => { const pathParts = window.location.pathname.split('/').filter(Boolean); const locales = ['en', 'nl', 'de', 'es', 'fr']; if (pathParts.length > 0 && locales.includes(pathParts[0])) { return `/${pathParts[0]}`; } return '/en'; // Default to English if no locale found }; window.Echo = new Echo({ broadcaster: 'reverb', key: import.meta.env.VITE_REVERB_APP_KEY, wsHost: import.meta.env.VITE_REVERB_HOST, wsPort: import.meta.env.VITE_REVERB_PORT ?? 80, wssPort: import.meta.env.VITE_REVERB_PORT ?? 443, wsPath: import.meta.env.VITE_REVERB_PATH ?? "/", forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? "https") === "https", enabledTransports: ['ws', 'wss'], authEndpoint: `${getLocalePrefix()}/broadcasting/auth`, auth: { headers: { 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') } } });