mirror of
https://github.com/yusufipk/RepoHub.git
synced 2026-09-11 18:46:07 +00:00
feat: Add smart package recommendations feature
- Implement onboarding modal with 3-step wizard - Category selection (up to 3 categories) - OS detection with manual override - Experience level selection - Add intelligent recommendation engine - Hybrid scoring algorithm (category 40%, popularity 30%, OS 20%, preset 10%) - 7 curated categories with preset packages - Support for all platforms (Windows, macOS, Ubuntu, Debian, Arch, Fedora) - Create recommendation UI components - RecommendationsSection with grid layout - Package cards with recommendation scores and reasons - User profile display with customization options - Add localStorage-based profile management - Persistent user preferences - Automatic OS detection - Profile CRUD operations via useRecommendationProfile hook - Implement API endpoint - POST /api/recommendations - GET /api/recommendations (query params) - Request validation and error handling - Add full i18n support - English and Turkish translations - Onboarding flow, categories, and UI labels - Update TypeScript config (lib: es2017 for array.includes) Closes #1
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { RecommendationService } from '@/services/recommendationService'
|
||||
import { RecommendationRequest } from '@/types/recommendations'
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const body: RecommendationRequest = await request.json()
|
||||
|
||||
// Validate required fields
|
||||
if (!body.platform_id) {
|
||||
return NextResponse.json(
|
||||
{ error: 'platform_id is required' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
if (!body.categories || body.categories.length === 0) {
|
||||
return NextResponse.json(
|
||||
{ error: 'At least one category is required' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
// Validate platform_id
|
||||
const validPlatforms = ['windows', 'macos', 'ubuntu', 'debian', 'arch', 'fedora']
|
||||
if (!validPlatforms.includes(body.platform_id)) {
|
||||
return NextResponse.json(
|
||||
{ error: `Invalid platform_id. Must be one of: ${validPlatforms.join(', ')}` },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
// Validate categories
|
||||
const validCategories = [
|
||||
'development',
|
||||
'design',
|
||||
'multimedia',
|
||||
'system-tools',
|
||||
'gaming',
|
||||
'productivity',
|
||||
'education'
|
||||
]
|
||||
const invalidCategories = body.categories.filter(
|
||||
cat => !validCategories.includes(cat)
|
||||
)
|
||||
if (invalidCategories.length > 0) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: `Invalid categories: ${invalidCategories.join(', ')}`,
|
||||
validCategories
|
||||
},
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
// Set default limit
|
||||
const limit = body.limit && body.limit > 0 && body.limit <= 50
|
||||
? body.limit
|
||||
: 20
|
||||
|
||||
// Generate recommendations
|
||||
const recommendations = await RecommendationService.generateRecommendations({
|
||||
platform_id: body.platform_id,
|
||||
categories: body.categories,
|
||||
experienceLevel: body.experienceLevel,
|
||||
limit
|
||||
})
|
||||
|
||||
return NextResponse.json({
|
||||
recommendations,
|
||||
total: recommendations.length,
|
||||
userProfile: {
|
||||
categories: body.categories,
|
||||
platform: body.platform_id,
|
||||
experienceLevel: body.experienceLevel
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Error generating recommendations:', error)
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: 'Failed to generate recommendations',
|
||||
details: error instanceof Error ? error.message : 'Unknown error'
|
||||
},
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const { searchParams } = new URL(request.url)
|
||||
const platformId = searchParams.get('platform_id')
|
||||
const categoriesParam = searchParams.get('categories')
|
||||
const experienceLevel = searchParams.get('experience_level')
|
||||
const limit = searchParams.get('limit')
|
||||
|
||||
// Validate required fields
|
||||
if (!platformId) {
|
||||
return NextResponse.json(
|
||||
{ error: 'platform_id query parameter is required' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
if (!categoriesParam) {
|
||||
return NextResponse.json(
|
||||
{ error: 'categories query parameter is required (comma-separated)' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
// Parse categories
|
||||
const categories = categoriesParam.split(',').map(c => c.trim())
|
||||
|
||||
// Validate platform_id
|
||||
const validPlatforms = ['windows', 'macos', 'ubuntu', 'debian', 'arch', 'fedora']
|
||||
if (!validPlatforms.includes(platformId)) {
|
||||
return NextResponse.json(
|
||||
{ error: `Invalid platform_id. Must be one of: ${validPlatforms.join(', ')}` },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
// Set default limit
|
||||
const parsedLimit = limit && parseInt(limit) > 0 && parseInt(limit) <= 50
|
||||
? parseInt(limit)
|
||||
: 20
|
||||
|
||||
// Generate recommendations
|
||||
const recommendations = await RecommendationService.generateRecommendations({
|
||||
platform_id: platformId,
|
||||
categories: categories as any,
|
||||
experienceLevel: experienceLevel as any,
|
||||
limit: parsedLimit
|
||||
})
|
||||
|
||||
return NextResponse.json({
|
||||
recommendations,
|
||||
total: recommendations.length,
|
||||
userProfile: {
|
||||
categories,
|
||||
platform: platformId,
|
||||
experienceLevel
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Error generating recommendations:', error)
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: 'Failed to generate recommendations',
|
||||
details: error instanceof Error ? error.message : 'Unknown error'
|
||||
},
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user