diff --git a/dashboard/components/dashboard/TopCards.vue b/dashboard/components/dashboard/TopCards.vue index e073502..e319db4 100644 --- a/dashboard/components/dashboard/TopCards.vue +++ b/dashboard/components/dashboard/TopCards.vue @@ -70,27 +70,27 @@ const avgBouncingRate = computed(() => { function weightedAverage(data: number[]): number { if (data.length === 0) return 0; - + // Compute median const sortedData = [...data].sort((a, b) => a - b); const middle = Math.floor(sortedData.length / 2); - const median = sortedData.length % 2 === 0 - ? (sortedData[middle - 1] + sortedData[middle]) / 2 + const median = sortedData.length % 2 === 0 + ? (sortedData[middle - 1] + sortedData[middle]) / 2 : sortedData[middle]; - + // Define a threshold (e.g., 3 times the median) to filter out extreme values const threshold = median * 3; const filteredData = data.filter(num => num <= threshold); - + if (filteredData.length === 0) return median; // Fallback to median if all are removed - + // Compute weights based on inverse absolute deviation from median const weights = filteredData.map(num => 1 / (1 + Math.abs(num - median))); - + // Compute weighted sum and sum of weights const weightedSum = filteredData.reduce((sum, num, i) => sum + num * weights[i], 0); const sumOfWeights = weights.reduce((sum, weight) => sum + weight, 0); - + return weightedSum / sumOfWeights; } const avgSessionDuration = computed(() => { @@ -109,6 +109,9 @@ const avgSessionDuration = computed(() => { seconds += avg * 60; while (seconds >= 60) { seconds -= 60; minutes += 1; } while (minutes >= 60) { minutes -= 60; hours += 1; } + + + if (hours == 0 && minutes == 0 && seconds < 10) return `0m ~10s` return `${hours > 0 ? hours + 'h ' : ''}${minutes}m ${seconds.toFixed()}s` }); diff --git a/dashboard/components/layout/VerticalNavigation.vue b/dashboard/components/layout/VerticalNavigation.vue index 2307862..cda38f5 100644 --- a/dashboard/components/layout/VerticalNavigation.vue +++ b/dashboard/components/layout/VerticalNavigation.vue @@ -32,7 +32,7 @@ const { data: pendingInvites, refresh: refreshInvites } = useFetch('/api/project headers: useComputedHeaders({}) }); -const { userRoles } = useLoggedUser(); +const { userRoles, isPremium } = useLoggedUser(); const { projectList } = useProject(); const debugMode = process.dev; @@ -94,6 +94,9 @@ async function generatePDF() { const { actions } = useProject(); +const { showDrawer } = useDrawer(); + + const modal = useModal(); @@ -138,13 +141,6 @@ function openPendingInvites() { }">