chore: ran linting

This commit is contained in:
Anish Sarkar 2026-04-17 16:45:14 +05:30
parent aef4c90107
commit 0fa32c3a10
6 changed files with 140 additions and 73 deletions

View file

@ -42,7 +42,13 @@ export const openReportPanelAtom = atom(
wordCount,
shareToken,
contentType,
}: { reportId: number; title: string; wordCount?: number; shareToken?: string | null; contentType?: string }
}: {
reportId: number;
title: string;
wordCount?: number;
shareToken?: string | null;
contentType?: string;
}
) => {
if (!get(reportPanelAtom).isOpen) {
set(preReportCollapsedAtom, get(rightPanelCollapsedAtom));

View file

@ -1,9 +1,9 @@
"use client";
import { ZoomInIcon, ZoomOutIcon } from "lucide-react";
import { useCallback, useEffect, useRef, useState } from "react";
import * as pdfjsLib from "pdfjs-dist";
import type { PDFDocumentProxy, RenderTask } from "pdfjs-dist";
import * as pdfjsLib from "pdfjs-dist";
import { useCallback, useEffect, useRef, useState } from "react";
import { Button } from "@/components/ui/button";
import { Spinner } from "@/components/ui/spinner";
import { getAuthHeaders } from "@/lib/auth-utils";
@ -50,7 +50,7 @@ export function PdfViewer({ pdfUrl, isPublic = false }: PdfViewerProps) {
const dims = pageDimsRef.current[pageIndex];
return dims ? Math.floor(dims.height * scale) : 0;
},
[scale],
[scale]
);
const getVisibleRange = useCallback(() => {
@ -285,14 +285,28 @@ export function PdfViewer({ pdfUrl, isPublic = false }: PdfViewerProps) {
return (
<div className="flex flex-col h-full">
{numPages > 0 && (
<div className={`flex items-center justify-center gap-2 px-4 py-2 border-b shrink-0 select-none ${isPublic ? "bg-main-panel" : "bg-sidebar"}`}>
<Button variant="ghost" size="icon" onClick={zoomOut} disabled={scale <= MIN_ZOOM} className="size-7">
<div
className={`flex items-center justify-center gap-2 px-4 py-2 border-b shrink-0 select-none ${isPublic ? "bg-main-panel" : "bg-sidebar"}`}
>
<Button
variant="ghost"
size="icon"
onClick={zoomOut}
disabled={scale <= MIN_ZOOM}
className="size-7"
>
<ZoomOutIcon className="size-4" />
</Button>
<span className="text-xs text-muted-foreground tabular-nums min-w-[40px] text-center">
{Math.round(scale * 100)}%
</span>
<Button variant="ghost" size="icon" onClick={zoomIn} disabled={scale >= MAX_ZOOM} className="size-7">
<Button
variant="ghost"
size="icon"
onClick={zoomIn}
disabled={scale >= MAX_ZOOM}
className="size-7"
>
<ZoomInIcon className="size-4" />
</Button>
</div>
@ -303,7 +317,9 @@ export function PdfViewer({ pdfUrl, isPublic = false }: PdfViewerProps) {
className={`relative flex-1 overflow-auto ${isPublic ? "bg-main-panel" : "bg-sidebar"}`}
>
{loading ? (
<div className={`absolute inset-0 flex items-center justify-center ${isPublic ? "text-foreground" : "text-sidebar-foreground"}`}>
<div
className={`absolute inset-0 flex items-center justify-center ${isPublic ? "text-foreground" : "text-sidebar-foreground"}`}
>
<Spinner size="md" />
</div>
) : (

View file

@ -308,42 +308,42 @@ export function ReportPanelContent({
</Button>
)}
{/* Export — plain button for resume (typst), dropdown for others */}
{reportContent?.content_type === "typst" ? (
<Button
variant="outline"
size="sm"
onClick={() => handleExport("pdf")}
disabled={isLoading || !reportContent?.content || exporting !== null}
className={`h-8 min-w-[100px] px-3.5 py-4 text-[15px] ${btnBg} select-none`}
>
{exporting === "pdf" ? <Spinner size="xs" /> : "Download"}
</Button>
) : (
<DropdownMenu modal={insideDrawer ? false : undefined}>
<DropdownMenuTrigger asChild>
<Button
variant="outline"
size="sm"
disabled={isLoading || !reportContent?.content}
className={`h-8 px-3.5 py-4 text-[15px] gap-1.5 ${btnBg} select-none`}
>
Export
<ChevronDownIcon className="size-3" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent
align="start"
className={`min-w-[200px] select-none${insideDrawer ? " z-[100]" : ""}`}
{/* Export — plain button for resume (typst), dropdown for others */}
{reportContent?.content_type === "typst" ? (
<Button
variant="outline"
size="sm"
onClick={() => handleExport("pdf")}
disabled={isLoading || !reportContent?.content || exporting !== null}
className={`h-8 min-w-[100px] px-3.5 py-4 text-[15px] ${btnBg} select-none`}
>
<ExportDropdownItems
onExport={handleExport}
exporting={exporting}
showAllFormats={!shareToken}
/>
</DropdownMenuContent>
</DropdownMenu>
)}
{exporting === "pdf" ? <Spinner size="xs" /> : "Download"}
</Button>
) : (
<DropdownMenu modal={insideDrawer ? false : undefined}>
<DropdownMenuTrigger asChild>
<Button
variant="outline"
size="sm"
disabled={isLoading || !reportContent?.content}
className={`h-8 px-3.5 py-4 text-[15px] gap-1.5 ${btnBg} select-none`}
>
Export
<ChevronDownIcon className="size-3" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent
align="start"
className={`min-w-[200px] select-none${insideDrawer ? " z-[100]" : ""}`}
>
<ExportDropdownItems
onExport={handleExport}
exporting={exporting}
showAllFormats={!shareToken}
/>
</DropdownMenuContent>
</DropdownMenu>
)}
{/* Version switcher — only shown when multiple versions exist */}
{versions.length > 1 && (
@ -395,10 +395,10 @@ export function ReportPanelContent({
</div>
</div>
) : reportContent.content_type === "typst" ? (
<PdfViewer
pdfUrl={`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}${shareToken ? `/api/v1/public/${shareToken}/reports/${activeReportId}/preview` : `/api/v1/reports/${activeReportId}/preview`}`}
isPublic={isPublic}
/>
<PdfViewer
pdfUrl={`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}${shareToken ? `/api/v1/public/${shareToken}/reports/${activeReportId}/preview` : `/api/v1/reports/${activeReportId}/preview`}`}
isPublic={isPublic}
/>
) : reportContent.content ? (
isReadOnly ? (
<div className="h-full overflow-y-auto px-5 py-4">

View file

@ -99,7 +99,9 @@ function ReportErrorState({ title, error }: { title: string; error: string }) {
{title && title !== "Report" && (
<p className="text-sm font-medium text-foreground line-clamp-2">{title}</p>
)}
<p className={`text-sm text-muted-foreground${title && title !== "Report" ? " mt-1" : ""}`}>{error}</p>
<p className={`text-sm text-muted-foreground${title && title !== "Report" ? " mt-1" : ""}`}>
{error}
</p>
</div>
</div>
);
@ -217,11 +219,11 @@ function ReportCard({
<div
className={`my-4 max-w-lg overflow-hidden rounded-2xl border bg-muted/30 transition-[box-shadow] duration-300 ${isActive ? "ring-1 ring-primary/50" : ""}`}
>
<button
type="button"
onClick={handleOpen}
className="w-full text-left transition-colors hover:bg-muted/50 focus:outline-none focus-visible:outline-none cursor-pointer"
>
<button
type="button"
onClick={handleOpen}
className="w-full text-left transition-colors hover:bg-muted/50 focus:outline-none focus-visible:outline-none cursor-pointer"
>
<div className="px-5 pt-5 pb-4 select-none">
<p className="text-sm font-semibold text-foreground line-clamp-2">
{isLoading ? title : metadata.title}

View file

@ -3,8 +3,8 @@
import type { ToolCallMessagePartProps } from "@assistant-ui/react";
import { useAtomValue, useSetAtom } from "jotai";
import { useParams, usePathname } from "next/navigation";
import { useCallback, useEffect, useRef, useState } from "react";
import * as pdfjsLib from "pdfjs-dist";
import { useCallback, useEffect, useRef, useState } from "react";
import { z } from "zod";
import { openReportPanelAtom, reportPanelAtom } from "@/atoms/chat/report-panel.atom";
import { TextShimmerLoader } from "@/components/prompt-kit/loader";
@ -70,7 +70,9 @@ function ResumeErrorState({ title, error }: { title: string; error: string }) {
{title && title !== "Resume" && (
<p className="text-sm font-medium text-foreground line-clamp-2">{title}</p>
)}
<p className={`text-sm text-muted-foreground${title && title !== "Resume" ? " mt-1" : ""}`}>{error}</p>
<p className={`text-sm text-muted-foreground${title && title !== "Resume" ? " mt-1" : ""}`}>
{error}
</p>
</div>
</div>
);
@ -101,7 +103,15 @@ function ThumbnailSkeleton() {
);
}
function PdfThumbnail({ pdfUrl, onLoad, onError }: { pdfUrl: string; onLoad: () => void; onError: () => void }) {
function PdfThumbnail({
pdfUrl,
onLoad,
onError,
}: {
pdfUrl: string;
onLoad: () => void;
onError: () => void;
}) {
const wrapperRef = useRef<HTMLDivElement>(null);
const canvasRef = useRef<HTMLCanvasElement>(null);
const [ready, setReady] = useState(false);
@ -117,13 +127,22 @@ function PdfThumbnail({ pdfUrl, onLoad, onError }: { pdfUrl: string; onLoad: ()
});
const pdf = await loadingTask.promise;
if (cancelled) { pdf.destroy(); return; }
if (cancelled) {
pdf.destroy();
return;
}
const page = await pdf.getPage(1);
if (cancelled) { pdf.destroy(); return; }
if (cancelled) {
pdf.destroy();
return;
}
const canvas = canvasRef.current;
if (!canvas) { pdf.destroy(); return; }
if (!canvas) {
pdf.destroy();
return;
}
const containerWidth = wrapperRef.current?.clientWidth || 400;
const unscaledViewport = page.getViewport({ scale: 1 });
@ -152,15 +171,14 @@ function PdfThumbnail({ pdfUrl, onLoad, onError }: { pdfUrl: string; onLoad: ()
};
renderThumbnail();
return () => { cancelled = true; };
return () => {
cancelled = true;
};
}, [pdfUrl, onLoad, onError]);
return (
<div ref={wrapperRef}>
<canvas
ref={canvasRef}
className={ready ? "w-full h-auto" : "hidden"}
/>
<canvas ref={canvasRef} className={ready ? "w-full h-auto" : "hidden"} />
</div>
);
}
@ -294,7 +312,9 @@ export const GenerateResumeToolUI = ({
return (
<ResumeErrorState
title={result.title || "Resume"}
error={result.error || "Resume generation failed. Please try again or rephrase your request."}
error={
result.error || "Resume generation failed. Please try again or rephrase your request."
}
/>
);
}