From 07d194ee6aad26df6dd696e48aad3f10a073b254 Mon Sep 17 00:00:00 2001 From: Theis Gaedigk Date: Sun, 23 Nov 2025 19:58:04 +0100 Subject: [PATCH] Refactor API and frontend components: update item state handling, adjust API key length, and improve table layout for MyLoansPage --- Docs/backend_API_docs/README.md | 29 ++-- FrontendV2/src/pages/MyLoansPage.tsx | 224 ++++++++++++++------------- admin/src/components/AddAPIKey.tsx | 8 +- backend/services/database.js | 2 +- backendV2/routes/api/api.database.js | 8 +- backendV2/routes/api/api.route.js | 25 +-- 6 files changed, 154 insertions(+), 142 deletions(-) diff --git a/Docs/backend_API_docs/README.md b/Docs/backend_API_docs/README.md index 86a175f..eeaa3ed 100644 --- a/Docs/backend_API_docs/README.md +++ b/Docs/backend_API_docs/README.md @@ -20,7 +20,7 @@ All **protected** endpoints require an API key as a path parameter `:key`. Rules for `:key`: -- Exactly 8 characters +- Exactly 8 characters - Digits only (`^[0-9]{8}$`) Example: @@ -49,9 +49,11 @@ Route handlers: ## Endpoints (Overview) 1. **Public** + - `GET /api/all-items` – List all items (no auth; from original docs) 2. **Items (authenticated)** + - `GET /api/items/:key` – List all items - `POST /api/change-state/:key/:itemId/:state` – Toggle item safe state @@ -88,7 +90,7 @@ GET https://backend.insta.the1s.de/api/items/12345678 "id": 1, "item_name": "DJI 1er Mikro", "can_borrow_role": 4, - "inSafe": 1, + "in_safe": 1, "safe_nr": "01", "entry_created_at": "2025-08-19T22:02:16.000Z", "entry_updated_at": "2025-08-19T22:02:16.000Z", @@ -115,7 +117,7 @@ GET https://backend.insta.the1s.de/api/items/12345678 ### 2.2 Toggle item safe state -**POST** `/api/change-state/:key/:itemId/:state` +**POST** `/api/change-state/:key/:itemId` > You do not need this endpoint to set the states of the items when the items are taken out or returned. When you take or return a loan, the item states are set automatically by the loan endpoints. This endpoint is only for manually toggling the `inSafe` state of an item. @@ -123,21 +125,20 @@ Path parameters: - `:key` – API key (8 digits) - `:itemId` – numeric `id` of the item -- `:state` – must be `"1"` or `"0"` Handler in `api.route.js` calls `changeInSafeStateV2(itemId)`, which executes: ```sql -UPDATE items SET inSafe = NOT inSafe WHERE id = ? +UPDATE items SET in_safe = NOT in_safe WHERE id = ? ``` #### Example request ```http -POST https://backend.insta.the1s.de/api/change-state/12345678/42/1 +POST https://backend.insta.the1s.de/api/change-state/12345678/42 ``` -(Will toggle `inSafe` for item `42`, regardless of the final `1`.) +(Will toggle `in_safe` for item `42`.) #### Successful response (current implementation) @@ -301,13 +302,21 @@ POST https://backend.insta.the1s.de/api/set-return-date/12345678/646473 **Success – list (authenticated items):** ```json -{ "data": [ /* array of rows */ ] } +{ + "data": [ + /* array of rows */ + ] +} ``` **Success – single loan:** ```json -{ "data": { /* selected loan fields */ } } +{ + "data": { + /* selected loan fields */ + } +} ``` **Success – mutations (current code):** @@ -333,4 +342,4 @@ POST https://backend.insta.the1s.de/api/set-return-date/12345678/646473 - `400 Bad Request` – invalid `state` parameter - `401 Unauthorized` – invalid/missing API key - `404 Not Found` – loan not found -- `500 Internal Server Error` – database / server failure or `success: false` from DB layer \ No newline at end of file +- `500 Internal Server Error` – database / server failure or `success: false` from DB layer diff --git a/FrontendV2/src/pages/MyLoansPage.tsx b/FrontendV2/src/pages/MyLoansPage.tsx index 31148b2..5219c2e 100644 --- a/FrontendV2/src/pages/MyLoansPage.tsx +++ b/FrontendV2/src/pages/MyLoansPage.tsx @@ -13,6 +13,7 @@ import { Dialog, Portal, Code, + Box, } from "@chakra-ui/react"; import { Header } from "@/components/Header"; import { Trash2 } from "lucide-react"; @@ -129,114 +130,125 @@ export const MyLoansPage = () => { )} {loans && ( - - - {/* Ausleihcode */} - - {/* Startdatum */} - - {/* Enddatum */} - - {/* Geräte (flexibler) */} - - {/* Ausleihdatum */} - - {/* Rückgabedatum */} - - {/* Notiz */} - - {/* Aktionen */} - - - - - {t("loan-code")} - {t("start-date")} - {t("end-date")} - {t("devices")} - {t("take-date")} - {t("return-date")} - {t("note")} - {t("actions")} - - - - {loans.map((loan) => ( - - - - {`${loan.loan_code}`} - - - {formatDate(loan.start_date)} - {formatDate(loan.end_date)} - - - {loan.loaned_items_name} - - - {formatDate(loan.take_date)} - {formatDate(loan.returned_date)} - {loan.note} - - - - - - - - - - - {t("sure")} - - - - {t("sure-delete-loan-0")} - - {delLoanCode} - {" "} - {t("sure-delete-loan-1")} -
- {t("sure-delete-loan-2")} -
-
- - - - - - - - - -
-
-
-
-
+ + + {/* Ausleihcode */} + + {/* Startdatum */} + + {/* Enddatum */} + + {/* Geräte (flexibler) */} + + {/* Ausleihdatum */} + + {/* Rückgabedatum */} + + {/* Notiz */} + + {/* Aktionen */} + + + + + {t("loan-code")} + {t("start-date")} + {t("end-date")} + {t("devices")} + {t("take-date")} + {t("return-date")} + {t("note")} + {t("actions")} - ))} -
-
+ + + {loans.map((loan) => ( + + + + {`${loan.loan_code}`} + + + {formatDate(loan.start_date)} + {formatDate(loan.end_date)} + + + {loan.loaned_items_name} + + + {formatDate(loan.take_date)} + {formatDate(loan.returned_date)} + {loan.note} + + + + + + + + + + + {t("sure")} + + + + {t("sure-delete-loan-0")} + + {delLoanCode} + {" "} + {t("sure-delete-loan-1")} +
+ {t("sure-delete-loan-2")} +
+
+ + + + + + + + + +
+
+
+
+
+
+ ))} +
+ + )} diff --git a/admin/src/components/AddAPIKey.tsx b/admin/src/components/AddAPIKey.tsx index 459e1ed..36fcd80 100644 --- a/admin/src/components/AddAPIKey.tsx +++ b/admin/src/components/AddAPIKey.tsx @@ -37,17 +37,17 @@ const AddAPIKey: React.FC = ({ onClose, alert }) => { - {value.length} / {15} + {value.length} / {8} } > { - setValue(e.currentTarget.value.slice(0, 15)); + setValue(e.currentTarget.value.slice(0, 8)); }} /> diff --git a/backend/services/database.js b/backend/services/database.js index 4549509..960432d 100644 --- a/backend/services/database.js +++ b/backend/services/database.js @@ -41,7 +41,7 @@ export const getLoanByCodeV2 = async (loan_code) => { export const changeInSafeStateV2 = async (itemId) => { const [result] = await pool.query( - "UPDATE items SET inSafe = NOT inSafe WHERE id = ?", + "UPDATE items SET in = NOT inSafe WHERE id = ?", [itemId] ); if (result.affectedRows > 0) { diff --git a/backendV2/routes/api/api.database.js b/backendV2/routes/api/api.database.js index f1d3581..507453b 100644 --- a/backendV2/routes/api/api.database.js +++ b/backendV2/routes/api/api.database.js @@ -21,7 +21,7 @@ export const getItemsFromDatabaseV2 = async () => { export const getLoanByCodeV2 = async (loan_code) => { const [result] = await pool.query( - "SELECT first_name, returned_date, take_date, lockers FROM loans WHERE loan_code = ?;", + "SELECT username, returned_date, take_date, lockers FROM loans WHERE loan_code = ?;", [loan_code] ); if (result.length > 0) { @@ -32,7 +32,7 @@ export const getLoanByCodeV2 = async (loan_code) => { export const changeInSafeStateV2 = async (itemId) => { const [result] = await pool.query( - "UPDATE items SET inSafe = NOT inSafe WHERE id = ?", + "UPDATE items SET in_safe = NOT in_safe WHERE id = ?", [itemId] ); if (result.affectedRows > 0) { @@ -59,7 +59,7 @@ export const setReturnDateV2 = async (loanCode) => { : JSON.parse(items[0].loaned_items_id || "[]"); const [setItemStates] = await pool.query( - "UPDATE items SET inSafe = 1, currently_borrowing = NULL, last_borrowed_person = (?) WHERE id IN (?)", + "UPDATE items SET in_safe = 1, currently_borrowing = NULL, last_borrowed_person = (?) WHERE id IN (?)", [owner[0].username, itemIds] ); @@ -92,7 +92,7 @@ export const setTakeDateV2 = async (loanCode) => { : JSON.parse(items[0].loaned_items_id || "[]"); const [setItemStates] = await pool.query( - "UPDATE items SET inSafe = 0, currently_borrowing = (?) WHERE id IN (?)", + "UPDATE items SET in_safe = 0, currently_borrowing = (?) WHERE id IN (?)", [owner[0].username, itemIds] ); diff --git a/backendV2/routes/api/api.route.js b/backendV2/routes/api/api.route.js index d45b227..4d1dcee 100644 --- a/backendV2/routes/api/api.route.js +++ b/backendV2/routes/api/api.route.js @@ -23,25 +23,16 @@ router.get("/items/:key", authenticate, async (req, res) => { }); // Route for API to control the safe state of an item -router.post( - "/change-state/:key/:itemId/:state", - authenticate, - async (req, res) => { - const itemId = req.params.itemId; - const state = req.params.state; +router.post("/change-state/:key/:itemId", authenticate, async (req, res) => { + const itemId = req.params.itemId; - if (state === "1" || state === "0") { - const result = await changeInSafeStateV2(itemId, state); - if (result.success) { - res.status(200).json({ data: result.data }); - } else { - res.status(500).json({ message: "Failed to update item state" }); - } - } else { - res.status(400).json({ message: "Invalid state value" }); - } + const result = await changeInSafeStateV2(itemId); + if (result.success) { + res.status(200).json({ data: result.data }); + } else { + res.status(500).json({ message: "Failed to update item state" }); } -); +}); // Route for API to get a loan by its code router.get(