feat(auth): endpoint /auth/me, cockpits renomeados e menu de logout

- GET /api/v1/auth/me retorna perfil real do ERP (vw_representantes)
- Contrato UserProfile adicionado ao shared api-interface
- Hook useCurrentUser() no frontend consome o endpoint
- Cockpit rafael → rep, sandra → supervisor (pastas e componentes)
- Topbar exibe iniciais do usuário e dropdown com nome, role e "Sair"
- Logout limpa token e recarrega para voltar ao DevLogin

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-29 17:48:24 +00:00
parent 20b0793227
commit a00a5c6a53
16 changed files with 156 additions and 33 deletions

View File

@@ -9,6 +9,7 @@ import { Link } from '@tanstack/react-router';
import type { PedidoSummary } from '@sar/api-interface';
import { SITUA_LABEL } from '@sar/api-interface';
import { useRepDashboard } from '../../lib/queries/dashboard';
import { useCurrentUser } from '../../lib/queries/auth';
const { Title, Text } = Typography;
@@ -37,8 +38,9 @@ function today(): string {
});
}
export function RafaelPainel() {
export function RepPainel() {
const { data, isLoading } = useRepDashboard();
const { data: user } = useCurrentUser();
if (isLoading || !data) {
return (
@@ -66,7 +68,7 @@ export function RafaelPainel() {
{/* Saudação */}
<Flex vertical gap={4}>
<Title level={2} style={{ margin: 0 }}>
{greeting()}, Rafael
{greeting()}, {user?.nome?.split(' ')[0] ?? '...'}
</Title>
<Text type="secondary" style={{ fontSize: 'var(--text-lg)' }}>
{today()}

View File

@@ -9,6 +9,7 @@ import {
import { Link } from '@tanstack/react-router';
import type { PedidoSummary } from '@sar/api-interface';
import { useSupervisorDashboard } from '../../lib/queries/dashboard';
import { useCurrentUser } from '../../lib/queries/auth';
const { Title, Text } = Typography;
@@ -26,6 +27,13 @@ function delta(current: number, previous: number): { label: string; positive: bo
return { label: `${pct >= 0 ? '+' : ''}${pct}% vs semana passada`, positive: pct >= 0 };
}
function greeting(): string {
const h = new Date().getHours();
if (h < 12) return 'Bom dia';
if (h < 18) return 'Boa tarde';
return 'Boa noite';
}
function today(): string {
return new Date().toLocaleDateString('pt-BR', { weekday: 'long', day: 'numeric', month: 'long' });
}
@@ -72,8 +80,9 @@ const queueColumns: TableColumnsType<PedidoSummary> = [
},
];
export function SandraPainel() {
export function SupervisorPainel() {
const { data, isLoading } = useSupervisorDashboard();
const { data: user } = useCurrentUser();
if (isLoading || !data) {
return (
@@ -100,7 +109,7 @@ export function SandraPainel() {
{/* Saudação */}
<Flex vertical gap={4}>
<Title level={2} style={{ margin: 0 }}>
Bom dia, Sandra
{greeting()}, {user?.nome?.split(' ')[0] ?? '...'}
</Title>
<Text type="secondary" style={{ fontSize: 'var(--text-lg)' }}>
{today()}