refactor: Pass user profile as a prop to the recommendations section and remove the manual refresh button.

This commit is contained in:
Yusuf İpek
2025-11-23 13:08:25 +03:00
parent b6afaaf67e
commit 17bbe54cb1
2 changed files with 34 additions and 35 deletions
+22 -24
View File
@@ -3,7 +3,7 @@
import { useState, useEffect, useMemo } from 'react' import { useState, useEffect, useMemo } from 'react'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Sparkles, RefreshCw, Settings, Package as PackageIcon, Star, Grid3x3, List, TrendingUp, Award, ChevronDown, ChevronUp } from 'lucide-react' import { Sparkles, Settings, Package as PackageIcon, Star, Grid3x3, List, TrendingUp, Award, ChevronDown, ChevronUp } from 'lucide-react'
import { RecommendedPackage, UserCategory } from '@/types/recommendations' import { RecommendedPackage, UserCategory } from '@/types/recommendations'
import { Package } from '@/types' import { Package } from '@/types'
import { useLocale } from '@/contexts/LocaleContext' import { useLocale } from '@/contexts/LocaleContext'
@@ -12,10 +12,13 @@ import { CATEGORY_ICONS } from '@/constants/categoryIcons'
import { RecommendationCard } from './RecommendationCard' import { RecommendationCard } from './RecommendationCard'
import { RecommendationListItem } from './RecommendationListItem' import { RecommendationListItem } from './RecommendationListItem'
import { UserProfile } from '@/types/recommendations'
interface RecommendationsSectionProps { interface RecommendationsSectionProps {
onPackageToggle: (pkg: Package) => void onPackageToggle: (pkg: Package) => void
selectedPackages: Package[] selectedPackages: Package[]
onCustomizeClick: () => void onCustomizeClick: () => void
profile: UserProfile
} }
type ViewMode = 'grid' | 'compact' type ViewMode = 'grid' | 'compact'
@@ -25,17 +28,20 @@ type FilterCategory = 'all' | string
export function RecommendationsSection({ export function RecommendationsSection({
onPackageToggle, onPackageToggle,
selectedPackages, selectedPackages,
onCustomizeClick onCustomizeClick,
profile
}: RecommendationsSectionProps) { }: RecommendationsSectionProps) {
const { t } = useLocale() const { t } = useLocale()
const { profile, getEffectiveOS, isProfileComplete } = useRecommendationProfile() const { getEffectiveOS, isProfileComplete } = useRecommendationProfile()
// Override profile from hook with prop
const effectiveProfile = profile
const [recommendations, setRecommendations] = useState<RecommendedPackage[]>([]) const [recommendations, setRecommendations] = useState<RecommendedPackage[]>([])
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null) const [error, setError] = useState<string | null>(null)
const [viewMode, setViewMode] = useState<ViewMode>('grid') const [viewMode, setViewMode] = useState<ViewMode>('grid')
const [sortMode, setSortMode] = useState<SortMode>('recommended') const [sortMode, setSortMode] = useState<SortMode>('recommended')
const [filterCategory, setFilterCategory] = useState<FilterCategory>('all') const [filterCategory, setFilterCategory] = useState<FilterCategory>('all')
const [isExpanded, setIsExpanded] = useState(true) const [isExpanded, setIsExpanded] = useState(false)
const fetchRecommendations = async () => { const fetchRecommendations = async () => {
if (!isProfileComplete()) { if (!isProfileComplete()) {
@@ -53,8 +59,8 @@ export function RecommendationsSection({
}, },
body: JSON.stringify({ body: JSON.stringify({
platform_id: getEffectiveOS(), platform_id: getEffectiveOS(),
categories: profile.categories, categories: effectiveProfile.categories,
experienceLevel: profile.experienceLevel, experienceLevel: effectiveProfile.experienceLevel,
limit: 12 limit: 12
}) })
}) })
@@ -74,7 +80,8 @@ export function RecommendationsSection({
} }
const data = await response.json() const data = await response.json()
setRecommendations(data.recommendations || []) const recs = data.recommendations || []
setRecommendations(recs)
} catch (err) { } catch (err) {
console.error('Error fetching recommendations:', err) console.error('Error fetching recommendations:', err)
@@ -92,9 +99,11 @@ export function RecommendationsSection({
// Fetch recommendations on mount and when profile changes // Fetch recommendations on mount and when profile changes
useEffect(() => { useEffect(() => {
if (isProfileComplete()) { if (isProfileComplete()) {
// If profile just changed (e.g. from customization), we might want to force refresh
// But for now, let's rely on the cache key changing which includes profile data
fetchRecommendations() fetchRecommendations()
} }
}, [profile.categories, profile.selectedOS, profile.experienceLevel]) }, [effectiveProfile.categories, effectiveProfile.selectedOS, effectiveProfile.experienceLevel])
const isPackageSelected = (pkg: RecommendedPackage) => { const isPackageSelected = (pkg: RecommendedPackage) => {
return selectedPackages.some(selected => selected.id === pkg.id) return selectedPackages.some(selected => selected.id === pkg.id)
@@ -196,18 +205,7 @@ export function RecommendationsSection({
? (t('common.deselect_all') || 'Deselect All') ? (t('common.deselect_all') || 'Deselect All')
: (t('common.select_all') || 'Select All')} : (t('common.select_all') || 'Select All')}
</Button> </Button>
<Button
variant="outline"
size="sm"
onClick={(e) => {
e.stopPropagation()
fetchRecommendations()
}}
disabled={loading}
>
<RefreshCw className={`h-4 w-4 mr-2 ${loading ? 'animate-spin' : ''}`} />
{t('recommendations.refresh')}
</Button>
<Button <Button
variant="outline" variant="outline"
size="sm" size="sm"
@@ -241,7 +239,7 @@ export function RecommendationsSection({
<span className="text-xs px-2 py-1 rounded-full bg-primary/10 text-primary"> <span className="text-xs px-2 py-1 rounded-full bg-primary/10 text-primary">
{getEffectiveOS()} {getEffectiveOS()}
</span> </span>
{profile.categories.map(cat => ( {effectiveProfile.categories.map(cat => (
<span <span
key={cat} key={cat}
className="text-xs px-2 py-1 rounded-full bg-secondary text-secondary-foreground" className="text-xs px-2 py-1 rounded-full bg-secondary text-secondary-foreground"
@@ -271,7 +269,7 @@ export function RecommendationsSection({
> >
All ({recommendations.length}) All ({recommendations.length})
</Button> </Button>
{profile.categories.map(cat => { {effectiveProfile.categories.map(cat => {
const count = getCategoryCount(cat) const count = getCategoryCount(cat)
const Icon = CATEGORY_ICONS[cat] const Icon = CATEGORY_ICONS[cat]
return ( return (
@@ -368,7 +366,7 @@ export function RecommendationsSection({
<CardContent> <CardContent>
{loading && ( {loading && (
<div className="text-center py-12"> <div className="text-center py-12">
<RefreshCw className="h-8 w-8 animate-spin mx-auto mb-4 text-primary" /> <Sparkles className="h-8 w-8 animate-spin mx-auto mb-4 text-primary" />
<p className="text-muted-foreground">{t('recommendations.loading')}</p> <p className="text-muted-foreground">{t('recommendations.loading')}</p>
</div> </div>
)} )}
@@ -376,7 +374,7 @@ export function RecommendationsSection({
{error && ( {error && (
<div className="text-center py-12"> <div className="text-center py-12">
<p className="text-destructive mb-4">{error}</p> <p className="text-destructive mb-4">{error}</p>
<Button onClick={fetchRecommendations} variant="outline"> <Button onClick={() => fetchRecommendations()} variant="outline">
Try Again Try Again
</Button> </Button>
</div> </div>
+1
View File
@@ -179,6 +179,7 @@ function RepoHubAppContent({ cryptomusEnabled }: { cryptomusEnabled: boolean })
onPackageToggle={handlePackageToggle} onPackageToggle={handlePackageToggle}
selectedPackages={selectedPackages} selectedPackages={selectedPackages}
onCustomizeClick={handleCustomizePreferences} onCustomizeClick={handleCustomizePreferences}
profile={profile}
/> />
)} )}