diff --git a/Mock/Frames.pdf b/Mock/Frames.pdf deleted file mode 100644 index 2aed09a..0000000 Binary files a/Mock/Frames.pdf and /dev/null differ diff --git a/frontend/index.html b/frontend/index.html index e4b78ea..e4d2f69 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -1,10 +1,10 @@ - + - + - Vite + React + TS + Ausleihsystem
diff --git a/frontend/public/shapes.svg b/frontend/public/shapes.svg new file mode 100644 index 0000000..a3b6099 --- /dev/null +++ b/frontend/public/shapes.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/public/vite.svg b/frontend/public/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/frontend/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 02ef27f..ae29d81 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -22,14 +22,12 @@ function App() { localStorage.setItem("borrowableItems", JSON.stringify([])); }, []); - // Mock flow without real logic: show the three sections stacked for design preview const handleLogout = () => { Cookies.remove("token"); localStorage.removeItem("allItems"); localStorage.removeItem("allLoans"); localStorage.removeItem("userLoans"); localStorage.removeItem("borrowableItems"); - // Let listeners refresh from empty state window.dispatchEvent(new Event(ALL_ITEMS_UPDATED_EVENT)); myToast("Logged out successfully!", "success"); setIsLoggedIn(false); @@ -37,11 +35,11 @@ function App() { return isLoggedIn ? ( -
+
-
+
-
+
diff --git a/frontend/src/components/Form1.tsx b/frontend/src/components/Form1.tsx index 0c6cf47..b225477 100644 --- a/frontend/src/components/Form1.tsx +++ b/frontend/src/components/Form1.tsx @@ -4,10 +4,12 @@ import { getBorrowableItems } from "../utils/fetchData"; const Form1: React.FC = () => { return ( -
-

1. Zeitraum wählen

+
+

+ 1. Zeitraum wählen +

{ e.preventDefault(); const form = e.currentTarget as HTMLFormElement; @@ -17,40 +19,41 @@ const Form1: React.FC = () => { Cookies.set("startDate", start); Cookies.set("endDate", end); getBorrowableItems(); - console.log("Zeitraum erfolgreich gesetzt!"); }} > -
- - -
-
- - +
+
+ + +
+
+ + +
diff --git a/frontend/src/components/Form2.tsx b/frontend/src/components/Form2.tsx index 5583006..29a95bf 100644 --- a/frontend/src/components/Form2.tsx +++ b/frontend/src/components/Form2.tsx @@ -1,7 +1,6 @@ import React from "react"; import Cookies from "js-cookie"; -import { createLoan } from "../utils/userHandler"; -import { addToRemove, rmFromRemove } from "../utils/userHandler"; +import { createLoan, addToRemove, rmFromRemove } from "../utils/userHandler"; import { BORROWABLE_ITEMS_UPDATED_EVENT } from "../utils/fetchData"; interface BorrowItem { @@ -59,16 +58,13 @@ function useBorrowableItems() { }, []); React.useEffect(() => { - // Initial read readFromStorage(); - // Cross-tab updates const onStorage = (e: StorageEvent) => { if (e.key === LOCAL_STORAGE_KEY) readFromStorage(); }; window.addEventListener("storage", onStorage); - // Same-tab updates via Custom Event const onBorrowableUpdated = () => readFromStorage(); window.addEventListener( BORROWABLE_ITEMS_UPDATED_EVENT, @@ -91,58 +87,85 @@ const Form2: React.FC = () => { const items = useBorrowableItems(); return ( -
-

+
+

2. Gegenstand auswählen

{items.length === 0 ? ( -
+
Keine Gegenstände verfügbar für diesen Zeitraum.
) : ( -
- - - - - - - - - {items.map((item) => ( - - - + +
+ {item.inSafe ? "Verfügbar" : "Nicht im Schließfach"} +
+ + { + if (e.target.checked) addToRemove(item.id); + else rmFromRemove(item.id); + }} + className="h-5 w-5 accent-indigo-600" + /> + + ))} + + + {/* Desktop: table */} +
+
- Gegenstand - - -
+ <> + {/* Mobile: card list */} +
+ {items.map((item) => ( +
- { - if (e.target.checked) { - addToRemove(item.id); - } else { - rmFromRemove(item.id); - } - }} - id={`item-${item.id}`} - /> -
+ + + + - ))} - -
+ Gegenstand + + +
-
+ + + {items.map((item) => ( + + + {item.item_name} + + + { + if (e.target.checked) addToRemove(item.id); + else rmFromRemove(item.id); + }} + id={`item-${item.id}`} + className="h-4 w-4 accent-indigo-600" + /> + + + ))} + + +
+ )} -
+
diff --git a/frontend/src/components/Form4.tsx b/frontend/src/components/Form4.tsx index 2962d82..2c862c3 100644 --- a/frontend/src/components/Form4.tsx +++ b/frontend/src/components/Form4.tsx @@ -1,5 +1,4 @@ import React, { useEffect, useState } from "react"; -import { Trash, ArrowLeftRight } from "lucide-react"; import { handleDeleteLoan } from "../utils/userHandler"; type Loan = { @@ -33,12 +32,27 @@ const readUserLoansFromStorage = (): Loan[] => { } }; +const TrashIcon = (props: React.SVGProps) => ( + + + +); + const Form4: React.FC = () => { const [userLoans, setUserLoans] = useState(() => readUserLoansFromStorage() ); - // Keep in sync if localStorage changes (e.g., other tabs or parts of the app) useEffect(() => { const onStorage = (e: StorageEvent) => { if (e.key === "userLoans") { @@ -60,7 +74,7 @@ const Form4: React.FC = () => { if (userLoans.length === 0) { return ( -
+

Keine Ausleihen gefunden.

); @@ -68,71 +82,117 @@ const Form4: React.FC = () => { return (
-

+

Meine Ausleihen

-

- Wenn du eine Ausleihe ändern oder löschen möchtest, klicke auf das - Papierkorb-Symbol. +

+ Tippe auf das Papierkorb-Symbol, um eine Ausleihe zu löschen.

-
+ {/* Mobile: cards */} +
+ {userLoans.map((loan) => ( +
+
+
+
+ Leihcode: {loan.loan_code} +
+
+
+ Start:{" "} + {formatDate(loan.start_date)} +
+
+ Ende:{" "} + {formatDate(loan.end_date)} +
+
+ Abgeholt:{" "} + {formatDate(loan.take_date)} +
+
+ Zurück:{" "} + {formatDate(loan.returned_date)} +
+
+
+ Gegenstände:{" "} + {Array.isArray(loan.loaned_items_name) + ? loan.loaned_items_name.join(", ") + : "-"} +
+
+ +
+
+ ))} +
+ + {/* Desktop: table */} +
- - - -
+ + + + - - - - - - - - + {userLoans.map((loan) => ( - - + - - - - - @@ -152,14 +212,6 @@ const Form4: React.FC = () => {
Leihcode + Start + Ende + Abgeholt + Zurückgegeben + Erstellt + Gegenstände + Aktionen
+
{loan.loan_code} + {formatDate(loan.start_date)} + {formatDate(loan.end_date)} + {formatDate(loan.take_date)} + {formatDate(loan.returned_date)} + {formatDate(loan.created_at)} -
+
{Array.isArray(loan.loaned_items_name) ? loan.loaned_items_name.join(", ") : "-"} @@ -142,9 +202,9 @@ const Form4: React.FC = () => {
- - {/* Scroll hint */} -
-
- - Hinweis: Horizontal scrollen, um alle Spalten zu sehen. -
-
); diff --git a/frontend/src/components/Header.tsx b/frontend/src/components/Header.tsx index e891823..a7e8454 100644 --- a/frontend/src/components/Header.tsx +++ b/frontend/src/components/Header.tsx @@ -6,20 +6,24 @@ type HeaderProps = { const Header: React.FC = ({ onLogout }) => { return ( -
-

- Gegenstand ausleihen -

-

- Schnell und unkompliziert Equipment reservieren -

- +
+
+
+

+ Gegenstand ausleihen +

+

+ Schnell und unkompliziert Equipment reservieren +

+
+ +
); }; diff --git a/frontend/src/components/LoginForm.tsx b/frontend/src/components/LoginForm.tsx index 78121c9..ea74839 100644 --- a/frontend/src/components/LoginForm.tsx +++ b/frontend/src/components/LoginForm.tsx @@ -22,16 +22,16 @@ const LoginForm: React.FC = ({ onLogin }) => { }; return ( -
-
-

+
+
+

Login

- +
@@ -39,14 +39,14 @@ const LoginForm: React.FC = ({ onLogin }) => { type="text" onChange={(e) => setUsername(e.target.value)} id="username" - className="mt-1 block w-full border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 px-3 py-2" + className="mt-1 block w-full border border-slate-300 rounded-md shadow-sm focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 px-3 py-2.5 bg-white" required />
@@ -54,13 +54,13 @@ const LoginForm: React.FC = ({ onLogin }) => { onChange={(e) => setPassword(e.target.value)} type="password" id="password" - className="mt-1 block w-full border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 px-3 py-2" + className="mt-1 block w-full border border-slate-300 rounded-md shadow-sm focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 px-3 py-2.5 bg-white" required />
diff --git a/frontend/src/components/Object.tsx b/frontend/src/components/Object.tsx index 0a6cb12..339612f 100644 --- a/frontend/src/components/Object.tsx +++ b/frontend/src/components/Object.tsx @@ -7,9 +7,9 @@ type ObjectProps = { const Object: React.FC = ({ title, description }) => { return ( -
-

{title}

-

{description}

+
+

{title}

+

{description}

); }; diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx index 120a24e..2d0c77b 100644 --- a/frontend/src/components/Sidebar.tsx +++ b/frontend/src/components/Sidebar.tsx @@ -12,25 +12,25 @@ const Sidebar: React.FC = () => { const next = JSON.parse(localStorage.getItem("allItems") || "[]"); setItems(next); }; - // Update immediately in case data changed before this mounted handler(); window.addEventListener(ALL_ITEMS_UPDATED_EVENT, handler); return () => window.removeEventListener(ALL_ITEMS_UPDATED_EVENT, handler); }, []); const outCount = items.reduce((n, it) => n + (it.inSafe ? 0 : 1), 0); - const sorted = [...items].sort((a, b) => Number(a.inSafe) - Number(b.inSafe)); // außerhalb zuerst + const sorted = [...items].sort((a, b) => Number(a.inSafe) - Number(b.inSafe)); return ( -