Add open job listing action to discovered jobs (#274)
* feat: add open job listing action to discovered jobs * chore: add skills lockfile * impeccable
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
import { ExternalLink } from "lucide-react";
|
||||
import type React from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { KbdHint } from "./KbdHint";
|
||||
|
||||
interface OpenJobListingButtonProps {
|
||||
href: string;
|
||||
className?: string;
|
||||
shortcut?: string;
|
||||
}
|
||||
|
||||
export const OpenJobListingButton: React.FC<OpenJobListingButtonProps> = ({
|
||||
href,
|
||||
className,
|
||||
shortcut,
|
||||
}) => {
|
||||
return (
|
||||
<Button asChild variant="outline" className={cn("gap-1", className)}>
|
||||
<a href={href} target="_blank" rel="noopener noreferrer">
|
||||
<ExternalLink className="h-3.5 w-3.5 shrink-0" />
|
||||
<span className="truncate">Open Job Listing</span>
|
||||
{shortcut ? <KbdHint shortcut={shortcut} className="ml-auto" /> : null}
|
||||
</a>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
@@ -52,6 +52,7 @@ import { TailorMode } from "./discovered-panel/TailorMode";
|
||||
import { GhostwriterDrawer } from "./ghostwriter/GhostwriterDrawer";
|
||||
import { JobDetailsEditDrawer } from "./JobDetailsEditDrawer";
|
||||
import { KbdHint } from "./KbdHint";
|
||||
import { OpenJobListingButton } from "./OpenJobListingButton";
|
||||
import { ReadySummaryAccordion } from "./ReadySummaryAccordion";
|
||||
import { buildReadyPanelGoogleDorks } from "./ready-panel-google-dorks";
|
||||
|
||||
@@ -397,17 +398,11 @@ export const ReadyPanel: React.FC<ReadyPanelProps> = ({
|
||||
</Button>
|
||||
|
||||
{/* Open job - to verify before applying */}
|
||||
<Button
|
||||
asChild
|
||||
variant="outline"
|
||||
className="h-9 w-full gap-1 px-2 text-xs"
|
||||
>
|
||||
<a href={jobLink} target="_blank" rel="noopener noreferrer">
|
||||
<ExternalLink className="h-3.5 w-3.5 shrink-0" />
|
||||
<span className="truncate">Open Job Listing</span>
|
||||
<KbdHint shortcut="o" className="ml-auto" />
|
||||
</a>
|
||||
</Button>
|
||||
<OpenJobListingButton
|
||||
href={jobLink}
|
||||
className="h-9 w-full px-2 text-xs"
|
||||
shortcut="o"
|
||||
/>
|
||||
|
||||
{/* Primary CTA: Mark Applied */}
|
||||
<Button
|
||||
|
||||
@@ -2,7 +2,6 @@ import type { Job } from "@shared/types.js";
|
||||
import {
|
||||
ChevronUp,
|
||||
Edit2,
|
||||
ExternalLink,
|
||||
Loader2,
|
||||
RefreshCcw,
|
||||
Sparkles,
|
||||
@@ -20,6 +19,7 @@ import {
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { FitAssessment, JobHeader, TailoredSummary } from "..";
|
||||
import { KbdHint } from "../KbdHint";
|
||||
import { OpenJobListingButton } from "../OpenJobListingButton";
|
||||
import { CollapsibleSection } from "./CollapsibleSection";
|
||||
import { getPlainDescription } from "./helpers";
|
||||
|
||||
@@ -58,6 +58,12 @@ export const DecideMode: React.FC<DecideModeProps> = ({
|
||||
<JobHeader job={job} onCheckSponsor={onCheckSponsor} />
|
||||
|
||||
<div className="flex flex-col gap-2.5 pt-2 sm:flex-row">
|
||||
{jobLink ? (
|
||||
<OpenJobListingButton
|
||||
href={jobLink}
|
||||
className="flex-1 h-11 text-sm sm:h-10 sm:text-xs"
|
||||
/>
|
||||
) : null}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="default"
|
||||
@@ -133,20 +139,6 @@ export const DecideMode: React.FC<DecideModeProps> = ({
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
{jobLink ? (
|
||||
<div className="flex justify-center">
|
||||
<a
|
||||
href={jobLink}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-1.5 text-[11px] font-medium text-muted-foreground hover:text-foreground transition-colors"
|
||||
>
|
||||
<ExternalLink className="h-3.5 w-3.5" />
|
||||
Original Job Listing
|
||||
</a>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -140,4 +140,26 @@ describe("DiscoveredPanel", () => {
|
||||
screen.queryByTestId("job-details-edit-drawer"),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("shows an open job listing link when the discovered job has an external url", () => {
|
||||
const job = createJob({
|
||||
id: "job-3",
|
||||
jobUrl: "https://example.com/jobs/visit-me",
|
||||
applicationLink: null,
|
||||
});
|
||||
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<DiscoveredPanel
|
||||
job={job}
|
||||
onJobUpdated={vi.fn()}
|
||||
onJobMoved={vi.fn()}
|
||||
/>
|
||||
</MemoryRouter>,
|
||||
);
|
||||
|
||||
expect(
|
||||
screen.getByRole("link", { name: /open job listing/i }),
|
||||
).toHaveAttribute("href", "https://example.com/jobs/visit-me");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@ export { FitAssessment } from "./FitAssessment";
|
||||
export { JobHeader } from "./JobHeader";
|
||||
export * from "./layout";
|
||||
export { ManualImportSheet } from "./ManualImportSheet";
|
||||
export { OpenJobListingButton } from "./OpenJobListingButton";
|
||||
export { PipelineProgress } from "./PipelineProgress";
|
||||
export { ReadyPanel } from "./ReadyPanel";
|
||||
export { ScoreIndicator } from "./ScoreIndicator";
|
||||
|
||||
Reference in New Issue
Block a user