Analytics Commands
Przegląd
Dział zatytułowany „Przegląd”Analytics API dostarcza dane do dashboardu, wykresów i raportów. Wszystkie komendy wymagają aktywnej sesji i obsługują deduplikację zapytań (cache).
Service: src/services/analyticsService.ts
Types: src/types/analytics.ts
Hook: src/components/analytics/dashboard/hooks/useAnalyticsData.ts
Analytics Scope
Dział zatytułowany „Analytics Scope”Każde zapytanie analityczne wymaga AnalyticsScope:
interface AnalyticsScope { dateRange: { start: Date; end: Date; }; clinicId?: string; // Z user.clinic_id period?: AnalyticsPeriod; // 'week' | 'month' | 'year'}Scope Transformation
Dział zatytułowany „Scope Transformation”// FE → Backend payloadtoScopePayload(scope) → { clinic_id: scope.clinicId, date_range: { start: scope.dateRange.start.toISOString(), end: scope.dateRange.end.toISOString() }, period: scope.period // optional}
// Cache key dla deduplikacjianalyticsScopeKey(payload) → "clinic:range:period"Commands Reference
Dział zatytułowany „Commands Reference”Dashboard Stats
Dział zatytułowany „Dashboard Stats”// get_dashboard_statsanalyticsService.getDashboardStats(scope: AnalyticsScope): Promise<DashboardStats>
// Responseinterface DashboardStats { totalVisits: number; totalPatients: number; avgVisitDuration: number; completionRate: number; // ...}Usage: Dashboard główny (ostatnie 30 dni), zakładka Overview.
Visit Trends
Dział zatytułowany „Visit Trends”// get_visit_trendsanalyticsService.getVisitTrends( scope: AnalyticsScope & { period: AnalyticsPeriod }): Promise<VisitTrend[]>
// Responseinterface VisitTrend { date: string; count: number;}Aggregation: Trendy wizyt z agregacją wg period (tydzień/miesiąc/rok).
Visit Trends Comparison
Dział zatytułowany „Visit Trends Comparison”// get_visit_trends_period_compare// Porównanie dwóch okresów z tą samą periodyzacjąanalyticsService.getVisitTrendsPeriodCompare( scope: AnalyticsScope & { period: AnalyticsPeriod }): Promise<VisitTrendsCompare>
// get_visit_trends_compare// Porównanie bez periodyzacjianalyticsService.getVisitTrendsCompare( scope: AnalyticsScope): Promise<VisitTrendsCompare>
// Responseinterface VisitTrendsCompare { current: VisitTrend[]; previous: VisitTrend[];}Visit Type Distribution
Dział zatytułowany „Visit Type Distribution”// get_visit_type_distributionanalyticsService.getVisitTypeDistribution( scope: AnalyticsScope): Promise<VisitTypeDistribution[]>
// Response (z kolorem dodanym przez FE)interface VisitTypeDistribution { type: string; count: number; percentage: number; color: string; // Dodane przez getVisitTypeColor()}Visit Type Colors
Dział zatytułowany „Visit Type Colors”FE przypisuje kolory na podstawie typu wizyty:
const VISIT_TYPE_COLORS = { consultation: 'var(--color-blue)', vaccination: 'var(--color-green)', surgery: 'var(--color-red)', emergency: 'var(--color-orange)', other: 'var(--color-gray)',};
// Fuzzy mapping dla PL nazwgetVisitTypeColor('pierwsza wizyta') → VISIT_TYPE_COLORS.consultationgetVisitTypeColor('szczepienie') → VISIT_TYPE_COLORS.vaccinationgetVisitTypeColor('usg') → VISIT_TYPE_COLORS.otherStaff Performance
Dział zatytułowany „Staff Performance”// get_staff_performanceanalyticsService.getStaffPerformance( scope: AnalyticsScope): Promise<StaffPerformance[]>
// Responseinterface StaffPerformance { staffId: string; staffName: string; totalVisits: number; avgDuration: number; completionRate: number;}Staff Time Distribution
Dział zatytułowany „Staff Time Distribution”// get_staff_time_distributionanalyticsService.getStaffTimeDistribution( scope: AnalyticsScope): Promise<StaffTimeDistribution[]>
// Responseinterface StaffTimeDistribution { staffId: string; staffName: string; visitTypes: Array<{ type: string; minutes: number; }>;}Patient Demographics
Dział zatytułowany „Patient Demographics”// get_patient_demographicsanalyticsService.getPatientDemographics( scope: AnalyticsScope): Promise<PatientDemographics[]>
// Responseinterface PatientDemographics { species: string; count: number; percentage: number;}Time Slot Analysis
Dział zatytułowany „Time Slot Analysis”// get_time_slot_analysisanalyticsService.getTimeSlotAnalysis( scope: AnalyticsScope): Promise<TimeSlotAnalysis[]>
// Responseinterface TimeSlotAnalysis { hour: number; // 0-23 count: number; avgDuration: number;}Day/Hour Heatmap
Dział zatytułowany „Day/Hour Heatmap”// get_day_hour_heatmapanalyticsService.getDayHourHeatmap( scope: AnalyticsScope): Promise<DayHourHeatCell[]>
// Responseinterface DayHourHeatCell { day: number; // 0-6 (Sunday-Saturday) hour: number; // 0-23 count: number;}Overview Bundle
Dział zatytułowany „Overview Bundle”// get_overview_bundle// Zbiorczy pakiet do szybkiego ładowania zakładki OverviewanalyticsService.getOverviewBundle( scope: AnalyticsScope): Promise<OverviewBundle>
// Responseinterface OverviewBundle { stats: DashboardStats; compare: { current: VisitTrend[]; previous: VisitTrend[]; };}Revenue Data
Dział zatytułowany „Revenue Data”// get_revenue_data// Jedyna komenda bez AnalyticsScopeanalyticsService.getRevenueData(months: number = 12): Promise<RevenueData[]>
// Responseinterface RevenueData { month: string; // "2024-01", "2024-02", ... revenue: number; visitCount: number;}Hook: useAnalyticsData
Dział zatytułowany „Hook: useAnalyticsData”Plik: src/components/analytics/dashboard/hooks/useAnalyticsData.ts
Parameters
Dział zatytułowany „Parameters”useAnalyticsData({ dateRange: { start: Date; end: Date }, activeTab: 'overview' | 'visits' | 'patients' | 'performance'})Loading Strategy
Dział zatytułowany „Loading Strategy”flowchart TB subgraph "Per Tab Loading" overview[Overview Tab] --> getOverviewBundle visits[Visits Tab] --> getVisitTypeDistribution visits --> getTimeSlotAnalysis patients[Patients Tab] --> getPatientDemographics performance[Performance Tab] --> getStaffPerformance performance --> getDayHourHeatmap performance --> getStaffTimeDistribution endTransformations
Dział zatytułowany „Transformations”| Data | Transformation |
|---|---|
visitTypes | translateVisitType(item.type, t) |
patientDemographics | translateSpecies(item.species) |
staffTimeDistribution | Lokalizacja visitTypes[].type |
Insights
Dział zatytułowany „Insights”// Helpery do generowania insightówgetPeakHourInsight(timeSlots) // "Najwięcej wizyt o 10:00"getBestDayHourInsight(heatmap) // "Najlepszy dzień: Poniedziałek 9:00-11:00"Caching & Deduplication
Dział zatytułowany „Caching & Deduplication”Wszystkie komendy używają dedupeGet z kluczem cache:
// Patternanalytics:<sessionId>:<endpoint>:<scopeKey>
// Przykładyanalytics:abc123:dashboard:clinic1:2024-01-01:2024-01-31:monthanalytics:abc123:visitTypeDistribution:clinic1:2024-01-01:2024-01-31analytics:abc123:revenue:12Error Handling
Dział zatytułowany „Error Handling”try { const stats = await analyticsService.getDashboardStats(scope);} catch (error) { if (error instanceof SessionNotReadyError) { // Propagowane dalej throw error; } // Inne błędy logowane i rzucane secureLogger.error('[Analytics] getDashboardStats failed', error); throw error;}UI Integration
Dział zatytułowany „UI Integration”| Component | Data Source |
|---|---|
Dashboard.tsx | getDashboardStats (30 dni) |
AnalyticsDashboard.tsx | useAnalyticsData |
KpiSummary.tsx | stats z useAnalyticsData |
PerformanceTablePanel.tsx | staffPerformance |
Powiązane dokumenty
Dział zatytułowany „Powiązane dokumenty”- Dashboard Overview - Główny dashboard
- Settings Commands - Preferencje użytkownika