diff --git a/src/components/events/PurchaseTicketDialog.vue b/src/components/events/PurchaseTicketDialog.vue index eec3f03..2ec7657 100644 --- a/src/components/events/PurchaseTicketDialog.vue +++ b/src/components/events/PurchaseTicketDialog.vue @@ -7,6 +7,7 @@ import { Badge } from '@/components/ui/badge' import { useTicketPurchase } from '@/composables/useTicketPurchase' import { useAuth } from '@/composables/useAuth' import { User, Wallet, CreditCard, Zap, Ticket } from 'lucide-vue-next' +import { formatEventPrice, formatWalletBalance } from '@/lib/utils/formatting' interface Props { event: { @@ -76,7 +77,7 @@ onUnmounted(() => { Purchase Ticket - Purchase a ticket for {{ event.name }} for {{ event.price_per_ticket }} {{ event.currency }} + Purchase a ticket for {{ event.name }} for {{ formatEventPrice(event.price_per_ticket, event.currency) }} @@ -130,7 +131,7 @@ onUnmounted(() => {
{{ wallet.name }} - {{ (wallet.balance_msat / 1000).toFixed(0) }} sats + {{ formatWalletBalance(wallet.balance_msat) }} Empty
@@ -158,7 +159,7 @@ onUnmounted(() => {
Price: - {{ event.price_per_ticket }} {{ event.currency }} + {{ formatEventPrice(event.price_per_ticket, event.currency) }}
diff --git a/src/lib/utils/formatting.test.ts b/src/lib/utils/formatting.test.ts new file mode 100644 index 0000000..bc9a849 --- /dev/null +++ b/src/lib/utils/formatting.test.ts @@ -0,0 +1,201 @@ +/** + * Test file for formatting utility functions + * This file can be run with a test runner or used for manual verification + */ + +import { + formatNumber, + formatSats, + formatMsats, + formatCurrency, + formatEventPrice, + formatWalletBalance +} from './formatting' + +// Test data +const testNumbers = [ + 0, + 1, + 999, + 1000, + 1001, + 9999, + 10000, + 10001, + 99999, + 100000, + 100001, + 999999, + 1000000, + 1000001, + 1234567, + 9999999, + 10000000 +] + +const testSats = [ + 0, + 1, + 999, + 1000, + 1001, + 9999, + 10000, + 10001, + 99999, + 100000, + 100001, + 999999, + 1000000, + 1000001, + 1234567, + 9999999, + 10000000 +] + +const testMsats = [ + 0, + 1000, + 999000, + 1000000, + 1001000, + 9999000, + 10000000, + 10001000, + 99999000, + 100000000, + 100001000, + 999999000, + 1000000000, + 1000001000, + 1234567000, + 9999999000, + 10000000000 +] + +const testCurrencies = [ + { amount: 0, currency: 'USD' }, + { amount: 1.99, currency: 'USD' }, + { amount: 999.99, currency: 'USD' }, + { amount: 1000, currency: 'USD' }, + { amount: 1001.50, currency: 'USD' }, + { amount: 9999.99, currency: 'USD' }, + { amount: 10000, currency: 'USD' }, + { amount: 0, currency: 'EUR' }, + { amount: 1.99, currency: 'EUR' }, + { amount: 999.99, currency: 'EUR' }, + { amount: 1000, currency: 'EUR' } +] + +const testEventPrices = [ + { price: 0, currency: 'sats' }, + { price: 1, currency: 'sats' }, + { price: 999, currency: 'sats' }, + { price: 1000, currency: 'sats' }, + { price: 1001, currency: 'sats' }, + { price: 9999, currency: 'sats' }, + { price: 10000, currency: 'sats' }, + { price: 0, currency: 'USD' }, + { price: 1.99, currency: 'USD' }, + { price: 999.99, currency: 'USD' }, + { price: 1000, currency: 'USD' }, + { price: 0, currency: 'EUR' }, + { price: 1.99, currency: 'EUR' }, + { price: 999.99, currency: 'EUR' }, + { price: 1000, currency: 'EUR' } +] + +// Test functions +function testFormatNumber() { + console.log('Testing formatNumber function:') + testNumbers.forEach(num => { + const formatted = formatNumber(num) + console.log(`${num} -> "${formatted}"`) + }) + console.log('') +} + +function testFormatSats() { + console.log('Testing formatSats function:') + testSats.forEach(sats => { + const formatted = formatSats(sats) + console.log(`${sats} sats -> "${formatted}"`) + }) + console.log('') +} + +function testFormatMsats() { + console.log('Testing formatMsats function:') + testMsats.forEach(msats => { + const formatted = formatMsats(msats) + console.log(`${msats} msats -> "${formatted}"`) + }) + console.log('') +} + +function testFormatCurrency() { + console.log('Testing formatCurrency function:') + testCurrencies.forEach(({ amount, currency }) => { + const formatted = formatCurrency(amount, currency) + console.log(`${amount} ${currency} -> "${formatted}"`) + }) + console.log('') +} + +function testFormatEventPrice() { + console.log('Testing formatEventPrice function:') + testEventPrices.forEach(({ price, currency }) => { + const formatted = formatEventPrice(price, currency) + console.log(`${price} ${currency} -> "${formatted}"`) + }) + console.log('') +} + +function testFormatWalletBalance() { + console.log('Testing formatWalletBalance function:') + testMsats.forEach(msats => { + const formatted = formatWalletBalance(msats) + console.log(`${msats} msats -> "${formatted}"`) + }) + console.log('') +} + +// Run all tests +function runAllTests() { + console.log('=== FORMATTING UTILITY TESTS ===\n') + + testFormatNumber() + testFormatSats() + testFormatMsats() + testFormatCurrency() + testFormatEventPrice() + testFormatWalletBalance() + + console.log('=== TESTS COMPLETED ===') +} + +// Export for manual testing +export { + runAllTests, + testFormatNumber, + testFormatSats, + testFormatMsats, + testFormatCurrency, + testFormatEventPrice, + testFormatWalletBalance +} + +// Run tests if this file is executed directly +if (typeof window !== 'undefined') { + // Browser environment - add to window for console testing + (window as any).formattingTests = { + runAllTests, + testFormatNumber, + testFormatSats, + testFormatMsats, + testFormatCurrency, + testFormatEventPrice, + testFormatWalletBalance + } + console.log('Formatting tests available at window.formattingTests') +} diff --git a/src/lib/utils/formatting.ts b/src/lib/utils/formatting.ts new file mode 100644 index 0000000..a61b999 --- /dev/null +++ b/src/lib/utils/formatting.ts @@ -0,0 +1,80 @@ +/** + * Formatting utility functions for amounts and currencies + */ + +/** + * Format a number with thousand separators + * @param value - The number to format + * @param locale - The locale to use for formatting (default: 'en-US') + * @returns Formatted string with thousand separators + */ +export function formatNumber(value: number, locale: string = 'en-US'): string { + return new Intl.NumberFormat(locale).format(value) +} + +/** + * Format satoshi amounts with thousand separators + * @param sats - The satoshi amount + * @param locale - The locale to use for formatting (default: 'en-US') + * @returns Formatted string with "sats" suffix + */ +export function formatSats(sats: number, locale: string = 'en-US'): string { + return `${formatNumber(sats, locale)} sats` +} + +/** + * Format millisatoshi amounts with thousand separators + * @param msats - The millisatoshi amount + * @param locale - The locale to use for formatting (default: 'en-US') + * @returns Formatted string with "sats" suffix + */ +export function formatMsats(msats: number, locale: string = 'en-US'): string { + const sats = Math.floor(msats / 1000) + return formatSats(sats, locale) +} + +/** + * Format currency amounts with thousand separators + * @param amount - The amount to format + * @param currency - The currency code (e.g., 'USD', 'EUR') + * @param locale - The locale to use for formatting (default: 'en-US') + * @returns Formatted currency string + */ +export function formatCurrency(amount: number, currency: string, locale: string = 'en-US'): string { + try { + return new Intl.NumberFormat(locale, { + style: 'currency', + currency: currency.toUpperCase() + }).format(amount) + } catch (error) { + // Fallback to basic formatting if currency is not supported + return `${formatNumber(amount, locale)} ${currency}` + } +} + +/** + * Format event ticket price with appropriate formatting + * @param price - The price amount + * @param currency - The currency code + * @param locale - The locale to use for formatting (default: 'en-US') + * @returns Formatted price string + */ +export function formatEventPrice(price: number, currency: string, locale: string = 'en-US'): string { + if (currency.toLowerCase() === 'sats' || currency.toLowerCase() === 'sat') { + return formatSats(price, locale) + } + return formatCurrency(price, currency, locale) +} + +/** + * Format wallet balance with appropriate formatting + * @param balanceMsat - The balance in millisatoshi + * @param locale - The locale to use for formatting (default: 'en-US') + * @returns Formatted balance string + */ +export function formatWalletBalance(balanceMsat: number, locale: string = 'en-US'): string { + if (balanceMsat === 0) { + return '0 sats' + } + return formatMsats(balanceMsat, locale) +} diff --git a/src/pages/events.vue b/src/pages/events.vue index e3f1182..6186ac8 100644 --- a/src/pages/events.vue +++ b/src/pages/events.vue @@ -11,6 +11,7 @@ import { Badge } from '@/components/ui/badge' import { format } from 'date-fns' import PurchaseTicketDialog from '@/components/events/PurchaseTicketDialog.vue' import { RefreshCw, User, LogIn } from 'lucide-vue-next' +import { formatEventPrice } from '@/lib/utils/formatting' const { upcomingEvents, pastEvents, isLoading, error, refresh } = useEvents() const { isAuthenticated, userDisplay } = useAuth() @@ -99,7 +100,7 @@ function handlePurchaseClick(event: {
Price: - {{ event.price_per_ticket }} {{ event.currency }} + {{ formatEventPrice(event.price_per_ticket, event.currency) }}