- Introduced MeStatus module to aggregate customer status, integrating dashboard summary, payment methods, internet eligibility, and residence card verification. - Updated dashboard hooks to utilize MeStatus for improved data fetching and error handling. - Enhanced notification handling across various modules, including cancellation notifications for internet and SIM services, ensuring timely user alerts. - Refactored related schemas and services to support new dashboard tasks and notification types, improving overall user engagement and experience.
140 lines
4.1 KiB
TypeScript
140 lines
4.1 KiB
TypeScript
import { z } from "zod";
|
|
import { invoiceSchema } from "../billing/schema.js";
|
|
import { internetEligibilityDetailsSchema } from "../catalog/schema.js";
|
|
import { residenceCardVerificationSchema } from "../customer/schema.js";
|
|
|
|
export const activityTypeSchema = z.enum([
|
|
"invoice_created",
|
|
"invoice_paid",
|
|
"service_activated",
|
|
"case_created",
|
|
"case_closed",
|
|
]);
|
|
|
|
export const activitySchema = z.object({
|
|
id: z.string(),
|
|
type: activityTypeSchema,
|
|
title: z.string(),
|
|
description: z.string().optional(),
|
|
date: z.string(),
|
|
relatedId: z.number().optional(),
|
|
metadata: z.record(z.string(), z.unknown()).optional(),
|
|
});
|
|
|
|
export const invoiceActivityMetadataSchema = z
|
|
.object({
|
|
amount: z.number(),
|
|
currency: z.string().optional(),
|
|
dueDate: z.string().optional(),
|
|
invoiceNumber: z.string().optional(),
|
|
status: z.string().optional(),
|
|
})
|
|
.partial()
|
|
.refine(data => typeof data.amount === "number", {
|
|
message: "amount is required",
|
|
path: ["amount"],
|
|
});
|
|
|
|
export const serviceActivityMetadataSchema = z
|
|
.object({
|
|
productName: z.string().optional(),
|
|
registrationDate: z.string().optional(),
|
|
status: z.string().optional(),
|
|
})
|
|
.partial();
|
|
|
|
export const dashboardStatsSchema = z.object({
|
|
activeSubscriptions: z.number().int().nonnegative(),
|
|
unpaidInvoices: z.number().int().nonnegative(),
|
|
openCases: z.number().int().nonnegative(),
|
|
recentOrders: z.number().int().nonnegative().optional(),
|
|
totalSpent: z.number().nonnegative().optional(),
|
|
currency: z.string(),
|
|
});
|
|
|
|
export const nextInvoiceSchema = z.object({
|
|
id: z.number().int().positive(),
|
|
dueDate: z.string(),
|
|
amount: z.number(),
|
|
currency: z.string(),
|
|
});
|
|
|
|
export const dashboardSummarySchema = z.object({
|
|
stats: dashboardStatsSchema,
|
|
nextInvoice: nextInvoiceSchema.nullable(),
|
|
recentActivity: z.array(activitySchema),
|
|
});
|
|
|
|
export const dashboardErrorSchema = z.object({
|
|
code: z.string(),
|
|
message: z.string(),
|
|
details: z.record(z.string(), z.unknown()).optional(),
|
|
});
|
|
|
|
export const activityFilterSchema = z.enum(["all", "billing", "orders", "support"]);
|
|
|
|
export const activityFilterConfigSchema = z.object({
|
|
key: activityFilterSchema,
|
|
label: z.string(),
|
|
types: z.array(activityTypeSchema).optional(),
|
|
});
|
|
|
|
export const dashboardSummaryResponseSchema = dashboardSummarySchema.extend({
|
|
invoices: z.array(invoiceSchema).optional(),
|
|
});
|
|
|
|
// ============================================================================
|
|
// Dashboard Tasks (Customer-facing)
|
|
// ============================================================================
|
|
|
|
export const dashboardTaskTypeSchema = z.enum([
|
|
"invoice",
|
|
"payment_method",
|
|
"order",
|
|
"internet_eligibility",
|
|
"id_verification",
|
|
"onboarding",
|
|
]);
|
|
|
|
export const dashboardTaskToneSchema = z.enum(["critical", "warning", "info", "neutral"]);
|
|
|
|
export const dashboardTaskSchema = z.object({
|
|
id: z.string(),
|
|
priority: z.union([z.literal(1), z.literal(2), z.literal(3), z.literal(4)]),
|
|
type: dashboardTaskTypeSchema,
|
|
title: z.string(),
|
|
description: z.string(),
|
|
actionLabel: z.string(),
|
|
detailHref: z.string().optional(),
|
|
requiresSsoAction: z.boolean().optional(),
|
|
tone: dashboardTaskToneSchema,
|
|
metadata: z
|
|
.object({
|
|
invoiceId: z.number().int().positive().optional(),
|
|
orderId: z.string().optional(),
|
|
amount: z.number().optional(),
|
|
currency: z.string().optional(),
|
|
dueDate: z.string().datetime().optional(),
|
|
})
|
|
.optional(),
|
|
});
|
|
|
|
export const paymentMethodsStatusSchema = z.object({
|
|
/** null indicates the value could not be loaded (avoid incorrect UI gating). */
|
|
totalCount: z.number().int().nonnegative().nullable(),
|
|
});
|
|
|
|
/**
|
|
* Aggregated customer status payload intended to power dashboard + gating UX.
|
|
*/
|
|
export const meStatusSchema = z.object({
|
|
summary: dashboardSummarySchema,
|
|
paymentMethods: paymentMethodsStatusSchema,
|
|
internetEligibility: internetEligibilityDetailsSchema,
|
|
residenceCardVerification: residenceCardVerificationSchema,
|
|
tasks: z.array(dashboardTaskSchema),
|
|
});
|
|
|
|
export type InvoiceActivityMetadata = z.infer<typeof invoiceActivityMetadataSchema>;
|
|
export type ServiceActivityMetadata = z.infer<typeof serviceActivityMetadataSchema>;
|