import { useCallback, useEffect, useMemo, useState } from 'react'; import { getSikshyaApi, SIKSHYA_ENDPOINTS } from '../api'; import { MetricTile, QuickActionCard } from '../components/dashboard'; import { NavIcon } from '../components/NavIcon'; import { ButtonPrimary } from '../components/shared/buttons'; import { CreateCourseModal } from '../components/shared/CreateCourseModal'; import { EmbeddableShell } from '../components/shared/EmbeddableShell'; import { ListEmptyState } from '../components/shared/list/ListEmptyState'; import { ListPanel } from '../components/shared/list/ListPanel'; import { StatusBadge } from '../components/shared/list/StatusBadge'; import { appViewHref } from '../lib/appUrl'; import { formatPostDate } from '../lib/formatPostDate'; import { getLicensing } from '../lib/licensing'; import type { SikshyaReactConfig } from '../types'; import { __, _n, sprintf } from '../lib/i18n'; type DashboardStats = { publishedCourses: number; draftCourses?: number; lessons?: number; quizzes?: number; assignments?: number; questions?: number; chapters?: number; certificateTemplates?: number; students: number; instructors?: number; revenue: string; enrollments: number; completedEnrollments?: number; distinctLearners?: number; hasEnrollmentTable?: boolean; hasPaymentsTable?: boolean; }; type RecentCourse = { id: number; title: string; status: string; modified: string; }; function resolveDashboardData(config: SikshyaReactConfig): { siteName: string; stats: DashboardStats; recentCourses: RecentCourse[]; dashboardLinks: { enrollments: boolean; payments: boolean }; } { const raw = config.initialData as { siteName?: string; stats?: Partial; recentCourses?: RecentCourse[]; dashboardLinks?: { enrollments?: boolean; payments?: boolean }; }; const stats: DashboardStats = { publishedCourses: raw.stats?.publishedCourses ?? 0, draftCourses: raw.stats?.draftCourses ?? 0, lessons: raw.stats?.lessons ?? 0, quizzes: raw.stats?.quizzes ?? 0, assignments: raw.stats?.assignments ?? 0, questions: raw.stats?.questions ?? 0, chapters: raw.stats?.chapters ?? 0, certificateTemplates: raw.stats?.certificateTemplates ?? 0, students: raw.stats?.students ?? 0, instructors: raw.stats?.instructors ?? 0, revenue: raw.stats?.revenue ?? '$0.00', enrollments: raw.stats?.enrollments ?? 0, completedEnrollments: raw.stats?.completedEnrollments ?? 0, distinctLearners: raw.stats?.distinctLearners ?? 0, hasEnrollmentTable: raw.stats?.hasEnrollmentTable ?? false, hasPaymentsTable: raw.stats?.hasPaymentsTable ?? false, }; return { siteName: typeof raw.siteName === 'string' ? raw.siteName : '', stats, recentCourses: Array.isArray(raw.recentCourses) ? raw.recentCourses : [], dashboardLinks: { enrollments: Boolean(raw.dashboardLinks?.enrollments), payments: Boolean(raw.dashboardLinks?.payments), }, }; } function greetingLabel(): string { const h = new Date().getHours(); if (h < 12) { return __('Good morning', 'sikshya'); } if (h < 18) { return __('Good afternoon', 'sikshya'); } return __('Good evening', 'sikshya'); } type OverviewPayload = { siteName?: string; stats?: Partial; recentCourses?: RecentCourse[]; dashboardLinks?: { enrollments?: boolean; payments?: boolean }; }; export function DashboardPage(props: { embedded?: boolean; config: SikshyaReactConfig; title: string }) { const { config, title } = props; const [createOpen, setCreateOpen] = useState(false); const boot = useMemo(() => resolveDashboardData(config), [config.initialData]); const [live, setLive] = useState(null); const { siteName, stats, recentCourses, dashboardLinks } = live ?? boot; const refreshOverview = useCallback(async () => { try { const d = await getSikshyaApi().get(SIKSHYA_ENDPOINTS.admin.overview); setLive((prev) => { const cur = prev ?? boot; return { siteName: typeof d.siteName === 'string' ? d.siteName : cur.siteName, stats: { ...cur.stats, ...(d.stats || {}) }, recentCourses: Array.isArray(d.recentCourses) ? d.recentCourses : cur.recentCourses, dashboardLinks: { enrollments: Boolean(d.dashboardLinks?.enrollments ?? cur.dashboardLinks.enrollments), payments: Boolean(d.dashboardLinks?.payments ?? cur.dashboardLinks.payments), }, }; }); } catch { /* keep SSR / boot data */ } }, [boot]); useEffect(() => { void refreshOverview(); }, [refreshOverview]); const dateLine = useMemo(() => { try { return new Intl.DateTimeFormat(undefined, { weekday: 'long', month: 'long', day: 'numeric', year: 'numeric', }).format(new Date()); } catch { return ''; } }, []); const draftHint = (stats.draftCourses ?? 0) > 0 ? sprintf( _n( '%d draft course not yet published', '%d draft courses not yet published', stats.draftCourses ?? 0, 'sikshya' ), stats.draftCourses ?? 0 ) : __('All courses are either live or archived', 'sikshya'); const enrollmentHint = stats.hasEnrollmentTable ? sprintf(__(' %d marked completed', 'sikshya'), stats.completedEnrollments ?? 0).trimStart() : __('Enrollments table not found — activate the plugin or run DB updates', 'sikshya'); const licensing = getLicensing(config); return ( setCreateOpen(false)} />

{dateLine}

{greetingLabel()}, {config.user.name}

{siteName ? ( <> You are managing {siteName}. Track catalog growth, learner sign-ups, and revenue from this overview. ) : ( <>{__('Track catalog growth, learner sign-ups, and revenue from this overview.', 'sikshya')} )}

{licensing && !licensing.isProActive ? (

{__('Scale your course business', 'sikshya')} {' — '} {__('Scheduled lesson access, subscriptions, gradebook, shared course staff, richer certificates, and more. Your admin layout stays familiar; upgraded plans unlock the behaviour behind each screen.', 'sikshya')}

View plans
) : null}

Primary metrics

} /> } /> } /> } />

Content library

} /> } /> } /> } />
} /> } /> } /> } />

Recently updated courses

View all
{recentCourses.length === 0 ? ( setCreateOpen(true)}>{__('Create a course', 'sikshya')}} /> ) : (
{recentCourses.map((row) => ( ))}
Course Status Updated {__('Open', 'sikshya')}
{row.title || '(No title)'} {formatPostDate(row.modified)}
)}

Shortcuts

{__('Jump to the screens you use most when running your LMS.', 'sikshya')}

setCreateOpen(true)} icon="plusCircle" title={__('New course', 'sikshya')} description={__('Name your course, we save a draft and open the builder.', 'sikshya')} /> {dashboardLinks.enrollments ? ( ) : null} {dashboardLinks.payments ? ( ) : null}

{__('Grow your course business', 'sikshya')}

  • {__('Invite instructors and assign content ownership from Users.', 'sikshya')}
  • {__('Use Reports to spot completion trends once learners are active.', 'sikshya')}
  • {__('Tune certificates, emails, and branding under Settings.', 'sikshya')}
Open reports {dashboardLinks.enrollments ? ( Enrollments ) : null} {dashboardLinks.payments ? ( Payments ) : null} Settings
); }