diff --git a/src/apps/officer-web/Screens/Dashboard/Jobs/JobsPage.tsx b/src/apps/officer-web/Screens/Dashboard/Jobs/JobsPage.tsx
index c215b8eb..888fd074 100644
--- a/src/apps/officer-web/Screens/Dashboard/Jobs/JobsPage.tsx
+++ b/src/apps/officer-web/Screens/Dashboard/Jobs/JobsPage.tsx
@@ -1,4 +1,4 @@
-import { useState, useEffect } from 'react';
+import { useState, useEffect, type ReactNode } from 'react';
import { useParams, useNavigate } from 'react-router';
import { Search, CheckCircle2, AlertCircle, Clock, Loader2, StopCircle, AlertTriangle, Inbox } from 'lucide-react';
import { WorkspaceLayout } from 'officerdev';
@@ -34,6 +34,12 @@ const StatusIcon = ({ status }: { status: JobSummary['status'] }) => {
}
};
+const SectionLabel = ({ children }: { children: ReactNode }) => (
+
+ {children}
+
+);
+
// ── Left panel: the jobs list (polls so running/queued statuses stay fresh) ──
const JobsListPanel = () => {
const client = useClient();
@@ -59,10 +65,37 @@ const JobsListPanel = () => {
})
: jobs;
+ // Active = running first, then the FIFO queue (oldest pending on top — next to run). History = the
+ // rest (already newest-first from the API).
+ const active = [
+ ...filtered.filter((j) => j.status === 'running'),
+ ...filtered.filter((j) => j.status === 'pending').sort((a, b) => +new Date(a.createdAt) - +new Date(b.createdAt)),
+ ];
+ const history = filtered.filter((j) => j.status !== 'running' && j.status !== 'pending');
+
+ const renderRow = (job: JobSummary) => (
+
+ );
+
return (
-
+
Jobs
@@ -76,32 +109,34 @@ const JobsListPanel = () => {
-
- {isLoading &&
Loading…
}
- {!isLoading && filtered.length === 0 && (
-
- {search ? 'No jobs match' : 'No jobs yet'}
-
- )}
- {filtered.map((job) => (
-
);