Adiciona o frontend Next.js em frontend/ (setup, design system, autenticação/tema, layout/navegação, área master, área tenant completa: clientes, produtos, vendas, recebimentos, whatsapp, e-mail, alertas, equipe e perfil). Estende o backend de forma aditiva e autorizada: cookie httpOnly para refresh token (Etapa 13) e CRUD de equipe + edição de perfil do tenant (Etapa 18, módulo src/modules/equipe/ novo e PUT /tenant/perfil). Detalhes completos em Etapas/V2/*. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
66 lines
2.0 KiB
TypeScript
66 lines
2.0 KiB
TypeScript
'use client';
|
|
|
|
import { useEffect, useState } from 'react';
|
|
import { apiClient, ApiError } from '@/lib/api/client';
|
|
|
|
interface HealthStatus {
|
|
status: 'ok' | 'error';
|
|
timestamp: string;
|
|
database: 'up' | 'down';
|
|
}
|
|
|
|
type DiagnosticoState =
|
|
| { phase: 'loading' }
|
|
| { phase: 'success'; data: HealthStatus }
|
|
| { phase: 'error'; message: string };
|
|
|
|
/**
|
|
* Rota temporária para validar a integração frontend↔backend de ponta a
|
|
* ponta (Etapa 11). Pode ser removida quando não fizer mais falta.
|
|
*/
|
|
export default function DiagnosticoPage() {
|
|
const [state, setState] = useState<DiagnosticoState>({ phase: 'loading' });
|
|
|
|
useEffect(() => {
|
|
apiClient
|
|
.get<HealthStatus>('/health')
|
|
.then((data) => setState({ phase: 'success', data }))
|
|
.catch((err: unknown) => {
|
|
const message = err instanceof ApiError ? err.message : 'Falha ao conectar com a API.';
|
|
setState({ phase: 'error', message });
|
|
});
|
|
}, []);
|
|
|
|
return (
|
|
<main className="flex min-h-screen flex-col items-center justify-center gap-4 p-8">
|
|
<h1 className="text-xl font-semibold text-neutral-950">Diagnóstico de conexão com a API</h1>
|
|
|
|
{state.phase === 'loading' && <p className="text-neutral-500">Consultando GET /health…</p>}
|
|
|
|
{state.phase === 'success' && (
|
|
<div className="tabular-nums rounded-lg border border-neutral-200 bg-surface p-4 text-sm">
|
|
<p>
|
|
Status:{' '}
|
|
<span className={state.data.status === 'ok' ? 'text-success' : 'text-danger'}>
|
|
{state.data.status}
|
|
</span>
|
|
</p>
|
|
<p>
|
|
Banco de dados:{' '}
|
|
<span className={state.data.database === 'up' ? 'text-success' : 'text-danger'}>
|
|
{state.data.database}
|
|
</span>
|
|
</p>
|
|
<p>Timestamp: {state.data.timestamp}</p>
|
|
</div>
|
|
)}
|
|
|
|
{state.phase === 'error' && (
|
|
<p className="rounded-lg border border-danger bg-surface p-4 text-sm text-danger">
|
|
{state.message}
|
|
</p>
|
|
)}
|
|
</main>
|
|
);
|
|
}
|