Projeto bot pontos
This commit is contained in:
79
web/app/(painel)/page.tsx
Normal file
79
web/app/(painel)/page.tsx
Normal file
@@ -0,0 +1,79 @@
|
||||
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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user