Compare commits
2 Commits
af68e8923c
...
be844bc4d0
| Author | SHA256 | Date | |
|---|---|---|---|
| be844bc4d0 | |||
| a90824efcd |
16307
package-lock.json
generated
16307
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -4,14 +4,15 @@
|
||||
"chartjs-plugin-annotation": "^3.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.15.31",
|
||||
"parcel": "^2.15.2",
|
||||
"@types/node": "^22.16.3",
|
||||
"autoprefixer": "^10.4.21",
|
||||
"parcel": "^2.15.4",
|
||||
"postcss": "^8.5.6",
|
||||
"typescript": "^5.8.3"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "parcel src/roast.html",
|
||||
"build": "parcel build src/roast.html --public-url=./ --dist-dir dist"
|
||||
|
||||
},
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
|
||||
@@ -13,7 +13,23 @@
|
||||
<div id="create-plan">
|
||||
<input type="text" id="plan-input" placeholder="Enter temperatures (comma separated)">
|
||||
<button onclick="setPlan()">Set Plan</button>
|
||||
|
||||
<!-- Save and Load Plan UI -->
|
||||
<div id="plan-storage" style="margin-top: 16px;">
|
||||
<input type="text" id="save-name" placeholder="Save plan as..." style="width: 60%; padding: 8px;">
|
||||
<button onclick="saveCurrentPlan()" style="padding: 8px 16px;">Save Plan</button>
|
||||
|
||||
<br><br>
|
||||
<button onclick="clearSavedPlans()" style="margin-top: 10px; padding: 6px 16px;">Clear All Plans</button>
|
||||
|
||||
<label for="saved-plans">Load a saved plan:</label>
|
||||
<select id="saved-plans" onchange="loadSavedPlan(this.value)" style="margin-left: 8px; padding: 6px;">
|
||||
<option value="">-- Select saved plan --</option>
|
||||
</select>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="controls" class="hidden">
|
||||
<div id="temp-buttons" class="button-group"></div>
|
||||
<div id="event-buttons" class="button-group">
|
||||
|
||||
88
src/roast.ts
88
src/roast.ts
@@ -21,9 +21,13 @@ declare global {
|
||||
exportCSV: () => void;
|
||||
showGraph: () => void;
|
||||
hideGraph: () => void;
|
||||
saveCurrentPlan: () => void;
|
||||
loadSavedPlan: (name: string) => void;
|
||||
clearSavedPlans: () => void;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function startTimer(): void {
|
||||
if (isRunning) {
|
||||
alert("Timer is already running. Click again to reset.");
|
||||
@@ -263,9 +267,87 @@ function hideGraph(): void {
|
||||
graphContainer.classList.add("hidden");
|
||||
graphContainer.classList.remove("graph-display-flex");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Expose functions to the global scope (allowing html direct access)
|
||||
function saveCurrentPlan(): void {
|
||||
const nameInput = document.getElementById("save-name") as HTMLInputElement;
|
||||
const planName = nameInput.value.trim();
|
||||
const rawInput = (document.getElementById("plan-input") as HTMLInputElement).value.trim();
|
||||
|
||||
if (!planName) {
|
||||
alert("Please enter a name to save the plan.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rawInput) {
|
||||
alert("Temperature list is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
const parsed = rawInput.split(',').map(x => x.trim()).map(Number);
|
||||
if (parsed.some(val => isNaN(val))) {
|
||||
alert("Invalid temperature list. Please enter comma-separated numbers.");
|
||||
return;
|
||||
}
|
||||
|
||||
const tempStr = parsed.join(",");
|
||||
localStorage.setItem(`roastplan_${planName}`, tempStr);
|
||||
nameInput.value = "";
|
||||
updateSavedPlansDropdown();
|
||||
}
|
||||
|
||||
|
||||
function loadSavedPlan(name: string): void {
|
||||
if (!name) return;
|
||||
const stored = localStorage.getItem(`roastplan_${name}`);
|
||||
if (stored) {
|
||||
targets = stored.split(",").map(Number);
|
||||
currentTargetIndex = 0;
|
||||
document.getElementById("controls")!.classList.remove("hidden");
|
||||
document.getElementById("create-plan")!.classList.add("hidden");
|
||||
generateTempButtons();
|
||||
}
|
||||
}
|
||||
|
||||
function updateSavedPlansDropdown(): void {
|
||||
const dropdown = document.getElementById("saved-plans") as HTMLSelectElement;
|
||||
dropdown.innerHTML = '<option value="">-- Select saved plan --</option>';
|
||||
for (let i = 0; i < localStorage.length; i++) {
|
||||
const key = localStorage.key(i);
|
||||
if (key && key.startsWith("roastplan_")) {
|
||||
const name = key.replace("roastplan_", "");
|
||||
const option = document.createElement("option");
|
||||
option.value = name;
|
||||
option.textContent = name;
|
||||
dropdown.appendChild(option);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clearSavedPlans(): void {
|
||||
const confirmClear = confirm("Are you sure you want to delete all saved roast plans?");
|
||||
if (!confirmClear) return;
|
||||
|
||||
const keysToRemove: string[] = [];
|
||||
|
||||
for (let i = 0; i < localStorage.length; i++) {
|
||||
const key = localStorage.key(i);
|
||||
if (key && key.startsWith("roastplan_")) {
|
||||
keysToRemove.push(key);
|
||||
}
|
||||
}
|
||||
|
||||
keysToRemove.forEach(key => localStorage.removeItem(key));
|
||||
updateSavedPlansDropdown();
|
||||
alert("All saved roast plans have been deleted.");
|
||||
}
|
||||
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
updateSavedPlansDropdown();
|
||||
});
|
||||
|
||||
// Include in window export
|
||||
if (typeof window !== 'undefined') {
|
||||
window.startTimer = startTimer;
|
||||
window.stopTimer = stopTimer;
|
||||
@@ -277,6 +359,10 @@ if (typeof window !== 'undefined') {
|
||||
window.exportCSV = exportCSV;
|
||||
window.showGraph = showGraph;
|
||||
window.hideGraph = hideGraph;
|
||||
window.saveCurrentPlan = saveCurrentPlan;
|
||||
window.loadSavedPlan = loadSavedPlan;
|
||||
window.clearSavedPlans = clearSavedPlans;
|
||||
}
|
||||
|
||||
|
||||
export {};
|
||||
|
||||
Reference in New Issue
Block a user