diff --git a/src/features/dashboard/header/AppLinks.tsx b/src/features/dashboard/header/AppLinks.tsx deleted file mode 100644 index 80f8e8f..0000000 --- a/src/features/dashboard/header/AppLinks.tsx +++ /dev/null @@ -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 ( - - {dropdownData.appsLink.map((links) => ( - - - - - - - - - {links.title} - - - {links.subtext} - - - - - - ))} - - ); -}; - -export default AppLinks; diff --git a/src/features/dashboard/header/Header.tsx b/src/features/dashboard/header/Header.tsx index 1857583..16cee51 100644 --- a/src/features/dashboard/header/Header.tsx +++ b/src/features/dashboard/header/Header.tsx @@ -12,11 +12,8 @@ import DarkModeIcon from '@mui/icons-material/DarkMode'; import LightModeIcon from '@mui/icons-material/LightMode'; import { useCustomizerStore } from '../store/useCustomizerStore'; -import Notifications from './Notification'; import Profile from './Profile'; import Search from './Search'; -import Navigation from './Navigation'; -import MobileRightSidebar from './MobileRightSidebar'; const AppBarStyled = styled(AppBar)(({ theme }) => ({ boxShadow: 'none', @@ -33,7 +30,6 @@ const ToolbarStyled = styled(Toolbar)(({ theme }) => ({ const Header = () => { const lgUp = useMediaQuery((theme: Theme) => theme.breakpoints.up('lg')); - const lgDown = useMediaQuery((theme: Theme) => theme.breakpoints.down('lg')); const { activeMode, @@ -51,7 +47,7 @@ const Header = () => { {/* ------------------------------------------- */} - {/* Toggle Button Sidebar (Fluxo 2) */} + {/* Toggle Button Sidebar */} {/* ------------------------------------------- */} { {/* ------------------------------------------- */} - {/* Search & Navigation */} + {/* Search */} {/* ------------------------------------------- */} - {lgUp && } @@ -84,12 +79,9 @@ const Header = () => { {activeMode === 'light' ? : } - - {/* ------------------------------------------- */} - {/* Mobile Right Sidebar & Profile */} + {/* Profile */} {/* ------------------------------------------- */} - {lgDown && } @@ -98,3 +90,4 @@ const Header = () => { }; export default Header; + diff --git a/src/features/dashboard/header/MobileRightSidebar.tsx b/src/features/dashboard/header/MobileRightSidebar.tsx deleted file mode 100644 index b165d4a..0000000 --- a/src/features/dashboard/header/MobileRightSidebar.tsx +++ /dev/null @@ -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 = ( - - {/* ------------------------------------------- */} - {/* Apps Content */} - {/* ------------------------------------------- */} - - - - - - - - - Chats - - - - - - - - - - Email - - - - - - - - - - Apps - - - {open ? ( - - ) : ( - - )} - - - - - - - - - - - - ); - - return ( - - setShowDrawer(true)} - sx={{ - ...(showDrawer && { - color: 'primary.main', - }), - }} - > - - - {/* ------------------------------------------- */} - {/* Cart Sidebar */} - {/* ------------------------------------------- */} - setShowDrawer(false)} - PaperProps={{ sx: { width: '300px' } }} - > - - - Navigation - - - - {/* component */} - {cartContent} - - - ); -}; - -export default MobileRightSidebar; diff --git a/src/features/dashboard/header/Navigation.tsx b/src/features/dashboard/header/Navigation.tsx deleted file mode 100644 index e371d42..0000000 --- a/src/features/dashboard/header/Navigation.tsx +++ /dev/null @@ -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 ( - <> - - - {/* ------------------------------------------- */} - {/* Message Dropdown */} - {/* ------------------------------------------- */} - - - - - - - - - - - Frequently Asked Questions - - - - - - - - - - - - - - - - - ); -}; - -export default AppDD; diff --git a/src/features/dashboard/header/Notification.tsx b/src/features/dashboard/header/Notification.tsx deleted file mode 100644 index 89d49e1..0000000 --- a/src/features/dashboard/header/Notification.tsx +++ /dev/null @@ -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 ( - - - - - - - {/* ------------------------------------------- */} - {/* Message Dropdown */} - {/* ------------------------------------------- */} - - - Notifications - - - - {dropdownData.notifications.map((notification) => ( - - - - - - - {notification.title} - - - {notification.subtitle} - - - - - - ))} - - - - - - - ); -}; - -export default Notifications; diff --git a/src/features/dashboard/header/Profile.tsx b/src/features/dashboard/header/Profile.tsx index b8f4aee..0d8394d 100644 --- a/src/features/dashboard/header/Profile.tsx +++ b/src/features/dashboard/header/Profile.tsx @@ -5,11 +5,9 @@ import { Menu, Avatar, Typography, - Divider, Button, IconButton, } from '@mui/material'; -import { IconMail } from '@tabler/icons-react'; import { Stack } from '@mui/system'; import { useAuthStore } from '../../login/store/useAuthStore'; @@ -27,10 +25,18 @@ const Profile = () => { 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 ( { bgcolor: 'primary.main', }} > - {user?.nome?.[0] || user?.userName?.[0] || 'U'} + {getIniciais()} {/* ------------------------------------------- */} - {/* Message Dropdown */} + {/* Profile Dropdown */} {/* ------------------------------------------- */} { transformOrigin={{ horizontal: 'right', vertical: 'top' }} sx={{ '& .MuiMenu-paper': { - width: '360px', - p: 4, + width: '320px', + p: 3, }, }} > - User Profile - + + Meu Perfil + + - {user?.nome?.[0] || user?.userName?.[0] || 'U'} + {getIniciais()} { > {user?.nome || user?.userName || 'Usuário'} - - {user?.nomeFilial || 'Sem filial'} + + {user?.nomeFilial || '-'} - - - {user?.rca ? `RCA: ${user.rca}` : 'Sem e-mail'} + + Matrícula: {user?.matricula || '-'} - - - + + ); }; export default Profile; + diff --git a/src/features/dashboard/header/data.ts b/src/features/dashboard/header/data.ts deleted file mode 100644 index 8383eb9..0000000 --- a/src/features/dashboard/header/data.ts +++ /dev/null @@ -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 }; diff --git a/src/features/login/hooks/useAuth.ts b/src/features/login/hooks/useAuth.ts index 07f38ab..6c2a213 100644 --- a/src/features/login/hooks/useAuth.ts +++ b/src/features/login/hooks/useAuth.ts @@ -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 { useAuthStore } from '../store/useAuthStore'; import { loginService } from '../services/login.service'; import { profileService } from '../../profile/services/profile.service'; import { clearAuthData } from '../utils/tokenRefresh'; import { mapToSafeProfile } from '../utils/mappers'; +import { COLABORADOR_ATUAL_QUERY_KEY } from '../../profile'; export function useAuth() { const queryClient = useQueryClient(); @@ -20,7 +21,7 @@ export function useAuth() { const safeProfile = mapToSafeProfile(profile); setUser(safeProfile); - queryClient.setQueryData(['auth-me'], safeProfile); + queryClient.setQueryData(COLABORADOR_ATUAL_QUERY_KEY, profile); router.push('/dashboard'); } 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 () => { try { await loginService.logout(); @@ -54,5 +42,5 @@ export function useAuth() { } }; - return { loginMutation, useMe, logout }; + return { loginMutation, logout }; } diff --git a/src/features/profile/components/ProfilePage.tsx b/src/features/profile/components/ProfilePage.tsx index b1a9b89..507cc2c 100644 --- a/src/features/profile/components/ProfilePage.tsx +++ b/src/features/profile/components/ProfilePage.tsx @@ -9,21 +9,10 @@ import CircularProgress from '@mui/material/CircularProgress'; import Alert from '@mui/material/Alert'; import Avatar from '@mui/material/Avatar'; import Chip from '@mui/material/Chip'; -import { useAuthStore } from '../../login/store/useAuthStore'; -import { useAuth } from '../../login/hooks/useAuth'; -import { Colaborador } from '../domain/Colaborador'; +import { useColaboradorAtual } from '../hooks/useColaboradorAtual'; export default function ProfilePage() { - const { useMe } = useAuth(); - 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; + const { data: colaborador, isLoading, error } = useColaboradorAtual(); if (isLoading) { return ( @@ -44,7 +33,7 @@ export default function ProfilePage() { return Erro ao carregar dados do perfil; } - if (!displayData) { + if (!colaborador) { return Nenhum dado de perfil disponível; } @@ -63,22 +52,22 @@ export default function ProfilePage() { fontSize: '1.5rem', }} > - {displayData.iniciais} + {colaborador.iniciais} - {displayData.nome} + {colaborador.nome} - {displayData.nomeComFilial} + {colaborador.nomeComFilial} - {displayData.ehRepresentanteComercial && ( + {colaborador.ehRepresentanteComercial && ( )} - {displayData.podeAplicarDesconto && ( + {colaborador.podeAplicarDesconto && ( @@ -103,7 +92,7 @@ export default function ProfilePage() { Nome - {displayData.nome || '-'} + {colaborador.nome || '-'} @@ -111,7 +100,7 @@ export default function ProfilePage() { Usuário - {displayData.userName || '-'} + {colaborador.userName || '-'} @@ -119,7 +108,7 @@ export default function ProfilePage() { Matrícula - {displayData.matricula || '-'} + {colaborador.matricula || '-'} @@ -140,7 +129,7 @@ export default function ProfilePage() { Filial - {displayData.nomeFilial || '-'} ({displayData.codigoFilial || '-'}) + {colaborador.nomeFilial || '-'} ({colaborador.codigoFilial || '-'}) @@ -148,16 +137,16 @@ export default function ProfilePage() { RCA - {displayData.ehRepresentanteComercial ? displayData.codigoRCA : 'Não é vendedor'} + {colaborador.ehRepresentanteComercial ? colaborador.codigoRCA : 'Não é vendedor'} - {displayData.podeAplicarDesconto && ( + {colaborador.podeAplicarDesconto && ( Desconto Disponível - {displayData.percentualDesconto}% + {colaborador.percentualDesconto}% )} @@ -167,8 +156,8 @@ export default function ProfilePage() { {/* Informações Adicionais */} - {(displayData.codigoSetor !== undefined || - displayData.codigoSupervisor !== undefined) && ( + {(colaborador.codigoSetor !== undefined || + colaborador.codigoSupervisor !== undefined) && ( @@ -176,23 +165,23 @@ export default function ProfilePage() { Informações Adicionais - {displayData.codigoSetor !== undefined && ( + {colaborador.codigoSetor !== undefined && ( Setor - {displayData.codigoSetor} + {colaborador.codigoSetor} )} - {displayData.codigoSupervisor !== undefined && ( + {colaborador.codigoSupervisor !== undefined && ( Supervisor - {displayData.codigoSupervisor} + {colaborador.codigoSupervisor} )} @@ -204,3 +193,4 @@ export default function ProfilePage() { ); } + diff --git a/src/features/profile/hooks/useColaboradorAtual.ts b/src/features/profile/hooks/useColaboradorAtual.ts new file mode 100644 index 0000000..c5d940a --- /dev/null +++ b/src/features/profile/hooks/useColaboradorAtual.ts @@ -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 { + return useQuery({ + queryKey: COLABORADOR_ATUAL_QUERY_KEY, + queryFn: () => profileService.obterColaboradorAtual(), + retry: false, + staleTime: Infinity, + }); +} diff --git a/src/features/profile/index.ts b/src/features/profile/index.ts index eaf7d14..59bdeb7 100644 --- a/src/features/profile/index.ts +++ b/src/features/profile/index.ts @@ -2,3 +2,4 @@ export { default as ProfilePage } from './components/ProfilePage'; export type { UserProfileDto } from './types'; export { Colaborador } from './domain/Colaborador'; +export { useColaboradorAtual, COLABORADOR_ATUAL_QUERY_KEY } from './hooks/useColaboradorAtual';