Record playback heartbeats via POST /api/v1/videos/engagement/heartbeat and expose completion, replay, and drop-off rates on the analytics dashboard. Co-authored-by: Cursor <cursoragent@cursor.com>
130 lines
6.2 KiB
Go
130 lines
6.2 KiB
Go
package handlers
|
|
|
|
import (
|
|
dbgen "Yimaru-Backend/gen/db"
|
|
"Yimaru-Backend/internal/domain"
|
|
"time"
|
|
|
|
"github.com/jackc/pgx/v5/pgtype"
|
|
)
|
|
|
|
type analyticsQueryParams struct {
|
|
UsersSummary dbgen.AnalyticsUsersSummaryParams
|
|
UsersByRole dbgen.AnalyticsUsersByRoleParams
|
|
UsersByStatus dbgen.AnalyticsUsersByStatusParams
|
|
UsersByAgeGroup dbgen.AnalyticsUsersByAgeGroupParams
|
|
UsersByEducationLevel dbgen.AnalyticsUsersByEducationLevelParams
|
|
UsersByOccupation dbgen.AnalyticsUsersByOccupationParams
|
|
UsersByLearningGoal dbgen.AnalyticsUsersByLearningGoalParams
|
|
UsersByLanguageChallange dbgen.AnalyticsUsersByLanguageChallangeParams
|
|
UsersByKnowledgeLevel dbgen.AnalyticsUsersByKnowledgeLevelParams
|
|
UsersByCountry dbgen.AnalyticsUsersByCountryParams
|
|
UsersByRegion dbgen.AnalyticsUsersByRegionParams
|
|
UserRegistrationsSeries dbgen.AnalyticsUserRegistrationsLast30DaysParams
|
|
|
|
SubscriptionsSummary dbgen.AnalyticsSubscriptionsSummaryParams
|
|
SubscriptionsByStatus dbgen.AnalyticsSubscriptionsByStatusParams
|
|
RevenueByPlan dbgen.AnalyticsRevenueByPlanParams
|
|
NewSubscriptionsSeries dbgen.AnalyticsNewSubscriptionsLast30DaysParams
|
|
|
|
PaymentsSummary dbgen.AnalyticsPaymentsSummaryParams
|
|
PaymentsByStatus dbgen.AnalyticsPaymentsByStatusParams
|
|
PaymentsByMethod dbgen.AnalyticsPaymentsByMethodParams
|
|
RevenueSeries dbgen.AnalyticsRevenueLast30DaysParams
|
|
|
|
QuestionsCounts dbgen.AnalyticsQuestionsCountsParams
|
|
QuestionsByType dbgen.AnalyticsQuestionsByTypeParams
|
|
QuestionSetsByType dbgen.AnalyticsQuestionSetsByTypeParams
|
|
|
|
NotificationsSummary dbgen.AnalyticsNotificationsSummaryParams
|
|
NotificationsChannel dbgen.AnalyticsNotificationsByChannelParams
|
|
NotificationsType dbgen.AnalyticsNotificationsByTypeParams
|
|
|
|
IssuesSummary dbgen.AnalyticsIssuesSummaryParams
|
|
IssuesByStatus dbgen.AnalyticsIssuesByStatusParams
|
|
IssuesByType dbgen.AnalyticsIssuesByTypeParams
|
|
|
|
TeamSummary dbgen.AnalyticsTeamSummaryParams
|
|
TeamByRole dbgen.AnalyticsTeamByRoleParams
|
|
TeamByStatus dbgen.AnalyticsTeamByStatusParams
|
|
|
|
VideoEngagementSummary dbgen.AnalyticsVideoEngagementSummaryParams
|
|
VideoDropOffByCheckpoint dbgen.AnalyticsVideoDropOffByCheckpointParams
|
|
}
|
|
|
|
func newAnalyticsQueryParams(f domain.AnalyticsDateFilter) analyticsQueryParams {
|
|
ref := pgAnalyticsDate(f.RefDate)
|
|
rs, re := pgAnalyticsTimestamptzPtr(f.RangeStart), pgAnalyticsTimestamptzPtr(f.RangeEnd)
|
|
series := dbgen.AnalyticsUserRegistrationsLast30DaysParams{
|
|
SeriesStart: pgAnalyticsDate(f.SeriesStart),
|
|
SeriesEnd: pgAnalyticsDate(f.SeriesEnd),
|
|
RangeStart: rs,
|
|
RangeEnd: re,
|
|
}
|
|
|
|
return analyticsQueryParams{
|
|
UsersSummary: dbgen.AnalyticsUsersSummaryParams{RefDate: ref, RangeStart: rs, RangeEnd: re},
|
|
UsersByRole: dbgen.AnalyticsUsersByRoleParams{RangeStart: rs, RangeEnd: re},
|
|
UsersByStatus: dbgen.AnalyticsUsersByStatusParams{RangeStart: rs, RangeEnd: re},
|
|
UsersByAgeGroup: dbgen.AnalyticsUsersByAgeGroupParams{RangeStart: rs, RangeEnd: re},
|
|
UsersByEducationLevel: dbgen.AnalyticsUsersByEducationLevelParams{RangeStart: rs, RangeEnd: re},
|
|
UsersByOccupation: dbgen.AnalyticsUsersByOccupationParams{RangeStart: rs, RangeEnd: re},
|
|
UsersByLearningGoal: dbgen.AnalyticsUsersByLearningGoalParams{RangeStart: rs, RangeEnd: re},
|
|
UsersByLanguageChallange: dbgen.AnalyticsUsersByLanguageChallangeParams{RangeStart: rs, RangeEnd: re},
|
|
UsersByKnowledgeLevel: dbgen.AnalyticsUsersByKnowledgeLevelParams{RangeStart: rs, RangeEnd: re},
|
|
UsersByCountry: dbgen.AnalyticsUsersByCountryParams{RangeStart: rs, RangeEnd: re},
|
|
UsersByRegion: dbgen.AnalyticsUsersByRegionParams{RangeStart: rs, RangeEnd: re},
|
|
UserRegistrationsSeries: series,
|
|
|
|
SubscriptionsSummary: dbgen.AnalyticsSubscriptionsSummaryParams{RefDate: ref, RangeStart: rs, RangeEnd: re},
|
|
SubscriptionsByStatus: dbgen.AnalyticsSubscriptionsByStatusParams{RangeStart: rs, RangeEnd: re},
|
|
RevenueByPlan: dbgen.AnalyticsRevenueByPlanParams{RangeStart: rs, RangeEnd: re},
|
|
NewSubscriptionsSeries: dbgen.AnalyticsNewSubscriptionsLast30DaysParams{
|
|
SeriesStart: series.SeriesStart,
|
|
SeriesEnd: series.SeriesEnd,
|
|
RangeStart: rs,
|
|
RangeEnd: re,
|
|
},
|
|
|
|
PaymentsSummary: dbgen.AnalyticsPaymentsSummaryParams{RangeStart: rs, RangeEnd: re},
|
|
PaymentsByStatus: dbgen.AnalyticsPaymentsByStatusParams{RangeStart: rs, RangeEnd: re},
|
|
PaymentsByMethod: dbgen.AnalyticsPaymentsByMethodParams{RangeStart: rs, RangeEnd: re},
|
|
RevenueSeries: dbgen.AnalyticsRevenueLast30DaysParams{
|
|
SeriesStart: series.SeriesStart,
|
|
SeriesEnd: series.SeriesEnd,
|
|
RangeStart: rs,
|
|
RangeEnd: re,
|
|
},
|
|
|
|
QuestionsCounts: dbgen.AnalyticsQuestionsCountsParams{RangeStart: rs, RangeEnd: re},
|
|
QuestionsByType: dbgen.AnalyticsQuestionsByTypeParams{RangeStart: rs, RangeEnd: re},
|
|
QuestionSetsByType: dbgen.AnalyticsQuestionSetsByTypeParams{RangeStart: rs, RangeEnd: re},
|
|
|
|
NotificationsSummary: dbgen.AnalyticsNotificationsSummaryParams{RangeStart: rs, RangeEnd: re},
|
|
NotificationsChannel: dbgen.AnalyticsNotificationsByChannelParams{RangeStart: rs, RangeEnd: re},
|
|
NotificationsType: dbgen.AnalyticsNotificationsByTypeParams{RangeStart: rs, RangeEnd: re},
|
|
|
|
IssuesSummary: dbgen.AnalyticsIssuesSummaryParams{RangeStart: rs, RangeEnd: re},
|
|
IssuesByStatus: dbgen.AnalyticsIssuesByStatusParams{RangeStart: rs, RangeEnd: re},
|
|
IssuesByType: dbgen.AnalyticsIssuesByTypeParams{RangeStart: rs, RangeEnd: re},
|
|
|
|
TeamSummary: dbgen.AnalyticsTeamSummaryParams{RangeStart: rs, RangeEnd: re},
|
|
TeamByRole: dbgen.AnalyticsTeamByRoleParams{RangeStart: rs, RangeEnd: re},
|
|
TeamByStatus: dbgen.AnalyticsTeamByStatusParams{RangeStart: rs, RangeEnd: re},
|
|
|
|
VideoEngagementSummary: dbgen.AnalyticsVideoEngagementSummaryParams{RangeStart: rs, RangeEnd: re},
|
|
VideoDropOffByCheckpoint: dbgen.AnalyticsVideoDropOffByCheckpointParams{RangeStart: rs, RangeEnd: re},
|
|
}
|
|
}
|
|
|
|
func pgAnalyticsDate(t time.Time) pgtype.Date {
|
|
return pgtype.Date{Time: t.UTC(), Valid: true}
|
|
}
|
|
|
|
func pgAnalyticsTimestamptzPtr(t *time.Time) pgtype.Timestamptz {
|
|
if t == nil {
|
|
return pgtype.Timestamptz{Valid: false}
|
|
}
|
|
return pgtype.Timestamptz{Time: t.UTC(), Valid: true}
|
|
}
|