138 lines
5.2 KiB
TypeScript
138 lines
5.2 KiB
TypeScript
import Link from "next/link";
|
|
import { apiGet } from "@/lib/server-api";
|
|
import { badgeClass, dayStatusLabel, fmtDateTime, pauseReasonLabel, userStatusLabel } from "@/lib/format";
|
|
import { isRestricted } from "@/lib/access";
|
|
import type { Me, UserDetail } from "@/lib/types";
|
|
import { ActionButton } from "@/components/ActionButton";
|
|
import { CredentialsForm, ScheduleForm, TodayPanel } from "./forms";
|
|
|
|
export default async function UserPage({ params }: { params: Promise<{ id: string }> }) {
|
|
const { id } = await params;
|
|
const [detail, me] = await Promise.all([apiGet<UserDetail>(`/users/${id}`), apiGet<Me>("/auth/me")]);
|
|
const { user, credential, today } = detail;
|
|
const restricted = isRestricted(me.account);
|
|
const canAdmin = me.account.role !== "viewer";
|
|
// Conta de leitura ligada a este usuário também altera as próprias configurações.
|
|
const canEdit = canAdmin || me.account.user_id === user.id;
|
|
const base = `/users/${user.id}`;
|
|
|
|
return (
|
|
<>
|
|
{!restricted && (
|
|
<p>
|
|
<Link href="/usuarios">← Usuários</Link>
|
|
</p>
|
|
)}
|
|
<h1>
|
|
{user.display_name} <span className={badgeClass(user.status)}>{userStatusLabel[user.status]}</span>
|
|
</h1>
|
|
<p className="muted">
|
|
ID {user.id} · chat {user.telegram_chat_id} · cadastrado em {fmtDateTime(user.created_at)}
|
|
</p>
|
|
|
|
<section className="card">
|
|
<h2>Cadastro e lembretes</h2>
|
|
<dl className="kv">
|
|
<dt>Lembretes</dt>
|
|
<dd>
|
|
{user.notifications_enabled
|
|
? "ligados"
|
|
: user.paused_reason
|
|
? pauseReasonLabel[user.paused_reason]
|
|
: "desligados"}
|
|
</dd>
|
|
<dt>Admin do bot</dt>
|
|
<dd>{user.is_bot_admin ? "sim" : "não"}</dd>
|
|
<dt>Hoje ({today.day})</dt>
|
|
<dd>
|
|
<span className={badgeClass(today.status)}>{dayStatusLabel[today.status]}</span>{" "}
|
|
<span className="muted">
|
|
{today.last_point_count} ponto(s) na última consulta · próxima consulta: {fmtDateTime(today.next_check_at)}
|
|
</span>
|
|
</dd>
|
|
</dl>
|
|
{canEdit && (
|
|
<div className="actions">
|
|
{canAdmin && user.status !== "active" && <ActionButton path={`${base}/activate`} label="Ativar" variant="primary" />}
|
|
{canAdmin && user.status !== "disabled" && (
|
|
<ActionButton
|
|
path={`${base}/disable`}
|
|
label="Desativar"
|
|
variant="danger"
|
|
confirm="Desativar este usuário? Os lembretes agendados serão cancelados."
|
|
/>
|
|
)}
|
|
{user.status === "active" &&
|
|
(user.notifications_enabled ? (
|
|
<ActionButton path={`${base}/notifications/disable`} label="Pausar lembretes" />
|
|
) : (
|
|
<ActionButton path={`${base}/notifications/enable`} label="Ligar lembretes" variant="primary" />
|
|
))}
|
|
{canAdmin && (
|
|
<ActionButton
|
|
path={`${base}/bot-admin`}
|
|
method="PUT"
|
|
body={{ enabled: !user.is_bot_admin }}
|
|
label={user.is_bot_admin ? "Remover admin do bot" : "Tornar admin do bot"}
|
|
/>
|
|
)}
|
|
{canAdmin && (today.status === "no_points" || today.status === "not_working") && (
|
|
<ActionButton path={`${base}/today/resume`} label="Retomar consultas de hoje" />
|
|
)}
|
|
</div>
|
|
)}
|
|
</section>
|
|
|
|
<section className="card">
|
|
<h2>Credencial PontoMais</h2>
|
|
{credential ? (
|
|
<dl className="kv">
|
|
<dt>E-mail</dt>
|
|
<dd>{credential.api_email}</dd>
|
|
<dt>Situação</dt>
|
|
<dd>
|
|
{credential.validated ? (
|
|
<span className="badge ok">validada em {fmtDateTime(credential.last_validated_at)}</span>
|
|
) : (
|
|
<span className="badge warn">não validada</span>
|
|
)}
|
|
</dd>
|
|
<dt>Falhas seguidas</dt>
|
|
<dd>{credential.consecutive_failures}</dd>
|
|
{credential.last_error && (
|
|
<>
|
|
<dt>Último erro</dt>
|
|
<dd className="error-text">{credential.last_error}</dd>
|
|
</>
|
|
)}
|
|
</dl>
|
|
) : (
|
|
<p className="muted">Nenhuma credencial configurada. Sem ela o usuário não pode ser ativado.</p>
|
|
)}
|
|
{canEdit && <CredentialsForm userId={user.id} />}
|
|
</section>
|
|
|
|
<section className="card">
|
|
<h2>Jornada e janela de consulta</h2>
|
|
<ScheduleForm
|
|
userId={user.id}
|
|
schedule={detail.schedule}
|
|
timezone={user.timezone}
|
|
effectiveWindow={detail.effective_window}
|
|
disabled={!canEdit}
|
|
/>
|
|
</section>
|
|
|
|
<section className="card">
|
|
<h2>Pontos de hoje</h2>
|
|
<TodayPanel userId={user.id} canTest={canEdit} />
|
|
</section>
|
|
|
|
<p>
|
|
<Link href={`/notificacoes?user_id=${user.id}`}>Lembretes deste usuário</Link> ·{" "}
|
|
{!restricted && <Link href={`/auditoria?target_user_id=${user.id}`}>Auditoria deste usuário</Link>}
|
|
</p>
|
|
</>
|
|
);
|
|
}
|