Skip to content

Commit 2b48f09

Browse files
authored
Merge pull request #63 from MuslimeKaya/main
refactor: clean up layout and sidebar components for improved readability and structure
2 parents 82ba5eb + 662ec2a commit 2b48f09

File tree

3 files changed

+112
-119
lines changed

3 files changed

+112
-119
lines changed

src/app/dashboard/page.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client'
22

3-
import { useEffect } from 'react'
3+
import { useEffect } from 'react'
44
import { useSearchParams, useRouter } from 'next/navigation'
55
import { Layout } from '@/components/layout/Layout'
66

@@ -59,7 +59,7 @@ function mapActionItemToGitHubIssue(item: ActionItemInput): GitHubIssue {
5959
comments: 0,
6060
state: 'open' as const,
6161
assignee: null,
62-
priority: (item.priority && isValidPriority(item.priority)) ?
62+
priority: (item.priority && isValidPriority(item.priority)) ?
6363
item.priority as 'low' | 'medium' | 'high' : 'low',
6464
}
6565
}
@@ -93,7 +93,7 @@ export default function DashboardPage() {
9393
const searchParams = useSearchParams()
9494
const router = useRouter()
9595

96-
const currentTab = searchParams.get('tab') || 'assigned'
96+
const currentTab = searchParams?.get('tab') || 'assigned'
9797
const isQuickWinsTab = currentTab === 'quick-wins' || currentTab === 'good-first-issues' || currentTab === 'easy-fixes'
9898
const isActionRequiredTab = !isQuickWinsTab
9999

@@ -156,7 +156,7 @@ export default function DashboardPage() {
156156
<Layout>
157157
<div className="max-w-7xl mx-auto p-6 space-y-6">
158158
{/* Header */}
159-
<div className="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4 border-b pb-4">
159+
<div className="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4 border-b pb-4 sticky top-0 bg-white dark:bg-gray-900 z-10">
160160
<div>
161161
<h1 className="text-3xl font-bold text-gray-900 dark:text-white">
162162
{getWelcomeMessage()}

src/components/layout/Layout.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,13 @@ import { Sidebar, SidebarToggle } from './Sidebar'
55
import { useSidebarState } from '@/stores'
66

77
export function Layout({ children }: { children: React.ReactNode }) {
8-
const { setOpen } = useSidebarState()
8+
const { setOpen } = useSidebarState()
99

1010
return (
1111
<div className="flex">
1212
<Sidebar />
1313
<SidebarToggle onClick={() => setOpen(true)} />
14-
15-
<main className="flex-1 min-h-screen">
14+
<main className="flex-1 min-h-screen lg:ml-80 max-w-7xl mx-auto p-6 space-y-6 overflow-auto">
1615
{children}
1716
</main>
1817
</div>

src/components/layout/Sidebar.tsx

Lines changed: 106 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import Link from 'next/link'
44
import { usePathname, useSearchParams } from 'next/navigation'
5+
import { useState } from 'react'
56
import { Button } from '@/components/ui/button'
67
import { useSidebarState, useAuthStore, useStoreHydration, useActionItemsStore } from '@/stores'
78
import { ChevronRight, Clock, LogOut, MessageSquare, Sparkles, Star, Target, Zap } from 'lucide-react'
@@ -18,31 +19,31 @@ export function Sidebar() {
1819
const { isConnected, logout } = useAuthStore()
1920

2021
// Action items state
21-
const { getCountByType, getTotalCount, loading } = useActionItemsStore()
22+
const { getCountByType, loading } = useActionItemsStore()
23+
24+
// Accordion states - MUI style
25+
const [actionRequiredOpen, setActionRequiredOpen] = useState(true)
26+
const [quickWinsOpen, setQuickWinsOpen] = useState(true)
2227

2328
// Get current tab from URL params
2429
const currentTab = searchParams?.get('tab') || 'assigned'
25-
const isDashboardPage = pathname ? pathname.startsWith('/dashboard') : false
30+
const isDashboardPage = pathname?.startsWith('/dashboard')
2631

27-
// Badge count helpers
32+
// Badge count helpers - Dinamik hesaplama
2833
const getBadgeCount = (type: 'assigned' | 'mentions' | 'stale' | 'goodFirstIssues' | 'easyFixes') => getCountByType(type)
29-
const getTotalActionCount = () => getTotalCount()
34+
const getActionRequiredTotal = () => getBadgeCount('assigned') + getBadgeCount('mentions') + getBadgeCount('stale')
35+
const getQuickWinsTotal = () => getBadgeCount('goodFirstIssues') + getBadgeCount('easyFixes')
3036

3137
// Show loading state in badges
3238
const getBadgeContent = (type: 'assigned' | 'mentions' | 'stale' | 'goodFirstIssues' | 'easyFixes') => {
3339
if (loading[type]) return '...'
3440
return getBadgeCount(type)
3541
}
3642

37-
// Debug logs
38-
console.log('Sidebar Debug:', { currentTab, pathname, isDashboardPage })
39-
40-
// Fixed logic - works for all tabs
43+
// Active states for highlighting (separate from accordion state)
4144
const isQuickWinsTab = currentTab === 'good-first-issues' || currentTab === 'easy-fixes'
4245
const isActionRequiredTab = ['assigned', 'mentions', 'stale'].includes(currentTab)
4346

44-
console.log('Tab States:', { isQuickWinsTab, isActionRequiredTab })
45-
4647
const handleLogout = () => {
4748
logout()
4849
}
@@ -58,11 +59,12 @@ export function Sidebar() {
5859
)}
5960

6061
<aside className={`
61-
fixed top-0 left-0 h-screen bg-sidebar border-r border-sidebar-border z-50 transform transition-transform duration-300 ease-in-out
62+
fixed top-0 left-0 bg-sidebar border-r border-sidebar-border z-50 transform transition-transform duration-300 ease-in-out
6263
${isOpen ? 'translate-x-0' : '-translate-x-full'}
63-
lg:translate-x-0 lg:static lg:z-auto lg:h-screen
64+
lg:translate-x-0
6465
flex flex-col
6566
w-80 min-w-[20rem] max-w-[20rem]
67+
h-screen
6668
`}>
6769

6870
{/* Header */}
@@ -79,117 +81,109 @@ export function Sidebar() {
7981
</button>
8082
</div>
8183

82-
{/* Scrollable Content */}
8384
<div className="flex-1 overflow-y-auto">
84-
{/* Navigation Menu with Collapsible */}
85-
<div className="flex-1 overflow-y-auto p-4">
85+
{/* Navigation Menu */}
86+
<div className="p-4">
8687
<nav className="space-y-2">
87-
{/* Action Required - Active with Collapsible */}
88-
<Collapsible open={true} onOpenChange={() => { }}>
89-
<CollapsibleTrigger asChild>
90-
<Link href="/dashboard" className={`
91-
flex items-center justify-between w-full px-3 py-2 rounded-lg transition-colors
92-
${isActionRequiredTab
93-
? 'bg-sidebar-accent text-sidebar-accent-foreground'
94-
: 'hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground'
95-
}
88+
{/* Action Required Accordion */}
89+
<Collapsible open={actionRequiredOpen} onOpenChange={setActionRequiredOpen}>
90+
<CollapsibleTrigger className={`
91+
flex items-center justify-between w-full px-3 py-2 rounded-lg transition-colors cursor-pointer
92+
${isActionRequiredTab
93+
? 'bg-sidebar-accent text-sidebar-accent-foreground'
94+
: 'hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground'
95+
}
9696
`}>
97-
<div className="flex items-center gap-3">
98-
<Zap className="w-5 h-5" />
99-
<span>Action Required</span>
100-
{getTotalActionCount() > 0 && (
101-
<Badge variant="destructive" className="ml-1 text-xs min-w-[1.25rem] h-5">
102-
{getTotalActionCount()}
103-
</Badge>
104-
)}
105-
</div>
106-
<ChevronRight className={`w-4 h-4 transition-transform ${isActionRequiredTab ? 'rotate-90' : ''}`} />
107-
</Link>
97+
<div className="flex items-center gap-3">
98+
<Zap className="w-5 h-5" />
99+
<span>Action Required</span>
100+
{getActionRequiredTotal() > 0 && (
101+
<Badge variant="destructive" className="ml-1 text-xs min-w-[1.25rem] h-5">
102+
{getActionRequiredTotal()}
103+
</Badge>
104+
)}
105+
</div>
106+
<ChevronRight className={`w-4 h-4 transition-transform ${actionRequiredOpen ? 'rotate-90' : ''}`} />
108107
</CollapsibleTrigger>
109108

110-
{/* Action Required sub-items - Always show space */}
109+
{/* Action Required sub-items */}
111110
<CollapsibleContent className="pl-8 space-y-1 mt-1">
112-
<div className={`transition-opacity duration-200 ${!isDashboardPage ? 'opacity-50 pointer-events-none' : 'opacity-100'}`}>
113-
<Link
114-
href="/dashboard?tab=assigned"
115-
className={`flex items-center gap-2 px-3 py-1.5 text-sm rounded transition-colors
116-
${currentTab === 'assigned'
117-
? 'bg-blue-50 text-blue-600 dark:bg-blue-900/20 dark:text-blue-400'
118-
: 'text-gray-600 hover:text-blue-600 hover:bg-gray-50 dark:hover:bg-gray-800'
119-
}`}
111+
<Link
112+
href="/dashboard?tab=assigned"
113+
className={`flex items-center gap-2 px-3 py-1.5 text-sm rounded transition-colors
114+
${currentTab === 'assigned'
115+
? 'bg-blue-50 text-blue-600 dark:bg-blue-900/20 dark:text-blue-400'
116+
: 'text-gray-600 hover:text-blue-600 hover:bg-gray-50 dark:hover:bg-gray-800'
117+
}`}
118+
>
119+
<Target className="w-4 h-4" />
120+
Assigned
121+
<Badge
122+
variant={getBadgeCount('assigned') > 0 ? "default" : "secondary"}
123+
className="ml-auto text-xs"
120124
>
121-
122-
<Target className="w-4 h-4" />
123-
Assigned
124-
<Badge
125-
variant={getBadgeCount('assigned') > 0 ? "default" : "secondary"}
126-
className="ml-auto text-xs"
127-
>
128-
{getBadgeContent('assigned')}
129-
</Badge>
130-
</Link>
131-
<Link
132-
href="/dashboard?tab=mentions"
133-
className={`flex items-center gap-2 px-3 py-1.5 text-sm rounded transition-colors
134-
${currentTab === 'mentions'
135-
? 'bg-blue-50 text-blue-600 dark:bg-blue-900/20 dark:text-blue-400'
136-
: 'text-gray-600 hover:text-blue-600 hover:bg-gray-50 dark:hover:bg-gray-800'
137-
}`}
125+
{getBadgeContent('assigned')}
126+
</Badge>
127+
</Link>
128+
<Link
129+
href="/dashboard?tab=mentions"
130+
className={`flex items-center gap-2 px-3 py-1.5 text-sm rounded transition-colors
131+
${currentTab === 'mentions'
132+
? 'bg-blue-50 text-blue-600 dark:bg-blue-900/20 dark:text-blue-400'
133+
: 'text-gray-600 hover:text-blue-600 hover:bg-gray-50 dark:hover:bg-gray-800'
134+
}`}
135+
>
136+
<MessageSquare className="w-4 h-4" />
137+
Mentions
138+
<Badge
139+
variant={getBadgeCount('mentions') > 0 ? "default" : "secondary"}
140+
className="ml-auto text-xs"
138141
>
139-
<MessageSquare className="w-4 h-4" />
140-
Mentions
141-
<Badge
142-
variant={getBadgeCount('mentions') > 0 ? "default" : "secondary"}
143-
className="ml-auto text-xs"
144-
>
145-
{getBadgeContent('mentions')}
146-
</Badge>
147-
</Link>
148-
<Link
149-
href="/dashboard?tab=stale"
150-
className={`flex items-center gap-2 px-3 py-1.5 text-sm rounded transition-colors
151-
${currentTab === 'stale'
152-
? 'bg-blue-50 text-blue-600 dark:bg-blue-900/20 dark:text-blue-400'
153-
: 'text-gray-600 hover:text-blue-600 hover:bg-gray-50 dark:hover:bg-gray-800'
154-
}`}
142+
{getBadgeContent('mentions')}
143+
</Badge>
144+
</Link>
145+
<Link
146+
href="/dashboard?tab=stale"
147+
className={`flex items-center gap-2 px-3 py-1.5 text-sm rounded transition-colors
148+
${currentTab === 'stale'
149+
? 'bg-blue-50 text-blue-600 dark:bg-blue-900/20 dark:text-blue-400'
150+
: 'text-gray-600 hover:text-blue-600 hover:bg-gray-50 dark:hover:bg-gray-800'
151+
}`}
152+
>
153+
<Clock className="w-4 h-4" />
154+
Stale PRs
155+
<Badge
156+
variant={getBadgeCount('stale') > 0 ? "destructive" : "secondary"}
157+
className="ml-auto text-xs"
155158
>
156-
<Clock className="w-4 h-4" />
157-
Stale PRs
158-
<Badge
159-
variant={getBadgeCount('stale') > 0 ? "destructive" : "secondary"}
160-
className="ml-auto text-xs"
161-
>
162-
{getBadgeContent('stale')}
163-
</Badge>
164-
</Link>
165-
</div>
159+
{getBadgeContent('stale')}
160+
</Badge>
161+
</Link>
166162
</CollapsibleContent>
167163
</Collapsible>
168164

169-
{/* Quick Wins - Always available */}
170-
<Collapsible open={true} onOpenChange={() => { }}>
171-
<CollapsibleTrigger asChild>
172-
<Link href="/dashboard?tab=good-first-issues" className={`
173-
flex items-center justify-between w-full px-3 py-2 rounded-lg transition-colors
174-
${isQuickWinsTab
175-
? 'bg-sidebar-accent text-sidebar-accent-foreground'
176-
: 'hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground'
177-
}
165+
{/* Quick Wins Accordion */}
166+
<Collapsible open={quickWinsOpen} onOpenChange={setQuickWinsOpen}>
167+
<CollapsibleTrigger className={`
168+
flex items-center justify-between w-full px-3 py-2 rounded-lg transition-colors cursor-pointer
169+
${isQuickWinsTab
170+
? 'bg-sidebar-accent text-sidebar-accent-foreground'
171+
: 'hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground'
172+
}
178173
`}>
179-
<div className="flex items-center gap-3">
180-
<Target className="w-5 h-5" />
181-
<span>Quick Wins</span>
182-
{(getBadgeCount('goodFirstIssues') + getBadgeCount('easyFixes')) > 0 && (
183-
<Badge variant="default" className="ml-1 text-xs min-w-[1.25rem] h-5">
184-
{getBadgeCount('goodFirstIssues') + getBadgeCount('easyFixes')}
185-
</Badge>
186-
)}
187-
</div>
188-
<ChevronRight className={`w-4 h-4 transition-transform ${isQuickWinsTab ? 'rotate-90' : ''}`} />
189-
</Link>
174+
<div className="flex items-center gap-3">
175+
<Target className="w-5 h-5" />
176+
<span>Quick Wins</span>
177+
{getQuickWinsTotal() > 0 && (
178+
<Badge variant="default" className="ml-1 text-xs min-w-[1.25rem] h-5">
179+
{getQuickWinsTotal()}
180+
</Badge>
181+
)}
182+
</div>
183+
<ChevronRight className={`w-4 h-4 transition-transform ${quickWinsOpen ? 'rotate-90' : ''}`} />
190184
</CollapsibleTrigger>
191185

192-
{/* Quick Wins sub-items - Always show space */}
186+
{/* Quick Wins sub-items */}
193187
<CollapsibleContent className="pl-8 space-y-1 mt-1">
194188
<Link
195189
href="/dashboard?tab=good-first-issues"
@@ -264,9 +258,9 @@ export function Sidebar() {
264258
</div>
265259
</div>
266260

267-
{/* Logout - Fixed at bottom */}
261+
{/* Logout - Fixed at bottom with fixed height */}
268262
{hasHydrated && isConnected && (
269-
<div className="p-4 border-t border-sidebar-border">
263+
<div className="p-4 border-t border-sidebar-border flex-shrink-0">
270264
<Button
271265
variant="ghost"
272266
size="sm"
@@ -289,9 +283,9 @@ export function SidebarToggle({ onClick }: { onClick: () => void }) {
289283
onClick={onClick}
290284
className="lg:hidden fixed top-4 left-4 z-50 bg-background p-2 rounded-lg shadow-lg border border-border hover:bg-accent transition-colors"
291285
>
292-
<svg className="w-6 h-6 text-foreground" fill="none" stroke="currentColor" viewBox="0 24 24">
286+
<svg className="w-6 h-6 text-foreground" fill="none" stroke="currentColor" viewBox="0 0 24 24">
293287
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
294288
</svg>
295289
</button>
296290
)
297-
}
291+
}

0 commit comments

Comments
 (0)