import { useCallback, useMemo } from 'react'; import { getSikshyaApi, SIKSHYA_ENDPOINTS } from '../api'; import { EmbeddableShell } from '../components/shared/EmbeddableShell'; import { ApiErrorPanel } from '../components/shared/ApiErrorPanel'; import { ButtonPrimary, ButtonSecondary } from '../components/shared/buttons'; import { StatusBadge } from '../components/shared/list/StatusBadge'; import { useAsyncData } from '../hooks/useAsyncData'; import { useAdminRouting } from '../lib/adminRouting'; import { appViewHref } from '../lib/appUrl'; import { formatPostDate } from '../lib/formatPostDate'; import { term, termLower } from '../lib/terminology'; import type { SikshyaReactConfig } from '../types'; import { __ } from '../lib/i18n'; type EnrollmentDetail = { id: number; user_id: number; course_id: number; status: string; enrolled_date: string; completed_date: string; payment_method: string; transaction_id: string; amount: number; progress: number; notes: string; learner_name: string; learner_email: string; learner_login: string; course_title: string; course_status: string; }; type DetailsResponse = { success?: boolean; enrollment?: EnrollmentDetail; message?: string }; /** * Enrollment Details page. URL: `?page=sikshya&view=enrollment-detail&id=`. * * Linked from the Enrollments list (student name column). Shows the full * row joined with the user + course post, plus the progress % and payment * trail in one scannable layout. */ export function EnrollmentDetailsPage(props: { config: SikshyaReactConfig; title: string; embedded?: boolean }) { const { config, embedded, title } = props; const { route, navigateView } = useAdminRouting(); const adminBase = config.adminUrl.replace(/\/?$/, '/'); const enrollmentId = useMemo(() => parseInt(route.query?.id || '0', 10) || 0, [route.query]); const student = term(config, 'student'); const course = term(config, 'course'); const enrollmentLower = termLower(config, 'enrollment'); const loader = useCallback(async () => { if (!enrollmentId) throw new Error(__('Missing enrollment id.', 'sikshya')); return getSikshyaApi().get(SIKSHYA_ENDPOINTS.admin.enrollmentDetail(enrollmentId)); }, [enrollmentId]); const { loading, data, error, refetch } = useAsyncData(loader, [enrollmentId]); const e = data?.enrollment; const progressPct = e ? Math.max(0, Math.min(100, Math.round(e.progress))) : 0; return ( navigateView('enrollments')}> {__('Back to enrollments', 'sikshya')} refetch()}> {__('Refresh', 'sikshya')} } > {error ? (
refetch()} />
) : null} {loading ? (
{__('Loading enrollment…', 'sikshya')}
) : !e ? (
{__('Enrollment not found.', 'sikshya')}
) : (
{/* Hero card: status + progress at a glance */}
{e.completed_date ? ( {__('Completed', 'sikshya')} · {formatPostDate(e.completed_date)} ) : null}

{e.learner_name || `${student} #${e.user_id}`}

{e.learner_email || '—'}

{__('Enrolled in', 'sikshya')}{' '} {e.course_id > 0 ? ( {e.course_title || `${course} #${e.course_id}`} ) : ( '—' )}{' '} · {formatPostDate(e.enrolled_date)}

{__('Progress', 'sikshya')}

{progressPct}%
{/* Detail grid */}
{__('Open in WP admin →', 'sikshya')} } /> 0 ? ( {__('Open in course builder →', 'sikshya')} ) : ( '—' ) } /> 0 ? e.amount.toFixed(2) : __('Free', 'sikshya')} />
)} ); } function DetailCard(props: { title: string; children: React.ReactNode }) { return (

{props.title}

{props.children}
); } function DetailRow(props: { label: string; value: React.ReactNode }) { return (
{props.label}
{props.value}
); }