Skip to content

Commit 886e53c

Browse files
Merge pull request #49 from Evolvus/codex/split-large-components-into-subcomponents
Refactor large components into subcomponents
2 parents d573a88 + aa3fc1c commit 886e53c

5 files changed

Lines changed: 634 additions & 624 deletions

File tree

src/App.jsx

Lines changed: 16 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@
22
import React, { useEffect, useMemo, useState, Suspense, lazy } from "react";
33
import { Routes, Route, Navigate } from "react-router-dom";
44
import { Card, CardHeader, CardContent, CardTitle } from "./components/ui/card";
5-
import { Button } from "./components/ui/button";
6-
import { Input } from "./components/ui/input";
7-
import { Loader2, Github, RefreshCcw, ShieldQuestion, Sun, Moon, Monitor, Maximize2, Minimize2, ExternalLink } from "lucide-react";
5+
import { Loader2, ShieldQuestion } from "lucide-react";
86
import { githubGraphQL, ORG_REPOS_ISSUES, fetchProjectsWithStatus, fetchIssueTypes } from "./api/github";
97
import useAppStore from "./store";
8+
import AppHeader from "./components/AppHeader";
109

1110
// Import components
12-
const Navigation = lazy(() => import("./components/Navigation"));
1311
const Dashboard = lazy(() => import("./components/Dashboard"));
1412
const ByAssignee = lazy(() => import("./components/ByAssignee"));
1513
const ByTags = lazy(() => import("./components/ByTags"));
@@ -269,42 +267,20 @@ export default function App() {
269267
}, [issueTypes]);
270268

271269
return (
272-
<div className="min-h-screen bg-gray-50">
273-
<header className="sticky top-0 z-10 bg-white/80 backdrop-blur shadow-sm">
274-
<div className="max-w-7xl mx-auto px-4 py-4">
275-
<div className="flex items-center gap-3 mb-4">
276-
<Github className="w-6 h-6" />
277-
<h1 className="text-xl font-semibold">GitHub Issues Manager</h1>
278-
<a
279-
href="https://github.com/evolvus/github-issue-manager"
280-
target="_blank"
281-
rel="noopener noreferrer"
282-
className="text-sm text-blue-600 hover:underline flex items-center gap-1"
283-
title="View Source Code"
284-
>
285-
<Github className="w-4 h-4" />
286-
</a>
287-
<div className="ml-auto flex items-center gap-2 w-full sm:w-auto">
288-
<Input placeholder="Organization (e.g. vercel)" value={org} onChange={e=>setOrg(e.target.value)} className="w-44" />
289-
<Input placeholder="Personal Access Token" type="password" autoComplete="off" value={token} onChange={e=>setToken(e.target.value)} className="w-64" />
290-
<Button className="bg-black text-white" onClick={loadData} disabled={loading || !org || !token}>
291-
{loading ? (<><Loader2 className="w-4 h-4 animate-spin"/><span>Loading</span></>) : (<><RefreshCcw className="w-4 h-4"/><span>Load</span></>)}
292-
</Button>
293-
<button onClick={cycleTheme} title={`Theme: ${theme}`} className="p-2 border rounded">
294-
{theme === "dark" ? <Moon className="w-4 h-4"/> : theme === "light" ? <Sun className="w-4 h-4"/> : <Monitor className="w-4 h-4"/>}
295-
</button>
296-
<button onClick={toggleDensity} title={`Density: ${density}`} className="p-2 border rounded">
297-
{density === "compact" ? <Minimize2 className="w-4 h-4"/> : <Maximize2 className="w-4 h-4"/>}
298-
</button>
299-
</div>
300-
</div>
301-
{sidebarOpen && (
302-
<Suspense fallback={<Loader2 className="w-4 h-4 animate-spin" />}>
303-
<Navigation />
304-
</Suspense>
305-
)}
306-
</div>
307-
</header>
270+
<div className="min-h-screen bg-gray-50">
271+
<AppHeader
272+
org={org}
273+
setOrg={setOrg}
274+
token={token}
275+
setToken={setToken}
276+
loadData={loadData}
277+
loading={loading}
278+
cycleTheme={cycleTheme}
279+
toggleDensity={toggleDensity}
280+
theme={theme}
281+
density={density}
282+
sidebarOpen={sidebarOpen}
283+
/>
308284

309285
<main className="max-w-7xl mx-auto px-4 py-6">
310286
{error && (

src/components/AppHeader.jsx

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import React, { Suspense, lazy } from "react";
2+
import { Github, Loader2, RefreshCcw, Sun, Moon, Monitor, Maximize2, Minimize2 } from "lucide-react";
3+
import { Button } from "./ui/button";
4+
import { Input } from "./ui/input";
5+
6+
const Navigation = lazy(() => import("./Navigation"));
7+
8+
export default function AppHeader({
9+
org,
10+
setOrg,
11+
token,
12+
setToken,
13+
loadData,
14+
loading,
15+
cycleTheme,
16+
toggleDensity,
17+
theme,
18+
density,
19+
sidebarOpen,
20+
}) {
21+
return (
22+
<header className="sticky top-0 z-10 bg-white/80 backdrop-blur shadow-sm">
23+
<div className="max-w-7xl mx-auto px-4 py-4">
24+
<div className="flex items-center gap-3 mb-4">
25+
<Github className="w-6 h-6" />
26+
<h1 className="text-xl font-semibold">GitHub Issues Manager</h1>
27+
<a
28+
href="https://github.com/evolvus/github-issue-manager"
29+
target="_blank"
30+
rel="noopener noreferrer"
31+
className="text-sm text-blue-600 hover:underline flex items-center gap-1"
32+
title="View Source Code"
33+
>
34+
<Github className="w-4 h-4" />
35+
</a>
36+
<div className="ml-auto flex items-center gap-2 w-full sm:w-auto">
37+
<Input
38+
placeholder="Organization (e.g. vercel)"
39+
value={org}
40+
onChange={(e) => setOrg(e.target.value)}
41+
className="w-44"
42+
/>
43+
<Input
44+
placeholder="Personal Access Token"
45+
type="password"
46+
autoComplete="off"
47+
value={token}
48+
onChange={(e) => setToken(e.target.value)}
49+
className="w-64"
50+
/>
51+
<Button className="bg-black text-white" onClick={loadData} disabled={loading || !org || !token}>
52+
{loading ? (
53+
<>
54+
<Loader2 className="w-4 h-4 animate-spin" />
55+
<span>Loading</span>
56+
</>
57+
) : (
58+
<>
59+
<RefreshCcw className="w-4 h-4" />
60+
<span>Load</span>
61+
</>
62+
)}
63+
</Button>
64+
<button onClick={cycleTheme} title={`Theme: ${theme}`} className="p-2 border rounded">
65+
{theme === "dark" ? (
66+
<Moon className="w-4 h-4" />
67+
) : theme === "light" ? (
68+
<Sun className="w-4 h-4" />
69+
) : (
70+
<Monitor className="w-4 h-4" />
71+
)}
72+
</button>
73+
<button onClick={toggleDensity} title={`Density: ${density}`} className="p-2 border rounded">
74+
{density === "compact" ? (
75+
<Minimize2 className="w-4 h-4" />
76+
) : (
77+
<Maximize2 className="w-4 h-4" />
78+
)}
79+
</button>
80+
</div>
81+
</div>
82+
{sidebarOpen && (
83+
<Suspense fallback={<Loader2 className="w-4 h-4 animate-spin" />}>
84+
<Navigation />
85+
</Suspense>
86+
)}
87+
</div>
88+
</header>
89+
);
90+
}
91+

src/components/MilestoneTabs.jsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import React from "react";
2+
3+
export default function MilestoneTabs({ sprints, activeTab, setActiveTab }) {
4+
return (
5+
<div className="mb-6">
6+
<div className="mb-4">
7+
<h3 className="text-lg font-semibold text-gray-900">Milestones</h3>
8+
</div>
9+
<div className="flex gap-2 overflow-x-auto pb-2">
10+
{sprints.map((sp) => (
11+
<button
12+
key={sp.id}
13+
onClick={() => setActiveTab(sp.id)}
14+
className={`flex-shrink-0 px-4 py-2 rounded-lg border transition-all duration-200 ${
15+
activeTab === sp.id
16+
? "bg-blue-50 border-blue-200 shadow-sm text-blue-700"
17+
: "bg-white border-gray-200 hover:bg-gray-50 hover:border-gray-300 text-gray-700"
18+
}`}
19+
>
20+
<span className="text-sm font-medium whitespace-nowrap">{sp.title}</span>
21+
</button>
22+
))}
23+
</div>
24+
</div>
25+
);
26+
}
27+

0 commit comments

Comments
 (0)