separate component

This commit is contained in:
DaKheera47
2026-02-15 22:19:26 +00:00
parent 5a5cbb40ac
commit 3b86e56c22
47 changed files with 1960 additions and 191 deletions
+77 -118
View File
@@ -12,7 +12,6 @@ import {
CalendarClock,
ClipboardList,
DollarSign,
PanelRightOpen,
PlusCircle,
} from "lucide-react";
import React from "react";
@@ -21,18 +20,10 @@ import { toast } from "sonner";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import {
Sheet,
SheetContent,
SheetDescription,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@/components/ui/sheet";
import { formatTimestamp } from "@/lib/utils";
import * as api from "../api";
import { ConfirmDelete } from "../components/ConfirmDelete";
import { GhostwriterPanel } from "../components/ghostwriter/GhostwriterPanel";
import { GhostwriterDrawer } from "../components/ghostwriter/GhostwriterDrawer";
import { JobHeader } from "../components/JobHeader";
import {
type LogEventFormValues,
@@ -49,7 +40,6 @@ export const JobPage: React.FC = () => {
const [isLoading, setIsLoading] = React.useState(true);
const [isLogModalOpen, setIsLogModalOpen] = React.useState(false);
const [isDeleteModalOpen, setIsDeleteModalOpen] = React.useState(false);
const [isGhostwriterOpen, setIsGhostwriterOpen] = React.useState(false);
const [eventToDelete, setEventToDelete] = React.useState<string | null>(null);
const [editingEvent, setEditingEvent] = React.useState<StageEvent | null>(
null,
@@ -281,119 +271,88 @@ export const JobPage: React.FC = () => {
</CardContent>
</Card>
<Sheet open={isGhostwriterOpen} onOpenChange={setIsGhostwriterOpen}>
<div className="space-y-4">
<div className="space-y-4">
<Card className="border-border/50">
<CardHeader>
<div className="flex items-center justify-between gap-3">
<CardTitle className="flex items-center gap-2 text-base">
<CalendarClock className="h-4 w-4" />
Application details
</CardTitle>
<GhostwriterDrawer job={job} />
</div>
</CardHeader>
<CardContent className="space-y-4">
<div>
<div className="text-[10px] uppercase tracking-wide text-muted-foreground">
Current Stage
</div>
<div className="mt-1 text-sm font-medium">
{currentStage
? STAGE_LABELS[currentStage as ApplicationStage] ||
currentStage
: job?.status}
</div>
</div>
<div>
<div className="text-[10px] uppercase tracking-wide text-muted-foreground">
Outcome
</div>
<div className="mt-1 text-sm font-medium">
{job?.outcome ? job.outcome.replace(/_/g, " ") : "Open"}
</div>
</div>
{job?.closedAt && (
<div>
<div className="text-[10px] uppercase tracking-wide text-muted-foreground">
Closed On
</div>
<div className="mt-1 text-sm font-medium">
{formatTimestamp(job.closedAt)}
</div>
</div>
)}
</CardContent>
</Card>
{tasks.length > 0 && (
<Card className="border-border/50">
<CardHeader>
<div className="flex items-center justify-between gap-3">
<CardTitle className="flex items-center gap-2 text-base">
<CalendarClock className="h-4 w-4" />
Application details
</CardTitle>
<SheetTrigger asChild>
<Button
size="sm"
variant="outline"
className="h-8 gap-1.5 text-xs"
disabled={!job}
>
<PanelRightOpen className="h-3.5 w-3.5" />
Ghostwriter
</Button>
</SheetTrigger>
</div>
<CardTitle className="flex items-center gap-2 text-base">
<CalendarClock className="h-4 w-4" />
Upcoming tasks
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div>
<div className="text-[10px] uppercase tracking-wide text-muted-foreground">
Current Stage
</div>
<div className="mt-1 text-sm font-medium">
{currentStage
? STAGE_LABELS[currentStage as ApplicationStage] ||
currentStage
: job?.status}
</div>
</div>
<div>
<div className="text-[10px] uppercase tracking-wide text-muted-foreground">
Outcome
</div>
<div className="mt-1 text-sm font-medium">
{job?.outcome ? job.outcome.replace(/_/g, " ") : "Open"}
</div>
</div>
{job?.closedAt && (
<div>
<div className="text-[10px] uppercase tracking-wide text-muted-foreground">
Closed On
<CardContent>
<div className="space-y-3">
{tasks.map((task) => (
<div
key={task.id}
className="flex items-start justify-between gap-4"
>
<div className="space-y-1">
<div className="text-sm font-medium text-foreground/90">
{task.title}
</div>
{task.notes && (
<div className="text-xs text-muted-foreground">
{task.notes}
</div>
)}
</div>
<Badge
variant="outline"
className="text-[10px] uppercase tracking-wide"
>
{formatTimestamp(task.dueDate)}
</Badge>
</div>
<div className="mt-1 text-sm font-medium">
{formatTimestamp(job.closedAt)}
</div>
</div>
)}
))}
</div>
</CardContent>
</Card>
{tasks.length > 0 && (
<Card className="border-border/50">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-base">
<CalendarClock className="h-4 w-4" />
Upcoming tasks
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-3">
{tasks.map((task) => (
<div
key={task.id}
className="flex items-start justify-between gap-4"
>
<div className="space-y-1">
<div className="text-sm font-medium text-foreground/90">
{task.title}
</div>
{task.notes && (
<div className="text-xs text-muted-foreground">
{task.notes}
</div>
)}
</div>
<Badge
variant="outline"
className="text-[10px] uppercase tracking-wide"
>
{formatTimestamp(task.dueDate)}
</Badge>
</div>
))}
</div>
</CardContent>
</Card>
)}
<SheetContent
side="right"
className="w-full p-0 sm:max-w-none lg:w-[40vw]"
>
<div className="h-full overflow-y-auto p-4">
<SheetHeader>
<SheetTitle>Ghostwriter</SheetTitle>
<SheetDescription>
Chat with context from this job and your writing style.
</SheetDescription>
</SheetHeader>
{job && (
<div className="mt-4">
<GhostwriterPanel job={job} />
</div>
)}
</div>
</SheetContent>
</div>
</Sheet>
)}
</div>
</div>
<LogEventModal
@@ -7,7 +7,6 @@ import {
FileText,
Loader2,
MoreHorizontal,
PanelRightOpen,
RefreshCcw,
Save,
XCircle,
@@ -25,14 +24,6 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import {
Sheet,
SheetContent,
SheetDescription,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@/components/ui/sheet";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Textarea } from "@/components/ui/textarea";
import {
@@ -48,7 +39,7 @@ import {
JobHeader,
TailoredSummary,
} from "../../components";
import { GhostwriterPanel } from "../../components/ghostwriter/GhostwriterPanel";
import { GhostwriterDrawer } from "../../components/ghostwriter/GhostwriterDrawer";
import { JobDetailsEditDrawer } from "../../components/JobDetailsEditDrawer";
import { ReadyPanel } from "../../components/ReadyPanel";
import { TailoringEditor } from "../../components/TailoringEditor";
@@ -81,7 +72,6 @@ export const JobDetailPanel: React.FC<JobDetailPanelProps> = ({
const [hasUnsavedTailoring, setHasUnsavedTailoring] = useState(false);
const [processingJobId, setProcessingJobId] = useState<string | null>(null);
const [isEditDetailsOpen, setIsEditDetailsOpen] = useState(false);
const [isGhostwriterOpen, setIsGhostwriterOpen] = useState(false);
const saveTailoringRef = useRef<null | (() => Promise<void>)>(null);
const previousSelectedJobIdRef = useRef<string | null>(null);
@@ -323,37 +313,7 @@ export const JobDetailPanel: React.FC<JobDetailPanelProps> = ({
return (
<div className="space-y-3">
<div className="flex justify-end">
<Sheet open={isGhostwriterOpen} onOpenChange={setIsGhostwriterOpen}>
<SheetTrigger asChild>
<Button
size="sm"
variant="outline"
className="h-8 gap-1.5 text-xs"
disabled={!selectedJob}
>
<PanelRightOpen className="h-3.5 w-3.5" />
Ghostwriter
</Button>
</SheetTrigger>
<SheetContent
side="right"
className="w-full p-0 sm:max-w-none lg:w-[40vw]"
>
<div className="h-full overflow-y-auto p-4">
<SheetHeader>
<SheetTitle>Ghostwriter</SheetTitle>
<SheetDescription>
Chat with context from this job and your writing style.
</SheetDescription>
</SheetHeader>
{selectedJob && (
<div className="mt-4">
<GhostwriterPanel job={selectedJob} />
</div>
)}
</div>
</SheetContent>
</Sheet>
<GhostwriterDrawer job={selectedJob} />
</div>
<DiscoveredPanel
job={selectedJob}
@@ -369,37 +329,7 @@ export const JobDetailPanel: React.FC<JobDetailPanelProps> = ({
return (
<div className="space-y-3">
<div className="flex justify-end">
<Sheet open={isGhostwriterOpen} onOpenChange={setIsGhostwriterOpen}>
<SheetTrigger asChild>
<Button
size="sm"
variant="outline"
className="h-8 gap-1.5 text-xs"
disabled={!selectedJob}
>
<PanelRightOpen className="h-3.5 w-3.5" />
Ghostwriter
</Button>
</SheetTrigger>
<SheetContent
side="right"
className="w-full p-0 sm:max-w-none lg:w-[40vw]"
>
<div className="h-full overflow-y-auto p-4">
<SheetHeader>
<SheetTitle>Ghostwriter</SheetTitle>
<SheetDescription>
Chat with context from this job and your writing style.
</SheetDescription>
</SheetHeader>
{selectedJob && (
<div className="mt-4">
<GhostwriterPanel job={selectedJob} />
</div>
)}
</div>
</SheetContent>
</Sheet>
<GhostwriterDrawer job={selectedJob} />
</div>
<ReadyPanel
job={selectedJob}