Compare commits
4 Commits
a1435e3280
...
c389b38cf5
Author | SHA1 | Date | |
---|---|---|---|
c389b38cf5 | |||
4080d171cf | |||
6d4afa46d7 | |||
ffc8fbcefc |
@@ -78,9 +78,51 @@ POST /apiV2/controlInSafe/your_admin_key/5/0
|
|||||||
#### Example Response
|
#### Example Response
|
||||||
|
|
||||||
```
|
```
|
||||||
{
|
{}
|
||||||
"message": "Item state updated successfully"
|
```
|
||||||
}
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. Set Return Date
|
||||||
|
|
||||||
|
**POST** `/apiV2/setReturnDate/:key/:loan_code`
|
||||||
|
|
||||||
|
Sets the `returned_date` of a loan to the current server time.
|
||||||
|
|
||||||
|
- `loan_code`: The unique code of the loan.
|
||||||
|
|
||||||
|
#### Example Request
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /apiV2/setReturnDate/your_admin_key/123456
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Example Response
|
||||||
|
|
||||||
|
```
|
||||||
|
{}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. Set Take Date
|
||||||
|
|
||||||
|
**POST** `/apiV2/setTakeDate/:key/:loan_code`
|
||||||
|
|
||||||
|
Sets the `take_date` of a loan to the current server time.
|
||||||
|
|
||||||
|
- `loan_code`: The unique code of the loan.
|
||||||
|
|
||||||
|
#### Example Request
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /apiV2/setTakeDate/your_admin_key/123456
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Example Response
|
||||||
|
|
||||||
|
```
|
||||||
|
{}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@@ -3,16 +3,19 @@ import dotenv from "dotenv";
|
|||||||
import {
|
import {
|
||||||
getItemsFromDatabaseV2,
|
getItemsFromDatabaseV2,
|
||||||
changeInSafeStateV2,
|
changeInSafeStateV2,
|
||||||
|
setReturnDateV2,
|
||||||
|
setTakeDateV2,
|
||||||
} from "../services/database.js";
|
} from "../services/database.js";
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
|
// Route for API to get ALL items from the database
|
||||||
router.get("/items/:key", async (req, res) => {
|
router.get("/items/:key", async (req, res) => {
|
||||||
if (req.params.key === process.env.ADMIN_ID) {
|
if (req.params.key === process.env.ADMIN_ID) {
|
||||||
const result = await getItemsFromDatabaseV2();
|
const result = await getItemsFromDatabaseV2();
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
res.status(200).json(result.data);
|
res.status(200).json({ data: result.data });
|
||||||
} else {
|
} else {
|
||||||
res.status(500).json({ message: "Failed to fetch items" });
|
res.status(500).json({ message: "Failed to fetch items" });
|
||||||
}
|
}
|
||||||
@@ -21,6 +24,7 @@ router.get("/items/:key", async (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Route for API to control the position of an item
|
||||||
router.post("/controlInSafe/:key/:itemId/:state", async (req, res) => {
|
router.post("/controlInSafe/:key/:itemId/:state", async (req, res) => {
|
||||||
if (req.params.key === process.env.ADMIN_ID) {
|
if (req.params.key === process.env.ADMIN_ID) {
|
||||||
const itemId = req.params.itemId;
|
const itemId = req.params.itemId;
|
||||||
@@ -28,7 +32,7 @@ router.post("/controlInSafe/:key/:itemId/:state", async (req, res) => {
|
|||||||
if (state === "1" || state === "0") {
|
if (state === "1" || state === "0") {
|
||||||
const result = await changeInSafeStateV2(itemId, state);
|
const result = await changeInSafeStateV2(itemId, state);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
res.status(200).json({ message: "Item state updated successfully" });
|
res.status(200).json({ data: result.data });
|
||||||
} else {
|
} else {
|
||||||
res.status(500).json({ message: "Failed to update item state" });
|
res.status(500).json({ message: "Failed to update item state" });
|
||||||
}
|
}
|
||||||
@@ -40,4 +44,36 @@ router.post("/controlInSafe/:key/:itemId/:state", async (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Route for API to set the return date
|
||||||
|
router.post("/setReturnDate/:key/:loan_code", async (req, res) => {
|
||||||
|
if (req.params.key === process.env.ADMIN_ID) {
|
||||||
|
const loanCode = req.params.loan_code;
|
||||||
|
|
||||||
|
const result = await setReturnDateV2(loanCode);
|
||||||
|
if (result.success) {
|
||||||
|
res.status(200).json({ data: result.data });
|
||||||
|
} else {
|
||||||
|
res.status(500).json({ message: "Failed to set return date" });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res.status(403).json({ message: "Access denied" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Route for API to set the take away date
|
||||||
|
router.post("/setTakeDate/:key/:loan_code", async (req, res) => {
|
||||||
|
if (req.params.key === process.env.ADMIN_ID) {
|
||||||
|
const loanCode = req.params.loan_code;
|
||||||
|
|
||||||
|
const result = await setTakeDateV2(loanCode);
|
||||||
|
if (result.success) {
|
||||||
|
res.status(200).json({ data: result.data });
|
||||||
|
} else {
|
||||||
|
res.status(500).json({ message: "Failed to set take date" });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res.status(403).json({ message: "Access denied" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
@@ -7,6 +7,7 @@ CREATE TABLE `users` (
|
|||||||
`username` varchar(100) NOT NULL,
|
`username` varchar(100) NOT NULL,
|
||||||
`password` varchar(255) NOT NULL,
|
`password` varchar(255) NOT NULL,
|
||||||
`role` int DEFAULT NULL,
|
`role` int DEFAULT NULL,
|
||||||
|
`entry_created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `username` (`username`)
|
UNIQUE KEY `username` (`username`)
|
||||||
);
|
);
|
||||||
@@ -17,6 +18,7 @@ CREATE TABLE `loans` (
|
|||||||
`loan_code` int NOT NULL,
|
`loan_code` int NOT NULL,
|
||||||
`start_date` timestamp NOT NULL,
|
`start_date` timestamp NOT NULL,
|
||||||
`end_date` timestamp NOT NULL,
|
`end_date` timestamp NOT NULL,
|
||||||
|
`take_date` timestamp NULL DEFAULT NULL,
|
||||||
`returned_date` timestamp NULL DEFAULT NULL,
|
`returned_date` timestamp NULL DEFAULT NULL,
|
||||||
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
|
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
`loaned_items_id` json NOT NULL DEFAULT ('[]'),
|
`loaned_items_id` json NOT NULL DEFAULT ('[]'),
|
||||||
@@ -30,6 +32,7 @@ CREATE TABLE `items` (
|
|||||||
`item_name` varchar(255) NOT NULL,
|
`item_name` varchar(255) NOT NULL,
|
||||||
`can_borrow_role` INT NOT NULL,
|
`can_borrow_role` INT NOT NULL,
|
||||||
`inSafe` tinyint(1) NOT NULL DEFAULT '1',
|
`inSafe` tinyint(1) NOT NULL DEFAULT '1',
|
||||||
|
`entry_created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `item_name` (`item_name`)
|
UNIQUE KEY `item_name` (`item_name`)
|
||||||
);
|
);
|
||||||
@@ -38,100 +41,40 @@ CREATE TABLE `lockers` (
|
|||||||
`id` int NOT NULL AUTO_INCREMENT,
|
`id` int NOT NULL AUTO_INCREMENT,
|
||||||
`item` varchar(255) NOT NULL,
|
`item` varchar(255) NOT NULL,
|
||||||
`locker_number` int NOT NULL,
|
`locker_number` int NOT NULL,
|
||||||
|
`entry_created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `item` (`item`),
|
UNIQUE KEY `item` (`item`),
|
||||||
UNIQUE KEY `locker_number` (`locker_number`)
|
UNIQUE KEY `locker_number` (`locker_number`)
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Mock data for users
|
|
||||||
INSERT INTO `users` (`username`, `password`, `role`) VALUES
|
|
||||||
('alice', 'password1', 1),
|
|
||||||
('bob', 'password2', 2),
|
|
||||||
('carol', 'password3', 1),
|
|
||||||
('dave', 'password4', 3),
|
|
||||||
('eve', 'password5', 2),
|
|
||||||
('frank', 'password6', 1),
|
|
||||||
('grace', 'password7', 2),
|
|
||||||
('heidi', 'password8', 3),
|
|
||||||
('ivan', 'password9', 1),
|
|
||||||
('judy', 'password10', 2),
|
|
||||||
('mallory', 'password11', 1),
|
|
||||||
('oscar', 'password12', 3),
|
|
||||||
('peggy', 'password13', 2),
|
|
||||||
('trent', 'password14', 1),
|
|
||||||
('victor', 'password15', 2),
|
|
||||||
('wendy', 'password16', 3),
|
|
||||||
('zoe', 'password17', 1),
|
|
||||||
('quinn', 'password18', 2),
|
|
||||||
('ruth', 'password19', 1),
|
|
||||||
('sam', 'password20', 3);
|
|
||||||
|
|
||||||
-- Mock data for loans
|
|
||||||
INSERT INTO `loans` (`username`, `loan_code`, `start_date`, `end_date`, `returned_date`, `loaned_items_id`, `loaned_items_name`)
|
|
||||||
VALUES
|
|
||||||
('alice', 1001, '2025-08-01 09:00:00', '2025-08-10 09:00:00', NULL, '[1,2]', '["Laptop","Projector"]'),
|
|
||||||
('bob', 1002, '2025-08-02 10:00:00', '2025-08-12 10:00:00', NULL, '[3]', '["Tablet"]'),
|
|
||||||
('carol', 1003, '2025-08-03 11:00:00', '2025-08-13 11:00:00', NULL, '[4,5]', '["Camera","Tripod"]'),
|
|
||||||
('dave', 1004, '2025-08-04 12:00:00', '2025-08-14 12:00:00', NULL, '[6]', '["Microphone"]'),
|
|
||||||
('eve', 1005, '2025-08-05 13:00:00', '2025-08-15 13:00:00', NULL, '[7,8]', '["Speaker","Monitor"]'),
|
|
||||||
('frank', 1006, '2025-08-06 14:00:00', '2025-08-16 14:00:00', NULL, '[9]', '["Keyboard"]'),
|
|
||||||
('grace', 1007, '2025-08-07 15:00:00', '2025-08-17 15:00:00', NULL, '[10,11]', '["Mouse","Printer"]'),
|
|
||||||
('heidi', 1008, '2025-08-08 16:00:00', '2025-08-18 16:00:00', NULL, '[12]', '["Scanner"]'),
|
|
||||||
('ivan', 1009, '2025-08-09 17:00:00', '2025-08-19 17:00:00', NULL, '[13,14]', '["Router","Switch"]'),
|
|
||||||
('judy', 1010, '2025-08-10 18:00:00', '2025-08-20 18:00:00', NULL, '[15]', '["Projector"]'),
|
|
||||||
('mallory', 1011, '2025-08-11 09:00:00', '2025-08-21 09:00:00', NULL, '[16,17]', '["Laptop","Tablet"]'),
|
|
||||||
('oscar', 1012, '2025-08-12 10:00:00', '2025-08-22 10:00:00', NULL, '[18]', '["Camera"]'),
|
|
||||||
('peggy', 1013, '2025-08-13 11:00:00', '2025-08-23 11:00:00', NULL, '[19,20]', '["Tripod","Microphone"]'),
|
|
||||||
('trent', 1014, '2025-08-14 12:00:00', '2025-08-24 12:00:00', NULL, '[1]', '["Laptop"]'),
|
|
||||||
('victor', 1015, '2025-08-15 13:00:00', '2025-08-25 13:00:00', NULL, '[2,3]', '["Projector","Tablet"]'),
|
|
||||||
('wendy', 1016, '2025-08-16 14:00:00', '2025-08-26 14:00:00', NULL, '[4]', '["Camera"]'),
|
|
||||||
('zoe', 1017, '2025-08-17 15:00:00', '2025-08-27 15:00:00', NULL, '[5,6]', '["Tripod","Microphone"]'),
|
|
||||||
('quinn', 1018, '2025-08-18 16:00:00', '2025-08-28 16:00:00', NULL, '[7]', '["Speaker"]'),
|
|
||||||
('ruth', 1019, '2025-08-19 17:00:00', '2025-08-29 17:00:00', NULL, '[8,9]', '["Monitor","Keyboard"]'),
|
|
||||||
('sam', 1020, '2025-08-20 18:00:00', '2025-08-30 18:00:00', NULL, '[10]', '["Mouse"]');
|
|
||||||
|
|
||||||
-- Mock data for items
|
|
||||||
INSERT INTO `items` (`item_name`, `can_borrow_role`, `inSafe`) VALUES
|
INSERT INTO `items` (`item_name`, `can_borrow_role`, `inSafe`) VALUES
|
||||||
('Laptop', 1, 1),
|
('DJI 1er Mikro', 4, 1),
|
||||||
('Projector', 2, 1),
|
('DJI 2er Mikro 1', 4, 1),
|
||||||
('Tablet', 1, 1),
|
('DJI 2er Mikro 2', 4, 1),
|
||||||
('Camera', 2, 1),
|
('Rode Richt Mikrofon', 2, 1),
|
||||||
('Tripod', 1, 1),
|
('Kamera Stativ', 1, 0),
|
||||||
('Microphone', 3, 1),
|
('SONY Kamera - inkl. Akkus und Objektiv', 1, 1),
|
||||||
('Speaker', 2, 1),
|
('MacBook inkl. Adapter', 2, 0),
|
||||||
('Monitor', 1, 1),
|
('SD Karten', 3, 0),
|
||||||
('Keyboard', 2, 1),
|
('Kameragimbal', 1, 0),
|
||||||
('Mouse', 1, 1),
|
('ATEM MINI PRO', 1, 1),
|
||||||
('Printer', 3, 1),
|
('Handygimbal', 4, 0),
|
||||||
('Scanner', 2, 1),
|
('Kameralüfter', 1, 1),
|
||||||
('Router', 1, 1),
|
('Kleine Kamera 1 - inkl. Objektiv', 2, 1),
|
||||||
('Switch', 2, 1),
|
('Kleine Kamera 2 - inkl. Objektiv', 2, 1);
|
||||||
('Charger', 1, 1),
|
|
||||||
('USB Cable', 2, 1),
|
|
||||||
('HDMI Cable', 1, 1),
|
|
||||||
('Webcam', 3, 1),
|
|
||||||
('Headphones', 2, 1),
|
|
||||||
('Smartphone', 1, 1);
|
|
||||||
|
|
||||||
-- Mock data for lockers
|
|
||||||
INSERT INTO `lockers` (`item`, `locker_number`) VALUES
|
INSERT INTO `lockers` (`item`, `locker_number`) VALUES
|
||||||
('Laptop', 101),
|
('DJI 1er Mikro', 1),
|
||||||
('Projector', 102),
|
('DJI 2er Mikro 1', 2),
|
||||||
('Tablet', 103),
|
('DJI 2er Mikro 2', 3),
|
||||||
('Camera', 104),
|
('Rode Richt Mikrofon', 4),
|
||||||
('Tripod', 105),
|
('Kamera Stativ', 5),
|
||||||
('Microphone', 106),
|
('SONY Kamera - inkl. Akkus und Objektiv', 6),
|
||||||
('Speaker', 107),
|
('MacBook inkl. Adapter', 7),
|
||||||
('Monitor', 108),
|
('SD Karten', 8),
|
||||||
('Keyboard', 109),
|
('Kameragimbal', 9),
|
||||||
('Mouse', 110),
|
('ATEM MINI PRO', 10),
|
||||||
('Printer', 111),
|
('Handygimbal', 11),
|
||||||
('Scanner', 112),
|
('Kameralüfter', 12),
|
||||||
('Router', 113),
|
('Kleine Kamera 1 - inkl. Objektiv', 13),
|
||||||
('Switch', 114),
|
('Kleine Kamera 2 - inkl. Objektiv', 14);
|
||||||
('Charger', 115),
|
|
||||||
('USB Cable', 116),
|
|
||||||
('HDMI Cable', 117),
|
|
||||||
('Webcam', 118),
|
|
||||||
('Headphones', 119),
|
|
||||||
('Smartphone', 120);
|
|
@@ -39,6 +39,28 @@ export const changeInSafeStateV2 = async (itemId, state) => {
|
|||||||
return { success: false };
|
return { success: false };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const setReturnDateV2 = async (loanCode) => {
|
||||||
|
const [result] = await pool.query(
|
||||||
|
"UPDATE loans SET returned_date = NOW() WHERE loan_code = ?",
|
||||||
|
[loanCode]
|
||||||
|
);
|
||||||
|
if (result.affectedRows > 0) {
|
||||||
|
return { success: true };
|
||||||
|
}
|
||||||
|
return { success: false };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const setTakeDateV2 = async (loanCode) => {
|
||||||
|
const [result] = await pool.query(
|
||||||
|
"UPDATE loans SET take_date = NOW() WHERE loan_code = ?",
|
||||||
|
[loanCode]
|
||||||
|
);
|
||||||
|
if (result.affectedRows > 0) {
|
||||||
|
return { success: true };
|
||||||
|
}
|
||||||
|
return { success: false };
|
||||||
|
};
|
||||||
|
|
||||||
export const getItemsFromDatabase = async (role) => {
|
export const getItemsFromDatabase = async (role) => {
|
||||||
const sql =
|
const sql =
|
||||||
role == 0
|
role == 0
|
||||||
|
@@ -13,14 +13,12 @@ interface BorrowItem {
|
|||||||
|
|
||||||
const LOCAL_STORAGE_KEY = "borrowableItems";
|
const LOCAL_STORAGE_KEY = "borrowableItems";
|
||||||
|
|
||||||
// Einfache Type-Guard/Validierung
|
|
||||||
const isBorrowItem = (v: any): v is BorrowItem =>
|
const isBorrowItem = (v: any): v is BorrowItem =>
|
||||||
v &&
|
v &&
|
||||||
typeof v.id === "number" &&
|
typeof v.id === "number" &&
|
||||||
(typeof v.item_name === "string" || typeof v.name === "string") &&
|
(typeof v.item_name === "string" || typeof v.name === "string") &&
|
||||||
(typeof v.can_borrow_role === "string" || typeof v.role === "string");
|
(typeof v.can_borrow_role === "string" || typeof v.role === "string");
|
||||||
|
|
||||||
// Helfer: unterschiedliche Server-Shapes normalisieren
|
|
||||||
function normalizeBorrowable(data: any): BorrowItem[] {
|
function normalizeBorrowable(data: any): BorrowItem[] {
|
||||||
const rawArr = Array.isArray(data)
|
const rawArr = Array.isArray(data)
|
||||||
? data
|
? data
|
||||||
@@ -52,7 +50,6 @@ function normalizeBorrowable(data: any): BorrowItem[] {
|
|||||||
.filter(Boolean) as BorrowItem[];
|
.filter(Boolean) as BorrowItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hook, der automatisch aus dem Local Storage liest und auf Änderungen hört
|
|
||||||
function useBorrowableItems() {
|
function useBorrowableItems() {
|
||||||
const [items, setItems] = React.useState<BorrowItem[]>([]);
|
const [items, setItems] = React.useState<BorrowItem[]>([]);
|
||||||
|
|
||||||
|
@@ -8,6 +8,7 @@ type Loan = {
|
|||||||
loan_code: number;
|
loan_code: number;
|
||||||
start_date: string;
|
start_date: string;
|
||||||
end_date: string;
|
end_date: string;
|
||||||
|
take_date: string | null;
|
||||||
returned_date: string | null;
|
returned_date: string | null;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
loaned_items_id: number[];
|
loaned_items_id: number[];
|
||||||
@@ -89,6 +90,9 @@ const Form4: React.FC = () => {
|
|||||||
<th className="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-600">
|
<th className="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-600">
|
||||||
Ende
|
Ende
|
||||||
</th>
|
</th>
|
||||||
|
<th className="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-600">
|
||||||
|
Abgeholt
|
||||||
|
</th>
|
||||||
<th className="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-600">
|
<th className="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-600">
|
||||||
Zurückgegeben
|
Zurückgegeben
|
||||||
</th>
|
</th>
|
||||||
@@ -118,6 +122,9 @@ const Form4: React.FC = () => {
|
|||||||
<td className="px-4 py-3 whitespace-nowrap font-mono tabular-nums text-gray-900">
|
<td className="px-4 py-3 whitespace-nowrap font-mono tabular-nums text-gray-900">
|
||||||
{formatDate(loan.end_date)}
|
{formatDate(loan.end_date)}
|
||||||
</td>
|
</td>
|
||||||
|
<td className="px-4 py-3 whitespace-nowrap font-mono tabular-nums text-gray-900">
|
||||||
|
{formatDate(loan.take_date)}
|
||||||
|
</td>
|
||||||
<td className="px-4 py-3 whitespace-nowrap font-mono tabular-nums text-gray-900">
|
<td className="px-4 py-3 whitespace-nowrap font-mono tabular-nums text-gray-900">
|
||||||
{formatDate(loan.returned_date)}
|
{formatDate(loan.returned_date)}
|
||||||
</td>
|
</td>
|
||||||
|
Reference in New Issue
Block a user