views: criar página /views com gráficos (Canais movido do dashboard, CSAT distribuição, Filas abertas); dashboard: trocar por gráfico Abertos x Resolvidos (últimos 7/30/90 dias); reports: nova query openedResolvedByDay
This commit is contained in:
parent
5b14ecbe0f
commit
88b65c3e15
5 changed files with 317 additions and 2 deletions
|
|
@ -226,6 +226,52 @@ export const csatOverview = query({
|
|||
},
|
||||
});
|
||||
|
||||
export const openedResolvedByDay = query({
|
||||
args: { tenantId: v.string(), viewerId: v.id("users"), range: v.optional(v.string()), companyId: v.optional(v.id("companies")) },
|
||||
handler: async (ctx, { tenantId, viewerId, range, companyId }) => {
|
||||
const viewer = await requireStaff(ctx, viewerId, tenantId);
|
||||
let tickets = await fetchScopedTickets(ctx, tenantId, viewer);
|
||||
if (companyId) tickets = tickets.filter((t) => t.companyId === companyId)
|
||||
|
||||
const days = range === "7d" ? 7 : range === "30d" ? 30 : 90;
|
||||
const end = new Date();
|
||||
end.setUTCHours(0, 0, 0, 0);
|
||||
const endMs = end.getTime() + ONE_DAY_MS;
|
||||
const startMs = endMs - days * ONE_DAY_MS;
|
||||
|
||||
const opened: Record<string, number> = {}
|
||||
const resolved: Record<string, number> = {}
|
||||
|
||||
// pre-fill buckets
|
||||
for (let i = days - 1; i >= 0; i--) {
|
||||
const d = new Date(endMs - (i + 1) * ONE_DAY_MS)
|
||||
const key = formatDateKey(d.getTime())
|
||||
opened[key] = 0
|
||||
resolved[key] = 0
|
||||
}
|
||||
|
||||
for (const t of tickets) {
|
||||
if (t.createdAt >= startMs && t.createdAt < endMs) {
|
||||
const key = formatDateKey(t.createdAt)
|
||||
opened[key] = (opened[key] ?? 0) + 1
|
||||
}
|
||||
if (t.resolvedAt && t.resolvedAt >= startMs && t.resolvedAt < endMs) {
|
||||
const key = formatDateKey(t.resolvedAt)
|
||||
resolved[key] = (resolved[key] ?? 0) + 1
|
||||
}
|
||||
}
|
||||
|
||||
const series: Array<{ date: string; opened: number; resolved: number }> = []
|
||||
for (let i = days - 1; i >= 0; i--) {
|
||||
const d = new Date(endMs - (i + 1) * ONE_DAY_MS)
|
||||
const key = formatDateKey(d.getTime())
|
||||
series.push({ date: key, opened: opened[key] ?? 0, resolved: resolved[key] ?? 0 })
|
||||
}
|
||||
|
||||
return { rangeDays: days, series }
|
||||
},
|
||||
})
|
||||
|
||||
export const backlogOverview = query({
|
||||
args: { tenantId: v.string(), viewerId: v.id("users"), range: v.optional(v.string()), companyId: v.optional(v.id("companies")) },
|
||||
handler: async (ctx, { tenantId, viewerId, range, companyId }) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue