diff --git a/orchestrator/src/client/pages/OrchestratorPage.tsx b/orchestrator/src/client/pages/OrchestratorPage.tsx
index 9f3a9b2..6ddff5d 100644
--- a/orchestrator/src/client/pages/OrchestratorPage.tsx
+++ b/orchestrator/src/client/pages/OrchestratorPage.tsx
@@ -8,14 +8,12 @@ import {
Calendar,
CheckCircle2,
ChevronDown,
- Clock,
Copy,
DollarSign,
Edit2,
ExternalLink,
FileText,
Filter,
- GraduationCap,
Loader2,
MapPin,
MoreHorizontal,
@@ -47,7 +45,6 @@ import {
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Input } from "@/components/ui/input";
-import { Separator } from "@/components/ui/separator";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Textarea } from "@/components/ui/textarea";
import { cn } from "@/lib/utils";
@@ -252,31 +249,39 @@ const jobMatchesQuery = (job: Job, query: string) => {
const stripHtml = (value: string) => value.replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim();
+// Default fallback for unknown statuses
+const defaultStatusToken = {
+ label: "Unknown",
+ badge: "border-muted-foreground/20 bg-muted/30 text-muted-foreground",
+ dot: "bg-muted-foreground",
+};
+
+// Subdued status pill for inspector panel - not competing with list
const StatusPill: React.FC<{ status: JobStatus }> = ({ status }) => {
- const tokens = statusTokens[status];
+ const tokens = statusTokens[status] ?? defaultStatusToken;
return (
-
+
{tokens.label}
);
};
+// Compact score meter for inspector panel
const ScoreMeter: React.FC<{ score: number | null }> = ({ score }) => {
if (score == null) {
- return Not scored;
+ return —;
}
return (
-
-
+
+
@@ -693,15 +698,9 @@ export const OrchestratorPage: React.FC = () => {
-
+
-
-
Pipeline console
-
- Focused workspace with a split list/detail layout and icon-led actions.
-
-
-
{totalJobs} total jobs
+
Jobs
{isPipelineRunning && (
@@ -710,58 +709,55 @@ export const OrchestratorPage: React.FC = () => {
)}
-
- {[
- { label: "Discovered", value: stats.discovered },
- { label: "Processing", value: stats.processing },
- { label: "Ready", value: stats.ready },
- { label: "Applied", value: stats.applied },
- { label: "Skipped", value: stats.skipped },
- { label: "Expired", value: stats.expired },
- ].map((item, index) => (
-
0 && "border-t border-border/60 sm:border-t-0 sm:border-l",
- index > 0 && index % 3 === 0 && "sm:border-l-0 sm:border-t",
- index > 2 && "lg:border-t-0 lg:border-l",
- )}
- >
- {item.label}
- {item.value}
-
- ))}
+ {/* Compact metrics summary - demoted visual weight */}
+
+ {totalJobs} jobs total
+ •
+ {stats.ready} ready
+ •
+ {stats.discovered + stats.processing} pending
+ •
+ {stats.applied} applied
+ {(stats.skipped > 0 || stats.expired > 0) && (
+ <>
+ •
+ {stats.skipped + stats.expired} archived
+ >
+ )}
-
+
+ {/* Main content: tabs/filters -> list/detail */}
+
setActiveTab(value as FilterTab)}>
{tabs.map((tab) => (
-
+
{tab.label}
- ({counts[tab.id]})
+ {counts[tab.id] > 0 && (
+ {counts[tab.id]}
+ )}
))}
-
-
+
+
setSearchQuery(event.target.value)}
- placeholder="Filter jobs..."
- className="pl-9"
+ placeholder="Search..."
+ className="h-8 pl-8 text-sm"
/>
-
@@ -783,9 +779,9 @@ export const OrchestratorPage: React.FC = () => {
-
-
- Sort: {sortLabels[sort.key]}
+
+
+ {sortLabels[sort.key]}
@@ -820,19 +816,18 @@ export const OrchestratorPage: React.FC = () => {
-
- {activeResultsCount} jobs
-
-
-
-
- {isLoading && jobs.length === 0 ? (
-
-
-
Loading jobs...
+
+ {/* List/Detail grid - directly under tabs, no extra section */}
+
+ {/* Primary region: Job list with highest visual weight */}
+
+ {isLoading && jobs.length === 0 ? (
+
) : activeJobs.length === 0 ? (
@@ -842,51 +837,61 @@ export const OrchestratorPage: React.FC = () => {
) : (
-
+
{activeJobs.map((job) => {
const isSelected = job.id === selectedJobId;
+ const hasScore = job.suitabilityScore != null;
+ const statusToken = statusTokens[job.status] ?? defaultStatusToken;
return (
setSelectedJobId(job.id)}
className={cn(
- "flex w-full items-start gap-4 px-4 py-3 text-left transition-colors",
- isSelected ? "bg-muted/40" : "hover:bg-muted/30",
+ "flex w-full items-center gap-3 px-4 py-3 text-left transition-colors",
+ isSelected
+ ? "bg-primary/5 border-l-2 border-l-primary"
+ : "hover:bg-muted/20 border-l-2 border-l-transparent",
)}
aria-pressed={isSelected}
>
-
-
-
{job.title}
-
{job.employer}
-
- {job.location && (
-
-
- {job.location}
-
- )}
- {job.deadline && (
-
-
- {formatDate(job.deadline)}
-
- )}
- {job.discoveredAt && (
-
-
- Discovered {formatDateTime(job.discoveredAt)}
-
- )}
+ {/* Single status indicator: subtle dot */}
+
+
+ {/* Primary content: title strongest, company secondary */}
+
+
+ {job.title}
+
+
+ {job.employer}
+ {job.location && {job.location}}
-
-
-
- {statusTokens[job.status].label}
-
-
+
+ {/* Single triage cue: score only (status shown via dot) */}
+ {hasScore && (
+
+ = 70 ? "text-emerald-400/90" :
+ job.suitabilityScore! >= 50 ? "text-foreground/60" :
+ "text-muted-foreground/60"
+ )}>
+ {job.suitabilityScore}
+
+
+ )}
);
})}
@@ -894,115 +899,102 @@ export const OrchestratorPage: React.FC = () => {
)}
-
+ {/* Inspector panel: visually subordinate to list */}
+
{!selectedJob ? (
-
-
Select a job
-
Pick a job from the list to see details here.
+
+
No job selected
+
Select a job to view details
) : (
-
-
+
+ {/* Detail header: lighter weight than list items */}
+
-
{selectedJob.title}
-
{selectedJob.employer}
-
-
-
- {sourceLabel[selectedJob.source]}
-
-
+
{selectedJob.title}
+
{selectedJob.employer}
+
+ {sourceLabel[selectedJob.source]}
+
-
+ {/* Tertiary metadata - subdued */}
+
{selectedJob.location && (
-
+
{selectedJob.location}
)}
{selectedDeadline && (
-
+
{selectedDeadline}
)}
- {selectedDiscoveredAt && (
-
-
- Discovered {selectedDiscoveredAt}
-
- )}
{selectedJob.salary && (
-
+
{selectedJob.salary}
)}
- {selectedJob.degreeRequired && (
-
-
- {selectedJob.degreeRequired}
-
- )}
-
-
Suitability
+ {/* Status and score: single line, subdued */}
+
+
-
-
-
-
+
+
-
- View job
+
+ View
{showReadyPdf &&
(selectedHasPdf ? (
-
+
-
- View PDF
+
+ PDF
) : (
-
-
- View PDF
+
+
+ PDF
))}
{showGeneratePdf && (
handleProcess(selectedJob.id)}
disabled={!canProcess || isProcessingSelected}
>
{isProcessingSelected ? (
-
+
) : (
-
+
)}
- {isProcessingSelected ? "Generating..." : "Generate PDF"}
+ {isProcessingSelected ? "Generating..." : "Generate"}
)}
{canApply && (
handleApply(selectedJob.id)}
>
-
- Mark applied
+
+ Applied
)}
@@ -1076,69 +1068,55 @@ export const OrchestratorPage: React.FC = () => {
setDetailTab(value as typeof detailTab)}>
-
- Overview
- Tailoring
- Description
+
+ Overview
+ Tailoring
+ Description
-
-
- {selectedJob.suitabilityReason
- ? `"${selectedJob.suitabilityReason}"`
- : "No suitability summary yet."}
-
+
+ {selectedJob.suitabilityReason && (
+
+ "{selectedJob.suitabilityReason}"
+
+ )}
-
+
-
Discipline
-
{selectedJob.disciplines || "Not set"}
+
Discipline
+
{selectedJob.disciplines || "—"}
-
Job function
-
{selectedJob.jobFunction || "Not set"}
+
Function
+
{selectedJob.jobFunction || "—"}
-
Job level
-
{selectedJob.jobLevel || "Not set"}
+
Level
+
{selectedJob.jobLevel || "—"}
-
Job type
-
{selectedJob.jobType || "Not set"}
+
Type
+
{selectedJob.jobType || "—"}
-
-
-
-
-
- Description Preview
-
-
{
- setDetailTab("description");
- setIsEditingDescription(true);
- }}
- >
-
- Edit full JD
-
-
-
- {description}
-
-
+ setDetailTab("description")}
>
- Read full description
-
+ {description}
+
+
+ setDetailTab("description")}
+ >
+ View full description →
+
+
@@ -1267,6 +1245,7 @@ export const OrchestratorPage: React.FC = () => {
)}
+
>