diff --git a/src/app/api/recommendations/route.ts b/src/app/api/recommendations/route.ts
index 8892b71..dc6a50a 100644
--- a/src/app/api/recommendations/route.ts
+++ b/src/app/api/recommendations/route.ts
@@ -1,6 +1,6 @@
import { NextRequest, NextResponse } from "next/server";
import { RecommendationService } from "@/services/recommendationService";
-import { RecommendationRequest } from "@/types/recommendations";
+import { RecommendationRequest, UserCategory, ExperienceLevel } from "@/types/recommendations";
export async function POST(request: NextRequest) {
try {
@@ -151,18 +151,52 @@ export async function GET(request: NextRequest) {
);
}
+ // Validate categories
+ const validCategories: UserCategory[] = [
+ "development",
+ "design",
+ "multimedia",
+ "system-tools",
+ "gaming",
+ "productivity",
+ "education",
+ ];
+ const invalidCategories = categories.filter(
+ (cat) => !validCategories.includes(cat as UserCategory)
+ );
+ if (invalidCategories.length > 0) {
+ return NextResponse.json(
+ {
+ error: `Invalid categories: ${invalidCategories.join(", ")}`,
+ validCategories,
+ },
+ { status: 400 }
+ );
+ }
+
+ // Validate experience level if provided
+ const validExperienceLevels: ExperienceLevel[] = ["beginner", "intermediate", "advanced"];
+ if (experienceLevel && !validExperienceLevels.includes(experienceLevel as ExperienceLevel)) {
+ return NextResponse.json(
+ {
+ error: `Invalid experience_level. Must be one of: ${validExperienceLevels.join(", ")}`,
+ },
+ { status: 400 }
+ );
+ }
+
// Set default limit
const parsedLimit =
limit && parseInt(limit) > 0 && parseInt(limit) <= 50
? parseInt(limit)
: 20;
- // Generate recommendations
+ // Generate recommendations with validated types
const recommendations = await RecommendationService.generateRecommendations(
{
platform_id: platformId,
- categories: categories as any,
- experienceLevel: experienceLevel as any,
+ categories: categories as UserCategory[],
+ experienceLevel: experienceLevel as ExperienceLevel | undefined,
limit: parsedLimit,
}
);
diff --git a/src/components/Header.tsx b/src/components/Header.tsx
index c56bbef..f229a79 100644
--- a/src/components/Header.tsx
+++ b/src/components/Header.tsx
@@ -70,7 +70,7 @@ export function Header({ cryptomusEnabled, onResetPreferences, hasProfile }: Hea
>
- {locale === 'tr' ? 'Tercihler' : 'Preferences'}
+ {t('recommendations.customize')}
)}
diff --git a/src/components/RepoHubApp.tsx b/src/components/RepoHubApp.tsx
index 350ff3b..85cea16 100644
--- a/src/components/RepoHubApp.tsx
+++ b/src/components/RepoHubApp.tsx
@@ -20,6 +20,7 @@ function RepoHubAppContent({ cryptomusEnabled }: { cryptomusEnabled: boolean })
const [selectedPlatform, setSelectedPlatform] = useState(null)
const [selectedPackages, setSelectedPackages] = useState([])
const [generatedScript, setGeneratedScript] = useState(null)
+ const [availablePlatforms, setAvailablePlatforms] = useState([])
// Recommendation profile management
const {
@@ -32,6 +33,22 @@ function RepoHubAppContent({ cryptomusEnabled }: { cryptomusEnabled: boolean })
const [showOnboarding, setShowOnboarding] = useState(false)
+ // Load platforms on mount
+ useEffect(() => {
+ const loadPlatforms = async () => {
+ try {
+ const response = await fetch('/api/platforms')
+ if (response.ok) {
+ const platforms = await response.json()
+ setAvailablePlatforms(platforms)
+ }
+ } catch (error) {
+ console.error('Failed to load platforms:', error)
+ }
+ }
+ loadPlatforms()
+ }, [])
+
// Show onboarding modal on first visit
useEffect(() => {
if (!isProfileLoading && !hasCompletedOnboarding) {
@@ -97,64 +114,29 @@ function RepoHubAppContent({ cryptomusEnabled }: { cryptomusEnabled: boolean })
}
const handleGenerateScript = () => {
- console.log('🔧 handleGenerateScript called')
- console.log('📦 selectedPackages:', selectedPackages)
- console.log('🖥️ selectedPlatform:', selectedPlatform)
- console.log('✅ hasCompletedOnboarding:', hasCompletedOnboarding)
-
if (selectedPackages.length === 0) {
- console.log('❌ No packages selected')
return
}
- // Use selected platform, or if not selected, use the platform from recommendations profile
+ // Use selected platform, or if not selected, find platform from available platforms
let platformToUse = selectedPlatform
if (!platformToUse && hasCompletedOnboarding) {
- // Get effective OS from profile and find matching platform
+ // Get effective OS from profile and find matching platform from loaded platforms
const effectiveOS = profile.selectedOS || detectedOS
- console.log('🔍 effectiveOS:', effectiveOS)
-
- // We need to fetch the platform data - for now, create a mock platform
- // This should ideally come from the platforms list
- if (effectiveOS) {
- platformToUse = {
- id: effectiveOS,
- name: effectiveOS.charAt(0).toUpperCase() + effectiveOS.slice(1),
- description: '',
- icon: '',
- packageManager: getPackageManagerForOS(effectiveOS)
+
+ if (effectiveOS && availablePlatforms.length > 0) {
+ platformToUse = availablePlatforms.find(p => p.id === effectiveOS) || null
+
+ if (!platformToUse) {
+ console.warn(`Platform not found for OS: ${effectiveOS}`)
}
- console.log('🎯 Created platform:', platformToUse)
}
}
if (platformToUse) {
- console.log('✨ Generating script for platform:', platformToUse)
const script = generateScript(selectedPackages, platformToUse)
- console.log('📝 Script generated:', script)
setGeneratedScript(script)
- } else {
- console.log('❌ No platform available')
- }
- }
-
- // Helper function to get package manager for OS
- const getPackageManagerForOS = (os: string): string => {
- switch (os.toLowerCase()) {
- case 'windows':
- return 'winget'
- case 'macos':
- return 'brew'
- case 'ubuntu':
- case 'debian':
- return 'apt'
- case 'fedora':
- return 'dnf'
- case 'arch':
- return 'pacman'
- default:
- return 'unknown'
}
}
@@ -228,13 +210,16 @@ function RepoHubAppContent({ cryptomusEnabled }: { cryptomusEnabled: boolean })
p.id === generatedScript.platform) ||
+ {
+ id: generatedScript.platform,
+ name: generatedScript.platform.charAt(0).toUpperCase() + generatedScript.platform.slice(1),
+ description: '',
+ icon: '',
+ packageManager: ''
+ }
+ }
onClose={handleCloseScriptPreview}
/>
)}
diff --git a/src/types/recommendations.ts b/src/types/recommendations.ts
index 9296aba..d86dfe5 100644
--- a/src/types/recommendations.ts
+++ b/src/types/recommendations.ts
@@ -52,7 +52,7 @@ export interface RecommendedPackage {
category?: string;
license?: string;
type: "gui" | "cli";
- platform?: string | any;
+ platform?: Platform;
platform_id?: string;
repository: "official" | "third-party" | "aur";
download_url?: string;