feat(awooop): show callback gap freshness
All checks were successful
CD Pipeline / tests (push) Successful in 1m32s
Code Review / ai-code-review (push) Successful in 12s
CD Pipeline / build-and-deploy (push) Successful in 3m29s
CD Pipeline / post-deploy-checks (push) Successful in 1m20s

This commit is contained in:
Your Name
2026-05-25 21:20:10 +08:00
parent 101b08946a
commit dcde86c7f9
7 changed files with 236 additions and 17 deletions

View File

@@ -153,7 +153,13 @@ interface CallbackReplyAuditSummary {
outbound_incident_ref_total?: number;
outbound_reply_markup_total?: number;
outbound_reply_markup_missing_incident_ref_total?: number;
outbound_reply_markup_missing_incident_ref_recent_1h_total?: number;
outbound_reply_markup_missing_incident_ref_recent_24h_total?: number;
outbound_reply_markup_missing_incident_ref_latest_sent_at?: string | null;
outbound_reply_markup_missing_trace_ref_total?: number;
outbound_reply_markup_missing_trace_ref_recent_1h_total?: number;
outbound_reply_markup_missing_trace_ref_recent_24h_total?: number;
outbound_reply_markup_missing_trace_ref_latest_sent_at?: string | null;
outbound_reply_markup_missing_incident_ref_top_prefixes?: Array<{
prefix?: string | null;
total?: number | null;
@@ -2476,6 +2482,15 @@ function CallbackReplyAuditSummaryPanel({
summary.outbound_trace_ref_total ?? summary.outbound_incident_ref_total ?? 0,
outboundTotal
);
const formatShortDateTime = (value?: string | null) =>
value
? new Date(value).toLocaleString("zh-TW", {
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
})
: "--";
const formatPrefixGaps = (
items?: Array<{
prefix?: string | null;
@@ -2487,19 +2502,11 @@ function CallbackReplyAuditSummaryPanel({
items ?? []
).slice(0, 3)
.map((item) => {
const lastSeen = item.last_sent_at
? new Date(item.last_sent_at).toLocaleString("zh-TW", {
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
})
: "--";
return t("outboundReplyMarkupTopPrefixItem", {
prefix: item.prefix || "--",
total: item.total ?? 0,
recent: item.recent_24h_total ?? 0,
last: lastSeen,
last: formatShortDateTime(item.last_sent_at),
});
})
.join(" / ") || "--";
@@ -2513,14 +2520,13 @@ function CallbackReplyAuditSummaryPanel({
summary.callback_snapshot_captured_total ?? 0,
callbackTotal
);
const latestCallback = summary.latest_callback_at
? new Date(summary.latest_callback_at).toLocaleString("zh-TW", {
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
})
: "--";
const latestCallback = formatShortDateTime(summary.latest_callback_at);
const latestMissingTraceRef = formatShortDateTime(
summary.outbound_reply_markup_missing_trace_ref_latest_sent_at
);
const latestMissingIncidentRef = formatShortDateTime(
summary.outbound_reply_markup_missing_incident_ref_latest_sent_at
);
const snapshotClass = {
captured: "border-[#9bc7a4] bg-[#f0faf2] text-[#17602a]",
partial: "border-[#d9b36f] bg-[#fff7e8] text-[#8a5a08]",
@@ -2556,6 +2562,30 @@ function CallbackReplyAuditSummaryPanel({
summary.outbound_reply_markup_missing_trace_ref_total ?? 0,
})}
</p>
<p className="mt-1 text-xs leading-5 text-[#5f5b52]">
{t("outboundReplyMarkupTraceFreshness", {
recent1h:
summary.outbound_reply_markup_missing_trace_ref_recent_1h_total ??
0,
recent24h:
summary.outbound_reply_markup_missing_trace_ref_recent_24h_total ??
0,
latest: latestMissingTraceRef,
})}
</p>
<p className="mt-1 text-xs leading-5 text-[#5f5b52]">
{t("outboundReplyMarkupIncidentFreshness", {
recent1h:
summary
.outbound_reply_markup_missing_incident_ref_recent_1h_total ??
0,
recent24h:
summary
.outbound_reply_markup_missing_incident_ref_recent_24h_total ??
0,
latest: latestMissingIncidentRef,
})}
</p>
<p className="mt-1 text-xs leading-5 text-[#5f5b52]">
{t("outboundReplyMarkupTraceTopPrefixes", {
prefixes: topMissingTracePrefixes,