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
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
||||
getThumbnailUrl,
|
||||
type FileResponse,
|
||||
} from '@/lib/files';
|
||||
import Image from 'next/image';
|
||||
import { FilePreview } from './FilePreview';
|
||||
|
||||
interface FileGalleryProps {
|
||||
@@ -76,10 +77,12 @@ export function FileGallery({ vehicleId }: FileGalleryProps) {
|
||||
data-testid={`gallery-item-${image.id}`}
|
||||
>
|
||||
{thumbUrl && (
|
||||
<img
|
||||
<Image
|
||||
src={thumbUrl}
|
||||
alt={image.original_filename}
|
||||
className="w-full h-full object-cover transition-transform group-hover:scale-105"
|
||||
fill
|
||||
className="object-cover transition-transform group-hover:scale-105"
|
||||
unoptimized
|
||||
/>
|
||||
)}
|
||||
<div className="absolute inset-0 bg-black/0 group-hover:bg-black/30 transition-colors flex items-end p-2">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import Image from 'next/image';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Modal } from '@/components/ui/Modal';
|
||||
import {
|
||||
@@ -124,13 +125,15 @@ export function FileList({ vehicleId, onFileDeleted }: FileListProps) {
|
||||
data-testid={`file-item-${file.id}`}
|
||||
>
|
||||
{/* Thumbnail or file icon */}
|
||||
<div className="aspect-square bg-background flex items-center justify-center">
|
||||
<div className="aspect-square bg-background flex items-center justify-center relative">
|
||||
{isImg && thumbUrl ? (
|
||||
<img
|
||||
<Image
|
||||
src={thumbUrl}
|
||||
alt={file.original_filename}
|
||||
className="w-full h-full object-cover"
|
||||
fill
|
||||
className="object-cover"
|
||||
data-testid={`file-thumb-${file.id}`}
|
||||
unoptimized
|
||||
/>
|
||||
) : (
|
||||
<div className="flex flex-col items-center gap-2 text-text-muted">
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import Image from 'next/image';
|
||||
import { Modal } from '@/components/ui/Modal';
|
||||
import { isImageMime, formatFileSize, type FileResponse } from '@/lib/files';
|
||||
|
||||
@@ -22,11 +23,14 @@ export function FilePreview({ file, open, onClose }: FilePreviewProps) {
|
||||
{/* Preview content */}
|
||||
{isImg ? (
|
||||
<div className="flex justify-center">
|
||||
<img
|
||||
<Image
|
||||
src={downloadUrl}
|
||||
alt={file.original_filename}
|
||||
width={800}
|
||||
height={600}
|
||||
className="max-w-full max-h-[60vh] rounded-lg"
|
||||
data-testid="preview-image"
|
||||
unoptimized
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useCallback, useRef, useEffect } from 'react';
|
||||
import Image from 'next/image';
|
||||
|
||||
interface BeforeAfterSliderProps {
|
||||
beforeSrc: string;
|
||||
@@ -78,12 +79,14 @@ export function BeforeAfterSlider({
|
||||
onClick={handleClick}
|
||||
>
|
||||
{/* After image (full, background) */}
|
||||
<img
|
||||
<Image
|
||||
src={afterSrc}
|
||||
alt={afterLabel}
|
||||
className="absolute inset-0 w-full h-full object-cover"
|
||||
fill
|
||||
className="object-cover"
|
||||
data-testid="after-image"
|
||||
draggable={false}
|
||||
unoptimized
|
||||
/>
|
||||
|
||||
{/* Before image (clipped to left of slider) */}
|
||||
@@ -91,13 +94,15 @@ export function BeforeAfterSlider({
|
||||
className="absolute inset-0 overflow-hidden"
|
||||
style={{ width: `${sliderPos}%` }}
|
||||
>
|
||||
<img
|
||||
<Image
|
||||
src={beforeSrc}
|
||||
alt={beforeLabel}
|
||||
className="absolute inset-0 h-full object-cover"
|
||||
fill
|
||||
className="object-cover"
|
||||
style={{ width: `${containerRef.current?.clientWidth || 100}%` }}
|
||||
data-testid="before-image"
|
||||
draggable={false}
|
||||
unoptimized
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ export function ContractPreview({ saleId, contractPdfPath }: ContractPreviewProp
|
||||
<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 "Vertrag neu generieren", um ein PDF zu erstellen.
|
||||
Klicken Sie auf "Vertrag neu generieren", um ein PDF zu erstellen.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user