feat: complete Svelte 5 migration across entire application
All checks were successful
CI / update (push) Successful in 2m8s
All checks were successful
CI / update (push) Successful in 2m8s
Migrated all components and routes from Svelte 4 to Svelte 5 syntax:
- Converted export let → $props() with generic type syntax
- Replaced createEventDispatcher → callback props
- Migrated $: reactive statements → $derived() and $effect()
- Updated two-way bindings with $bindable()
- Fixed TypeScript syntax: added lang="ts" to script tags
- Converted inline type annotations to generic parameter syntax
- Updated deprecated event directives to Svelte 5 syntax:
- on:click → onclick
- on:submit → onsubmit
- on:change → onchange
- Converted deprecated <slot> elements → {@render children()}
- Updated slot props to Snippet types
- Fixed season/icon selector components with {#snippet} blocks
- Fixed non-reactive state by converting let → $state()
- Fixed infinite loop in EnhancedBalance by converting $effect → $derived
- Fixed Chart.js integration by converting $state proxies to plain arrays
- Updated cospend dashboard and payment pages with proper reactivity
- Migrated 20+ route files from export let data → $props()
- Fixed TypeScript type annotations in page components
- Updated reactive statements in error and cospend routes
- Removed invalid onchange attribute from Toggle component
- Fixed modal ID isolation in CreateIngredientList/CreateStepList
- Fixed dark mode button visibility in TranslationApproval
- Build now succeeds with zero deprecation warnings
All functionality tested and working. No breaking changes to user experience.
This commit is contained in:
@@ -4,29 +4,35 @@ import { browser } from '$app/environment';
|
||||
import { do_on_key } from '$lib/components/do_on_key.js'
|
||||
import Check from '$lib/assets/icons/Check.svelte'
|
||||
|
||||
export let type: 'ingredients' | 'instructions' = 'ingredients';
|
||||
export let onSelect: (recipe: any, options: any) => void;
|
||||
export let open = false;
|
||||
let {
|
||||
type = 'ingredients' as 'ingredients' | 'instructions',
|
||||
onSelect,
|
||||
open = $bindable(false)
|
||||
}: {
|
||||
type?: 'ingredients' | 'instructions',
|
||||
onSelect: (recipe: any, options: any) => void,
|
||||
open?: boolean
|
||||
} = $props();
|
||||
|
||||
// Unique dialog ID based on type to prevent conflicts when both are on the same page
|
||||
const dialogId = `base-recipe-selector-modal-${type}`;
|
||||
|
||||
let baseRecipes: any[] = [];
|
||||
let selectedRecipe: any = null;
|
||||
let options = {
|
||||
let baseRecipes: any[] = $state([]);
|
||||
let selectedRecipe: any = $state(null);
|
||||
let options = $state({
|
||||
includeIngredients: false,
|
||||
includeInstructions: false,
|
||||
showLabel: true,
|
||||
labelOverride: ''
|
||||
};
|
||||
});
|
||||
|
||||
// Reset options whenever type or modal state changes
|
||||
$: {
|
||||
$effect(() => {
|
||||
if (open || type) {
|
||||
options.includeIngredients = type === 'ingredients';
|
||||
options.includeInstructions = type === 'instructions';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
onMount(async () => {
|
||||
const res = await fetch('/api/rezepte/base-recipes');
|
||||
@@ -63,13 +69,15 @@ function openModal() {
|
||||
}
|
||||
}
|
||||
|
||||
$: if (browser) {
|
||||
if (open) {
|
||||
setTimeout(openModal, 0);
|
||||
} else {
|
||||
closeModal();
|
||||
$effect(() => {
|
||||
if (browser) {
|
||||
if (open) {
|
||||
setTimeout(openModal, 0);
|
||||
} else {
|
||||
closeModal();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -232,16 +240,16 @@ dialog h2 {
|
||||
type="text"
|
||||
bind:value={options.labelOverride}
|
||||
placeholder={selectedRecipe?.name || 'Überschrift eingeben...'}
|
||||
on:keydown={(event) => do_on_key(event, 'Enter', false, handleInsert)}
|
||||
onkeydown={(event) => do_on_key(event, 'Enter', false, handleInsert)}
|
||||
/>
|
||||
</label>
|
||||
{/if}
|
||||
|
||||
<div class="button-group">
|
||||
<button class="button-insert" on:click={handleInsert} disabled={!selectedRecipe}>
|
||||
<button class="button-insert" onclick={handleInsert} disabled={!selectedRecipe}>
|
||||
Einfügen
|
||||
</button>
|
||||
<button class="button-cancel" on:click={closeModal}>
|
||||
<button class="button-cancel" onclick={closeModal}>
|
||||
Abbrechen
|
||||
</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user