feat: add toast when endpoints are failing

This commit is contained in:
Rodolfo Ruiz
2025-07-03 17:23:09 -06:00
parent 2849ee2e6b
commit eb49416000
6 changed files with 91 additions and 48 deletions

41
package-lock.json generated
View File

@@ -14,6 +14,7 @@
"@mui/icons-material": "^7.1.0",
"@mui/material": "^7.1.0",
"@mui/x-data-grid": "^8.5.0",
"notistack": "^3.0.2",
"react": "^19.1.0",
"react-dom": "^19.1.0"
},
@@ -2993,6 +2994,15 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/goober": {
"version": "2.1.16",
"resolved": "https://registry.npmjs.org/goober/-/goober-2.1.16.tgz",
"integrity": "sha512-erjk19y1U33+XAMe1VTvIONHYoSqE4iS7BYUZfHaqeohLmnC0FdxEh7rQU+6MZ4OajItzjZFSRtVANrQwNq6/g==",
"license": "MIT",
"peerDependencies": {
"csstype": "^3.0.10"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
@@ -3461,6 +3471,37 @@
"dev": true,
"license": "MIT"
},
"node_modules/notistack": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/notistack/-/notistack-3.0.2.tgz",
"integrity": "sha512-0R+/arLYbK5Hh7mEfR2adt0tyXJcCC9KkA2hc56FeWik2QN6Bm/S4uW+BjzDARsJth5u06nTjelSw/VSnB1YEA==",
"license": "MIT",
"dependencies": {
"clsx": "^1.1.0",
"goober": "^2.0.33"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=6.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/notistack"
},
"peerDependencies": {
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/notistack/node_modules/clsx": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
"integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",

View File

@@ -16,6 +16,7 @@
"@mui/icons-material": "^7.1.0",
"@mui/material": "^7.1.0",
"@mui/x-data-grid": "^8.5.0",
"notistack": "^3.0.2",
"react": "^19.1.0",
"react-dom": "^19.1.0"
},

View File

@@ -1,65 +1,44 @@
const API_BASE_URL = 'http://portainer.white-enciso.pro:4001/api/v1/MongoSample';
export async function getExternalData() {
try {
const response = await fetch(`${API_BASE_URL}/GetAll`);
if (!response.ok) throw new Error('Failed to fetch external data');
const data = await response.json();
return data;
} catch (error) {
console.error('Error fetching external data:', error);
return [];
}
const response = await fetch(`${API_BASE_URL}/GetAll`);
if (!response.ok) throw new Error('Failed to fetch external data');
const data = await response.json();
return data;
}
export async function createExternalData(data) {
try {
const response = await fetch(`${API_BASE_URL}/Create`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
if (!response.ok) throw new Error('Failed to create external data');
const result = await response.json();
return result;
} catch (error) {
console.error('Error creating external data:', error);
throw error;
}
const response = await fetch(`${API_BASE_URL}/Create`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
if (!response.ok) throw new Error('Failed to create external data');
return await response.json();
}
export async function updateExternalData(data) {
const response = await fetch(`${API_BASE_URL}/Update`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
body: JSON.stringify(data),
});
if (!response.ok) {
throw new Error('Failed to update item');
}
if (!response.ok) throw new Error('Failed to update item');
return await response.json();
}
export async function deleteExternalData(_Id) {
try {
const response = await fetch(`${API_BASE_URL}/Delete`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ _Id }),
});
if (!response.ok) throw new Error('Failed to delete external data');
return await response.json();
} catch (error) {
console.error('Error deleting external data:', error);
throw error;
}
const response = await fetch(`${API_BASE_URL}/Delete`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ _Id }),
});
if (!response.ok) throw new Error('Failed to delete external data');
return await response.json();
}

12
src/hooks/useApiToast.jsx Normal file
View File

@@ -0,0 +1,12 @@
import { useSnackbar } from 'notistack';
export default function useApiToast() {
const { enqueueSnackbar } = useSnackbar();
const handleError = (error, defaultMessage = 'API error') => {
console.error(error);
enqueueSnackbar(error.message || defaultMessage, { variant: 'error' });
};
return { handleError };
}

View File

@@ -1,6 +1,6 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { SnackbarProvider } from 'notistack';
import { ThemeProvider } from '@mui/material/styles';
import theme from './theme';
import './index.css'
@@ -9,7 +9,14 @@ import App from './App.jsx'
createRoot(document.getElementById('root')).render(
<StrictMode>
<ThemeProvider theme={theme}>
<App />
<SnackbarProvider maxSnack={3}
autoHideDuration={5000}
anchorOrigin={{
vertical: 'top',
horizontal: 'right',
}}>
<App />
</SnackbarProvider>
</ThemeProvider>
</StrictMode>,
)

View File

@@ -6,6 +6,7 @@ import EditRoundedIcon from '@mui/icons-material/EditRounded';
import DeleteRoundedIcon from '@mui/icons-material/DeleteRounded';
import AddOrEditAdminForm from './AddOrEditAdminForm';
import { getExternalData, deleteExternalData } from '../../api/mongo/actions';
import useApiToast from '../../hooks/useApiToast';
const columnsBase = [
{ field: 'name', headerName: 'Name', flex: 2 },
@@ -39,6 +40,7 @@ export default function Admin() {
const [editingData, setEditingData] = useState(null);
const [confirmOpen, setConfirmOpen] = useState(false);
const [rowToDelete, setRowToDelete] = useState(null);
const { handleError } = useApiToast();
useEffect(() => {
let isMounted = true;
@@ -75,6 +77,7 @@ export default function Admin() {
setRows(safeData);
} catch (error) {
console.error('Error loading data:', error);
handleError(error, 'Failed to load data');
setRows([]);
}
};