feat(frontend): app shell + login + platform dashboard + billing tarifas
Primeiro commit do frontend Next.js (agente.md secao 161-176): login split-brand, dashboard "Visão Geral da Plataforma" com instrumentos ao vivo, e a tela Billing > Tarifas (price books + rate decks) completa — listagem com busca/ordenacao, criacao com itens/entradas dinamicos via Server Actions, detalhe — ponta a ponta contra a API real de billing (fase 22). Corrige de quebra 2 bugs reais achados construindo Tarifas: a topbar tinha o titulo fixo "Visao Geral" em toda pagina, e a sidebar fixa de 256px nao tinha nenhuma versao mobile (conteudo espremido em ~130px) — agora vira drawer via Radix Dialog abaixo de lg, com titulo/descricao da topbar resolvidos dinamicamente por rota. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EWHKmcVJtstQFErbZ1AanY
This commit is contained in:
38
apps/frontend/src/app/api/login/route.ts
Normal file
38
apps/frontend/src/app/api/login/route.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { API_BASE_URL } from "@/lib/api";
|
||||
import { sessionCookieName } from "@/lib/session";
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const { email, password } = await request.json();
|
||||
|
||||
const res = await fetch(`${API_BASE_URL}/auth/login`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ email, password }),
|
||||
cache: "no-store",
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
const body = await res.json().catch(() => ({ message: "Falha ao entrar" }));
|
||||
return NextResponse.json({ message: body.message ?? "Falha ao entrar" }, { status: res.status });
|
||||
}
|
||||
|
||||
const data = await res.json();
|
||||
|
||||
if (data.mustChangePassword) {
|
||||
return NextResponse.json(
|
||||
{ message: "Senha precisa ser trocada antes do primeiro acesso (use a API /auth/change-password por enquanto)." },
|
||||
{ status: 403 },
|
||||
);
|
||||
}
|
||||
|
||||
const response = NextResponse.json({ ok: true });
|
||||
response.cookies.set(sessionCookieName(), JSON.stringify({ accessToken: data.accessToken, refreshToken: data.refreshToken }), {
|
||||
httpOnly: true,
|
||||
sameSite: "lax",
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
path: "/",
|
||||
maxAge: 60 * 60 * 8,
|
||||
});
|
||||
return response;
|
||||
}
|
||||
Reference in New Issue
Block a user