tidy
This commit is contained in:
parent
71b73d5fcb
commit
0269cefeeb
@ -153,7 +153,9 @@ export class AuthController {
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Get("user-info")
|
||||
async getUserInfo(@Request() req) {
|
||||
return this.authService.getUserInfo(req.user.userId);
|
||||
return await this.authService.getUserInfo(req.user.userId);
|
||||
// const user = await this.authService.getUserInfo(req.user.userId);
|
||||
// return user;
|
||||
}
|
||||
|
||||
@Post("forgot-password")
|
||||
|
||||
@ -1,22 +1,22 @@
|
||||
import { useState } from 'react';
|
||||
import { useAuth } from '../../hooks/useAuth';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Button, Card, Input, FormGroup, Label, ErrorMessage } from '../UI';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useState } from "react";
|
||||
import { useAuth } from "../../hooks/useAuth";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Button, Card, Input, FormGroup, Label, ErrorMessage } from "../UI";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
export default function Login() {
|
||||
const { login } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
const [formData, setFormData] = useState({
|
||||
username: '',
|
||||
password: '',
|
||||
username: "",
|
||||
password: "",
|
||||
});
|
||||
const [error, setError] = useState('');
|
||||
const [error, setError] = useState("");
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
setError('');
|
||||
setError("");
|
||||
setIsLoading(true);
|
||||
|
||||
try {
|
||||
@ -24,13 +24,13 @@ export default function Login() {
|
||||
|
||||
// Navigate based on user role
|
||||
if (userData.isAdmin) {
|
||||
navigate('/admin');
|
||||
navigate("/admin");
|
||||
} else {
|
||||
navigate('/dashboard'); // Navigate normal users to dashboard
|
||||
navigate("/dashboard");
|
||||
}
|
||||
} catch (err) {
|
||||
setError('Invalid username or password');
|
||||
console.error('Login error:', err);
|
||||
setError("Invalid username or password");
|
||||
console.error("Login error:", err);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
@ -42,11 +42,17 @@ export default function Login() {
|
||||
<div className="absolute inset-0 bg-pattern opacity-5 z-0"></div>
|
||||
|
||||
{/* Main content with higher z-index */}
|
||||
<Card className="relative z-10 max-w-md w-full bg-neutral-900/80 backdrop-blur-lg shadow-2xl
|
||||
border border-neutral-800 rounded-xl">
|
||||
<Card
|
||||
className="relative z-10 max-w-md w-full bg-neutral-900/80 backdrop-blur-lg shadow-2xl
|
||||
border border-neutral-800 rounded-xl"
|
||||
>
|
||||
<div className="text-center mb-8">
|
||||
<h2 className="text-2xl font-semibold text-white">Sign in to your account</h2>
|
||||
<p className="text-sm text-neutral-300 mt-2">Welcome back! Please enter your details.</p>
|
||||
<h2 className="text-2xl font-semibold text-white">
|
||||
Sign in to your account
|
||||
</h2>
|
||||
<p className="text-sm text-neutral-300 mt-2">
|
||||
Welcome back! Please enter your details.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{error && (
|
||||
@ -66,7 +72,9 @@ export default function Login() {
|
||||
required
|
||||
placeholder="Enter your username"
|
||||
value={formData.username}
|
||||
onChange={(e) => setFormData({ ...formData, username: e.target.value })}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, username: e.target.value })
|
||||
}
|
||||
error={error}
|
||||
className="bg-neutral-800/50 border-neutral-700 text-white placeholder-neutral-400
|
||||
focus:border-primary-400 focus:ring-primary-400"
|
||||
@ -93,7 +101,9 @@ export default function Login() {
|
||||
required
|
||||
placeholder="Enter your password"
|
||||
value={formData.password}
|
||||
onChange={(e) => setFormData({ ...formData, password: e.target.value })}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, password: e.target.value })
|
||||
}
|
||||
error={error}
|
||||
className="bg-neutral-800/50 border-neutral-700 text-white placeholder-neutral-400
|
||||
focus:border-primary-400 focus:ring-primary-400"
|
||||
@ -110,7 +120,7 @@ export default function Login() {
|
||||
focus:ring-offset-2 focus:ring-primary-500 disabled:opacity-50
|
||||
disabled:cursor-not-allowed transition-colors"
|
||||
>
|
||||
{isLoading ? 'Signing in...' : 'Sign in'}
|
||||
{isLoading ? "Signing in..." : "Sign in"}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
@ -1,27 +1,59 @@
|
||||
import { useState } from "react";
|
||||
import { Dialog } from "@headlessui/react";
|
||||
import { Bars3Icon, XMarkIcon } from "@heroicons/react/24/outline";
|
||||
import { NavLink, Link } from "react-router-dom";
|
||||
import { Button } from '../UI';
|
||||
import { NavLink, Link, useNavigate } from "react-router-dom";
|
||||
import { Button } from "../UI";
|
||||
import { useAuth } from "../../hooks/useAuth";
|
||||
|
||||
const navigation = [
|
||||
const publicNavigation = [
|
||||
{ name: "Дома", href: "/" },
|
||||
{ name: "За нас", href: "/about" },
|
||||
{ name: "Галерија", href: "/gallery" },
|
||||
{ name: "Контакт", href: "/contact" },
|
||||
// { name: "Админ", href: "/admin" },
|
||||
{ name: "Логин", href: "/login" },
|
||||
];
|
||||
|
||||
const basePrivateNavigation = [
|
||||
{ name: "Дома", href: "/" },
|
||||
{ name: "За нас", href: "/about" },
|
||||
{ name: "Галерија", href: "/gallery" },
|
||||
{ name: "Контакт", href: "/contact" },
|
||||
];
|
||||
|
||||
export default function Navbar() {
|
||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
||||
const { user, logout } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const getNavigation = () => {
|
||||
if (!user) return publicNavigation;
|
||||
|
||||
// Add appropriate dashboard link based on user role
|
||||
const privateNavigation = [...basePrivateNavigation];
|
||||
if (user.isAdmin) {
|
||||
privateNavigation.push({ name: "Админ Панел", href: "/admin" });
|
||||
} else {
|
||||
privateNavigation.push({ name: "Клиент Зона", href: "/dashboard" });
|
||||
}
|
||||
return privateNavigation;
|
||||
};
|
||||
|
||||
const navigation = getNavigation();
|
||||
const handleLogout = async () => {
|
||||
try {
|
||||
await logout();
|
||||
navigate("/");
|
||||
} catch (error) {
|
||||
console.error("Logout failed:", error);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div className="w-full bg-gradient-to-b from-primary-900 to-primary-800 border-b border-primary-700/50">
|
||||
<header className="relative">
|
||||
<nav className="container-base py-4" aria-label="Global">
|
||||
<div className="flex items-center justify-between">
|
||||
{/* Left Logo */}
|
||||
<div className="flex-shrink-0">
|
||||
<Link to="/" className="p-2 hover:bg-white/20 transition-colors">
|
||||
<img
|
||||
className="h-10 w-auto transition-transform duration-300 hover:scale-105"
|
||||
@ -29,9 +61,10 @@ export default function Navbar() {
|
||||
alt="IMK logo"
|
||||
/>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Centered Desktop Navigation */}
|
||||
<div className="hidden lg:flex flex-grow justify-center mx-8">
|
||||
<div className="hidden lg:flex flex-grow justify-center">
|
||||
<div className="flex items-center gap-x-1">
|
||||
{navigation.map((item) => (
|
||||
<NavLink
|
||||
@ -39,9 +72,11 @@ export default function Navbar() {
|
||||
to={item.href}
|
||||
className={({ isActive }) =>
|
||||
`px-4 py-2 text-sm font-medium rounded-lg transition-all duration-200
|
||||
${isActive
|
||||
? 'bg-primary-700 text-white shadow-lg'
|
||||
: 'text-neutral-200 hover:bg-primary-700/50 hover:text-white'}`
|
||||
${
|
||||
isActive
|
||||
? "bg-primary-700 text-white shadow-lg"
|
||||
: "text-neutral-200 hover:bg-primary-700/50 hover:text-white"
|
||||
}`
|
||||
}
|
||||
>
|
||||
{item.name}
|
||||
@ -50,18 +85,36 @@ export default function Navbar() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right Side - TUF Logo & Mobile Menu */}
|
||||
{/* Right Side Content */}
|
||||
<div className="flex items-center gap-x-4">
|
||||
{/* User Menu & Logout */}
|
||||
{user && (
|
||||
<div className="hidden lg:flex items-center gap-x-4">
|
||||
<span className="text-white text-sm">
|
||||
{user.name || user.email}
|
||||
</span>
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={handleLogout}
|
||||
className="text-white hover:bg-primary-700/50 px-4 py-2 text-sm"
|
||||
>
|
||||
Одјави се
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* TUF Logo */}
|
||||
<a href="/" className="hidden lg:flex p-2 hover:bg-white/20 transition-colors">
|
||||
<div className="hidden lg:block">
|
||||
<a href="/" className="p-2 hover:bg-white/20 transition-colors">
|
||||
<img
|
||||
className="h-10 w-auto transition-transform duration-300 hover:scale-105"
|
||||
src="/tuf.png"
|
||||
alt="TUF logo"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Mobile menu button */}
|
||||
{/* Mobile Menu Button */}
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="lg:hidden text-white hover:bg-primary-700/50"
|
||||
@ -74,7 +127,7 @@ export default function Navbar() {
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{/* Mobile menu */}
|
||||
{/* Mobile Menu */}
|
||||
<Dialog
|
||||
as="div"
|
||||
className="lg:hidden"
|
||||
@ -100,17 +153,32 @@ export default function Navbar() {
|
||||
<XMarkIcon className="h-6 w-6" aria-hidden="true" />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="mt-6 flow-root">
|
||||
<div className="space-y-1 py-6">
|
||||
{/* User Info in Mobile Menu */}
|
||||
{user && (
|
||||
<div className="px-3 py-2 text-white border-b border-primary-700/50 mb-4">
|
||||
<span className="block text-sm font-medium">
|
||||
{user.name || user.email}
|
||||
</span>
|
||||
<span className="block text-sm text-primary-400">
|
||||
{user.isAdmin ? "Администратор" : "Корисник"}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Navigation Items */}
|
||||
{navigation.map((item) => (
|
||||
<NavLink
|
||||
key={item.name}
|
||||
to={item.href}
|
||||
className={({ isActive }) =>
|
||||
`block px-3 py-2 text-base font-medium rounded-lg transition-colors
|
||||
${isActive
|
||||
? 'bg-primary-700 text-white'
|
||||
: 'text-neutral-200 hover:bg-primary-700/50 hover:text-white'
|
||||
${
|
||||
isActive
|
||||
? "bg-primary-700 text-white"
|
||||
: "text-neutral-200 hover:bg-primary-700/50 hover:text-white"
|
||||
}`
|
||||
}
|
||||
onClick={() => setMobileMenuOpen(false)}
|
||||
@ -118,6 +186,20 @@ export default function Navbar() {
|
||||
{item.name}
|
||||
</NavLink>
|
||||
))}
|
||||
|
||||
{/* Logout in Mobile Menu */}
|
||||
{user && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => {
|
||||
handleLogout();
|
||||
setMobileMenuOpen(false);
|
||||
}}
|
||||
className="block w-full text-left px-3 py-2 text-base font-medium text-neutral-200 hover:bg-primary-700/50 hover:text-white rounded-lg mt-4"
|
||||
>
|
||||
Одјави се
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Dialog.Panel>
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
// frontend/src/hooks/useAuth.jsx
|
||||
import { createContext, useContext, useState, useEffect } from "react";
|
||||
import api from "../services/api";
|
||||
|
||||
@ -51,6 +50,7 @@ export const AuthProvider = ({ children }) => {
|
||||
};
|
||||
|
||||
const logout = () => {
|
||||
//no session menager in DB, can add it later
|
||||
localStorage.removeItem("token");
|
||||
setUser(null);
|
||||
};
|
||||
|
||||
@ -122,5 +122,4 @@ api.interceptors.response.use(
|
||||
return Promise.reject(error);
|
||||
},
|
||||
);
|
||||
export const logout = () => api.post("/auth/logout");
|
||||
export default api;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user