Created
April 10, 2025 22:56
-
-
Save Braunson/d0c54f8ac89b90ed1187503c6d0cc3cb to your computer and use it in GitHub Desktop.
Pizza Dough calculator build with Tailwind CSS & Alpine.js. Initially inspired + based on https://doughguy.co
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Pizza Dough Calculator</title> | |
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script> | |
<!-- Print-only styles --> | |
<style type="text/css" media="print"> | |
.print-hide, .print-hide * { | |
display: none !important; | |
} | |
.timer-section { | |
display: none !important; | |
} | |
body { | |
font-family: Arial, sans-serif; | |
background: white; | |
} | |
button, .text-sm.bg-blue-100 { | |
display: none !important; | |
} | |
@page { | |
margin: 1cm; | |
} | |
.recipe-content { | |
page-break-inside: avoid; | |
} | |
</style> | |
</head> | |
<body class="bg-gray-100 font-sans"> | |
<div class="container mx-auto py-8 px-4 max-w-4xl" x-data="doughCalculator()"> | |
<h1 class="text-3xl font-bold text-center mb-8 text-red-700">Pizza Dough Calculator</h1> | |
<!-- Controls --> | |
<div class="flex flex-wrap justify-between items-center mb-6 print-hide"> | |
<!-- Print Button --> | |
<button @click="printRecipe()" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded mb-2 sm:mb-0 flex items-center"> | |
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 17h2a2 2 0 002-2v-4a2 2 0 00-2-2H5a2 2 0 00-2 2v4a2 2 0 002 2h2m2 4h6a2 2 0 002-2v-4a2 2 0 00-2-2H9a2 2 0 00-2 2v4a2 2 0 002 2zm8-12V5a2 2 0 00-2-2H9a2 2 0 00-2 2v4h10z" /> | |
</svg> | |
Print Recipe | |
</button> | |
<!-- Show Active Timers --> | |
<button @click="showActiveTimers = !showActiveTimers" class="bg-gray-600 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded mb-2 sm:mb-0 flex items-center"> | |
Show/Hide Timers | |
</button> | |
<!-- Save Configuration --> | |
<div class="flex flex-col sm:flex-row gap-2"> | |
<input x-model="saveConfigName" placeholder="Configuration Name" class="border rounded px-3 py-2 w-full sm:w-48"> | |
<button @click="saveConfiguration()" class="bg-green-600 hover:bg-green-700 text-white font-bold py-2 px-4 rounded flex items-center"> | |
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4" /> | |
</svg> | |
Save Config | |
</button> | |
</div> | |
</div> | |
<!-- Saved Configurations --> | |
<div class="mb-6 print-hide" x-show="savedConfigs.length > 0"> | |
<div class="bg-white rounded-lg shadow p-4"> | |
<h3 class="font-semibold text-lg mb-2">Saved Configurations</h3> | |
<div class="flex flex-wrap gap-2"> | |
<template x-for="(config, index) in savedConfigs" :key="index"> | |
<div class="flex items-center"> | |
<button @click="loadConfiguration(config)" class="bg-gray-200 hover:bg-gray-300 text-gray-800 py-1 px-3 rounded-l"> | |
<span x-text="config.name"></span> | |
</button> | |
<button @click="deleteConfiguration(index)" class="bg-red-200 hover:bg-red-300 text-red-800 py-1 px-2 rounded-r"> | |
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" /> | |
</svg> | |
</button> | |
</div> | |
</template> | |
</div> | |
</div> | |
</div> | |
` | |
<!-- Main Calculator Card --> | |
<div class="bg-white rounded-lg shadow-lg p-6 mb-8"> | |
<!-- Basic Settings --> | |
<div class="grid md:grid-cols-2 gap-6 mb-6 print-hide"> | |
<div> | |
<h2 class="text-xl font-semibold mb-4 text-red-600">Basic Settings</h2> | |
<!-- Pizza Size --> | |
<div class="mb-4"> | |
<label class="block text-gray-700 mb-2">Pizza Size: <span x-text="pizzaSize"></span> <span x-text="units.length"></span></label> | |
<input type="range" x-model.number="pizzaSize" min="10" max="20" step="1" class="w-full h-2 bg-red-200 rounded-lg appearance-none cursor-pointer"> | |
</div> | |
<!-- Number of Pizzas --> | |
<div class="mb-4"> | |
<label class="block text-gray-700 mb-2">Number of Pizzas: <span x-text="pizzaQuantity"></span></label> | |
<input type="range" x-model.number="pizzaQuantity" min="1" max="10" step="1" class="w-full h-2 bg-red-200 rounded-lg appearance-none cursor-pointer"> | |
</div> | |
<!-- Pizza Thickness --> | |
<div class="mb-4"> | |
<label class="block text-gray-700 mb-2">Pizza Thickness:</label> | |
<select x-model.number="pizzaThickness" class="w-full p-2 border border-gray-300 rounded"> | |
<option value="1.8">Thin (1.8)</option> | |
<option value="2.11">Regular (2.11)</option> | |
<option value="2.75">Thick (2.75)</option> | |
</select> | |
</div> | |
<!-- Temperature Conversion --> | |
<div class="mb-4 p-4 bg-gray-50 rounded-lg"> | |
<h3 class="font-semibold text-md mb-2">Temperature Conversion</h3> | |
<div class="grid grid-cols-2 gap-3"> | |
<div> | |
<label class="block text-gray-700 text-sm">Fahrenheit</label> | |
<input type="number" x-model.number="fahrenheit" @input="celsiusFromF()" class="w-full p-2 border border-gray-300 rounded"> | |
</div> | |
<div> | |
<label class="block text-gray-700 text-sm">Celsius</label> | |
<input type="number" x-model.number="celsius" @input="fahrenheitFromC()" class="w-full p-2 border border-gray-300 rounded"> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div> | |
<h2 class="text-xl font-semibold mb-4 text-red-600">Advanced Settings</h2> | |
<!-- Unit Toggle --> | |
<div class="mb-4"> | |
<label class="block text-gray-700 mb-2">Measurement Units:</label> | |
<div class="flex space-x-4"> | |
<label class="inline-flex items-center"> | |
<input type="radio" x-model="unitSystem" value="metric" class="form-radio text-red-600"> | |
<span class="ml-2">Metric (g, ml)</span> | |
</label> | |
<label class="inline-flex items-center"> | |
<input type="radio" x-model="unitSystem" value="imperial" class="form-radio text-red-600"> | |
<span class="ml-2">Imperial (oz, cups)</span> | |
</label> | |
</div> | |
</div> | |
<!-- Hydration Percentage --> | |
<div class="mb-4"> | |
<label class="block text-gray-700 mb-2">Hydration: <span x-text="hydrationPercentage"></span>%</label> | |
<input type="range" x-model.number="hydrationPercentage" min="55" max="75" step="1" class="w-full h-2 bg-red-200 rounded-lg appearance-none cursor-pointer"> | |
</div> | |
<!-- Preferment Option --> | |
<div class="mb-4"> | |
<label class="block text-gray-700 mb-2">Dough Method:</label> | |
<select x-model="doughMethod" class="w-full p-2 border border-gray-300 rounded"> | |
<option value="direct">Direct Method</option> | |
<option value="preferment">Preferment (Biga/Poolish)</option> | |
<option value="sourdough">Sourdough</option> | |
</select> | |
</div> | |
<!-- Preferment Percentage (only visible when preferment is selected) --> | |
<div class="mb-4" x-show="doughMethod === 'preferment'"> | |
<label class="block text-gray-700 mb-2">Preferment Percentage: <span x-text="prefermentPercentage"></span>%</label> | |
<input type="range" x-model.number="prefermentPercentage" min="20" max="60" step="5" class="w-full h-2 bg-red-200 rounded-lg appearance-none cursor-pointer"> | |
</div> | |
<!-- Sourdough Starter Percentage (only visible when sourdough is selected) --> | |
<div class="mb-4" x-show="doughMethod === 'sourdough'"> | |
<label class="block text-gray-700 mb-2">Starter Percentage: <span x-text="starterPercentage"></span>%</label> | |
<input type="range" x-model.number="starterPercentage" min="10" max="30" step="5" class="w-full h-2 bg-red-200 rounded-lg appearance-none cursor-pointer"> | |
<p class="text-sm text-gray-500 mt-1">Assumes 100% hydration starter</p> | |
</div> | |
</div> | |
</div> | |
<!-- Results --> | |
<div class="mt-8 border-t pt-6 recipe-content"> | |
<h2 class="text-xl font-semibold mb-4 text-center text-red-600">Recipe Results</h2> | |
<!-- Ingredient Table --> | |
<div class="overflow-x-auto"> | |
<table class="w-full border-collapse"> | |
<thead> | |
<tr class="bg-red-100"> | |
<th class="p-2 text-left border">Ingredient</th> | |
<th class="p-2 text-right border">Amount</th> | |
<template x-if="doughMethod === 'preferment'"> | |
<th class="p-2 text-right border">For Preferment</th> | |
</template> | |
<template x-if="doughMethod === 'sourdough'"> | |
<th class="p-2 text-right border">For Levain</th> | |
</template> | |
<th class="p-2 text-right border">For Main Dough</th> | |
</tr> | |
</thead> | |
<tbody> | |
<!-- Flour --> | |
<tr class="border-b hover:bg-gray-50"> | |
<td class="p-2 border">Flour</td> | |
<td class="p-2 text-right border"> | |
<span x-text="formatMeasurement(ingredients.flour.total)"></span> | |
</td> | |
<template x-if="doughMethod === 'preferment'"> | |
<td class="p-2 text-right border"> | |
<span x-text="formatMeasurement(ingredients.flour.preferment)"></span> | |
</td> | |
</template> | |
<template x-if="doughMethod === 'sourdough'"> | |
<td class="p-2 text-right border"> | |
<span x-text="formatMeasurement(ingredients.flour.preferment)"></span> | |
</td> | |
</template> | |
<td class="p-2 text-right border"> | |
<span x-text="formatMeasurement(ingredients.flour.main)"></span> | |
</td> | |
</tr> | |
<!-- Water --> | |
<tr class="border-b hover:bg-gray-50"> | |
<td class="p-2 border">Water</td> | |
<td class="p-2 text-right border"> | |
<span x-text="formatMeasurement(ingredients.water.total, 'liquid')"></span> | |
</td> | |
<template x-if="doughMethod === 'preferment'"> | |
<td class="p-2 text-right border"> | |
<span x-text="formatMeasurement(ingredients.water.preferment, 'liquid')"></span> | |
</td> | |
</template> | |
<template x-if="doughMethod === 'sourdough'"> | |
<td class="p-2 text-right border"> | |
<span x-text="formatMeasurement(ingredients.water.preferment, 'liquid')"></span> | |
</td> | |
</template> | |
<td class="p-2 text-right border"> | |
<span x-text="formatMeasurement(ingredients.water.main, 'liquid')"></span> | |
</td> | |
</tr> | |
<!-- Sourdough Starter (only for sourdough method) --> | |
<template x-if="doughMethod === 'sourdough'"> | |
<tr class="border-b hover:bg-gray-50"> | |
<td class="p-2 border">Sourdough Starter (100% hydration)</td> | |
<td class="p-2 text-right border"> | |
<span x-text="formatMeasurement(ingredients.starter.total)"></span> | |
</td> | |
<td class="p-2 text-right border"> | |
<span x-text="formatMeasurement(ingredients.starter.total)"></span> | |
</td> | |
<td class="p-2 text-right border">0</td> | |
</tr> | |
</template> | |
<!-- Yeast (not for sourdough) --> | |
<template x-if="doughMethod !== 'sourdough'"> | |
<tr class="border-b hover:bg-gray-50"> | |
<td class="p-2 border">Yeast (instant dry)</td> | |
<td class="p-2 text-right border"> | |
<span x-text="formatMeasurement(ingredients.yeast.total, 'yeast')"></span> | |
</td> | |
<template x-if="doughMethod === 'preferment'"> | |
<td class="p-2 text-right border"> | |
<span x-text="formatMeasurement(ingredients.yeast.preferment, 'yeast')"></span> | |
</td> | |
</template> | |
<td class="p-2 text-right border"> | |
<span x-text="formatMeasurement(ingredients.yeast.main, 'yeast')"></span> | |
</td> | |
</tr> | |
</template> | |
<!-- Salt --> | |
<tr class="border-b hover:bg-gray-50"> | |
<td class="p-2 border">Salt</td> | |
<td class="p-2 text-right border"> | |
<span x-text="formatMeasurement(ingredients.salt.total)"></span> | |
</td> | |
<template x-if="doughMethod === 'preferment' || doughMethod === 'sourdough'"> | |
<td class="p-2 text-right border">0</td> | |
</template> | |
<td class="p-2 text-right border"> | |
<span x-text="formatMeasurement(ingredients.salt.main)"></span> | |
</td> | |
</tr> | |
<!-- Sugar --> | |
<tr class="border-b hover:bg-gray-50"> | |
<td class="p-2 border">Sugar</td> | |
<td class="p-2 text-right border"> | |
<span x-text="formatMeasurement(ingredients.sugar.total)"></span> | |
</td> | |
<template x-if="doughMethod === 'preferment' || doughMethod === 'sourdough'"> | |
<td class="p-2 text-right border">0</td> | |
</template> | |
<td class="p-2 text-right border"> | |
<span x-text="formatMeasurement(ingredients.sugar.main)"></span> | |
</td> | |
</tr> | |
<!-- Olive Oil --> | |
<tr class="border-b hover:bg-gray-50"> | |
<td class="p-2 border">Olive Oil</td> | |
<td class="p-2 text-right border"> | |
<span x-text="formatMeasurement(ingredients.oliveOil.total, 'liquid')"></span> | |
</td> | |
<template x-if="doughMethod === 'preferment' || doughMethod === 'sourdough'"> | |
<td class="p-2 text-right border">0</td> | |
</template> | |
<td class="p-2 text-right border"> | |
<span x-text="formatMeasurement(ingredients.oliveOil.main, 'liquid')"></span> | |
</td> | |
</tr> | |
<!-- Total Dough Weight --> | |
<tr class="border-b hover:bg-gray-50 font-bold bg-gray-100"> | |
<td class="p-2 border">Total Dough Weight</td> | |
<td class="p-2 text-right border"> | |
<span x-text="formatMeasurement(totalDoughWeight)"></span> | |
</td> | |
<template x-if="doughMethod === 'preferment' || doughMethod === 'sourdough'"> | |
<td class="p-2 text-right border"> | |
<span x-text="formatMeasurement(prefermentTotalWeight)"></span> | |
</td> | |
</template> | |
<td class="p-2 text-right border"> | |
<span x-text="formatMeasurement(mainDoughWeight)"></span> | |
</td> | |
</tr> | |
<!-- Dough Ball Weight --> | |
<tr class="border-b hover:bg-gray-50 font-bold"> | |
<td class="p-2 border">Dough Ball Weight (each)</td> | |
<td class="p-2 text-right border" colspan="3"> | |
<span x-text="formatMeasurement(doughBallWeight)"></span> | |
</td> | |
</tr> | |
</tbody> | |
</table> | |
</div> | |
</div> | |
</div> | |
<!-- The Active Timers section at the top still provides a consolidated view --> | |
<div class="mb-6 print-hide" x-show="activeTimers.length > 0 && showActiveTimers"> | |
<div class="bg-white rounded-lg shadow p-4"> | |
<h3 class="font-semibold text-lg mb-2">Active Timers</h3> | |
<div class="space-y-2"> | |
<template x-for="timer in activeTimers" :key="timer.id"> | |
<div class="bg-yellow-100 border-l-4 border-yellow-500 p-3 rounded" | |
:class="{ | |
'bg-yellow-100 border-yellow-500': timer.running && timer.remaining > 0, | |
'bg-gray-100 border-gray-500': !timer.running && timer.remaining > 0, | |
'bg-green-100 border-green-500': timer.remaining <= 0 | |
}"> | |
<div class="flex justify-between items-center"> | |
<div> | |
<h4 class="font-bold" x-text="timer.name"></h4> | |
<p class="text-2xl font-mono" x-text="formatTime(timer.remaining)"></p> | |
</div> | |
<div class="flex gap-2"> | |
<button | |
@click="toggleTimerById(timer.id)" | |
class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-1 px-3 rounded" | |
:class="timer.running ? 'bg-yellow-600 hover:bg-yellow-700' : 'bg-blue-600 hover:bg-blue-700'"> | |
<span x-text="timer.running ? 'Pause' : 'Resume'"></span> | |
</button> | |
<button | |
@click="resetTimerById(timer.id)" | |
class="bg-green-600 hover:bg-green-700 text-white font-bold py-1 px-3 rounded"> | |
Reset | |
</button> | |
<button | |
@click="removeTimerById(timer.id)" | |
class="bg-red-600 hover:bg-red-700 text-white font-bold py-1 px-3 rounded"> | |
Remove | |
</button> | |
</div> | |
</div> | |
</div> | |
</template> | |
</div> | |
</div> | |
</div> | |
<!-- Instructions Card --> | |
<div class="bg-white rounded-lg shadow-lg p-6 recipe-content"> | |
<h2 class="text-xl font-semibold mb-4 text-red-600">Dough Making Instructions</h2> | |
<!-- Direct Method Instructions --> | |
<template x-if="doughMethod === 'direct'"> | |
<ol class="list-decimal pl-6 space-y-2"> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>Cool water to <60°F (15°C).</span> | |
<div class="timer-section" x-html="timerButton('Cool water', 5)"></div> | |
</div> | |
</li> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>Mix the water and yeast.</span> | |
<div class="timer-section" x-html="timerButton('Mix water & yeast', 1)"></div> | |
</div> | |
</li> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>Add flour and olive oil and mix for 2 minutes.</span> | |
<div class="timer-section" x-html="timerButton('Initial mix', 2)"></div> | |
</div> | |
</li> | |
<li>Keep mixing on low, then add sugar and salt.</li> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>Mix for 10 more minutes.</span> | |
<div class="timer-section" x-html="timerButton('Final mix', 10)"></div> | |
</div> | |
</li> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>Cover the dough with plastic wrap and rest for 20 minutes.</span> | |
<div class="timer-section" x-html="timerButton('Dough rest', 20)"></div> | |
</div> | |
</li> | |
<li>Divide the dough into <span x-text="pizzaQuantity"></span> portions of <span x-text="formatMeasurement(doughBallWeight)"></span> each.</li> | |
<li>Shape into balls, sealing the seam.</li> | |
<li>Put the dough in a lightly oiled container.</li> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>Cover tightly and refrigerate for 2-4 days. 3 days is ideal.</span> | |
</div> | |
</li> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>Let the dough come to room temperature before using (about 2 hours).</span> | |
<div class="timer-section" x-html="timerButton('Room temp rest', 120, '2 hours')"></div> | |
</div> | |
</li> | |
</ol> | |
</template> | |
<!-- Preferment Method Instructions --> | |
<template x-if="doughMethod === 'preferment'"> | |
<div> | |
<h3 class="font-semibold text-lg mb-2">Day 1: Make the Preferment</h3> | |
<ol class="list-decimal pl-6 space-y-2 mb-4"> | |
<li>Mix <span x-text="formatMeasurement(ingredients.flour.preferment)"></span> flour with <span x-text="formatMeasurement(ingredients.water.preferment, 'liquid')"></span> water and <span x-text="formatMeasurement(ingredients.yeast.preferment, 'yeast')"></span> yeast.</li> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>Cover and let ferment at room temperature for 12-16 hours.</span> | |
<div class="flex items-center timer-section"> | |
<button @click="startTimer('Preferment fermentation', 14*60)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded"> | |
Set Timer (14 hrs) | |
</button> | |
</div> | |
</div> | |
</li> | |
</ol> | |
<h3 class="font-semibold text-lg mb-2">Day 2: Make the Final Dough</h3> | |
<ol class="list-decimal pl-6 space-y-2"> | |
<li>Add the preferment to <span x-text="formatMeasurement(ingredients.water.main, 'liquid')"></span> cool water.</li> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>Add <span x-text="formatMeasurement(ingredients.flour.main)"></span> flour and <span x-text="formatMeasurement(ingredients.oliveOil.main, 'liquid')"></span> olive oil and mix for 2 minutes.</span> | |
<div class="flex items-center timer-section"> | |
<button @click="startTimer('Initial mix', 2)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded"> | |
Set Timer (2 min) | |
</button> | |
</div> | |
</div> | |
</li> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>Add <span x-text="formatMeasurement(ingredients.salt.main)"></span> salt and <span x-text="formatMeasurement(ingredients.sugar.main)"></span> sugar and mix for 8-10 more minutes.</span> | |
<div class="flex items-center timer-section"> | |
<button @click="startTimer('Final mix', 9)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded"> | |
Set Timer (9 min) | |
</button> | |
</div> | |
</div> | |
</li> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>Cover the dough and let rest for 30 minutes.</span> | |
<div class="flex items-center timer-section"> | |
<button @click="startTimer('Dough rest', 30)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded"> | |
Set Timer (30 min) | |
</button> | |
</div> | |
</div> | |
</li> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>Perform 3-4 sets of stretch and folds at 30-minute intervals.</span> | |
<div class="flex items-center timer-section"> | |
<button @click="startTimer('Stretch and fold', 30)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded"> | |
Set Timer (30 min) | |
</button> | |
</div> | |
</div> | |
</li> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>After the final fold, let the dough bulk ferment for 1-2 hours at room temperature.</span> | |
<div class="flex items-center timer-section"> | |
<button @click="startTimer('Bulk fermentation', 90)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded"> | |
Set Timer (90 min) | |
</button> | |
</div> | |
</div> | |
</li> | |
<li>Divide the dough into <span x-text="pizzaQuantity"></span> portions of <span x-text="formatMeasurement(doughBallWeight)"></span> each.</li> | |
<li>Shape into balls, sealing the seam.</li> | |
<li>Put the dough in a lightly oiled container.</li> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>Cover tightly and refrigerate for 24-48 hours.</span> | |
<div class="flex items-center timer-section"> | |
<button @click="startTimer('Refrigeration', 36*60)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded"> | |
Set Timer (36 hrs) | |
</button> | |
</div> | |
</div> | |
</li> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>Let the dough come to room temperature before using (about 2-3 hours).</span> | |
<div class="flex items-center timer-section"> | |
<button @click="startTimer('Room temp rest', 150)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded"> | |
Set Timer (2.5 hrs) | |
</button> | |
</div> | |
</div> | |
</li> | |
</ol> | |
</div> | |
</template> | |
<!-- Sourdough Method Instructions --> | |
<template x-if="doughMethod === 'sourdough'"> | |
<div> | |
<h3 class="font-semibold text-lg mb-2">Day 1: Make the Levain</h3> | |
<ol class="list-decimal pl-6 space-y-2 mb-4"> | |
<li>Mix <span x-text="formatMeasurement(ingredients.starter.total)"></span> sourdough starter with <span x-text="formatMeasurement(ingredients.flour.preferment)"></span> flour and <span x-text="formatMeasurement(ingredients.water.preferment, 'liquid')"></span> water.</li> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>Cover and let ferment at room temperature for 8-12 hours.</span> | |
<div class="flex items-center timer-section"> | |
<button @click="startTimer('Levain fermentation', 10*60)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded"> | |
Set Timer (10 hrs) | |
</button> | |
</div> | |
</div> | |
</li> | |
</ol> | |
<h3 class="font-semibold text-lg mb-2">Day 2: Make the Final Dough</h3> | |
<ol class="list-decimal pl-6 space-y-2"> | |
<li>Add the levain to <span x-text="formatMeasurement(ingredients.water.main, 'liquid')"></span> cool water.</li> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>Add <span x-text="formatMeasurement(ingredients.flour.main)"></span> flour and <span x-text="formatMeasurement(ingredients.oliveOil.main, 'liquid')"></span> olive oil and mix for 2 minutes.</span> | |
<div class="flex items-center timer-section"> | |
<button @click="startTimer('Initial mix', 2)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded"> | |
Set Timer (2 min) | |
</button> | |
</div> | |
</div> | |
</li> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>Add <span x-text="formatMeasurement(ingredients.salt.main)"></span> salt and <span x-text="formatMeasurement(ingredients.sugar.main)"></span> sugar and mix for 2 more minutes.</span> | |
<div class="flex items-center timer-section"> | |
<button @click="startTimer('Final mix', 2)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded"> | |
Set Timer (2 min) | |
</button> | |
</div> | |
</div> | |
</li> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>Cover the dough and let rest for 30 minutes.</span> | |
<div class="flex items-center timer-section"> | |
<button @click="startTimer('Dough rest', 30)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded"> | |
Set Timer (30 min) | |
</button> | |
</div> | |
</div> | |
</li> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>Perform 4-6 sets of stretch and folds at 30-minute intervals.</span> | |
<div class="flex items-center timer-section"> | |
<button @click="startTimer('Stretch and fold', 30)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded"> | |
Set Timer (30 min) | |
</button> | |
</div> | |
</div> | |
</li> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>After the final fold, let the dough bulk ferment for 2-4 hours at room temperature.</span> | |
<div class="flex items-center timer-section"> | |
<button @click="startTimer('Bulk fermentation', 3*60)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded"> | |
Set Timer (3 hrs) | |
</button> | |
</div> | |
</div> | |
</li> | |
<li>Divide the dough into <span x-text="pizzaQuantity"></span> portions of <span x-text="formatMeasurement(doughBallWeight)"></span> each.</li> | |
<li>Shape into balls, sealing the seam.</li> | |
<li>Put the dough in a lightly oiled container.</li> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>Cover tightly and refrigerate for 24-72 hours.</span> | |
<div class="flex items-center timer-section"> | |
<button @click="startTimer('Refrigeration', 48*60)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded"> | |
Set Timer (48 hrs) | |
</button> | |
</div> | |
</div> | |
</li> | |
<li> | |
<div class="flex justify-between items-center"> | |
<span>Let the dough come to room temperature before using (about 3-4 hours).</span> | |
<div class="flex items-center timer-section"> | |
<button @click="startTimer('Room temp rest', 3.5*60)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded"> | |
Set Timer (3.5 hrs) | |
</button> | |
</div> | |
</div> | |
</li> | |
</ol> | |
</div> | |
</template> | |
</div> | |
<!-- Attribution Footer --> | |
<div class="mt-8 text-center text-gray-600 text-sm recipe-content"> | |
<p>Initially inspired by and based on the <a href="https://doughguy.co" class="text-blue-600 hover:underline">DoughGuy calculator</a></p> | |
</div> | |
</div> | |
<script> | |
function doughCalculator() { | |
return { | |
// Basic settings | |
pizzaSize: 16, | |
pizzaQuantity: 6, | |
pizzaThickness: 2.11, | |
// Advanced settings | |
unitSystem: 'metric', | |
hydrationPercentage: 62, | |
doughMethod: 'direct', | |
prefermentPercentage: 30, | |
starterPercentage: 20, | |
// Temperature conversion | |
fahrenheit: 60, | |
celsius: 15.6, | |
// Local storage config | |
savedConfigs: [], | |
saveConfigName: '', | |
// Timer settings (multiple timers) | |
activeTimers: [], | |
showActiveTimers: false, | |
// Unit conversions | |
units: { | |
weight: 'g', | |
liquid: 'ml', | |
length: 'inches' | |
}, | |
timerButton(name, minutes, timeFormat = null) { | |
return ` | |
<div x-data="{ localTimer: null }" :id="'timer-container-' + Date.now() + Math.floor(Math.random() * 1000)"> | |
<!-- Timer button --> | |
<button | |
@click="localTimer = startTimerForStep('${name}', ${minutes}, $el.parentNode)" | |
x-show="!localTimer || !timerExists(localTimer)" | |
class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded"> | |
Set Timer (${timeFormat ? timeFormat : minutes + ' mins'}) | |
</button> | |
<!-- Timer display --> | |
<div | |
x-show="localTimer && timerExists(localTimer)" | |
class="flex items-center space-x-1 py-1 px-2 rounded" | |
:class="{ | |
'bg-yellow-100 text-yellow-800': localTimer && getTimer(localTimer).running && getTimer(localTimer).remaining > 0, | |
'bg-gray-100 text-gray-800': localTimer && !getTimer(localTimer).running && getTimer(localTimer).remaining > 0, | |
'bg-green-100 text-green-800': localTimer && getTimer(localTimer).remaining <= 0 | |
}"> | |
<span class="font-mono" x-text="localTimer && timerExists(localTimer) ? formatTime(getTimer(localTimer).remaining) : ''"></span> | |
<div class="flex space-x-1"> | |
<button | |
@click="toggleTimerById(localTimer)" | |
class="text-xs p-1 rounded" | |
:class="localTimer && getTimer(localTimer).running ? 'bg-yellow-200 hover:bg-yellow-300' : 'bg-blue-200 hover:bg-blue-300'"> | |
<span x-text="localTimer && getTimer(localTimer).running ? 'Pause' : 'Resume'"></span> | |
</button> | |
<button | |
@click="resetTimerById(localTimer)" | |
class="text-xs p-1 bg-green-200 hover:bg-green-300 rounded"> | |
Reset | |
</button> | |
<button | |
@click="removeTimerById(localTimer)" | |
class="text-xs p-1 bg-red-200 hover:bg-red-300 rounded"> | |
✕ | |
</button> | |
</div> | |
</div> | |
</div> | |
`; | |
}, | |
// Initialize | |
init() { | |
this.loadSavedConfigs(); | |
// Set up a timer checking interval that runs every second | |
setInterval(() => { | |
this.activeTimers.forEach((timer, index) => { | |
if (timer.running) { | |
timer.remaining--; | |
// If timer reaches zero | |
if (timer.remaining <= 0) { | |
timer.running = false; | |
// Play sound or notification | |
if (Notification.permission === 'granted') { | |
new Notification('Timer Complete', { | |
body: `Your ${timer.name} timer is complete!`, | |
//icon: '/favicon.ico' | |
}); | |
} | |
try { | |
var snd = new Audio("data:audio/mp4;base64,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8VkVWN7//////ww4XW//hdaDYNC63//DDYNg7///8DDFwNIPC6wGOHgwcAMOxWRVKkxBTUUzLjEwMKqquMOly6gYAIXDoyTRg25i45Zso5un81SLA2ncI1tMgwKIcxMB4BC+NBoLAOwOgLUtch9coEAFOGjjxf5MsFALJEZVCC7Rf0LACBQsMNQUVRhhaLqS+kqV6meFekgMu7A9Jbwz/+rReadtUtNVrVa1aZmkyS1sU3liiXgtolKS+orHKYJoHyiCnDaf7O3//QJI2RWgSRSRSX/3E9KRqkiktX2E+I552Z+ZmcaMr0/v77VtW25uZubm5Ww5EYmtQ5ububS9L0vtLpEEETy9O/v74nhBR9VVVXtVVVZummi+llhkvPulQRBImCpjU0GmWsb1//PkZPAb+djUAHWs1rcUAbAE5ha9XhjUzmZyOc2s5qQ5GbTubgSIwFgoCRUBM3ibCC6UdhoQHCKs6clnIVUHOjNNS00ZhQNAQpOiXEm3ii9i3fvZY5Y1o7Du///1uOKBSCfvX7NqzWq0s1HVHkFo/Ur4MPk2iStf/8kEPx0B0KhyZL1dX///8xMPQD0fmJgxLVTIPSyQ3H1ryk0JruSbE+oHo/RSZWwnJNiYmHsZdeNpGXbI2kKea6YmWPZdXX/////82STK6//5QAfF6BOdPyTYmPVDycfV1VoE6qquGJVVTEFNRTMuMTAwqqqqqqqqCLRu+Q0BoUhFlkICqULALjhvh0jeLqXYdoyhZxbCaDGG6ZyLTBdRZg2RTR8EvPBLpUyiCjCFmHeWw40qqosFiTx+opcrpEncZpUGAdaacpp1CW4kI7SoN9OKdSKdQLaqQ1TNrcnTeKEexUHOjHcXD5hUymX1wxvG940qlDT+Uq6XKKO02DDO9QNLjGiwoMkl9b/9bQpcZxnGaU3X6jK0/jdO1IKdghtS5XCnZ3TM9ZlCX4kJAiNF/QhziSsSRTC8xvH7x+socX03Uwp2Bval9cJ9ncX0uKq4vonwsxAy+IepEmiEPRhwluO1SP5DlFeC//PkZPAl/hyUBmMPAiLUOVgEYU180hsjsLeciLOw5zaH8IUJ6Rou52GaQIaIkA7DLQLNq8yuOU3T2XbA1sR+l2Kk2TkUbhDgP3SqTylXm+RhP4upRKlavunxJHoTyocK3bVszA2+6urZaShxFQ1DmYK3H6f3TMz9WmWWL0/vrZqGh2fRFqiodmMqOzlMJKR2f/1RFRdP/oqaoqEdjFMIiQWNIPZymERISEyHRUUhHbMUSERpDt2MZUWqKMQ7P7FRfRV/0//6p+UkCiQI+LZzLvKfycCihR6Fw8bk07OxpwHVTEFNRTMuMTAwVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV"); | |
audio.play(); | |
} catch (e) { | |
console.log('Audio play failed', e); | |
} | |
} | |
} | |
}); | |
}, 1000); | |
}, | |
// Calculate all ingredients | |
get ingredients() { | |
// Base calculations for 16" pizza, 6 pizzas, regular thickness (2.11) | |
const basePizzaSize = 16; | |
const baseFlourAmount = 1509.797685; | |
const baseQuantity = 6; | |
const baseThickness = 2.11; | |
// Calculate scaling factors | |
const sizeScaleFactor = Math.pow(this.pizzaSize / basePizzaSize, 2); | |
const quantityScaleFactor = this.pizzaQuantity / baseQuantity; | |
const thicknessScaleFactor = this.pizzaThickness / baseThickness; | |
// Calculate total flour amount | |
const flourAmount = baseFlourAmount * sizeScaleFactor * quantityScaleFactor * thicknessScaleFactor; | |
// Calculate ingredients based on baker's percentages | |
const water = flourAmount * (this.hydrationPercentage / 100); | |
const yeast = flourAmount * 0.004; // 0.4% yeast | |
const salt = flourAmount * 0.025; // 2.5% salt | |
const sugar = flourAmount * 0.025; // 2.5% sugar | |
const oliveOil = flourAmount * 0.033; // 3.3% olive oil | |
let flourPreferment = 0; | |
let waterPreferment = 0; | |
let yeastPreferment = 0; | |
let starter = 0; | |
// Calculate preferment amounts if using preferment method | |
if (this.doughMethod === 'preferment') { | |
flourPreferment = flourAmount * (this.prefermentPercentage / 100); | |
waterPreferment = flourPreferment * 1; // 100% hydration preferment | |
yeastPreferment = flourPreferment * 0.001; // 0.1% yeast in preferment | |
} | |
// Calculate sourdough starter and levain if using sourdough method | |
if (this.doughMethod === 'sourdough') { | |
starter = flourAmount * (this.starterPercentage / 100); | |
flourPreferment = starter / 2; // Assuming 100% hydration starter | |
waterPreferment = starter / 2; | |
} | |
// Calculate main dough amounts | |
const flourMain = flourAmount - flourPreferment; | |
const waterMain = water - waterPreferment; | |
const yeastMain = this.doughMethod === 'preferment' ? (yeast - yeastPreferment) : yeast; | |
return { | |
flour: { | |
total: Math.round(flourAmount), | |
preferment: Math.round(flourPreferment), | |
main: Math.round(flourMain) | |
}, | |
water: { | |
total: Math.round(water), | |
preferment: Math.round(waterPreferment), | |
main: Math.round(waterMain) | |
}, | |
yeast: { | |
total: yeast, | |
preferment: yeastPreferment, | |
main: this.doughMethod === 'sourdough' ? 0 : yeast - yeastPreferment | |
}, | |
salt: { | |
total: Math.round(salt), | |
main: Math.round(salt) | |
}, | |
sugar: { | |
total: Math.round(sugar), | |
main: Math.round(sugar) | |
}, | |
oliveOil: { | |
total: Math.round(oliveOil), | |
main: Math.round(oliveOil) | |
}, | |
starter: { | |
total: Math.round(starter) | |
} | |
}; | |
}, | |
// Calculate total dough weight | |
get totalDoughWeight() { | |
return this.ingredients.flour.total + | |
this.ingredients.water.total + | |
(this.doughMethod === 'sourdough' ? 0 : this.ingredients.yeast.total) + | |
this.ingredients.salt.total + | |
this.ingredients.sugar.total + | |
this.ingredients.oliveOil.total; | |
}, | |
// Calculate preferment weight | |
get prefermentTotalWeight() { | |
if (this.doughMethod === 'preferment') { | |
return this.ingredients.flour.preferment + | |
this.ingredients.water.preferment + | |
this.ingredients.yeast.preferment; | |
} else if (this.doughMethod === 'sourdough') { | |
return this.ingredients.starter.total + | |
this.ingredients.flour.preferment + | |
this.ingredients.water.preferment; | |
} | |
return 0; | |
}, | |
// Calculate main dough weight | |
get mainDoughWeight() { | |
return this.totalDoughWeight - (this.prefermentTotalWeight || 0); | |
}, | |
// Calculate dough ball weight | |
get doughBallWeight() { | |
return Math.round(this.totalDoughWeight / this.pizzaQuantity); | |
}, | |
// Format measurements based on unit system | |
formatMeasurement(value, type = 'weight') { | |
if (value === 0) return '0'; | |
if (this.unitSystem === 'metric') { | |
if (type === 'yeast') { | |
return value.toFixed(1) + ' g'; | |
} else { | |
return Math.round(value) + (type === 'liquid' ? ' ml' : ' g'); | |
} | |
} else { | |
// Imperial conversions | |
if (type === 'yeast') { | |
const tsp = value / 3; // Approximately 3g per tsp of instant yeast | |
return tsp.toFixed(2) + ' tsp'; | |
} else if (type === 'liquid') { | |
const flOz = value / 29.574; // ml to fl oz | |
if (flOz < 0.25) { | |
return (flOz * 2).toFixed(1) + ' tsp'; | |
} else if (flOz < 2) { | |
return (flOz * 2).toFixed(1) + ' tbsp'; | |
} else { | |
const cups = flOz / 8; | |
return cups.toFixed(2) + ' cups'; | |
} | |
} else { | |
const oz = value / 28.35; // g to oz | |
return oz.toFixed(2) + ' oz'; | |
} | |
} | |
}, | |
// Temperature conversion functions | |
celsiusFromF() { | |
this.celsius = parseFloat(((this.fahrenheit - 32) * 5/9).toFixed(1)); | |
}, | |
fahrenheitFromC() { | |
this.fahrenheit = parseFloat((this.celsius * 9/5 + 32).toFixed(1)); | |
}, | |
// Multiple Timer functions | |
startTimer(name, minutes) { | |
// Request notification permission if needed | |
if (Notification.permission !== 'granted' && Notification.permission !== 'denied') { | |
Notification.requestPermission(); | |
} | |
// Add a new timer to the activeTimers array | |
this.activeTimers.push({ | |
name: name, | |
originalTime: minutes * 60, // Store original time for reset | |
remaining: minutes * 60, // In seconds | |
running: true, | |
id: Date.now() // Unique ID for the timer | |
}); | |
}, | |
// New timer functions for integrated timers | |
startTimerForStep(name, minutes, containerEl) { | |
// Request notification permission if needed | |
if (Notification.permission !== 'granted' && Notification.permission !== 'denied') { | |
Notification.requestPermission(); | |
} | |
// Generate a unique ID for this timer | |
const timerId = Date.now(); | |
// Track the container that started this timer | |
const containerId = containerEl ? containerEl.id : null; | |
// Add a new timer to the activeTimers array | |
this.activeTimers.push({ | |
id: timerId, | |
name: name, | |
originalTime: minutes * 60, // Store original time for reset | |
remaining: minutes * 60, // In seconds | |
running: true, | |
containerId: containerId // Store the container ID | |
}); | |
return timerId; | |
}, | |
timerExists(id) { | |
if (!id) return false; | |
return this.activeTimers.some(timer => timer.id === id); | |
}, | |
// Get a timer by ID | |
getTimer(id) { | |
if (!id) return { running: false, remaining: 0 }; | |
return this.activeTimers.find(timer => timer.id === id) || { running: false, remaining: 0 }; | |
}, | |
// Toggle timer by ID | |
toggleTimerById(id) { | |
const timerIndex = this.activeTimers.findIndex(timer => timer.id === id); | |
if (timerIndex >= 0) { | |
this.activeTimers[timerIndex].running = !this.activeTimers[timerIndex].running; | |
} | |
}, | |
// Reset timer by ID | |
resetTimerById(id) { | |
const timerIndex = this.activeTimers.findIndex(timer => timer.id === id); | |
if (timerIndex >= 0) { | |
this.activeTimers[timerIndex].remaining = this.activeTimers[timerIndex].originalTime; | |
this.activeTimers[timerIndex].running = true; | |
} | |
}, | |
// Remove timer by ID | |
removeTimerById(id) { | |
// Skip if no ID provided | |
if (!id) return; | |
// Remove from activeTimers array | |
const timerIndex = this.activeTimers.findIndex(t => t.id === id); | |
if (timerIndex >= 0) { | |
this.activeTimers.splice(timerIndex, 1); | |
} | |
// Find all containers that might reference this timer and reset them | |
// This is a more thorough approach than tracking a single container | |
document.querySelectorAll('[id^="timer-container-"]').forEach(container => { | |
if (container.__x && container.__x.$data.localTimer === id) { | |
container.__x.$data.localTimer = null; | |
} | |
}); | |
}, | |
// Function to properly clear a timer from both the list and the local reference | |
clearTimerAndLocal(id) { | |
this.removeTimerById(id); | |
}, | |
// Original timer functions for compatibility with the timers view at the top | |
startTimer(name, minutes) { | |
return this.startTimerForStep(name, minutes, null); | |
}, | |
formatTime(seconds) { | |
const hours = Math.floor(seconds / 3600); | |
const minutes = Math.floor((seconds % 3600) / 60); | |
const secs = seconds % 60; | |
let formattedTime = ''; | |
if (hours > 0) { | |
formattedTime += `${hours}:`; | |
formattedTime += `${minutes.toString().padStart(2, '0')}:`; | |
} else { | |
formattedTime += `${minutes}:`; | |
} | |
formattedTime += secs.toString().padStart(2, '0'); | |
return formattedTime; | |
}, | |
// Print only the recipe parts and hide the form | |
printRecipe() { | |
window.print(); | |
}, | |
// Save current configuration to local storage | |
saveConfiguration() { | |
if (!this.saveConfigName.trim()) { | |
alert('Please enter a name for your configuration.'); | |
return; | |
} | |
const config = { | |
name: this.saveConfigName, | |
settings: { | |
pizzaSize: this.pizzaSize, | |
pizzaQuantity: this.pizzaQuantity, | |
pizzaThickness: this.pizzaThickness, | |
unitSystem: this.unitSystem, | |
hydrationPercentage: this.hydrationPercentage, | |
doughMethod: this.doughMethod, | |
prefermentPercentage: this.prefermentPercentage, | |
starterPercentage: this.starterPercentage | |
} | |
}; | |
this.savedConfigs.push(config); | |
this.saveSavedConfigs(); | |
this.saveConfigName = ''; | |
}, | |
// Load configuration from saved configs | |
loadConfiguration(config) { | |
const settings = config.settings; | |
this.pizzaSize = settings.pizzaSize; | |
this.pizzaQuantity = settings.pizzaQuantity; | |
this.pizzaThickness = settings.pizzaThickness; | |
this.unitSystem = settings.unitSystem; | |
this.hydrationPercentage = settings.hydrationPercentage; | |
this.doughMethod = settings.doughMethod; | |
this.prefermentPercentage = settings.prefermentPercentage; | |
this.starterPercentage = settings.starterPercentage; | |
}, | |
// Delete a saved configuration | |
deleteConfiguration(index) { | |
if (confirm('Are you sure you want to delete this configuration?')) { | |
this.savedConfigs.splice(index, 1); | |
this.saveSavedConfigs(); | |
} | |
}, | |
// Save configs to local storage | |
saveSavedConfigs() { | |
localStorage.setItem('pizzaCalculatorConfigs', JSON.stringify(this.savedConfigs)); | |
}, | |
// Load configs from local storage | |
loadSavedConfigs() { | |
const savedConfigs = localStorage.getItem('pizzaCalculatorConfigs'); | |
if (savedConfigs) { | |
this.savedConfigs = JSON.parse(savedConfigs); | |
} | |
} | |
}; | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment