From a383f2594f390c3861e3a7b665765badd581ff77 Mon Sep 17 00:00:00 2001 From: Wiktor Szynaka Date: Mon, 28 Oct 2024 23:23:38 +0100 Subject: [PATCH] dodanie logowania --- firm/package-lock.json | 9 + firm/package.json | 1 + firm/src/App.js | 60 +- firm/src/components/Harmonogram.js | 11 + firm/src/components/Login.js | 58 ++ firm/src/components/NavBar.js | 19 +- firm/src/components/Raporty.js | 62 ++- firm/src/components/Sidebar.js | 33 +- firm/src/components/Transakcje.js | 22 +- firm/src/components/Wydatki.js | 87 +-- firm/src/components/ZarzadzanieProduktami.js | 12 +- firm/yarn.lock | 547 +++++++++++++------ 12 files changed, 665 insertions(+), 256 deletions(-) create mode 100644 firm/src/components/Harmonogram.js create mode 100644 firm/src/components/Login.js diff --git a/firm/package-lock.json b/firm/package-lock.json index a895bde..bfcc534 100644 --- a/firm/package-lock.json +++ b/firm/package-lock.json @@ -12,6 +12,7 @@ "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "axios": "^1.7.2", + "jwt-decode": "^4.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.23.1", @@ -12539,6 +12540,14 @@ "node": ">=4.0" } }, + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "engines": { + "node": ">=18" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", diff --git a/firm/package.json b/firm/package.json index 46e47d8..b4f4300 100644 --- a/firm/package.json +++ b/firm/package.json @@ -7,6 +7,7 @@ "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "axios": "^1.7.2", + "jwt-decode": "^4.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.23.1", diff --git a/firm/src/App.js b/firm/src/App.js index df19424..0cbd699 100644 --- a/firm/src/App.js +++ b/firm/src/App.js @@ -1,36 +1,70 @@ import 'tailwindcss/tailwind.css'; -import React from 'react'; -import { BrowserRouter as Router, Route, Routes } from 'react-router-dom'; +import React, { useState, useEffect } from 'react'; +import { BrowserRouter as Router, Route, Routes, Navigate } from 'react-router-dom'; import PanelAdministratora from './components/PanelAdministratora'; import ZarzadzanieProduktami from './components/ZarzadzanieProduktami'; import Transakcje from './components/Transakcje'; -import NavBar from './components/NavBar' +import NavBar from './components/NavBar'; import Sidebar from './components/Sidebar'; import Wydatki from './components/Wydatki'; import Raporty from './components/Raporty'; +import Login from './components/Login'; +import Harmonogram from './components/Harmonogram'; +import { jwtDecode } from 'jwt-decode'; const App = () => { + const [token, setToken] = useState(localStorage.getItem('token')); + const [userRole, setUserRole] = useState(null); + + useEffect(() => { + if (token) { + try { + const decodedToken = jwtDecode(token); + console.log(decodedToken); + setUserRole(decodedToken['http://schemas.microsoft.com/ws/2008/06/identity/claims/role']); + } catch (error) { + console.error('Failed to decode token:', error); + setUserRole(null); + } + } else { + setUserRole(null); + } + }, [token]); + return (
- -
+ {token && } +
+ {token && (
- +
+ )}
- } /> - } /> - } /> - } /> - } /> + {/* Przekierowanie na stronę logowania, jeśli token jest pusty */} + : } /> + + {/* Strona logowania */} + : } /> + + {/* Chronione ścieżki */} + : } /> + : } /> + : } /> + : } /> + : } /> + : } /> + + {/* Przekierowanie dla nieznanych ścieżek */} + } />
- + ); -} +}; export default App; diff --git a/firm/src/components/Harmonogram.js b/firm/src/components/Harmonogram.js new file mode 100644 index 0000000..42f2b82 --- /dev/null +++ b/firm/src/components/Harmonogram.js @@ -0,0 +1,11 @@ +import React from 'react'; + +const Harmonogram = () => { + return ( +
+

Harmonogram

+
+ ); +}; + +export default Harmonogram; diff --git a/firm/src/components/Login.js b/firm/src/components/Login.js new file mode 100644 index 0000000..2c0f4ba --- /dev/null +++ b/firm/src/components/Login.js @@ -0,0 +1,58 @@ +import React, { useState } from 'react'; +import axios from 'axios'; +import { useNavigate } from 'react-router-dom'; + +const Login = ({ setToken }) => { + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [error, setError] = useState(''); + const navigate = useNavigate(); + + const handleLogin = async (e) => { + e.preventDefault(); + try { + const response = await axios.post('https://localhost:7039/api/user/login', { email, password }); + + const token = response.data; + setToken(token); + localStorage.setItem('token', token); + navigate('/'); + } catch (error) { + setError('Nieprawidłowy email lub hasło'); + } + }; + + return ( +
+
+

Logowanie

+ {error &&

{error}

} +
+ + setEmail(e.target.value)} + className="border rounded w-full p-2" + required + /> +
+
+ + setPassword(e.target.value)} + className="border rounded w-full p-2" + required + /> +
+ +
+
+ ); +}; + +export default Login; diff --git a/firm/src/components/NavBar.js b/firm/src/components/NavBar.js index c00bcb4..4db8630 100644 --- a/firm/src/components/NavBar.js +++ b/firm/src/components/NavBar.js @@ -1,12 +1,20 @@ import React from 'react'; -import { Link } from 'react-router-dom'; +import { Link, useNavigate } from 'react-router-dom'; import lupaIcon from "../icons/lupa.jpg"; import domIcon from "../icons/dom.png"; import profilIcon from "../icons/profil.png"; import settingsIcon from "../icons/settings.png"; import znakIcon from "../icons/znak.png"; -const Navbar = () => { +const Navbar = ({ setToken }) => { + const navigate = useNavigate(); + + const handleLogout = () => { + setToken(null); + localStorage.removeItem('token'); + navigate('/login'); + }; + return (
@@ -22,7 +30,12 @@ const Navbar = () => { - + Profil
); diff --git a/firm/src/components/Raporty.js b/firm/src/components/Raporty.js index 62a646e..d1e5f94 100644 --- a/firm/src/components/Raporty.js +++ b/firm/src/components/Raporty.js @@ -11,17 +11,27 @@ const Raporty = () => { const [deleteReportId, setDeleteReportId] = useState(null); const fetchReports = async () => { + const token = localStorage.getItem('token'); + if (!token) { + console.error('Brak tokena. Użytkownik musi być zalogowany.'); + return; + } try { - const response = await axios.get('https://localhost:7039/api/Report'); + const response = await axios.get('https://localhost:7039/api/Report', { + headers: { + Authorization: `Bearer ${token}` + } + }); setReports(response.data); } catch (error) { console.error('Błąd podczas pobierania raportów:', error); } }; + const openDeleteConfirmation = (transactionId) => { setDeleteReportId(transactionId); }; - + const closeDeleteConfirmation = () => { setDeleteReportId(null); }; @@ -35,29 +45,48 @@ const Raporty = () => { setError('Proszę uzupełnić wszystkie pola.'); return; } + const token = localStorage.getItem('token'); try { console.log('Wysyłane dane:', fromDate, toDate); const response = await axios.post('https://localhost:7039/api/Report', { fromDate, toDate + }, { + headers: { + Authorization: `Bearer ${token}` + } }); const newReport = response.data; setReports([...reports, newReport]); } catch (error) { console.error('Błąd podczas generowania raportu:', error); + if (error.response && error.response.data) { + setError(error.response.data); + } else { + setError('Wystąpił nieoczekiwany błąd. Spróbuj ponownie później.'); + } } }; const handleDeleteReport = async (reportId) => { + const token = localStorage.getItem('token'); try { - await axios.delete(`https://localhost:7039/api/Report/${reportId}`); + await axios.delete(`https://localhost:7039/api/Report/${reportId}`, { + headers: { + Authorization: `Bearer ${token}` + } + }); fetchReports(); setDeleteReportId(null); } catch (error) { console.error('Błąd podczas usuwania raportu:', error); + if (error.response && error.response.data) { + setError(error.response.data); + } else { + setError('Wystąpił nieoczekiwany błąd. Spróbuj ponownie później.'); + } } }; - const formatDate = (dateString) => { const options = { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }; @@ -77,7 +106,7 @@ const Raporty = () => { setFromDate(e.target.value)} className="mr-5" /> setToDate(e.target.value)} className="mr-5" /> - +

Raporty

@@ -113,21 +142,22 @@ const Raporty = () => {
{error && (
-
-

Błąd

-

{error}

- -
+
+

Błąd

+

{error}

+ +
)} {deleteReportId && ( handleDeleteReport(deleteReportId)} - />)} + message="Czy na pewno chcesz usunąć ten raport?" + onCancel={closeDeleteConfirmation} + onConfirm={() => handleDeleteReport(deleteReportId)} + /> + )} ); }; diff --git a/firm/src/components/Sidebar.js b/firm/src/components/Sidebar.js index 7927abb..0cc4534 100644 --- a/firm/src/components/Sidebar.js +++ b/firm/src/components/Sidebar.js @@ -7,15 +7,19 @@ import harmonogramIcon from "../icons/harmonogram.png"; import wydatkiIcon from "../icons/wydatki.png"; import raportyIcon from "../icons/raport.png"; -const Sidebar = () => { +const Sidebar = ({ userRole }) => { return (
    + {userRole !== 'User' && ( + <>
  • Obrazek 1 Panel Administratora
  • + + )}
  • Obrazek 1 @@ -31,19 +35,22 @@ const Sidebar = () => { Obrazek 1 Harmonogram
  • - -
  • - Obrazek 1 - Wydatki -
  • - -
  • - Obrazek 1 - Raporty -
  • + {userRole !== 'User' && ( + <> + +
  • + Obrazek 1 + Wydatki +
  • + +
  • + Obrazek 1 + Raporty +
  • + + )}
); - } -export default Sidebar; \ No newline at end of file +export default Sidebar; diff --git a/firm/src/components/Transakcje.js b/firm/src/components/Transakcje.js index 00784eb..88077a6 100644 --- a/firm/src/components/Transakcje.js +++ b/firm/src/components/Transakcje.js @@ -34,16 +34,34 @@ const Transakcje = () => { }); const fetchTransactions = async () => { + const token = localStorage.getItem('token'); + if (!token) { + console.error('Brak tokena. Użytkownik musi być zalogowany.'); + return; + } try { - const response = await axios.get('https://localhost:7039/api/Transaction'); + const response = await axios.get('https://localhost:7039/api/Transaction', { + headers: { + Authorization: `Bearer ${token}` + } + }); setTransactions(response.data); } catch (error) { console.error('Błąd podczas dodawania transakcji:', error); } }; const fetchProducts = async () => { + const token = localStorage.getItem('token'); + if (!token) { + console.error('Brak tokena. Użytkownik musi być zalogowany.'); + return; + } try { - const response = await axios.get('https://localhost:7039/api/Products'); + const response = await axios.get('https://localhost:7039/api/Products', { + headers: { + Authorization: `Bearer ${token}` + } + }); setProducts(response.data.map(product => ({ value: product.id, label: product.name }))); } catch (error) { console.error('Błąd podczas pobierania produktów:', error); diff --git a/firm/src/components/Wydatki.js b/firm/src/components/Wydatki.js index 62708b9..39140bf 100644 --- a/firm/src/components/Wydatki.js +++ b/firm/src/components/Wydatki.js @@ -16,8 +16,17 @@ const Wydatki = () => { }); const fetchExpenses = async () => { + const token = localStorage.getItem('token'); + if (!token) { + console.error('Brak tokena. Użytkownik musi być zalogowany.'); + return; + } try { - const response = await axios.get('https://localhost:7039/api/Expenses'); + const response = await axios.get('https://localhost:7039/api/Expenses', { + headers: { + Authorization: `Bearer ${token}` + } + }); setExpenses(response.data); } catch (error) { console.error('Błąd podczas pobierania wydatków:', error); @@ -33,8 +42,13 @@ const Wydatki = () => { setError('Proszę uzupełnić wszystkie pola.'); return; } + const token = localStorage.getItem('token'); try { - const response = await axios.post('https://localhost:7039/api/Expenses', newExpense); + const response = await axios.post('https://localhost:7039/api/Expenses', newExpense, { + headers: { + Authorization: `Bearer ${token}` + } + }); const addedExpense = response.data; setExpenses([...expenses, addedExpense]); setNewExpense({ @@ -45,12 +59,18 @@ const Wydatki = () => { setShowModal(false); } catch (error) { console.error('Błąd podczas dodawania wydatku:', error); + setError('Wystąpił błąd podczas dodawania wydatku.'); } }; const handleDeleteExpense = async (expenseId) => { + const token = localStorage.getItem('token'); try { - await axios.delete(`https://localhost:7039/api/Expenses/${expenseId}`); + await axios.delete(`https://localhost:7039/api/Expenses/${expenseId}`, { + headers: { + Authorization: `Bearer ${token}` + } + }); fetchExpenses(); setDeleteExpenseId(null); } catch (error) { @@ -62,10 +82,11 @@ const Wydatki = () => { } } }; - const openDeleteConfirmation = (transactionId) => { - setDeleteExpenseId(transactionId); + + const openDeleteConfirmation = (expenseId) => { + setDeleteExpenseId(expenseId); }; - + const closeDeleteConfirmation = () => { setDeleteExpenseId(null); }; @@ -78,16 +99,15 @@ const Wydatki = () => { return (
-
-
-
- Wydatki +
+
+ Wydatki +
+
- -
@@ -107,7 +127,8 @@ const Wydatki = () => { ))} @@ -140,41 +161,41 @@ const Wydatki = () => {
{expense.description} + Usuń +