Skip to content

Commit 363daa5

Browse files
feat: remove independent tasks page and add lazy loading (#12)
* Remove independent tasks list page As requested in issue #11, removing the separate tasks list page since task management will be handled on the main home page with lazy loading functionality. * feat: add lazy loading to main page tasks list - Enhanced SupabaseService.getTasks() with pagination support (limit/offset) - Added lazy loading state management (pagination, loading states) - Replaced "View All" button with "Load More" functionality - Updated task list to show all loaded tasks instead of slice(0, 10) - Added loading indicators and proper state management - Tasks now load 10 at a time with smooth pagination Addresses issue #11 by consolidating task management on main page with improved UX through lazy loading.
1 parent 55bf3f2 commit 363daa5

File tree

3 files changed

+131
-535
lines changed

3 files changed

+131
-535
lines changed

async-code-web/app/page.tsx

Lines changed: 120 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ export default function Home() {
4141
const [isLoading, setIsLoading] = useState(false);
4242
const [showNotification, setShowNotification] = useState(false);
4343
const [notificationMessage, setNotificationMessage] = useState("");
44+
const [isLoadingMore, setIsLoadingMore] = useState(false);
45+
const [hasMoreTasks, setHasMoreTasks] = useState(true);
46+
const [taskPage, setTaskPage] = useState(0);
47+
const TASKS_PER_PAGE = 10;
4448

4549
// Initialize GitHub token from localStorage
4650
useEffect(() => {
@@ -124,17 +128,50 @@ export default function Home() {
124128
}
125129
};
126130

127-
const loadTasks = async () => {
131+
const loadTasks = async (reset: boolean = true) => {
128132
if (!user?.id) return;
129133

130134
try {
131-
const taskData = await SupabaseService.getTasks();
132-
setTasks(taskData);
135+
const taskData = await SupabaseService.getTasks(undefined, {
136+
limit: TASKS_PER_PAGE,
137+
offset: 0
138+
});
139+
140+
if (reset) {
141+
setTasks(taskData);
142+
setTaskPage(0);
143+
setHasMoreTasks(taskData.length === TASKS_PER_PAGE);
144+
}
133145
} catch (error) {
134146
console.error('Error loading tasks:', error);
135147
}
136148
};
137149

150+
const loadMoreTasks = async () => {
151+
if (!user?.id || isLoadingMore || !hasMoreTasks) return;
152+
153+
try {
154+
setIsLoadingMore(true);
155+
const nextPage = taskPage + 1;
156+
const taskData = await SupabaseService.getTasks(undefined, {
157+
limit: TASKS_PER_PAGE,
158+
offset: nextPage * TASKS_PER_PAGE
159+
});
160+
161+
if (taskData.length > 0) {
162+
setTasks(prev => [...prev, ...taskData]);
163+
setTaskPage(nextPage);
164+
setHasMoreTasks(taskData.length === TASKS_PER_PAGE);
165+
} else {
166+
setHasMoreTasks(false);
167+
}
168+
} catch (error) {
169+
console.error('Error loading more tasks:', error);
170+
} finally {
171+
setIsLoadingMore(false);
172+
}
173+
};
174+
138175
const handleStartTask = async () => {
139176
if (!prompt.trim() || !githubToken.trim()) {
140177
toast.error('Please provide both a prompt and GitHub token');
@@ -493,76 +530,106 @@ export default function Home() {
493530
<CardHeader>
494531
<div className="flex items-center justify-between">
495532
<CardTitle className="text-lg">All Tasks</CardTitle>
496-
<Link href="/tasks">
497-
<Button variant="outline" size="sm">View All</Button>
498-
</Link>
533+
<div className="text-sm text-slate-500">
534+
{tasks.length} tasks loaded
535+
</div>
499536
</div>
500537
<CardDescription>
501538
Track all your automation tasks
502539
</CardDescription>
503540
</CardHeader>
504-
<CardContent className="space-y-3 max-h-[500px] overflow-y-auto">
541+
<CardContent className="space-y-3">
505542
{tasks.length === 0 ? (
506543
<div className="text-center py-8 text-slate-500">
507544
<Code2 className="w-8 h-8 mx-auto mb-2 opacity-50" />
508545
<p className="text-sm">No tasks yet</p>
509546
<p className="text-xs">Start your first automation above</p>
510547
</div>
511548
) : (
512-
tasks.slice(0, 10).map((task) => (
513-
<div key={task.id} className="flex items-center justify-between p-3 bg-slate-50 rounded-lg hover:bg-slate-100 transition-colors">
514-
<div className="flex-1 min-w-0">
515-
<div className="flex items-center gap-2 mb-1">
516-
<TaskStatusBadge status={task.status || ''} />
517-
{task.pr_url && task.pr_number && (
518-
<PRStatusBadge
519-
prUrl={task.pr_url}
520-
prNumber={task.pr_number}
521-
prBranch={task.pr_branch}
522-
variant="badge"
523-
size="sm"
524-
/>
525-
)}
526-
<span className="text-xs text-slate-500 flex items-center gap-1">
527-
#{task.id}{getAgentIcon(task.agent || '')} {task.agent?.toUpperCase()}
528-
</span>
549+
<>
550+
<div className="space-y-3 max-h-[500px] overflow-y-auto">
551+
{tasks.map((task) => (
552+
<div key={task.id} className="flex items-center justify-between p-3 bg-slate-50 rounded-lg hover:bg-slate-100 transition-colors">
553+
<div className="flex-1 min-w-0">
554+
<div className="flex items-center gap-2 mb-1">
555+
<TaskStatusBadge status={task.status || ''} />
556+
{task.pr_url && task.pr_number && (
557+
<PRStatusBadge
558+
prUrl={task.pr_url}
559+
prNumber={task.pr_number}
560+
prBranch={task.pr_branch}
561+
variant="badge"
562+
size="sm"
563+
/>
564+
)}
565+
<span className="text-xs text-slate-500 flex items-center gap-1">
566+
#{task.id}{getAgentIcon(task.agent || '')} {task.agent?.toUpperCase()}
567+
</span>
568+
</div>
569+
<p className="text-sm font-medium text-slate-900 truncate">
570+
{(task.chat_messages as any[])?.[0]?.content?.substring(0, 50) || ''}...
571+
</p>
572+
<div className="flex items-center gap-2 text-xs text-slate-500 mt-1">
573+
{task.project ? (
574+
<>
575+
<FolderGit2 className="w-3 h-3" />
576+
{task.project.repo_name}
577+
</>
578+
) : (
579+
<>
580+
<Github className="w-3 h-3" />
581+
Custom
582+
</>
583+
)}
584+
<span></span>
585+
<span>{new Date(task.created_at || '').toLocaleDateString()}</span>
586+
</div>
587+
</div>
588+
<div className="flex items-center gap-2">
589+
{task.status === "completed" && (
590+
<CheckCircle className="w-4 h-4 text-green-600" />
591+
)}
592+
{task.status === "running" && (
593+
<div className="animate-spin">
594+
<AlertCircle className="w-4 h-4 text-blue-600" />
595+
</div>
596+
)}
597+
<Link href={`/tasks/${task.id}`}>
598+
<Button variant="ghost" size="sm">
599+
<Eye className="w-3 h-3" />
600+
</Button>
601+
</Link>
602+
</div>
529603
</div>
530-
<p className="text-sm font-medium text-slate-900 truncate">
531-
{(task.chat_messages as any[])?.[0]?.content?.substring(0, 50) || ''}...
532-
</p>
533-
<div className="flex items-center gap-2 text-xs text-slate-500 mt-1">
534-
{task.project ? (
604+
))}
605+
</div>
606+
607+
{/* Load More Button */}
608+
{hasMoreTasks && (
609+
<div className="flex justify-center pt-4">
610+
<Button
611+
onClick={loadMoreTasks}
612+
disabled={isLoadingMore}
613+
variant="outline"
614+
className="gap-2"
615+
>
616+
{isLoadingMore ? (
535617
<>
536-
<FolderGit2 className="w-3 h-3" />
537-
{task.project.repo_name}
618+
<div className="animate-spin">
619+
<AlertCircle className="w-4 h-4" />
620+
</div>
621+
Loading...
538622
</>
539623
) : (
540624
<>
541-
<Github className="w-3 h-3" />
542-
Custom
625+
<Plus className="w-4 h-4" />
626+
Load More
543627
</>
544628
)}
545-
<span></span>
546-
<span>{new Date(task.created_at || '').toLocaleDateString()}</span>
547-
</div>
629+
</Button>
548630
</div>
549-
<div className="flex items-center gap-2">
550-
{task.status === "completed" && (
551-
<CheckCircle className="w-4 h-4 text-green-600" />
552-
)}
553-
{task.status === "running" && (
554-
<div className="animate-spin">
555-
<AlertCircle className="w-4 h-4 text-blue-600" />
556-
</div>
557-
)}
558-
<Link href={`/tasks/${task.id}`}>
559-
<Button variant="ghost" size="sm">
560-
<Eye className="w-3 h-3" />
561-
</Button>
562-
</Link>
563-
</div>
564-
</div>
565-
))
631+
)}
632+
</>
566633
)}
567634
</CardContent>
568635
</Card>

0 commit comments

Comments
 (0)