@@ -3,6 +3,10 @@ import { InjectRepository } from '@nestjs/typeorm';
33import { Repository , MoreThanOrEqual } from 'typeorm' ;
44import { User } from '../users/entities/user.entity' ;
55import { NewsletterSubscriber } from '../newsletter/entities/newsletter.entity' ;
6+ import { Booking } from '../bookings/entities/booking.entity' ;
7+ import { Payment } from '../payments/entities/payment.entity' ;
8+ import { Invoice } from '../invoices/entities/invoice.entity' ;
9+ import { PaymentStatus } from '../payments/enums/paymentStatus.enum' ;
610
711@Injectable ( )
812export class DashboardService {
@@ -11,6 +15,12 @@ export class DashboardService {
1115 private readonly userRepository : Repository < User > ,
1216 @InjectRepository ( NewsletterSubscriber )
1317 private readonly newsletterRepository : Repository < NewsletterSubscriber > ,
18+ @InjectRepository ( Booking )
19+ private readonly bookingRepository : Repository < Booking > ,
20+ @InjectRepository ( Payment )
21+ private readonly paymentRepository : Repository < Payment > ,
22+ @InjectRepository ( Invoice )
23+ private readonly invoiceRepository : Repository < Invoice > ,
1424 ) { }
1525
1626 /**
@@ -28,8 +38,11 @@ export class DashboardService {
2838 return {
2939 totalMembers,
3040 verifiedMembers,
31- activeWorkspaces : 1 , // placeholder until workspaces entity exists
32- deskOccupancy : Math . min ( Math . round ( ( verifiedMembers / Math . max ( totalMembers , 1 ) ) * 100 ) , 100 ) ,
41+ activeWorkspaces : 1 ,
42+ deskOccupancy : Math . min (
43+ Math . round ( ( verifiedMembers / Math . max ( totalMembers , 1 ) ) * 100 ) ,
44+ 100 ,
45+ ) ,
3346 } ;
3447 }
3548
@@ -40,7 +53,14 @@ export class DashboardService {
4053 const recentUsers = await this . userRepository . find ( {
4154 order : { createdAt : 'DESC' } ,
4255 take : 10 ,
43- select : [ 'id' , 'firstname' , 'lastname' , 'email' , 'createdAt' , 'isVerified' ] ,
56+ select : [
57+ 'id' ,
58+ 'firstname' ,
59+ 'lastname' ,
60+ 'email' ,
61+ 'createdAt' ,
62+ 'isVerified' ,
63+ ] ,
4464 } ) ;
4565
4666 return recentUsers . map ( ( u ) => ( {
@@ -71,8 +91,12 @@ export class DashboardService {
7191 newSubscribersThisMonth ,
7292 ] = await Promise . all ( [
7393 this . userRepository . count ( { where : { isDeleted : false } } ) ,
74- this . userRepository . count ( { where : { isActive : true , isDeleted : false } } ) ,
75- this . userRepository . count ( { where : { isSuspended : true , isDeleted : false } } ) ,
94+ this . userRepository . count ( {
95+ where : { isActive : true , isDeleted : false } ,
96+ } ) ,
97+ this . userRepository . count ( {
98+ where : { isSuspended : true , isDeleted : false } ,
99+ } ) ,
76100 this . userRepository . count ( {
77101 where : { createdAt : MoreThanOrEqual ( thirtyDaysAgo ) , isDeleted : false } ,
78102 } ) ,
@@ -84,7 +108,6 @@ export class DashboardService {
84108 } ) ,
85109 ] ) ;
86110
87- // Registration trend — last 6 months
88111 const registrationTrend = await this . getMonthlyRegistrations ( 6 ) ;
89112
90113 return {
@@ -151,13 +174,71 @@ export class DashboardService {
151174 } ;
152175 }
153176
177+ async getMemberBookings ( userId : string , page : number , limit : number ) {
178+ const [ data , total ] = await this . bookingRepository . findAndCount ( {
179+ where : { userId } ,
180+ relations : [ 'workspace' ] ,
181+ order : { createdAt : 'DESC' } ,
182+ skip : ( page - 1 ) * limit ,
183+ take : limit ,
184+ } ) ;
185+
186+ return {
187+ data,
188+ meta : {
189+ total,
190+ page,
191+ limit,
192+ totalPages : Math . ceil ( total / limit ) ,
193+ } ,
194+ } ;
195+ }
196+
197+ async getMemberPayments ( userId : string , page : number , limit : number ) {
198+ const [ data , total ] = await this . paymentRepository . findAndCount ( {
199+ where : { userId, status : PaymentStatus . SUCCESS } ,
200+ order : { createdAt : 'DESC' } ,
201+ skip : ( page - 1 ) * limit ,
202+ take : limit ,
203+ } ) ;
204+
205+ return {
206+ data,
207+ meta : {
208+ total,
209+ page,
210+ limit,
211+ totalPages : Math . ceil ( total / limit ) ,
212+ } ,
213+ } ;
214+ }
215+
216+ async getMemberInvoices ( userId : string , page : number , limit : number ) {
217+ const [ data , total ] = await this . invoiceRepository . findAndCount ( {
218+ where : { userId } ,
219+ relations : [ 'booking' , 'booking.workspace' ] ,
220+ order : { createdAt : 'DESC' } ,
221+ skip : ( page - 1 ) * limit ,
222+ take : limit ,
223+ } ) ;
224+
225+ return {
226+ data,
227+ meta : {
228+ total,
229+ page,
230+ limit,
231+ totalPages : Math . ceil ( total / limit ) ,
232+ } ,
233+ } ;
234+ }
235+
154236 private async getMonthlyRegistrations ( months : number ) {
155237 const result : { month : string ; count : number } [ ] = [ ] ;
156238 const now = new Date ( ) ;
157239
158240 for ( let i = months - 1 ; i >= 0 ; i -- ) {
159241 const start = new Date ( now . getFullYear ( ) , now . getMonth ( ) - i , 1 ) ;
160- const end = new Date ( now . getFullYear ( ) , now . getMonth ( ) - i + 1 , 0 , 23 , 59 , 59 ) ;
161242
162243 const count = await this . userRepository . count ( {
163244 where : {
@@ -166,7 +247,6 @@ export class DashboardService {
166247 } ,
167248 } ) ;
168249
169- // We need a between query, but MoreThanOrEqual + manual filter works for trend
170250 const monthLabel = start . toLocaleString ( 'en' , { month : 'short' } ) ;
171251 result . push ( { month : monthLabel , count } ) ;
172252 }
0 commit comments