Files
krow_talent_app/src/pages/admin/Analytics.jsx
Aravind 6249e00a3a
Some checks failed
CI / check (push) Failing after 4m58s
candidates and board ui agent issue
2026-09-05 10:46:06 +05:30

80 lines
3.3 KiB
JavaScript

import React, { useMemo } from 'react';
import { useApplications, useJobPostings, useStaff } from '@/lib/krowHooks';
import { AdminPage } from '@/components/admin/PageShell';
import { UiTreeRenderer } from '@/components/ui-tree/UiTreeRenderer';
import { useUiEditing } from '@/components/ui-tree/UiEditingProvider';
import { UiEditor } from '@/components/ui-editor/UiEditor';
import { composePage } from '@/lib/ui/composition';
import '@/components/ui-tree/nodeTypes';
import '@/pages/admin/analytics/nodes';
import {
buildEfficiency, buildFunnel, buildInsights, buildTrend, byDepartment, byPosition,
hiresWithFill, summarise,
} from '@/lib/hiringRecords';
/**
* Admin Analytics — how hiring is performing.
*
* This page and Hired History used to be the same component rendered twice with
* a different title, which is why they read as duplicates: identical sections,
* identical tabs, identical figures. They are not the same question.
*
* **Analytics asks "how is our hiring performing?"** — it is metrics, trends,
* comparison and what to do about them. Every section here is an aggregate: a
* rate, a distribution, a shape over time. No individual hire is named anywhere
* on this page, because a name is a record and records are Hired History's job.
*
* It is also structurally different, not just differently coloured. Analytics is
* one scrolling dashboard — the seven readings are meant to be taken together,
* and a comparison you have to remember across a tab switch is not a comparison.
* Hired History is a filtered record you search, so it keeps its controls and its
* table. Same design system, same blue, same cards; different jobs.
*
* Both read `lib/hiringRecords.js`, so a total here and the same total there
* cannot disagree.
*/
export default function AdminAnalytics() {
const { data: staff = [], isLoading } = useStaff();
const { data: applications = [] } = useApplications();
const { data: postings = [] } = useJobPostings();
const hires = useMemo(
() => hiresWithFill({ staff, applications, postings }),
[staff, applications, postings]
);
const summary = useMemo(() => summarise(hires), [hires]);
const funnel = useMemo(() => buildFunnel(applications), [applications]);
const trend = useMemo(() => buildTrend(hires), [hires]);
const departments = useMemo(() => byDepartment(hires), [hires]);
const positions = useMemo(() => byPosition(hires), [hires]);
const efficiency = useMemo(() => buildEfficiency(hires), [hires]);
const insights = useMemo(
() => buildInsights({ hires, departments, positions, funnel, efficiency }),
[hires, departments, positions, funnel, efficiency]
);
const context = useMemo(() => ({
summary, funnel, trend, departments, positions, efficiency, insights, hires, isLoading, applications,
}), [summary, funnel, trend, departments, positions, efficiency, insights, hires, isLoading, applications]);
return (
<AdminPage
title="Analytics"
subtitle="How hiring is performing — rates, trends, comparison and what to act on."
>
<UiEditor />
<AnalyticsComposition context={context} />
</AdminPage>
);
}
/** The composed page. */
function AnalyticsComposition({ context }) {
const editing = useUiEditing();
const tree = editing?.tree || composePage('analytics').tree;
return <UiTreeRenderer nodes={tree} context={context} />;
}