Spaces:
Configuration error
Configuration error
File size: 4,463 Bytes
bcce530 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | /**
* Search utilities for OpenPrompt
* Supports full-text search across prompts
*/
export interface SearchFilters {
query?: string
category?: string
tags?: string[]
model?: string
minStars?: number
minRuns?: number
dateRange?: 'day' | 'week' | 'month' | 'all'
sortBy?: 'trending' | 'recent' | 'stars' | 'runs'
}
export interface SearchResult {
id: string
slug: string
title: string
description: string | null
category: string | null
tags: string[]
totalRuns: number
starsCount: number
remixesCount: number
createdAt: Date
creator: {
name: string | null
username: string | null
image: string | null
} | null
score?: number // relevance score
}
/**
* Build Prisma where clause from search filters
*/
export function buildSearchWhere(filters: SearchFilters) {
const where: Record<string, unknown> = {
visibility: 'public',
}
// Text search (title + description)
if (filters.query) {
where.OR = [
{ title: { contains: filters.query, mode: 'insensitive' } },
{ description: { contains: filters.query, mode: 'insensitive' } },
{ tags: { hasSome: [filters.query.toLowerCase()] } },
]
}
// Category filter
if (filters.category) {
where.category = filters.category
}
// Tags filter
if (filters.tags && filters.tags.length > 0) {
where.tags = { hasSome: filters.tags }
}
// Model filter
if (filters.model) {
where.modelAllowed = { has: filters.model }
}
// Stars filter
if (filters.minStars) {
where.starsCount = { gte: filters.minStars }
}
// Runs filter
if (filters.minRuns) {
where.totalRuns = { gte: filters.minRuns }
}
// Date range filter
if (filters.dateRange && filters.dateRange !== 'all') {
const now = new Date()
const cutoff = new Date()
switch (filters.dateRange) {
case 'day':
cutoff.setDate(now.getDate() - 1)
break
case 'week':
cutoff.setDate(now.getDate() - 7)
break
case 'month':
cutoff.setMonth(now.getMonth() - 1)
break
}
where.createdAt = { gte: cutoff }
}
return where
}
/**
* Build Prisma orderBy from sort option
*/
export function buildSearchOrderBy(sortBy: SearchFilters['sortBy'] = 'trending') {
switch (sortBy) {
case 'recent':
return [{ createdAt: 'desc' as const }]
case 'stars':
return [{ starsCount: 'desc' as const }, { createdAt: 'desc' as const }]
case 'runs':
return [{ totalRuns: 'desc' as const }, { createdAt: 'desc' as const }]
case 'trending':
default:
// Trending uses a calculated score (handled separately)
return [{ totalRuns: 'desc' as const }, { starsCount: 'desc' as const }]
}
}
/**
* Extract unique categories from prompts
*/
export function getCategories(): string[] {
return [
'Content',
'Development',
'Marketing',
'Business',
'Education',
'Creative',
'Research',
]
}
/**
* Extract unique tags from prompts
*/
export async function getPopularTags(limit: number = 20): Promise<string[]> {
try {
// Query database for actual popular tags
const { prisma } = await import('@/lib/prisma')
const prompts = await prisma.prompt.findMany({
where: { visibility: 'public', tags: { isEmpty: false } },
select: { tags: true },
orderBy: { totalRuns: 'desc' },
take: 200,
})
// Count tag frequency
const tagCounts = new Map<string, number>()
for (const prompt of prompts) {
for (const tag of prompt.tags) {
tagCounts.set(tag, (tagCounts.get(tag) || 0) + 1)
}
}
// Sort by frequency and return top N
return [...tagCounts.entries()]
.sort((a, b) => b[1] - a[1])
.slice(0, limit)
.map(([tag]) => tag)
} catch {
// Fallback to hardcoded list if DB query fails
return [
'blog', 'writing', 'code', 'email', 'social-media',
'seo', 'ai', 'productivity', 'marketing', 'business',
].slice(0, limit)
}
}
|