diff --git a/web_app/src/Librarian/LibrarianAddBook.tsx b/web_app/src/Librarian/LibrarianAddBook.tsx
index 4da762ee..490f718b 100644
--- a/web_app/src/Librarian/LibrarianAddBook.tsx
+++ b/web_app/src/Librarian/LibrarianAddBook.tsx
@@ -1,5 +1,8 @@
import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
+import {useWebSocketNewOrderNotification} from './useWebSocketNewOrderNotification.tsx';
+import {toast} from 'react-toastify';
+import 'react-toastify/dist/ReactToastify.css';
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;
@@ -83,6 +86,13 @@ const LibrarianAddBook: React.FC = () => {
fetchDropdownData();
}, []);
+ useWebSocketNewOrderNotification('librarian/orders/pending', () => {
+ toast.info("Otrzymano nowe zamówienie!", {
+ position: "bottom-right",
+ });
+ console.log("New order received!");
+ });
+
const handleAuthorSelect = async (author: string) => {
if (!authors.includes(author)) {
setAuthors([...authors, author]);
diff --git a/web_app/src/Librarian/LibrarianHomePage.tsx b/web_app/src/Librarian/LibrarianHomePage.tsx
index 4785dd63..f352a040 100644
--- a/web_app/src/Librarian/LibrarianHomePage.tsx
+++ b/web_app/src/Librarian/LibrarianHomePage.tsx
@@ -1,5 +1,8 @@
-import React, {useEffect, useState} from 'react';
+import React, {useEffect, useState, useRef} from 'react';
import {Link, useNavigate} from 'react-router-dom';
+import {useWebSocketNewOrderNotification} from './useWebSocketNewOrderNotification.tsx';
+import {toast} from 'react-toastify';
+import 'react-toastify/dist/ReactToastify.css';
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;
@@ -72,6 +75,7 @@ const LibrarianHomePage: React.FC = () => {
const [page, setPage] = useState(0);
const [hasMore, setHasMore] = useState(true);
const [isLoading, setIsLoading] = useState(false);
+ const isFetchingRef = useRef(false);
useEffect(() => {
fetchAssignedLibrary();
@@ -131,6 +135,13 @@ const LibrarianHomePage: React.FC = () => {
return () => window.removeEventListener('scroll', handleScroll);
}, [isLoading, hasMore, page, isUserLibraryChecked]);
+ useWebSocketNewOrderNotification('librarian/orders/pending', () => {
+ toast.info("Otrzymano nowe zamówienie!", {
+ position: "bottom-right",
+ });
+ console.log("New order received!");
+ });
+
const fetchDropdownData = async () => {
const token = localStorage.getItem('access_token');
@@ -221,8 +232,9 @@ const LibrarianHomePage: React.FC = () => {
const fetchBooks = async (filterByLibrary: boolean, pageToFetch: number = 0) => {
const token = localStorage.getItem('access_token');
- if (!token || isLoading || !hasMore) return;
+ if (!token || isFetchingRef.current || isLoading || !hasMore) return;
+ isFetchingRef.current = true;
setIsLoading(true);
const queryParams = new URLSearchParams();
@@ -241,7 +253,7 @@ const LibrarianHomePage: React.FC = () => {
if (releaseYearTo) queryParams.append("releaseYearTo", releaseYearTo.toString());
queryParams.append("page", pageToFetch.toString());
- queryParams.append("size", "3");
+ queryParams.append("size", "2");
try {
const response = await fetch(`${API_BASE_URL}/api/books/search?${queryParams.toString()}`, {
@@ -265,6 +277,7 @@ const LibrarianHomePage: React.FC = () => {
console.error("Error: ", error);
} finally {
setIsLoading(false);
+ isFetchingRef.current = false;
}
};
diff --git a/web_app/src/Librarian/LibrarianLogin.tsx b/web_app/src/Librarian/LibrarianLogin.tsx
index 381c2d26..245adf7c 100644
--- a/web_app/src/Librarian/LibrarianLogin.tsx
+++ b/web_app/src/Librarian/LibrarianLogin.tsx
@@ -142,7 +142,7 @@ const LibrarianLogin: React.FC = () => {
+ className="absolute top-[22%] left-1/2 transform -translate-x-1/2 bg-white p-10 rounded-xl shadow-2xl w-[clamp(280px,400px,400px)] h-[clamp(550px,55px,90px)]">
Logowanie bibliotekarza
diff --git a/web_app/src/Librarian/LibrarianOrders.tsx b/web_app/src/Librarian/LibrarianOrders.tsx
index 9c2a398a..c5afcee7 100644
--- a/web_app/src/Librarian/LibrarianOrders.tsx
+++ b/web_app/src/Librarian/LibrarianOrders.tsx
@@ -1,5 +1,8 @@
import React, {useState, useEffect } from 'react';
import {Link, useNavigate} from 'react-router-dom';
+import {useWebSocketNewOrderNotification} from './useWebSocketNewOrderNotification.tsx';
+import {toast} from 'react-toastify';
+import 'react-toastify/dist/ReactToastify.css';
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;
@@ -26,7 +29,6 @@ const LibrarianOrders: React.FC = () => {
const [realizationMessage, setRealizationMessage] = React.useState('');
const [realizationMessageType, setRealizationMessageType] = React.useState<'success' | 'error' | ''>('');
-
// Orders
const [orderDetails, setOrderDetails] = useState
([]);
const [showRejectionInput, setShowRejectionInput] = useState(false);
@@ -67,6 +69,13 @@ const LibrarianOrders: React.FC = () => {
const navigate = useNavigate();
+ useWebSocketNewOrderNotification('librarian/orders/pending', () => {
+ toast.info("Otrzymano nowe zamówienie!", {
+ position: "bottom-right",
+ });
+ console.log("New order received!");
+ });
+
// Orders ----------------------------------------------------------------------------------------------------------
useEffect(() => {
fetchOrderDetails();
@@ -234,7 +243,7 @@ const LibrarianOrders: React.FC = () => {
};
return (
-
+
diff --git a/web_app/src/Librarian/LibrarianReaders.tsx b/web_app/src/Librarian/LibrarianReaders.tsx
index d19570d5..806db30c 100644
--- a/web_app/src/Librarian/LibrarianReaders.tsx
+++ b/web_app/src/Librarian/LibrarianReaders.tsx
@@ -1,5 +1,8 @@
import React, {useState} from 'react';
import {Link, useNavigate} from 'react-router-dom';
+import {useWebSocketNewOrderNotification} from './useWebSocketNewOrderNotification.tsx';
+import {toast} from 'react-toastify';
+import 'react-toastify/dist/ReactToastify.css';
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;
@@ -25,6 +28,13 @@ const LibrarianReaders: React.FC = () => {
const navigate = useNavigate();
+ useWebSocketNewOrderNotification('librarian/orders/pending', () => {
+ toast.info("Otrzymano nowe zamówienie!", {
+ position: "bottom-right",
+ });
+ console.log("New order received!");
+ });
+
// Readers ---------------------------------------------------------------------------------------------------------
const handleCreateLibraryCard = async () => {
const token = localStorage.getItem('access_token');
diff --git a/web_app/src/Librarian/LibrarianSettings.tsx b/web_app/src/Librarian/LibrarianSettings.tsx
index bc6bcd53..ab5131c1 100644
--- a/web_app/src/Librarian/LibrarianSettings.tsx
+++ b/web_app/src/Librarian/LibrarianSettings.tsx
@@ -1,9 +1,70 @@
-import React from 'react';
+import React, { useState } from 'react';
import {Link, useNavigate} from 'react-router-dom';
+import {useWebSocketNewOrderNotification} from './useWebSocketNewOrderNotification.tsx';
+import {toast} from 'react-toastify';
+import 'react-toastify/dist/ReactToastify.css';
-// const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;
+const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;
const LibrarianSettings: React.FC = () => {
+ const [oldPassword, setOldPassword] = useState('');
+ const [newPassword, setNewPassword] = useState('');
+ const [repeatPassword, setRepeatPassword] = useState('');
+ const [message, setMessage] = useState('');
+ const [error, setError] = useState('');
+
+ useWebSocketNewOrderNotification('librarian/orders/pending', () => {
+ toast.info("Otrzymano nowe zamówienie!", {
+ position: "bottom-right",
+ });
+ console.log("New order received!");
+ });
+
+ const handleChangePassword = async (e: React.FormEvent) => {
+ e.preventDefault();
+ setMessage('');
+ setError('');
+
+ if (newPassword !== repeatPassword) {
+ setError('Hasła nie pasują do siebie.');
+ return;
+ }
+
+ try {
+ const token = localStorage.getItem('access_token');
+ if (!token) throw new Error('Brak tokenu autoryzacyjnego.');
+
+ const response = await fetch(`${API_BASE_URL}/api/users/change-password`, {
+ method: 'PUT',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': `Bearer ${token}`,
+ },
+ body: JSON.stringify({
+ oldPassword,
+ newPassword,
+ }),
+ });
+
+ const data = await response.json();
+
+ if (!response.ok) {
+ throw new Error(data.message || 'Nie udało się zmienić hasła.');
+ }
+
+ setMessage('Hasło zostało zmienione.');
+ setOldPassword('');
+ setNewPassword('');
+ setRepeatPassword('');
+ } catch (err: unknown) {
+ if (err instanceof Error) {
+ setError(err.message);
+ } else {
+ setError('Wystąpił nieznany błąd.');
+ }
+ }
+ };
+
const navigate = useNavigate();
const handleLogout = () => {
@@ -50,10 +111,59 @@ const LibrarianSettings: React.FC = () => {
-
-
Ustawienia będą tutaj
-
+
);