Compare commits
2 Commits
db5d326fa2
...
296201eee5
| Author | SHA1 | Date | |
|---|---|---|---|
|
296201eee5
|
|||
|
b43b45dac2
|
@@ -23,7 +23,8 @@ let options = $state({
|
||||
includeIngredients: false,
|
||||
includeInstructions: false,
|
||||
showLabel: true,
|
||||
labelOverride: ''
|
||||
labelOverride: '',
|
||||
baseMultiplier: 1
|
||||
});
|
||||
|
||||
// Reset options whenever type or modal state changes
|
||||
@@ -46,6 +47,7 @@ function handleInsert() {
|
||||
selectedRecipe = null;
|
||||
options.labelOverride = '';
|
||||
options.showLabel = true;
|
||||
options.baseMultiplier = 1;
|
||||
closeModal();
|
||||
}
|
||||
}
|
||||
@@ -134,7 +136,8 @@ dialog h2 {
|
||||
}
|
||||
|
||||
.selector-content select,
|
||||
.selector-content input[type="text"] {
|
||||
.selector-content input[type="text"],
|
||||
.selector-content input[type="number"] {
|
||||
width: 100%;
|
||||
padding: 0.5em 1em;
|
||||
margin-top: 0.5em;
|
||||
@@ -149,7 +152,9 @@ dialog h2 {
|
||||
.selector-content select:hover,
|
||||
.selector-content select:focus,
|
||||
.selector-content input[type="text"]:hover,
|
||||
.selector-content input[type="text"]:focus {
|
||||
.selector-content input[type="text"]:focus,
|
||||
.selector-content input[type="number"]:hover,
|
||||
.selector-content input[type="number"]:focus {
|
||||
border-color: var(--nord9);
|
||||
transform: scale(1.02, 1.02);
|
||||
}
|
||||
@@ -245,6 +250,18 @@ dialog h2 {
|
||||
</label>
|
||||
{/if}
|
||||
|
||||
<label>
|
||||
Mengenfaktor (Multiplikator):
|
||||
<input
|
||||
type="number"
|
||||
bind:value={options.baseMultiplier}
|
||||
min="0.1"
|
||||
step="0.1"
|
||||
placeholder="1"
|
||||
onkeydown={(event) => do_on_key(event, 'Enter', false, handleInsert)}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<div class="button-group">
|
||||
<button class="button-insert" onclick={handleInsert} disabled={!selectedRecipe}>
|
||||
Einfügen
|
||||
|
||||
@@ -128,6 +128,7 @@ function handleSelect(recipe: any, options: any) {
|
||||
includeIngredients: options.includeIngredients,
|
||||
showLabel: options.showLabel,
|
||||
labelOverride: options.labelOverride || '',
|
||||
baseMultiplier: options.baseMultiplier || 1,
|
||||
itemsBefore: [],
|
||||
itemsAfter: []
|
||||
};
|
||||
@@ -746,6 +747,18 @@ h3{
|
||||
</div>
|
||||
<div class="reference-badge">
|
||||
📋 {t[lang].baseRecipe}: {list.name || t[lang].unnamed}
|
||||
<div style="margin-top: 0.5em;">
|
||||
<label style="font-size: 0.9em; display: flex; align-items: center; gap: 0.5em;">
|
||||
{t[lang].baseMultiplier || 'Mengenfaktor'}:
|
||||
<input
|
||||
type="number"
|
||||
bind:value={list.baseMultiplier}
|
||||
min="0.1"
|
||||
step="0.1"
|
||||
style="width: 5em; padding: 0.25em 0.5em; border-radius: 5px; border: 1px solid var(--nord4);"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mod_icons">
|
||||
<button type="button" class="action_button button_subtle" onclick={() => removeReference(list_index)} aria-label={t[lang].removeReferenceAria}>
|
||||
|
||||
@@ -125,6 +125,7 @@ function handleSelect(recipe: any, options: any) {
|
||||
includeInstructions: options.includeInstructions,
|
||||
showLabel: options.showLabel,
|
||||
labelOverride: options.labelOverride || '',
|
||||
baseMultiplier: options.baseMultiplier || 1,
|
||||
stepsBefore: [],
|
||||
stepsAfter: []
|
||||
};
|
||||
@@ -246,7 +247,8 @@ export function add_new_step(){
|
||||
instructions[list_index].steps.push(new_step.step)
|
||||
}
|
||||
const el = document.querySelector("#step")
|
||||
el.innerHTML = step_placeholder
|
||||
el.innerHTML = ""
|
||||
new_step.step = ""
|
||||
instructions = instructions //tells svelte to update dom
|
||||
}
|
||||
|
||||
@@ -797,6 +799,18 @@ h3{
|
||||
</div>
|
||||
<div class="reference-badge">
|
||||
📋 {t[lang].baseRecipe}: {list.name || t[lang].unnamed}
|
||||
<div style="margin-top: 0.5em;">
|
||||
<label style="font-size: 0.9em; display: flex; align-items: center; gap: 0.5em;">
|
||||
{t[lang].baseMultiplier || 'Mengenfaktor'}:
|
||||
<input
|
||||
type="number"
|
||||
bind:value={list.baseMultiplier}
|
||||
min="0.1"
|
||||
step="0.1"
|
||||
style="width: 5em; padding: 0.25em 0.5em; border-radius: 5px; border: 1px solid var(--nord4);"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mod_icons">
|
||||
<button type="button" class="action_button button_subtle" onclick={() => removeReference(list_index)} aria-label={t[lang].removeReferenceAria}>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
let { note = $bindable("") } = $props<{ note?: string }>();
|
||||
</script>
|
||||
<style>
|
||||
div{
|
||||
@@ -14,9 +15,25 @@ div{
|
||||
h3{
|
||||
margin-block: 0;
|
||||
}
|
||||
textarea {
|
||||
width: 100%;
|
||||
min-height: 80px;
|
||||
padding: 0.5em;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
color: white;
|
||||
font-size: 1rem;
|
||||
resize: vertical;
|
||||
margin-top: 0.5em;
|
||||
font-family: sans-serif;
|
||||
background-color: transparent;
|
||||
}
|
||||
textarea::placeholder {
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div>
|
||||
<h3>Notiz:</h3>
|
||||
<slot></slot>
|
||||
<textarea bind:value={note} placeholder="Füge eine Notiz für dieses Rezept hinzu..."></textarea>
|
||||
</div>
|
||||
|
||||
@@ -7,8 +7,20 @@ import HefeSwapper from './HefeSwapper.svelte';
|
||||
|
||||
let { data } = $props();
|
||||
|
||||
// Helper function to multiply numbers in ingredient amounts
|
||||
function multiplyIngredientAmount(amount, multiplier) {
|
||||
if (!amount || multiplier === 1) return amount;
|
||||
return amount.replace(/(\d+(?:[\.,]\d+)?)/g, match => {
|
||||
const number = match.includes(',') ? match.replace(/\./g, '').replace(',', '.') : match;
|
||||
const multiplied = (parseFloat(number) * multiplier).toString();
|
||||
const rounded = parseFloat(multiplied).toFixed(3);
|
||||
const trimmed = parseFloat(rounded).toString();
|
||||
return match.includes(',') ? trimmed.replace('.', ',') : trimmed;
|
||||
});
|
||||
}
|
||||
|
||||
// Recursively flatten nested ingredient references
|
||||
function flattenIngredientReferences(items, lang, visited = new Set()) {
|
||||
function flattenIngredientReferences(items, lang, visited = new Set(), baseMultiplier = 1) {
|
||||
const result = [];
|
||||
|
||||
for (const item of items) {
|
||||
@@ -29,18 +41,22 @@ function flattenIngredientReferences(items, lang, visited = new Set()) {
|
||||
? item.resolvedRecipe.translations.en.ingredients
|
||||
: item.resolvedRecipe.ingredients || [];
|
||||
|
||||
// Recursively flatten nested references
|
||||
const flattenedNested = flattenIngredientReferences(ingredientsToUse, lang, newVisited);
|
||||
// Calculate combined multiplier for this reference
|
||||
const itemBaseMultiplier = item.baseMultiplier || 1;
|
||||
const combinedMultiplier = baseMultiplier * itemBaseMultiplier;
|
||||
|
||||
// Recursively flatten nested references with the combined multiplier
|
||||
const flattenedNested = flattenIngredientReferences(ingredientsToUse, lang, newVisited, combinedMultiplier);
|
||||
|
||||
// Combine all items into one list
|
||||
const combinedList = [];
|
||||
|
||||
// Add items before
|
||||
// Add items before (not affected by baseMultiplier)
|
||||
if (item.itemsBefore && item.itemsBefore.length > 0) {
|
||||
combinedList.push(...item.itemsBefore);
|
||||
}
|
||||
|
||||
// Add base recipe ingredients (now recursively flattened)
|
||||
// Add base recipe ingredients (now recursively flattened with multiplier applied)
|
||||
if (item.includeIngredients) {
|
||||
flattenedNested.forEach(section => {
|
||||
if (section.list) {
|
||||
@@ -49,7 +65,7 @@ function flattenIngredientReferences(items, lang, visited = new Set()) {
|
||||
});
|
||||
}
|
||||
|
||||
// Add items after
|
||||
// Add items after (not affected by baseMultiplier)
|
||||
if (item.itemsAfter && item.itemsAfter.length > 0) {
|
||||
combinedList.push(...item.itemsAfter);
|
||||
}
|
||||
@@ -69,12 +85,24 @@ function flattenIngredientReferences(items, lang, visited = new Set()) {
|
||||
name: item.showLabel ? (item.labelOverride || baseRecipeName) : '',
|
||||
list: combinedList,
|
||||
isReference: item.showLabel,
|
||||
short_name: baseRecipeShortName
|
||||
short_name: baseRecipeShortName,
|
||||
baseMultiplier: itemBaseMultiplier
|
||||
});
|
||||
}
|
||||
} else if (item.type === 'section' || !item.type) {
|
||||
// Regular section - pass through
|
||||
result.push(item);
|
||||
// Regular section - pass through with multiplier applied to amounts
|
||||
if (baseMultiplier !== 1 && item.list) {
|
||||
const adjustedList = item.list.map(ingredient => ({
|
||||
...ingredient,
|
||||
amount: multiplyIngredientAmount(ingredient.amount, baseMultiplier)
|
||||
}));
|
||||
result.push({
|
||||
...item,
|
||||
list: adjustedList
|
||||
});
|
||||
} else {
|
||||
result.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -488,7 +516,7 @@ h3 a:hover {
|
||||
{#each flattenedIngredients as list, listIndex}
|
||||
{#if list.name}
|
||||
{#if list.isReference}
|
||||
<h3><a href="{list.short_name}?multiplier={multiplier}">{@html list.name}</a></h3>
|
||||
<h3><a href="{list.short_name}?multiplier={multiplier * (list.baseMultiplier || 1)}">{@html list.name}</a></h3>
|
||||
{:else}
|
||||
<h3>{@html list.name}</h3>
|
||||
{/if}
|
||||
|
||||
@@ -60,12 +60,15 @@ function flattenInstructionReferences(items, lang, visited = new Set()) {
|
||||
? item.resolvedRecipe.translations.en.short_name
|
||||
: item.resolvedRecipe.short_name;
|
||||
|
||||
const itemBaseMultiplier = item.baseMultiplier || 1;
|
||||
|
||||
result.push({
|
||||
type: 'section',
|
||||
name: item.showLabel ? (item.labelOverride || baseRecipeName) : '',
|
||||
steps: combinedSteps,
|
||||
isReference: item.showLabel,
|
||||
short_name: baseRecipeShortName
|
||||
short_name: baseRecipeShortName,
|
||||
baseMultiplier: itemBaseMultiplier
|
||||
});
|
||||
}
|
||||
} else if (item.type === 'section' || !item.type) {
|
||||
@@ -211,7 +214,7 @@ h3 a:hover {
|
||||
{#each flattenedInstructions as list}
|
||||
{#if list.name}
|
||||
{#if list.isReference}
|
||||
<h3><a href="{list.short_name}?multiplier={multiplier}">{@html list.name}</a></h3>
|
||||
<h3><a href="{list.short_name}?multiplier={multiplier * (list.baseMultiplier || 1)}">{@html list.name}</a></h3>
|
||||
{:else}
|
||||
<h3>{@html list.name}</h3>
|
||||
{/if}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<style>
|
||||
.toggle-wrapper {
|
||||
display: flex;
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.toggle-wrapper label {
|
||||
|
||||
@@ -46,6 +46,7 @@ const RecipeSchema = new mongoose.Schema(
|
||||
includeIngredients: { type: Boolean, default: true },
|
||||
showLabel: { type: Boolean, default: true },
|
||||
labelOverride: { type: String, default: "" },
|
||||
baseMultiplier: { type: Number, default: 1 },
|
||||
itemsBefore: [{
|
||||
name: { type: String, default: "" },
|
||||
unit: String,
|
||||
@@ -70,6 +71,7 @@ const RecipeSchema = new mongoose.Schema(
|
||||
includeInstructions: { type: Boolean, default: true },
|
||||
showLabel: { type: Boolean, default: true },
|
||||
labelOverride: { type: String, default: "" },
|
||||
baseMultiplier: { type: Number, default: 1 },
|
||||
stepsBefore: [String],
|
||||
stepsAfter: [String],
|
||||
}],
|
||||
@@ -115,6 +117,7 @@ const RecipeSchema = new mongoose.Schema(
|
||||
includeIngredients: { type: Boolean, default: true },
|
||||
showLabel: { type: Boolean, default: true },
|
||||
labelOverride: { type: String, default: "" },
|
||||
baseMultiplier: { type: Number, default: 1 },
|
||||
itemsBefore: [{
|
||||
name: { type: String, default: "" },
|
||||
unit: String,
|
||||
@@ -134,6 +137,7 @@ const RecipeSchema = new mongoose.Schema(
|
||||
includeInstructions: { type: Boolean, default: true },
|
||||
showLabel: { type: Boolean, default: true },
|
||||
labelOverride: { type: String, default: "" },
|
||||
baseMultiplier: { type: Number, default: 1 },
|
||||
stepsBefore: [String],
|
||||
stepsAfter: [String],
|
||||
}],
|
||||
|
||||
@@ -25,6 +25,7 @@ export type IngredientReference = {
|
||||
includeIngredients: boolean;
|
||||
showLabel: boolean;
|
||||
labelOverride?: string;
|
||||
baseMultiplier?: number;
|
||||
itemsBefore?: [{
|
||||
name: string;
|
||||
unit: string;
|
||||
@@ -61,6 +62,7 @@ export type InstructionReference = {
|
||||
includeInstructions: boolean;
|
||||
showLabel: boolean;
|
||||
labelOverride?: string;
|
||||
baseMultiplier?: number;
|
||||
stepsBefore?: [string];
|
||||
stepsAfter?: [string];
|
||||
// Populated after server-side resolution
|
||||
|
||||
Reference in New Issue
Block a user