Files
hotline-planner/monolith/hlp quasar initial layout split/js/store.js
2026-02-23 12:27:26 +01:00

209 lines
7.3 KiB
JavaScript

const { reactive, computed } = Vue;
const DEPARTMENTS = ["Support", "Technical", "Sales", "VIP", "Billing"];
const ROLES = ["Senior Lead", "Specialist", "Agent"];
const SKILLS = ["English", "German", "Technical Support", "VIP Handling", "Molecular App", "Hardware", "Billing Specialist"];
// Mock Data Generators
const generateMoreUsers = (startId, count) => {
return Array.from({ length: count }, (_, i) => ({
id: startId + i,
name: `Colleague ${startId + i}`,
email: `colleague.${startId + i}@company.com`,
role: "Contributor",
img: `https://i.pravatar.cc/150?u=${startId + i}`
}));
};
const CORE_USERS = [
{ id: 1, name: "Alice Freeman", email: "alice.f@company.com", role: "Product Manager", img: "https://i.pravatar.cc/150?u=1" },
{ id: 2, name: "Bob Smith", email: "bob.smith@company.com", role: "Senior Developer", img: "https://i.pravatar.cc/150?u=2" },
{ id: 3, name: "Charlie Kim", email: "charlie.k@company.com", role: "UX Designer", img: "https://i.pravatar.cc/150?u=3" },
{ id: 4, name: "Diana Prince", email: "diana.p@company.com", role: "QA Lead", img: "https://i.pravatar.cc/150?u=4" },
{ id: 5, name: "Evan Wright", email: "evan.w@company.com", role: "Frontend Dev", img: "https://i.pravatar.cc/150?u=5" },
];
const ALL_ONLINE_USERS = [...CORE_USERS, ...generateMoreUsers(6, 27)];
const AGENTS = Array.from({ length: 100 }, (_, i) => ({
id: i + 1,
name: `Agent ${i + 1}`,
dept: DEPARTMENTS[i % DEPARTMENTS.length],
role: ROLES[i % ROLES.length],
skills: [SKILLS[i % SKILLS.length]],
avatar: `https://api.dicebear.com/7.x/avataaars/svg?seed=Agent${i}`,
// Map of date string (YYYY-MM-DD) -> Array of shift IDs/Codes
shifts: {}
}));
// Helper to format date key
const getDateKey = (date) => {
return date.toISOString().split('T')[0];
};
// Global Store
const store = reactive({
// State
agents: AGENTS,
onlineUsers: ALL_ONLINE_USERS,
// View Settings
viewSettings: {
leftDrawerOpen: false,
rightDrawerOpen: false,
isCompact: false,
weekendsAreWorkingDays: false,
viewScope: 4, // Weeks
startDate: new Date(),
searchQuery: "",
activeDept: "All",
weekStart: 1 // 1 = Mon, 0 = Sun
},
// Selection State
selection: {
agent: null,
date: null,
mode: 'assignment' // 'assignment' | 'profile'
},
// Constant Data
consts: {
DEPARTMENTS,
ROLES,
SKILLS,
SHIFTS: [
{ id: 'm', label: 'Morning', color: 'green-7' },
{ id: 'a', label: 'Afternoon', color: 'blue-7' },
{ id: 'e', label: 'EOD Only', color: 'pink-7' }
]
},
// Computed Helpers (as methods for now since they depend on state)
get dates() {
const res = [];
const now = new Date(this.viewSettings.startDate);
for (let i = 0; i < this.viewSettings.viewScope * 7; i++) {
const d = new Date(now);
d.setDate(now.getDate() + i);
res.push(d);
}
return res;
},
get filteredAgents() {
let result = this.agents;
// Filter by Search
if (this.viewSettings.searchQuery) {
const lower = this.viewSettings.searchQuery.toLowerCase();
result = result.filter(a => a.name.toLowerCase().includes(lower));
}
// Filter by Dept
if (this.viewSettings.activeDept !== 'All') {
result = result.filter(a => a.dept === this.viewSettings.activeDept);
}
return result;
},
// Actions
setStartDate(dateStr) {
this.viewSettings.startDate = new Date(dateStr);
},
toggleLeftDrawer() {
this.viewSettings.leftDrawerOpen = !this.viewSettings.leftDrawerOpen;
},
openAssignment(agent, date) {
this.selection.mode = 'assignment';
this.selection.agent = agent;
this.selection.date = date;
this.viewSettings.rightDrawerOpen = true;
},
openProfile(agent) {
this.selection.mode = 'profile';
this.selection.agent = agent; // In a real app, might want a clone here
this.selection.date = null;
this.viewSettings.rightDrawerOpen = true;
},
// Mock WebSocket Handler
handleMockUpdate(payload) {
console.log("Store received update:", payload);
// Payload: { type: 'SHIFT_UPDATE', agentId: 1, date: '2023-10-27', shifts: ['m', 'vip_support'] }
if (payload.type === 'SHIFT_UPDATE') {
const agent = this.agents.find(a => a.id === payload.agentId);
if (agent) {
// Vue 3 reactive update
// If the agent is visible/in-memory, we update directly
if (!agent.shifts) agent.shifts = {};
agent.shifts[payload.date] = payload.shifts;
console.log(`Updated shifts for ${agent.name} on ${payload.date} to`, payload.shifts);
// Trigger Quasar notification if available (accessed via global Q or just console)
if (window.Quasar) {
window.Quasar.Notify.create({
message: `Update received for ${agent.name}`,
color: 'indigo',
position: 'bottom-right'
});
}
}
}
},
// Action to Assign Shifts (used by UI)
assignShifts(agentId, date, shiftCodes, meta = {}) {
const agent = this.agents.find(a => a.id === agentId);
if (agent && date) {
const key = getDateKey(date);
if (!agent.shifts) agent.shifts = {};
// Store as object if meta exists, otherwise just array for backward compat?
// Better to standardize on object now?
// For now, let's store: { codes: [], meta: {} }
// But previous code expects array. Let's keep it simple:
// We'll store an object keyed by date, but the value will be { codes: [], ...meta }
// Wait, getAgentShifts returns array. I should update that too or store meta separately.
// Let's store meta in a parallel structure or modify the shift storage format.
// Requirement: "complex inputs... specific start/end times"
// Let's change the storage format to:
// agent.shifts[key] = { codes: ['m'], start: '10:00', end: '12:00' }
// And update getAgentShifts to return .codes for compatibility with existing UI loop
agent.shifts[key] = { codes: shiftCodes, ...meta };
}
},
getAgentShifts(agentId, date) {
const agent = this.agents.find(a => a.id === agentId);
if (agent && agent.shifts && date) {
const key = getDateKey(date);
const entry = agent.shifts[key];
if (!entry) return [];
// If legacy array (from mock update potentially), wrap it
if (Array.isArray(entry)) return entry;
return entry.codes || [];
}
return [];
},
// New helper for meta
getAgentShiftMeta(agentId, date) {
const agent = this.agents.find(a => a.id === agentId);
if (agent && agent.shifts && date) {
const key = getDateKey(date);
const entry = agent.shifts[key];
if (entry && !Array.isArray(entry)) return entry;
}
return {};
}
});