Files
bot-pontos/web/app/(painel)/page.tsx
2026-10-23 22:31:02 -03:00

80 lines
3.1 KiB
TypeScript

import Link from "next/link";
import { apiGet } from "@/lib/server-api";
import { fmtDateTime, fmtDay, notificationStatusLabel } from "@/lib/format";
import { isRestricted } from "@/lib/access";
import type { Dashboard, Me } from "@/lib/types";
export default async function DashboardPage() {
const [d, me] = await Promise.all([apiGet<Dashboard>("/dashboard"), apiGet<Me>("/auth/me")]);
const users = d.users_by_status;
const restricted = isRestricted(me.account);
return (
<>
<h1>Início</h1>
{d.outage_since && (
<div className="alert error">
A PontoMais está fora do ar desde {fmtDateTime(d.outage_since)}. Ninguém foi pausado; os admins foram avisados
pelo Telegram.
</div>
)}
{d.holiday_fallback_day && (
<div className="alert warn">
Não foi possível obter os feriados deste ano: segunda a sexta estão valendo como dias úteis.{" "}
<Link href="/feriados">Ver feriados</Link>
</div>
)}
{!restricted && (
<section className="stats">
<Stat label="Aguardando aprovação" value={users.pending ?? 0} href="/usuarios?status=pending" />
<Stat label="Usuários ativos" value={users.active ?? 0} href="/usuarios?status=active" />
<Stat label="Com lembretes ligados" value={d.notifications_enabled} />
<Stat label="Pausados por falha na PontoMais" value={d.paused_by_api_failures} tone={d.paused_by_api_failures ? "error" : undefined} />
<Stat label="Falhas de envio (7 dias)" value={d.failed_last_7_days} href="/notificacoes?status=failed" tone={d.failed_last_7_days ? "error" : undefined} />
<Stat label="Expirados (7 dias)" value={d.expired_last_7_days} href="/notificacoes?status=expired" />
<Stat label="Janelas personalizadas" value={d.custom_windows} href="/usuarios?custom_window=true" />
</section>
)}
<section className="card">
<h2>Lembretes de hoje ({fmtDay(d.today)})</h2>
{Object.keys(d.today_by_status).length === 0 ? (
<p className="muted">Nenhum lembrete gerado hoje.</p>
) : (
<ul className="inline-list">
{Object.entries(d.today_by_status).map(([status, count]) => (
<li key={status}>
{restricted ? (
<span>
{notificationStatusLabel[status] ?? status}: <strong>{count}</strong>
</span>
) : (
<Link href={`/notificacoes?day=${d.today}&status=${status}`}>
{notificationStatusLabel[status] ?? status}: <strong>{count}</strong>
</Link>
)}
</li>
))}
</ul>
)}
</section>
</>
);
}
function Stat({ label, value, href, tone }: { label: string; value: number; href?: string; tone?: "error" }) {
const content = (
<>
<span className="stat-value">{value}</span>
<span className="stat-label">{label}</span>
</>
);
return (
<div className={`stat ${tone ?? ""}`}>
{href ? <Link href={href}>{content}</Link> : content}
</div>
);
}