// Wallet Component for Trust Economy class Wallet { static init() { console.log('Wallet component initialized'); this.setupWalletInterface(); this.loadWalletData(); this.setupRealTimeUpdates(); } static setupWalletInterface() { // Setup wallet interaction handlers const walletButtons = document.querySelectorAll('[data-wallet-action]'); walletButtons.forEach(button => { button.addEventListener('click', (e) => { const action = e.target.dataset.walletAction; this.handleWalletAction(action); }); }); } static handleWalletAction(action) { switch (action) { case 'view-transactions': this.showTransactionHistory(); break; case 'withdraw': this.showWithdrawModal(); break; case 'add-payment-method': this.showPaymentMethodModal(); break; default: console.log('Unknown wallet action:', action); } } static async processReferralReward(qrId, conversionData) { try { // Calculate reward based on conversion value and recommender trust const baseReward = this.calculateBaseReward(conversionData.salePrice); const trustMultiplier = this.getTrustMultiplier(conversionData.recommenderTrust); const wageBonus = this.getWageTransparencyBonus(conversionData.merchantId); const totalReward = baseReward * trustMultiplier * wageBonus; const reward = { id: this.generateTransactionId(), type: 'referral_reward', amount: totalReward, currency: 'USD', status: 'pending_maturation', qrId, conversionId: conversionData.id, recipientId: conversionData.recommenderId, metadata: { baseReward, trustMultiplier, wageBonus, salePrice: conversionData.salePrice }, createdAt: new Date().toISOString(), maturationDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString() // 7 days }; // Store pending reward this.storePendingReward(reward); return { success: true, reward }; } catch (error) { console.error('Referral reward processing failed:', error); return { success: false, error: error.message }; } } static calculateBaseReward(salePrice) { // Base reward calculation: 5-10% of sale price const rate = Math.max(0.05, Math.min(0.10, salePrice / 1000)); return salePrice * rate; } static getTrustMultiplier(trustLevel) { // Trust level affects reward multiplier const multipliers = { 'low': 0.8, 'medium': 1.0, 'high': 1.2, 'verified': 1.5 }; return multipliers[trustLevel] || 1.0; } static getWageTransparencyBonus(merchantId) { // Bonus for supporting wage-transparent merchants // In real implementation, this would check merchant's wage transparency score const wageTransparent = this.isWageTransparent(merchantId); return wageTransparent ? 1.02 : 1.0; // 2% bonus } static isWageTransparent(merchantId) { // Check if merchant meets wage transparency requirements const transparentMerchants = JSON.parse(localStorage.getItem('wageTransparentMerchants') || '[]'); return transparentMerchants.includes(merchantId); } static async processReviewBonus(reviewId, bonusAmount) { const review = this.getReviewById(reviewId); if (!review) { throw new Error('Review not found'); } // Check if review meets bonus criteria if (!this.isReviewBonusEligible(review)) { throw new Error('Review not eligible for bonus'); } const bonus = { id: this.generateTransactionId(), type: 'review_bonus', amount: bonusAmount, currency: 'USD', status: 'completed', reviewId, recipientId: review.userId, metadata: { reviewRating: review.rating, dimensions: review.dimensions, maturityDays: this.getDaysSinceReview(review.createdAt) }, createdAt: new Date().toISOString() }; this.addToWallet(review.userId, bonus.amount); this.storeTransaction(bonus); return { success: true, bonus }; } static isReviewBonusEligible(review) { const maturityDays = this.getDaysSinceReview(review.createdAt); const hasMinimumRating = review.rating >= 4; const hasDetailedContent = review.content && review.content.length >= 100; const hasAllDimensions = Object.keys(review.dimensions || {}).length >= 3; return maturityDays >= 14 && hasMinimumRating && hasDetailedContent && hasAllDimensions; } static getDaysSinceReview(createdAt) { return Math.floor((new Date() - new Date(createdAt)) / (1000 * 60 * 60 * 24)); } static async processDisputeRefund(disputeData) { // Handle refund processing due to disputes const refund = { id: this.generateTransactionId(), type: 'dispute_refund', amount: -Math.abs(disputeData.refundAmount), currency: 'USD', status: 'completed', originalTransactionId: disputeData.originalTxId, recipientId: disputeData.userId, metadata: { disputeReason: disputeData.reason, resolvedAt: new Date().toISOString(), merchantId: disputeData.merchantId }, createdAt: new Date().toISOString() }; // Subtract from merchant payout if applicable if (disputeData.merchantId) { await this.adjustMerchantPayout(disputeData.merchantId, refund.amount); } // Add back to user wallet this.addToWallet(disputeData.userId, Math.abs(refund.amount)); this.storeTransaction(refund); // Trigger score recalculation due to refund this.triggerScoreRecalculation(disputeData.productId); return { success: true, refund }; } static async adjustMerchantPayout(merchantId, adjustmentAmount) { // Adjust merchant payout for refunds/disputes const merchantPayouts = JSON.parse(localStorage.getItem(`merchantPayouts_${merchantId}`) || '[]'); const adjustment = { id: this.generateTransactionId(), type: 'payout_adjustment', amount: adjustmentAmount, currency: 'USD', status: 'pending', merchantId, reason: 'dispute_refund', createdAt: new Date().toISOString() }; merchantPayouts.push(adjustment); localStorage.setItem(`merchantPayouts_${merchantId}`, JSON.stringify(merchantPayouts)); } static addToWallet(userId, amount) { const wallets = JSON.parse(localStorage.getItem('wallets') || '{}'); if (!wallets[userId]) { wallets[userId] = { balance: 0, transactions: [], createdAt: new Date().toISOString() }; } wallets[userId].balance += amount; wallets[userId].lastUpdated = new Date().toISOString(); localStorage.setItem('wallets', JSON.stringify(wallets)); } static getWalletBalance(userId) { const wallets = JSON.parse(localStorage.getItem('wallets') || '{}'); return wallets[userId]?.balance || 0; } static storeTransaction(transaction) { const allTransactions = JSON.parse(localStorage.getItem('allTransactions') || '[]'); allTransactions.push(transaction); localStorage.setItem('allTransactions', JSON.stringify(allTransactions)); } static storePendingReward(reward) { const pendingRewards = JSON.parse(localStorage.getItem('pendingRewards') || '[]'); pendingRewards.push(reward); localStorage.setItem('pendingRewards', JSON.stringify(pendingRewards)); } static checkPendingMaturation() { const pendingRewards = JSON.parse(localStorage.getItem('pendingRewards') || '[]'); const now = new Date(); pendingRewards.forEach(reward => { if (new Date(reward.maturationDate) <= now && reward.status === 'pending_maturation') { this.matureReward(reward); } }); } static matureReward(reward) { // Move pending reward to completed wallet transaction reward.status = 'completed'; reward.maturedAt = new Date().toISOString(); this.addToWallet(reward.recipientId, reward.amount); this.storeTransaction(reward); // Update pending rewards list const pendingRewards = JSON.parse(localStorage.getItem('pendingRewards') || '[]'); const updatedRewards = pendingRewards.filter(r => r.id !== reward.id); localStorage.setItem('pendingRewards', JSON.stringify(updatedRewards)); // Notify user if (window.OneSearchApp) { window.OneSearchApp.showNotification( `Referral reward of $${reward.amount.toFixed(2)} has matured`, 'success' ); } } static loadWalletData() { const userId = window.OneSearchApp?.user?.id; if (!userId) return; // Initialize demo wallet data if not exists const wallets = JSON.parse(localStorage.getItem('wallets') || '{}'); if (!wallets[userId]) { wallets[userId] = { balance: 47.23, transactions: [ { id: 'tx_1', type: 'referral_reward', amount: 3.45, currency: 'USD', status: 'completed', description: 'Kitchen organizer purchase', createdAt: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString() }, { id: 'tx_2', type: 'review_bonus', amount: 1.20, currency: 'USD', status: 'completed', description: 'Verified product review', createdAt: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000).toISOString() } ], createdAt: new Date().toISOString() }; localStorage.setItem('wallets', JSON.stringify(wallets)); } this.updateWalletDisplay(userId); } static updateWalletDisplay(userId) { const wallets = JSON.parse(localStorage.getItem('wallets') || '{}'); const wallet = wallets[userId]; if (!wallet) return; // Update balance display const balanceElements = document.querySelectorAll('.wallet-balance'); balanceElements.forEach(el => { el.textContent = `$${wallet.balance.toFixed(2)}`; }); // Update transaction history this.updateTransactionDisplay(wallet.transactions); } static updateTransactionDisplay(transactions) { const container = document.querySelector('#wallet .space-y-3'); if (!container) return; // Clear existing transactions container.innerHTML = ''; // Add current transactions transactions.forEach(tx => { const txElement = this.createTransactionElement(tx); container.appendChild(txElement); }); } static createTransactionElement(transaction) { const element = document.createElement('div'); element.className = 'flex justify-between items-center p-3 border rounded-lg'; const typeColors = { 'referral_reward': 'text-green-600', 'review_bonus': 'text-green-600', 'dispute_refund': 'text-blue-600', 'withdrawal': 'text-red-600' }; const iconMap = { 'referral_reward': 'share-2', 'review_bonus': 'star', 'dispute_refund': 'rotate-ccw', 'withdrawal': 'arrow-up' }; const timeAgo = this.getTimeAgo(transaction.createdAt); const amountColor = transaction.amount >= 0 ? 'text-green-600' : 'text-red-600'; element.innerHTML = `