hMarket Trae ilk versiyon

This commit is contained in:
hOLOlu
2026-02-03 01:22:08 +03:00
commit 2b861156fe
74 changed files with 42127 additions and 0 deletions

View File

@@ -0,0 +1,282 @@
import React, { useState } from 'react';
import {
AppBar,
Toolbar,
Typography,
Button,
IconButton,
Menu,
MenuItem,
Avatar,
Badge,
Box,
useTheme,
useMediaQuery,
Drawer,
List,
ListItem,
ListItemButton,
ListItemIcon,
ListItemText,
Divider,
} from '@mui/material';
import {
Menu as MenuIcon,
Notifications as NotificationsIcon,
AccountCircle,
Dashboard,
List as ListIcon,
Inventory,
Settings,
AdminPanelSettings,
Logout,
ShoppingCart,
} from '@mui/icons-material';
import { useNavigate, useLocation } from 'react-router-dom';
import { useAuth } from '../../contexts/AuthContext';
import { useQuery } from '@tanstack/react-query';
import { notificationsAPI } from '../../services/api';
const Navbar: React.FC = () => {
const navigate = useNavigate();
const location = useLocation();
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
const { user, logout, isAuthenticated } = useAuth();
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [mobileOpen, setMobileOpen] = useState(false);
// Get unread notifications count
const { data: unreadCount } = useQuery({
queryKey: ['notifications', 'unread-count'],
queryFn: () => notificationsAPI.getUnreadCount(),
enabled: isAuthenticated,
refetchInterval: 30000, // Refetch every 30 seconds
});
const handleProfileMenuOpen = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
};
const handleMenuClose = () => {
setAnchorEl(null);
};
const handleDrawerToggle = () => {
setMobileOpen(!mobileOpen);
};
const handleLogout = () => {
logout();
handleMenuClose();
navigate('/login');
};
const menuItems = [
{ text: 'Anasayfa', icon: <Dashboard />, path: '/dashboard' },
{ text: 'Listeler', icon: <ListIcon />, path: '/lists' },
{ text: 'Ürünler', icon: <Inventory />, path: '/products' },
];
if (user?.role === 'ADMIN') {
menuItems.push({ text: 'Yönetim', icon: <AdminPanelSettings />, path: '/admin' });
}
const drawer = (
<Box sx={{ width: 250 }}>
<Box sx={{ p: 2, display: 'flex', alignItems: 'center' }}>
<ShoppingCart sx={{ mr: 1, color: 'primary.main' }} />
<Typography variant="h6" color="primary.main" fontWeight="bold">
HMarket
</Typography>
</Box>
<Divider />
<List>
{menuItems.map((item) => (
<ListItem key={item.text} disablePadding>
<ListItemButton
onClick={() => {
navigate(item.path);
setMobileOpen(false);
}}
selected={location.pathname === item.path}
>
<ListItemIcon>{item.icon}</ListItemIcon>
<ListItemText primary={item.text} />
</ListItemButton>
</ListItem>
))}
</List>
<Divider />
<List>
<ListItem disablePadding>
<ListItemButton
onClick={() => {
navigate('/profile');
setMobileOpen(false);
}}
selected={location.pathname === '/profile'}
>
<ListItemIcon><Settings /></ListItemIcon>
<ListItemText primary="Profil" />
</ListItemButton>
</ListItem>
<ListItem disablePadding>
<ListItemButton onClick={handleLogout}>
<ListItemIcon><Logout /></ListItemIcon>
<ListItemText primary=ıkış" />
</ListItemButton>
</ListItem>
</List>
</Box>
);
if (!isAuthenticated) {
return (
<AppBar position="sticky" color="primary">
<Toolbar>
<Box sx={{ display: 'flex', alignItems: 'center', flexGrow: 1 }}>
<ShoppingCart sx={{ mr: 1 }} />
<Typography variant="h6" component="div" fontWeight="bold">
HMarket
</Typography>
</Box>
<Box sx={{ display: 'flex', gap: 1 }}>
<Button
color="inherit"
onClick={() => navigate('/login')}
variant={location.pathname === '/login' ? 'outlined' : 'text'}
>
Giriş
</Button>
<Button
color="inherit"
onClick={() => navigate('/register')}
variant={location.pathname === '/register' ? 'outlined' : 'text'}
>
Kayıt
</Button>
</Box>
</Toolbar>
</AppBar>
);
}
return (
<>
<AppBar position="sticky" color="primary">
<Toolbar>
{isMobile && (
<IconButton
color="inherit"
aria-label="open drawer"
edge="start"
onClick={handleDrawerToggle}
sx={{ mr: 2 }}
>
<MenuIcon />
</IconButton>
)}
<Box sx={{ display: 'flex', alignItems: 'center', flexGrow: 1 }}>
<ShoppingCart sx={{ mr: 1 }} />
<Typography
variant="h6"
component="div"
fontWeight="bold"
sx={{ cursor: 'pointer' }}
onClick={() => navigate('/dashboard')}
>
HMarket
</Typography>
</Box>
{!isMobile && (
<Box sx={{ display: 'flex', gap: 1, mr: 2 }}>
{menuItems.map((item) => (
<Button
key={item.text}
color="inherit"
onClick={() => navigate(item.path)}
variant={location.pathname === item.path ? 'outlined' : 'text'}
startIcon={item.icon}
>
{item.text}
</Button>
))}
</Box>
)}
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
<IconButton color="inherit" onClick={() => navigate('/notifications')}>
<Badge badgeContent={unreadCount?.data?.data?.count || 0} color="error">
<NotificationsIcon />
</Badge>
</IconButton>
<IconButton
size="large"
edge="end"
aria-label="account of current user"
aria-controls="primary-search-account-menu"
aria-haspopup="true"
onClick={handleProfileMenuOpen}
color="inherit"
>
{user?.avatar ? (
<Avatar src={user.avatar} sx={{ width: 32, height: 32 }} />
) : (
<AccountCircle />
)}
</IconButton>
</Box>
</Toolbar>
</AppBar>
{/* Mobile drawer */}
<Drawer
variant="temporary"
open={mobileOpen}
onClose={handleDrawerToggle}
ModalProps={{
keepMounted: true, // Better open performance on mobile.
}}
sx={{
display: { xs: 'block', md: 'none' },
'& .MuiDrawer-paper': { boxSizing: 'border-box', width: 250 },
}}
>
{drawer}
</Drawer>
{/* Profile menu */}
<Menu
anchorEl={anchorEl}
anchorOrigin={{
vertical: 'top',
horizontal: 'right',
}}
id="primary-search-account-menu"
keepMounted
transformOrigin={{
vertical: 'top',
horizontal: 'right',
}}
open={Boolean(anchorEl)}
onClose={handleMenuClose}
>
<MenuItem onClick={() => { navigate('/profile'); handleMenuClose(); }}>
<Settings sx={{ mr: 1 }} />
Profil
</MenuItem>
<MenuItem onClick={handleLogout}>
<Logout sx={{ mr: 1 }} />
Çıkış
</MenuItem>
</Menu>
</>
);
};
export default Navbar;