feat: Implement loan management features including fetching, creating, and deleting loans
- Added database functions for managing loans: getLoans, getUserLoans, deleteLoan, and createLoan. - Updated frontend to include new Form4 for displaying user loans and handling loan deletions. - Replaced Form3 with Form4 in App component. - Enhanced Form1 to set borrowing dates and fetch available items. - Improved Form2 to display borrowable items and allow selection for loans. - Introduced utility functions for handling loan creation and deletion in userHandler. - Added event listeners for local storage updates to keep UI in sync. - Updated fetchData utility to retrieve loans and user loans from the backend.
This commit is contained in:
@@ -1,5 +1,13 @@
|
||||
import express from "express";
|
||||
import { loginFunc, getItemsFromDatabase } from "../services/database.js";
|
||||
import {
|
||||
loginFunc,
|
||||
getItemsFromDatabase,
|
||||
getLoansFromDatabase,
|
||||
getUserLoansFromDatabase,
|
||||
deleteLoanFromDatabase,
|
||||
getBorrowableItemsFromDatabase,
|
||||
createLoanInDatabase,
|
||||
} from "../services/database.js";
|
||||
import { authenticate, generateToken } from "../services/tokenService.js";
|
||||
const router = express.Router();
|
||||
|
||||
@@ -27,4 +35,114 @@ router.get("/items", authenticate, async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
router.get("/loans", authenticate, async (req, res) => {
|
||||
const result = await getLoansFromDatabase();
|
||||
if (result.success) {
|
||||
res.status(200).json(result.data);
|
||||
} else {
|
||||
res.status(500).json({ message: "Failed to fetch loans" });
|
||||
}
|
||||
});
|
||||
|
||||
router.get("/userLoans", authenticate, async (req, res) => {
|
||||
const result = await getUserLoansFromDatabase(req.user.username);
|
||||
if (result.success) {
|
||||
res.status(200).json(result.data);
|
||||
} else {
|
||||
res.status(500).json({ message: "Failed to fetch user loans" });
|
||||
}
|
||||
});
|
||||
|
||||
router.delete("/deleteLoan/:id", authenticate, async (req, res) => {
|
||||
const loanId = req.params.id;
|
||||
const result = await deleteLoanFromDatabase(loanId);
|
||||
if (result.success) {
|
||||
res.status(200).json({ message: "Loan deleted successfully" });
|
||||
} else {
|
||||
res.status(500).json({ message: "Failed to delete loan" });
|
||||
}
|
||||
});
|
||||
|
||||
router.post("/borrowableItems", authenticate, async (req, res) => {
|
||||
const { startDate, endDate } = req.body || {};
|
||||
if (!startDate || !endDate) {
|
||||
return res
|
||||
.status(400)
|
||||
.json({ message: "startDate and endDate are required" });
|
||||
}
|
||||
|
||||
const result = await getBorrowableItemsFromDatabase(
|
||||
startDate,
|
||||
endDate,
|
||||
req.user.role
|
||||
);
|
||||
if (result.success) {
|
||||
// return the array directly for consistency with /items
|
||||
return res.status(200).json(result.data);
|
||||
} else {
|
||||
return res
|
||||
.status(500)
|
||||
.json({ message: "Failed to fetch borrowable items" });
|
||||
}
|
||||
});
|
||||
|
||||
router.post("/createLoan", authenticate, async (req, res) => {
|
||||
try {
|
||||
const { items, startDate, endDate } = req.body || {};
|
||||
|
||||
if (!Array.isArray(items) || items.length === 0) {
|
||||
return res.status(400).json({ message: "Items array is required" });
|
||||
}
|
||||
|
||||
// If dates are not provided, default to now .. +7 days
|
||||
const start =
|
||||
startDate ?? new Date().toISOString().slice(0, 19).replace("T", " ");
|
||||
const end =
|
||||
endDate ??
|
||||
new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)
|
||||
.toISOString()
|
||||
.slice(0, 19)
|
||||
.replace("T", " ");
|
||||
|
||||
// Coerce item IDs to numbers and filter invalids
|
||||
const itemIds = items
|
||||
.map((v) => Number(v))
|
||||
.filter((n) => Number.isFinite(n));
|
||||
|
||||
if (itemIds.length === 0) {
|
||||
return res.status(400).json({ message: "No valid item IDs provided" });
|
||||
}
|
||||
|
||||
const result = await createLoanInDatabase(
|
||||
req.user.username,
|
||||
start,
|
||||
end,
|
||||
itemIds
|
||||
);
|
||||
|
||||
if (result.success) {
|
||||
return res.status(201).json({
|
||||
message: "Loan created successfully",
|
||||
loanId: result.data.id,
|
||||
loanCode: result.data.loan_code,
|
||||
});
|
||||
}
|
||||
|
||||
if (result.code === "CONFLICT") {
|
||||
return res
|
||||
.status(409)
|
||||
.json({ message: "Items not available in the selected period" });
|
||||
}
|
||||
|
||||
if (result.code === "BAD_REQUEST") {
|
||||
return res.status(400).json({ message: result.message });
|
||||
}
|
||||
|
||||
return res.status(500).json({ message: "Failed to create loan" });
|
||||
} catch (err) {
|
||||
console.error("createLoan error:", err);
|
||||
return res.status(500).json({ message: "Failed to create loan" });
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
Reference in New Issue
Block a user