feat(settings): aba de diagnóstico e cópia de user ID no menu do usuário

- Nova aba "Diagnóstico" em Settings com:
  - Identidade: user ID (copiável), nome, e-mail
  - Sessão: criada em / expira em
  - Aplicação: versão, NODE_ENV, build SHA (se definido)
  - Configuração do servidor: S3, e-mail e domínio público — apenas booleans, sem expor credenciais
  - Saúde: status e latência do banco de dados
  - Uso: contagem de lançamentos, anexos, anotações e itens no inbox
- Botão de cópia do user ID no dropdown do avatar (ao lado do e-mail)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Felipe Coutinho
2026-04-11 18:06:40 +00:00
parent 9ecafdb15f
commit 5f7bfb98da
4 changed files with 368 additions and 6 deletions

View File

@@ -5,6 +5,8 @@ import { connection } from "next/server";
import { CompanionTab } from "@/features/settings/components/companion-tab";
import { DeleteAccountForm } from "@/features/settings/components/delete-account-form";
import { DiagnosticsTab } from "@/features/settings/components/diagnostics-tab";
import { fetchDiagnosticsData } from "@/features/settings/diagnostics-queries";
import { PasskeysForm } from "@/features/settings/components/passkeys-form";
import { PreferencesForm } from "@/features/settings/components/preferences-form";
import { UpdateEmailForm } from "@/features/settings/components/update-email-form";
@@ -37,6 +39,19 @@ export default async function Page() {
const { authProvider, userPreferences, userApiTokens } =
await fetchSettingsPageData(session.user.id);
const diagnosticsData = await fetchDiagnosticsData(
session.user.id,
{
id: session.user.id,
name: session.user.name ?? "",
email: session.user.email ?? "",
},
{
createdAt: session.session.createdAt,
expiresAt: session.session.expiresAt,
},
);
return (
<div className="w-full">
<Tabs defaultValue="preferencias" className="w-full">
@@ -50,6 +65,7 @@ export default async function Page() {
<TabsTrigger value="senha">Alterar senha</TabsTrigger>
<TabsTrigger value="passkeys">Passkeys</TabsTrigger>
<TabsTrigger value="email">Alterar e-mail</TabsTrigger>
<TabsTrigger value="diagnostico">Diagnóstico</TabsTrigger>
<TabsTrigger value="deletar" className="text-destructive">
Deletar conta
</TabsTrigger>
@@ -180,13 +196,27 @@ export default async function Page() {
</Card>
</TabsContent>
<TabsContent value="diagnostico" className="mt-4">
<Card className="p-6">
<div className="space-y-4">
<div>
<h2 className="text-xl font-semibold mb-1">Diagnóstico</h2>
<p className="text-sm text-muted-foreground">
Informações técnicas sobre sua conta, sessão e estado do
servidor. Nenhuma credencial ou dado sensível é exibido.
</p>
</div>
<Separator />
<DiagnosticsTab data={diagnosticsData} />
</div>
</Card>
</TabsContent>
<TabsContent value="deletar" className="mt-4">
<Card className="p-6">
<div className="space-y-4">
<div>
<h2 className="text-xl font-semibold mb-1 text-destructive">
Ações perigosas
</h2>
<h2 className="text-xl font-semibold mb-1">Ações perigosas</h2>
<p className="text-sm text-muted-foreground">
Você pode zerar os dados do OpenMonetis e manter seu acesso,
ou excluir sua conta inteira de forma irreversível.