Ctrl K
ComunidadGuías…

src/stores/main.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import type { AppUsageByApp, AppUsageGlobal, Plan } from './../services/console'
import type { User } from '~/services/consoleClient'
import type { Database } from '~/types/database.types'
import { acceptHMRUpdate, defineStore } from 'pinia'
import { ref, watch } from 'vue'
import {
  clearSpoof,
  findBestPlan,
  getAllDashboard,
  getLocalConfig,
  getTotalStorage,
  isPlatformAdmin,
  normalizeDashboardDateRange,
  useConsole,
} from '~/services/console'
import { getDaysBetweenDates } from '~/services/conversion'
import { normalizeToUtcStartOfDay } from '~/services/date'
import { reset } from '~/services/posthog'
import { clearSimulatorSessions } from '~/services/simulatorSessions'
import { setWebsitePaidUserCookie } from '~/services/websiteAuthCookie'
import { createDeferredPromise } from '../utils/promise'

interface TotalStats {
  mau: number
  storage: number
  bandwidth: number
  build_time_seconds: number
}

export const useMainStore = defineStore('main', () => {
  const auth = ref<User | undefined>()
  const authGeneration = ref(0)
  const path = ref('')
  const user = ref<Database['public']['Tables']['users']['Row']>()
  const plans = ref<Plan[]>([])
  const totalStats = ref<TotalStats>({
    mau: 0,
    storage: 0,
    bandwidth: 0,
    build_time_seconds: 0,
  })
  const bestPlan = ref<string>('')
  const statsTime = ref<{ next_run: string, last_run: string }>({
    next_run: '',
    last_run: '',
  })
  const isAdmin = ref<boolean>(false)
  let platformAdminStatusGeneration = -1
  let platformAdminStatusEpoch = 0
  let platformAdminStatusRequest: { epoch: number, generation: number, promise: Promise<boolean> } | undefined
  const dashboard = ref<AppUsageGlobal[]>([])
  const dashboardOrgId = ref<string | null>(null)
  const dashboardPlanOrgId = ref<string | null>(null)
  const dashboardByapp = ref<AppUsageByApp[]>([])
  const totalDevices = ref<number>(0)
  const totalStorage = ref<number>(0)
  const dashboardFetched = ref<boolean>(false)
  const _initialLoadPromise = ref(createDeferredPromise<boolean>())
  let dashboardLoadId = 0
  let dashboardRequest: { orgId: string, start: string, end: string, generation: number, promise: Promise<void> } | undefined

  const totalDownload = ref<number>(0)

  const invalidatePlatformAdminStatus = () => {
    platformAdminStatusEpoch += 1
    platformAdminStatusGeneration = -1
    platformAdminStatusRequest = undefined
    isAdmin.value = false
  }

  const resolvePlatformAdminStatus = async () => {
    const generation = authGeneration.value
    const epoch = platformAdminStatusEpoch
    if (platformAdminStatusGeneration === generation)
      return isAdmin.value
    if (platformAdminStatusRequest?.generation === generation && platformAdminStatusRequest.epoch === epoch)
      return platformAdminStatusRequest.promise

    const promise: Promise<boolean> = isPlatformAdmin()
      .then((status) => {
        if (authGeneration.value === generation && platformAdminStatusEpoch === epoch) {
          isAdmin.value = status
          platformAdminStatusGeneration = generation
          if (status)
            setWebsitePaidUserCookie(true)
        }
        return status
      })
      .finally(() => {
        if (platformAdminStatusRequest?.promise === promise)
          platformAdminStatusRequest = undefined
      })

    platformAdminStatusRequest = { epoch, generation, promise }
    return promise
  }

  const refreshPlatformAdminStatus = () => {
    invalidatePlatformAdminStatus()
    return resolvePlatformAdminStatus()
  }

  watch(auth, (next, previous) => {
    authGeneration.value += 1
    if (previous?.id !== next?.id)
      clearSimulatorSessions()
    dashboardOrgId.value = null
    dashboardPlanOrgId.value = null
    bestPlan.value = ''
    invalidatePlatformAdminStatus()
  }, { flush: 'sync' })

  const logout = async () => {
    const capgo = useConsole()
    const config = getLocalConfig()
    const { error } = await capgo.auth.signOut()
    auth.value = undefined
    user.value = undefined
    isAdmin.value = false
    reset(config.apiHost)
    clearSpoof()
    if (error)
      console.error('Failed to log out', error)
  }

  const getTotalStats: () => TotalStats = () => {
    return dashboard.value.reduce((acc: TotalStats, cur: AppUsageGlobal) => {
      acc.mau += cur.mau
      acc.bandwidth += cur.bandwidth
      acc.storage += cur.storage
      acc.build_time_seconds += cur.build_time_seconds
      return acc
    }, {
      mau: 0,
      bandwidth: 0,
      storage: 0,
      build_time_seconds: 0,
    })
  }

  const calculateMonthDay = (subscriptionStart: string | undefined) => {
    // Parse dates consistently using UTC day boundaries (dashboard stats are UTC-bucketed)
    const startDate = normalizeToUtcStartOfDay(subscriptionStart ? new Date(subscriptionStart) : new Date())
    const currentDate = normalizeToUtcStartOfDay()

    const daysInMonth = new Date(Date.UTC(currentDate.getUTCFullYear(), currentDate.getUTCMonth() + 1, 0)).getUTCDate()
    return (getDaysBetweenDates(startDate, currentDate) % daysInMonth || daysInMonth) - 1
  }

  const updateDashboard = async (currentOrgId: string, rangeStart?: string, rangeEnd?: string) => {
    const { start, end } = normalizeDashboardDateRange(rangeStart, rangeEnd)
    const generation = authGeneration.value
    if (dashboardRequest?.orgId === currentOrgId && dashboardRequest.start === start && dashboardRequest.end === end && dashboardRequest.generation === generation)
      return dashboardRequest.promise

    if (dashboardOrgId.value !== currentOrgId)
      bestPlan.value = ''
    dashboardPlanOrgId.value = null
    const loadId = ++dashboardLoadId
    const isCurrent = () => loadId === dashboardLoadId && generation === authGeneration.value
    const request = (async () => {
      try {
        const dashboardRes = await getAllDashboard(currentOrgId, start, end)
        if (!isCurrent())
          return
        dashboardOrgId.value = currentOrgId
        dashboard.value = dashboardRes.global
        dashboardByapp.value = dashboardRes.byApp

        const monthDay = calculateMonthDay(start)
        totalDevices.value = dashboard.value[monthDay]?.mau ?? 0
        totalDownload.value = dashboard.value[monthDay]?.get ?? 0

        const storage = await getTotalStorage()
        if (!isCurrent())
          return
        totalStorage.value = storage
        totalStats.value = getTotalStats()

        const plan = await findBestPlan(totalStats.value)
        if (!isCurrent())
          return
        bestPlan.value = plan
        dashboardPlanOrgId.value = currentOrgId
        dashboardFetched.value = true
        _initialLoadPromise.value.resolve(true)
      }
      catch (error) {
        if (!isCurrent())
          return
        _initialLoadPromise.value.reject(error)
        throw error
      }
    })().finally(() => {
      if (dashboardRequest?.promise === request)
        dashboardRequest = undefined
    })

    dashboardRequest = { orgId: currentOrgId, start, end, generation, promise: request }
    return request
  }

  const filterDashboard = (appId: string) => {
    return dashboardByapp.value.filter(d => d.app_id === appId)
  }

  const getTotalStatsByApp = async (appId: string, subscriptionStart?: string) => {
    const monthDay = calculateMonthDay(subscriptionStart)
    const appData = dashboardByapp.value.filter(d => d.app_id === appId)
    return appData[monthDay]?.get ?? 0
  }
  const getTotalMauByApp = async (appId: string, subscriptionStart?: string) => {
    // Get the app's dashboard data
    const appData = dashboardByapp.value.filter(d => d.app_id === appId)

    // Calculate how many days into the billing cycle we are
    const startDate = normalizeToUtcStartOfDay(subscriptionStart ? new Date(subscriptionStart) : new Date())
    const currentDate = normalizeToUtcStartOfDay()

    // Calculate days in billing cycle
    const daysInBillingCycle = Math.floor((currentDate.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24)) + 1

    // Accumulate only the MAU values within the current billing cycle
    let totalMau = 0
    const dataLength = Math.min(daysInBillingCycle, appData.length)
    for (let i = 0; i < dataLength; i++) {
      if (appData[i]?.mau !== undefined) {
        totalMau += appData[i].mau
      }
    }
    return totalMau
  }

  const awaitInitialLoad = () => {
    return _initialLoadPromise.value.promise
  }

  return {
    auth,
    authGeneration,
    statsTime,
    plans,
    isAdmin,
    invalidatePlatformAdminStatus,
    refreshPlatformAdminStatus,
    resolvePlatformAdminStatus,
    totalStorage,
    totalStats,
    bestPlan,
    totalDevices,
    totalDownload,
    dashboardFetched,
    updateDashboard,
    filterDashboard,
    dashboard,
    dashboardOrgId,
    dashboardPlanOrgId,
    awaitInitialLoad,
    dashboardByapp,
    getTotalMauByApp,
    getTotalStatsByApp,
    user,
    path,
    logout,
  }
})

if (import.meta.hot)
  import.meta.hot.accept(acceptHMRUpdate(useMainStore, import.meta.hot))