Enhance App component with view management by adding Tabs for Dashboard and Table views. Update DataViewer to receive current view and handle export data accordingly. Refactor BUTable to improve form validation and handle vst values more robustly. Update admin routes to ensure vst is correctly processed.
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
import React, { Component } from 'react';
|
||||
import { ThemeProvider, createTheme } from '@mui/material/styles';
|
||||
import CssBaseline from '@mui/material/CssBaseline';
|
||||
import { Container, AppBar, Toolbar, Typography, Button, Box } from '@mui/material';
|
||||
import { Container, AppBar, Toolbar, Typography, Button, Box, Tabs, Tab } from '@mui/material';
|
||||
import LoginIcon from '@mui/icons-material/Login';
|
||||
import DashboardIcon from '@mui/icons-material/Dashboard';
|
||||
import DownloadIcon from '@mui/icons-material/Download';
|
||||
import TableChart from '@mui/icons-material/TableChart';
|
||||
import AuthService from './services/AuthService';
|
||||
import DataViewer from './components/DataViewer';
|
||||
import Login from './components/Login';
|
||||
@@ -29,6 +30,7 @@ class App extends Component {
|
||||
user: null,
|
||||
loading: true,
|
||||
exportData: null, // { selectedMonth, canExport, onExport }
|
||||
currentView: 'dashboard', // 'dashboard' or 'tables'
|
||||
};
|
||||
this.authService = new AuthService();
|
||||
}
|
||||
@@ -77,8 +79,12 @@ class App extends Component {
|
||||
this.setState({ exportData });
|
||||
};
|
||||
|
||||
handleViewChange = (event, newValue) => {
|
||||
this.setState({ currentView: newValue });
|
||||
};
|
||||
|
||||
render() {
|
||||
const { isAuthenticated, user, loading } = this.state;
|
||||
const { isAuthenticated, user, loading, currentView } = this.state;
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
@@ -99,7 +105,7 @@ class App extends Component {
|
||||
<AppBar position="static">
|
||||
<Toolbar>
|
||||
<DashboardIcon sx={{ mr: { xs: 1, sm: 2 } }} />
|
||||
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
|
||||
<Typography variant="h6" component="div" sx={{ mr: 3 }}>
|
||||
FibDash
|
||||
</Typography>
|
||||
{isAuthenticated && user && (
|
||||
@@ -107,12 +113,42 @@ class App extends Component {
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{
|
||||
mr: { xs: 1, sm: 2 },
|
||||
mr: { xs: 2, sm: 3 },
|
||||
display: { xs: 'none', sm: 'block' }
|
||||
}}
|
||||
>
|
||||
Willkommen, {user.name}
|
||||
</Typography>
|
||||
<Tabs
|
||||
value={currentView}
|
||||
onChange={this.handleViewChange}
|
||||
sx={{
|
||||
mr: 'auto',
|
||||
'& .MuiTab-root': {
|
||||
color: 'rgba(255, 255, 255, 0.7)',
|
||||
minHeight: 48,
|
||||
'&.Mui-selected': {
|
||||
color: 'white'
|
||||
}
|
||||
},
|
||||
'& .MuiTabs-indicator': {
|
||||
backgroundColor: 'white'
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Tab
|
||||
icon={<DashboardIcon />}
|
||||
label="Dashboard"
|
||||
value="dashboard"
|
||||
sx={{ minHeight: 48 }}
|
||||
/>
|
||||
<Tab
|
||||
icon={<TableChart />}
|
||||
label="Stammdaten"
|
||||
value="tables"
|
||||
sx={{ minHeight: 48 }}
|
||||
/>
|
||||
</Tabs>
|
||||
{this.state.exportData && (
|
||||
<Button
|
||||
color="inherit"
|
||||
@@ -153,7 +189,12 @@ class App extends Component {
|
||||
<Box sx={{ height: 'calc(100vh - 64px)', display: 'flex', flexDirection: 'column' }}>
|
||||
<Container maxWidth={false} sx={{ mt: 4, flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column', width: '100%' }}>
|
||||
{isAuthenticated ? (
|
||||
<DataViewer user={user} onUpdateExportData={this.updateExportData} />
|
||||
<DataViewer
|
||||
user={user}
|
||||
onUpdateExportData={this.updateExportData}
|
||||
currentView={currentView}
|
||||
onViewChange={this.handleViewChange}
|
||||
/>
|
||||
) : (
|
||||
<Login onLogin={this.handleLogin} />
|
||||
)}
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
import AuthService from '../services/AuthService';
|
||||
import SummaryHeader from './SummaryHeader';
|
||||
import TransactionsTable from './TransactionsTable';
|
||||
import Navigation from './Navigation';
|
||||
import Dashboard from './Dashboard';
|
||||
import TableManagement from './TableManagement';
|
||||
|
||||
@@ -21,7 +20,7 @@ class DataViewer extends Component {
|
||||
summary: null,
|
||||
loading: true,
|
||||
error: null,
|
||||
currentView: 'dashboard', // 'dashboard' or 'tables'
|
||||
|
||||
};
|
||||
this.authService = new AuthService();
|
||||
}
|
||||
@@ -114,21 +113,17 @@ class DataViewer extends Component {
|
||||
if (this.props.onUpdateExportData) {
|
||||
this.props.onUpdateExportData({
|
||||
selectedMonth,
|
||||
canExport: !!selectedMonth && !this.state.loading && this.state.currentView === 'dashboard',
|
||||
canExport: !!selectedMonth && !this.state.loading && this.props.currentView === 'dashboard',
|
||||
onExport: this.downloadDatev
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleViewChange = (event, newView) => {
|
||||
this.setState({ currentView: newView });
|
||||
// Update export data when view changes
|
||||
this.updateExportData();
|
||||
};
|
||||
|
||||
|
||||
render() {
|
||||
const { months, selectedMonth, transactions, summary, loading, error, currentView } = this.state;
|
||||
const { user } = this.props;
|
||||
const { months, selectedMonth, transactions, summary, loading, error } = this.state;
|
||||
const { user, currentView } = this.props;
|
||||
|
||||
if (loading && !transactions.length) {
|
||||
return (
|
||||
@@ -148,11 +143,6 @@ class DataViewer extends Component {
|
||||
|
||||
return (
|
||||
<Box sx={{ height: '100vh', display: 'flex', flexDirection: 'column' }}>
|
||||
<Navigation
|
||||
currentView={currentView}
|
||||
onViewChange={this.handleViewChange}
|
||||
/>
|
||||
|
||||
{currentView === 'dashboard' ? (
|
||||
<>
|
||||
<Box sx={{ flexShrink: 0 }}>
|
||||
|
||||
@@ -72,7 +72,7 @@ class BUTable extends Component {
|
||||
formData: bu ? {
|
||||
bu: bu.bu,
|
||||
name: bu.name,
|
||||
vst: bu.vst || '',
|
||||
vst: bu.vst !== null && bu.vst !== undefined ? bu.vst.toString() : '',
|
||||
} : {
|
||||
bu: '',
|
||||
name: '',
|
||||
@@ -102,13 +102,20 @@ class BUTable extends Component {
|
||||
});
|
||||
};
|
||||
|
||||
isFormValid = () => {
|
||||
const { formData } = this.state;
|
||||
return formData.bu.trim() !== '' &&
|
||||
formData.name.trim() !== '' &&
|
||||
formData.vst !== '';
|
||||
};
|
||||
|
||||
handleSave = async () => {
|
||||
const { editingBU, formData } = this.state;
|
||||
|
||||
// Convert vst to number or null
|
||||
const payload = {
|
||||
...formData,
|
||||
vst: formData.vst ? parseFloat(formData.vst) : null,
|
||||
vst: formData.vst !== '' ? parseFloat(formData.vst) : null,
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -220,7 +227,7 @@ class BUTable extends Component {
|
||||
<TableCell>{bu.bu}</TableCell>
|
||||
<TableCell>{bu.name}</TableCell>
|
||||
<TableCell align="right">
|
||||
{bu.vst ? `${bu.vst}%` : '-'}
|
||||
{bu.vst !== null && bu.vst !== undefined ? `${bu.vst}%` : '-'}
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
<IconButton
|
||||
@@ -287,7 +294,11 @@ class BUTable extends Component {
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={this.handleCloseDialog}>Abbrechen</Button>
|
||||
<Button onClick={this.handleSave} variant="contained">
|
||||
<Button
|
||||
onClick={this.handleSave}
|
||||
variant="contained"
|
||||
disabled={!this.isFormValid()}
|
||||
>
|
||||
Speichern
|
||||
</Button>
|
||||
</DialogActions>
|
||||
|
||||
@@ -199,7 +199,7 @@ router.post('/buchungsschluessel', authenticateToken, async (req, res) => {
|
||||
try {
|
||||
await executeQuery(
|
||||
'INSERT INTO fibdash.BU (bu, name, vst) VALUES (@bu, @name, @vst)',
|
||||
{ bu, name, vst: vst || null }
|
||||
{ bu, name, vst: vst !== undefined && vst !== '' ? vst : null }
|
||||
);
|
||||
res.json({ message: 'Buchungsschlüssel erfolgreich erstellt' });
|
||||
} catch (error) {
|
||||
@@ -224,7 +224,7 @@ router.put('/buchungsschluessel/:id', authenticateToken, async (req, res) => {
|
||||
try {
|
||||
await executeQuery(
|
||||
'UPDATE fibdash.BU SET bu = @bu, name = @name, vst = @vst WHERE id = @id',
|
||||
{ bu, name, vst: vst || null, id }
|
||||
{ bu, name, vst: vst !== undefined && vst !== '' ? vst : null, id }
|
||||
);
|
||||
res.json({ message: 'Buchungsschlüssel erfolgreich aktualisiert' });
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user