diff --git a/backend/routes/api.js b/backend/routes/api.js index 87f1613..4b23e96 100644 --- a/backend/routes/api.js +++ b/backend/routes/api.js @@ -11,7 +11,6 @@ import { import { authenticate, generateToken } from "../services/tokenService.js"; const router = express.Router(); -// Example endpoint router.post("/login", async (req, res) => { const result = await loginFunc(req.body.username, req.body.password); if (result.success) { diff --git a/backend/routes/apiV2.js b/backend/routes/apiV2.js index f251c49..faecec2 100644 --- a/backend/routes/apiV2.js +++ b/backend/routes/apiV2.js @@ -5,6 +5,7 @@ import { changeInSafeStateV2, setReturnDateV2, setTakeDateV2, + getLoanByCodeV2, } from "../services/database.js"; dotenv.config(); @@ -44,6 +45,19 @@ router.post("/controlInSafe/:key/:itemId/:state", async (req, res) => { } }); +router.get("/getLoanByCode/:key/:loan_code", async (req, res) => { + if (req.params.key === process.env.ADMIN_ID) { + const loan_code = req.params.loan_code; + + const result = await getLoanByCodeV2(loan_code); + if (result.success) { + res.status(200).json({ data: result.data }); + } else { + res.status(404).json({ message: "Loan not found" }); + } + } +}); + // 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) { diff --git a/backend/services/database.js b/backend/services/database.js index dec6e0a..b8d3277 100644 --- a/backend/services/database.js +++ b/backend/services/database.js @@ -29,6 +29,17 @@ export const getItemsFromDatabaseV2 = async () => { return { success: false }; }; +export const getLoanByCodeV2 = async (loan_code) => { + const [result] = await pool.query( + "SELECT * FROM loans WHERE loan_code = ?;", + [loan_code] + ); + if (result.length > 0) { + return { success: true, data: result[0] }; + } + return { success: false }; +}; + export const changeInSafeStateV2 = async (itemId, state) => { const [result] = await pool.query( "UPDATE items SET inSafe = ? WHERE id = ?", diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index ae29d81..a4c847d 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -6,7 +6,11 @@ import Form2 from "./components/Form2"; import Form4 from "./components/Form4"; import LoginForm from "./components/LoginForm"; import Cookies from "js-cookie"; -import { fetchAllData, ALL_ITEMS_UPDATED_EVENT } from "./utils/fetchData"; +import { + fetchAllData, + ALL_ITEMS_UPDATED_EVENT, + AUTH_LOGOUT_EVENT, +} from "./utils/fetchData"; import { myToast } from "./utils/toastify"; function App() { @@ -18,10 +22,17 @@ function App() { setIsLoggedIn(true); fetchAllData(token); } - localStorage.setItem("borrowableItems", JSON.stringify([])); }, []); + useEffect(() => { + const onAuthLogout = () => { + setIsLoggedIn(false); + }; + window.addEventListener(AUTH_LOGOUT_EVENT, onAuthLogout); + return () => window.removeEventListener(AUTH_LOGOUT_EVENT, onAuthLogout); + }, []); + const handleLogout = () => { Cookies.remove("token"); localStorage.removeItem("allItems"); diff --git a/frontend/src/utils/fetchData.ts b/frontend/src/utils/fetchData.ts index 9f9a375..c8a92ad 100644 --- a/frontend/src/utils/fetchData.ts +++ b/frontend/src/utils/fetchData.ts @@ -4,6 +4,22 @@ import { myToast } from "./toastify"; // Event name used to notify the app when the list of items has been updated export const ALL_ITEMS_UPDATED_EVENT = "allItemsUpdated"; export const BORROWABLE_ITEMS_UPDATED_EVENT = "borrowableItemsUpdated"; +export const AUTH_LOGOUT_EVENT = "authLogout"; + +let sendError = false; + +function logout() { + Cookies.remove("token"); + Cookies.remove("startDate"); + Cookies.remove("endDate"); + localStorage.removeItem("allItems"); + localStorage.removeItem("allLoans"); + localStorage.removeItem("userLoans"); + localStorage.removeItem("borrowableItems"); + window.dispatchEvent(new Event(ALL_ITEMS_UPDATED_EVENT)); + window.dispatchEvent(new Event(BORROWABLE_ITEMS_UPDATED_EVENT)); + window.dispatchEvent(new Event(AUTH_LOGOUT_EVENT)); +} export const fetchAllData = async (token: string | undefined) => { if (!token) return; @@ -16,6 +32,16 @@ export const fetchAllData = async (token: string | undefined) => { }, }); + if (response.status === 500) { + if (!sendError) { + sendError = true; + myToast("Session expired. Please log in again.", "error"); + logout(); + return; + } + return; + } + if (!response.ok) { myToast("Failed to fetch items", "error"); return; @@ -38,6 +64,16 @@ export const fetchAllData = async (token: string | undefined) => { }, }); + if (response.status === 500) { + if (!sendError) { + sendError = true; + myToast("Session expired. Please log in again.", "error"); + logout(); + return; + } + return; + } + if (!response.ok) { myToast("Failed to fetch loans!", "error"); return; @@ -60,6 +96,16 @@ export const fetchAllData = async (token: string | undefined) => { }, }); + if (response.status === 500) { + if (!sendError) { + sendError = true; + myToast("Session expired. Please log in again.", "error"); + logout(); + return; + } + return; + } + if (!response.ok) { myToast("Failed to fetch user loans!", "error"); return; @@ -122,6 +168,16 @@ export const getBorrowableItems = async () => { body: JSON.stringify({ startDate, endDate }), }); + if (response.status === 500) { + if (!sendError) { + sendError = true; + myToast("Session expired. Please log in again.", "error"); + logout(); + return; + } + return; + } + if (!response.ok) { myToast("Failed to fetch borrowable items", "error"); return;