ValidationFailuresSection.tsx61 lines · main
| 1 | import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Badge, Card } from 'ui' |
| 2 | import { Admonition } from 'ui-patterns' |
| 3 | |
| 4 | import type { ValidationFailure } from '@/data/replication/validate-destination-mutation' |
| 5 | |
| 6 | interface ValidationFailuresSectionProps { |
| 7 | destinationFailures: ValidationFailure[] |
| 8 | pipelineFailures: ValidationFailure[] |
| 9 | } |
| 10 | |
| 11 | export 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 | } |