mirror of
https://github.com/Dvorinka/Bookra.git
synced 2026-10-28 07:41:16 +00:00
feat(dashboard): real business metrics with week-over-week trends
Dashboard KPIs were three flat counters with no trend data — the cards rendered a neutral dash where the design intends movement indicators. Summary now queries three trailing windows and emits four KPIs with real deltas: bookings this week, completed (new CompletedCount metric in both repositories), cancellations, and utilization in percentage points. KPI labels localize in the frontend via a code-to-key map so Czech operators no longer see English labels on live data. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
668a54ae1d
commit
0dc26e0c16
10 files changed
+141
-8
No files matched your search
@@ -569,6 +569,14 @@ func (s *Service) DashboardSummary(ctx context.Context, principal domain.Princip
|
||||
if err != nil {
|
||||
return domain.DashboardSummary{}, err
|
||||
}
|
||||
previousMetrics, err := s.repo.GetDashboardMetrics(ctx, membership.Tenant.ID, now.AddDate(0, 0, -7), now)
|
||||
if err != nil {
|
||||
return domain.DashboardSummary{}, err
|
||||
}
|
||||
priorMetrics, err := s.repo.GetDashboardMetrics(ctx, membership.Tenant.ID, now.AddDate(0, 0, -14), now.AddDate(0, 0, -7))
|
||||
if err != nil {
|
||||
return domain.DashboardSummary{}, err
|
||||
}
|
||||
upcomingRecords, err := s.repo.ListBookingsByTenantBetween(ctx, membership.Tenant.ID, now, weekEnd)
|
||||
if err != nil {
|
||||
return domain.DashboardSummary{}, err
|
||||
@@ -614,9 +622,10 @@ func (s *Service) DashboardSummary(ctx context.Context, principal domain.Princip
|
||||
PublicBookingURL: "/book/" + membership.Tenant.Slug,
|
||||
SetupCompletion: setupCompletion(brandName, len(locationNames), len(serviceNames), len(staffNames), scheduleCount),
|
||||
KPIs: []domain.DashboardKPI{
|
||||
{Code: "bookings_this_week", Label: "Bookings this week", Value: fmt.Sprintf("%d", metrics.BookingsCount)},
|
||||
{Code: "cancellations", Label: "Cancellations", Value: fmt.Sprintf("%d", metrics.CancellationsCount)},
|
||||
{Code: "utilization", Label: "Utilization", Value: fmt.Sprintf("%d%%", metrics.UtilizationPercent)},
|
||||
dashboardKPI("bookings_this_week", "Bookings this week", metrics.BookingsCount, previousMetrics.BookingsCount, ""),
|
||||
dashboardKPI("completed", "Completed", previousMetrics.CompletedCount, priorMetrics.CompletedCount, ""),
|
||||
dashboardKPI("cancellations", "Cancellations", metrics.CancellationsCount, previousMetrics.CancellationsCount, ""),
|
||||
dashboardKPI("utilization", "Utilization", metrics.UtilizationPercent, previousMetrics.UtilizationPercent, "%"),
|
||||
},
|
||||
UpcomingBookings: upcoming,
|
||||
AllBookings: allBookings,
|
||||
@@ -909,3 +918,20 @@ func reminderSchedule(startsAt time.Time) (time.Time, bool) {
|
||||
return time.Time{}, false
|
||||
}
|
||||
}
|
||||
|
||||
func dashboardKPI(code, label string, current int, previous int, suffix string) domain.DashboardKPI {
|
||||
delta := current - previous
|
||||
change := "0"
|
||||
trend := "neutral"
|
||||
if delta > 0 {
|
||||
change = fmt.Sprintf("+%d", delta)
|
||||
trend = "up"
|
||||
} else if delta < 0 {
|
||||
change = fmt.Sprintf("%d", delta)
|
||||
trend = "down"
|
||||
}
|
||||
if suffix != "" && change != "0" {
|
||||
change += suffix
|
||||
}
|
||||
return domain.DashboardKPI{Code: code, Label: label, Value: fmt.Sprintf("%d%s", current, suffix), Change: change, Trend: trend}
|
||||
}
|
||||
Reference in new issue
Block a user