From ad20f58b415fac65854a9d27b76f677186ac7714 Mon Sep 17 00:00:00 2001
From: kmiola <kmiola@ethz.ch>
Date: Sat, 16 Nov 2024 00:46:29 +0000
Subject: [PATCH] implement bill, credit and reimbursement form on one page,
 connection to backend works, kst and ledgers are added as dropdown

---
 src/pages/Belegformular.tsx | 341 +++---------------------------
 src/pages/Bills.tsx         | 411 ++++++++++++++++++++++++++++++++++++
 src/pages/CreditPayment.tsx | 322 ++++++++++++++++++++++++++++
 src/pages/Reimbursement.tsx | 322 ++++++++++++++++++++++++++++
 4 files changed, 1089 insertions(+), 307 deletions(-)
 create mode 100644 src/pages/Bills.tsx
 create mode 100644 src/pages/CreditPayment.tsx
 create mode 100644 src/pages/Reimbursement.tsx

diff --git a/src/pages/Belegformular.tsx b/src/pages/Belegformular.tsx
index 45c64dc..8846d49 100644
--- a/src/pages/Belegformular.tsx
+++ b/src/pages/Belegformular.tsx
@@ -1,322 +1,49 @@
-import React, { useState, useEffect } from 'react';
-import { Container, CircularProgress, Typography, Select, MenuItem, FormControl, InputLabel, Stack, Button, TextField, Alert } from '@mui/material';
-import { kstsReadKsts, reimbursementsCreateReimbursement, ledgersReadLedgers } from '../client/services.gen';
-import { KstsPublic, KstPublic, ReimbursementsCreateReimbursementData, LedgersPublic, LedgerPublic } from '../client/types.gen';
-import { SelectChangeEvent } from '@mui/material/Select';
+import React, { useState } from 'react';
+import { Container, FormControl, InputLabel, Select, MenuItem, Typography, SelectChangeEvent } from '@mui/material';
+import Reimbursement from './Reimbursement';
+import Bills from './Bills';
+import CreditPayment from './CreditPayment';
 
-import { client } from '../client/services.gen';
+const MainForm: React.FC = () => {
+  const [selectedType, setSelectedType] = useState<string>('');
 
-// Configure the client
-client.setConfig({
-  baseUrl: import.meta.env.VITE_API_BASE_URL,
-  headers: {
-    Origin: `localhost`,
-  },
-});
-
-const Belegformular: React.FC = () => {
-  const [kstItems, setKstItems] = useState<KstPublic[]>([]);
-  const [ledgerItems, setLedgerItems] = useState<LedgerPublic[]>([]);
-  const [loadingKst, setLoadingKst] = useState(true);
-  const [loadingLedger, setLoadingLedger] = useState(true);
-  const [errorKst, setErrorKst] = useState<string | null>(null);
-  const [errorLedger, setErrorLedger] = useState<string | null>(null);
-
-  const [formData, setFormData] = useState<ReimbursementsCreateReimbursementData>({
-    body: {
-      creditor: {
-        kst_id: '',
-        ledger_id: '',
-        amount: 0,
-        accounting_year: 2024,
-        currency: 'CHF',
-        comment: '',
-        qcomment: '',
-      },
-      recipt: '',
-      creator: '',
-      recipient: '',
-    },
-  });
-
-  const [error, setError] = useState<string | null>(null);
-  const [success, setSuccess] = useState<string | null>(null);
-  const [validationErrors, setValidationErrors] = useState<Record<string, string>>({});
-
-  const fetchKsts = async () => {
-    setErrorKst(null);
-    setLoadingKst(true);
-
-    try {
-      const responseKst = await kstsReadKsts();
-
-      // Check if response is HTML, indicating a possible error
-      if (typeof responseKst.data !== 'object' || !('items' in responseKst.data)) {
-        console.error('Unexpected response format:', responseKst.data);
-        setErrorKst('Received unexpected response format from the server.');
-        return;
-      }
-
-      const KstList = responseKst.data as KstsPublic;
-      if (!KstList.items) {
-        setErrorKst('No KSTs found');
-        return;
-      }
-      setKstItems(KstList.items);
-    } catch (err) {
-      setErrorKst('Failed to load KSTs');
-      console.error('Error fetching KSTs:', err);
-    } finally {
-      setLoadingKst(false);
-    }
+  const handleTypeChange = (event: SelectChangeEvent<string>) => {
+    setSelectedType(event.target.value as string);
   };
 
-  const fetchLedgers = async () => {
-    setErrorLedger(null);
-    setLoadingLedger(true);
-
-    try {
-      const responseLedger = await ledgersReadLedgers();
-
-      // Check if response is HTML, indicating a possible error
-      if (typeof responseLedger.data !== 'object' || !('items' in responseLedger.data)) {
-        console.error('Unexpected response format:', responseLedger.data);
-        setErrorLedger('Received unexpected response format from the server.');
-        return;
-      }
-
-      const LedgerList = responseLedger.data as LedgersPublic;
-      if (!LedgerList.items) {
-        setErrorLedger('No Ledgers found');
-        return;
-      }
-      setLedgerItems(LedgerList.items);
-    } catch (err) {
-      setErrorLedger('Failed to load Ledgers');
-      console.error('Error fetching Ledgers:', err);
-    } finally {
-      setLoadingLedger(false);
-    }
-  };
-
-  useEffect(() => {
-    fetchKsts();
-    fetchLedgers();
-  }, []);
-
-  const handleChange = (e: React.ChangeEvent<{ name?: string; value: unknown }>) => {
-    const { name, value } = e.target as HTMLInputElement;
-
-    const keys = name.split('.'); // Handle nested keys like creditor.kst_id
-    const updatedFormData = { ...formData };
-
-    let current = updatedFormData.body as any; // Use `any` for dynamic nested updates
-    for (let i = 0; i < keys.length - 1; i++) {
-      current = current[keys[i]];
-    }
-    current[keys[keys.length - 1]] = value;
-
-    setFormData(updatedFormData);
-  };
-
-  const handleSelectChange = (event: SelectChangeEvent<string>) => {
-    const { name, value } = event.target;
-    setFormData((prevFormData) => ({
-      ...prevFormData,
-      body: {
-        ...prevFormData.body,
-        creditor: {
-          ...prevFormData.body.creditor,
-          [name]: value,
-        },
-      },
-    }));
-  };
-
-  const validateForm = (): boolean => {
-    let isValid = true;
-    const errors: Record<string, string> = {};
-
-    if (!formData.body.creditor.kst_id.trim()) {
-      errors['creditor.kst_id'] = 'KST-ID is required';
-      isValid = false;
-    }
-    if (!formData.body.creditor.ledger_id.trim()) {
-      errors['creditor.ledger_id'] = 'Ledger-ID is required';
-      isValid = false;
-    }
-    if (!formData.body.creditor.amount || formData.body.creditor.amount <= 0) {
-      errors['creditor.amount'] = 'Amount must be greater than zero';
-    }
-
-    // Set validation errors if any
-    setValidationErrors(errors);
-    return isValid;
-  };
-
-  const handleSubmit = async () => {
-    setError(null);
-    setSuccess(null);
-    if (!validateForm()) {
-      return;
-    }
-    try {
-      await reimbursementsCreateReimbursement(formData);
-      setSuccess('Reimbursement created successfully!');
-      setFormData({
-        body: {
-          creditor: {
-            kst_id: '',
-            ledger_id: '',
-            amount: 0,
-            accounting_year: 2024,
-            currency: 'CHF',
-            comment: '',
-            qcomment: '',
-          },
-          recipt: '',
-          creator: '',
-          recipient: '',
-        },
-      });
-    } catch (err) {
-      setError('Failed to create reimbursement.');
-      console.error('Error creating reimbursement:', err);
+  const renderForm = () => {
+    switch (selectedType) {
+      case 'beleg':
+        return <Reimbursement />;
+      case 'bill':
+        return <Bills />
+        case 'creditPayment':
+            return <CreditPayment />
+      default:
+        return null;
     }
   };
 
   return (
     <Container>
       <Typography variant="h4" component="h2" gutterBottom>
-        Create New Reimbursement
+        Select Form Type
       </Typography>
-
-      {success && <Alert severity="success">{success}</Alert>}
-      {error && <Alert severity="error">{error}</Alert>}
-
-      <Stack spacing={2} sx={{ mt: 2 }}>
-        <FormControl fullWidth required error={!!validationErrors['creditor.kst_id']}>
-          <InputLabel id="kst-id-label">KST ID</InputLabel>
-          <Select
-            labelId="kst-id-label"
-            name="kst_id"
-            value={formData.body.creditor.kst_id}
-            onChange={handleSelectChange}
-          >
-            {kstItems.map((item) => (
-              <MenuItem key={item.id} value={item.id}>
-                {item.name_de}
-              </MenuItem>
-            ))}
-          </Select>
-          {validationErrors['creditor.kst_id'] && (
-            <Typography color="error">{validationErrors['creditor.kst_id']}</Typography>
-          )}
-        </FormControl>
-        <FormControl fullWidth required error={!!validationErrors['creditor.ledger_id']}>
-          <InputLabel id="ledger-id-label">Ledger ID</InputLabel>
-          <Select
-            labelId="ledger-id-label"
-            name="ledger_id"
-            value={formData.body.creditor.ledger_id}
-            onChange={handleSelectChange}
-          >
-            {ledgerItems.map((item) => (
-              <MenuItem key={item.id} value={item.id}>
-                {item.namede}
-              </MenuItem>
-            ))}
-          </Select>
-          {validationErrors['creditor.ledger_id'] && (
-            <Typography color="error">{validationErrors['creditor.ledger_id']}</Typography>
-          )}
-        </FormControl>
-        <TextField
-          label="Amount"
-          name="creditor.amount"
-          type="number"
-          value={formData.body.creditor.amount}
-          onChange={handleChange}
-          fullWidth
-          required
-          error={!!validationErrors['creditor.amount']}
-          helperText={validationErrors['creditor.amount']}
-        />
-        <TextField
-          label="Accounting Year"
-          name="creditor.accounting_year"
-          type="number"
-          value={formData.body.creditor.accounting_year}
-          onChange={handleChange}
-          fullWidth
-          required
-          error={!!validationErrors['creditor.accounting_year']}
-          helperText={validationErrors['creditor.accounting_year']}
-        />
-        <TextField
-          label="Currency"
-          name="creditor.currency"
-          value={formData.body.creditor.currency}
-          onChange={handleChange}
-          fullWidth
-          required
-          error={!!validationErrors['creditor.currency']}
-          helperText={validationErrors['creditor.currency']}
-        />
-        <TextField
-          label="Comment"
-          name="creditor.comment"
-          value={formData.body.creditor.comment}
-          onChange={handleChange}
-          fullWidth
-          error={!!validationErrors['creditor.comment']}
-          helperText={validationErrors['creditor.comment']}
-        />
-        <TextField
-          label="QComment"
-          name="creditor.qcomment"
-          value={formData.body.creditor.qcomment}
-          onChange={handleChange}
-          fullWidth
-          error={!!validationErrors['creditor.qcomment']}
-          helperText={validationErrors['creditor.qcomment']}
-        />
-        <TextField
-          label="Recipt"
-          name="recipt"
-          value={formData.body.recipt}
-          onChange={handleChange}
-          fullWidth
-          required
-          error={!!validationErrors['recipt']}
-          helperText={validationErrors['recipt']}
-        />
-        <TextField
-          label="Creator"
-          name="creator"
-          value={formData.body.creator}
-          onChange={handleChange}
-          fullWidth
-          required
-          error={!!validationErrors['creator']}
-          helperText={validationErrors['creator']}
-        />
-        <TextField
-          label="Recipient"
-          name="recipient"
-          value={formData.body.recipient}
-          onChange={handleChange}
-          fullWidth
-          required
-          error={!!validationErrors['recipient']}
-          helperText={validationErrors['recipient']}
-        />
-        <Button onClick={handleSubmit} variant="contained" color="primary">
-          Create Reimbursement
-        </Button>
-      </Stack>
+      <FormControl fullWidth>
+        <InputLabel id="form-type-label">Form Type</InputLabel>
+        <Select
+          labelId="form-type-label"
+          value={selectedType}
+          onChange={handleTypeChange}
+        >
+          <MenuItem value="beleg">Beleg</MenuItem>
+          <MenuItem value="bill">Bill</MenuItem>
+          <MenuItem value="creditPayment">Credit Payment</MenuItem>
+        </Select>
+      </FormControl>
+      {renderForm()}
     </Container>
   );
 };
 
-export default Belegformular;
\ No newline at end of file
+export default MainForm;
diff --git a/src/pages/Bills.tsx b/src/pages/Bills.tsx
new file mode 100644
index 0000000..481133b
--- /dev/null
+++ b/src/pages/Bills.tsx
@@ -0,0 +1,411 @@
+import React, { useState, useEffect } from 'react';
+import { Container, CircularProgress, Typography, Select, MenuItem, FormControl, InputLabel, Stack, Button, TextField, Alert } from '@mui/material';
+import { kstsReadKsts, billsCreateBill, ledgersReadLedgers } from '../client/services.gen'; // Adjust the import path as needed
+import { KstsPublic, KstPublic, BillsCreateBillData, LedgersPublic, LedgerPublic } from '../client/types.gen';
+
+import { SelectChangeEvent } from '@mui/material/Select';
+
+import { client } from '../client/services.gen';
+
+// Configure the client
+client.setConfig({
+  baseUrl: import.meta.env.VITE_API_BASE_URL,
+  headers: {
+    Origin: `localhost`,
+  },
+});
+
+
+
+
+const CreateBillForm: React.FC = () => {
+
+    const [kstItems, setKstItems] = useState<KstPublic[]>([]);
+    const [ledgerItems, setLedgerItems] = useState<LedgerPublic[]>([]);
+    const [loadingKst, setLoadingKst] = useState(true);
+    const [loadingLedger, setLoadingLedger] = useState(true);
+    const [errorKst, setErrorKst] = useState<string | null>(null);
+    const [errorLedger, setErrorLedger] = useState<string | null>(null);
+  
+
+  const [formData, setFormData] = useState<BillsCreateBillData>({
+    body:{
+        creditor: {
+        kst_id: '',
+        ledger_id: '',
+        amount: 0,
+        accounting_year: 2024,
+        currency: 'CHF', // Default value, adjust as needed
+        comment: '',
+        qcomment: '',
+        },
+        address: {
+        name: '',
+        address1: '',
+        address2: '',
+        address3: '',
+        plz: 0,
+        city: '',
+        country: '',
+        },
+        reference: 0,
+        iban: '',
+        recipt: '',
+        comment: '',
+    }
+  });
+
+  const [error, setError] = useState<string | null>(null);
+  const [success, setSuccess] = useState<string | null>(null);
+  const [validationErrors, setValidationErrors] = useState<Record<string, string>>({});
+
+
+  const fetchKsts = async () => {
+    setErrorKst(null);
+    setLoadingKst(true);
+
+    try {
+      const responseKst = await kstsReadKsts();
+
+      // Check if response is HTML, indicating a possible error
+      if (typeof responseKst.data !== 'object' || !('items' in responseKst.data)) {
+        console.error('Unexpected response format:', responseKst.data);
+        setErrorKst('Received unexpected response format from the server.');
+        return;
+      }
+
+      const KstList = responseKst.data as KstsPublic;
+      if (!KstList.items) {
+        setErrorKst('No KSTs found');
+        return;
+      }
+      setKstItems(KstList.items);
+    } catch (err) {
+      setErrorKst('Failed to load KSTs');
+      console.error('Error fetching KSTs:', err);
+    } finally {
+      setLoadingKst(false);
+    }
+  };
+
+  const fetchLedgers = async () => {
+    setErrorLedger(null);
+    setLoadingLedger(true);
+
+    try {
+      const responseLedger = await ledgersReadLedgers();
+
+      // Check if response is HTML, indicating a possible error
+      if (typeof responseLedger.data !== 'object' || !('items' in responseLedger.data)) {
+        console.error('Unexpected response format:', responseLedger.data);
+        setErrorLedger('Received unexpected response format from the server.');
+        return;
+      }
+
+      const LedgerList = responseLedger.data as LedgersPublic;
+      if (!LedgerList.items) {
+        setErrorLedger('No Ledgers found');
+        return;
+      }
+      setLedgerItems(LedgerList.items);
+    } catch (err) {
+      setErrorLedger('Failed to load Ledgers');
+      console.error('Error fetching Ledgers:', err);
+    } finally {
+      setLoadingLedger(false);
+    }
+  };
+
+  useEffect(() => {
+    fetchKsts();
+    fetchLedgers();
+  }, []);
+
+  const handleChange = (e: React.ChangeEvent<{ name?: string; value: unknown }>) => {
+    const { name, value } = e.target as HTMLInputElement;
+
+    const keys = name.split('.'); // Handle nested keys like creditor.kst_id
+    const updatedFormData = { ...formData };
+
+    let current = updatedFormData.body as any; // Use `any` for dynamic nested updates
+    for (let i = 0; i < keys.length - 1; i++) {
+      current = current[keys[i]];
+    }
+    current[keys[keys.length - 1]] = value;
+
+    setFormData(updatedFormData);
+  };
+
+  const handleSelectChange = (event: SelectChangeEvent<string>) => {
+    const { name, value } = event.target;
+    setFormData((prevFormData) => ({
+      ...prevFormData,
+      body: {
+        ...prevFormData.body,
+        creditor: {
+          ...prevFormData.body.creditor,
+          [name]: value,
+        },
+      },
+    }));
+  };
+
+  const validateForm = (): boolean => {
+    let isValid = true;
+    const errors: Record<string, string> = {};
+
+    if (!formData.body.creditor.kst_id.trim()) {
+      errors['creditor.kst_id'] = 'KST-ID is required';
+      isValid = false;
+    }
+    if (!formData.body.creditor.ledger_id.trim()) {
+      errors['creditor.ledger_id'] = 'Ledger-ID is required';
+      isValid = false;
+    }
+    if (!formData.body.creditor.amount || formData.body.creditor.amount <= 0) {
+      errors['creditor.amount'] = 'Amount must be greater than zero';
+    }
+
+    // Set validation errors if any
+    setValidationErrors(errors);
+    return isValid;
+  };
+
+  const handleSubmit = async () => {
+    setError(null);
+    setSuccess(null);
+    if (!validateForm()) {
+      return;
+    }
+    try {
+      await billsCreateBill(formData);
+      setSuccess('Reimbursement created successfully!');
+      setFormData({
+        body:{
+            creditor: {
+                kst_id: '',
+                ledger_id: '',
+                amount: 0,
+                accounting_year: 2024,
+                currency: 'CHF', // Default value, adjust as needed
+                comment: '',
+                qcomment: '',
+            },
+            address: {
+                name: '',
+                address1: '',
+                address2: '',
+                address3: '',
+                plz: 0,
+                city: '',
+                country: '',
+            },
+            reference: 0,
+            iban: '',
+            recipt: '',
+            comment: '',
+        }
+      });
+    } catch (err) {
+      setError('Failed to create bill.');
+      console.error('Error creating bill:', err);
+    }
+  };
+
+  return (
+    <Container>
+      <Typography variant="h4" component="h2" gutterBottom>
+        Create Bill
+      </Typography>
+      {success && <Alert severity="success">{success}</Alert>}
+      {error && <Alert severity="error">{error}</Alert>}
+
+      <Stack spacing={2} sx={{ mt: 2 }}>
+        <FormControl fullWidth required error={!!validationErrors['creditor.kst_id']}>
+          <InputLabel id="kst-id-label">KST ID</InputLabel>
+          <Select
+            labelId="kst-id-label"
+            name="kst_id"
+            value={formData.body.creditor.kst_id}
+            onChange={handleSelectChange}
+          >
+            {kstItems.map((item) => (
+              <MenuItem key={item.id} value={item.id}>
+                {item.name_de}
+              </MenuItem>
+            ))}
+          </Select>
+          {validationErrors['creditor.kst_id'] && (
+            <Typography color="error">{validationErrors['creditor.kst_id']}</Typography>
+          )}
+        </FormControl>
+        <FormControl fullWidth required error={!!validationErrors['creditor.ledger_id']}>
+          <InputLabel id="ledger-id-label">Ledger ID</InputLabel>
+          <Select
+            labelId="ledger-id-label"
+            name="ledger_id"
+            value={formData.body.creditor.ledger_id}
+            onChange={handleSelectChange}
+          >
+            {ledgerItems.map((item) => (
+              <MenuItem key={item.id} value={item.id}>
+                {item.namede}
+              </MenuItem>
+            ))}
+          </Select>
+          {validationErrors['creditor.ledger_id'] && (
+            <Typography color="error">{validationErrors['creditor.ledger_id']}</Typography>
+          )}
+        </FormControl>
+        <TextField
+          label="Amount"
+          name="creditor.amount"
+          type="number"
+          value={formData.body.creditor.amount}
+          onChange={handleChange}
+          fullWidth
+          required
+          error={!!validationErrors['creditor.amount']}
+          helperText={validationErrors['creditor.amount']}
+        />
+        <TextField
+          label="Accounting Year"
+          name="creditor.accounting_year"
+          type="number"
+          value={formData.body.creditor.accounting_year}
+          onChange={handleChange}
+          fullWidth
+          required
+          error={!!validationErrors['creditor.accounting_year']}
+          helperText={validationErrors['creditor.accounting_year']}
+        />
+        <TextField
+          label="Currency"
+          name="creditor.currency"
+          value={formData.body.creditor.currency}
+          onChange={handleChange}
+          fullWidth
+          required
+          error={!!validationErrors['creditor.currency']}
+          helperText={validationErrors['creditor.currency']}
+        />
+        <TextField
+          label="Comment"
+          name="creditor.comment"
+          value={formData.body.creditor.comment}
+          onChange={handleChange}
+          fullWidth
+          error={!!validationErrors['creditor.comment']}
+          helperText={validationErrors['creditor.comment']}
+        />
+        <TextField
+          label="QComment"
+          name="creditor.qcomment"
+          value={formData.body.creditor.qcomment}
+          onChange={handleChange}
+          fullWidth
+          margin="normal"
+        />
+        <TextField
+          label="Address Name"
+          name="address.name"
+          value={formData.body.address.name}
+          onChange={handleChange}
+          fullWidth
+          margin="normal"
+        />
+        <TextField
+          label="Address Line 1"
+          name="address.address1"
+          value={formData.body.address.address1}
+          onChange={handleChange}
+          fullWidth
+          margin="normal"
+        />
+        <TextField
+          label="Address Line 2"
+          name="address.address2"
+          value={formData.body.address.address2}
+          onChange={handleChange}
+          fullWidth
+          margin="normal"
+        />
+        <TextField
+          label="Address Line 3"
+          name="address.address3"
+          value={formData.body.address.address3}
+          onChange={handleChange}
+          fullWidth
+          margin="normal"
+        />
+        <TextField
+          label="Postal Code"
+          name="address.plz"
+          type="number"
+          value={formData.body.address.plz}
+          onChange={handleChange}
+          fullWidth
+          margin="normal"
+        />
+        <TextField
+          label="City"
+          name="address.city"
+          value={formData.body.address.city}
+          onChange={handleChange}
+          fullWidth
+          margin="normal"
+        />
+        <TextField
+          label="Country"
+          name="address.country"
+          value={formData.body.address.country}
+          onChange={handleChange}
+          fullWidth
+          margin="normal"
+        />
+        <TextField
+          label="Reference"
+          name="reference"
+          type="number"
+          value={formData.body.reference}
+          onChange={handleChange}
+          fullWidth
+          margin="normal"
+        />
+        <TextField
+          label="IBAN"
+          name="iban"
+          value={formData.body.iban}
+          onChange={handleChange}
+          fullWidth
+          margin="normal"
+        />
+        <TextField
+          label="Recipt"
+          name="recipt"
+          value={formData.body.recipt}
+          onChange={handleChange}
+          fullWidth
+          required
+          error={!!validationErrors['recipt']}
+          helperText={validationErrors['recipt']}
+        />
+        <TextField
+          label="Comment"
+          name="comment"
+          value={formData.body.comment}
+          onChange={handleChange}
+          fullWidth
+          required
+          error={!!validationErrors['recipient']}
+          helperText={validationErrors['recipient']}
+        />
+        <Button onClick={handleSubmit} variant="contained" color="primary">
+          Create Bill
+        </Button>
+      </Stack>
+    </Container>
+  );
+};
+
+export default CreateBillForm;
\ No newline at end of file
diff --git a/src/pages/CreditPayment.tsx b/src/pages/CreditPayment.tsx
new file mode 100644
index 0000000..a4862f2
--- /dev/null
+++ b/src/pages/CreditPayment.tsx
@@ -0,0 +1,322 @@
+import React, { useState, useEffect } from 'react';
+import { Container, CircularProgress, Typography, Select, MenuItem, FormControl, InputLabel, Stack, Button, TextField, Alert } from '@mui/material';
+import { kstsReadKsts, creditPaymentsCreateCreditPayment, ledgersReadLedgers } from '../client/services.gen';
+import { KstsPublic, KstPublic, CreditPaymentsCreateCreditPaymentData, LedgersPublic, LedgerPublic } from '../client/types.gen';
+import { SelectChangeEvent } from '@mui/material/Select';
+
+import { client } from '../client/services.gen';
+
+// Configure the client
+client.setConfig({
+  baseUrl: import.meta.env.VITE_API_BASE_URL,
+  headers: {
+    Origin: `localhost`,
+  },
+});
+
+const CreditPayment: React.FC = () => {
+  const [kstItems, setKstItems] = useState<KstPublic[]>([]);
+  const [ledgerItems, setLedgerItems] = useState<LedgerPublic[]>([]);
+  const [loadingKst, setLoadingKst] = useState(true);
+  const [loadingLedger, setLoadingLedger] = useState(true);
+  const [errorKst, setErrorKst] = useState<string | null>(null);
+  const [errorLedger, setErrorLedger] = useState<string | null>(null);
+
+  const [formData, setFormData] = useState<CreditPaymentsCreateCreditPaymentData>({
+    body: {
+      creditor: {
+        kst_id: '',
+        ledger_id: '',
+        amount: 0,
+        accounting_year: 2024,
+        currency: 'CHF',
+        comment: '',
+        qcomment: '',
+      },
+      recipt: '',
+      card: 'President',
+      creator: '',
+    },
+  });
+
+  const [error, setError] = useState<string | null>(null);
+  const [success, setSuccess] = useState<string | null>(null);
+  const [validationErrors, setValidationErrors] = useState<Record<string, string>>({});
+
+  const fetchKsts = async () => {
+    setErrorKst(null);
+    setLoadingKst(true);
+
+    try {
+      const responseKst = await kstsReadKsts();
+
+      // Check if response is HTML, indicating a possible error
+      if (typeof responseKst.data !== 'object' || !('items' in responseKst.data)) {
+        console.error('Unexpected response format:', responseKst.data);
+        setErrorKst('Received unexpected response format from the server.');
+        return;
+      }
+
+      const KstList = responseKst.data as KstsPublic;
+      if (!KstList.items) {
+        setErrorKst('No KSTs found');
+        return;
+      }
+      setKstItems(KstList.items);
+    } catch (err) {
+      setErrorKst('Failed to load KSTs');
+      console.error('Error fetching KSTs:', err);
+    } finally {
+      setLoadingKst(false);
+    }
+  };
+
+  const fetchLedgers = async () => {
+    setErrorLedger(null);
+    setLoadingLedger(true);
+
+    try {
+      const responseLedger = await ledgersReadLedgers();
+
+      // Check if response is HTML, indicating a possible error
+      if (typeof responseLedger.data !== 'object' || !('items' in responseLedger.data)) {
+        console.error('Unexpected response format:', responseLedger.data);
+        setErrorLedger('Received unexpected response format from the server.');
+        return;
+      }
+
+      const LedgerList = responseLedger.data as LedgersPublic;
+      if (!LedgerList.items) {
+        setErrorLedger('No Ledgers found');
+        return;
+      }
+      setLedgerItems(LedgerList.items);
+    } catch (err) {
+      setErrorLedger('Failed to load Ledgers');
+      console.error('Error fetching Ledgers:', err);
+    } finally {
+      setLoadingLedger(false);
+    }
+  };
+
+  useEffect(() => {
+    fetchKsts();
+    fetchLedgers();
+  }, []);
+
+  const handleChange = (e: React.ChangeEvent<{ name?: string; value: unknown }>) => {
+    const { name, value } = e.target as HTMLInputElement;
+
+    const keys = name.split('.'); // Handle nested keys like creditor.kst_id
+    const updatedFormData = { ...formData };
+
+    let current = updatedFormData.body as any; // Use `any` for dynamic nested updates
+    for (let i = 0; i < keys.length - 1; i++) {
+      current = current[keys[i]];
+    }
+    current[keys[keys.length - 1]] = value;
+
+    setFormData(updatedFormData);
+  };
+
+  const handleSelectChange = (event: SelectChangeEvent<string>) => {
+    const { name, value } = event.target;
+    setFormData((prevFormData) => ({
+      ...prevFormData,
+      body: {
+        ...prevFormData.body,
+        creditor: {
+          ...prevFormData.body.creditor,
+          [name]: value,
+        },
+      },
+    }));
+  };
+
+  const validateForm = (): boolean => {
+    let isValid = true;
+    const errors: Record<string, string> = {};
+
+    if (!formData.body.creditor.kst_id.trim()) {
+      errors['creditor.kst_id'] = 'KST-ID is required';
+      isValid = false;
+    }
+    if (!formData.body.creditor.ledger_id.trim()) {
+      errors['creditor.ledger_id'] = 'Ledger-ID is required';
+      isValid = false;
+    }
+    if (!formData.body.creditor.amount || formData.body.creditor.amount <= 0) {
+      errors['creditor.amount'] = 'Amount must be greater than zero';
+    }
+
+    // Set validation errors if any
+    setValidationErrors(errors);
+    return isValid;
+  };
+
+  const handleSubmit = async () => {
+    setError(null);
+    setSuccess(null);
+    if (!validateForm()) {
+      return;
+    }
+    try {
+      await creditPaymentsCreateCreditPayment(formData);
+      setSuccess('CreditPayment created successfully!');
+      setFormData({
+        body: {
+          creditor: {
+            kst_id: '',
+            ledger_id: '',
+            amount: 0,
+            accounting_year: 2024,
+            currency: 'CHF',
+            comment: '',
+            qcomment: '',
+          },
+          recipt: '',
+          card: 'President',
+          creator: '',
+        },
+      });
+    } catch (err) {
+      setError('Failed to create reimbursement.');
+      console.error('Error creating reimbursement:', err);
+    }
+  };
+
+  return (
+    <Container>
+      <Typography variant="h4" component="h2" gutterBottom>
+        Create New CreditPayment
+      </Typography>
+
+      {success && <Alert severity="success">{success}</Alert>}
+      {error && <Alert severity="error">{error}</Alert>}
+
+      <Stack spacing={2} sx={{ mt: 2 }}>
+        <FormControl fullWidth required error={!!validationErrors['creditor.kst_id']}>
+          <InputLabel id="kst-id-label">KST ID</InputLabel>
+          <Select
+            labelId="kst-id-label"
+            name="kst_id"
+            value={formData.body.creditor.kst_id}
+            onChange={handleSelectChange}
+          >
+            {kstItems.map((item) => (
+              <MenuItem key={item.id} value={item.id}>
+                {item.name_de}
+              </MenuItem>
+            ))}
+          </Select>
+          {validationErrors['creditor.kst_id'] && (
+            <Typography color="error">{validationErrors['creditor.kst_id']}</Typography>
+          )}
+        </FormControl>
+        <FormControl fullWidth required error={!!validationErrors['creditor.ledger_id']}>
+          <InputLabel id="ledger-id-label">Ledger ID</InputLabel>
+          <Select
+            labelId="ledger-id-label"
+            name="ledger_id"
+            value={formData.body.creditor.ledger_id}
+            onChange={handleSelectChange}
+          >
+            {ledgerItems.map((item) => (
+              <MenuItem key={item.id} value={item.id}>
+                {item.namede}
+              </MenuItem>
+            ))}
+          </Select>
+          {validationErrors['creditor.ledger_id'] && (
+            <Typography color="error">{validationErrors['creditor.ledger_id']}</Typography>
+          )}
+        </FormControl>
+        <TextField
+          label="Amount"
+          name="creditor.amount"
+          type="number"
+          value={formData.body.creditor.amount}
+          onChange={handleChange}
+          fullWidth
+          required
+          error={!!validationErrors['creditor.amount']}
+          helperText={validationErrors['creditor.amount']}
+        />
+        <TextField
+          label="Accounting Year"
+          name="creditor.accounting_year"
+          type="number"
+          value={formData.body.creditor.accounting_year}
+          onChange={handleChange}
+          fullWidth
+          required
+          error={!!validationErrors['creditor.accounting_year']}
+          helperText={validationErrors['creditor.accounting_year']}
+        />
+        <TextField
+          label="Currency"
+          name="creditor.currency"
+          value={formData.body.creditor.currency}
+          onChange={handleChange}
+          fullWidth
+          required
+          error={!!validationErrors['creditor.currency']}
+          helperText={validationErrors['creditor.currency']}
+        />
+        <TextField
+          label="Comment"
+          name="creditor.comment"
+          value={formData.body.creditor.comment}
+          onChange={handleChange}
+          fullWidth
+          error={!!validationErrors['creditor.comment']}
+          helperText={validationErrors['creditor.comment']}
+        />
+        <TextField
+          label="QComment"
+          name="creditor.qcomment"
+          value={formData.body.creditor.qcomment}
+          onChange={handleChange}
+          fullWidth
+          error={!!validationErrors['creditor.qcomment']}
+          helperText={validationErrors['creditor.qcomment']}
+        />
+        <TextField
+          label="Recipt"
+          name="recipt"
+          value={formData.body.recipt}
+          onChange={handleChange}
+          fullWidth
+          required
+          error={!!validationErrors['recipt']}
+          helperText={validationErrors['recipt']}
+        />
+        <TextField
+          label="Creator"
+          name="creator"
+          value={formData.body.creator}
+          onChange={handleChange}
+          fullWidth
+          required
+          error={!!validationErrors['creator']}
+          helperText={validationErrors['creator']}
+        />
+        <TextField
+          label="Recipient"
+          name="recipient"
+          value={formData.body.card}
+          onChange={handleChange}
+          fullWidth
+          required
+          error={!!validationErrors['recipient']}
+          helperText={validationErrors['recipient']}
+        />
+        <Button onClick={handleSubmit} variant="contained" color="primary">
+          Create CreditPayment
+        </Button>
+      </Stack>
+    </Container>
+  );
+};
+
+export default CreditPayment;
\ No newline at end of file
diff --git a/src/pages/Reimbursement.tsx b/src/pages/Reimbursement.tsx
new file mode 100644
index 0000000..c75ee7b
--- /dev/null
+++ b/src/pages/Reimbursement.tsx
@@ -0,0 +1,322 @@
+import React, { useState, useEffect } from 'react';
+import { Container, CircularProgress, Typography, Select, MenuItem, FormControl, InputLabel, Stack, Button, TextField, Alert } from '@mui/material';
+import { kstsReadKsts, reimbursementsCreateReimbursement, ledgersReadLedgers } from '../client/services.gen';
+import { KstsPublic, KstPublic, ReimbursementsCreateReimbursementData, LedgersPublic, LedgerPublic } from '../client/types.gen';
+import { SelectChangeEvent } from '@mui/material/Select';
+
+import { client } from '../client/services.gen';
+
+// Configure the client
+client.setConfig({
+  baseUrl: import.meta.env.VITE_API_BASE_URL,
+  headers: {
+    Origin: `localhost`,
+  },
+});
+
+const Reimbursement: React.FC = () => {
+  const [kstItems, setKstItems] = useState<KstPublic[]>([]);
+  const [ledgerItems, setLedgerItems] = useState<LedgerPublic[]>([]);
+  const [loadingKst, setLoadingKst] = useState(true);
+  const [loadingLedger, setLoadingLedger] = useState(true);
+  const [errorKst, setErrorKst] = useState<string | null>(null);
+  const [errorLedger, setErrorLedger] = useState<string | null>(null);
+
+  const [formData, setFormData] = useState<ReimbursementsCreateReimbursementData>({
+    body: {
+      creditor: {
+        kst_id: '',
+        ledger_id: '',
+        amount: 0,
+        accounting_year: 2024,
+        currency: 'CHF',
+        comment: '',
+        qcomment: '',
+      },
+      recipt: '',
+      creator: '',
+      recipient: '',
+    },
+  });
+
+  const [error, setError] = useState<string | null>(null);
+  const [success, setSuccess] = useState<string | null>(null);
+  const [validationErrors, setValidationErrors] = useState<Record<string, string>>({});
+
+  const fetchKsts = async () => {
+    setErrorKst(null);
+    setLoadingKst(true);
+
+    try {
+      const responseKst = await kstsReadKsts();
+
+      // Check if response is HTML, indicating a possible error
+      if (typeof responseKst.data !== 'object' || !('items' in responseKst.data)) {
+        console.error('Unexpected response format:', responseKst.data);
+        setErrorKst('Received unexpected response format from the server.');
+        return;
+      }
+
+      const KstList = responseKst.data as KstsPublic;
+      if (!KstList.items) {
+        setErrorKst('No KSTs found');
+        return;
+      }
+      setKstItems(KstList.items);
+    } catch (err) {
+      setErrorKst('Failed to load KSTs');
+      console.error('Error fetching KSTs:', err);
+    } finally {
+      setLoadingKst(false);
+    }
+  };
+
+  const fetchLedgers = async () => {
+    setErrorLedger(null);
+    setLoadingLedger(true);
+
+    try {
+      const responseLedger = await ledgersReadLedgers();
+
+      // Check if response is HTML, indicating a possible error
+      if (typeof responseLedger.data !== 'object' || !('items' in responseLedger.data)) {
+        console.error('Unexpected response format:', responseLedger.data);
+        setErrorLedger('Received unexpected response format from the server.');
+        return;
+      }
+
+      const LedgerList = responseLedger.data as LedgersPublic;
+      if (!LedgerList.items) {
+        setErrorLedger('No Ledgers found');
+        return;
+      }
+      setLedgerItems(LedgerList.items);
+    } catch (err) {
+      setErrorLedger('Failed to load Ledgers');
+      console.error('Error fetching Ledgers:', err);
+    } finally {
+      setLoadingLedger(false);
+    }
+  };
+
+  useEffect(() => {
+    fetchKsts();
+    fetchLedgers();
+  }, []);
+
+  const handleChange = (e: React.ChangeEvent<{ name?: string; value: unknown }>) => {
+    const { name, value } = e.target as HTMLInputElement;
+
+    const keys = name.split('.'); // Handle nested keys like creditor.kst_id
+    const updatedFormData = { ...formData };
+
+    let current = updatedFormData.body as any; // Use `any` for dynamic nested updates
+    for (let i = 0; i < keys.length - 1; i++) {
+      current = current[keys[i]];
+    }
+    current[keys[keys.length - 1]] = value;
+
+    setFormData(updatedFormData);
+  };
+
+  const handleSelectChange = (event: SelectChangeEvent<string>) => {
+    const { name, value } = event.target;
+    setFormData((prevFormData) => ({
+      ...prevFormData,
+      body: {
+        ...prevFormData.body,
+        creditor: {
+          ...prevFormData.body.creditor,
+          [name]: value,
+        },
+      },
+    }));
+  };
+
+  const validateForm = (): boolean => {
+    let isValid = true;
+    const errors: Record<string, string> = {};
+
+    if (!formData.body.creditor.kst_id.trim()) {
+      errors['creditor.kst_id'] = 'KST-ID is required';
+      isValid = false;
+    }
+    if (!formData.body.creditor.ledger_id.trim()) {
+      errors['creditor.ledger_id'] = 'Ledger-ID is required';
+      isValid = false;
+    }
+    if (!formData.body.creditor.amount || formData.body.creditor.amount <= 0) {
+      errors['creditor.amount'] = 'Amount must be greater than zero';
+    }
+
+    // Set validation errors if any
+    setValidationErrors(errors);
+    return isValid;
+  };
+
+  const handleSubmit = async () => {
+    setError(null);
+    setSuccess(null);
+    if (!validateForm()) {
+      return;
+    }
+    try {
+      await reimbursementsCreateReimbursement(formData);
+      setSuccess('Reimbursement created successfully!');
+      setFormData({
+        body: {
+          creditor: {
+            kst_id: '',
+            ledger_id: '',
+            amount: 0,
+            accounting_year: 2024,
+            currency: 'CHF',
+            comment: '',
+            qcomment: '',
+          },
+          recipt: '',
+          creator: '',
+          recipient: '',
+        },
+      });
+    } catch (err) {
+      setError('Failed to create reimbursement.');
+      console.error('Error creating reimbursement:', err);
+    }
+  };
+
+  return (
+    <Container>
+      <Typography variant="h4" component="h2" gutterBottom>
+        Create New Reimbursement
+      </Typography>
+
+      {success && <Alert severity="success">{success}</Alert>}
+      {error && <Alert severity="error">{error}</Alert>}
+
+      <Stack spacing={2} sx={{ mt: 2 }}>
+        <FormControl fullWidth required error={!!validationErrors['creditor.kst_id']}>
+          <InputLabel id="kst-id-label">KST ID</InputLabel>
+          <Select
+            labelId="kst-id-label"
+            name="kst_id"
+            value={formData.body.creditor.kst_id}
+            onChange={handleSelectChange}
+          >
+            {kstItems.map((item) => (
+              <MenuItem key={item.id} value={item.id}>
+                {item.name_de}
+              </MenuItem>
+            ))}
+          </Select>
+          {validationErrors['creditor.kst_id'] && (
+            <Typography color="error">{validationErrors['creditor.kst_id']}</Typography>
+          )}
+        </FormControl>
+        <FormControl fullWidth required error={!!validationErrors['creditor.ledger_id']}>
+          <InputLabel id="ledger-id-label">Ledger ID</InputLabel>
+          <Select
+            labelId="ledger-id-label"
+            name="ledger_id"
+            value={formData.body.creditor.ledger_id}
+            onChange={handleSelectChange}
+          >
+            {ledgerItems.map((item) => (
+              <MenuItem key={item.id} value={item.id}>
+                {item.namede}
+              </MenuItem>
+            ))}
+          </Select>
+          {validationErrors['creditor.ledger_id'] && (
+            <Typography color="error">{validationErrors['creditor.ledger_id']}</Typography>
+          )}
+        </FormControl>
+        <TextField
+          label="Amount"
+          name="creditor.amount"
+          type="number"
+          value={formData.body.creditor.amount}
+          onChange={handleChange}
+          fullWidth
+          required
+          error={!!validationErrors['creditor.amount']}
+          helperText={validationErrors['creditor.amount']}
+        />
+        <TextField
+          label="Accounting Year"
+          name="creditor.accounting_year"
+          type="number"
+          value={formData.body.creditor.accounting_year}
+          onChange={handleChange}
+          fullWidth
+          required
+          error={!!validationErrors['creditor.accounting_year']}
+          helperText={validationErrors['creditor.accounting_year']}
+        />
+        <TextField
+          label="Currency"
+          name="creditor.currency"
+          value={formData.body.creditor.currency}
+          onChange={handleChange}
+          fullWidth
+          required
+          error={!!validationErrors['creditor.currency']}
+          helperText={validationErrors['creditor.currency']}
+        />
+        <TextField
+          label="Comment"
+          name="creditor.comment"
+          value={formData.body.creditor.comment}
+          onChange={handleChange}
+          fullWidth
+          error={!!validationErrors['creditor.comment']}
+          helperText={validationErrors['creditor.comment']}
+        />
+        <TextField
+          label="QComment"
+          name="creditor.qcomment"
+          value={formData.body.creditor.qcomment}
+          onChange={handleChange}
+          fullWidth
+          error={!!validationErrors['creditor.qcomment']}
+          helperText={validationErrors['creditor.qcomment']}
+        />
+        <TextField
+          label="Recipt"
+          name="recipt"
+          value={formData.body.recipt}
+          onChange={handleChange}
+          fullWidth
+          required
+          error={!!validationErrors['recipt']}
+          helperText={validationErrors['recipt']}
+        />
+        <TextField
+          label="Creator"
+          name="creator"
+          value={formData.body.creator}
+          onChange={handleChange}
+          fullWidth
+          required
+          error={!!validationErrors['creator']}
+          helperText={validationErrors['creator']}
+        />
+        <TextField
+          label="Recipient"
+          name="recipient"
+          value={formData.body.recipient}
+          onChange={handleChange}
+          fullWidth
+          required
+          error={!!validationErrors['recipient']}
+          helperText={validationErrors['recipient']}
+        />
+        <Button onClick={handleSubmit} variant="contained" color="primary">
+          Create Reimbursement
+        </Button>
+      </Stack>
+    </Container>
+  );
+};
+
+export default Reimbursement;
\ No newline at end of file
-- 
GitLab