196 lines
5.0 KiB
JavaScript
196 lines
5.0 KiB
JavaScript
/**
|
|
* Configuration utilities for handling settings and form submissions
|
|
*/
|
|
|
|
class ConfigHandler {
|
|
constructor(options = {}) {
|
|
this.options = {
|
|
apiEndpoint: options.apiEndpoint || "/config/api/update_config",
|
|
...options,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Update configuration via API
|
|
* @param {object} configData - Configuration data to send
|
|
* @returns {Promise} API response promise
|
|
*/
|
|
async updateConfig(configData) {
|
|
try {
|
|
const response = await fetch(this.options.apiEndpoint, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify(configData),
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (data.success) {
|
|
showFlashMessage(
|
|
data.message || "Configuration updated successfully!",
|
|
"success"
|
|
);
|
|
} else {
|
|
const errorMessage =
|
|
data.updates?.[0]?.message ||
|
|
data.message ||
|
|
"Error updating configuration";
|
|
showFlashMessage(errorMessage, "error");
|
|
}
|
|
|
|
return data;
|
|
} catch (error) {
|
|
console.error("Error updating configuration:", error);
|
|
showFlashMessage("Network error occurred", "error");
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update volume configuration
|
|
* @param {number} volume - New volume value
|
|
*/
|
|
async updateVolume(volume) {
|
|
return this.updateConfig({ volume: volume });
|
|
}
|
|
|
|
/**
|
|
* Update schedule configuration
|
|
* @param {object} schedule - Schedule configuration object
|
|
*/
|
|
async updateSchedule(schedule) {
|
|
return this.updateConfig({ schedule: schedule });
|
|
}
|
|
|
|
/**
|
|
* Create an Alpine.js data object for schedule management
|
|
* Reads configuration from JSON script tag in the template
|
|
* @returns {object} Alpine.js data object
|
|
*/
|
|
createScheduleManager() {
|
|
const self = this;
|
|
|
|
// Read configuration from JSON script tag
|
|
const configElement = document.getElementById("schedule-config");
|
|
const config = configElement ? JSON.parse(configElement.textContent) : {};
|
|
const initialSchedule = config.initialSchedule || {};
|
|
const volume = config.totalVolume || 0;
|
|
|
|
return {
|
|
schedule: { ...initialSchedule },
|
|
volume: volume,
|
|
selectedHours: [],
|
|
newWeight: 1.0,
|
|
volumeValue: volume,
|
|
isDragging: false,
|
|
dragOperation: null,
|
|
|
|
formatHour(h) {
|
|
return String(h).padStart(2, "0") + ":00";
|
|
},
|
|
|
|
async updateVolume() {
|
|
try {
|
|
const data = await self.updateVolume(this.volumeValue);
|
|
if (data.success) {
|
|
this.volume = parseFloat(this.volumeValue);
|
|
}
|
|
} catch (error) {
|
|
// Error handling is done in updateConfig
|
|
}
|
|
},
|
|
|
|
getBackgroundStyle(hour) {
|
|
const weight = parseFloat(this.schedule[hour]);
|
|
const maxWeight = 2.5;
|
|
|
|
// Normalize weight (0.0 to 1.0)
|
|
const t = Math.min(weight / maxWeight, 1.0);
|
|
|
|
// Interpolate HSL lightness: 95% (light) to 30% (dark)
|
|
const lightness = 95 - t * 65;
|
|
const backgroundColor = `hsl(210, 10%, ${lightness}%)`;
|
|
|
|
const textColor = t > 0.65 ? "white" : "black";
|
|
|
|
return {
|
|
backgroundColor,
|
|
color: textColor,
|
|
};
|
|
},
|
|
|
|
startDrag(event, hour) {
|
|
event.preventDefault();
|
|
this.isDragging = true;
|
|
this.dragOperation = this.isSelected(hour) ? "remove" : "add";
|
|
this.toggleSelect(hour);
|
|
},
|
|
|
|
dragSelect(hour) {
|
|
if (!this.isDragging) return;
|
|
const selected = this.isSelected(hour);
|
|
|
|
if (this.dragOperation === "add" && !selected) {
|
|
this.selectedHours.push(hour);
|
|
} else if (this.dragOperation === "remove" && selected) {
|
|
this.selectedHours = this.selectedHours.filter((h) => h !== hour);
|
|
}
|
|
},
|
|
|
|
endDrag() {
|
|
this.isDragging = false;
|
|
},
|
|
|
|
toggleSelect(hour) {
|
|
if (this.isSelected(hour)) {
|
|
this.selectedHours = this.selectedHours.filter((h) => h !== hour);
|
|
} else {
|
|
this.selectedHours.push(hour);
|
|
}
|
|
},
|
|
|
|
isSelected(hour) {
|
|
return this.selectedHours.includes(hour);
|
|
},
|
|
|
|
applyWeight() {
|
|
this.selectedHours.forEach((hour) => {
|
|
this.schedule[hour] = parseFloat(this.newWeight).toFixed(1);
|
|
});
|
|
this.selectedHours = [];
|
|
},
|
|
|
|
getTotalWeight() {
|
|
return Object.values(this.schedule).reduce(
|
|
(sum, w) => sum + parseFloat(w),
|
|
0
|
|
);
|
|
},
|
|
|
|
getPapersPerHour(hour) {
|
|
const total = this.getTotalWeight();
|
|
if (total === 0) return 0;
|
|
return (
|
|
(parseFloat(this.schedule[hour]) / total) *
|
|
this.volume
|
|
).toFixed(1);
|
|
},
|
|
|
|
async saveSchedule() {
|
|
try {
|
|
await self.updateSchedule(this.schedule);
|
|
} catch (error) {
|
|
// Error handling is done in updateConfig
|
|
}
|
|
},
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Global instance for easy access
|
|
*/
|
|
window.configHandler = new ConfigHandler();
|