From 40cb84c31e42cdc16f23d74c9db453ea2b416178 Mon Sep 17 00:00:00 2001 From: kmiola <kmiola@ethz.ch> Date: Sat, 16 Nov 2024 11:28:35 +0000 Subject: [PATCH] fetch creditpayments, list as table, first filters working --- src/pages/CreditPaymentsList.tsx | 237 ++++++++++++++++++++++++++----- src/pages/index.tsx | 16 +-- src/pages/root.tsx | 3 +- 3 files changed, 210 insertions(+), 46 deletions(-) diff --git a/src/pages/CreditPaymentsList.tsx b/src/pages/CreditPaymentsList.tsx index cfdc751..17a85ef 100644 --- a/src/pages/CreditPaymentsList.tsx +++ b/src/pages/CreditPaymentsList.tsx @@ -1,10 +1,8 @@ -import React, { useEffect, useState } from 'react'; -import { Container, CircularProgress, Typography, Card, Stack, Button } from '@mui/material'; -import { creditPaymentsReadCreditPayments } from '../client/services.gen'; -import { CreditPaymentPublic_Output, CreditPaymentsList } from '../client/types.gen'; - - -import { client } from '../client/services.gen'; // Adjust this path based on where your generated client is located +import React, { useState, useEffect } from 'react'; +import { Container, CircularProgress, Typography, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Alert, TextField, FormControl, InputLabel, Select, MenuItem } from '@mui/material'; +import { creditPaymentsReadCreditPayments, reimbursementsReadReimbursements, client, ledgersReadLedgers, kstsReadKsts } from '../client/services.gen'; // Adjust this path based on where your generated client is located +import { CreditPaymentPublic_Output, CreditPaymentsList, ReimbursementsList, ReimbursementPublic_Output, LedgerPublic, KstPublic } from '../client/types.gen'; +import { SelectChangeEvent } from '@mui/material/Select'; // Set the base URL and headers for the client client.setConfig({ @@ -16,8 +14,21 @@ client.setConfig({ export default function CreditPaymentsPage() { const [creditPayments, setCreditPayments] = useState<CreditPaymentPublic_Output[]>([]); + const [filteredPayments, setFilteredPayments] = useState<CreditPaymentPublic_Output[]>([]); + const [ledgerItems, setLedgerItems] = useState<LedgerPublic[]>([]); + const [kstItems, setKstItems] = useState<KstPublic[]>([]); const [loading, setLoading] = useState(true); const [error, setError] = useState<string | null>(null); + const [loadingLedger, setLoadingLedger] = useState(true); + const [errorLedger, setErrorLedger] = useState<string | null>(null); + const [loadingKst, setLoadingKst] = useState(true); + const [errorKst, setErrorKst] = useState<string | null>(null); + + const [filters, setFilters] = useState({ + kstId: '', + ledgerId: '', + amount: '', + }); const fetchCreditPayments = async () => { setLoading(true); @@ -35,52 +46,204 @@ export default function CreditPaymentsPage() { const creditPaymentsList = response.data as CreditPaymentsList; setCreditPayments(creditPaymentsList.items); + setFilteredPayments(creditPaymentsList.items); } catch (err) { - setError('Failed to load credit payments'); console.error('Error fetching credit payments:', err); + setError('Error fetching credit payments'); } finally { setLoading(false); } }; + const fetchLedgers = async () => { + setErrorLedger(null); + setLoadingLedger(true); + + try { + const response = await ledgersReadLedgers(); + + // Check if response is HTML, indicating a possible error + if (typeof response.data !== 'object' || !('items' in response.data)) { + console.error('Unexpected response format:', response.data); + setErrorLedger('Received unexpected response format from the server.'); + return; + } + + const ledgersList = response.data as { items: LedgerPublic[] }; + setLedgerItems(ledgersList.items); + } catch (err) { + setErrorLedger('Failed to load ledgers'); + console.error('Error fetching ledgers:', err); + } finally { + setLoadingLedger(false); + } + }; + + const fetchKsts = async () => { + setErrorKst(null); + setLoadingKst(true); + + try { + const response = await kstsReadKsts(); + + // Check if response is HTML, indicating a possible error + if (typeof response.data !== 'object' || !('items' in response.data)) { + console.error('Unexpected response format:', response.data); + setErrorKst('Received unexpected response format from the server.'); + return; + } + + const KstList = response.data as { items: KstPublic[] }; + setKstItems(KstList.items); + } catch (err) { + setErrorKst('Failed to load KSTs'); + console.error('Error fetching KSTs:', err); + } finally { + setLoadingKst(false); + } + }; + useEffect(() => { fetchCreditPayments(); + fetchLedgers(); + fetchKsts(); }, []); - if (loading) { - return ( - <Container> - <CircularProgress /> - </Container> - ); - } - - if (error) { - return ( - <Container> - <Typography color="error">{error}</Typography> - </Container> - ); - } + const getLedgerName = (ledgerId: string) => { + const ledger = ledgerItems.find((ledger) => ledger.id === ledgerId); + return ledger ? ledger.namede : ledgerId; + }; + + const getKstName = (KstId: string) => { + const kst = kstItems.find((kst) => kst.id === KstId); + return kst ? kst.name_de : KstId; + }; + + const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => { + const { name, value } = e.target; + setFilters({ + ...filters, + [name]: value, + }); + }; + + const handleSelectChange = (event: SelectChangeEvent<string>) => { + const { name, value } = event.target; + setFilters({ + ...filters, + [name]: value, + }); + }; + + useEffect(() => { + let filtered = creditPayments; + + if (filters.kstId) { + filtered = filtered.filter((payment) => payment.creditor.kst_id === filters.kstId); + } + + if (filters.ledgerId) { + filtered = filtered.filter((payment) => payment.creditor.ledger_id === filters.ledgerId); + } + + if (filters.amount) { + filtered = filtered.filter((payment) => payment.creditor.amount === Number(filters.amount)); + } + + setFilteredPayments(filtered); + }, [filters, creditPayments]); return ( <Container> <Typography variant="h4" component="h2" gutterBottom> Credit Payments </Typography> - <Button variant="contained" onClick={fetchCreditPayments} sx={{ mb: 2 }}> - Refresh List - </Button> - <Stack spacing={2}> - {creditPayments.map((payment) => ( - <Card key={payment.id} variant="outlined" sx={{ padding: 2 }}> - <Typography variant="h6">Payment ID: {payment.id}</Typography> - <Typography>Recipient: {payment.creator}</Typography> - <Typography>Name: {payment.name}</Typography> - <Typography>Receipt: {payment.recipt}</Typography> - </Card> - ))} - </Stack> + <FormControl fullWidth margin="normal"> + <InputLabel id="kst-filter-label">KST</InputLabel> + <Select + labelId="kst-filter-label" + name="kstId" + value={filters.kstId} + onChange={handleSelectChange} + > + <MenuItem value=""> + <em>None</em> + </MenuItem> + {kstItems.map((kst) => ( + <MenuItem key={kst.id} value={kst.id}> + {kst.name_de} + </MenuItem> + ))} + </Select> + </FormControl> + <FormControl fullWidth margin="normal"> + <InputLabel id="ledger-filter-label">Ledger</InputLabel> + <Select + labelId="ledger-filter-label" + name="ledgerId" + value={filters.ledgerId} + onChange={handleSelectChange} + > + <MenuItem value=""> + <em>None</em> + </MenuItem> + {ledgerItems.map((ledger) => ( + <MenuItem key={ledger.id} value={ledger.id}> + {ledger.namede} + </MenuItem> + ))} + </Select> + </FormControl> + <TextField + label="Amount" + name="amount" + value={filters.amount} + onChange={handleInputChange} + fullWidth + margin="normal" + /> + {loading || loadingLedger || loadingKst ? ( + <CircularProgress /> + ) : error ? ( + <Alert severity="error">{error}</Alert> + ) : errorLedger ? ( + <Alert severity="error">{errorLedger}</Alert> + ) : errorKst ? ( + <Alert severity="error">{errorKst}</Alert> + ) : ( + <TableContainer component={Paper}> + <Table> + <TableHead> + <TableRow> + <TableCell>Recipt</TableCell> + <TableCell>Card</TableCell> + <TableCell>KST</TableCell> + <TableCell>Ledger</TableCell> + <TableCell>Amount</TableCell> + <TableCell>Accounting Year</TableCell> + <TableCell>Currency</TableCell> + <TableCell>Comment</TableCell> + <TableCell>QComment</TableCell> + </TableRow> + </TableHead> + <TableBody> + {filteredPayments.map((payment) => ( + <TableRow key={payment.id}> + <TableCell>{payment.recipt}</TableCell> + <TableCell>{payment.card}</TableCell> + <TableCell>{getKstName(payment.creditor.kst_id)}</TableCell> + <TableCell>{getLedgerName(payment.creditor.ledger_id)}</TableCell> + <TableCell>{payment.creditor.amount}</TableCell> + <TableCell>{payment.creditor.accounting_year}</TableCell> + <TableCell>{payment.creditor.currency}</TableCell> + <TableCell>{payment.creditor.comment}</TableCell> + <TableCell>{payment.creditor.qcomment}</TableCell> + </TableRow> + ))} + </TableBody> + </Table> + </TableContainer> + )} </Container> ); -} +} \ No newline at end of file diff --git a/src/pages/index.tsx b/src/pages/index.tsx index c243b62..169ff84 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,22 +1,22 @@ - import React from "react"; -import { Container, CircularProgress } from "@mui/material"; +import { Container, CircularProgress, Typography, Box } from "@mui/material"; export default function Index() { return ( <Container sx={{ display: "flex", + flexDirection: "column", // Stack children vertically justifyContent: "center", - alignItems: "center", // Center vertically + alignItems: "center", // Center horizontally padding: 2, - height: "100vh" // Ensure full viewport height if needed + height: "100vh", // Ensure full viewport height }} - > + > + <Box sx={{ textAlign: "center", marginBottom: 2 }}> + <Typography variant="h6">This page is still work in Progress, but check out the pages in the side bar, you are up for a treat.</Typography> + </Box> <CircularProgress /> - </Container> ); } - - diff --git a/src/pages/root.tsx b/src/pages/root.tsx index a842e9a..068a240 100644 --- a/src/pages/root.tsx +++ b/src/pages/root.tsx @@ -1,6 +1,7 @@ import { AppBar, Toolbar, Typography, Button, useMediaQuery, Box, SxProps, IconButton, useTheme, ListItem, ListItemButton, ListItemIcon, ListItemText, List, Drawer, Checkbox, FormControlLabel, Divider} from "@mui/material"; import { Outlet, useLocation } from "react-router-dom"; import { Checklist, Groups, Home, Login, Logout, Menu, Payment, Settings, ShoppingCart } from "@mui/icons-material"; +import ReceiptIcon from "@mui/icons-material/Receipt"; // Import the Receipt icon import { Link } from "react-router-dom"; import { useContext, useEffect, useState } from "react"; import AmivLogoSVG from '../assets/amiv.svg'; @@ -16,7 +17,7 @@ const navContent = [ { path: "/Belegformular", name: "Belegformular", - icon: <Payment /> + icon: <ReceiptIcon /> }, { path: "/GenerateItem", -- GitLab