Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions web_app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import SysAdminLogin from "./SystemAdmin/SystemAdminLogin.tsx";
import SystemAdminDashboard from './SystemAdmin/SystemAdminHomePage';
import SubmissionDetailsLibrary from './SystemAdmin/SubmissionDetailsLibrary.tsx';
import SubmissionDetailsDriver from './SystemAdmin/SubmissionDetailsDriver.tsx';
import SystemAdminSettings from './SystemAdmin/SystemAdminSettings.tsx';

// Library Administrator
import RegistrationForm from './LibraryAdmin/LibraryAdminRegisterForm.tsx';
Expand Down Expand Up @@ -66,6 +67,7 @@ const App: React.FC = () => {
<Route path="/librarian-settings" element={<LibrarianSettings />} />
<Route path="/library-admin-add-librarian" element={<LibraryAdminAddLibrarian />} />
<Route path="/library-admin-settings" element={<LibraryAdminSettings />} />
<Route path="/system-admin-settings" element={<SystemAdminSettings />} />
<Route
path="/api-docs"
element={
Expand Down
4 changes: 2 additions & 2 deletions web_app/src/Librarian/LibrarianAddBook.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import {useWebSocketNewOrderNotification} from './useWebSocketNewOrderNotification.tsx';
import {useWebSocketNotification} from '../Utils/useWebSocketNotification.tsx';
import {toast} from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';

Expand Down Expand Up @@ -86,7 +86,7 @@ const LibrarianAddBook: React.FC = () => {
fetchDropdownData();
}, []);

useWebSocketNewOrderNotification('librarian/orders/pending', () => {
useWebSocketNotification('librarian/orders/pending', () => {
toast.info("Otrzymano nowe zamówienie!", {
position: "bottom-right",
});
Expand Down
4 changes: 2 additions & 2 deletions web_app/src/Librarian/LibrarianHomePage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, {useEffect, useState, useRef} from 'react';
import {Link, useNavigate} from 'react-router-dom';
import {useWebSocketNewOrderNotification} from './useWebSocketNewOrderNotification.tsx';
import {useWebSocketNotification} from '../Utils/useWebSocketNotification.tsx';
import {toast} from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';

Expand Down Expand Up @@ -135,7 +135,7 @@ const LibrarianHomePage: React.FC = () => {
return () => window.removeEventListener('scroll', handleScroll);
}, [isLoading, hasMore, page, isUserLibraryChecked]);

useWebSocketNewOrderNotification('librarian/orders/pending', () => {
useWebSocketNotification('librarian/orders/pending', () => {
toast.info("Otrzymano nowe zamówienie!", {
position: "bottom-right",
});
Expand Down
4 changes: 2 additions & 2 deletions web_app/src/Librarian/LibrarianOrders.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, {useState, useEffect } from 'react';
import {Link, useNavigate} from 'react-router-dom';
import {useWebSocketNewOrderNotification} from './useWebSocketNewOrderNotification.tsx';
import {useWebSocketNotification} from '../Utils/useWebSocketNotification.tsx';
import {toast} from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';

Expand Down Expand Up @@ -69,7 +69,7 @@ const LibrarianOrders: React.FC = () => {

const navigate = useNavigate();

useWebSocketNewOrderNotification('librarian/orders/pending', () => {
useWebSocketNotification('librarian/orders/pending', () => {
toast.info("Otrzymano nowe zamówienie!", {
position: "bottom-right",
});
Expand Down
4 changes: 2 additions & 2 deletions web_app/src/Librarian/LibrarianReaders.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, {useState} from 'react';
import {Link, useNavigate} from 'react-router-dom';
import {useWebSocketNewOrderNotification} from './useWebSocketNewOrderNotification.tsx';
import {useWebSocketNotification} from '../Utils/useWebSocketNotification.tsx';
import {toast} from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';

Expand Down Expand Up @@ -28,7 +28,7 @@ const LibrarianReaders: React.FC = () => {

const navigate = useNavigate();

useWebSocketNewOrderNotification('librarian/orders/pending', () => {
useWebSocketNotification('librarian/orders/pending', () => {
toast.info("Otrzymano nowe zamówienie!", {
position: "bottom-right",
});
Expand Down
4 changes: 2 additions & 2 deletions web_app/src/Librarian/LibrarianReturns.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, {useEffect, useState} from 'react';
import {Link, useNavigate} from 'react-router-dom';
import {useWebSocketNewOrderNotification} from './useWebSocketNewOrderNotification.tsx';
import {useWebSocketNotification} from '../Utils/useWebSocketNotification.tsx';
import {toast} from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';

Expand All @@ -10,7 +10,7 @@ const LibrarianReturns: React.FC = () => {
const [message, setMessage] = useState<string | null>(null);
const [messageType, setMessageType] = useState<'success' | 'error' | null>(null);

useWebSocketNewOrderNotification('librarian/orders/pending', () => {
useWebSocketNotification('librarian/orders/pending', () => {
toast.info("Otrzymano nowe zamówienie!", {
position: "bottom-right",
});
Expand Down
13 changes: 7 additions & 6 deletions web_app/src/Librarian/LibrarianSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import {Link, useNavigate} from 'react-router-dom';
import {useWebSocketNewOrderNotification} from './useWebSocketNewOrderNotification.tsx';
import {useWebSocketNotification} from '../Utils/useWebSocketNotification.tsx';
import {toast} from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';

Expand All @@ -13,7 +13,7 @@ const LibrarianSettings: React.FC = () => {
const [message, setMessage] = useState('');
const [error, setError] = useState('');

useWebSocketNewOrderNotification('librarian/orders/pending', () => {
useWebSocketNotification('librarian/orders/pending', () => {
toast.info("Otrzymano nowe zamówienie!", {
position: "bottom-right",
});
Expand Down Expand Up @@ -46,10 +46,11 @@ const LibrarianSettings: React.FC = () => {
}),
});

const data = await response.json();
const text = await response.text();

if (!response.ok) {
throw new Error(data.message || 'Nie udało się zmienić hasła.');
const errorData = text ? JSON.parse(text) : { message: 'Błąd zmiany hasła' };
throw new Error(errorData.message);
}

setMessage('Hasło zostało zmienione.');
Expand Down Expand Up @@ -160,8 +161,8 @@ const LibrarianSettings: React.FC = () => {
</button>
</div>

{message && <p className="text-green-400 mt-4">{message}</p>}
{error && <p className="text-red-400 mt-4">{error}</p>}
{message && <p className="text-green-500 mt-4">{message}</p>}
{error && <p className="text-red-500 mt-4">{error}</p>}
</form>
</div>
</main>
Expand Down
10 changes: 0 additions & 10 deletions web_app/src/LibraryAdmin/LibraryAdminAddLibrary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,6 @@ const LibraryAdminAddLibrary: React.FC = () => {
}
};

const handleSettings = () => {
alert('Ustawienia');
};

return (
<div className="bg-[#3B576C] min-h-screen">
<header
Expand All @@ -85,12 +81,6 @@ const LibraryAdminAddLibrary: React.FC = () => {
src="/book-rider-high-resolution-logo.png"
/>
</div>
<button
onClick={handleSettings}
className="relative mr-3 px-6 py-3 right-[1%] w-[8%] bg-[#314757] rounded-md text-sm transition-all duration-300 hover:bg-[#4b6477] flex items-center justify-center"
>
Ustawienia
</button>
<button
onClick={handleLogout}
className="relative py-3 right-[1%] w-[13%] bg-[#314757] rounded-md text-sm transition-all duration-300 hover:bg-[#4b6477]"
Expand Down
122 changes: 117 additions & 5 deletions web_app/src/LibraryAdmin/LibraryAdminSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,71 @@
import React from 'react';
import React, {useState} from 'react';
import {Link, useNavigate} from 'react-router-dom';
import {useWebSocketNotification} from "../Utils/useWebSocketNotification.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 LibraryAdminSettings: React.FC = () => {
const [oldPassword, setOldPassword] = useState('');
const [newPassword, setNewPassword] = useState('');
const [repeatPassword, setRepeatPassword] = useState('');
const [message, setMessage] = useState('');
const [error, setError] = useState('');

useWebSocketNotification('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 text = await response.text();

if (!response.ok) {
const errorData = text ? JSON.parse(text) : { message: 'Błąd zmiany hasła' };
throw new Error(errorData.message);
}

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 = () => {
Expand Down Expand Up @@ -47,9 +109,59 @@ const LibraryAdminSettings: React.FC = () => {
</button>
</header>
<main className="flex justify-center items-center p-9 w-full max-w-[800vw]">
<section className="h-[80%] max-h-[90%] p-9 rounded-2xl mb-[400px] w-[65%] bg-white text-gray-600">
<h2 className="text-center p-4 mb-4 text-3xl font-semibold">Ustawienia</h2>
</section>
<div className="bg-white p-9 rounded-2xl shadow-md h-[80%] max-h-[90%] w-[65%]">
<form
onSubmit={handleChangePassword}
className="w-full"
>
<h2 className="text-3xl p-4 font-semibold mb-10 text-gray-600 text-center">Zmień hasło</h2>

<div className="mb-4">
<label className="block mb-1 text-gray-600 text-xl">Stare hasło:</label>
<input
type="password"
value={oldPassword}
onChange={(e) => setOldPassword(e.target.value)}
className="text-lg w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-[#3B576C]"
required
/>
</div>

<div className="block mb-5 text-gray-600 text-lg">
<label className="block mb-1">Nowe hasło:</label>
<input
type="password"
value={newPassword}
onChange={(e) => setNewPassword(e.target.value)}
className="text-lg text-black w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-[#3B576C]"
required
/>
</div>

<div className="block mb-5 text-gray-600 text-lg"> {/* ✅ NEW FIELD */}
<label className="block mb-1">Powtórz hasło:</label>
<input
type="password"
value={repeatPassword}
onChange={(e) => setRepeatPassword(e.target.value)}
className="text-lg text-black w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-[#3B576C]"
required
/>
</div>

<div className="flex justify-center mt-4">
<button
type="submit"
className="mb-5 mt-5 w-[15vw] py-2 px-4 bg-[#3B576C] text-white rounded-md hover:bg-[#314757] ease-out duration-300"
>
Zmień hasło
</button>
</div>

{message && <p className="text-green-500 mt-4">{message}</p>}
{error && <p className="text-red-500 mt-4">{error}</p>}
</form>
</div>
</main>
</div>
);
Expand Down
33 changes: 22 additions & 11 deletions web_app/src/SystemAdmin/SystemAdminHomePage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import React, {useEffect, useRef, useState} from 'react';
import {useNavigate} from 'react-router-dom';
import {useWebSocketNotification} from '../Utils/useWebSocketNotification.tsx';
import {toast} from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';

const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;

Expand Down Expand Up @@ -30,7 +33,6 @@ const formatDate = (isoString: string) => {
};

const SystemAdminDashboard: React.FC = () => {
const [email, setEmail] = useState<string | null>(null);
const [activeSection, setActiveSection] = useState<string>('librarySubmissions');
const [driverApplications, setDriverApplications] = useState<DriverApplication[]>([]);
const [libraryRequests, setLibraryRequests] = useState<LibraryRequest[]>([]);
Expand All @@ -42,8 +44,22 @@ const SystemAdminDashboard: React.FC = () => {

const firstLoad = useRef(true);

const getEmail = () => {
return localStorage.getItem('email');
useWebSocketNotification('system-administrator/library-requests/pending', () => {
toast.info("Otrzymano nowe zgłoszenie biblioteki!", {
position: "bottom-right",
});
console.log("New library request received!");
});

useWebSocketNotification('system-administrator/driver-requests/pending', () => {
toast.info("Otrzymano nowe zgłoszenie kierowcy!", {
position: "bottom-right",
});
console.log("New driver request received!");
});

const handleChangePassword = ()=> {
navigate('/system-admin-settings');
}

const handleLogout = () => {
Expand All @@ -60,11 +76,6 @@ const SystemAdminDashboard: React.FC = () => {
return;
}

const userEmail = getEmail();
if (userEmail) {
setEmail(userEmail);
}

if (activeSection === 'driverSubmissions') {
setDriverApplications([]);
setDriverPage(0);
Expand Down Expand Up @@ -178,9 +189,9 @@ const SystemAdminDashboard: React.FC = () => {
<div className="text-white p-4 flex justify-end">

<div className="flex items-center">
{email && (
<span className="mr-4">{email}</span>
)}
<button onClick={handleChangePassword} className="bg-gray-700 text-white px-6 py-2 rounded-md ml-4 whitespace-nowrap">
Ustawienia
</button>
<button onClick={handleLogout} className="bg-gray-700 text-white px-6 py-2 rounded-md ml-4 whitespace-nowrap">
Wyloguj się
</button>
Expand Down
2 changes: 1 addition & 1 deletion web_app/src/SystemAdmin/SystemAdminLogin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ const SysAdminLogin: React.FC = () => {
</Link>
</div>
<div
className="absolute top-[25%] left-1/2 transform -translate-x-1/2 bg-white p-10 rounded-xl shadow-2xl w-[clamp(280px,30vw,400px)] h-[clamp(430px,48vh,90vh)]">
className="absolute top-[25%] left-1/2 transform -translate-x-1/2 bg-white p-10 rounded-xl shadow-2xl w-[clamp(280px,30vw,400px)] h-[clamp(500px,55vh,90vh)]">
<h2 className="text-center text-3xl font-semibold text-[#2c3e50] mb-6 w-[100%]">
Logowanie <br/> administratora systemów
</h2>
Expand Down
Loading