const { ref, reactive } = Vue; const HUBS = [ { id: 'DE', name: 'GERMANY HUB (DE)' }, { id: 'IT', name: 'ITALY HUB (IT)' }, { id: 'FR', name: 'FRANCE HUB (FR)' }, { id: 'GB', name: 'UNITED KINGDOM (GB)' }, { id: 'ES', name: 'SPAIN HUB (ES)' }, { id: 'AE', name: 'UAE HUB (AE)' }, { id: 'PL', name: 'POLAND HUB (PL)' } ]; const DEPARTMENTS = ['Support', 'Technical', 'Sales', 'VIP', 'Billing']; const ROLES = ['Senior Lead', 'Specialist', 'Agent']; const SKILLS = [ 'English', 'German', 'French', 'Molecular App', 'Hardware', 'Billing Specialist', 'VIP Concierge', 'Technical Training' ]; const SHIFTS = [ { id: 'm', label: 'MORNING', color: 'green-7', badgeClass: 'day-cell-shift-badge-green' }, { id: 'a', label: 'AFTERNOON', color: 'blue-7', badgeClass: 'day-cell-shift-badge-blue' }, { id: 'h', label: 'HOTLINE', color: 'indigo-7', badgeClass: 'day-cell-shift-badge-indigo' }, { id: 'e', label: 'EOD ONLY', color: 'pink-7', badgeClass: 'day-cell-shift-badge-pink' } ]; const agents = ref([]); const loading = ref(false); const lockedCells = ref(new Set()); const onlineUsers = ref([]); const assignments = reactive({}); const comments = reactive({}); const notes = reactive({}); const holidays = reactive({}); const specialDays = reactive({}); const MOCK_COMMENTS_TEXT = [ 'Late arrival expected.', 'Dental appointment.', 'Swapped shift.', 'Priority focus.', 'Remote session.' ]; const MOCK_NOTES_TEXT = [ 'Headset check.', 'VPN slow.', 'Training session.', 'Backup Billing.', 'Overtime pending.' ]; const ONLINE_USER_ROLES = ['Planner', 'Scheduler', 'Lead', 'Manager']; const ONLINE_USERS_POOL = Array.from({ length: 28 }, (_, i) => { const pravatarId = (i % 70) + 1; return { id: i + 1, name: `User ${i + 1}`, role: ONLINE_USER_ROLES[i % ONLINE_USER_ROLES.length], img: `https://i.pravatar.cc/150?img=${pravatarId}` }; }); const formatDateForId = (date) => { if (!date) return ''; const d = new Date(date); const month = '' + (d.getMonth() + 1); const day = '' + d.getDate(); const year = d.getFullYear(); return [year, month.padStart(2, '0'), day.padStart(2, '0')].join('-'); }; const generateMockAgents = (count) => { return Array.from({ length: count }, (_, i) => { const hub = HUBS[Math.floor(Math.random() * HUBS.length)]; return { id: i + 1, name: `Agent ${i + 1}`, dept: DEPARTMENTS[i % DEPARTMENTS.length], role: ROLES[i % ROLES.length], hub: hub.id, hubName: hub.name, skills: [SKILLS[i % SKILLS.length], SKILLS[(i + 2) % SKILLS.length]], avatar: `https://api.dicebear.com/7.x/avataaars/svg?seed=Agent${i}` }; }); }; const loadDataFromDatabase = (startDate, notify) => { loading.value = true; setTimeout(() => { const fetchedAgents = generateMockAgents(800); agents.value = fetchedAgents; const mockStartDate = new Date(startDate); fetchedAgents.forEach(agent => { if (!assignments[agent.id]) assignments[agent.id] = {}; if (!comments[agent.id]) comments[agent.id] = {}; if (!notes[agent.id]) notes[agent.id] = {}; for (let i = 0; i < 60; i++) { const d = new Date(mockStartDate); d.setDate(d.getDate() + i); const dStr = formatDateForId(d); if ((agent.id + i) % 7 === 0) assignments[agent.id][dStr] = SHIFTS[0].id; else if ((agent.id + i) % 5 === 0) assignments[agent.id][dStr] = SHIFTS[1].id; if ((agent.id + i) % 20 === 0) comments[agent.id][dStr] = MOCK_COMMENTS_TEXT[(agent.id + i) % MOCK_COMMENTS_TEXT.length]; if ((agent.id + i) % 25 === 0) notes[agent.id][dStr] = MOCK_NOTES_TEXT[(agent.id + i) % MOCK_NOTES_TEXT.length]; } }); for (const key in holidays) delete holidays[key]; for (const key in specialDays) delete specialDays[key]; const today = new Date(); const tomorrow = new Date(today); tomorrow.setDate(today.getDate() + 1); holidays[formatDateForId(tomorrow)] = 'Regional Holiday'; const eventDay = new Date(today); eventDay.setDate(today.getDate() + 5); specialDays[formatDateForId(eventDay)] = 'Quarterly Planning'; loading.value = false; if (notify) { notify({ message: 'Data Loaded: 800 Agents', color: 'positive', position: 'top', timeout: 1000 }); } }, 2000); }; const handleWssMessage = (type, payload, notify) => { if (type === 'LOCK_CELL') { const key = `${payload.agentId}:${payload.date}`; lockedCells.value.add(key); const agent = agents.value.find(a => a.id === payload.agentId); const name = agent ? agent.name : 'Unknown Agent'; if (notify) { notify({ message: `WSS: Cell Locked for ${name} on ${payload.date}`, color: 'negative', position: 'top', icon: 'lock' }); } } }; const simulateWssLock = (notify) => { if (agents.value.length === 0) return; const randomAgent = agents.value[Math.floor(Math.random() * agents.value.length)]; let targetDate = new Date(); const day = targetDate.getDay(); if (day === 0) { targetDate.setDate(targetDate.getDate() + 1); } else if (day === 6) { targetDate.setDate(targetDate.getDate() + 2); } const dateStr = formatDateForId(targetDate); handleWssMessage('LOCK_CELL', { agentId: randomAgent.id, date: dateStr }, notify); }; const selectRandomItems = (list, count) => { const pool = [...list]; const selected = []; while (pool.length > 0 && selected.length < count) { const idx = Math.floor(Math.random() * pool.length); selected.push(pool.splice(idx, 1)[0]); } return selected; }; const seedOnlineUsers = (count = 7) => { onlineUsers.value = selectRandomItems(ONLINE_USERS_POOL, count); }; const simulateWssOnlineUsersChange = (notify) => { if (onlineUsers.value.length === 0) { seedOnlineUsers(3); return; } const maxOnline = 18; const minOnline = 1; const shouldAdd = Math.random() > 0.45; const current = [...onlineUsers.value]; if (shouldAdd && current.length < maxOnline) { const available = ONLINE_USERS_POOL.filter( user => !current.some(existing => existing.id === user.id) ); if (available.length === 0) return; const joiner = available[Math.floor(Math.random() * available.length)]; onlineUsers.value = [...current, joiner]; if (notify) { notify({ message: `WSS: ${joiner.name} joined`, color: 'grey-8', textColor: 'white', position: 'bottom-right', timeout: 700, icon: 'group_add' }); } return; } if (current.length > minOnline) { const leaverIndex = Math.floor(Math.random() * current.length); const [leaver] = current.splice(leaverIndex, 1); onlineUsers.value = current; if (notify) { notify({ message: `WSS: ${leaver.name} left`, color: 'grey-8', textColor: 'white', position: 'bottom-right', timeout: 700, icon: 'person_remove' }); } } }; const startOnlineUsersSimulation = (notify, options = {}) => { const minDelay = options.minDelay ?? 1800; const maxDelay = options.maxDelay ?? 5200; let timeoutId = null; let active = true; if (onlineUsers.value.length === 0) { seedOnlineUsers(options.seedCount ?? 7); } const scheduleNext = () => { if (!active) return; const delay = Math.floor(minDelay + Math.random() * (maxDelay - minDelay)); timeoutId = setTimeout(() => { simulateWssOnlineUsersChange(notify); scheduleNext(); }, delay); }; scheduleNext(); return () => { active = false; if (timeoutId) clearTimeout(timeoutId); }; }; export { HUBS, DEPARTMENTS, ROLES, SKILLS, SHIFTS, agents, loading, lockedCells, onlineUsers, assignments, comments, notes, holidays, specialDays, loadDataFromDatabase, handleWssMessage, simulateWssLock, seedOnlineUsers, simulateWssOnlineUsersChange, startOnlineUsersSimulation };