@@ -4,109 +4,65 @@ import type { AdminProjectsList } from '~/server/api/admin/projects';
44
55definePageMeta ({ layout: ' dashboard' });
66
7- const { data : projects } = await useFetch <AdminProjectsList []>(' /api/admin/projects' , signHeaders ());
7+ const { data : projectsAggregatedResponseData } = await useFetch <AdminProjectsList []>(' /api/admin/projects' , signHeaders ());
88const { data : counts } = await useFetch (' /api/admin/counts' , signHeaders ());
99
10-
11- type TProjectsGrouped = {
12- user: {
13- name: string ,
14- email: string ,
15- given_name: string ,
16- picture: string ,
17- created_at: Date
18- },
19- projects: {
20- _id: string ,
21- premium: boolean ,
22- premium_type: number ,
23- created_at: Date ,
24- project_name: string ,
25- total_visits: number ,
26- total_events: number ,
27- total_sessions: number
28- }[]
10+ function onHideClicked() {
11+ isAdminHidden .value = true ;
2912}
3013
31- const projectsGrouped = computed (() => {
32-
33- if (! projects .value ) return [];
34-
35- const result: TProjectsGrouped [] = [];
36-
37- for (const project of projects .value ) {
38-
39- if (! project .user ) continue ;
40-
41-
42- const target = result .find (e => e .user .email == project .user .email );
43-
44- if (target ) {
45-
46- target .projects .push ({
47- _id: project ._id ,
48- created_at: project .created_at ,
49- premium_type: project .premium_type ,
50- premium: project .premium ,
51- project_name: project .project_name ,
52- total_events: project .total_events ,
53- total_visits: project .total_visits ,
54- total_sessions: project .total_sessions
55- });
56-
57- } else {
58-
59- const item: TProjectsGrouped = {
60- user: project .user ,
61- projects: [{
62- _id: project ._id ,
63- created_at: project .created_at ,
64- premium: project .premium ,
65- premium_type: project .premium_type ,
66- project_name: project .project_name ,
67- total_events: project .total_events ,
68- total_visits: project .total_visits ,
69- total_sessions: project .total_sessions
70- }]
71- }
7214
73- result .push (item );
74-
75- }
15+ const projectsAggregated = computed (() => {
16+ return projectsAggregatedResponseData .value ?.sort ((a , b ) => {
17+ const sumVisitsA = a .projects .reduce ((pa , pe ) => pa + (pe .counts ?.visits || 0 ) + (pe .counts ?.events || 0 ), 0 );
18+ const sumVisitsB = b .projects .reduce ((pa , pe ) => pa + (pe .counts ?.visits || 0 ) + (pe .counts ?.events || 0 ), 0 );
19+ return sumVisitsB - sumVisitsA ;
20+ });
21+ })
7622
77- }
23+ const premiumCount = computed (() => {
24+ let premiums = 0 ;
25+ projectsAggregated .value ?.forEach (e => {
26+ e .projects .forEach (p => {
27+ if (p .premium ) premiums ++ ;
28+ });
7829
79- result .sort ((sa , sb ) => {
80- const ca = sa .projects .reduce ((a , e ) => a + (e .total_visits + e .total_events ), 0 );
81- const cb = sb .projects .reduce ((a , e ) => a + (e .total_visits + e .total_events ), 0 );
82- return cb - ca ;
8330 })
31+ return premiums ;
32+ })
8433
85- return result ;
86-
87- });
8834
89- function onHideClicked() {
90- isAdminHidden .value = true ;
91- }
35+ const activeProjects = computed (() => {
36+ let actives = 0 ;
9237
93- const premiumCount = computed (() => {
94- let premiums = 0 ;
95- projects .value ?.forEach (e => {
96- if (e .premium ) premiums ++ ;
38+ projectsAggregated .value ?.forEach (e => {
39+ e .projects .forEach (p => {
40+ if (! p .counts ) return ;
41+ if (! p .counts .updated_at ) return ;
42+ const updated_at = new Date (p .counts .updated_at ).getTime ();
43+ if (updated_at < Date .now () - 1000 * 60 * 60 * 24 ) return ;
44+ actives ++ ;
45+ });
9746 })
98- return premiums ;
99- })
47+ return actives ;
48+ });
10049
10150
10251
10352const totalVisits = computed (() => {
104- return projects .value ?.reduce ((a , e ) => a + e .total_visits , 0 ) || 0 ;
53+ return projectsAggregated .value ?.reduce ((a , e ) => {
54+ return a + e .projects .reduce ((pa , pe ) => pa + (pe .counts ?.visits || 0 ), 0 );
55+ }, 0 ) || 0 ;
10556});
57+
10658const totalEvents = computed (() => {
107- return projects .value ?.reduce ((a , e ) => a + e .total_events , 0 ) || 0 ;
59+ return projectsAggregated .value ?.reduce ((a , e ) => {
60+ return a + e .projects .reduce ((pa , pe ) => pa + (pe .counts ?.events || 0 ), 0 );
61+ }, 0 ) || 0 ;
10862});
10963
64+
65+
11066const details = ref <any >();
11167const showDetails = ref <boolean >(false );
11268async function getProjectDetails(project_id : string ) {
@@ -118,6 +74,28 @@ async function resetCount(project_id: string) {
11874 await $fetch (` /api/admin/reset_count?project_id=${project_id } ` , signHeaders ());
11975}
12076
77+
78+ function dateDiffDays(a : string ) {
79+ return (Date .now () - new Date (a ).getTime ()) / (1000 * 60 * 60 * 24 )
80+ }
81+
82+ function getLogBg(last_logged_at ? : string ) {
83+
84+ const day = 1000 * 60 * 60 * 24 ;
85+ const week = 1000 * 60 * 60 * 24 * 7 ;
86+
87+ const lastLoggedAtDate = new Date (last_logged_at || 0 );
88+
89+ if (lastLoggedAtDate .getTime () > Date .now () - day ) {
90+ return ' bg-green-500'
91+ } else if (lastLoggedAtDate .getTime () > Date .now () - week ) {
92+ return ' bg-yellow-500'
93+ } else {
94+ return ' bg-red-500'
95+ }
96+
97+ }
98+
12199 </script >
122100
123101
@@ -144,7 +122,7 @@ async function resetCount(project_id: string) {
144122
145123 <Card class =" p-4" >
146124
147- <div class =" grid grid-cols-2" >
125+ <div class =" grid grid-cols-2 gap-1 " >
148126 <div >
149127 Users: {{ counts?.users }}
150128 </div >
@@ -154,6 +132,10 @@ async function resetCount(project_id: string) {
154132 <div >
155133 Total visits: {{ formatNumberK(totalVisits) }}
156134 </div >
135+ <div >
136+ Active: {{ activeProjects }} |
137+ Dead: {{ (counts?.projects || 0) - activeProjects }}
138+ </div >
157139 <div >
158140 Total events: {{ formatNumberK(totalEvents) }}
159141 </div >
@@ -162,17 +144,29 @@ async function resetCount(project_id: string) {
162144 </Card >
163145
164146
165- <div v-for =" item of projectsGrouped" class =" bg-menu p-4 rounded-xl flex flex-col gap-2 w-full relative" >
147+ <Card >
148+ <!-- <USelectMenu></USelectMenu> -->
149+ </Card >
150+
151+ <div v-for =" item of projectsAggregated || []"
152+ class =" bg-menu p-4 rounded-xl flex flex-col gap-2 w-full relative" >
166153 <div class =" flex flex-col gap-6" >
167154
168155 <div class =" flex flex-col gap-1" >
169- <div > {{ item.user. email }} </div >
170- <div > {{ item.user. name }} </div >
156+ <div > {{ item.email }} </div >
157+ <div > {{ item.name }} </div >
171158 </div >
172159
173- <div class =" flex justify-evenly flex-col lg:flex-row gap-2 lg:gap-0" >
160+ <div class =" flex justify-evenly flex-col lg:grid lg:grid-cols-3 gap-2 lg:gap-4" >
161+
174162 <div v-for =" project of item.projects"
175- class =" lg:w-[30%] flex flex-col items-center bg-bg p-6 rounded-xl" >
163+ class =" flex relative flex-col items-center bg-bg p-6 rounded-xl" >
164+
165+ <div class =" absolute left-2 top-2 flex items-center gap-2" >
166+ <div :class =" getLogBg(project?.counts?.updated_at)" class =" h-3 w-3 rounded-full" > </div >
167+ <div > {{ dateDiffDays(project?.counts?.updated_at || '0').toFixed(0) }} days </div >
168+ </div >
169+
176170 <div class =" flex gap-4" >
177171 <div class =" font-bold" > {{ project.premium ? 'PREMIUM' : 'FREE' }} </div >
178172 <div class =" text-text-sub/90" >
@@ -181,14 +175,14 @@ async function resetCount(project_id: string) {
181175 </div >
182176
183177
184- <div class =" text-ellipsis line-clamp-1" > {{ project.project_name }} </div >
178+ <div class =" text-ellipsis line-clamp-1" > {{ project.name }} </div >
185179 <div class =" flex gap-2" >
186180 <div > Visits: </div >
187- <div > {{ project.total_visits }} </div >
181+ <div > {{ formatNumberK( project.counts?.visits || 0) }} </div >
188182 <div > Events: </div >
189- <div > {{ project.total_events }} </div >
183+ <div > {{ formatNumberK( project.counts?.events || 0) }} </div >
190184 <div > Sessions: </div >
191- <div > {{ project.total_sessions }} </div >
185+ <div > {{ formatNumberK( project.counts?.sessions || 0) }} </div >
192186 </div >
193187
194188 <div class =" flex gap-4 items-center mt-4" >
0 commit comments