ValidationFailuresSection.tsx61 lines · main
1import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Badge, Card } from 'ui'
2import { Admonition } from 'ui-patterns'
3
4import type { ValidationFailure } from '@/data/replication/validate-destination-mutation'
5
6interface ValidationFailuresSectionProps {
7 destinationFailures: ValidationFailure[]
8 pipelineFailures: ValidationFailure[]
9}
10
11export const ValidationFailuresSection = ({
12 destinationFailures,
13 pipelineFailures,
14}: ValidationFailuresSectionProps) => {
15 const validationIssues = [...destinationFailures, ...pipelineFailures].sort((a, _b) =>
16 a.failure_type === 'critical' ? -1 : 1
17 )
18
19 const criticalFailures = validationIssues.filter((f) => f.failure_type === 'critical')
20 const warnings = validationIssues.filter((f) => f.failure_type === 'warning')
21
22 const hasCriticalFailures = criticalFailures.length > 0
23 const hasWarnings = warnings.length > 0
24
25 if (validationIssues.length === 0) {
26 return null
27 }
28
29 return (
30 <Admonition
31 type={hasCriticalFailures ? 'warning' : 'default'}
32 className="px-5 rounded-none border-0"
33 title="Destination configuration issues"
34 >
35 <p className="text-sm text-foreground-light mb-2!">
36 {hasCriticalFailures
37 ? `Please fix all required issues below${hasWarnings ? ' and review the others' : ''} before continuing.`
38 : 'The following issues were identified, although you may still proceed to create the destination.'}
39 </p>
40 <Card>
41 <Accordion type="multiple">
42 {validationIssues.map((failure, idx) => (
43 <AccordionItem key={idx} value={`${failure.name}+${idx}`} className="last:border-b-0">
44 <AccordionTrigger className="text-sm px-3 text-foreground decoration-foreground-lighter">
45 <p className="flex items-center gap-x-2">
46 {failure.name}
47 {failure.failure_type === 'critical' && <Badge variant="warning">Required</Badge>}
48 </p>
49 </AccordionTrigger>
50 <AccordionContent className="px-3">
51 <p className="whitespace-pre-wrap text-sm">
52 {failure.reason.replaceAll('\n\n', '\n')}
53 </p>
54 </AccordionContent>
55 </AccordionItem>
56 ))}
57 </Accordion>
58 </Card>
59 </Admonition>
60 )
61}