diff --git a/.gitignore b/.gitignore index 5fd7033..4913a08 100644 --- a/.gitignore +++ b/.gitignore @@ -111,4 +111,6 @@ backend/public/uploads/ # API keys and secrets (additional protection) config/ secrets/ -keys/ \ No newline at end of file +keys/ + +ToDo.txt \ No newline at end of file diff --git a/Docs/HELP.md b/Docs/HELP.md new file mode 100644 index 0000000..97d5fe1 --- /dev/null +++ b/Docs/HELP.md @@ -0,0 +1,11 @@ +# Hilfe Seite + +Hier finden Sie Informationen zur Verwendung des Systems. + +## Unerwartete Probleme + +Falls unerwartetet Probleme im Web oder im Safe auftreten sollten, können Sie den Support via Teams kontaktieren. + +**Kontaktpersonen:** +- Theis Gaedigk (Web & Safe) +- Niklas Brunke (Safe) \ No newline at end of file diff --git a/Docs/backend_API_docs/README.md b/Docs/backend_API_docs/README.md index d7b8c5b..2f005ae 100644 --- a/Docs/backend_API_docs/README.md +++ b/Docs/backend_API_docs/README.md @@ -8,7 +8,7 @@ On this page you will learn how my API works. When you look at my backend folder and file structure, you can see that I have two files called `API`. The first file called `api.js` is for my web frontend, because this file works together with my JWT token service. -But I have built a second API. You can see the second API file in the same directory, the file is called `apiV2.js`. +**\*But I have built a second API. You can see the second API file in the same directory, the file is called `apiV2.js`.** This is the file that you can use to build an API. @@ -45,21 +45,114 @@ Returns a list of all items and their details. #### Example Request ``` -GET /apiV2/items/your_admin_key +GET https://backend.insta.the1s.de/apiV2/items/your_admin_key ``` #### Example Response ``` -[ - { - "id": 1, - "item_name": "DJI 1er Mikro", - "can_borrow_role": "4", - "inSafe": 1 - }, - ... -] +{ + "data": [ + { + "id": 1, + "item_name": "DJI 1er Mikro", + "can_borrow_role": 4, + "inSafe": 1, + "entry_created_at": "2025-08-19T22:02:16.000Z" + }, + { + "id": 2, + "item_name": "DJI 2er Mikro 1", + "can_borrow_role": 4, + "inSafe": 1, + "entry_created_at": "2025-08-19T22:02:16.000Z" + }, + { + "id": 3, + "item_name": "DJI 2er Mikro 2", + "can_borrow_role": 4, + "inSafe": 1, + "entry_created_at": "2025-08-19T22:02:16.000Z" + }, + { + "id": 4, + "item_name": "Rode Richt Mikrofon", + "can_borrow_role": 2, + "inSafe": 1, + "entry_created_at": "2025-08-19T22:02:16.000Z" + }, + { + "id": 5, + "item_name": "Kamera Stativ", + "can_borrow_role": 1, + "inSafe": 1, + "entry_created_at": "2025-08-19T22:02:16.000Z" + }, + { + "id": 6, + "item_name": "SONY Kamera - inkl. Akkus und Objektiv", + "can_borrow_role": 1, + "inSafe": 1, + "entry_created_at": "2025-08-19T22:02:16.000Z" + }, + { + "id": 7, + "item_name": "MacBook inkl. Adapter", + "can_borrow_role": 2, + "inSafe": 1, + "entry_created_at": "2025-08-19T22:02:16.000Z" + }, + { + "id": 8, + "item_name": "SD Karten", + "can_borrow_role": 3, + "inSafe": 1, + "entry_created_at": "2025-08-19T22:02:16.000Z" + }, + { + "id": 9, + "item_name": "Kameragimbal", + "can_borrow_role": 1, + "inSafe": 1, + "entry_created_at": "2025-08-19T22:02:16.000Z" + }, + { + "id": 10, + "item_name": "ATEM MINI PRO", + "can_borrow_role": 1, + "inSafe": 1, + "entry_created_at": "2025-08-19T22:02:16.000Z" + }, + { + "id": 11, + "item_name": "Handygimbal", + "can_borrow_role": 4, + "inSafe": 1, + "entry_created_at": "2025-08-19T22:02:16.000Z" + }, + { + "id": 12, + "item_name": "Kameralfter", + "can_borrow_role": 1, + "inSafe": 1, + "entry_created_at": "2025-08-19T22:02:16.000Z" + }, + { + "id": 13, + "item_name": "Kleine Kamera 1 - inkl. Objektiv", + "can_borrow_role": 2, + "inSafe": 1, + "entry_created_at": "2025-08-19T22:02:16.000Z" + }, + { + "id": 14, + "item_name": "Kleine Kamera 2 - inkl. Objektiv", + "can_borrow_role": 2, + "inSafe": 1, + "entry_created_at": "2025-08-19T22:02:16.000Z" + } + ] +} ``` Each item has the following properties: @@ -69,6 +162,8 @@ Each item has the following properties: - `can_borrow_role`: The role ID that is allowed to borrow the item. - `inSafe`: Indicates whether the item is currently in the locker (1) or not (0). This variable/state can change over time. +_You also get an http 200 status code._ + --- ### 2. Change Item Safe State @@ -82,7 +177,7 @@ Updates the `inSafe` state of an item (whether it is in the locker). #### Example Request ``` -POST /apiV2/controlInSafe/your_admin_key/5/0 +POST https://backend.insta.the1s.de/apiV2/controlInSafe/your_admin_key/item_id/new_item_state ``` #### Example Response @@ -93,7 +188,7 @@ POST /apiV2/controlInSafe/your_admin_key/5/0 _An empty object means, that the operation was successful and no further information is returned._ -_You also get an http 2xx status code._ +_You also get an http 200 status code._ --- @@ -108,7 +203,7 @@ Sets the `returned_date` of a loan to the current server time. #### Example Request ``` -POST /apiV2/setReturnDate/your_admin_key/123456 +POST https://backend.insta.the1s.de/apiV2/setReturnDate/your_admin_key/your_loan_code ``` #### Example Response @@ -119,7 +214,7 @@ POST /apiV2/setReturnDate/your_admin_key/123456 _An empty object means, that the operation was successful and no further information is returned._ -_You also get an http 2xx status code._ +_You also get an http 200 status code._ --- @@ -134,7 +229,7 @@ Sets the `take_date` of a loan to the current server time. #### Example Request ``` -POST /apiV2/setTakeDate/your_admin_key/123456 +POST https://backend.insta.the1s.de/apiV2/setTakeDate/your_admin_key/your_loan_code ``` #### Example Response @@ -149,6 +244,57 @@ _You also get an http 2xx status code._ --- +### 5. Get whole loan by loan code + +**POST** `/getLoanByCode/:key/:loan_code` + +Retrieves the details of a specific loan by its unique code. + +- `loan_code`: The unique code of the loan. + +#### Example Request + +``` +GET https://backend.insta.the1s.de/getLoanByCode/your_admin_key/your_loan_code +``` + +#### Example Response + +``` +{ + "data": { + "id": 6, + "username": "theis", + "loan_code": 646473, + "start_date": "2025-08-25T13:23:00.000Z", + "end_date": "2025-08-26T13:23:00.000Z", + "take_date": null, + "returned_date": null, + "created_at": "2025-08-20T11:23:40.000Z", + "loaned_items_id": [ + 8, + 9 + ], + "loaned_items_name": [ + "SD Karten", + "Kameragimbal" + ] + } +} +``` + +_You also get an http 200 status code._ + +If the loan id does not exist, you will receive a 404 status code and an error message. + +``` +{ + "message": "Loan not found" +} +``` + +--- + ## Error Handling - `403 Forbidden`: Invalid or missing API key. diff --git a/frontend/src/components/Footer.tsx b/frontend/src/components/Footer.tsx new file mode 100644 index 0000000..55d4654 --- /dev/null +++ b/frontend/src/components/Footer.tsx @@ -0,0 +1,12 @@ +import React from "react"; + +const Footer: React.FC = () => { + return ( + + ); +}; + +export default Footer; diff --git a/frontend/src/components/Header.tsx b/frontend/src/components/Header.tsx index a7e8454..b04bd4c 100644 --- a/frontend/src/components/Header.tsx +++ b/frontend/src/components/Header.tsx @@ -23,6 +23,16 @@ const Header: React.FC = ({ onLogout }) => { > Logout + + + + + + ); diff --git a/frontend/src/components/LoginForm.tsx b/frontend/src/components/LoginForm.tsx index ea74839..2769b06 100644 --- a/frontend/src/components/LoginForm.tsx +++ b/frontend/src/components/LoginForm.tsx @@ -1,4 +1,5 @@ import React from "react"; +import Footer from "./Footer"; import { useState } from "react"; import { loginUser } from "../utils/fetchData"; import { myToast } from "../utils/toastify"; @@ -66,6 +67,7 @@ const LoginForm: React.FC = ({ onLogin }) => { +