mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-21 11:31:13 -05:00
98 lines
3.5 KiB
TypeScript
98 lines
3.5 KiB
TypeScript
import { useState } from 'react';
|
|
import { AlertCircle, ChevronDown } from 'lucide-react';
|
|
import {
|
|
AlertDialog,
|
|
AlertDialogAction,
|
|
AlertDialogContent,
|
|
AlertDialogDescription,
|
|
AlertDialogFooter,
|
|
AlertDialogHeader,
|
|
AlertDialogTitle,
|
|
} from '@/components/ui/alert-dialog';
|
|
import { Alert, AlertDescription } from '@/components/ui/alert';
|
|
import { Badge } from '@/components/ui/badge';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
|
|
import { ValidationError } from '@/lib/entityValidationSchemas';
|
|
|
|
interface ValidationBlockerDialogProps {
|
|
open: boolean;
|
|
onClose: () => void;
|
|
blockingErrors: ValidationError[];
|
|
itemNames: string[];
|
|
}
|
|
|
|
export function ValidationBlockerDialog({
|
|
open,
|
|
onClose,
|
|
blockingErrors,
|
|
itemNames,
|
|
}: ValidationBlockerDialogProps) {
|
|
const [showDetails, setShowDetails] = useState(false);
|
|
|
|
return (
|
|
<AlertDialog open={open} onOpenChange={onClose}>
|
|
<AlertDialogContent className="max-w-2xl">
|
|
<AlertDialogHeader>
|
|
<AlertDialogTitle className="flex items-center gap-2 text-destructive">
|
|
<AlertCircle className="w-5 h-5" />
|
|
Cannot Approve: Validation Errors
|
|
</AlertDialogTitle>
|
|
<AlertDialogDescription>
|
|
The following items have blocking validation errors that MUST be fixed before approval.
|
|
Edit the items to fix the errors, or reject them.
|
|
</AlertDialogDescription>
|
|
</AlertDialogHeader>
|
|
|
|
<div className="space-y-3 my-4">
|
|
{itemNames.map((name, index) => {
|
|
const itemErrors = blockingErrors.filter((_, i) =>
|
|
itemNames.length === 1 || i === index
|
|
);
|
|
|
|
return (
|
|
<div key={index} className="space-y-2">
|
|
<div className="font-medium text-sm flex items-center justify-between">
|
|
<span>{name}</span>
|
|
<Badge variant="destructive">
|
|
{itemErrors.length} error{itemErrors.length > 1 ? 's' : ''}
|
|
</Badge>
|
|
</div>
|
|
<Alert variant="destructive">
|
|
<AlertDescription className="space-y-1">
|
|
{itemErrors.map((error, errIndex) => (
|
|
<div key={errIndex} className="text-sm">
|
|
• <span className="font-medium">{error.field}:</span> {error.message}
|
|
</div>
|
|
))}
|
|
</AlertDescription>
|
|
</Alert>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
|
|
<Collapsible open={showDetails} onOpenChange={setShowDetails}>
|
|
<CollapsibleTrigger asChild>
|
|
<Button variant="ghost" size="sm" className="w-full">
|
|
{showDetails ? 'Hide' : 'Show'} Technical Details
|
|
<ChevronDown className={`ml-2 h-4 w-4 transition-transform ${showDetails ? 'rotate-180' : ''}`} />
|
|
</Button>
|
|
</CollapsibleTrigger>
|
|
<CollapsibleContent className="mt-2">
|
|
<div className="bg-muted p-3 rounded text-xs font-mono max-h-60 overflow-auto">
|
|
<pre>{JSON.stringify(blockingErrors, null, 2)}</pre>
|
|
</div>
|
|
</CollapsibleContent>
|
|
</Collapsible>
|
|
|
|
<AlertDialogFooter>
|
|
<AlertDialogAction onClick={onClose}>
|
|
Close
|
|
</AlertDialogAction>
|
|
</AlertDialogFooter>
|
|
</AlertDialogContent>
|
|
</AlertDialog>
|
|
);
|
|
}
|