- Changed TypeScript target and library settings in tsconfig files to align with ESNext standards. - Updated pnpm version in GitHub workflows for better dependency management. - Modified Dockerfile to reflect the updated pnpm version. - Adjusted import statements across various domain modules to include file extensions for consistency and compatibility. - Cleaned up TypeScript configuration files for improved clarity and organization.
105 lines
2.4 KiB
TypeScript
105 lines
2.4 KiB
TypeScript
/**
|
|
* Dashboard Domain Utilities
|
|
* Business logic for dashboard activities and task generation
|
|
*/
|
|
|
|
import type { Activity, ActivityFilter, ActivityFilterConfig, ActivityType } from "./contract.js";
|
|
|
|
/**
|
|
* Activity filter configurations
|
|
* Defines which activity types belong to each filter category
|
|
*/
|
|
export const ACTIVITY_FILTERS: ActivityFilterConfig[] = [
|
|
{ key: "all", label: "All" },
|
|
{
|
|
key: "billing",
|
|
label: "Billing",
|
|
types: ["invoice_created", "invoice_paid"],
|
|
},
|
|
{
|
|
key: "orders",
|
|
label: "Orders",
|
|
types: ["service_activated"],
|
|
},
|
|
{
|
|
key: "support",
|
|
label: "Support",
|
|
types: ["case_created", "case_closed"],
|
|
},
|
|
];
|
|
|
|
/**
|
|
* Filter activities by type category
|
|
*/
|
|
export function filterActivities(activities: Activity[], filter: ActivityFilter): Activity[] {
|
|
if (filter === "all") {
|
|
return activities;
|
|
}
|
|
|
|
const filterConfig = ACTIVITY_FILTERS.find(f => f.key === filter);
|
|
if (!filterConfig?.types) {
|
|
return activities;
|
|
}
|
|
|
|
return activities.filter(activity => filterConfig.types!.includes(activity.type));
|
|
}
|
|
|
|
/**
|
|
* Activity types that support navigation to detail views
|
|
*/
|
|
const CLICKABLE_ACTIVITY_TYPES: ActivityType[] = ["invoice_created", "invoice_paid"];
|
|
|
|
/**
|
|
* Check if an activity is clickable (has a navigable detail view)
|
|
*/
|
|
export function isActivityClickable(activity: Activity): boolean {
|
|
return CLICKABLE_ACTIVITY_TYPES.includes(activity.type) && !!activity.relatedId;
|
|
}
|
|
|
|
/**
|
|
* Dashboard task definition
|
|
*/
|
|
export interface DashboardTask {
|
|
label: string;
|
|
href: string;
|
|
}
|
|
|
|
/**
|
|
* Dashboard summary input for task generation
|
|
*/
|
|
export interface DashboardTaskSummary {
|
|
nextInvoice?: { id: number } | null;
|
|
stats?: { unpaidInvoices?: number; openCases?: number };
|
|
}
|
|
|
|
/**
|
|
* Generate dashboard task suggestions based on summary data
|
|
*/
|
|
export function generateDashboardTasks(summary: DashboardTaskSummary): DashboardTask[] {
|
|
const tasks: DashboardTask[] = [];
|
|
|
|
if (summary.nextInvoice) {
|
|
tasks.push({
|
|
label: "Pay upcoming invoice",
|
|
href: "#attention",
|
|
});
|
|
}
|
|
|
|
if (summary.stats?.unpaidInvoices && summary.stats.unpaidInvoices > 0) {
|
|
tasks.push({
|
|
label: "Review unpaid invoices",
|
|
href: "/billing/invoices",
|
|
});
|
|
}
|
|
|
|
if (summary.stats?.openCases && summary.stats.openCases > 0) {
|
|
tasks.push({
|
|
label: "Check support cases",
|
|
href: "/support/cases",
|
|
});
|
|
}
|
|
|
|
return tasks;
|
|
}
|
|
|