upload.html au top

This commit is contained in:
2025-11-01 12:31:11 +01:00
parent af13ae9f1e
commit 79c0d8d276
7 changed files with 2037 additions and 466 deletions

View File

@@ -168,7 +168,7 @@
const timelineOptions = {
timeAxis: {scale: "hour", step: 6},
orientation: {axis: "top"},
stack: false,
stack: true,
xss: {disabled: true}
};
@@ -372,131 +372,155 @@
}
}
}
function getColorForSkill(skill) {
const skillColors = {
"INFIRMIER": "#FF69B4", // Rose
"MEDECIN": "#4169E1", // Bleu
"PRELEVEMENT": "#FF8C00", // Orange
"ACCUEIL": "#228B22", // Vert
"TRANSPORT": "#8B008B", // Violet
"SUPERVISION": "#FFD700" // Or
};
return skillColors[skill] || COLORS.DEFAULT;
}
function renderSchedule(schedule) {
// Clear existing data
// Efface les anciennes données
byEmployeeGroupDataSet.clear();
byEmployeeItemDataSet.clear();
byLocationGroupDataSet.clear();
byLocationItemDataSet.clear();
// Update score
// Met à jour le score
$('#score').text('Score: ' + (schedule.score || '?'));
$('#analyzeButton').prop('disabled', !schedule.score);
// Count unassigned shifts
// Compte les shifts non assignés
let unassignedCount = 0;
schedule.shifts.forEach(shift => {
if (!shift.employee) unassignedCount++;
});
$('#unassignedShifts').text(
unassignedCount === 0
? 'No unassigned shifts'
: `${unassignedCount} unassigned shifts`
unassignedCount === 0 ? 'No unassigned shifts' : `${unassignedCount} unassigned shifts`
);
// Render employees
schedule.employees.forEach((employee, index) => {
// Add employee group
const skillsBadges = employee.skills.map(skill =>
// Rend les employés
schedule.employees.forEach(employee => {
const skillsBadges = employee.skills.map(skill =>
`<span class="badge bg-secondary me-1">${skill}</span>`
).join('');
byEmployeeGroupDataSet.add({
id: employee.name,
content: `<div><strong>${employee.name}</strong><br/>${skillsBadges}</div>`
});
// Add availability indicators
// Ajoute les disponibilités
['unavailableDates', 'undesiredDates', 'desiredDates'].forEach((dateType, typeIndex) => {
const color = [COLORS.UNAVAILABLE, COLORS.UNDESIRED, COLORS.DESIRED][typeIndex];
const label = ['Unavailable', 'Undesired', 'Desired'][typeIndex];
employee[dateType]?.forEach((date, dateIndex) => {
const startDate = new Date(date + 'T00:00:00');
const endDate = new Date(date + 'T23:59:59');
byEmployeeItemDataSet.add({
id: `${employee.name}-${dateType}-${dateIndex}`,
group: employee.name,
content: label,
content: ['Unavailable', 'Undesired', 'Desired'][typeIndex],
start: startDate,
end: endDate,
type: 'background',
style: `opacity: 0.5; background-color: ${color}`
style: `opacity: 0.3; background-color: ${color}`
});
});
});
});
}
);
// Render locations and shifts
const locations = [...new Set(schedule.shifts.map(shift => shift.location))];
locations.forEach(location => {
byLocationGroupDataSet.add({
id: location,
content: location
});
});
// Render shifts
schedule.shifts.forEach((shift, index) => {
const startTime = new Date(shift.start);
const endTime = new Date(shift.end);
if (shift.employee) {
// Assigned shift
const hasRequiredSkill = shift.employee.skills.includes(shift.requiredSkill);
const skillColor = hasRequiredSkill ? COLORS.SKILL_MATCH : COLORS.SKILL_MISMATCH;
const shiftColor = getShiftColor(shift, shift.employee);
// Add to employee timeline
byEmployeeItemDataSet.add({
id: `shift-${index}-emp`,
group: shift.employee.name,
content: `<div><strong>${shift.location}</strong><br/>
<span class="badge" style="background-color:${skillColor}">${shift.requiredSkill}</span></div>`,
start: startTime,
end: endTime,
style: `background-color: ${shiftColor}`
});
// Add to location timeline
byLocationItemDataSet.add({
id: `shift-${index}-loc`,
group: shift.location,
content: `<div><strong>${shift.employee.name}</strong><br/>
<span class="badge" style="background-color:${skillColor}">${shift.requiredSkill}</span></div>`,
start: startTime,
end: endTime,
style: `background-color: ${shiftColor}`
});
} else {
// Unassigned shift
byLocationItemDataSet.add({
id: `shift-${index}-unassigned`,
group: shift.location,
content: `<div><strong>Unassigned</strong><br/>
<span class="badge bg-secondary">${shift.requiredSkill}</span></div>`,
start: startTime,
end: endTime,
style: `background-color: ${COLORS.UNASSIGNED}`
// Crée les groupes par (lieu + compétence)
const locationSkillGroups = {};
schedule.shifts.forEach(shift => {
const groupId = `${shift.location}_${shift.requiredSkill}`;
if (!locationSkillGroups[groupId]) {
locationSkillGroups[groupId] = true;
byLocationGroupDataSet.add({
id: groupId,
content: `<div>
<strong>${shift.location}</strong><br/>
<span class="badge" style="background-color: ${getColorForSkill(shift.requiredSkill)}">
${shift.requiredSkill}
</span>
</div>`
});
}
});
// Set timeline window
// Ajoute les shifts aux groupes
schedule.shifts.forEach((shift, index) => {
const startTime = new Date(shift.start);
const endTime = new Date(shift.end);
const groupId = `${shift.location}_${shift.requiredSkill}`;
const skillColor = getColorForSkill(shift.requiredSkill);
// Ajoute au timeline "By Employee"
if (shift.employee) {
const hasRequiredSkill = shift.employee.skills.includes(shift.requiredSkill);
const shiftColor = hasRequiredSkill ? COLORS.SKILL_MATCH : COLORS.SKILL_MISMATCH;
byEmployeeItemDataSet.add({
id: `shift-${index}-emp`,
group: shift.employee.name,
content: `<div>
<strong>${shift.location}</strong><br/>
<span class="badge" style="background-color:${skillColor}">${shift.requiredSkill}</span><br/>
${startTime.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})} -
${endTime.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})}
</div>`,
start: startTime,
end: endTime,
style: `background-color: ${shiftColor}; border: 1px solid #555; color: #fff;`
});
}
// Ajoute au timeline "By Location"
if (shift.employee) {
const hasRequiredSkill = shift.employee.skills.includes(shift.requiredSkill);
const shiftColor = hasRequiredSkill ? skillColor : COLORS.SKILL_MISMATCH;
byLocationItemDataSet.add({
id: `shift-${index}-loc`,
group: groupId,
content: `<div>
<strong>${shift.employee.name}</strong><br/>
${startTime.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})} -
${endTime.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})}
</div>`,
start: startTime,
end: endTime,
style: `background-color: ${shiftColor}; border: 1px solid #555; color: #fff;`
});
} else {
// Shift non assigné
byLocationItemDataSet.add({
id: `shift-${index}-unassigned`,
group: groupId,
content: `<div><strong>Non assigné</strong></div>`,
start: startTime,
end: endTime,
style: `background-color: ${COLORS.UNASSIGNED}; border: 1px solid #555; color: #000;`
});
}
});
// Ajuste la fenêtre de la timeline
if (schedule.shifts.length > 0) {
const dates = schedule.shifts.map(shift => new Date(shift.start));
const minDate = new Date(Math.min(...dates));
const maxDate = new Date(Math.max(...dates));
maxDate.setDate(maxDate.getDate() + 1);
byEmployeeTimeline.setWindow(minDate, maxDate);
byLocationTimeline.setWindow(minDate, maxDate);
}
}
function getShiftColor(shift, employee) {
const shiftDate = new Date(shift.start).toISOString().split('T')[0];