diff --git a/src/lib/components/ui/FormField.svelte b/src/lib/components/ui/FormField.svelte new file mode 100644 index 0000000..c2034b5 --- /dev/null +++ b/src/lib/components/ui/FormField.svelte @@ -0,0 +1,35 @@ + + +
+ + {#if description} +

{description}

+ {/if} + {@render children()} +
diff --git a/src/lib/components/ui/ThemedCard.svelte b/src/lib/components/ui/ThemedCard.svelte new file mode 100644 index 0000000..f8d3f79 --- /dev/null +++ b/src/lib/components/ui/ThemedCard.svelte @@ -0,0 +1,54 @@ + + + + + + {#if title} + + {title} + {#if description} + {description} + {/if} + + {/if} + + + {@render children?.()} + + diff --git a/src/lib/components/ui/select/index.ts b/src/lib/components/ui/select/index.ts new file mode 100644 index 0000000..ad93350 --- /dev/null +++ b/src/lib/components/ui/select/index.ts @@ -0,0 +1,6 @@ +import Root from './select.svelte'; + +export { + Root, + Root as Select +}; diff --git a/src/lib/components/ui/select/select.svelte b/src/lib/components/ui/select/select.svelte new file mode 100644 index 0000000..9e76716 --- /dev/null +++ b/src/lib/components/ui/select/select.svelte @@ -0,0 +1,22 @@ + + + diff --git a/src/lib/components/wishlist/ItemForm.svelte b/src/lib/components/wishlist/ItemForm.svelte index 97d11ed..4fa17bf 100644 --- a/src/lib/components/wishlist/ItemForm.svelte +++ b/src/lib/components/wishlist/ItemForm.svelte @@ -3,14 +3,14 @@ import { Input } from '$lib/components/ui/input'; import { Label } from '$lib/components/ui/label'; import { Textarea } from '$lib/components/ui/textarea'; - import { Card, CardContent, CardHeader, CardTitle } from '$lib/components/ui/card'; + import { Select } from '$lib/components/ui/select'; + import ThemedCard from '$lib/components/ui/ThemedCard.svelte'; import ImageSelector from './ImageSelector.svelte'; import ColorPicker from '$lib/components/ui/ColorPicker.svelte'; import { enhance } from '$app/forms'; import type { Item } from '$lib/db/schema'; import { languageStore } from '$lib/stores/language.svelte'; - import ThemeCard from '$lib/components/themes/ThemeCard.svelte'; - import { getCardStyle } from '$lib/utils/colors'; + import { CURRENCIES } from '$lib/utils/currency'; import { createEventDispatcher } from 'svelte'; const dispatch = createEventDispatcher<{ @@ -37,9 +37,7 @@ }: Props = $props(); const isEdit = mode === 'edit' && item !== null; - const cardStyle = $derived(getCardStyle(wishlistColor, null)); const t = $derived(languageStore.t); - const currencies = ['DKK', 'EUR', 'USD', 'SEK', 'NOK', 'GBP']; // Form state - initialized from item if editing let linkUrl = $state(item?.link || ''); @@ -114,12 +112,7 @@ }); - - - - {titleLabel} - - +
- + {#each CURRENCIES as curr (curr)} + {/each} - +
@@ -251,5 +238,4 @@ {/if}
-
-
+ diff --git a/src/lib/components/wishlist/WishlistItem.svelte b/src/lib/components/wishlist/WishlistItem.svelte index ed92c3c..c5cc0bb 100644 --- a/src/lib/components/wishlist/WishlistItem.svelte +++ b/src/lib/components/wishlist/WishlistItem.svelte @@ -1,11 +1,10 @@ - - - +
{#if showDragHandle}
-
-
+ diff --git a/src/lib/server/validation.ts b/src/lib/server/validation.ts index c7dd90a..a66c325 100644 --- a/src/lib/server/validation.ts +++ b/src/lib/server/validation.ts @@ -93,8 +93,9 @@ export function sanitizeToken(token: string | null | undefined): string { // Zod schemas for type-safe form validation import { z } from 'zod'; +import { CURRENCIES } from '$lib/utils/currency'; -export const currencySchema = z.enum(['DKK', 'EUR', 'USD', 'SEK', 'NOK', 'GBP']); +export const currencySchema = z.enum(CURRENCIES); export const itemSchema = z.object({ title: z.string().min(1, 'Title is required').max(255), diff --git a/src/lib/utils/currency.ts b/src/lib/utils/currency.ts new file mode 100644 index 0000000..65eb27c --- /dev/null +++ b/src/lib/utils/currency.ts @@ -0,0 +1,41 @@ +/** + * Currency utilities for formatting and displaying prices + */ + +export const CURRENCIES = ['DKK', 'EUR', 'USD', 'SEK', 'NOK', 'GBP'] as const; + +export type Currency = (typeof CURRENCIES)[number]; + +export const currencySymbols: Record = { + DKK: 'kr', + EUR: '€', + USD: '$', + SEK: 'kr', + NOK: 'kr', + GBP: '£' +}; + +/** + * Check if a currency symbol should be placed after the amount + */ +export function isPostfixCurrency(currency: Currency): boolean { + return ['DKK', 'SEK', 'NOK'].includes(currency); +} + +/** + * Format a price with the appropriate currency symbol + */ +export function formatPrice(price: string | number | null, currency: Currency | null): string { + if (!price) return ''; + + const symbol = currency ? currencySymbols[currency] || currency : 'kr'; + const amount = typeof price === 'string' ? parseFloat(price).toFixed(2) : price.toFixed(2); + + // For Danish, Swedish, Norwegian kroner, put symbol after the amount + if (currency && isPostfixCurrency(currency)) { + return `${amount} ${symbol}`; + } + + // For other currencies, put symbol before + return `${symbol}${amount}`; +}