Compare commits

...

2 Commits

Author SHA256 Message Date
be844bc4d0 basic save function 2025-07-13 17:05:58 -04:00
a90824efcd package updates 2025-07-13 16:51:47 -04:00
4 changed files with 826 additions and 15592 deletions

16307
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -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",

View File

@@ -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">

View File

@@ -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 {};