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 {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" > ))}
{editingKreditor ? 'Kreditor bearbeiten' : 'Neuer Kreditor'} } label="Banking-Konto (z.B. PayPal) - benötigt manuelle Kreditor-Zuordnung" /> {/* Confirmation Dialog */} Löschen bestätigen {this.state.itemToDelete && `Kreditor "${this.state.itemToDelete.name}" wirklich löschen?` }
); } } export default KreditorTable;