Files
erp-nutzfahrzeuge/frontend/components/sales/ContractPreview.tsx
T
Leopoldadmin 341d0c6f38 fix: resolve all ruff and ESLint lint errors
Backend (ruff):
- F821: Add TYPE_CHECKING imports for Vehicle, Contact, File in models
  (file.py, retouch.py, sale.py, vehicle.py)
- E741: Rename ambiguous variable  to /
  (copilot_service.py, price_compare_service.py, openrouter.py)
- F841: Remove unused variable  in sale_service.py

Frontend (ESLint):
- react/no-unescaped-entities: Escape quotes in ContractPreview.tsx
- @next/next/no-img-element: Replace <img> with <Image> from next/image
  (FileGallery.tsx, FileList.tsx, FilePreview.tsx, BeforeAfterSlider.tsx)

Tests: 392 backend passed, 112 frontend passed, next build successful
2026-07-17 21:16:38 +02:00

77 lines
2.4 KiB
TypeScript

'use client';
import { useState } from 'react';
import { Button } from '@/components/ui/Button';
import { getContractDownloadUrl, regenerateContract } from '@/lib/sales';
interface ContractPreviewProps {
saleId: string;
contractPdfPath?: string | null;
}
export function ContractPreview({ saleId, contractPdfPath }: ContractPreviewProps) {
const [regenerating, setRegenerating] = useState(false);
const [error, setError] = useState<string | null>(null);
const [pdfPath, setPdfPath] = useState<string | null>(contractPdfPath || null);
const handleRegenerate = async () => {
setRegenerating(true);
setError(null);
try {
const result = await regenerateContract(saleId);
setPdfPath(result.contract_pdf_path);
} catch (err: unknown) {
const apiErr = err as { error?: { message?: string } };
setError(apiErr?.error?.message || 'Failed to regenerate contract');
} finally {
setRegenerating(false);
}
};
const downloadUrl = getContractDownloadUrl(saleId);
return (
<div className="space-y-4" data-testid="contract-preview">
<div className="flex items-center justify-between">
<h2 className="text-xl font-bold">Vertrags-PDF</h2>
<div className="flex gap-2">
<Button
onClick={handleRegenerate}
disabled={regenerating}
data-testid="contract-regenerate-btn"
>
{regenerating ? 'Wird erstellt...' : 'Vertrag neu generieren'}
</Button>
{pdfPath && (
<a href={downloadUrl} target="_blank" rel="noopener noreferrer" data-testid="contract-download-link">
<Button>Herunterladen</Button>
</a>
)}
</div>
</div>
{error && (
<div className="bg-red-50 text-red-600 p-3 rounded" data-testid="contract-error">
{error}
</div>
)}
{pdfPath ? (
<iframe
src={downloadUrl}
className="w-full h-[600px] border rounded"
data-testid="contract-iframe"
title="Vertrags-PDF"
/>
) : (
<div className="bg-gray-50 p-8 text-center rounded" data-testid="contract-empty">
<p className="text-gray-500">Es wurde noch kein Vertrag generiert.</p>
<p className="text-sm text-gray-400 mt-2">
Klicken Sie auf &quot;Vertrag neu generieren&quot;, um ein PDF zu erstellen.
</p>
</div>
)}
</div>
);
}