allow manual editing JD

This commit is contained in:
DaKheera47
2026-01-11 00:31:07 +00:00
parent 0ec38773b5
commit f0b4d278ae
3 changed files with 155 additions and 33 deletions
@@ -10,6 +10,7 @@ import {
Copy, Copy,
DollarSign, DollarSign,
Download, Download,
Edit2,
ExternalLink, ExternalLink,
GraduationCap, GraduationCap,
Loader2, Loader2,
@@ -32,6 +33,7 @@ interface JobCardProps {
onApply: (id: string) => void | Promise<void>; onApply: (id: string) => void | Promise<void>;
onReject: (id: string) => void | Promise<void>; onReject: (id: string) => void | Promise<void>;
onProcess: (id: string) => void | Promise<void>; onProcess: (id: string) => void | Promise<void>;
onEditDescription?: (id: string) => void;
isProcessing: boolean; isProcessing: boolean;
highlightedJobId?: string | null; highlightedJobId?: string | null;
onHighlightChange?: (jobId: string | null) => void; onHighlightChange?: (jobId: string | null) => void;
@@ -78,6 +80,7 @@ export const JobCard: React.FC<JobCardProps> = ({
onApply, onApply,
onReject, onReject,
onProcess, onProcess,
onEditDescription,
isProcessing, isProcessing,
highlightedJobId, highlightedJobId,
onHighlightChange, onHighlightChange,
@@ -184,6 +187,13 @@ export const JobCard: React.FC<JobCardProps> = ({
Copy info Copy info
</Button> </Button>
{onEditDescription && (
<Button variant="outline" size="sm" onClick={() => onEditDescription(job.id)}>
<Edit2 className="mr-2 h-4 w-4" />
Edit JD
</Button>
)}
{onHighlightChange && ( {onHighlightChange && (
<Button <Button
variant="outline" variant="outline"
@@ -10,6 +10,7 @@ import {
CheckCircle2, CheckCircle2,
Copy, Copy,
Download, Download,
Edit2,
ExternalLink, ExternalLink,
MoreHorizontal, MoreHorizontal,
RefreshCcw, RefreshCcw,
@@ -58,6 +59,7 @@ export interface JobTableProps {
onApply: (id: string) => void | Promise<void>; onApply: (id: string) => void | Promise<void>;
onReject: (id: string) => void | Promise<void>; onReject: (id: string) => void | Promise<void>;
onProcess: (id: string) => void | Promise<void>; onProcess: (id: string) => void | Promise<void>;
onEditDescription?: (id: string) => void;
processingJobId: string | null; processingJobId: string | null;
highlightedJobId?: string | null; highlightedJobId?: string | null;
onHighlightChange?: (jobId: string | null) => void; onHighlightChange?: (jobId: string | null) => void;
@@ -145,6 +147,7 @@ export const JobTable: React.FC<JobTableProps> = ({
onApply, onApply,
onReject, onReject,
onProcess, onProcess,
onEditDescription,
processingJobId, processingJobId,
highlightedJobId, highlightedJobId,
onHighlightChange, onHighlightChange,
@@ -304,6 +307,13 @@ export const JobTable: React.FC<JobTableProps> = ({
Copy info Copy info
</DropdownMenuItem> </DropdownMenuItem>
{onEditDescription && (
<DropdownMenuItem onSelect={() => onEditDescription(job.id)}>
<Edit2 className="mr-2 h-4 w-4" />
Edit description
</DropdownMenuItem>
)}
{onHighlightChange && ( {onHighlightChange && (
<DropdownMenuItem <DropdownMenuItem
onSelect={() => onHighlightChange(isHighlighted ? null : job.id)} onSelect={() => onHighlightChange(isHighlighted ? null : job.id)}
@@ -11,6 +11,7 @@ import {
Clock, Clock,
Copy, Copy,
DollarSign, DollarSign,
Edit2,
ExternalLink, ExternalLink,
FileText, FileText,
Filter, Filter,
@@ -20,6 +21,7 @@ import {
MoreHorizontal, MoreHorizontal,
Play, Play,
RefreshCcw, RefreshCcw,
Save,
Search, Search,
Settings, Settings,
Sparkles, Sparkles,
@@ -1016,6 +1018,15 @@ export const OrchestratorPage: React.FC = () => {
: "Generate PDF"} : "Generate PDF"}
</DropdownMenuItem> </DropdownMenuItem>
)} )}
<DropdownMenuItem
onSelect={() => {
setDetailTab("description");
setIsEditingDescription(true);
}}
>
<Edit2 className="mr-2 h-4 w-4" />
Edit description
</DropdownMenuItem>
<DropdownMenuItem onSelect={() => void handleCopyInfo(selectedJob)}> <DropdownMenuItem onSelect={() => void handleCopyInfo(selectedJob)}>
<Copy className="mr-2 h-4 w-4" /> <Copy className="mr-2 h-4 w-4" />
Copy info Copy info
@@ -1088,6 +1099,39 @@ export const OrchestratorPage: React.FC = () => {
<div className="font-medium">{selectedJob.jobType || "Not set"}</div> <div className="font-medium">{selectedJob.jobType || "Not set"}</div>
</div> </div>
</div> </div>
<Separator className="my-2" />
<div className="space-y-2">
<div className="flex items-center justify-between">
<div className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
Description Preview
</div>
<Button
variant="link"
size="sm"
className="h-auto p-0 text-xs text-primary"
onClick={() => {
setDetailTab("description");
setIsEditingDescription(true);
}}
>
<Edit2 className="mr-1 h-3 w-3" />
Edit full JD
</Button>
</div>
<div className="rounded-md border border-border/40 bg-muted/5 p-3 text-xs text-muted-foreground line-clamp-6 whitespace-pre-wrap leading-relaxed">
{description}
</div>
<Button
variant="ghost"
size="sm"
className="w-full h-8 text-xs text-muted-foreground"
onClick={() => setDetailTab("description")}
>
Read full description
</Button>
</div>
</TabsContent> </TabsContent>
<TabsContent value="tailoring" className="pt-3"> <TabsContent value="tailoring" className="pt-3">
@@ -1107,45 +1151,103 @@ export const OrchestratorPage: React.FC = () => {
<div className="text-xs font-semibold uppercase tracking-wide text-muted-foreground"> <div className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
Job description Job description
</div> </div>
<DropdownMenu> <div className="flex items-center gap-1">
<DropdownMenuTrigger asChild> {!isEditingDescription ? (
<Button size="icon" variant="ghost" aria-label="Description actions"> <Button
<MoreHorizontal className="h-4 w-4" /> size="sm"
variant="ghost"
onClick={() => setIsEditingDescription(true)}
className="h-8 px-2 text-xs"
>
<Edit2 className="mr-1.5 h-3.5 w-3.5" />
Edit
</Button> </Button>
</DropdownMenuTrigger> ) : (
<DropdownMenuContent align="end"> <>
{!isEditingDescription ? ( <Button
<DropdownMenuItem onSelect={() => setIsEditingDescription(true)}> size="sm"
Edit description variant="ghost"
onClick={() => {
setIsEditingDescription(false);
setEditedDescription(selectedJob.jobDescription || "");
}}
className="h-8 px-2 text-xs text-muted-foreground"
disabled={isSavingDescription}
>
Cancel
</Button>
<Button
size="sm"
variant="secondary"
onClick={handleSaveDescription}
className="h-8 px-3 text-xs"
disabled={isSavingDescription}
>
{isSavingDescription ? (
<Loader2 className="mr-1.5 h-3.5 w-3.5 animate-spin" />
) : (
<Save className="mr-1.5 h-3.5 w-3.5" />
)}
Save Changes
</Button>
</>
)}
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button size="icon" variant="ghost" className="h-8 w-8" aria-label="Description actions">
<MoreHorizontal className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem
onSelect={() => {
void copyTextToClipboard(selectedJob.jobDescription || "");
toast.success("Copied raw description");
}}
>
<Copy className="mr-2 h-4 w-4" />
Copy raw text
</DropdownMenuItem> </DropdownMenuItem>
) : ( </DropdownMenuContent>
<> </DropdownMenu>
<DropdownMenuItem onSelect={handleSaveDescription} disabled={isSavingDescription}> </div>
{isSavingDescription ? "Saving..." : "Save changes"}
</DropdownMenuItem>
<DropdownMenuItem
onSelect={() => {
setIsEditingDescription(false);
setEditedDescription(selectedJob.jobDescription || "");
}}
disabled={isSavingDescription}
>
Cancel edit
</DropdownMenuItem>
</>
)}
</DropdownMenuContent>
</DropdownMenu>
</div> </div>
<div className="rounded-lg border border-border/60 bg-muted/10 p-3 text-sm text-muted-foreground"> <div className="rounded-lg border border-border/60 bg-muted/10 p-3 text-sm text-muted-foreground">
{isEditingDescription ? ( {isEditingDescription ? (
<Textarea <div className="space-y-3">
value={editedDescription} <Textarea
onChange={(event) => setEditedDescription(event.target.value)} value={editedDescription}
className="min-h-[240px] font-mono text-sm leading-relaxed" onChange={(event) => setEditedDescription(event.target.value)}
placeholder="Enter job description..." className="min-h-[400px] font-mono text-sm leading-relaxed focus-visible:ring-1"
/> placeholder="Enter job description..."
/>
<div className="flex justify-end gap-2">
<Button
size="sm"
variant="outline"
onClick={() => {
setIsEditingDescription(false);
setEditedDescription(selectedJob.jobDescription || "");
}}
disabled={isSavingDescription}
>
Cancel
</Button>
<Button
size="sm"
onClick={handleSaveDescription}
disabled={isSavingDescription}
>
{isSavingDescription ? (
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
) : (
<CheckCircle2 className="mr-2 h-4 w-4" />
)}
Save Description
</Button>
</div>
</div>
) : ( ) : (
<div className="whitespace-pre-wrap leading-relaxed"> <div className="whitespace-pre-wrap leading-relaxed">
<ReactMarkdown remarkPlugins={[remarkGfm]}>{description}</ReactMarkdown> <ReactMarkdown remarkPlugins={[remarkGfm]}>{description}</ReactMarkdown>