144 lines
4.3 KiB
JavaScript
144 lines
4.3 KiB
JavaScript
/**
|
|
* state.js — Shared reactive state store
|
|
* Uses Vue.reactive() for global state management.
|
|
* Replace with Pinia or API integration when backend is ready.
|
|
*/
|
|
|
|
function createStore() {
|
|
const today = new Date();
|
|
// Start on the most recent Monday
|
|
const dayOfWeek = today.getDay();
|
|
const mondayOffset = dayOfWeek === 0 ? -6 : 1 - dayOfWeek;
|
|
const startDate = new Date(today);
|
|
startDate.setDate(today.getDate() + mondayOffset);
|
|
const startDateStr = startDate.toISOString().split('T')[0];
|
|
|
|
const weekCount = 6;
|
|
const totalDays = weekCount * 7;
|
|
|
|
const schedule = generateSampleSchedule(AGENTS, startDate, totalDays);
|
|
const exnetTargets = generateExnetTargets(startDate, totalDays);
|
|
|
|
return Vue.reactive({
|
|
// --- Data ---
|
|
agents: [...AGENTS],
|
|
shiftTypes: [...SHIFT_TYPES],
|
|
exnetGroups: [...EXNET_GROUPS],
|
|
departments: [...DEPARTMENTS],
|
|
allSkills: [...SKILLS],
|
|
activeUsers: [...ACTIVE_USERS],
|
|
versionHistory: [...VERSION_HISTORY],
|
|
|
|
// --- Schedule ---
|
|
schedule: schedule,
|
|
exnetTargets: exnetTargets,
|
|
|
|
// --- View State ---
|
|
startDate: startDateStr,
|
|
weekCount: weekCount,
|
|
todayStr: today.toISOString().split('T')[0],
|
|
|
|
// --- Filters ---
|
|
searchQuery: '',
|
|
activeSkillFilters: [],
|
|
activeDepartmentFilter: '',
|
|
|
|
// --- Sidebar ---
|
|
sidebarOpen: false,
|
|
sidebarContext: null, // { agentId, dateStr }
|
|
|
|
// --- Cell Editing ---
|
|
editingCell: null, // { agentId, dateStr }
|
|
|
|
// --- UI ---
|
|
showVersionHistory: false,
|
|
});
|
|
}
|
|
|
|
/* --- Computed helpers (plain functions operating on store) --- */
|
|
|
|
function getDateRange(store) {
|
|
const dates = [];
|
|
const start = new Date(store.startDate);
|
|
const total = store.weekCount * 7;
|
|
for (let i = 0; i < total; i++) {
|
|
const d = new Date(start);
|
|
d.setDate(start.getDate() + i);
|
|
dates.push({
|
|
date: d,
|
|
dateStr: d.toISOString().split('T')[0],
|
|
dayName: d.toLocaleDateString('en-US', { weekday: 'short' }),
|
|
dayDate: d.toLocaleDateString('en-US', { day: 'numeric', month: 'short' }),
|
|
dayOfWeek: d.getDay(),
|
|
isToday: d.toISOString().split('T')[0] === store.todayStr,
|
|
isWeekend: d.getDay() === 0 || d.getDay() === 6,
|
|
});
|
|
}
|
|
return dates;
|
|
}
|
|
|
|
function getFilteredAgents(store) {
|
|
let result = store.agents;
|
|
|
|
if (store.searchQuery) {
|
|
const q = store.searchQuery.toLowerCase();
|
|
result = result.filter(a =>
|
|
a.name.toLowerCase().includes(q) ||
|
|
a.email.toLowerCase().includes(q) ||
|
|
a.department.toLowerCase().includes(q)
|
|
);
|
|
}
|
|
|
|
if (store.activeSkillFilters.length > 0) {
|
|
result = result.filter(a =>
|
|
store.activeSkillFilters.some(skill => a.skills.includes(skill))
|
|
);
|
|
}
|
|
|
|
if (store.activeDepartmentFilter) {
|
|
result = result.filter(a => a.department === store.activeDepartmentFilter);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
function getCellData(store, agentId, dateStr) {
|
|
const key = `${agentId}_${dateStr}`;
|
|
return store.schedule[key] || { shifts: [], exnet: [], notes: '', locked: null, history: [] };
|
|
}
|
|
|
|
function updateCellShifts(store, agentId, dateStr, shifts, exnet) {
|
|
const key = `${agentId}_${dateStr}`;
|
|
if (!store.schedule[key]) {
|
|
store.schedule[key] = { shifts: [], exnet: [], notes: '', locked: null, history: [] };
|
|
}
|
|
store.schedule[key].shifts = [...shifts];
|
|
if (exnet !== undefined) {
|
|
store.schedule[key].exnet = [...exnet];
|
|
}
|
|
// Add history entry
|
|
store.schedule[key].history.unshift({
|
|
user: 'You',
|
|
action: shifts.length > 0 ? `Set ${shifts.join(', ')}` : 'Cleared shifts',
|
|
timestamp: new Date().toISOString(),
|
|
});
|
|
}
|
|
|
|
function updateCellNotes(store, agentId, dateStr, notes) {
|
|
const key = `${agentId}_${dateStr}`;
|
|
if (!store.schedule[key]) {
|
|
store.schedule[key] = { shifts: [], exnet: [], notes: '', locked: null, history: [] };
|
|
}
|
|
store.schedule[key].notes = notes;
|
|
}
|
|
|
|
function openSidebar(store, agentId, dateStr) {
|
|
store.sidebarContext = { agentId, dateStr };
|
|
store.sidebarOpen = true;
|
|
}
|
|
|
|
function closeSidebar(store) {
|
|
store.sidebarOpen = false;
|
|
store.sidebarContext = null;
|
|
}
|