@page "/home" @using Microsoft.AspNetCore.Authorization @using Indotalent.Infrastructure.Authorization.Identity @using Indotalent.Features.Root.Home.Cqrs @using Indotalent.Features.Root.Home @attribute [Authorize(Roles = $"{ApplicationRoles.Admin},{ApplicationRoles.Member}")] @inject HomeService HomeService @inject IJSRuntime JS CMS Dashboard - Clinic Management System
@* HEADER *@

CMS Dashboard

@* ROW 1: 12-col KPI layout *@
@* Key Metrics Card *@

CMS Overview

Key Metrics

Total Patients

@_data.FormattedTotalPatients

Active Bookings

@_data.FormattedActiveAppointments

Medical Records

@_data.FormattedTotalMedicalRecords

Completion Rate

@_data.BookingCompletionRate%

MRR: @_data.FormattedMRR FY @DateTime.Now.Year
@* 8 Small KPI Cards (row 1, cols 6-12) *@

Total Patients

@_data.FormattedTotalPatients

Active Bookings

@_data.FormattedActiveAppointments

Completion Rate

@_data.BookingCompletionRate%

Medical Records

@_data.FormattedTotalMedicalRecords

Avg Booking

@_data.FormattedAvgBooking

CVR

@_data.OverallConversionRate%

Employees

@_data.TotalEmployees

MRR

@_data.FormattedMRR

@* Metrics Matrix *@

CMS Metrics Matrix

Key indicators across all categories

@{ var mmItems = new[] { new { Title = "Total Patients", Sub = _data.FormattedTotalPatients, ColorClass = "mm-c1" }, new { Title = "Active Bookings", Sub = _data.FormattedActiveAppointments, ColorClass = "mm-c2" }, new { Title = "Completion Rate", Sub = $"{_data.BookingCompletionRate}%", ColorClass = "mm-c3" }, new { Title = "Medical Records", Sub = _data.FormattedTotalMedicalRecords, ColorClass = "mm-c4" }, new { Title = "Avg Booking", Sub = _data.FormattedAvgBooking, ColorClass = "mm-c5" }, new { Title = "CVR", Sub = $"{_data.OverallConversionRate}%", ColorClass = "mm-c6" }, new { Title = "Employees", Sub = _data.TotalEmployees.ToString(), ColorClass = "mm-c7" }, new { Title = "MRR", Sub = _data.FormattedMRR, ColorClass = "mm-c8" }, new { Title = "Products", Sub = _data.TotalProducts.ToString(), ColorClass = "mm-c9" }, new { Title = "Retention", Sub = $"{_data.PatientRetentionRate}%", ColorClass = "mm-c10" }, new { Title = "Conversion", Sub = $"{_data.OverallConversionRate}%", ColorClass = "mm-c11" }, new { Title = "SLA", Sub = $"{_data.SlaPercentage}%", ColorClass = "mm-c12" }, new { Title = "MTD Revenue", Sub = _data.FormattedSales, ColorClass = "mm-c13" }, new { Title = "MTD Purchase", Sub = _data.FormattedPurchase, ColorClass = "mm-c14" }, new { Title = "Receivable", Sub = _data.FormattedReceivable, ColorClass = "mm-c15" }, new { Title = "Payable", Sub = _data.FormattedPayable, ColorClass = "mm-c16" }, new { Title = "Draft SO", Sub = _data.PendingSO.ToString(), ColorClass = "mm-c17" }, new { Title = "Draft PO", Sub = _data.PendingPO.ToString(), ColorClass = "mm-c18" }, new { Title = "Draft Inv", Sub = _data.PendingInvoice.ToString(), ColorClass = "mm-c19" }, new { Title = "Enterprise", Sub = $"{_data.EnterprisePercentage}%", ColorClass = "mm-c20" } }; } @foreach (var item in mmItems) {

@item.Title

@item.Sub

}
@* ROW 2: Revenue Trend + Patient Sources *@

Revenue Trend

Monthly revenue vs expense

Revenue Expense

Patient Sources

By category this period

@foreach (var src in _data.LeadSources) {
@src.Source @src.Percentage%
}
@* ROW 3: Pipeline Summary + Booking Stages + Patient Activity *@

Pipeline Summary

As of @DateTime.Now.ToString("MMMM dd, yyyy")

@foreach (var ps in _data.PipelineSummary) {

@ps.Label

@(ps.FormattedValue ?? ps.Value.ToString("N0"))

}
Completion@_data.BookingCompletionRate% Patients@_data.FormattedTotalPatients

Booking Stages

Pipeline by stage

@foreach (var bs in _data.BookingStages) {

@bs.Stage

@bs.Count

}
CVR: @_data.OverallConversionRate%Active: @_data.ActiveAppointments

Patient Activity

Monthly movement

@foreach (var sa in _data.SalesActivities.Take(3)) {
+@sa.Count

@sa.Category

}
@* ROW 4: Recent Bookings + CMS Activity *@

Recent Bookings

Latest appointments

@if (_data.RecentBookings.Any()) { @foreach (var bk in _data.RecentBookings) { } } else { }
DateBooking#PatientResourceStatus
@(bk.Date?.ToString("MMM dd") ?? "-") @bk.Number @bk.Patient @bk.Resource @bk.Status
No recent bookings available
Active: @_data.ActiveAppointments Total Bookings: @_data.FormattedTotalBookings

CMS Activity

Real-time updates

Live
@if (_data.ActivityFeeds.Any()) { @foreach (var af in _data.ActivityFeeds) {
@af.AvatarText

@af.Title

@af.Detail

@af.TimeAgo

@af.ChipLabel
} } else {

No recent activity

}
@* ROW 5: Conversion Metrics + Patient Distribution + Support Metrics *@

Conversion Metrics

@DateTime.Now.Year Performance

@foreach (var cm in _data.ConversionMetrics) {

@cm.Label

@cm.Current / @cm.Target
}
Target CVR: @_data.TargetCvr% @(_data.OverallConversionRate >= 5 ? "On Track" : "Improving")

Patient Distribution

By patient group

@if (_data.PatientDistribution.Any()) { var distColors = new[] { "#f97316", "#f59e0b", "#6366f1", "#8b5cf6", "#2563eb" }; @for (int i = 0; i < Math.Min(_data.PatientDistribution.Count, 5); i++) { var pd = _data.PatientDistribution[i];

@pd.Label

@pd.Value

@pd.PctValue%
} } else {

No distribution data available

}
Total Groups: @_data.PatientDistribution.CountTotal: @_data.FormattedTotalPatients

Revenue Metrics

Financial KPIs

@foreach (var rm in _data.RevenueMetrics) {

@rm.Label

@rm.FormattedValue
}
@* ROW 6: Document Lifecycle + Recent Sales Orders *@

Document Lifecycle

System transaction volume

@foreach (var doc in _data.DocGrid) { }
Document TypeCount
@doc.Label @doc.Value
Draft SO: @_data.PendingSO Draft PO: @_data.PendingPO Draft Inv: @_data.PendingInvoice

Recent Patient Activity

Latest sales orders

@if (_data.GlobalFlowLog.Any()) { @foreach (var tx in _data.GlobalFlowLog.Take(6)) { } } else { }
Ref#CustomerQtyDateStatus
@tx.Number @tx.Partner @tx.Qty.ToString("N0") @(tx.Date?.ToString("MMM dd") ?? "-") @tx.Status
No transactions available
Total Transactions: @_data.GlobalFlowLog.Count
@code { private DashboardScmResponse _data = new(); private bool _isLoading = true; private bool _chartsInitialized = false; protected override async Task OnInitializedAsync() { var res = await HomeService.GetScmDashboardStatsAsync(); if (res?.IsSuccess == true && res.Value != null) { _data = res.Value; } } protected override async Task OnAfterRenderAsync(bool firstRender) { if (!_chartsInitialized && _data.RevenueTrend.Count > 0) { _chartsInitialized = true; await InitCharts(); } } private async Task InitCharts() { var revenueLabels = _data.RevenueTrend.Select(x => x.Label).ToArray(); var revenueData = _data.RevenueTrend.Select(x => x.SalesAmount).ToArray(); var expenseData = _data.RevenueTrend.Select(x => x.PurchaseAmount).ToArray(); var sourceLabels = _data.LeadSources.Select(x => x.Source).ToArray(); var sourceData = _data.LeadSources.Select(x => x.Percentage).Cast().ToArray(); var sourceColors = _data.LeadSources.Select(x => x.Color).ToArray(); var activityLabels = _data.SalesActivities.Take(4).Select(x => x.Category).ToArray(); var activityCounts = _data.SalesActivities.Take(4).Select(x => (double)x.Count).ToArray(); var activityColors = _data.SalesActivities.Take(4).Select(x => x.Color).ToArray(); await JS.InvokeVoidAsync("initDashboardCharts", revenueLabels, revenueData, expenseData, sourceLabels, sourceData, sourceColors, activityLabels, activityCounts, activityColors); } } @* Chart initialization script *@