diff --git a/frontend/src/pages/Planner/Dashboard.tsx b/frontend/src/pages/Planner/Dashboard.tsx index a6b10ac3..0a025737 100644 --- a/frontend/src/pages/Planner/Dashboard.tsx +++ b/frontend/src/pages/Planner/Dashboard.tsx @@ -1,10 +1,11 @@ -import { useEffect, useState, useMemo } from "react"; +import { useEffect, useState, useMemo, lazy, Suspense } from "react"; import { Link, useNavigate } from "react-router"; import PageMeta from "../../components/common/PageMeta"; import ComponentCard from "../../components/common/ComponentCard"; import { ProgressBar } from "../../components/ui/progress"; -import Chart from "react-apexcharts"; import { ApexOptions } from "apexcharts"; + +const Chart = lazy(() => import("react-apexcharts").then((mod) => ({ default: mod.default }))); import { ListIcon, GroupIcon, @@ -445,18 +446,18 @@ export default function PlannerDashboard() { {/* Top Status Cards */}
- -
-
-
-

Keywords Ready

+ > +
+
+
+

Keywords Ready

{stats.keywords.total.toLocaleString()} -

+ {trends.keywords !== 0 && (
0 ? 'text-success-500' : 'text-error-500'}`}> {trends.keywords > 0 ? : } @@ -464,28 +465,28 @@ export default function PlannerDashboard() {
)}
-

+

{stats.keywords.mapped} mapped • {stats.keywords.unmapped} unmapped -

-
-
- -
+

- +
+ +
+
+ - -
-
-
-

Clusters Built

+ > +
+
+
+

Clusters Built

{stats.clusters.total.toLocaleString()} -

+ {trends.clusters !== 0 && (
0 ? 'text-success-500' : 'text-error-500'}`}> {trends.clusters > 0 ? : } @@ -493,28 +494,28 @@ export default function PlannerDashboard() {
)}
-

+

{stats.clusters.totalVolume.toLocaleString()} total volume • {stats.clusters.avgKeywords} avg keywords -

-
-
- -
+

- +
+ +
+
+ - -
-
-
-

Ideas Generated

+ > +
+
+
+

Ideas Generated

{stats.ideas.total.toLocaleString()} -

+ {trends.ideas !== 0 && (
0 ? 'text-success-500' : 'text-error-500'}`}> {trends.ideas > 0 ? : } @@ -522,48 +523,48 @@ export default function PlannerDashboard() {
)}
-

+

{stats.ideas.queued} queued • {stats.ideas.notQueued} pending -

-
-
- -
+

- +
+ +
+
+ - -
-
-
+ > +
+
+

Mapping Progress

-

+

{keywordMappingPct}% -

-

+ +

{stats.keywords.mapped} of {stats.keywords.total} keywords mapped -

-
-
- -
+

- -
+
+ +
+
+ +
- {/* Planner Workflow Steps */} - -
- {workflowSteps.map((step) => ( - +
+ {workflowSteps.map((step) => ( + -
+ > +
{step.status === "completed" ? : step.number} -
-

{step.title}

+

{step.title}

+
-
- {step.status === "completed" ? ( - <> - - Completed - - ) : ( - <> - - Pending - - )} -
+
+ {step.status === "completed" ? ( + <> + + Completed + + ) : ( + <> + + Pending + + )}
- {step.count !== null && ( +
+ {step.count !== null && (

{step.count} {step.title.includes("Keywords") ? "keywords" : step.title.includes("Clusters") ? "clusters" : step.title.includes("Ideas") ? "ideas" : "items"} -

- )} - {step.status === "pending" && ( - - )} - - ))} + + )} + + ))} +
+ + +
+ {/* Progress Summary */} + +
+
+
+ Keyword Mapping + {keywordMappingPct}% +
+ +

+ {stats.keywords.mapped} of {stats.keywords.total} keywords mapped +

+
+ +
+
+ Clusters With Ideas + {clustersIdeasPct}% +
+ +

+ {stats.clusters.withIdeas} of {stats.clusters.total} clusters have ideas +

+
+ +
+
+ Ideas Queued to Writer + {ideasQueuedPct}% +
+ +

+ {stats.ideas.queued} of {stats.ideas.total} ideas queued +

+
-
- {/* Progress Summary */} - -
-
-
- Keyword Mapping - {keywordMappingPct}% -
- -

- {stats.keywords.mapped} of {stats.keywords.total} keywords mapped -

-
- -
-
- Clusters With Ideas - {clustersIdeasPct}% -
- -

- {stats.clusters.withIdeas} of {stats.clusters.total} clusters have ideas -

-
- -
-
- Ideas Queued to Writer - {ideasQueuedPct}% -
- -

- {stats.ideas.queued} of {stats.ideas.total} ideas queued -

-
-
-
- {/* Top 5 Clusters */} {topClustersChart ? ( - +
}> + + ) : (
No clusters data available
)} -
+
{/* Keywords by Status */} {keywordsStatusChart && ( - +
}> + +
)} {/* Ideas by Status */} {ideasStatusChart && ( - +
}> + + )} -
+
- {/* Next Actions */} + {/* Next Actions */} {nextActions.length > 0 && ( - -
- {nextActions.map((action, index) => ( -
+
+ {nextActions.map((action, index) => ( +
+ > {action.text} - - {action.action} - - -
- ))} + > + {action.action} + +
- + ))} +
+ )}
diff --git a/frontend/src/pages/Writer/Dashboard.tsx b/frontend/src/pages/Writer/Dashboard.tsx index 1dbdce03..14c6801f 100644 --- a/frontend/src/pages/Writer/Dashboard.tsx +++ b/frontend/src/pages/Writer/Dashboard.tsx @@ -1,10 +1,11 @@ -import { useEffect, useState, useMemo } from "react"; +import { useEffect, useState, useMemo, lazy, Suspense } from "react"; import { Link, useNavigate } from "react-router"; import PageMeta from "../../components/common/PageMeta"; import ComponentCard from "../../components/common/ComponentCard"; import { ProgressBar } from "../../components/ui/progress"; -import Chart from "react-apexcharts"; import { ApexOptions } from "apexcharts"; + +const Chart = lazy(() => import("react-apexcharts").then((mod) => ({ default: mod.default }))); import { FileTextIcon, BoxIcon, @@ -748,12 +749,14 @@ export default function WriterDashboard() { {/* Content Status Chart */} {contentStatusChart && ( - +
}> + +
)} @@ -762,24 +765,28 @@ export default function WriterDashboard() { {/* Tasks by Status */} {tasksStatusChart && ( - +
}> + +
)} {/* Images by Type */} {imagesTypeChart ? ( - +
}> + +
) : ( @@ -804,12 +811,14 @@ export default function WriterDashboard() { {/* Productivity Chart */} {productivityChart && ( - +
}> + +
)} diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 6a34b26b..910ace1c 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -25,6 +25,9 @@ export default defineConfig(({ mode }) => { 'clsx', 'tailwind-merge', 'zustand', + // Include apexcharts for proper module resolution + 'apexcharts', + 'react-apexcharts', ], // Exclude heavy dependencies that are only used in specific pages // They will be lazy-loaded when needed @@ -35,8 +38,6 @@ export default defineConfig(({ mode }) => { '@fullcalendar/list', '@fullcalendar/react', '@fullcalendar/timegrid', - 'apexcharts', - 'react-apexcharts', '@react-jvectormap/core', '@react-jvectormap/world', 'react-dnd',