const ValidationUtils = { isWeekend(date) { if (!date) return false; const day = date.getDay(); return day === 0 || day === 6; }, isSat(date) { return date && date.getDay() === 6; }, isSun(date) { return date && date.getDay() === 0; }, // Check for conflicting shift combinations hasConflict(shiftCodes) { if (!shiftCodes || !Array.isArray(shiftCodes)) return false; // Rule: Morning ('m') and Afternoon/Hotline ('a') cannot overlap if (shiftCodes.includes('m') && shiftCodes.includes('a')) { return "Cannot work Morning and Afternoon simultaneously."; } // Rule: Vacation ('v') cannot be combined with working shifts if (shiftCodes.includes('v') && shiftCodes.length > 1) { return "Vacation must be the only entry."; } return false; // No conflict }, getConflictMessage(shiftCodes) { const result = this.hasConflict(shiftCodes); return typeof result === 'string' ? result : ''; } };