diff --git a/orchestrator/src/client/components/DiscoveredPanel.tsx b/orchestrator/src/client/components/DiscoveredPanel.tsx
index 02d5325..1ac58dc 100644
--- a/orchestrator/src/client/components/DiscoveredPanel.tsx
+++ b/orchestrator/src/client/components/DiscoveredPanel.tsx
@@ -30,6 +30,7 @@ import { Checkbox } from "@/components/ui/checkbox";
import { Separator } from "@/components/ui/separator";
import { cn } from "@/lib/utils";
import * as api from "../api";
+import { FitAssessment } from ".";
import type { Job, ResumeProjectCatalogItem } from "../../shared/types";
// ─────────────────────────────────────────────────────────────────────────────
@@ -61,46 +62,6 @@ const formatDate = (dateStr: string | null) => {
}
};
-const getScoreLabel = (
- score: number | null
-): { label: string; color: string; description: string } => {
- if (score == null)
- return {
- label: "Unscored",
- color: "text-muted-foreground",
- description: "No AI assessment yet",
- };
- if (score >= 80)
- return {
- label: "Excellent fit",
- color: "text-emerald-400",
- description: "Strong match for your profile",
- };
- if (score >= 65)
- return {
- label: "Good fit",
- color: "text-emerald-400/80",
- description: "Solid match worth considering",
- };
- if (score >= 50)
- return {
- label: "Possible fit",
- color: "text-amber-400",
- description: "Some relevant aspects",
- };
- if (score >= 35)
- return {
- label: "Weak fit",
- color: "text-orange-400",
- description: "Limited alignment",
- };
- return {
- label: "Poor fit",
- color: "text-rose-400",
- description: "May not be worth pursuing",
- };
-};
-
const stripHtml = (value: string) =>
value
.replace(/<[^>]*>/g, " ")
@@ -114,44 +75,6 @@ const sourceLabel: Record = {
ukvisajobs: "UK Visa Jobs",
};
-// ─────────────────────────────────────────────────────────────────────────────
-// Fit Summary Component (for Decide mode)
-// ─────────────────────────────────────────────────────────────────────────────
-
-interface FitSummaryProps {
- job: Job;
-}
-
-const FitSummary: React.FC = ({ job }) => {
- return (
-
- {/* AI Assessment */}
- {job.suitabilityReason && (
-
-
- AI Assessment
-
-
- {job.suitabilityReason}
-
-
- )}
-
- {/* No assessment fallback */}
- {!job.suitabilityReason && !job.suitabilityScore && (
-
-
- No AI assessment available yet.
-
-
- Review the job description to decide if you want to tailor.
-
-
- )}
-
- );
-};
-
// ─────────────────────────────────────────────────────────────────────────────
// Decide Mode Panel
// ─────────────────────────────────────────────────────────────────────────────
@@ -172,7 +95,6 @@ const DecideMode: React.FC = ({
const [showDescription, setShowDescription] = useState(false);
const deadline = formatDate(job.deadline);
const jobLink = job.applicationLink || job.jobUrl;
- const scoreInfo = getScoreLabel(job.suitabilityScore);
const description = useMemo(() => {
if (!job.jobDescription) return "No description available.";
@@ -195,25 +117,13 @@ const DecideMode: React.FC = ({
-
+
{sourceLabel[job.source]}
- {job.suitabilityScore != null && (
-
-
- {job.suitabilityScore}%
-
-
- )}
@@ -244,7 +154,7 @@ const DecideMode: React.FC = ({
{/* Fit Summary - the core content */}
-
+
{/* Collapsible full description */}
diff --git a/orchestrator/src/client/components/FitAssessment.tsx b/orchestrator/src/client/components/FitAssessment.tsx
new file mode 100644
index 0000000..aacb42a
--- /dev/null
+++ b/orchestrator/src/client/components/FitAssessment.tsx
@@ -0,0 +1,30 @@
+import React from "react";
+import { Sparkles } from "lucide-react";
+import { cn } from "@/lib/utils";
+import type { Job } from "../../shared/types";
+
+interface FitAssessmentProps {
+ job: Job;
+ className?: string;
+}
+
+export const FitAssessment: React.FC
= ({
+ job,
+ className,
+}) => {
+ if (!job.suitabilityReason) return null;
+
+ return (
+
+
+
+
+ Fit Assessment
+
+
+ {job.suitabilityReason}
+
+
+
+ );
+};
diff --git a/orchestrator/src/client/components/ReadyPanel.tsx b/orchestrator/src/client/components/ReadyPanel.tsx
index 9a3ebbf..5d9de59 100644
--- a/orchestrator/src/client/components/ReadyPanel.tsx
+++ b/orchestrator/src/client/components/ReadyPanel.tsx
@@ -22,7 +22,6 @@ import {
Briefcase,
Building2,
FolderKanban,
- Sparkles,
} from "lucide-react";
import { toast } from "sonner";
@@ -43,6 +42,7 @@ import {
import { cn } from "@/lib/utils";
import { copyTextToClipboard, formatJobForWebhook } from "@client/lib/jobCopy";
import * as api from "../api";
+import { FitAssessment } from ".";
import type { Job, ResumeProjectCatalogItem } from "../../shared/types";
interface ReadyPanelProps {
@@ -275,18 +275,7 @@ export const ReadyPanel: React.FC = ({
{/* Job identity - confirm this is the right role */}
- {/* AI Suitability Reasoning - Why you're a fit */}
- {job.suitabilityReason && (
-
-
-
- Fit Assessment
-
-
- {job.suitabilityReason}
-
-
- )}
+
{/* Tailored summary snippet - shows what's in the PDF */}
{tailoredSummary && (
diff --git a/orchestrator/src/client/components/index.ts b/orchestrator/src/client/components/index.ts
index 76fdba3..6478036 100644
--- a/orchestrator/src/client/components/index.ts
+++ b/orchestrator/src/client/components/index.ts
@@ -2,6 +2,7 @@ export { Header } from './Header';
export { Stats } from './Stats';
export { StatusBadge } from './StatusBadge';
export { ScoreIndicator } from './ScoreIndicator';
+export { FitAssessment } from './FitAssessment';
export { JobCard } from './JobCard';
export { JobTable } from './JobTable';
export { JobList } from './JobList';