refactor: simplify ItemForm API using events instead of callback props
This commit is contained in:
@@ -11,16 +11,19 @@
|
||||
import { languageStore } from '$lib/stores/language.svelte';
|
||||
import ThemeCard from '$lib/components/themes/ThemeCard.svelte';
|
||||
import { getCardStyle } from '$lib/utils/colors';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
success: void;
|
||||
cancel: void;
|
||||
colorChange: { itemId: string; color: string };
|
||||
positionChange: { itemId: string; newPosition: number };
|
||||
}>();
|
||||
|
||||
interface Props {
|
||||
item?: Item | null;
|
||||
mode: 'add' | 'edit';
|
||||
onSuccess?: () => void;
|
||||
onCancel?: () => void;
|
||||
onColorChange?: (itemId: string, color: string) => void;
|
||||
currentPosition?: number;
|
||||
totalItems?: number;
|
||||
onPositionChange?: (newPosition: number) => void;
|
||||
itemCount?: number;
|
||||
wishlistColor?: string | null;
|
||||
wishlistTheme?: string | null;
|
||||
}
|
||||
@@ -28,12 +31,7 @@
|
||||
let {
|
||||
item = null,
|
||||
mode,
|
||||
onSuccess,
|
||||
onCancel,
|
||||
onColorChange,
|
||||
currentPosition = 1,
|
||||
totalItems = 1,
|
||||
onPositionChange,
|
||||
itemCount = 1,
|
||||
wishlistColor = null,
|
||||
wishlistTheme = null
|
||||
}: Props = $props();
|
||||
@@ -47,6 +45,7 @@
|
||||
let linkUrl = $state(item?.link || '');
|
||||
let imageUrl = $state(item?.imageUrl || '');
|
||||
let color = $state<string | null>(item?.color || null);
|
||||
let position = $state(item?.order ? Number(item.order) + 1 : 1);
|
||||
let scrapedImages = $state<string[]>([]);
|
||||
let isLoadingImages = $state(false);
|
||||
let debounceTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
@@ -97,7 +96,13 @@
|
||||
|
||||
function handleColorChange() {
|
||||
if (isEdit && item) {
|
||||
onColorChange?.(item.id, color || '');
|
||||
dispatch('colorChange', { itemId: item.id, color: color || '' });
|
||||
}
|
||||
}
|
||||
|
||||
function handlePositionChange() {
|
||||
if (isEdit && item) {
|
||||
dispatch('positionChange', { itemId: item.id, newPosition: position });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +126,7 @@
|
||||
use:enhance={() => {
|
||||
return async ({ update }) => {
|
||||
await update({ reset: false });
|
||||
onSuccess?.();
|
||||
dispatch('success');
|
||||
};
|
||||
}}
|
||||
class="space-y-4"
|
||||
@@ -222,20 +227,16 @@
|
||||
<Label for="position">{t.form.position}</Label>
|
||||
<Input
|
||||
id="position"
|
||||
name="position"
|
||||
type="number"
|
||||
min="1"
|
||||
max={totalItems}
|
||||
value={currentPosition}
|
||||
onchange={(e) => {
|
||||
const newPos = parseInt((e.target as HTMLInputElement).value);
|
||||
if (newPos >= 1 && newPos <= totalItems) {
|
||||
onPositionChange?.(newPos);
|
||||
}
|
||||
}}
|
||||
max={itemCount}
|
||||
bind:value={position}
|
||||
onchange={handlePositionChange}
|
||||
placeholder="1"
|
||||
/>
|
||||
<p class="text-sm text-muted-foreground">
|
||||
Choose where this item appears in your wishlist (1 = top, {totalItems} = bottom)
|
||||
Choose where this item appears in your wishlist (1 = top, {itemCount} = bottom)
|
||||
</p>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -243,8 +244,8 @@
|
||||
|
||||
<div class="flex gap-2">
|
||||
<Button type="submit" class="flex-1 md:flex-none">{submitLabel}</Button>
|
||||
{#if onCancel}
|
||||
<Button type="button" variant="outline" class="flex-1 md:flex-none" onclick={onCancel}>
|
||||
{#if isEdit}
|
||||
<Button type="button" variant="outline" class="flex-1 md:flex-none" onclick={() => dispatch('cancel')}>
|
||||
{t.form.cancel}
|
||||
</Button>
|
||||
{/if}
|
||||
|
||||
@@ -88,10 +88,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function handlePositionChange(newPosition: number) {
|
||||
if (!editingItem) return;
|
||||
|
||||
const currentIndex = items.findIndex((item) => item.id === editingItem.id);
|
||||
async function handlePositionChange(itemId: string, newPosition: number) {
|
||||
const currentIndex = items.findIndex((item) => item.id === itemId);
|
||||
if (currentIndex === -1) return;
|
||||
|
||||
const newIndex = newPosition - 1; // Convert to 0-based index
|
||||
@@ -150,7 +148,7 @@
|
||||
<div bind:this={addFormElement}>
|
||||
<ItemForm
|
||||
mode="add"
|
||||
onSuccess={handleItemAdded}
|
||||
on:success={handleItemAdded}
|
||||
wishlistColor={currentColor}
|
||||
wishlistTheme={currentTheme}
|
||||
/>
|
||||
@@ -162,12 +160,11 @@
|
||||
<ItemForm
|
||||
mode="edit"
|
||||
item={editingItem}
|
||||
onSuccess={handleItemUpdated}
|
||||
onCancel={cancelEditing}
|
||||
onColorChange={handleColorChange}
|
||||
currentPosition={items.findIndex((item) => item.id === editingItem.id) + 1}
|
||||
totalItems={items.length}
|
||||
onPositionChange={handlePositionChange}
|
||||
itemCount={items.length}
|
||||
on:success={handleItemUpdated}
|
||||
on:cancel={cancelEditing}
|
||||
on:colorChange={(e) => handleColorChange(e.detail.itemId, e.detail.color)}
|
||||
on:positionChange={(e) => handlePositionChange(e.detail.itemId, e.detail.newPosition)}
|
||||
wishlistColor={currentColor}
|
||||
wishlistTheme={currentTheme}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user