import React, { Component } from 'react';
import {
Box,
Button,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Paper,
Dialog,
DialogTitle,
DialogContent,
DialogActions,
TextField,
IconButton,
Typography,
Alert,
CircularProgress,
Checkbox,
FormControlLabel,
} from '@mui/material';
import {
Add as AddIcon,
Edit as EditIcon,
Delete as DeleteIcon,
} from '@mui/icons-material';
import AuthService from '../../services/AuthService';
class KreditorTable extends Component {
constructor(props) {
super(props);
this.state = {
kreditoren: [],
loading: true,
error: null,
dialogOpen: false,
editingKreditor: null,
confirmDialogOpen: false,
itemToDelete: null,
formData: {
iban: '',
name: '',
kreditorId: '',
is_banking: false,
},
};
this.authService = new AuthService();
// Focus management refs
this.triggerRef = React.createRef();
this.dialogRef = React.createRef();
this.confirmDialogRef = React.createRef();
}
componentDidMount() {
this.loadKreditoren();
}
loadKreditoren = async () => {
try {
const response = await this.authService.apiCall('/admin/kreditoren');
if (response && response.ok) {
const data = await response.json();
this.setState({ kreditoren: data.kreditoren, loading: false });
} else {
this.setState({ error: 'Fehler beim Laden der Kreditoren', loading: false });
}
} catch (error) {
console.error('Error loading kreditoren:', error);
this.setState({ error: 'Fehler beim Laden der Kreditoren', loading: false });
}
};
handleOpenDialog = (kreditor = null) => {
// Store reference to the trigger element for focus restoration
this.triggerRef.current = document.activeElement;
this.setState({
dialogOpen: true,
editingKreditor: kreditor,
formData: kreditor ? {
iban: kreditor.iban || '',
name: kreditor.name,
kreditorId: kreditor.kreditorId,
is_banking: Boolean(kreditor.is_banking),
} : {
iban: '',
name: '',
kreditorId: '',
is_banking: false,
},
});
};
handleCloseDialog = () => {
this.setState({
dialogOpen: false,
editingKreditor: null,
formData: {
iban: '',
name: '',
kreditorId: '',
is_banking: false,
},
});
// Restore focus to the trigger element after dialog closes
setTimeout(() => {
if (this.triggerRef.current && this.triggerRef.current.focus) {
this.triggerRef.current.focus();
}
}, 100);
};
handleInputChange = (field) => (event) => {
this.setState({
formData: {
...this.state.formData,
[field]: event.target.value,
},
});
};
handleCheckboxChange = (field) => (event) => {
this.setState({
formData: {
...this.state.formData,
[field]: event.target.checked,
},
});
};
isFormValid = () => {
const { formData } = this.state;
// Name and kreditorId are always required
const basicFieldsValid = formData.name.trim() !== '' && formData.kreditorId.trim() !== '';
// IBAN is optional for banking accounts, required for regular kreditors
const ibanValid = formData.is_banking || formData.iban.trim() !== '';
return basicFieldsValid && ibanValid;
};
handleSave = async () => {
const { editingKreditor, formData } = this.state;
try {
const url = editingKreditor
? `/admin/kreditoren/${editingKreditor.id}`
: '/admin/kreditoren';
const method = editingKreditor ? 'PUT' : 'POST';
const response = await this.authService.apiCall(url, {
method,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formData),
});
if (response && response.ok) {
this.handleCloseDialog();
this.loadKreditoren();
} else {
const errorData = await response.json();
this.setState({ error: errorData.error || 'Fehler beim Speichern' });
}
} catch (error) {
console.error('Error saving kreditor:', error);
this.setState({ error: 'Fehler beim Speichern des Kreditors' });
}
};
handleDeleteClick = (kreditor) => {
// Store reference to the trigger element for focus restoration
this.triggerRef.current = document.activeElement;
this.setState({
confirmDialogOpen: true,
itemToDelete: kreditor,
});
};
handleDeleteConfirm = async () => {
const { itemToDelete } = this.state;
if (!itemToDelete) return;
this.setState({ confirmDialogOpen: false, itemToDelete: null });
// Restore focus to the trigger element after dialog closes
setTimeout(() => {
if (this.triggerRef.current && this.triggerRef.current.focus) {
this.triggerRef.current.focus();
}
}, 100);
try {
const response = await this.authService.apiCall(`/admin/kreditoren/${kreditor.id}`, {
method: 'DELETE',
});
if (response && response.ok) {
this.loadKreditoren();
} else {
const errorData = await response.json();
this.setState({ error: errorData.error || 'Fehler beim Löschen' });
}
} catch (error) {
console.error('Error deleting kreditor:', error);
this.setState({ error: 'Fehler beim Löschen des Kreditors' });
}
};
handleDeleteCancel = () => {
this.setState({
confirmDialogOpen: false,
itemToDelete: null,
});
// Restore focus to the trigger element after dialog closes
setTimeout(() => {
if (this.triggerRef.current && this.triggerRef.current.focus) {
this.triggerRef.current.focus();
}
}, 100);
};
render() {
const { kreditoren, loading, error, dialogOpen, editingKreditor, formData } = this.state;
if (loading) {
return (
);
}
return (
Kreditoren
}
onClick={() => this.handleOpenDialog()}
>
Neuer Kreditor
{error && (
{error}
)}
Kreditor ID
Name
IBAN
Typ
Aktionen
{kreditoren.map((kreditor) => (
{kreditor.kreditorId}
{kreditor.name}
{kreditor.iban || 'Keine IBAN'}
{kreditor.is_banking ?
Banking :
'Kreditor'
}
this.handleOpenDialog(kreditor)}
>
this.handleDeleteClick(kreditor)}
color="error"
>
))}
{/* Confirmation Dialog */}
);
}
}
export default KreditorTable;