Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 38 additions & 137 deletions src/app/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
import { Separator } from '@/components/ui/separator'
import { useAuthStore, useDataCacheStore, useStoreHydration } from '@/stores'
import { useAuthStore, useDataCacheStore, useStoreHydration, useSearchStore } from '@/stores'
import { ossInsightClient } from '@/lib/api/oss-insight-client'
import type { TrendingRepo, TopLanguage, GitHubEvent, TopContributor } from '@/types/oss-insight'
import { TrendingReposWidget } from '@/components/widget/TrendingReposWidget'
import { LanguageHeatmapWidget } from '@/components/widget/LanguageHeatmapWidget'
import { ActivityFeedWidget } from '@/components/widget/ActivityFeedWidget'
import { Star, Folder, GitFork, HeartPulse, AlertTriangle } from "lucide-react"
import { StatsOverview } from '@/components/dashboard/StatsOverview'
import { Folder, AlertTriangle, Search } from "lucide-react"
import { SearchModal } from '@/components/search/SearchModal'

interface DashboardStats {
totalRepos: number
Expand All @@ -41,6 +43,7 @@ export default function DashboardPage() {
const hasHydrated = useStoreHydration()
const { isConnected, orgData, isTokenValid } = useAuthStore()
const { getCachedData, setCachedData } = useDataCacheStore()
const { setSearchModalOpen } = useSearchStore()

const [period, setPeriod] = useState<'24h' | '7d' | '30d'>('7d')
const [selectedCategory, setSelectedCategory] = useState<'all' | 'ai-ml' | 'web-dev' | 'devops' | 'mobile'>('all')
Expand Down Expand Up @@ -85,7 +88,24 @@ export default function DashboardPage() {

try {
const cacheKey = `dashboard_${period}_${orgData?.orgName}`
const cachedData = getCachedData(cacheKey)
let cachedData = null;

try {

if (cacheKey && typeof getCachedData === 'function') {
cachedData = getCachedData(cacheKey)
// Ensure the returned data is valid
if (cachedData && typeof cachedData !== 'object') {
console.warn('Invalid cache data format, ignoring cache')
cachedData = null
}
} else {
console.warn('Cache key or getCachedData function is invalid')
}
} catch (cacheError) {
console.warn('Cache retrieval failed:', cacheError)
// Continue without using cache
}

if (cachedData) {
setDashboardData(prev => ({
Expand Down Expand Up @@ -126,11 +146,7 @@ export default function DashboardPage() {
setDashboardData(newData)

// Cache for 10 minutes
const cacheKeyMap = {
'24h': `trendingRepos_24h_${orgData?.orgName}`,
'7d': `trendingRepos_7d_${orgData?.orgName}`,
'30d': `trendingRepos_30d_${orgData?.orgName}`,
} as const
setCachedData(cacheKey, newData, 10 * 60 * 1000)

} catch (error) {
console.error('Dashboard data loading failed:', error)
Expand All @@ -149,18 +165,6 @@ export default function DashboardPage() {
return `${timeOfDay}, ${userName}! `
}

const getHealthScore = () => {
const { stats } = dashboardData
let score = 70 // Base score

if (stats.healthyReposPercentage > 80) score += 20
else if (stats.healthyReposPercentage > 60) score += 10

if (stats.trendingCount > 5) score += 10

return Math.min(100, score)
}

if (!hasHydrated || dashboardData.loading) {
return (
<Layout>
Expand Down Expand Up @@ -189,6 +193,16 @@ export default function DashboardPage() {
</div>

<div className="flex items-center gap-3">
<Button
variant="outline"
onClick={() => setSearchModalOpen(true)}
className="px-6 py-2.5 font-medium text-base"
size="lg"
>
<Search className="w-6 h-6 mr-2" />
Search
</Button>

<Select value={period} onValueChange={(value: '24h' | '7d' | '30d') => setPeriod(value)}>
<SelectTrigger className="w-40">
<SelectValue />
Expand All @@ -207,49 +221,7 @@ export default function DashboardPage() {
</div>

{/* Quick Stats Cards */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<Card className="bg-white dark:bg-gray-800 shadow-sm">
<CardContent className="p-4">
<div className="flex items-center gap-3">
<Folder className="w-4 h-4 text-gray-500 dark:text-gray-400" />
<div>
<p className="text-sm font-medium text-gray-500 dark:text-gray-400">Total Repos</p>
<p className="text-xl font-semibold text-gray-800 dark:text-gray-200">
{dashboardData.stats.totalRepos.toLocaleString()}
</p>
</div>
</div>
</CardContent>
</Card>

<Card className="bg-white dark:bg-gray-800 shadow-sm">
<CardContent className="p-4">
<div className="flex items-center gap-3">
<Star className="w-4 h-4 text-amber-400" />
<div>
<p className="text-sm font-medium text-gray-500 dark:text-gray-400">Total Stars</p>
<p className="text-xl font-semibold text-gray-800 dark:text-gray-200">
{(dashboardData.stats.totalStars / 1000000).toFixed(1)}M
</p>
</div>
</div>
</CardContent>
</Card>

<Card className="bg-white dark:bg-gray-800 shadow-sm">
<CardContent className="p-4">
<div className="flex items-center gap-3">
<GitFork className="w-4 h-4 text-gray-500 dark:text-gray-400" />
<div>
<p className="text-sm font-medium text-gray-500 dark:text-gray-400">Total Forks</p>
<p className="text-xl font-semibold text-gray-800 dark:text-gray-200">
{dashboardData.stats.totalForks.toLocaleString()}
</p>
</div>
</div>
</CardContent>
</Card>
</div>
<StatsOverview stats={dashboardData.stats} loading={dashboardData.loading} />

{/* Error State */}
{dashboardData.error && (
Expand Down Expand Up @@ -356,81 +328,10 @@ export default function DashboardPage() {
</Card>
</div>
</div>

{/* Bottom Section - Insights */}
<Card className="bg-white dark:bg-gray-800">
<CardContent className="p-6">
<h3 className="text-lg font-semibold mb-4 flex items-center">
AI Insights
</h3>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<Card>
<CardContent className="p-4">
<div className="flex items-center gap-2">
<Folder className="w-4 h-4" />
<div>
<p className="text-sm font-medium text-gray-600 dark:text-gray-400">
Total Repos
</p>
<p className="text-xl font-semibold">
{dashboardData.stats.totalRepos.toLocaleString()}
</p>
</div>
</div>
</CardContent>
</Card>

<Card>
<CardContent className="p-4">
<div className="flex items-center gap-2">
<Star className="w-4 h-4" />
<div>
<p className="text-sm font-medium text-gray-600 dark:text-gray-400">
Total Stars
</p>
<p className="text-xl font-semibold">
{(dashboardData.stats.totalStars / 1000000).toFixed(1)}M
</p>
</div>
</div>
</CardContent>
</Card>

<Card>
<CardContent className="p-4">
<div className="flex items-center gap-2">
<GitFork className="w-4 h-4" />
<div>
<p className="text-sm font-medium text-gray-600 dark:text-gray-400">
Total Forks
</p>
<p className="text-xl font-semibold">
{dashboardData.stats.totalForks.toLocaleString()}
</p>
</div>
</div>
</CardContent>
</Card>

<Card>
<CardContent className="p-4">
<div className="flex items-center gap-2">
<HeartPulse className="w-4 h-4" />
<div>
<p className="text-sm font-medium text-gray-600 dark:text-gray-400">
Health Score
</p>
<p className="text-xl font-semibold">
{getHealthScore()}%
</p>
</div>
</div>
</CardContent>
</Card>
</div>
</CardContent>
</Card>
</div>

{/* Search Modal - no props needed */}
<SearchModal />
</Layout>
)
}
Loading