-
Notifications
You must be signed in to change notification settings - Fork 19
feat: Add PDF export functionality for escrow contracts #50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat: Add PDF export functionality for escrow contracts #50
Conversation
|
@Jayrodri088 is attempting to deploy a commit to the Trustless Work Team on Vercel. A member of the Team first needs to authorize it. |
📝 WalkthroughWalkthroughAdds client-side PDF export: introduces Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant ExportPdfButton
participant generateEscrowPdf
participant jsPDF
participant Browser
User->>ExportPdfButton: Click "Export to PDF"
ExportPdfButton->>ExportPdfButton: Resolve/validate contractId
ExportPdfButton->>generateEscrowPdf: Invoke with organized, network, contractId
generateEscrowPdf->>generateEscrowPdf: Load logo image (async)
generateEscrowPdf->>jsPDF: Create document and add sections (header, summary, status, roles, milestones, footers)
generateEscrowPdf->>Browser: Trigger PDF download
Browser->>User: Deliver PDF file
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@src/utils/pdf-export.ts`:
- Around line 74-90: The addKeyValue helper can overflow because it only calls
checkPageBreak once; modify it to iterate valueLines and before rendering each
line call checkPageBreak(8) (or appropriate height), and if a new page was
started re-render the key label (using doc.setFont/bold and doc.text(`${key}:`,
xPos, yPosition)) so the key appears above continued lines; ensure valueX,
margin, contentWidth calculations remain the same and update yPosition after
each drawn line as currently done.
🧹 Nitpick comments (1)
src/components/escrow/ExportPdfButton.tsx (1)
1-53: Add a loading/disabled state to prevent duplicate exports.
Multiple clicks can trigger parallel PDF generation and duplicate downloads. Consider a simpleisExportingstate to disable the button and provide user feedback.♻️ Suggested update (loading state + disable)
+import { useState } from "react"; import { Button } from "@/components/ui/button"; import { FileDown } from "lucide-react"; import { generateEscrowPdf } from "@/utils/pdf-export"; import type { OrganizedEscrowData } from "@/mappers/escrow-mapper"; import type { NetworkType } from "@/lib/network-config"; @@ export function ExportPdfButton({ organized, network, contractId, initialEscrowId, }: ExportPdfButtonProps) { + const [isExporting, setIsExporting] = useState(false); const handleExport = async () => { + if (isExporting) return; const contractIdToUse = organized.properties.escrow_id || contractId || initialEscrowId; @@ - try { + try { + setIsExporting(true); await generateEscrowPdf({ organized, network, contractId: contractIdToUse, }); } catch (error) { console.error("Error generating PDF:", error); alert("Error generating PDF. Please try again."); + } finally { + setIsExporting(false); } }; @@ <Button onClick={handleExport} variant="outline" className="w-full inline-flex justify-center items-center gap-2" title="Export escrow data to PDF" + disabled={isExporting} + aria-busy={isExporting} > <FileDown className="h-4 w-4" /> - Export to PDF + {isExporting ? "Exporting..." : "Export to PDF"} </Button> ); }
| const addKeyValue = (key: string, value: string, indent = 0) => { | ||
| checkPageBreak(8); | ||
| const xPos = margin + indent; | ||
| doc.setFontSize(10); | ||
| doc.setFont('helvetica', 'bold'); | ||
| doc.setTextColor(60, 60, 60); | ||
| doc.text(`${key}:`, xPos, yPosition); | ||
|
|
||
| const valueX = xPos + 50; | ||
| doc.setFont('helvetica', 'normal'); | ||
| doc.setTextColor(0, 0, 0); | ||
| const valueLines = doc.splitTextToSize(value, contentWidth - 50 - indent); | ||
| valueLines.forEach((line: string) => { | ||
| doc.text(line, valueX, yPosition); | ||
| yPosition += 5; | ||
| }); | ||
| yPosition += 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prevent long value lines from overflowing the page.
addKeyValue only checks page space once, so multi-line values can bleed into the footer or off-page. Add per-line page-break handling (and re-render the key on a new page for context).
🧾 Proposed fix (per-line page breaks + key reprint)
- const addKeyValue = (key: string, value: string, indent = 0) => {
- checkPageBreak(8);
- const xPos = margin + indent;
- doc.setFontSize(10);
- doc.setFont('helvetica', 'bold');
- doc.setTextColor(60, 60, 60);
- doc.text(`${key}:`, xPos, yPosition);
-
- const valueX = xPos + 50;
- doc.setFont('helvetica', 'normal');
- doc.setTextColor(0, 0, 0);
- const valueLines = doc.splitTextToSize(value, contentWidth - 50 - indent);
- valueLines.forEach((line: string) => {
- doc.text(line, valueX, yPosition);
- yPosition += 5;
- });
- yPosition += 2;
- };
+ const addKeyValue = (key: string, value: string, indent = 0) => {
+ const xPos = margin + indent;
+ const valueX = xPos + 50;
+
+ const renderKey = () => {
+ doc.setFontSize(10);
+ doc.setFont('helvetica', 'bold');
+ doc.setTextColor(60, 60, 60);
+ doc.text(`${key}:`, xPos, yPosition);
+ doc.setFont('helvetica', 'normal');
+ doc.setTextColor(0, 0, 0);
+ };
+
+ checkPageBreak(8);
+ renderKey();
+
+ const valueLines = doc.splitTextToSize(value, contentWidth - 50 - indent);
+ valueLines.forEach((line: string) => {
+ if (checkPageBreak(5)) {
+ renderKey();
+ }
+ doc.text(line, valueX, yPosition);
+ yPosition += 5;
+ });
+ yPosition += 2;
+ };📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const addKeyValue = (key: string, value: string, indent = 0) => { | |
| checkPageBreak(8); | |
| const xPos = margin + indent; | |
| doc.setFontSize(10); | |
| doc.setFont('helvetica', 'bold'); | |
| doc.setTextColor(60, 60, 60); | |
| doc.text(`${key}:`, xPos, yPosition); | |
| const valueX = xPos + 50; | |
| doc.setFont('helvetica', 'normal'); | |
| doc.setTextColor(0, 0, 0); | |
| const valueLines = doc.splitTextToSize(value, contentWidth - 50 - indent); | |
| valueLines.forEach((line: string) => { | |
| doc.text(line, valueX, yPosition); | |
| yPosition += 5; | |
| }); | |
| yPosition += 2; | |
| const addKeyValue = (key: string, value: string, indent = 0) => { | |
| const xPos = margin + indent; | |
| const valueX = xPos + 50; | |
| const renderKey = () => { | |
| doc.setFontSize(10); | |
| doc.setFont('helvetica', 'bold'); | |
| doc.setTextColor(60, 60, 60); | |
| doc.text(`${key}:`, xPos, yPosition); | |
| doc.setFont('helvetica', 'normal'); | |
| doc.setTextColor(0, 0, 0); | |
| }; | |
| checkPageBreak(8); | |
| renderKey(); | |
| const valueLines = doc.splitTextToSize(value, contentWidth - 50 - indent); | |
| valueLines.forEach((line: string) => { | |
| if (checkPageBreak(5)) { | |
| renderKey(); | |
| } | |
| doc.text(line, valueX, yPosition); | |
| yPosition += 5; | |
| }); | |
| yPosition += 2; | |
| }; |
🤖 Prompt for AI Agents
In `@src/utils/pdf-export.ts` around lines 74 - 90, The addKeyValue helper can
overflow because it only calls checkPageBreak once; modify it to iterate
valueLines and before rendering each line call checkPageBreak(8) (or appropriate
height), and if a new page was started re-render the key label (using
doc.setFont/bold and doc.text(`${key}:`, xPos, yPosition)) so the key appears
above continued lines; ensure valueX, margin, contentWidth calculations remain
the same and update yPosition after each drawn line as currently done.
|
Hello @techrebelgit still waiting on a review |
9d93425 to
a578bbe
Compare
…ri088/escrow-viewer into feature/escrow-pdf-export
PDF Export Feature for Escrow Viewer
Overview
This PR adds a comprehensive PDF export feature that allows users to generate and download detailed reports of escrow contracts. The feature includes professional formatting, branding, and all relevant escrow information.
Features Implemented
1. PDF Generation
jsPDFfor client-side PDF generation2. PDF Content Sections
Header Section
/logo.png)Escrow Summary
Escrow Status
Assigned Roles
Milestones
Footer
3. Component Architecture
ExportPdfButton.tsx4. Code Quality Improvements
EscrowDetails.tsxcomponentTechnical Details
PDF Export Utility (
src/utils/pdf-export.ts)generateEscrowPdf()for PDF generationExport Button Component (
src/components/escrow/ExportPdfButton.tsx)organized,network,contractId,initialEscrowIdorganized.properties.escrow_idcontractIdpropinitialEscrowIdpropIntegration
organizedWithLiveis available)File Changes
New Files
src/components/escrow/ExportPdfButton.tsx- Export button componentsrc/utils/pdf-export.ts- PDF generation utilityModified Files
src/components/escrow/EscrowDetails.tsx- Integrated ExportPdfButton componentDependencies
jspdf- Added to package.json for PDF generationTesting Considerations
/logo.pngexists in public folder)User Experience
escrow-report-{contractId}-{date}.pdfCloses: #39
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.