feat: add error recovery with retry functionality

Error recovery features:
- **Retry button**: Appears on failed conversions
- **Smart retry logic**: Re-attempts conversion with same settings
- **State management**: Properly resets job state before retry
- **Progress tracking**: Shows progress during retry attempt
- **Toast notifications**: Informs user of retry success/failure
- **History updates**: Successful retries added to history
- **Visual feedback**: RefreshCw icon with clear button label

Implementation:
- Added onRetry prop to ConversionPreview component
- Implemented handleRetry function in FileConverter
- Reuses existing conversion logic for consistency
- Maintains all conversion options during retry
- Updates job status through proper state flow:
  error → loading → processing → completed/error

User experience:
- One-click retry for failed conversions
- No need to re-upload file or reconfigure settings
- Clear visual indication when retry is in progress
- Helpful error messages if retry also fails

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-17 13:22:44 +01:00
parent 649cd3cd7b
commit ba2e011f4a
2 changed files with 119 additions and 3 deletions

View File

@@ -1,7 +1,7 @@
'use client';
import * as React from 'react';
import { Download, CheckCircle, XCircle, Loader2, Clock, TrendingUp, FileCheck2, ArrowRight } from 'lucide-react';
import { Download, CheckCircle, XCircle, Loader2, Clock, TrendingUp, FileCheck2, ArrowRight, RefreshCw } from 'lucide-react';
import { cn } from '@/lib/utils/cn';
import { Button } from '@/components/ui/Button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/Card';
@@ -12,9 +12,10 @@ import type { ConversionJob } from '@/types/conversion';
export interface ConversionPreviewProps {
job: ConversionJob;
onDownload?: () => void;
onRetry?: () => void;
}
export function ConversionPreview({ job, onDownload }: ConversionPreviewProps) {
export function ConversionPreview({ job, onDownload, onRetry }: ConversionPreviewProps) {
const [previewUrl, setPreviewUrl] = React.useState<string | null>(null);
const [elapsedTime, setElapsedTime] = React.useState(0);
const [estimatedTimeRemaining, setEstimatedTimeRemaining] = React.useState<number | null>(null);
@@ -260,6 +261,14 @@ export function ConversionPreview({ job, onDownload }: ConversionPreviewProps) {
</div>
)}
{/* Retry button */}
{job.status === 'error' && onRetry && (
<Button onClick={onRetry} variant="outline" className="w-full gap-2">
<RefreshCw className="h-4 w-4" />
Retry Conversion
</Button>
)}
{/* Preview */}
{job.status === 'completed' && renderPreview()}