<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Employee Scheduling App</title>

<style>

body {

font-family: Arial, sans-serif !important;

margin: 0 !important;

padding: 20px !important;

background-color: #f0f4f8 !important;

}

.sch-container {

max-width: 1000px !important;

margin: 0 auto !important;

background-color: white !important;

border-radius: 10px !important;

padding: 20px !important;

box-shadow: 0 0 10px rgba(0,0,0,0.1) !important;

}

h1 {

color: #2d3748 !important;

text-align: center !important;

margin-bottom: 30px !important;

}

#sch-schedule {

display: grid !important;

grid-template-columns: auto repeat(7, 1fr) !important;

gap: 10px !important;

margin-bottom: 20px !important;

overflow-x: auto !important;

}

.sch-day, .sch-shift-type {

font-weight: bold !important;

text-align: center !important;

padding: 10px !important;

background-color: #edf2f7 !important;

border-radius: 5px !important;

position: relative !important;

}

.sch-day .sch-copy-dropdown {

margin-top: 5px !important;

}

.sch-copy-dropdown select {

border: 1px solid #e2e8f0 !important;

background-color: #f0f4f8 !important;

padding: 5px !important;

border-radius: 5px !important;

cursor: pointer !important;

color: black !important;

}

.sch-shift-time {

font-size: 0.8em !important;

}

.sch-shift-slot {

border: 1px solid #e2e8f0 !important;

min-height: 50px !important;

padding: 5px !important;

position: relative !important;

border-radius: 5px !important;

}

#sch-employees {

margin-top: 20px !important;

border: 1px solid #e2e8f0 !important;

padding: 10px !important;

background-color: #edf2f7 !important;

border-radius: 5px !important;

text-align: center !important;

}

#sch-employee-list {

display: flex !important;

flex-wrap: wrap !important;

gap: 10px !important;

margin-top: 10px !important;

justify-content: center !important;

}

.sch-employee {

padding: 10px !important;

cursor: move !important;

border-radius: 5px !important;

width: 120px !important;

text-align: center !important;

box-shadow: 0 2px 4px rgba(0,0,0,0.1) !important;

position: relative !important;

}

.sch-employee .sch-title {

font-size: 0.9em !important;

font-weight: bold !important;

}

.sch-employee .sch-name {

font-size: 0.8em !important;

}

.sch-employee .sch-actions {

position: absolute !important;

top: 2px !important;

right: 2px !important;

display: none !important;

}

.sch-employee:hover .sch-actions {

display: block !important;

}

.sch-employee .sch-actions button {

background: none !important;

border: none !important;

cursor: pointer !important;

font-size: 12px !important;

padding: 2px !important;

}

.sch-assigned-employee {

padding: 5px !important;

margin: 2px !important;

border-radius: 3px !important;

font-size: 0.8em !important;

position: relative !important;

}

.sch-remove-employee {

position: absolute !important;

top: 2px !important;

right: 2px !important;

background-color: #fc8181 !important;

color: white !important;

border: none !important;

border-radius: 50% !important;

width: 16px !important;

height: 16px !important;

font-size: 10px !important;

cursor: pointer !important;

display: none !important;

}

.sch-assigned-employee:hover .sch-remove-employee {

display: block !important;

}

.sch-edit-shift, .sch-delete-shift {

cursor: pointer !important;

margin-left: 5px !important;

color: #4a5568 !important;

}

.sch-delete-shift {

color: #e53e3e !important;

}

button {

background-color: #4299e1 !important;

color: white !important;

border: none !important;

padding: 10px 15px !important;

border-radius: 5px !important;

cursor: pointer !important;

transition: background-color 0.3s !important;

}

button:hover {

background-color: #3182ce !important;

}

input, select {

padding: 8px !important;

border: 1px solid #e2e8f0 !important;

border-radius: 5px !important;

margin-right: 10px !important;

}

.sch-highlight {

border: 2px solid #e53e3e !important;

}

.sch-dropdown {

position: relative !important;

display: inline-block !important;

margin-right: 10px !important;

}

.sch-dropdown-content {

display: none !important;

position: absolute !important;

background-color: #f0f4f8 !important;

box-shadow: 0 0 10px rgba(0,0,0,0.1) !important;

border-radius: 5px !important;

z-index: 10 !important;

right: 0 !important;

color: black !important;

}

.sch-dropdown-content button {

display: block !important;

width: 100% !important;

text-align: left !important;

padding: 10px !important;

background-color: #f0f4f8 !important;

border: none !important;

cursor: pointer !important;

color: black !important;

}

.sch-dropdown-content button:hover {

background-color: #e2e8f0 !important;

}

.sch-dropdown:hover .sch-dropdown-content {

display: block !important;

}

/* Tabs styling */

.tab-container {

display: flex !important;

justify-content: center !important;

margin-bottom: 20px !important;

border-bottom: 2px solid #e2e8f0 !important;

}

.tab {

cursor: pointer !important;

padding: 10px 20px !important;

border: 1px solid #e2e8f0 !important;

border-bottom: none !important;

background-color: #edf2f7 !important;

margin-right: 5px !important;

border-radius: 5px 5px 0 0 !important;

transition: background-color 0.3s !important;

}

.tab.active {

background-color: white !important;

box-shadow: 0 0 10px rgba(0,0,0,0.1) !important;

}

.tab-content {

display: none !important;

padding: 20px !important;

background-color: white !important;

border-radius: 0 5px 5px 5px !important;

box-shadow: 0 0 10px rgba(0,0,0,0.1) !important;

}

.tab-content.active {

display: block !important;

}

/* Controls Section */

#controls {

background-color: #edf2f7 !important;

padding: 20px !important;

border-radius: 10px !important;

margin-top: 20px !important;

box-shadow: 0 0 10px rgba(0,0,0,0.1) !important;

}

#controls h2 {

margin-bottom: 15px !important;

color: #2d3748 !important;

text-align: center !important;

}

#controls .control-group {

margin-bottom: 15px !important;

display: flex !important;

justify-content: space-between !important;

align-items: center !important;

}

#controls .control-group label {

flex: 1 !important;

color: #4a5568 !important;

}

#controls .control-group input {

flex: 2 !important;

max-width: 150px !important;

}

#controls .control-group .sch-dropdown,

#controls .control-group button {

margin-top: 10px !important;

}

/* Enhanced Tables Styling */

table {

width: 100% !important;

border-collapse: collapse !important;

margin-bottom: 20px !important;

}

th, td {

border: 1px solid #e2e8f0 !important;

padding: 10px !important;

text-align: left !important;

}

th {

background-color: #4299e1 !important;

color: white !important;

}

td {

background-color: white !important;

}

td .sch-edit-link, td .sch-delete-link {

cursor: pointer !important;

color: #4299e1 !important;

text-decoration: underline !important;

}

td .sch-delete-link {

color: #e53e3e !important;

}

</style>

</head>

<body>

<div class="sch-container">

<h1>Employee Scheduling App</h1>

<div id="sch-schedule"></div>

<div id="sch-employees">

<h2>Available Employees</h2>

<div id="sch-employee-list"></div>

<div id="sch-employee-insights"></div>

</div>

<!-- Management Area with Tabs -->

<div class="sch-container">

<h2>Management Area</h2>

<div class="tab-container">

<div class="tab active" onclick="showTab('shift-management')">Shift Management</div>

<div class="tab" onclick="showTab('employee-management')">Employee Management</div>

<div class="tab" onclick="showTab('controls')">Controls</div>

</div>

<div id="shift-management" class="tab-content active">

<!-- Shift Management Section -->

<div class="sch-section">

<h2>Manage Shifts</h2>

<div id="sch-add-shift">

<h3>Add Shift</h3>

<input type="text" id="sch-new-shift-name" placeholder="Shift Name">

<input type="time" id="sch-new-shift-start" placeholder="Start Time">

<input type="time" id="sch-new-shift-end" placeholder="End Time">

<select id="sch-shift-position">

<option value="before">Before</option>

<option value="after">After</option>

</select>

<select id="sch-existing-shifts"></select>

<button onclick="addShift()">Add Shift</button>

</div>

<h3>Shift Overview</h3>

<table id="sch-shift-overview">

<thead>

<tr>

<th>Shift Name</th>

<th>Start Time</th>

<th>End Time</th>

<th>Actions</th>

</tr>

</thead>

<tbody id="sch-shift-overview-body">

<!-- Shift rows will be dynamically populated here -->

</tbody>

</table>

</div>

</div>

<div id="employee-management" class="tab-content">

<!-- Employee Management Section -->

<div class="sch-section">

<h2>Manage Employees</h2>

<div id="sch-add-employee">

<h3>Add Employee</h3>

<input type="text" id="sch-new-employee-name" placeholder="Name">

<input type="text" id="sch-new-employee-title" placeholder="Title">

<input type="text" id="sch-new-employee-phone" placeholder="Phone">

<input type="email" id="sch-new-employee-email" placeholder="Email">

<input type="color" id="sch-new-employee-color" value="#4299e1">

<button onclick="addEmployee()">Add Employee</button>

</div>

<h3>Employee Overview</h3>

<table id="sch-employee-overview">

<thead>

<tr>

<th>Name</th>

<th>Title</th>

<th>Phone</th>

<th>Email</th>

<th>Color</th>

<th>Actions</th>

</tr>

</thead>

<tbody id="sch-employee-overview-body">

<!-- Employee rows will be dynamically populated here -->

</tbody>

</table>

</div>

</div>

<div id="controls" class="tab-content">

<!-- Controls Section -->

<div class="sch-section">

<h2>Controls</h2>

<div class="control-group">

<label for="sch-weekly-hours-limit-input">Set Weekly Hours Limit:</label>

<input type="number" id="sch-weekly-hours-limit-input" placeholder="Weekly Hours Limit">

</div>

<div class="control-group">

<div class="sch-dropdown">

<button onclick="toggleDropdown('sch-save-dropdown')">Save Schedule</button>

<div id="sch-save-dropdown" class="sch-dropdown-content">

<button onclick="exportToCSV()">CSV File</button>

<button onclick="saveDataToCookie()">Browser (Cookie)</button>

<button onclick="saveDataToFile()">Local File (JSON)</button>

</div>

</div>

<div class="sch-dropdown">

<button onclick="toggleDropdown('sch-import-dropdown')">Import Schedule</button>

<div id="sch-import-dropdown" class="sch-dropdown-content">

<button onclick="importFromFileClick()">Local File (JSON)</button>

<button onclick="importDataFromCookie()">Browser (Cookie)</button>

<button onclick="importFromCSV()">CSV File</button>

<input type="file" id="sch-file-input" style="display:none" accept=".json,.csv" onchange="handleFileImport(event)">

</div>

</div>

</div>

<div class="control-group">

<button id="sch-verify-button" onclick="verifySchedule()">Verify Schedule</button>

<button id="sch-clear-button" onclick="clearSchedule()">Clear Schedule</button>

</div>

</div>

</div>

</div>

</div>

<script>

let employees = [

{ name: "John Doe", title: "Manager", phone: "123-456-7890", email: "john@example.com", color: "#4299e1" },

{ name: "Jane Smith", title: "Assistant", phone: "987-654-3210", email: "jane@example.com", color: "#48bb78" },

{ name: "Bob Johnson", title: "Associate", phone: "555-555-5555", email: "bob@example.com", color: "#ed8936" }

];

let shifts = [

{ name: "Morning Shift", start: "08:00", end: "12:00" },

{ name: "Afternoon Shift", start: "12:00", end: "16:00" },

{ name: "Evening Shift", start: "16:00", end: "20:00" }

];

let schedule = {};

function initializeSchedule() {

shifts.forEach(shift => {

schedule[shift.name] = {

monday: [], tuesday: [], wednesday: [], thursday: [], friday: [], saturday: [], sunday: []

};

});

}

function getContrastColor(hexcolor) {

if (hexcolor.slice(0, 1) === '#') {

hexcolor = hexcolor.slice(1);

}

var r = parseInt(hexcolor.substr(0,2),16);

var g = parseInt(hexcolor.substr(2,2),16);

var b = parseInt(hexcolor.substr(4,2),16);

var yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;

return (yiq >= 128) ? 'black' : 'white';

}

function renderSchedule() {

const scheduleElement = document.getElementById('sch-schedule');

scheduleElement.innerHTML = `

<div></div>

${['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'].map(day => `

<div class="sch-day">

${day}

<div class="sch-copy-dropdown">

<select onchange="copyShifts('${day.toLowerCase()}', this.value)">

<option value="">Copy to</option>

<option value="all">All</option>

${['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'].map((targetDay, index) => `

${targetDay.toLowerCase() !== day.toLowerCase() ? `<option value="${targetDay.toLowerCase()}">${targetDay}</option>` : ''}

`).join('')}

</select>

</div>

</div>

`).join('')}

`;

shifts.forEach((shift, index) => {

scheduleElement.innerHTML += `

<div class="sch-shift-type">

${shift.name}

<div class="sch-shift-time">${shift.start} - ${shift.end}</div>

<span class="sch-edit-shift" onclick="editShift(${index})">✏️</span>

<span class="sch-delete-shift" onclick="deleteShift(${index})">🗑️</span>

</div>

${['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'].map(day => `

<div class="sch-shift-slot" data-day="${day}" data-shift="${shift.name}" ondrop="drop(event)" ondragover="allowDrop(event)">

${schedule[shift.name][day].map((employeeIndex, idx) => {

const employee = employees[employeeIndex];

const textColor = getContrastColor(employee.color);

return `

<div class="sch-assigned-employee" data-employee="${employeeIndex}" style="background-color: ${employee.color}; color: ${textColor}">

<div class="sch-title">${employee.title}</div>

<div class="sch-name">${employee.name}</div>

<button class="sch-remove-employee" onclick="removeEmployeeFromShift('${shift.name}', '${day}', ${idx})">X</button>

</div>

`;

}).join('')}

</div>

`).join('')}

`;

});

addDragAndDropListeners();

updateExistingShiftsDropdown();

updateEmployeeInsights();

renderShiftOverview(); // Render the shift overview table

}

function renderEmployees() {

const employeeList = document.getElementById('sch-employee-list');

employeeList.innerHTML = '';

employees.forEach((employee, index) => {

const textColor = getContrastColor(employee.color);

employeeList.innerHTML += `

<div class="sch-employee" draggable="true" data-employee="${index}" style="background-color: ${employee.color}; color: ${textColor}" onmouseover="highlightEmployee(${index})" onmouseout="unhighlightEmployee(${index})" ondragstart="drag(event)">

<div class="sch-title">${employee.title}</div>

<div class="sch-name">${employee.name}</div>

<div class="sch-actions">

<button onclick="editEmployee(${index})">✏️</button>

<button onclick="deleteEmployee(${index})">🗑️</button>

</div>

</div>

`;

});

renderEmployeeOverview(); // Render the employee overview table

}

function renderEmployeeOverview() {

const employeeOverviewBody = document.getElementById('sch-employee-overview-body');

employeeOverviewBody.innerHTML = '';

employees.forEach((employee, index) => {

employeeOverviewBody.innerHTML += `

<tr>

<td>${employee.name}</td>

<td>${employee.title}</td>

<td>${employee.phone}</td>

<td>${employee.email}</td>

<td style="background-color: ${employee.color}; color: ${getContrastColor(employee.color)}">${employee.color}</td>

<td>

<span class="sch-edit-link" onclick="editEmployee(${index})">Edit</span> |

<span class="sch-delete-link" onclick="deleteEmployee(${index})">Delete</span>

</td>

</tr>

`;

});

}

function renderShiftOverview() {

const shiftOverviewBody = document.getElementById('sch-shift-overview-body');

shiftOverviewBody.innerHTML = '';

shifts.forEach((shift, index) => {

shiftOverviewBody.innerHTML += `

<tr>

<td>${shift.name}</td>

<td>${shift.start}</td>

<td>${shift.end}</td>

<td>

<span class="sch-edit-link" onclick="editShift(${index})">Edit</span> |

<span class="sch-delete-link" onclick="deleteShift(${index})">Delete</span>

</td>

</tr>

`;

});

}

function addDragAndDropListeners() {

const draggables = document.querySelectorAll('.sch-employee');

const dropZones = document.querySelectorAll('.sch-shift-slot');

draggables.forEach(draggable => {

draggable.addEventListener('dragstart', drag);

});

dropZones.forEach(dropZone => {

dropZone.addEventListener('dragover', allowDrop);

dropZone.addEventListener('drop', drop);

});

}

function allowDrop(e) {

e.preventDefault();

}

function drag(e) {

e.dataTransfer.setData('text', e.target.getAttribute('data-employee'));

}

function drop(e) {

e.preventDefault();

const employeeIndex = e.dataTransfer.getData('text');

const targetSlot = e.target.closest('.sch-shift-slot');

if (targetSlot) {

const day = targetSlot.dataset.day;

const shift = targetSlot.dataset.shift;

const weeklyHoursLimit = parseInt(document.getElementById('sch-weekly-hours-limit-input').value) || Infinity;

if (getTotalWeeklyHours(employeeIndex) + getHoursDifference(shifts.find(s => s.name === shift).start, shifts.find(s => s.name === shift).end) <= weeklyHoursLimit) {

if (!schedule[shift][day].includes(parseInt(employeeIndex))) { // Prevent duplicate entries

schedule[shift][day].push(parseInt(employeeIndex));

renderSchedule();

}

} else {

alert("This assignment exceeds the weekly hours limit for this employee.");

}

}

}

function addEmployee() {

const name = document.getElementById('sch-new-employee-name').value;

const title = document.getElementById('sch-new-employee-title').value;

const phone = document.getElementById('sch-new-employee-phone').value;

const email = document.getElementById('sch-new-employee-email').value;

const color = document.getElementById('sch-new-employee-color').value;

if (name && title && phone && email) {

employees.push({ name, title, phone, email, color });

renderEmployees();

renderSchedule();

clearEmployeeInputs();

}

}

function editEmployee(index) {

const employee = employees[index];

const newName = prompt("Enter new name:", employee.name);

const newTitle = prompt("Enter new title:", employee.title);

const newPhone = prompt("Enter new phone number:", employee.phone);

const newEmail = prompt("Enter new email:", employee.email);

const newColor = prompt("Enter new color (hex code):", employee.color);

if (newName !== null && newTitle !== null && newPhone !== null && newEmail !== null && newColor !== null) {

employees[index] = {

name: newName || employee.name,

title: newTitle || employee.title,

phone: newPhone || employee.phone,

email: newEmail || employee.email,

color: newColor || employee.color

};

renderEmployees();

renderSchedule();

}

}

function deleteEmployee(index) {

if (confirm("Are you sure you want to delete this employee?")) {

employees.splice(index, 1);

// Remove the deleted employee from all shifts

Object.keys(schedule).forEach(shift => {

Object.keys(schedule[shift]).forEach(day => {

schedule[shift][day] = schedule[shift][day].filter(empIndex => empIndex !== index);

schedule[shift][day] = schedule[shift][day].map(empIndex => empIndex > index ? empIndex - 1 : empIndex);

});

});

renderEmployees();

renderSchedule();

}

}

function clearEmployeeInputs() {

document.getElementById('sch-new-employee-name').value = '';

document.getElementById('sch-new-employee-title').value = '';

document.getElementById('sch-new-employee-phone').value = '';

document.getElementById('sch-new-employee-email').value = '';

document.getElementById('sch-new-employee-color').value = '#4299e1';

}

function addShift() {

const shiftName = document.getElementById('sch-new-shift-name').value;

const start = document.getElementById('sch-new-shift-start').value;

const end = document.getElementById('sch-new-shift-end').value;

const position = document.getElementById('sch-shift-position').value;

const existingShiftIndex = document.getElementById('sch-existing-shifts').value;

if (shiftName && start && end && existingShiftIndex !== '') {

const index = parseInt(existingShiftIndex);

const newShift = { name: shiftName, start, end };

if (position === 'before') {

shifts.splice(index, 0, newShift);

} else {

shifts.splice(index + 1, 0, newShift);

}

schedule[shiftName] = {

monday: [], tuesday: [], wednesday: [], thursday: [], friday: [], saturday: [], sunday: []

};

renderSchedule();

document.getElementById('sch-new-shift-name').value = '';

document.getElementById('sch-new-shift-start').value = '';

document.getElementById('sch-new-shift-end').value = '';

}

}

function editShift(index) {

const shift = shifts[index];

const newName = prompt("Enter new name for the shift:", shift.name);

const newStart = prompt("Enter new start time (HH:MM):", shift.start);

const newEnd = prompt("Enter new end time (HH:MM):", shift.end);

if (newName !== null && newName.trim() !== "" && newName !== shift.name) {

schedule[newName] = schedule[shift.name];

delete schedule[shift.name];

shifts[index].name = newName.trim();

}

if (newStart !== null && newStart.trim() !== "" && newStart !== shift.start) {

shifts[index].start = newStart.trim();

}

if (newEnd !== null && newEnd.trim() !== "" && newEnd !== shift.end) {

shifts[index].end = newEnd.trim();

}

renderSchedule();

updateEmployeeInsights();

}

function deleteShift(index) {

if (confirm("Are you sure you want to delete this shift?")) {

const shiftToDelete = shifts[index];

shifts.splice(index, 1);

delete schedule[shiftToDelete.name];

renderSchedule();

}

}

function updateExistingShiftsDropdown() {

const dropdown = document.getElementById('sch-existing-shifts');

dropdown.innerHTML = '';

shifts.forEach((shift, index) => {

const option = document.createElement('option');

option.value = index;

option.textContent = shift.name;

dropdown.appendChild(option);

});

}

function removeEmployeeFromShift(shift, day, employeeIndex) {

schedule[shift][day].splice(employeeIndex, 1);

renderSchedule();

}

function exportToCSV() {

let csvContent = "data:text/csv;charset=utf-8,";

// Add header row

csvContent += "Shift,Day,Employees\n";

// Add data rows

shifts.forEach(shift => {

['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'].forEach(day => {

let employeeNames = schedule[shift.name][day].map(index => employees[index].name).join(', ');

csvContent += `${shift.name},${day},${employeeNames}\n`;

});

});

// Create a download link and trigger the download

var encodedUri = encodeURI(csvContent);

var link = document.createElement("a");

link.setAttribute("href", encodedUri);

link.setAttribute("download", "schedule.csv");

document.body.appendChild(link);

link.click();

document.body.removeChild(link);

}

function verifySchedule() {

// Clear previous highlights

document.querySelectorAll('.sch-highlight').forEach(element => {

element.classList.remove('sch-highlight');

});

// Mark shifts with duplicate employees in red and empty shifts in light green

shifts.forEach(shift => {

['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'].forEach(day => {

const shiftSlot = document.querySelector(`.sch-shift-slot[data-day="${day}"][data-shift="${shift.name}"]`);

const employeeIndices = schedule[shift.name][day];

const uniqueEmployeeIndices = new Set(employeeIndices);

if (employeeIndices.length !== uniqueEmployeeIndices.size) {

shiftSlot.classList.add('sch-highlight');

shiftSlot.style.backgroundColor = '#ffcccc'; // Light red

} else if (employeeIndices.length === 0) {

shiftSlot.style.backgroundColor = '#ccffcc'; // Light green

} else {

shiftSlot.style.backgroundColor = '';

}

});

});

}

function saveDataToCookie() {

const data = {

employees,

shifts,

schedule

};

const jsonData = JSON.stringify(data);

document.cookie = `scheduleData=${encodeURIComponent(jsonData)}; path=/`;

}

function saveDataToFile() {

const data = {

employees,

shifts,

schedule

};

const jsonData = JSON.stringify(data);

// Create a download link for the JSON file

const blob = new Blob([jsonData], { type: "application/json" });

const url = URL.createObjectURL(blob);

const link = document.createElement("a");

link.setAttribute("href", url);

link.setAttribute("download", "scheduleData.json");

document.body.appendChild(link);

link.click();

document.body.removeChild(link);

}

function importDataFromCookie() {

const cookies = document.cookie.split(';');

let scheduleDataCookie = cookies.find(cookie => cookie.trim().startsWith('scheduleData='));

if (scheduleDataCookie) {

const jsonData = decodeURIComponent(scheduleDataCookie.split('=')[1]);

const data = JSON.parse(jsonData);

employees = data.employees;

shifts = data.shifts;

schedule = data.schedule;

renderEmployees();

renderSchedule();

}

}

function importFromFileClick() {

document.getElementById('sch-file-input').click();

}

function handleFileImport(event) {

const file = event.target.files[0];

if (file) {

const reader = new FileReader();

reader.onload = function(e) {

const content = e.target.result;

if (file.type === 'application/json') {

const data = JSON.parse(content);

employees = data.employees;

shifts = data.shifts;

schedule = data.schedule;

} else if (file.type === 'text/csv') {

importFromCSVContent(content);

}

renderEmployees();

renderSchedule();

};

reader.readAsText(file);

}

}

function importFromCSV() {

document.getElementById('sch-file-input').click();

}

function importFromCSVContent(content) {

const rows = content.split('\n');

rows.forEach(row => {

const [shiftName, day, employeeNames] = row.split(',');

if (shiftName && day && employeeNames) {

const employeeIndices = employeeNames.split(' ').map(name => {

return employees.findIndex(e => e.name === name);

});

schedule[shiftName][day] = employeeIndices;

}

});

}

function toggleDropdown(id) {

const dropdown = document.getElementById(id);

dropdown.style.display = dropdown.style.display === 'block' ? 'none' : 'block';

}

function clearSchedule() {

if (confirm("Are you sure you want to clear the schedule?")) {

initializeSchedule();

renderSchedule();

}

}

function highlightEmployee(index) {

document.querySelectorAll('.sch-assigned-employee').forEach(employee => {

if (parseInt(employee.dataset.employee) !== index) {

employee.style.opacity = '0.6';

}

});

}

function unhighlightEmployee() {

document.querySelectorAll('.sch-assigned-employee').forEach(employee => {

employee.style.opacity = '1';

});

}

function updateEmployeeInsights() {

const shiftCounts = {};

const hourCounts = {};

employees.forEach((employee, index) => {

shiftCounts[employee.name] = 0;

hourCounts[employee.name] = 0;

});

shifts.forEach(shift => {

['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'].forEach(day => {

schedule[shift.name][day].forEach(employeeIndex => {

const employee = employees[employeeIndex];

shiftCounts[employee.name]++;

hourCounts[employee.name] += getHoursDifference(shift.start, shift.end);

});

});

});

const employeeInsightsElement = document.getElementById('sch-employee-insights');

employeeInsightsElement.innerHTML = '';

for (const [name, count] of Object.entries(shiftCounts)) {

const hours = hourCounts[name];

employeeInsightsElement.innerHTML += `<p>${name}: ${count} shifts, ${hours} hours</p>`;

}

}

function getHoursDifference(startTime, endTime) {

const [startHour, startMinute] = startTime.split(':').map(Number);

const [endHour, endMinute] = endTime.split(':').map(Number);

const startDate = new Date(0, 0, 0, startHour, startMinute, 0);

const endDate = new Date(0, 0, 0, endHour, endMinute, 0);

const diff = endDate - startDate;

const hours = diff / (1000 * 60 * 60);

return hours;

}

function getTotalWeeklyHours(employeeIndex) {

let totalHours = 0;

shifts.forEach(shift => {

['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'].forEach(day => {

if (schedule[shift.name][day].includes(employeeIndex)) {

totalHours += getHoursDifference(shift.start, shift.end);

}

});

});

return totalHours;

}

function copyShifts(fromDay, toDay) {

if (toDay === "all") {

['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'].forEach(day => {

if (day !== fromDay) {

shifts.forEach(shift => {

schedule[shift.name][day] = [...schedule[shift.name][fromDay]];

});

}

});

} else if (toDay) {

shifts.forEach(shift => {

const dayMapping = {

mon: 'monday',

tue: 'tuesday',

wed: 'wednesday',

thu: 'thursday',

fri: 'friday',

sat: 'saturday',

sun: 'sunday'

};

schedule[shift.name][dayMapping[toDay]] = [...schedule[shift.name][fromDay]];

});

}

renderSchedule();

}

function capitalize(str) {

return str.charAt(0).toUpperCase() + str.slice(1);

}

function showTab(tabId) {

// Remove active class from all tabs and tab contents

document.querySelectorAll('.tab, .tab-content').forEach(element => {

element.classList.remove('active');

});

// Add active class to the clicked tab and its content

document.querySelector(`.tab[onclick="showTab('${tabId}')"]`).classList.add('active');

document.getElementById(tabId).classList.add('active');

}

// Initial setup

initializeSchedule();

renderSchedule();

renderEmployees();

</script>

</body>

</html>