/** * Skateboard emoji rating system for SkateSpots * Uses 🛹 emojis instead of stars, from 1 to 10 */ /** * Generate skateboard rating display (1-10 skateboards based on count) * @param count - The count to convert to a rating (sales, reviews, etc.) * @param maxDisplay - Maximum skateboards to display (default 10) * @returns Object with emoji string and numeric rating */ export function getSkateboardRating(count: number, maxDisplay = 10): { rating: number; display: string; label: string; } { // Scale: 1-10 based on count thresholds let rating: number; let label: string; if (count === 0) { rating = 0; label = 'New'; } else if (count === 1) { rating = 1; label = 'Just starting'; } else if (count <= 3) { rating = 2; label = 'Getting known'; } else if (count <= 5) { rating = 3; label = 'Building rep'; } else if (count <= 8) { rating = 4; label = 'Solid'; } else if (count <= 12) { rating = 5; label = 'Reliable'; } else if (count <= 18) { rating = 6; label = 'Well known'; } else if (count <= 25) { rating = 7; label = 'Established'; } else if (count <= 35) { rating = 8; label = 'Trusted'; } else if (count <= 50) { rating = 9; label = 'Pro seller'; } else { rating = 10; label = 'Legendary'; } // Clamp to max display const displayRating = Math.min(rating, maxDisplay); const display = '🛹'.repeat(displayRating); return { rating, display, label }; } /** * Get skateboard rating for skate spots (based on reviews/ratings) * @param reviewCount - Number of reviews * @param averageRating - Average rating (1-5 scale typically) * @returns Object with emoji string and numeric rating */ export function getSpotSkateboardRating(reviewCount: number, averageRating: number = 0): { rating: number; display: string; label: string; } { // Combine review count and average rating for final score // Weight: 60% average rating, 40% review count factor let rating: number; let label: string; if (reviewCount === 0) { rating = 0; label = 'No reviews'; } else { // Scale average rating (1-5) to (2-10) const ratingScore = ((averageRating - 1) / 4) * 8 + 2; // Review count bonus (up to +2 for 20+ reviews) const countBonus = Math.min(reviewCount / 10, 2); rating = Math.round(Math.min(ratingScore + countBonus, 10)); if (rating <= 2) label = 'Sketchy'; else if (rating <= 4) label = 'Decent'; else if (rating <= 6) label = 'Solid spot'; else if (rating <= 8) label = 'Classic'; else label = 'Legendary'; } const display = rating > 0 ? '🛹'.repeat(rating) : ''; return { rating, display, label }; } /** * Compact display for tight spaces (shows count + single emoji) */ export function getCompactRating(count: number): string { if (count === 0) return '🛹 0'; return `🛹 ${count}`; } /** * Trust badge configurations matching the skateboard theme */ export const SELLER_TRUST_BADGES = { verified: { emoji: '✅', label: 'Verified', description: 'You follow them directly', className: 'border-green-500/50 text-green-400 bg-green-500/10' }, trusted: { emoji: '🛡️', label: 'Trusted', description: 'Friend-of-friend or NIP-05', className: 'border-blue-500/50 text-blue-400 bg-blue-500/10' }, new: { emoji: '⚠️', label: 'New', description: 'No trust signals yet', className: 'border-yellow-500/50 text-yellow-400 bg-yellow-500/10' }, } as const; export type TrustLevel = keyof typeof SELLER_TRUST_BADGES; /** * Get trust level from trust score */ export function getTrustLevel(trustScore: number | undefined): TrustLevel { if (trustScore === undefined || trustScore < 50) return 'new'; if (trustScore >= 90) return 'verified'; return 'trusted'; }