Skip to content

Commit 7666ff2

Browse files
committed
Fix up comparisons
1 parent 74c4e47 commit 7666ff2

File tree

3 files changed

+104
-12
lines changed

3 files changed

+104
-12
lines changed

src/actions/tool-actions.ts

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,21 +68,54 @@ export async function getAllTools(): Promise<Tool[]> {
6868
export async function getToolBySlug(slug: string): Promise<Tool | null> {
6969
console.log(`Fetching tool by slug: ${slug} (using Prisma)`)
7070
try {
71-
// Convert slug back to a readable name for searching
72-
const searchName = slug
71+
// Generate search patterns inline to avoid dynamic import issues
72+
const patterns = []
73+
74+
// Original slug
75+
patterns.push(slug)
76+
77+
// Title case version
78+
const titleCase = slug
7379
.split('-')
7480
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
75-
.join(' ');
81+
.join(' ')
82+
patterns.push(titleCase)
83+
84+
// All lowercase version
85+
patterns.push(slug.replace(/-/g, ' '))
86+
87+
// All uppercase version
88+
patterns.push(titleCase.toUpperCase())
89+
90+
// Handle common variations
91+
const variations = [
92+
slug.replace(/-/g, ''), // Remove all hyphens
93+
slug.replace(/-/g, '_'), // Replace hyphens with underscores
94+
slug.replace(/-ai$/, ' AI'), // Handle AI suffix
95+
slug.replace(/-io$/, '.io'), // Handle .io domains
96+
]
7697

98+
patterns.push(...variations)
99+
const searchPatterns = [...new Set(patterns)] // Remove duplicates
100+
101+
console.log(`Search patterns for slug "${slug}":`, searchPatterns)
102+
103+
// Try exact matches first, then fuzzy matches
77104
const tool = await prisma.tool.findFirst({
78105
where: {
79-
OR: [
80-
{ name: { equals: searchName, mode: 'insensitive' } },
81-
{ name: { contains: slug, mode: 'insensitive' } },
82-
{ name: { contains: searchName, mode: 'insensitive' } }
83-
]
106+
OR: searchPatterns.flatMap(pattern => [
107+
{ name: { equals: pattern, mode: 'insensitive' } },
108+
{ name: { contains: pattern, mode: 'insensitive' } }
109+
])
84110
}
85111
});
112+
113+
if (tool) {
114+
console.log(`Found tool: ${tool.name} for slug: ${slug}`)
115+
} else {
116+
console.log(`No tool found for slug: ${slug}`)
117+
}
118+
86119
return tool;
87120
} catch (error) {
88121
console.error("Error fetching tool by slug:", error)

src/components/dynamic-comparison-search.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
Code,
1818
DollarSign
1919
} from 'lucide-react'
20+
import { nameToSlug } from '@/utils/slug-helpers'
2021

2122
interface DynamicComparisonSearchProps {
2223
tools: Tool[]
@@ -98,15 +99,15 @@ export function DynamicComparisonSearch({ tools }: DynamicComparisonSearchProps)
9899

99100
const handleCompare = () => {
100101
if (selectedTool1 && selectedTool2) {
101-
const tool1Slug = selectedTool1.name.toLowerCase().replace(/\s+/g, '-').replace(/[^\w-]+/g, '')
102-
const tool2Slug = selectedTool2.name.toLowerCase().replace(/\s+/g, '-').replace(/[^\w-]+/g, '')
102+
const tool1Slug = nameToSlug(selectedTool1.name)
103+
const tool2Slug = nameToSlug(selectedTool2.name)
103104
router.push(`/comparisons/${tool1Slug}/vs/${tool2Slug}`)
104105
}
105106
}
106107

107108
const handlePopularComparison = (tool1: Tool, tool2: Tool) => {
108-
const tool1Slug = tool1.name.toLowerCase().replace(/\s+/g, '-').replace(/[^\w-]+/g, '')
109-
const tool2Slug = tool2.name.toLowerCase().replace(/\s+/g, '-').replace(/[^\w-]+/g, '')
109+
const tool1Slug = nameToSlug(tool1.name)
110+
const tool2Slug = nameToSlug(tool2.name)
110111
router.push(`/comparisons/${tool1Slug}/vs/${tool2Slug}`)
111112
}
112113

src/utils/slug-helpers.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* Utility functions for converting between tool names and URL-friendly slugs
3+
*/
4+
5+
/**
6+
* Convert a tool name to a URL-friendly slug
7+
*/
8+
export function nameToSlug(name: string): string {
9+
return name
10+
.toLowerCase()
11+
.replace(/[^\w\s-]/g, '') // Remove special characters except spaces and hyphens
12+
.replace(/\s+/g, '-') // Replace spaces with hyphens
13+
.replace(/-+/g, '-') // Replace multiple hyphens with single hyphen
14+
.trim()
15+
}
16+
17+
/**
18+
* Convert a URL slug back to a searchable name pattern
19+
* This handles common variations and patterns
20+
*/
21+
export function slugToNamePattern(slug: string): string {
22+
return slug
23+
.split('-')
24+
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
25+
.join(' ')
26+
}
27+
28+
/**
29+
* Generate multiple search patterns from a slug to improve matching
30+
*/
31+
export function generateSearchPatterns(slug: string): string[] {
32+
const patterns = []
33+
34+
// Original slug
35+
patterns.push(slug)
36+
37+
// Title case version
38+
const titleCase = slugToNamePattern(slug)
39+
patterns.push(titleCase)
40+
41+
// All lowercase version
42+
patterns.push(slug.replace(/-/g, ' '))
43+
44+
// All uppercase version
45+
patterns.push(titleCase.toUpperCase())
46+
47+
// Handle common variations
48+
const variations = [
49+
slug.replace(/-/g, ''), // Remove all hyphens
50+
slug.replace(/-/g, '_'), // Replace hyphens with underscores
51+
slug.replace(/-ai$/, ' AI'), // Handle AI suffix
52+
slug.replace(/-io$/, '.io'), // Handle .io domains
53+
]
54+
55+
patterns.push(...variations)
56+
57+
return [...new Set(patterns)] // Remove duplicates
58+
}

0 commit comments

Comments
 (0)