import { useCallback, useMemo } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import useSWR from "swr"; // plane imports import { MODULE_STATUS, MODULE_STATUS_COLORS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { BarChart } from "@plane/propel/charts/bar-chart"; import { IModuleProgressData, IChartResponse, TChartData, TModuleStatus } from "@plane/types"; import { renderFormattedDate } from "@plane/utils"; // components import AnalyticsSectionWrapper from "@/components/analytics/analytics-section-wrapper"; import AnalyticsEmptyState from "@/components/analytics/empty-state"; import { ChartLoader } from "@/components/analytics/loaders"; // hooks import { useAnalytics } from "@/hooks/store/use-analytics"; import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; 8; // services import { AnalyticsService } from "@/services/analytics.service"; import ModulesCyclesTooltip, { ICycleModuleTooltipProps } from "../modules-cycles-tooltip"; const analyticsService = new AnalyticsService(); const ModuleProgress = observer(() => { const params = useParams(); const { t } = useTranslation(); const workspaceSlug = params.workspaceSlug.toString(); const { selectedDuration, selectedDurationLabel, selectedProjects, selectedCycle, selectedModule, isPeekView } = useAnalytics(); const resolvedPath = useResolvedAssetPath({ basePath: "/empty-state/analytics/empty-chart-radar" }); const { data: moduleInsightsData, isLoading: isLoadingModuleInsight } = useSWR( `radar-chart-module-progress-${workspaceSlug}-${selectedDuration}-${selectedProjects}-${selectedCycle}-${selectedModule}-${isPeekView}`, () => analyticsService.getAdvanceAnalyticsCharts( workspaceSlug, "modules", { // date_filter: selectedDuration, ...(selectedProjects?.length > 0 && { project_ids: selectedProjects?.join(",") }), ...(selectedCycle ? { cycle_id: selectedCycle } : {}), ...(selectedModule ? { module_id: selectedModule } : {}), }, isPeekView ) ); const parsedData: TChartData[] = useMemo(() => { if (!moduleInsightsData?.data) return []; return moduleInsightsData.data.map((datum) => ({ ...datum, [datum.key]: datum.count, name: renderFormattedDate(datum.key) ?? datum.key, })); }, [moduleInsightsData]); const tooltipRows = useCallback( (data: IModuleProgressData) => [ { label: t("workspace_analytics.total", { entity: t("common.work_items"), }), value: data.total_issues, }, { label: t("workspace_projects.state.completed"), value: data.completed_issues, }, { label: t("workspace_projects.state.started"), value: data.started_issues, }, { label: t("workspace_projects.state.unstarted"), value: data.unstarted_issues, }, { label: t("workspace_projects.state.cancelled"), value: data.cancelled_issues, }, ], [t] ); return ( {isLoadingModuleInsight ? ( ) : moduleInsightsData && moduleInsightsData?.data?.length > 0 ? (
MODULE_STATUS_COLORS[payload.status.toLowerCase() as TModuleStatus], textClassName: "text-xs", stackId: "a", shapeVariant: "lollipop", }, ]} className="h-full" xAxis={{ key: "name", label: t("common.modules"), }} yAxis={{ key: "count", label: t("common.completion") + " %", domain: [0, 100], dx: -25, }} margin={{ top: 20, right: 20, bottom: 35, left: 20, }} showTooltip customTooltipContent={({ active, label, payload }) => { if (!active) return null; const data: IModuleProgressData = payload[0]?.payload as IModuleProgressData; const tooltipProps: ICycleModuleTooltipProps = { title: data.name, startDate: data.start_date, endDate: data.target_date, rows: tooltipRows(data), totalCount: data.total_issues, completedCount: data.completed_issues, }; return ; }} />
{Object.entries(MODULE_STATUS_COLORS).map(([key, value]) => (
{t(MODULE_STATUS.find((status) => status.value === key)?.i18n_label || "")}
))}
) : ( )} ); }); export default ModuleProgress;