74 lines
2.4 KiB
TypeScript
74 lines
2.4 KiB
TypeScript
import React from "react";
|
|
import { Box, Typography, Alert, Snackbar, List, ListItem, ListItemIcon, ListItemText } from "@mui/material";
|
|
import ErrorIcon from "@mui/icons-material/Error";
|
|
import WarningIcon from "@mui/icons-material/Warning";
|
|
import type { ValidationMessage } from "../types";
|
|
|
|
interface ValidationAlertProps {
|
|
errors: ValidationMessage[];
|
|
warnings: ValidationMessage[];
|
|
}
|
|
|
|
export function ValidationAlert({ errors, warnings }: ValidationAlertProps) {
|
|
const [warningOpen, setWarningOpen] = React.useState(warnings.length > 0);
|
|
|
|
if (errors.length > 0) {
|
|
return (
|
|
<Box sx={{ p: 4, maxWidth: 700, mx: "auto", mt: 8 }}>
|
|
<Alert severity="error" sx={{ mb: 2 }}>
|
|
<Typography variant="h6" fontWeight={700}>
|
|
OpenAPI Spec Validation Failed
|
|
</Typography>
|
|
<Typography variant="body2">
|
|
The spec has {errors.length} error{errors.length > 1 ? "s" : ""}. Fix them before the admin panel can render.
|
|
</Typography>
|
|
</Alert>
|
|
<List dense>
|
|
{errors.map((e, i) => (
|
|
<ListItem key={i}>
|
|
<ListItemIcon sx={{ minWidth: 36 }}>
|
|
<ErrorIcon color="error" fontSize="small" />
|
|
</ListItemIcon>
|
|
<ListItemText primary={e.message} />
|
|
</ListItem>
|
|
))}
|
|
</List>
|
|
{warnings.length > 0 && (
|
|
<>
|
|
<Typography variant="subtitle2" sx={{ mt: 2, mb: 1, color: "text.secondary" }}>
|
|
Warnings ({warnings.length})
|
|
</Typography>
|
|
<List dense>
|
|
{warnings.map((w, i) => (
|
|
<ListItem key={i}>
|
|
<ListItemIcon sx={{ minWidth: 36 }}>
|
|
<WarningIcon color="warning" fontSize="small" />
|
|
</ListItemIcon>
|
|
<ListItemText primary={w.message} />
|
|
</ListItem>
|
|
))}
|
|
</List>
|
|
</>
|
|
)}
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Snackbar
|
|
open={warningOpen}
|
|
autoHideDuration={8000}
|
|
onClose={() => setWarningOpen(false)}
|
|
anchorOrigin={{ vertical: "bottom", horizontal: "center" }}
|
|
>
|
|
<Box>
|
|
{warnings.map((w, i) => (
|
|
<Alert key={i} severity="warning" sx={{ mb: 1 }} onClose={() => setWarningOpen(false)}>
|
|
{w.message}
|
|
</Alert>
|
|
))}
|
|
</Box>
|
|
</Snackbar>
|
|
);
|
|
}
|