FR-6.1/6.2: Sandra recebe push quando pedido entra em pending_approval; Rafael recebe quando pedido é aprovado ou recusado. Service worker registrado em background (PWA-ready via public/sw.js). FR-6.3: Badge na Topbar busca GET /notifications/pending-count (supervisores veem count de pending_approval; reps veem 0). Intervalo de 30s. FR-6.4: Botão Compartilhar no OrderDetailPage para pedidos approved/invoiced (apenas reps). Usa navigator.share() com texto formatado para WhatsApp. Infra: modelo PushSubscription (Prisma), NotificationsModule (subscribe/ unsubscribe/pending-count + PushService VAPID), VAPID keys em .env, integração no OrdersService (create → supervisores, approve/reject → repId). Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
55 lines
1.5 KiB
TypeScript
55 lines
1.5 KiB
TypeScript
import { StrictMode, useState } from 'react';
|
|
import { createRoot } from 'react-dom/client';
|
|
import { ConfigProvider, App as AntdApp } from 'antd';
|
|
import ptBR from 'antd/locale/pt_BR';
|
|
import { QueryClientProvider } from '@tanstack/react-query';
|
|
import { RouterProvider } from '@tanstack/react-router';
|
|
import dayjs from 'dayjs';
|
|
import 'dayjs/locale/pt-br';
|
|
|
|
import './styles/global.css';
|
|
|
|
import { sarTheme } from './lib/theme';
|
|
import { queryClient } from './lib/query-client';
|
|
import { router } from './lib/router';
|
|
import { authStore } from './lib/auth-store';
|
|
import { DevLogin } from './components/dev/DevLogin';
|
|
|
|
dayjs.locale('pt-br');
|
|
|
|
if ('serviceWorker' in navigator) {
|
|
navigator.serviceWorker.register('/sw.js').catch(() => {
|
|
// SW é opt-in — falha silenciosa não impede o app
|
|
});
|
|
}
|
|
|
|
const isDev = import.meta.env.DEV;
|
|
|
|
function Root() {
|
|
const [hasToken, setHasToken] = useState(() => !!authStore.get());
|
|
|
|
// Em dev, exibe DevLogin se não houver token. Em prod, fluxo de auth real virá aqui.
|
|
if (isDev && !hasToken) {
|
|
return <DevLogin onLogin={() => setHasToken(true)} />;
|
|
}
|
|
|
|
return <RouterProvider router={router} />;
|
|
}
|
|
|
|
const rootEl = document.getElementById('root');
|
|
if (!rootEl) {
|
|
throw new Error('Root element not found');
|
|
}
|
|
|
|
createRoot(rootEl).render(
|
|
<StrictMode>
|
|
<ConfigProvider theme={sarTheme} locale={ptBR} componentSize="middle">
|
|
<AntdApp>
|
|
<QueryClientProvider client={queryClient}>
|
|
<Root />
|
|
</QueryClientProvider>
|
|
</AntdApp>
|
|
</ConfigProvider>
|
|
</StrictMode>,
|
|
);
|