Connect all CRM pages to the BFF and CRM service, add module docs, and mark CRM available in the SuperApp catalog. Co-authored-by: Cursor <cursoragent@cursor.com>
118 lines
5.9 KiB
JavaScript
118 lines
5.9 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Generates CRM app routes (thin page.tsx re-exports) and stub feature files if missing.
|
|
*/
|
|
import fs from "fs";
|
|
import path from "path";
|
|
import { fileURLToPath } from "url";
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
|
const ROOT = path.join(__dirname, "..");
|
|
const APP = path.join(ROOT, "app", "crm");
|
|
const FEATURES = path.join(ROOT, "modules", "crm", "features");
|
|
|
|
const ROUTES = [
|
|
["hub", "pages/hub", "CrmHub", "pages/hub"],
|
|
["sales/dashboard/overview", "sales/dashboards", "OverviewDashboard", "sales/dashboards"],
|
|
["sales/dashboard/sales", "sales/dashboards", "SalesDashboard", "sales/dashboards"],
|
|
["sales/dashboard/pipeline", "sales/dashboards", "PipelineDashboard", "sales/dashboards"],
|
|
["sales/dashboard/leads", "sales/dashboards", "LeadDashboard", "sales/dashboards"],
|
|
["sales/dashboard/activities", "sales/dashboards", "ActivityDashboard", "sales/dashboards"],
|
|
["sales/dashboard/calendar", "sales/dashboards", "CalendarDashboard", "sales/dashboards"],
|
|
["sales/customers", "sales/customers", "default", "sales/customers"],
|
|
["sales/companies", "sales/companies", "default", "sales/companies"],
|
|
["sales/contacts", "sales/contacts", "default", "sales/contacts"],
|
|
["sales/leads", "sales/leads", "default", "sales/leads"],
|
|
["sales/deals", "sales/deals", "default", "sales/deals"],
|
|
["sales/kanban", "sales/kanban", "default", "sales/kanban"],
|
|
["sales/pipelines", "sales/pipelines", "default", "sales/pipelines"],
|
|
["sales/quotes", "sales/quotes", "default", "sales/quotes"],
|
|
["sales/activities", "sales/activities", "default", "sales/activities"],
|
|
["sales/tasks", "sales/tasks", "default", "sales/tasks"],
|
|
["sales/meetings", "sales/meetings", "default", "sales/meetings"],
|
|
["sales/calls", "sales/calls", "default", "sales/calls"],
|
|
["sales/emails", "sales/emails", "default", "sales/emails"],
|
|
["sales/notes", "sales/notes", "default", "sales/notes"],
|
|
["sales/timeline", "sales/timeline", "default", "sales/timeline"],
|
|
["sales/documents", "sales/documents", "default", "sales/documents"],
|
|
["sales/campaigns", "sales/scoped", "CampaignsPage", "sales/scoped"],
|
|
["sales/segments", "sales/scoped", "SegmentsPage", "sales/scoped"],
|
|
["sales/tags", "sales/tags", "default", "sales/tags"],
|
|
["sales/custom-fields", "sales/custom-fields", "default", "sales/custom-fields"],
|
|
["sales/import", "sales/scoped", "ImportPage", "sales/scoped"],
|
|
["sales/export", "sales/export", "default", "sales/export"],
|
|
["sales/reports", "sales/reports", "default", "sales/reports"],
|
|
["sales/analytics", "sales/analytics", "default", "sales/analytics"],
|
|
["sales/automation", "sales/scoped", "AutomationPage", "sales/scoped"],
|
|
["sales/notifications", "sales/admin", "NotificationsPage", "sales/admin"],
|
|
["sales/roles", "sales/admin", "RolesPage", "sales/admin"],
|
|
["sales/permissions", "sales/admin", "PermissionsPage", "sales/admin"],
|
|
["sales/integrations", "sales/scoped", "IntegrationsPage", "sales/scoped"],
|
|
["sales/api-keys", "sales/scoped", "ApiKeysPage", "sales/scoped"],
|
|
["sales/audit-logs", "sales/admin", "AuditLogsPage", "sales/admin"],
|
|
["sales/settings", "sales/admin", "SettingsPage", "sales/admin"],
|
|
["sales/health", "sales/admin", "HealthPage", "sales/admin"],
|
|
["sales/capabilities", "sales/admin", "CapabilitiesPage", "sales/admin"],
|
|
];
|
|
|
|
function ensureDir(dir) {
|
|
fs.mkdirSync(dir, { recursive: true });
|
|
}
|
|
|
|
function writePage(routePath, modulePath, exportName) {
|
|
const dir = path.join(APP, routePath);
|
|
ensureDir(dir);
|
|
const pageContent =
|
|
exportName === "default"
|
|
? `"use client";\n\nexport { default } from "@/modules/crm/features/${modulePath}";\n`
|
|
: `"use client";\n\nexport { ${exportName} as default } from "@/modules/crm/features/${modulePath}";\n`;
|
|
fs.writeFileSync(path.join(dir, "page.tsx"), pageContent);
|
|
|
|
for (const name of ["loading.tsx", "error.tsx"]) {
|
|
const file = path.join(dir, name);
|
|
if (!fs.existsSync(file)) {
|
|
if (name === "loading.tsx") {
|
|
fs.writeFileSync(
|
|
file,
|
|
`import { LoadingState } from "@/components/ds";\n\nexport default function Loading() {\n return <LoadingState label="در حال بارگذاری CRM…" />;\n}\n`
|
|
);
|
|
} else {
|
|
fs.writeFileSync(
|
|
file,
|
|
`"use client";\n\nimport { ErrorState } from "@/components/ds";\n\nexport default function Error({ error, reset }: { error: Error; reset: () => void }) {\n return <ErrorState message={error.message} onRetry={reset} />;\n}\n`
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Root layouts
|
|
ensureDir(path.join(APP));
|
|
if (!fs.existsSync(path.join(APP, "layout.tsx"))) {
|
|
fs.writeFileSync(
|
|
path.join(APP, "layout.tsx"),
|
|
`/** CRM root — sub-routes supply portal shells. */\nexport default function CrmRootLayout({ children }: { children: React.ReactNode }) {\n return children;\n}\n`
|
|
);
|
|
}
|
|
if (!fs.existsSync(path.join(APP, "not-found.tsx"))) {
|
|
fs.writeFileSync(
|
|
path.join(APP, "not-found.tsx"),
|
|
`import Link from "next/link";\nimport { Button, EmptyState } from "@/components/ds";\n\nexport default function CrmNotFound() {\n return (\n <div className="flex min-h-[50vh] items-center justify-center p-6">\n <EmptyState\n title="صفحه CRM یافت نشد"\n action={<Link href="/crm/hub"><Button>بازگشت به CRM</Button></Link>}\n />\n </div>\n );\n}\n`
|
|
);
|
|
}
|
|
|
|
ensureDir(path.join(APP, "sales"));
|
|
if (!fs.existsSync(path.join(APP, "sales", "layout.tsx"))) {
|
|
fs.writeFileSync(
|
|
path.join(APP, "sales", "layout.tsx"),
|
|
`"use client";\n\nimport { createPortalLayout } from "@/modules/crm/components/createPortalLayout";\n\nexport default createPortalLayout("sales");\n`
|
|
);
|
|
}
|
|
|
|
for (const [route, mod, exp] of ROUTES) {
|
|
writePage(route, mod, exp);
|
|
}
|
|
|
|
console.log(`Generated ${ROUTES.length} CRM routes under app/crm/`);
|