import { z } from "zod"; import { invoiceSchema } from "../billing/schema.js"; import { internetEligibilityDetailsSchema } from "../services/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; export type ServiceActivityMetadata = z.infer;