feat: add door_key field to items and update related logic in forms and database

This commit is contained in:
2025-11-24 17:12:37 +01:00
parent df6b5eac59
commit fd2ccaa747
8 changed files with 45 additions and 19 deletions

View File

@@ -29,8 +29,8 @@ const AddItemForm: React.FC<AddItemFormProps> = ({ onClose, alert }) => {
<Input id="item_name" placeholder="z.B. Laptop" />
</Field.Root>
<Field.Root>
<Field.Label>Schließfachnummer (immer zwei Zahlen)</Field.Label>
<Input id="safe_nr" placeholder="Nummer 01 - 06" />
<Field.Label>Schließfachnummer</Field.Label>
<Input id="safe_nr" placeholder="Nummer 1 - 6" />
</Field.Root>
<Field.Root>
<Field.Label>Ausleih-Berechtigung (Rolle)</Field.Label>
@@ -64,7 +64,6 @@ const AddItemForm: React.FC<AddItemFormProps> = ({ onClose, alert }) => {
const safeNr = safeNrValue === "" ? null : safeNrValue;
if (!name || Number.isNaN(role)) return;
if (safeNr !== null && !/^\d{2}$/.test(safeNr)) return;
const res = await createItem(name, role, safeNr);
if (res.success) {

View File

@@ -38,6 +38,7 @@ type Items = {
can_borrow_role: string;
in_safe: boolean;
safe_nr: string;
door_key: string;
entry_created_at: string;
entry_updated_at: string;
last_borrowed_person: string | null;
@@ -72,6 +73,12 @@ const ItemTable: React.FC = () => {
);
};
const handleDoorKeyChange = (id: number, value: string) => {
setItems((prev) =>
prev.map((it) => (it.id === id ? { ...it, door_key: value } : it))
);
};
const setError = (
status: "error" | "success",
message: string,
@@ -204,6 +211,9 @@ const ItemTable: React.FC = () => {
<Table.ColumnHeader>
<strong>Schließfachnummer</strong>
</Table.ColumnHeader>
<Table.ColumnHeader>
<strong>Schlüssel</strong>
</Table.ColumnHeader>
<Table.ColumnHeader>
<strong>Eintrag erstellt am</strong>
</Table.ColumnHeader>
@@ -290,6 +300,16 @@ const ItemTable: React.FC = () => {
value={item.safe_nr}
/>
</Table.Cell>
<Table.Cell>
<Input
size="sm"
w="max-content"
onChange={(e) =>
handleDoorKeyChange(item.id, e.target.value)
}
value={item.door_key}
/>
</Table.Cell>
<Table.Cell>{formatDateTime(item.entry_created_at)}</Table.Cell>
<Table.Cell>{formatDateTime(item.entry_updated_at)}</Table.Cell>
<Table.Cell>{item.last_borrowed_person}</Table.Cell>
@@ -301,6 +321,7 @@ const ItemTable: React.FC = () => {
item.id,
item.item_name,
item.safe_nr,
item.door_key,
item.can_borrow_role
).then((response) => {
if (response.success) {

View File

@@ -184,7 +184,7 @@ export const createItem = async (
return {
success: false,
message:
"Fehler beim Erstellen des Gegenstands. Der Name des Gegenstandes darf nicht mehrmals vergeben werden.",
"Fehler beim Erstellen des Gegenstands. Der Name des Gegenstandes und die Schließfachnummer dürfen nicht mehrmals vergeben werden.",
};
}
return { success: true };
@@ -198,6 +198,7 @@ export const handleEditItems = async (
itemId: number,
item_name: string,
safe_nr: string | null,
door_key: string | null,
can_borrow_role: string
) => {
try {
@@ -209,7 +210,7 @@ export const handleEditItems = async (
"Content-Type": "application/json",
Authorization: `Bearer ${Cookies.get("token")}`,
},
body: JSON.stringify({ item_name, safe_nr, can_borrow_role }),
body: JSON.stringify({ item_name, safe_nr, door_key, can_borrow_role }),
}
);
if (!response.ok) {

View File

@@ -36,7 +36,8 @@ export const editItemById = async (
itemId,
item_name,
can_borrow_role,
safe_nr
safe_nr,
door_key
) => {
let newSafeNr;
if (safe_nr === null || safe_nr === "") {
@@ -45,8 +46,8 @@ export const editItemById = async (
newSafeNr = safe_nr;
}
const [result] = await pool.query(
"UPDATE items SET item_name = ?, can_borrow_role = ?, safe_nr = ?, entry_updated_at = NOW() WHERE id = ?",
[item_name, can_borrow_role, newSafeNr, itemId]
"UPDATE items SET item_name = ?, can_borrow_role = ?, safe_nr = ?, door_key = ?, entry_updated_at = NOW() WHERE id = ?",
[item_name, can_borrow_role, newSafeNr, door_key, itemId]
);
if (result.affectedRows > 0) return { success: true };
return { success: false };

View File

@@ -41,13 +41,14 @@ router.post("/create-item", authenticateAdmin, async (req, res) => {
router.post("/edit-item/:id", authenticateAdmin, async (req, res) => {
const itemId = req.params.id;
const { item_name, can_borrow_role, safe_nr } = req.body;
const { item_name, can_borrow_role, safe_nr, door_key } = req.body;
const result = await editItemById(
itemId,
item_name,
can_borrow_role,
safe_nr
safe_nr,
door_key
);
if (result.success) {
return res.status(200).json({ message: "Item edited successfully" });

View File

@@ -117,11 +117,19 @@ export const getAllLoansV2 = async () => {
export const openDoor = async (doorKey) => {
const [result] = await pool.query(
"SELECT lockers FROM doorKeys WHERE door_key = ?;",
"SELECT safe_nr, id FROM items WHERE door_key = ?;",
[doorKey]
);
if (result.length > 0) {
const [changeItemSate] = await pool.query(
"UPDATE items SET in_safe = NOT in_safe WHERE id = ?",
[result[0].id]
);
if (changeItemSate.affectedRows > 0) {
return { success: true, data: result[0] };
} else {
return { success: false };
}
}
return { success: false };
};

View File

@@ -80,6 +80,7 @@ router.post(
}
);
// Route for API to open a door
router.get("/open-door/:key/:doorKey", authenticate, async (req, res) => {
const doorKey = req.params.doorKey;

View File

@@ -38,6 +38,7 @@ CREATE TABLE items (
can_borrow_role INT NOT NULL,
in_safe bool NOT NULL DEFAULT true,
safe_nr INT DEFAULT NULL UNIQUE,
door_key INT DEFAULT NULL UNIQUE,
entry_created_at timestamp NULL DEFAULT CURRENT_TIMESTAMP,
entry_updated_at timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
last_borrowed_person varchar(255) DEFAULT NULL,
@@ -54,10 +55,3 @@ CREATE TABLE apiKeys (
PRIMARY KEY (id),
CHECK (api_key REGEXP '^[0-9]{8}$')
) ENGINE=InnoDB;
CREATE TABLE doorKeys (
id int NOT NULL AUTO_INCREMENT,
door_key INT NOT NULL,
lockers INT NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;