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