import { type ClassValue, clsx } from "clsx" import { twMerge } from "tailwind-merge" export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } // Format currency with symbol export function formatCurrency(amount: number, currencyCode: string, symbol: string): string { return `${symbol}${amount.toFixed(2)} ${currencyCode}` } // Format date for display export function formatDate(dateString: string): string { const date = new Date(dateString) return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric', }) } // Format time for display export function formatTime(dateString: string): string { const date = new Date(dateString) return date.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', }) } // Generate share code export function generateShareCode(): string { const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' let result = '' for (let i = 0; i < 6; i++) { result += characters.charAt(Math.floor(Math.random() * characters.length)) } return result } // Validate share code format export function isValidShareCode(code: string): boolean { return /^[A-Z0-9]{6}$/.test(code.toUpperCase()) } // Calculate percentage splits export function calculateSplits(amount: number, splits: { participant_id: number; percentage: number }[]) { const totalPercentage = splits.reduce((sum, split) => sum + split.percentage, 0) if (Math.abs(totalPercentage - 100) > 0.01) { throw new Error('Splits must total 100%') } return splits.map(split => ({ ...split, amount: (amount * split.percentage) / 100, })) } // Calculate user's balance in a trip export function calculateUserBalance( userId: number, expenses: any[], currencyCode: string = 'USD' ): { totalOwed: number totalOwing: number netBalance: number } { let totalOwed = 0 let totalOwing = 0 expenses.forEach(expense => { // Amount user paid (others owe them) if (expense.paid_by_id === userId) { const totalPaidByOthers = expense.splits .filter(split => split.participant_id !== userId) .reduce((sum, split) => sum + split.amount, 0) totalOwed += totalPaidByOthers } // Amount user owes const userSplit = expense.splits.find(split => split.participant_id === userId) if (userSplit && !userSplit.is_settled) { totalOwing += userSplit.amount } }) return { totalOwed, totalOwing, netBalance: totalOwed - totalOwing, } } // Generate device fingerprint (privacy-conscious version) export function generateDeviceFingerprint(): string { const navigator = window.navigator const screen = window.screen // Only collect non-sensitive, user-resettable information const fingerprint = [ navigator.userAgent, navigator.language, screen.colorDepth, screen.width + 'x' + screen.height, new Date().getTimezoneOffset(), ].join('|') // Create a hash of the fingerprint return btoa(fingerprint).replace(/[^a-zA-Z0-9]/g, '').substr(0, 16) }