feat(admin): implement admin statistics API and service
Add admin statistics endpoint to provide user, content, and category stats. Introduce `AdminModule` with controller, service, and repository integration for data aggregation. Include frontend service to consume the stats API.
This commit is contained in:
17
backend/src/admin/admin.controller.ts
Normal file
17
backend/src/admin/admin.controller.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { Controller, Get, UseGuards } from "@nestjs/common";
|
||||||
|
import { AuthGuard } from "../auth/guards/auth.guard";
|
||||||
|
import { RolesGuard } from "../auth/guards/roles.guard";
|
||||||
|
import { Roles } from "../auth/decorators/roles.decorator";
|
||||||
|
import { AdminService } from "./admin.service";
|
||||||
|
|
||||||
|
@Controller("admin")
|
||||||
|
@UseGuards(AuthGuard, RolesGuard)
|
||||||
|
@Roles("admin")
|
||||||
|
export class AdminController {
|
||||||
|
constructor(private readonly adminService: AdminService) {}
|
||||||
|
|
||||||
|
@Get("stats")
|
||||||
|
getStats() {
|
||||||
|
return this.adminService.getStats();
|
||||||
|
}
|
||||||
|
}
|
||||||
14
backend/src/admin/admin.module.ts
Normal file
14
backend/src/admin/admin.module.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { Module } from "@nestjs/common";
|
||||||
|
import { AuthModule } from "../auth/auth.module";
|
||||||
|
import { UsersModule } from "../users/users.module";
|
||||||
|
import { ContentsModule } from "../contents/contents.module";
|
||||||
|
import { CategoriesModule } from "../categories/categories.module";
|
||||||
|
import { AdminController } from "./admin.controller";
|
||||||
|
import { AdminService } from "./admin.service";
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [AuthModule, UsersModule, ContentsModule, CategoriesModule],
|
||||||
|
controllers: [AdminController],
|
||||||
|
providers: [AdminService],
|
||||||
|
})
|
||||||
|
export class AdminModule {}
|
||||||
27
backend/src/admin/admin.service.ts
Normal file
27
backend/src/admin/admin.service.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { Injectable } from "@nestjs/common";
|
||||||
|
import { UsersRepository } from "../users/repositories/users.repository";
|
||||||
|
import { ContentsRepository } from "../contents/repositories/contents.repository";
|
||||||
|
import { CategoriesRepository } from "../categories/repositories/categories.repository";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AdminService {
|
||||||
|
constructor(
|
||||||
|
private readonly usersRepository: UsersRepository,
|
||||||
|
private readonly contentsRepository: ContentsRepository,
|
||||||
|
private readonly categoriesRepository: CategoriesRepository,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async getStats() {
|
||||||
|
const [userCount, contentCount, categoryCount] = await Promise.all([
|
||||||
|
this.usersRepository.countAll(),
|
||||||
|
this.contentsRepository.count({}),
|
||||||
|
this.categoriesRepository.countAll(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
users: userCount,
|
||||||
|
contents: contentCount,
|
||||||
|
categories: categoryCount,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
14
frontend/src/services/admin.service.ts
Normal file
14
frontend/src/services/admin.service.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { api } from "./api";
|
||||||
|
|
||||||
|
export interface AdminStats {
|
||||||
|
users: number;
|
||||||
|
contents: number;
|
||||||
|
categories: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const adminService = {
|
||||||
|
getStats: async (): Promise<AdminStats> => {
|
||||||
|
const response = await api.get("/admin/stats");
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user