open-prompt / src /lib /badges.ts
GitHub Action
Automated sync to Hugging Face
bcce530
// Imports removed as icons are now strings
interface Prompt {
id: string
totalRuns: number
starsCount: number
remixesCount: number
createdAt: Date
framework?: string | null
description?: string | null
schema?: any
}
export interface Badge {
id: string
label: string
icon: string
color: string
description: string
}
export const BADGE_DEFINITIONS: Record<string, Badge> = {
HOT: {
id: 'HOT',
label: 'Hot',
icon: 'Flame',
color: 'orange',
description: 'Trending this week',
},
VIRAL: {
id: 'VIRAL',
label: 'Viral',
icon: 'Rocket',
color: 'purple',
description: '10,000+ total runs',
},
FEATURED: {
id: 'FEATURED',
label: 'Featured',
icon: 'Star',
color: 'yellow',
description: 'Staff pick',
},
TOP_RATED: {
id: 'TOP_RATED',
label: 'Top Rated',
icon: 'Trophy',
color: 'gold',
description: 'Highly starred',
},
WELL_DOCUMENTED: {
id: 'WELL_DOCUMENTED',
label: 'Well Documented',
icon: '',
color: 'blue',
description: 'Complete documentation and examples',
},
FRAMEWORK: {
id: 'FRAMEWORK',
label: 'Framework',
icon: '',
color: 'green',
description: 'Uses structured framework',
},
BATTLE_TESTED: {
id: 'BATTLE_TESTED',
label: 'Battle Tested',
icon: '',
color: 'teal',
description: '1,000+ runs with high quality',
},
POPULAR: {
id: 'POPULAR',
label: 'Popular',
icon: '',
color: 'red',
description: '100+ stars',
},
RISING: {
id: 'RISING',
label: 'Rising',
icon: '',
color: 'cyan',
description: 'Fast growing engagement',
},
NEW: {
id: 'NEW',
label: 'New',
icon: '',
color: 'indigo',
description: 'Created within last 7 days',
},
}
/**
* Calculate which badges a prompt should have
*/
export function calculateBadges(prompt: Prompt, allPrompts: Prompt[] = []): string[] {
const badges: string[] = []
// NEW - Created within last 7 days
const daysSinceCreation = (Date.now() - prompt.createdAt.getTime()) / (1000 * 60 * 60 * 24)
if (daysSinceCreation <= 7) {
badges.push('NEW')
}
// VIRAL - 10,000+ runs
if (prompt.totalRuns >= 10000) {
badges.push('VIRAL')
}
// BATTLE_TESTED - 1,000+ runs
if (prompt.totalRuns >= 1000) {
badges.push('BATTLE_TESTED')
}
// POPULAR - 100+ stars
if (prompt.starsCount >= 100) {
badges.push('POPULAR')
}
// TOP_RATED - Top 10% by stars
if (allPrompts.length > 0) {
const sorted = [...allPrompts].sort((a, b) => b.starsCount - a.starsCount)
const topThreshold = sorted[Math.floor(sorted.length * 0.1)]?.starsCount || 0
if (prompt.starsCount >= topThreshold && prompt.starsCount > 20) {
badges.push('TOP_RATED')
}
}
// FRAMEWORK - Uses structured framework
if (prompt.framework) {
badges.push('FRAMEWORK')
}
// WELL_DOCUMENTED - Has description and schema with multiple variables
const hasDescription = prompt.description && prompt.description.length > 50
const hasSchema = prompt.schema?.variables?.length >= 3
if (hasDescription && hasSchema) {
badges.push('WELL_DOCUMENTED')
}
// HOT - Trending (simplified: created in last 14 days + good engagement)
if (daysSinceCreation <= 14 && prompt.totalRuns >= 100 && prompt.starsCount >= 10) {
badges.push('HOT')
}
// RISING - Fast growth (created recently + high engagement rate)
if (daysSinceCreation <= 30 && daysSinceCreation > 7) {
const runsPerDay = prompt.totalRuns / daysSinceCreation
if (runsPerDay >= 10) {
badges.push('RISING')
}
}
return badges
}
/**
* Get badge details
*/
export function getBadge(id: string): Badge | undefined {
return BADGE_DEFINITIONS[id]
}
/**
* Get all badge definitions
*/
export function getAllBadges(): Badge[] {
return Object.values(BADGE_DEFINITIONS)
}
/**
* Sort badges by priority for display
*/
export function sortBadges(badgeIds: string[]): string[] {
const priority: Record<string, number> = {
FEATURED: 1,
VIRAL: 2,
HOT: 3,
RISING: 4,
TOP_RATED: 5,
BATTLE_TESTED: 6,
POPULAR: 7,
FRAMEWORK: 8,
WELL_DOCUMENTED: 9,
NEW: 10,
}
return badgeIds.sort((a, b) => (priority[a] || 999) - (priority[b] || 999))
}
/**
* Manually award FEATURED badge (admin only)
*/
export function awardFeaturedBadge(promptId: string): string[] {
// This would update the database
// For now, just return the badge
return ['FEATURED']
}