This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

semble / src / modules / user / application / useCases / queries / GetUserStatsUseCase.ts
5.5 kB 203 lines
1import { err, ok, Result } from 'src/shared/core/Result'; 2import { UseCase } from 'src/shared/core/UseCase'; 3import { 4 IUserStatsRepository, 5 UserGrowthStatsDTO, 6 UserEngagementStatsDTO, 7 DailyActivityStatsDTO, 8 ContentBreakdownStatsDTO, 9 UserStatType, 10 TimeInterval, 11} from '../../../domain/IUserStatsRepository'; 12 13export interface GetUserStatsQuery { 14 statType: UserStatType; 15 interval?: TimeInterval; 16 limit?: number; 17 includeTimeSeries?: boolean; // For engagement stats 18 // Future parameters can be added here for other stat types 19} 20 21export type GetUserStatsResult = 22 | UserGrowthStatsDTO 23 | UserEngagementStatsDTO 24 | DailyActivityStatsDTO 25 | ContentBreakdownStatsDTO; // Union type for different stat types 26 27export class ValidationError extends Error { 28 constructor(message: string) { 29 super(message); 30 this.name = 'ValidationError'; 31 } 32} 33 34export class GetUserStatsUseCase 35 implements UseCase<GetUserStatsQuery, Result<GetUserStatsResult>> 36{ 37 constructor(private userStatsRepository: IUserStatsRepository) {} 38 39 async execute(query: GetUserStatsQuery): Promise<Result<GetUserStatsResult>> { 40 try { 41 // Validate query parameters 42 if (!query.statType) { 43 return err(new ValidationError('Stat type is required')); 44 } 45 46 // Route to appropriate repository method based on stat type 47 switch (query.statType) { 48 case 'growth': 49 return await this.handleGrowthStats(query); 50 51 case 'engagement': 52 return await this.handleEngagementStats(query); 53 54 case 'activity': 55 return await this.handleActivityStats(query); 56 57 case 'breakdown': 58 return await this.handleBreakdownStats(query); 59 60 default: 61 return err( 62 new ValidationError(`Invalid stat type: ${query.statType}`), 63 ); 64 } 65 } catch (error) { 66 return err( 67 new Error( 68 `Failed to retrieve user stats: ${error instanceof Error ? error.message : 'Unknown error'}`, 69 ), 70 ); 71 } 72 } 73 74 private async handleGrowthStats( 75 query: GetUserStatsQuery, 76 ): Promise<Result<UserGrowthStatsDTO>> { 77 // Apply defaults 78 const interval = query.interval || 'day'; 79 const limit = query.limit || 30; 80 81 // Validate parameters 82 if (!['day', 'week', 'month'].includes(interval)) { 83 return err(new ValidationError(`Invalid interval: ${interval}`)); 84 } 85 86 if (limit < 1 || limit > 365) { 87 return err(new ValidationError('Limit must be between 1 and 365')); 88 } 89 90 try { 91 const stats = await this.userStatsRepository.getUserGrowthStats({ 92 interval, 93 limit, 94 }); 95 96 return ok(stats); 97 } catch (error) { 98 return err( 99 new Error( 100 `Failed to retrieve growth stats: ${error instanceof Error ? error.message : 'Unknown error'}`, 101 ), 102 ); 103 } 104 } 105 106 private async handleEngagementStats( 107 query: GetUserStatsQuery, 108 ): Promise<Result<UserEngagementStatsDTO>> { 109 // Apply defaults 110 const interval = query.interval || 'day'; 111 const limit = query.limit || 30; 112 const includeTimeSeries = query.includeTimeSeries || false; 113 114 // Validate parameters 115 if (interval && !['day', 'week', 'month'].includes(interval)) { 116 return err(new ValidationError(`Invalid interval: ${interval}`)); 117 } 118 119 if (limit < 1 || limit > 365) { 120 return err(new ValidationError('Limit must be between 1 and 365')); 121 } 122 123 try { 124 const stats = await this.userStatsRepository.getUserEngagementStats({ 125 interval, 126 limit, 127 includeTimeSeries, 128 }); 129 130 return ok(stats); 131 } catch (error) { 132 return err( 133 new Error( 134 `Failed to retrieve engagement stats: ${error instanceof Error ? error.message : 'Unknown error'}`, 135 ), 136 ); 137 } 138 } 139 140 private async handleActivityStats( 141 query: GetUserStatsQuery, 142 ): Promise<Result<DailyActivityStatsDTO>> { 143 // Apply defaults 144 const interval = query.interval || 'day'; 145 const limit = query.limit || 30; 146 147 // Validate parameters 148 if (!['day', 'week', 'month'].includes(interval)) { 149 return err(new ValidationError(`Invalid interval: ${interval}`)); 150 } 151 152 if (limit < 1 || limit > 365) { 153 return err(new ValidationError('Limit must be between 1 and 365')); 154 } 155 156 try { 157 const stats = await this.userStatsRepository.getDailyActivityStats({ 158 interval, 159 limit, 160 }); 161 162 return ok(stats); 163 } catch (error) { 164 return err( 165 new Error( 166 `Failed to retrieve activity stats: ${error instanceof Error ? error.message : 'Unknown error'}`, 167 ), 168 ); 169 } 170 } 171 172 private async handleBreakdownStats( 173 query: GetUserStatsQuery, 174 ): Promise<Result<ContentBreakdownStatsDTO>> { 175 // Apply defaults 176 const interval = query.interval || 'day'; 177 const limit = query.limit || 30; 178 179 // Validate parameters 180 if (!['day', 'week', 'month'].includes(interval)) { 181 return err(new ValidationError(`Invalid interval: ${interval}`)); 182 } 183 184 if (limit < 1 || limit > 365) { 185 return err(new ValidationError('Limit must be between 1 and 365')); 186 } 187 188 try { 189 const stats = await this.userStatsRepository.getContentBreakdownStats({ 190 interval, 191 limit, 192 }); 193 194 return ok(stats); 195 } catch (error) { 196 return err( 197 new Error( 198 `Failed to retrieve breakdown stats: ${error instanceof Error ? error.message : 'Unknown error'}`, 199 ), 200 ); 201 } 202 } 203}