feature: add actions for edit and delete

This commit is contained in:
Rodolfo Ruiz
2025-06-25 20:07:31 -06:00
parent 03022206ae
commit c9de10c46e
4 changed files with 145 additions and 84 deletions

View File

@@ -1,13 +0,0 @@
export async function getExternalData() {
try {
const response = await fetch('http://portainer.white-enciso.pro:4001/api/v1/MongoSample/GetAll');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error('Failed to fetch data:', error);
return [];
}
}

65
src/api/mongo/actions.jsx Normal file
View File

@@ -0,0 +1,65 @@
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 [];
}
}
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;
}
}
export async function updateExternalData(data) {
const response = await fetch(`${API_BASE_URL}/Update`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
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;
}
}

View File

@@ -1,12 +1,6 @@
import { useEffect, useState } from 'react'; import { useState, useEffect } from 'react';
import { import { Box, Button, TextField, MenuItem } from '@mui/material';
Box, import { createExternalData, updateExternalData } from '../../api/mongo/actions';
Button,
TextField,
Typography,
Paper,
MenuItem
} from '@mui/material';
export default function AddOrEditAdminForm({ onAdd, initialData, onCancel }) { export default function AddOrEditAdminForm({ onAdd, initialData, onCancel }) {
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
@@ -17,7 +11,7 @@ export default function AddOrEditAdminForm({ onAdd, initialData, onCancel }) {
useEffect(() => { useEffect(() => {
if (initialData) { if (initialData) {
setFormData(initialData); setFormData({ ...initialData });
} else { } else {
setFormData({ setFormData({
name: '', name: '',
@@ -29,25 +23,25 @@ export default function AddOrEditAdminForm({ onAdd, initialData, onCancel }) {
const handleChange = (e) => { const handleChange = (e) => {
const { name, value } = e.target; const { name, value } = e.target;
setFormData((prev) => ({ setFormData(prev => ({ ...prev, [name]: value }));
...prev,
[name]: value
}));
}; };
const handleSubmit = () => { const handleSubmit = async () => {
if (onAdd) { try {
onAdd(formData); if (initialData) {
await updateExternalData(formData);
} else {
await createExternalData(formData);
}
if (onAdd) onAdd();
} catch (error) {
console.error('Error submitting form:', error);
} }
}; };
return ( return (
<Box sx={{ px: 2, py: 3 }}>
<Paper elevation={0} sx={{ bgcolor: '#f9f9f9', p: 2, borderRadius: 2 }}>
<Typography variant="h6" gutterBottom>
Item details
</Typography>
<Box sx={{ py: 2 }}>
<TextField <TextField
fullWidth fullWidth
label="Name" label="Name"
@@ -56,7 +50,6 @@ export default function AddOrEditAdminForm({ onAdd, initialData, onCancel }) {
onChange={handleChange} onChange={handleChange}
margin="normal" margin="normal"
/> />
<TextField <TextField
fullWidth fullWidth
label="Description" label="Description"
@@ -65,10 +58,9 @@ export default function AddOrEditAdminForm({ onAdd, initialData, onCancel }) {
onChange={handleChange} onChange={handleChange}
margin="normal" margin="normal"
/> />
<TextField <TextField
select
fullWidth fullWidth
select
label="Status" label="Status"
name="status" name="status"
value={formData.status} value={formData.status}
@@ -78,16 +70,11 @@ export default function AddOrEditAdminForm({ onAdd, initialData, onCancel }) {
<MenuItem value="Active">Active</MenuItem> <MenuItem value="Active">Active</MenuItem>
<MenuItem value="Inactive">Inactive</MenuItem> <MenuItem value="Inactive">Inactive</MenuItem>
</TextField> </TextField>
<Box display="flex" justifyContent="flex-end" mt={3} gap={1}>
<Box display="flex" justifyContent="flex-end" gap={1} mt={3}> <Button onClick={onCancel} className="button-transparent">Cancel</Button>
<Button onClick={onCancel} className="button-transparent"> <Button variant="contained" onClick={handleSubmit} className="button-gold">Save</Button>
Cancel
</Button>
<Button variant="contained" onClick={handleSubmit} className="button-gold">
Save
</Button>
</Box> </Box>
</Paper>
</Box> </Box>
); );
} }

View File

@@ -5,7 +5,7 @@ import { Typography, Button, Dialog, DialogTitle, DialogContent, IconButton, Box
import EditRoundedIcon from '@mui/icons-material/EditRounded'; import EditRoundedIcon from '@mui/icons-material/EditRounded';
import DeleteRoundedIcon from '@mui/icons-material/DeleteRounded'; import DeleteRoundedIcon from '@mui/icons-material/DeleteRounded';
import AddOrEditAdminForm from './AddOrEditAdminForm'; import AddOrEditAdminForm from './AddOrEditAdminForm';
import { getExternalData } from '../../api/actions'; import { getExternalData, deleteExternalData } from '../../api/mongo/actions';
const columnsBase = [ const columnsBase = [
{ field: 'name', headerName: 'Name', flex: 2 }, { field: 'name', headerName: 'Name', flex: 2 },
@@ -41,13 +41,23 @@ export default function Admin() {
const [rowToDelete, setRowToDelete] = useState(null); const [rowToDelete, setRowToDelete] = useState(null);
useEffect(() => { useEffect(() => {
getExternalData().then(data => { let isMounted = true;
getExternalData()
.then(data => {
if (isMounted) {
const safeData = Array.isArray(data) ? data : []; const safeData = Array.isArray(data) ? data : [];
setRows(safeData); setRows(safeData);
}).catch(error => { }
})
.catch(error => {
console.error('Error loading data:', error); console.error('Error loading data:', error);
setRows([]); if (isMounted) setRows([]);
}); });
return () => {
isMounted = false;
};
}, []); }, []);
const handleEditClick = (params) => { const handleEditClick = (params) => {
@@ -60,6 +70,18 @@ export default function Admin() {
setConfirmOpen(true); setConfirmOpen(true);
}; };
const handleConfirmDelete = async () => {
try {
await deleteExternalData(rowToDelete._Id);
setRows((prevRows) => prevRows.filter(r => r._Id !== rowToDelete._Id));
} catch (error) {
console.error('Delete failed:', error);
} finally {
setConfirmOpen(false);
setRowToDelete(null);
}
};
const columns = [ const columns = [
...columnsBase, ...columnsBase,
{ {
@@ -118,7 +140,7 @@ export default function Admin() {
</Typography> </Typography>
<Box mt={2} display="flex" justifyContent="flex-end" gap={1}> <Box mt={2} display="flex" justifyContent="flex-end" gap={1}>
<Button onClick={() => setConfirmOpen(false)} className='button-transparent'>Cancel</Button> <Button onClick={() => setConfirmOpen(false)} className='button-transparent'>Cancel</Button>
<Button variant="contained" onClick={() => { }} className="button-gold">Delete</Button> <Button variant="contained" onClick={handleConfirmDelete} className="button-gold">Delete</Button>
</Box> </Box>
</DialogContent> </DialogContent>
</Dialog> </Dialog>