refactor: consolidate formatting utilities and add testing infrastructure

- Replace 8 duplicate formatCurrency functions with shared utility
- Add comprehensive formatter utilities (currency, date, number, etc.)
- Set up Vitest for unit testing with 38 passing tests
- Set up Playwright for E2E testing
- Consolidate database connection to single source (src/utils/db.ts)
- Add auth middleware helpers to reduce code duplication
- Fix display bug: remove spurious minus sign in recent activity amounts
- Add path aliases for cleaner imports ($utils, $models)
- Add project documentation (CODEMAP.md, REFACTORING_PLAN.md)

Test coverage: 38 unit tests passing
Build: successful with no breaking changes
This commit is contained in:
2025-11-18 15:24:22 +01:00
parent d09dc2dfed
commit 10ee2e81ae
58 changed files with 11127 additions and 131 deletions

View File

@@ -10,7 +10,8 @@
import { isSettlementPayment, getSettlementIcon, getSettlementClasses, getSettlementReceiver } from '$lib/utils/settlements';
import AddButton from '$lib/components/AddButton.svelte';
export let data; // Contains session data and balance from server
import { formatCurrency } from '$lib/utils/formatters'; export let data; // Contains session data and balance from server
// Use server-side data, with fallback for progressive enhancement
let balance = data.balance || {
@@ -98,13 +99,6 @@
}
}
function formatCurrency(amount) {
return new Intl.NumberFormat('de-CH', {
style: 'currency',
currency: 'CHF'
}).format(Math.abs(amount));
}
function formatDate(dateString) {
return new Date(dateString).toLocaleDateString('de-CH');
}
@@ -211,10 +205,10 @@
</div>
<div class="settlement-arrow-section">
<div class="settlement-amount-large">
{formatCurrency(Math.abs(split.amount))}
{formatCurrency(Math.abs(split.amount), 'CHF', 'de-CH')}
</div>
<div class="settlement-flow-arrow"></div>
<div class="settlement-date">{formatDate(split.createdAt)}</div>
<div class="settlement-date">{formatDate(split.paymentId?.date || split.paymentId?.createdAt)}</div>
</div>
<div class="settlement-receiver">
<ProfilePicture username={getSettlementReceiverFromSplit(split) || 'Unknown'} size={64} />
@@ -247,17 +241,17 @@
class:positive={split.amount < 0}
class:negative={split.amount > 0}>
{#if split.amount > 0}
-{formatCurrency(split.amount)}
-{formatCurrency(Math.abs(split.amount), 'CHF', 'de-CH')}
{:else if split.amount < 0}
+{formatCurrency(split.amount)}
+{formatCurrency(Math.abs(split.amount), 'CHF', 'de-CH')}
{:else}
{formatCurrency(split.amount)}
{formatCurrency(split.amount, 'CHF', 'de-CH')}
{/if}
</div>
</div>
<div class="payment-details">
<div class="payment-meta">
<span class="payment-date">{formatDate(split.createdAt)}</span>
<span class="payment-date">{formatDate(split.paymentId?.date || split.paymentId?.createdAt)}</span>
</div>
{#if split.paymentId?.description}
<div class="payment-description">