feat: Implement user authentication initialization and profile management with a Colaborador domain entity.
This commit is contained in:
parent
e19798e582
commit
c66bc9620b
|
|
@ -1,64 +0,0 @@
|
||||||
import { Avatar, Box, Typography, Grid, Stack } from '@mui/material';
|
|
||||||
import * as dropdownData from './data';
|
|
||||||
import Link from 'next/link';
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
const AppLinks = () => {
|
|
||||||
return (
|
|
||||||
<Grid container spacing={3} mb={4}>
|
|
||||||
{dropdownData.appsLink.map((links) => (
|
|
||||||
<Grid size={{ lg: 6 }} key={links.title}>
|
|
||||||
<Link href={links.href} className="hover-text-primary">
|
|
||||||
<Stack direction="row" spacing={2}>
|
|
||||||
<Box
|
|
||||||
minWidth="45px"
|
|
||||||
height="45px"
|
|
||||||
bgcolor="grey.100"
|
|
||||||
display="flex"
|
|
||||||
alignItems="center"
|
|
||||||
justifyContent="center"
|
|
||||||
>
|
|
||||||
<Avatar
|
|
||||||
src={links.avatar}
|
|
||||||
alt={links.avatar}
|
|
||||||
sx={{
|
|
||||||
width: 24,
|
|
||||||
height: 24,
|
|
||||||
borderRadius: 0,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
<Box>
|
|
||||||
<Typography
|
|
||||||
variant="subtitle2"
|
|
||||||
fontWeight={600}
|
|
||||||
color="textPrimary"
|
|
||||||
noWrap
|
|
||||||
className="text-hover"
|
|
||||||
sx={{
|
|
||||||
width: '240px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{links.title}
|
|
||||||
</Typography>
|
|
||||||
<Typography
|
|
||||||
color="textSecondary"
|
|
||||||
variant="subtitle2"
|
|
||||||
fontSize="12px"
|
|
||||||
sx={{
|
|
||||||
width: '240px',
|
|
||||||
}}
|
|
||||||
noWrap
|
|
||||||
>
|
|
||||||
{links.subtext}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
</Stack>
|
|
||||||
</Link>
|
|
||||||
</Grid>
|
|
||||||
))}
|
|
||||||
</Grid>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AppLinks;
|
|
||||||
|
|
@ -12,11 +12,8 @@ import DarkModeIcon from '@mui/icons-material/DarkMode';
|
||||||
import LightModeIcon from '@mui/icons-material/LightMode';
|
import LightModeIcon from '@mui/icons-material/LightMode';
|
||||||
import { useCustomizerStore } from '../store/useCustomizerStore';
|
import { useCustomizerStore } from '../store/useCustomizerStore';
|
||||||
|
|
||||||
import Notifications from './Notification';
|
|
||||||
import Profile from './Profile';
|
import Profile from './Profile';
|
||||||
import Search from './Search';
|
import Search from './Search';
|
||||||
import Navigation from './Navigation';
|
|
||||||
import MobileRightSidebar from './MobileRightSidebar';
|
|
||||||
|
|
||||||
const AppBarStyled = styled(AppBar)(({ theme }) => ({
|
const AppBarStyled = styled(AppBar)(({ theme }) => ({
|
||||||
boxShadow: 'none',
|
boxShadow: 'none',
|
||||||
|
|
@ -33,7 +30,6 @@ const ToolbarStyled = styled(Toolbar)(({ theme }) => ({
|
||||||
|
|
||||||
const Header = () => {
|
const Header = () => {
|
||||||
const lgUp = useMediaQuery((theme: Theme) => theme.breakpoints.up('lg'));
|
const lgUp = useMediaQuery((theme: Theme) => theme.breakpoints.up('lg'));
|
||||||
const lgDown = useMediaQuery((theme: Theme) => theme.breakpoints.down('lg'));
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
activeMode,
|
activeMode,
|
||||||
|
|
@ -51,7 +47,7 @@ const Header = () => {
|
||||||
<AppBarStyled position="sticky" color="default">
|
<AppBarStyled position="sticky" color="default">
|
||||||
<ToolbarStyled>
|
<ToolbarStyled>
|
||||||
{/* ------------------------------------------- */}
|
{/* ------------------------------------------- */}
|
||||||
{/* Toggle Button Sidebar (Fluxo 2) */}
|
{/* Toggle Button Sidebar */}
|
||||||
{/* ------------------------------------------- */}
|
{/* ------------------------------------------- */}
|
||||||
<IconButton
|
<IconButton
|
||||||
color="inherit"
|
color="inherit"
|
||||||
|
|
@ -62,10 +58,9 @@ const Header = () => {
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
|
||||||
{/* ------------------------------------------- */}
|
{/* ------------------------------------------- */}
|
||||||
{/* Search & Navigation */}
|
{/* Search */}
|
||||||
{/* ------------------------------------------- */}
|
{/* ------------------------------------------- */}
|
||||||
<Search />
|
<Search />
|
||||||
{lgUp && <Navigation />}
|
|
||||||
|
|
||||||
<Box flexGrow={1} />
|
<Box flexGrow={1} />
|
||||||
|
|
||||||
|
|
@ -84,12 +79,9 @@ const Header = () => {
|
||||||
{activeMode === 'light' ? <DarkModeIcon /> : <LightModeIcon />}
|
{activeMode === 'light' ? <DarkModeIcon /> : <LightModeIcon />}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
|
||||||
<Notifications />
|
|
||||||
|
|
||||||
{/* ------------------------------------------- */}
|
{/* ------------------------------------------- */}
|
||||||
{/* Mobile Right Sidebar & Profile */}
|
{/* Profile */}
|
||||||
{/* ------------------------------------------- */}
|
{/* ------------------------------------------- */}
|
||||||
{lgDown && <MobileRightSidebar />}
|
|
||||||
<Profile />
|
<Profile />
|
||||||
</Stack>
|
</Stack>
|
||||||
</ToolbarStyled>
|
</ToolbarStyled>
|
||||||
|
|
@ -98,3 +90,4 @@ const Header = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Header;
|
export default Header;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,128 +0,0 @@
|
||||||
import React, { useState } from 'react';
|
|
||||||
import {
|
|
||||||
IconApps,
|
|
||||||
IconChevronDown,
|
|
||||||
IconChevronUp,
|
|
||||||
IconGridDots,
|
|
||||||
IconMail,
|
|
||||||
IconMessages,
|
|
||||||
} from '@tabler/icons-react';
|
|
||||||
import {
|
|
||||||
Box,
|
|
||||||
Typography,
|
|
||||||
Drawer,
|
|
||||||
IconButton,
|
|
||||||
List,
|
|
||||||
ListItemButton,
|
|
||||||
ListItemIcon,
|
|
||||||
ListItemText,
|
|
||||||
Collapse,
|
|
||||||
} from '@mui/material';
|
|
||||||
|
|
||||||
import Link from 'next/link';
|
|
||||||
import AppLinks from './AppLinks';
|
|
||||||
|
|
||||||
const MobileRightSidebar = () => {
|
|
||||||
const [showDrawer, setShowDrawer] = useState(false);
|
|
||||||
|
|
||||||
const [open, setOpen] = React.useState(true);
|
|
||||||
|
|
||||||
const handleClick = () => {
|
|
||||||
setOpen(!open);
|
|
||||||
};
|
|
||||||
|
|
||||||
const cartContent = (
|
|
||||||
<Box>
|
|
||||||
{/* ------------------------------------------- */}
|
|
||||||
{/* Apps Content */}
|
|
||||||
{/* ------------------------------------------- */}
|
|
||||||
<Box px={1}>
|
|
||||||
<List
|
|
||||||
sx={{ width: '100%', maxWidth: 360, bgcolor: 'background.paper' }}
|
|
||||||
component="nav"
|
|
||||||
aria-labelledby="nested-list-subheader"
|
|
||||||
>
|
|
||||||
<ListItemButton component={Link} href="/apps/chats">
|
|
||||||
<ListItemIcon sx={{ minWidth: 35 }}>
|
|
||||||
<IconMessages size="21" stroke="1.5" />
|
|
||||||
</ListItemIcon>
|
|
||||||
<ListItemText>
|
|
||||||
<Typography variant="subtitle2" fontWeight={600}>
|
|
||||||
Chats
|
|
||||||
</Typography>
|
|
||||||
</ListItemText>
|
|
||||||
</ListItemButton>
|
|
||||||
<ListItemButton component={Link} href="/apps/email">
|
|
||||||
<ListItemIcon sx={{ minWidth: 35 }}>
|
|
||||||
<IconMail size="21" stroke="1.5" />
|
|
||||||
</ListItemIcon>
|
|
||||||
<ListItemText>
|
|
||||||
<Typography variant="subtitle2" fontWeight={600}>
|
|
||||||
Email
|
|
||||||
</Typography>
|
|
||||||
</ListItemText>
|
|
||||||
</ListItemButton>
|
|
||||||
<ListItemButton onClick={handleClick}>
|
|
||||||
<ListItemIcon sx={{ minWidth: 35 }}>
|
|
||||||
<IconApps size="21" stroke="1.5" />
|
|
||||||
</ListItemIcon>
|
|
||||||
<ListItemText>
|
|
||||||
<Typography variant="subtitle2" fontWeight={600}>
|
|
||||||
Apps
|
|
||||||
</Typography>
|
|
||||||
</ListItemText>
|
|
||||||
{open ? (
|
|
||||||
<IconChevronDown size="21" stroke="1.5" />
|
|
||||||
) : (
|
|
||||||
<IconChevronUp size="21" stroke="1.5" />
|
|
||||||
)}
|
|
||||||
</ListItemButton>
|
|
||||||
<Collapse in={open} timeout="auto" unmountOnExit>
|
|
||||||
<Box px={4} pt={3} overflow="hidden">
|
|
||||||
<AppLinks />
|
|
||||||
</Box>
|
|
||||||
</Collapse>
|
|
||||||
</List>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Box px={3} mt={3}></Box>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<IconButton
|
|
||||||
size="large"
|
|
||||||
color="inherit"
|
|
||||||
onClick={() => setShowDrawer(true)}
|
|
||||||
sx={{
|
|
||||||
...(showDrawer && {
|
|
||||||
color: 'primary.main',
|
|
||||||
}),
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<IconGridDots size="21" stroke="1.5" />
|
|
||||||
</IconButton>
|
|
||||||
{/* ------------------------------------------- */}
|
|
||||||
{/* Cart Sidebar */}
|
|
||||||
{/* ------------------------------------------- */}
|
|
||||||
<Drawer
|
|
||||||
anchor="right"
|
|
||||||
open={showDrawer}
|
|
||||||
onClose={() => setShowDrawer(false)}
|
|
||||||
PaperProps={{ sx: { width: '300px' } }}
|
|
||||||
>
|
|
||||||
<Box p={3} pb={0}>
|
|
||||||
<Typography variant="h5" fontWeight={600}>
|
|
||||||
Navigation
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
{/* component */}
|
|
||||||
{cartContent}
|
|
||||||
</Drawer>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MobileRightSidebar;
|
|
||||||
|
|
@ -1,135 +0,0 @@
|
||||||
import { useState } from 'react';
|
|
||||||
import { Box, Menu, Typography, Button, Divider, Grid } from '@mui/material';
|
|
||||||
import Link from 'next/link';
|
|
||||||
import { IconChevronDown, IconHelp } from '@tabler/icons-react';
|
|
||||||
import AppLinks from './AppLinks';
|
|
||||||
|
|
||||||
const AppDD = () => {
|
|
||||||
const [anchorEl2, setAnchorEl2] = useState(null);
|
|
||||||
|
|
||||||
const handleClick2 = (event: any) => {
|
|
||||||
setAnchorEl2(event.currentTarget);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleClose2 = () => {
|
|
||||||
setAnchorEl2(null);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Box>
|
|
||||||
<Button
|
|
||||||
aria-label="show 11 new notifications"
|
|
||||||
color="inherit"
|
|
||||||
variant="text"
|
|
||||||
aria-controls="msgs-menu"
|
|
||||||
aria-haspopup="true"
|
|
||||||
sx={{
|
|
||||||
bgcolor: anchorEl2 ? 'primary.light' : '',
|
|
||||||
color: anchorEl2
|
|
||||||
? 'primary.main'
|
|
||||||
: (theme) => theme.palette.text.secondary,
|
|
||||||
fontSize: '13px',
|
|
||||||
}}
|
|
||||||
onClick={handleClick2}
|
|
||||||
endIcon={
|
|
||||||
<IconChevronDown
|
|
||||||
size="15"
|
|
||||||
style={{ marginLeft: '-5px', marginTop: '2px' }}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Apps
|
|
||||||
</Button>
|
|
||||||
{/* ------------------------------------------- */}
|
|
||||||
{/* Message Dropdown */}
|
|
||||||
{/* ------------------------------------------- */}
|
|
||||||
<Menu
|
|
||||||
id="msgs-menu"
|
|
||||||
anchorEl={anchorEl2}
|
|
||||||
keepMounted
|
|
||||||
open={Boolean(anchorEl2)}
|
|
||||||
onClose={handleClose2}
|
|
||||||
anchorOrigin={{ horizontal: 'left', vertical: 'bottom' }}
|
|
||||||
transformOrigin={{ horizontal: 'left', vertical: 'top' }}
|
|
||||||
sx={{
|
|
||||||
'& .MuiMenu-paper': {
|
|
||||||
width: '850px',
|
|
||||||
},
|
|
||||||
'& .MuiMenu-paper ul': {
|
|
||||||
p: 0,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Grid container>
|
|
||||||
<Grid size={{ sm: 8 }} display="flex">
|
|
||||||
<Box p={4} pr={0} pb={3}>
|
|
||||||
<AppLinks />
|
|
||||||
<Divider />
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: {
|
|
||||||
xs: 'none',
|
|
||||||
sm: 'flex',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
alignItems="center"
|
|
||||||
justifyContent="space-between"
|
|
||||||
pt={2}
|
|
||||||
pr={4}
|
|
||||||
>
|
|
||||||
<Link href="/faq">
|
|
||||||
<Typography
|
|
||||||
variant="subtitle2"
|
|
||||||
fontWeight="600"
|
|
||||||
color="textPrimary"
|
|
||||||
display="flex"
|
|
||||||
alignItems="center"
|
|
||||||
gap="4px"
|
|
||||||
>
|
|
||||||
<IconHelp width={24} />
|
|
||||||
Frequently Asked Questions
|
|
||||||
</Typography>
|
|
||||||
</Link>
|
|
||||||
<Button variant="contained" color="primary">
|
|
||||||
Check
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
<Divider orientation="vertical" />
|
|
||||||
</Grid>
|
|
||||||
<Grid size={{ sm: 4 }}>
|
|
||||||
<Box p={4}></Box>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Menu>
|
|
||||||
</Box>
|
|
||||||
<Button
|
|
||||||
color="inherit"
|
|
||||||
sx={{
|
|
||||||
color: (theme) => theme.palette.text.secondary,
|
|
||||||
fontSize: '13px',
|
|
||||||
}}
|
|
||||||
variant="text"
|
|
||||||
href="/apps/chats"
|
|
||||||
component={Link}
|
|
||||||
>
|
|
||||||
Chat
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
color="inherit"
|
|
||||||
sx={{
|
|
||||||
color: (theme) => theme.palette.text.secondary,
|
|
||||||
fontSize: '13px',
|
|
||||||
}}
|
|
||||||
variant="text"
|
|
||||||
href="/apps/email"
|
|
||||||
component={Link}
|
|
||||||
>
|
|
||||||
Email
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AppDD;
|
|
||||||
|
|
@ -1,132 +0,0 @@
|
||||||
import React, { useState } from 'react';
|
|
||||||
import {
|
|
||||||
IconButton,
|
|
||||||
Box,
|
|
||||||
Badge,
|
|
||||||
Menu,
|
|
||||||
MenuItem,
|
|
||||||
Avatar,
|
|
||||||
Typography,
|
|
||||||
Button,
|
|
||||||
Chip,
|
|
||||||
} from '@mui/material';
|
|
||||||
import * as dropdownData from './data';
|
|
||||||
import { Scrollbar } from '@/shared/components';
|
|
||||||
|
|
||||||
import { IconBellRinging } from '@tabler/icons-react';
|
|
||||||
import { Stack } from '@mui/system';
|
|
||||||
import Link from 'next/link';
|
|
||||||
|
|
||||||
const Notifications = () => {
|
|
||||||
const [anchorEl2, setAnchorEl2] = useState(null);
|
|
||||||
|
|
||||||
const handleClick2 = (event: any) => {
|
|
||||||
setAnchorEl2(event.currentTarget);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleClose2 = () => {
|
|
||||||
setAnchorEl2(null);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<IconButton
|
|
||||||
size="large"
|
|
||||||
aria-label="show 11 new notifications"
|
|
||||||
color="inherit"
|
|
||||||
aria-controls="msgs-menu"
|
|
||||||
aria-haspopup="true"
|
|
||||||
sx={{
|
|
||||||
color: anchorEl2 ? 'primary.main' : 'text.secondary',
|
|
||||||
}}
|
|
||||||
onClick={handleClick2}
|
|
||||||
>
|
|
||||||
<Badge variant="dot" color="primary">
|
|
||||||
<IconBellRinging size="21" stroke="1.5" />
|
|
||||||
</Badge>
|
|
||||||
</IconButton>
|
|
||||||
{/* ------------------------------------------- */}
|
|
||||||
{/* Message Dropdown */}
|
|
||||||
{/* ------------------------------------------- */}
|
|
||||||
<Menu
|
|
||||||
id="msgs-menu"
|
|
||||||
anchorEl={anchorEl2}
|
|
||||||
keepMounted
|
|
||||||
open={Boolean(anchorEl2)}
|
|
||||||
onClose={handleClose2}
|
|
||||||
anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }}
|
|
||||||
transformOrigin={{ horizontal: 'right', vertical: 'top' }}
|
|
||||||
sx={{
|
|
||||||
'& .MuiMenu-paper': {
|
|
||||||
width: '360px',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Stack
|
|
||||||
direction="row"
|
|
||||||
py={2}
|
|
||||||
px={4}
|
|
||||||
justifyContent="space-between"
|
|
||||||
alignItems="center"
|
|
||||||
>
|
|
||||||
<Typography variant="h6">Notifications</Typography>
|
|
||||||
<Chip label="5 new" color="primary" size="small" />
|
|
||||||
</Stack>
|
|
||||||
<Scrollbar sx={{ height: '385px' }}>
|
|
||||||
{dropdownData.notifications.map((notification) => (
|
|
||||||
<Box key={notification.id}>
|
|
||||||
<MenuItem sx={{ py: 2, px: 4 }}>
|
|
||||||
<Stack direction="row" spacing={2}>
|
|
||||||
<Avatar
|
|
||||||
src={notification.avatar}
|
|
||||||
alt={notification.avatar}
|
|
||||||
sx={{
|
|
||||||
width: 48,
|
|
||||||
height: 48,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Box>
|
|
||||||
<Typography
|
|
||||||
variant="subtitle2"
|
|
||||||
color="textPrimary"
|
|
||||||
fontWeight={600}
|
|
||||||
noWrap
|
|
||||||
sx={{
|
|
||||||
width: '240px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{notification.title}
|
|
||||||
</Typography>
|
|
||||||
<Typography
|
|
||||||
color="textSecondary"
|
|
||||||
variant="subtitle2"
|
|
||||||
sx={{
|
|
||||||
width: '240px',
|
|
||||||
}}
|
|
||||||
noWrap
|
|
||||||
>
|
|
||||||
{notification.subtitle}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
</Stack>
|
|
||||||
</MenuItem>
|
|
||||||
</Box>
|
|
||||||
))}
|
|
||||||
</Scrollbar>
|
|
||||||
<Box p={3} pb={1}>
|
|
||||||
<Button
|
|
||||||
href="/apps/email"
|
|
||||||
variant="outlined"
|
|
||||||
component={Link}
|
|
||||||
color="primary"
|
|
||||||
fullWidth
|
|
||||||
>
|
|
||||||
See all Notifications
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
</Menu>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Notifications;
|
|
||||||
|
|
@ -5,11 +5,9 @@ import {
|
||||||
Menu,
|
Menu,
|
||||||
Avatar,
|
Avatar,
|
||||||
Typography,
|
Typography,
|
||||||
Divider,
|
|
||||||
Button,
|
Button,
|
||||||
IconButton,
|
IconButton,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { IconMail } from '@tabler/icons-react';
|
|
||||||
import { Stack } from '@mui/system';
|
import { Stack } from '@mui/system';
|
||||||
|
|
||||||
import { useAuthStore } from '../../login/store/useAuthStore';
|
import { useAuthStore } from '../../login/store/useAuthStore';
|
||||||
|
|
@ -27,10 +25,18 @@ const Profile = () => {
|
||||||
setAnchorEl2(null);
|
setAnchorEl2(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Gera as iniciais do nome
|
||||||
|
const getIniciais = () => {
|
||||||
|
if (!user?.nome) return user?.userName?.[0]?.toUpperCase() || 'U';
|
||||||
|
const partes = user.nome.trim().split(' ').filter(Boolean);
|
||||||
|
if (partes.length === 1) return partes[0][0].toUpperCase();
|
||||||
|
return (partes[0][0] + partes[partes.length - 1][0]).toUpperCase();
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<IconButton
|
<IconButton
|
||||||
aria-label="show 11 new notifications"
|
aria-label="menu do perfil"
|
||||||
color="inherit"
|
color="inherit"
|
||||||
aria-controls="msgs-menu"
|
aria-controls="msgs-menu"
|
||||||
aria-haspopup="true"
|
aria-haspopup="true"
|
||||||
|
|
@ -48,11 +54,11 @@ const Profile = () => {
|
||||||
bgcolor: 'primary.main',
|
bgcolor: 'primary.main',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{user?.nome?.[0] || user?.userName?.[0] || 'U'}
|
{getIniciais()}
|
||||||
</Avatar>
|
</Avatar>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
{/* ------------------------------------------- */}
|
{/* ------------------------------------------- */}
|
||||||
{/* Message Dropdown */}
|
{/* Profile Dropdown */}
|
||||||
{/* ------------------------------------------- */}
|
{/* ------------------------------------------- */}
|
||||||
<Menu
|
<Menu
|
||||||
id="msgs-menu"
|
id="msgs-menu"
|
||||||
|
|
@ -64,17 +70,19 @@ const Profile = () => {
|
||||||
transformOrigin={{ horizontal: 'right', vertical: 'top' }}
|
transformOrigin={{ horizontal: 'right', vertical: 'top' }}
|
||||||
sx={{
|
sx={{
|
||||||
'& .MuiMenu-paper': {
|
'& .MuiMenu-paper': {
|
||||||
width: '360px',
|
width: '320px',
|
||||||
p: 4,
|
p: 3,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography variant="h5">User Profile</Typography>
|
<Typography variant="h6" fontWeight={600}>
|
||||||
<Stack direction="row" py={3} spacing={2} alignItems="center">
|
Meu Perfil
|
||||||
|
</Typography>
|
||||||
|
<Stack direction="row" py={2} spacing={2} alignItems="center">
|
||||||
<Avatar
|
<Avatar
|
||||||
sx={{ width: 95, height: 95, bgcolor: 'primary.main' }}
|
sx={{ width: 64, height: 64, bgcolor: 'primary.main', fontSize: '1.5rem' }}
|
||||||
>
|
>
|
||||||
{user?.nome?.[0] || user?.userName?.[0] || 'U'}
|
{getIniciais()}
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<Box>
|
<Box>
|
||||||
<Typography
|
<Typography
|
||||||
|
|
@ -84,34 +92,36 @@ const Profile = () => {
|
||||||
>
|
>
|
||||||
{user?.nome || user?.userName || 'Usuário'}
|
{user?.nome || user?.userName || 'Usuário'}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="subtitle2" color="textSecondary">
|
<Typography variant="body2" color="textSecondary">
|
||||||
{user?.nomeFilial || 'Sem filial'}
|
{user?.nomeFilial || '-'}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography
|
<Typography variant="body2" color="textSecondary">
|
||||||
variant="subtitle2"
|
Matrícula: {user?.matricula || '-'}
|
||||||
color="textSecondary"
|
|
||||||
display="flex"
|
|
||||||
alignItems="center"
|
|
||||||
gap={1}
|
|
||||||
>
|
|
||||||
<IconMail width={15} height={15} />
|
|
||||||
{user?.rca ? `RCA: ${user.rca}` : 'Sem e-mail'}
|
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Box mt={2}>
|
|
||||||
<Button
|
<Button
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
color="primary"
|
color="primary"
|
||||||
|
component={Link}
|
||||||
|
href="/dashboard/profile"
|
||||||
|
fullWidth
|
||||||
|
sx={{ mb: 1 }}
|
||||||
|
>
|
||||||
|
Ver Perfil Completo
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
onClick={logout}
|
onClick={logout}
|
||||||
fullWidth
|
fullWidth
|
||||||
>
|
>
|
||||||
Sair
|
Sair
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
|
||||||
</Menu>
|
</Menu>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Profile;
|
export default Profile;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,185 +0,0 @@
|
||||||
// Notifications dropdown
|
|
||||||
|
|
||||||
interface NotificationType {
|
|
||||||
id: string;
|
|
||||||
avatar: string;
|
|
||||||
title: string;
|
|
||||||
subtitle: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const notifications: NotificationType[] = [
|
|
||||||
{
|
|
||||||
id: '1',
|
|
||||||
avatar: '/images/profile/user-2.jpg',
|
|
||||||
title: 'Roman Joined the Team!',
|
|
||||||
subtitle: 'Congratulate him',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '2',
|
|
||||||
avatar: '/images/profile/user-3.jpg',
|
|
||||||
title: 'New message received',
|
|
||||||
subtitle: 'Salma sent you new message',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '3',
|
|
||||||
avatar: '/images/profile/user-4.jpg',
|
|
||||||
title: 'New Payment received',
|
|
||||||
subtitle: 'Check your earnings',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '4',
|
|
||||||
avatar: '/images/profile/user-5.jpg',
|
|
||||||
title: 'Jolly completed tasks',
|
|
||||||
subtitle: 'Assign her new tasks',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '5',
|
|
||||||
avatar: '/images/profile/user-6.jpg',
|
|
||||||
title: 'Roman Joined the Team!',
|
|
||||||
subtitle: 'Congratulate him',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '6',
|
|
||||||
avatar: '/images/profile/user-7.jpg',
|
|
||||||
title: 'New message received',
|
|
||||||
subtitle: 'Salma sent you new message',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '7',
|
|
||||||
avatar: '/images/profile/user-8.jpg',
|
|
||||||
title: 'New Payment received',
|
|
||||||
subtitle: 'Check your earnings',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '8',
|
|
||||||
avatar: '/images/profile/user-9.jpg',
|
|
||||||
title: 'Jolly completed tasks',
|
|
||||||
subtitle: 'Assign her new tasks',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
//
|
|
||||||
// Profile dropdown
|
|
||||||
//
|
|
||||||
interface ProfileType {
|
|
||||||
href: string;
|
|
||||||
title: string;
|
|
||||||
subtitle: string;
|
|
||||||
icon: any;
|
|
||||||
}
|
|
||||||
const profile: ProfileType[] = [
|
|
||||||
{
|
|
||||||
href: '/dashboard/profile',
|
|
||||||
title: 'My Profile',
|
|
||||||
subtitle: 'Account Settings',
|
|
||||||
icon: '/images/svgs/icon-account.svg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: '/apps/email',
|
|
||||||
title: 'My Inbox',
|
|
||||||
subtitle: 'Messages & Emails',
|
|
||||||
icon: '/images/svgs/icon-inbox.svg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: '/apps/notes',
|
|
||||||
title: 'My Tasks',
|
|
||||||
subtitle: 'To-do and Daily Tasks',
|
|
||||||
icon: '/images/svgs/icon-tasks.svg',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
// apps dropdown
|
|
||||||
|
|
||||||
interface AppsLinkType {
|
|
||||||
href: string;
|
|
||||||
title: string;
|
|
||||||
subtext: string;
|
|
||||||
avatar: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const appsLink: AppsLinkType[] = [
|
|
||||||
{
|
|
||||||
href: '/apps/chats',
|
|
||||||
title: 'Chat Application',
|
|
||||||
subtext: 'New messages arrived',
|
|
||||||
avatar: '/images/svgs/icon-dd-chat.svg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: '/apps/ecommerce/shop',
|
|
||||||
title: 'eCommerce App',
|
|
||||||
subtext: 'New stock available',
|
|
||||||
avatar: '/images/svgs/icon-dd-cart.svg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: '/apps/notes',
|
|
||||||
title: 'Notes App',
|
|
||||||
subtext: 'To-do and Daily tasks',
|
|
||||||
avatar: '/images/svgs/icon-dd-invoice.svg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: '/apps/contacts',
|
|
||||||
title: 'Contact Application',
|
|
||||||
subtext: '2 Unsaved Contacts',
|
|
||||||
avatar: '/images/svgs/icon-dd-mobile.svg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: '/apps/tickets',
|
|
||||||
title: 'Tickets App',
|
|
||||||
subtext: 'Submit tickets',
|
|
||||||
avatar: '/images/svgs/icon-dd-lifebuoy.svg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: '/apps/email',
|
|
||||||
title: 'Email App',
|
|
||||||
subtext: 'Get new emails',
|
|
||||||
avatar: '/images/svgs/icon-dd-message-box.svg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: '/apps/blog/post',
|
|
||||||
title: 'Blog App',
|
|
||||||
subtext: 'added new blog',
|
|
||||||
avatar: '/images/svgs/icon-dd-application.svg',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
interface LinkType {
|
|
||||||
href: string;
|
|
||||||
title: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const pageLinks: LinkType[] = [
|
|
||||||
{
|
|
||||||
href: '/theme-pages/pricing',
|
|
||||||
title: 'Pricing Page',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: '/auth/auth1/login',
|
|
||||||
title: 'Authentication Design',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: '/auth/auth1/register',
|
|
||||||
title: 'Register Now',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: '/404',
|
|
||||||
title: '404 Error Page',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: '/apps/note',
|
|
||||||
title: 'Notes App',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: '/apps/user-profile/profile',
|
|
||||||
title: 'User Application',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: '/apps/blog/post',
|
|
||||||
title: 'Blog Design',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: '/apps/ecommerce/checkout',
|
|
||||||
title: 'Shopping Cart',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export { notifications, profile, pageLinks, appsLink };
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useAuthStore } from '../store/useAuthStore';
|
import { useAuthStore } from '../store/useAuthStore';
|
||||||
import { loginService } from '../services/login.service';
|
import { loginService } from '../services/login.service';
|
||||||
import { profileService } from '../../profile/services/profile.service';
|
import { profileService } from '../../profile/services/profile.service';
|
||||||
import { clearAuthData } from '../utils/tokenRefresh';
|
import { clearAuthData } from '../utils/tokenRefresh';
|
||||||
import { mapToSafeProfile } from '../utils/mappers';
|
import { mapToSafeProfile } from '../utils/mappers';
|
||||||
|
import { COLABORADOR_ATUAL_QUERY_KEY } from '../../profile';
|
||||||
|
|
||||||
export function useAuth() {
|
export function useAuth() {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
@ -20,7 +21,7 @@ export function useAuth() {
|
||||||
const safeProfile = mapToSafeProfile(profile);
|
const safeProfile = mapToSafeProfile(profile);
|
||||||
|
|
||||||
setUser(safeProfile);
|
setUser(safeProfile);
|
||||||
queryClient.setQueryData(['auth-me'], safeProfile);
|
queryClient.setQueryData(COLABORADOR_ATUAL_QUERY_KEY, profile);
|
||||||
|
|
||||||
router.push('/dashboard');
|
router.push('/dashboard');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -30,19 +31,6 @@ export function useAuth() {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const useMe = () =>
|
|
||||||
useQuery({
|
|
||||||
queryKey: ['auth-me'],
|
|
||||||
queryFn: async () => {
|
|
||||||
const data = await profileService.obterColaboradorAtual();
|
|
||||||
const safeData = mapToSafeProfile(data);
|
|
||||||
setUser(safeData);
|
|
||||||
return safeData;
|
|
||||||
},
|
|
||||||
retry: false,
|
|
||||||
staleTime: Infinity,
|
|
||||||
});
|
|
||||||
|
|
||||||
const logout = async () => {
|
const logout = async () => {
|
||||||
try {
|
try {
|
||||||
await loginService.logout();
|
await loginService.logout();
|
||||||
|
|
@ -54,5 +42,5 @@ export function useAuth() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return { loginMutation, useMe, logout };
|
return { loginMutation, logout };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,21 +9,10 @@ import CircularProgress from '@mui/material/CircularProgress';
|
||||||
import Alert from '@mui/material/Alert';
|
import Alert from '@mui/material/Alert';
|
||||||
import Avatar from '@mui/material/Avatar';
|
import Avatar from '@mui/material/Avatar';
|
||||||
import Chip from '@mui/material/Chip';
|
import Chip from '@mui/material/Chip';
|
||||||
import { useAuthStore } from '../../login/store/useAuthStore';
|
import { useColaboradorAtual } from '../hooks/useColaboradorAtual';
|
||||||
import { useAuth } from '../../login/hooks/useAuth';
|
|
||||||
import { Colaborador } from '../domain/Colaborador';
|
|
||||||
|
|
||||||
export default function ProfilePage() {
|
export default function ProfilePage() {
|
||||||
const { useMe } = useAuth();
|
const { data: colaborador, isLoading, error } = useColaboradorAtual();
|
||||||
const { data: colaborador, isLoading, error } = useMe();
|
|
||||||
const user = useAuthStore((s) => s.user);
|
|
||||||
|
|
||||||
// Converte o DTO para a entidade de domínio Colaborador
|
|
||||||
const displayData: Colaborador | null = colaborador
|
|
||||||
? Colaborador.criarAPartirDoDto(colaborador)
|
|
||||||
: user
|
|
||||||
? Colaborador.criarAPartirDoDto(user)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
|
|
@ -44,7 +33,7 @@ export default function ProfilePage() {
|
||||||
return <Alert severity="error">Erro ao carregar dados do perfil</Alert>;
|
return <Alert severity="error">Erro ao carregar dados do perfil</Alert>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!displayData) {
|
if (!colaborador) {
|
||||||
return <Alert severity="warning">Nenhum dado de perfil disponível</Alert>;
|
return <Alert severity="warning">Nenhum dado de perfil disponível</Alert>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,22 +52,22 @@ export default function ProfilePage() {
|
||||||
fontSize: '1.5rem',
|
fontSize: '1.5rem',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{displayData.iniciais}
|
{colaborador.iniciais}
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<Box>
|
<Box>
|
||||||
<Typography variant="h5" fontWeight="600">
|
<Typography variant="h5" fontWeight="600">
|
||||||
{displayData.nome}
|
{colaborador.nome}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2" color="textSecondary">
|
<Typography variant="body2" color="textSecondary">
|
||||||
{displayData.nomeComFilial}
|
{colaborador.nomeComFilial}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Box sx={{ mt: 1, display: 'flex', gap: 1 }}>
|
<Box sx={{ mt: 1, display: 'flex', gap: 1 }}>
|
||||||
{displayData.ehRepresentanteComercial && (
|
{colaborador.ehRepresentanteComercial && (
|
||||||
<Chip label="RCA" color="primary" size="small" />
|
<Chip label="RCA" color="primary" size="small" />
|
||||||
)}
|
)}
|
||||||
{displayData.podeAplicarDesconto && (
|
{colaborador.podeAplicarDesconto && (
|
||||||
<Chip
|
<Chip
|
||||||
label={`${displayData.percentualDesconto}% desconto`}
|
label={`${colaborador.percentualDesconto}% desconto`}
|
||||||
color="success"
|
color="success"
|
||||||
size="small"
|
size="small"
|
||||||
/>
|
/>
|
||||||
|
|
@ -103,7 +92,7 @@ export default function ProfilePage() {
|
||||||
Nome
|
Nome
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body1" fontWeight="500">
|
<Typography variant="body1" fontWeight="500">
|
||||||
{displayData.nome || '-'}
|
{colaborador.nome || '-'}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Box>
|
<Box>
|
||||||
|
|
@ -111,7 +100,7 @@ export default function ProfilePage() {
|
||||||
Usuário
|
Usuário
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body1" fontWeight="500">
|
<Typography variant="body1" fontWeight="500">
|
||||||
{displayData.userName || '-'}
|
{colaborador.userName || '-'}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Box>
|
<Box>
|
||||||
|
|
@ -119,7 +108,7 @@ export default function ProfilePage() {
|
||||||
Matrícula
|
Matrícula
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body1" fontWeight="500">
|
<Typography variant="body1" fontWeight="500">
|
||||||
{displayData.matricula || '-'}
|
{colaborador.matricula || '-'}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
@ -140,7 +129,7 @@ export default function ProfilePage() {
|
||||||
Filial
|
Filial
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body1" fontWeight="500">
|
<Typography variant="body1" fontWeight="500">
|
||||||
{displayData.nomeFilial || '-'} ({displayData.codigoFilial || '-'})
|
{colaborador.nomeFilial || '-'} ({colaborador.codigoFilial || '-'})
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Box>
|
<Box>
|
||||||
|
|
@ -148,16 +137,16 @@ export default function ProfilePage() {
|
||||||
RCA
|
RCA
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body1" fontWeight="500">
|
<Typography variant="body1" fontWeight="500">
|
||||||
{displayData.ehRepresentanteComercial ? displayData.codigoRCA : 'Não é vendedor'}
|
{colaborador.ehRepresentanteComercial ? colaborador.codigoRCA : 'Não é vendedor'}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
{displayData.podeAplicarDesconto && (
|
{colaborador.podeAplicarDesconto && (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography variant="body2" color="textSecondary">
|
<Typography variant="body2" color="textSecondary">
|
||||||
Desconto Disponível
|
Desconto Disponível
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body1" fontWeight="500">
|
<Typography variant="body1" fontWeight="500">
|
||||||
{displayData.percentualDesconto}%
|
{colaborador.percentualDesconto}%
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
@ -167,8 +156,8 @@ export default function ProfilePage() {
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
{/* Informações Adicionais */}
|
{/* Informações Adicionais */}
|
||||||
{(displayData.codigoSetor !== undefined ||
|
{(colaborador.codigoSetor !== undefined ||
|
||||||
displayData.codigoSupervisor !== undefined) && (
|
colaborador.codigoSupervisor !== undefined) && (
|
||||||
<Grid size={{ xs: 12 }}>
|
<Grid size={{ xs: 12 }}>
|
||||||
<Card>
|
<Card>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
|
|
@ -176,23 +165,23 @@ export default function ProfilePage() {
|
||||||
Informações Adicionais
|
Informações Adicionais
|
||||||
</Typography>
|
</Typography>
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
{displayData.codigoSetor !== undefined && (
|
{colaborador.codigoSetor !== undefined && (
|
||||||
<Grid size={{ xs: 12, sm: 4 }}>
|
<Grid size={{ xs: 12, sm: 4 }}>
|
||||||
<Typography variant="body2" color="textSecondary">
|
<Typography variant="body2" color="textSecondary">
|
||||||
Setor
|
Setor
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body1" fontWeight="500">
|
<Typography variant="body1" fontWeight="500">
|
||||||
{displayData.codigoSetor}
|
{colaborador.codigoSetor}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
{displayData.codigoSupervisor !== undefined && (
|
{colaborador.codigoSupervisor !== undefined && (
|
||||||
<Grid size={{ xs: 12, sm: 4 }}>
|
<Grid size={{ xs: 12, sm: 4 }}>
|
||||||
<Typography variant="body2" color="textSecondary">
|
<Typography variant="body2" color="textSecondary">
|
||||||
Supervisor
|
Supervisor
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body1" fontWeight="500">
|
<Typography variant="body1" fontWeight="500">
|
||||||
{displayData.codigoSupervisor}
|
{colaborador.codigoSupervisor}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
|
|
@ -204,3 +193,4 @@ export default function ProfilePage() {
|
||||||
</Grid>
|
</Grid>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { useQuery, UseQueryResult } from '@tanstack/react-query';
|
||||||
|
import { profileService } from '../services/profile.service';
|
||||||
|
import { Colaborador } from '../domain/Colaborador';
|
||||||
|
|
||||||
|
export const COLABORADOR_ATUAL_QUERY_KEY = ['colaborador-atual'] as const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook para obter o colaborador atualmente autenticado.
|
||||||
|
* Encapsula a lógica de busca e cache do perfil do usuário,
|
||||||
|
* desacoplando essa responsabilidade do módulo de login.
|
||||||
|
*/
|
||||||
|
export function useColaboradorAtual(): UseQueryResult<Colaborador> {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: COLABORADOR_ATUAL_QUERY_KEY,
|
||||||
|
queryFn: () => profileService.obterColaboradorAtual(),
|
||||||
|
retry: false,
|
||||||
|
staleTime: Infinity,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -2,3 +2,4 @@
|
||||||
export { default as ProfilePage } from './components/ProfilePage';
|
export { default as ProfilePage } from './components/ProfilePage';
|
||||||
export type { UserProfileDto } from './types';
|
export type { UserProfileDto } from './types';
|
||||||
export { Colaborador } from './domain/Colaborador';
|
export { Colaborador } from './domain/Colaborador';
|
||||||
|
export { useColaboradorAtual, COLABORADOR_ATUAL_QUERY_KEY } from './hooks/useColaboradorAtual';
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue