Added profile view
This commit is contained in:
parent
749a5529f2
commit
e374df55de
10
frontend/package-lock.json
generated
10
frontend/package-lock.json
generated
@ -10,6 +10,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.8.3",
|
"axios": "^1.8.3",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
|
"lucide-react": "^0.488.0",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-router-dom": "^7.3.0"
|
"react-router-dom": "^7.3.0"
|
||||||
@ -2814,6 +2815,15 @@
|
|||||||
"yallist": "^3.0.2"
|
"yallist": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lucide-react": {
|
||||||
|
"version": "0.488.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.488.0.tgz",
|
||||||
|
"integrity": "sha512-ronlL0MyKut4CEzBY/ai2ZpKPxyWO4jUqdAkm2GNK5Zn3Rj+swDz+3lvyAUXN0PNqPKIX6XM9Xadwz/skLs/pQ==",
|
||||||
|
"license": "ISC",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/math-intrinsics": {
|
"node_modules/math-intrinsics": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.8.3",
|
"axios": "^1.8.3",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
|
"lucide-react": "^0.488.0",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-router-dom": "^7.3.0"
|
"react-router-dom": "^7.3.0"
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
|
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
|
||||||
import Login from "./pages/Login";
|
import Login from "./pages/Login";
|
||||||
import Tasks from "./pages/Tasks";
|
import Tasks from "./pages/Tasks";
|
||||||
|
import Profile from "./pages/Profile";
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
return (
|
return (
|
||||||
@ -8,6 +9,7 @@ const App = () => {
|
|||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/login" element={<Login />} />
|
<Route path="/login" element={<Login />} />
|
||||||
<Route path="/tasks" element={<Tasks />} />
|
<Route path="/tasks" element={<Tasks />} />
|
||||||
|
<Route path="/profile" element={<Profile />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</Router>
|
</Router>
|
||||||
);
|
);
|
||||||
|
24
frontend/src/api/user.ts
Normal file
24
frontend/src/api/user.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import api from "./api";
|
||||||
|
|
||||||
|
export const getUser = async (userId: number) => {
|
||||||
|
const response = await api.get(`/users/${userId}`);
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateUser = async (
|
||||||
|
userId: number,
|
||||||
|
data: {
|
||||||
|
username: string;
|
||||||
|
email: string;
|
||||||
|
password?: string;
|
||||||
|
oldPassword?: string;
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
const response = await api.patch(`/users/${userId}`, data);
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteUser = async (userId: number) => {
|
||||||
|
const response = await api.delete(`/users/${userId}`);
|
||||||
|
return response.data;
|
||||||
|
};
|
77
frontend/src/pages/Profile.tsx
Normal file
77
frontend/src/pages/Profile.tsx
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { getUser, deleteUser } from "../api/user";
|
||||||
|
import Cookies from "js-cookie";
|
||||||
|
|
||||||
|
interface User {
|
||||||
|
id: number;
|
||||||
|
username: string;
|
||||||
|
email: string;
|
||||||
|
role: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Profile = () => {
|
||||||
|
const id = Cookies.get("user_id")
|
||||||
|
const navigate = useNavigate();
|
||||||
|
if (!id) {
|
||||||
|
navigate("/login")
|
||||||
|
}
|
||||||
|
const [user, setUser] = useState<User | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchUser = async () => {
|
||||||
|
try {
|
||||||
|
const userData = await getUser(Number(id));
|
||||||
|
setUser(userData);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Błąd podczas pobierania danych użytkownika:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchUser();
|
||||||
|
}, [id]);
|
||||||
|
|
||||||
|
const handleDeleteAccount = async () => {
|
||||||
|
if (!window.confirm("Na pewno chcesz usunąć konto? Tej operacji nie da się cofnąć.")) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await deleteUser(Number(id));
|
||||||
|
Cookies.remove("user_id");
|
||||||
|
navigate("/login");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Błąd podczas usuwania konta:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!user) return <div className="p-6">Ładowanie danych użytkownika...</div>;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="p-6 max-w-md mx-auto">
|
||||||
|
<h1 className="text-2xl font-bold mb-4">Twój profil</h1>
|
||||||
|
|
||||||
|
<div className="bg-white shadow rounded p-4 mb-4">
|
||||||
|
<p><strong>Nazwa użytkownika:</strong> {user.username}</p>
|
||||||
|
<p><strong>Email:</strong> {user.email}</p>
|
||||||
|
<p><strong>Rola:</strong> {user.role}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<button
|
||||||
|
onClick={() => navigate(`/profile/${user.id}/change-password`)}
|
||||||
|
className="bg-blue-500 text-white p-2 rounded hover:bg-blue-600"
|
||||||
|
>
|
||||||
|
🔐 Zmień hasło
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={handleDeleteAccount}
|
||||||
|
className="bg-red-500 text-white p-2 rounded hover:bg-red-600"
|
||||||
|
>
|
||||||
|
🗑️ Usuń konto
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Profile;
|
@ -4,6 +4,7 @@ import { getUserTasks, createTask, deleteTask } from "../api/tasks";
|
|||||||
import { logout } from "../api/auth";
|
import { logout } from "../api/auth";
|
||||||
import api from "../api/api";
|
import api from "../api/api";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
|
import { User } from "lucide-react";
|
||||||
|
|
||||||
// Define Task type
|
// Define Task type
|
||||||
interface Task {
|
interface Task {
|
||||||
@ -82,9 +83,14 @@ const Tasks = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-6">
|
<div className="p-6 relative min-h-screen">
|
||||||
|
<button
|
||||||
|
onClick={() => navigate(`/profile`)}
|
||||||
|
className="text-gray-600 hover:text-black mb-4 flex items-center">
|
||||||
|
<User className="w-5 h-5 mr-1" />
|
||||||
|
Profil
|
||||||
|
</button>
|
||||||
<h1 className="text-2xl font-bold mb-4">Twoje zadania</h1>
|
<h1 className="text-2xl font-bold mb-4">Twoje zadania</h1>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={handleLogout}
|
onClick={handleLogout}
|
||||||
className="bg-red-500 text-white p-2 rounded hover:bg-red-600 mb-4"
|
className="bg-red-500 text-white p-2 rounded hover:bg-red-600 mb-4"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user