add admin services-by-professional endpoint + calendar view in admin panel

Backend:
- GET /services/admin/professional/:id (JWT-guarded) returns paginated
  services for any professional with embedded user (client) info

Admin professional detail page:
- Replace broken all-services-then-filter with new endpoint
- Add month calendar with colored dots per day (click to filter table)
- Services table shows client name/phone, time, colored status badges
- Fix DAY_NAMES array (was 0=Domingo, now 0=Lunes per DB convention)
- Schedule row shows both ranges + continuous_day flag

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-07-12 18:58:42 -05:00
co-authored by Claude Sonnet 4.6
parent 8a97b52eb7
commit 2180e0480c
3 changed files with 306 additions and 76 deletions
+14 -1
View File
@@ -1,4 +1,4 @@
import { Controller, Get, Post, Patch, Param, Body, UseGuards, Req, Query } from '@nestjs/common';
import { Controller, Get, Post, Patch, Param, Body, UseGuards, Req, Query, ParseIntPipe, Optional } from '@nestjs/common';
import { ApiTags, ApiBearerAuth, ApiQuery } from '@nestjs/swagger';
import { ServicesService } from './services.service';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
@@ -101,6 +101,19 @@ export class ServicesController {
return this.services.getPublicCalendar(id);
}
@Get('admin/professional/:professionalId')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiQuery({ name: 'page', required: false })
@ApiQuery({ name: 'limit', required: false })
getByProfessionalAdmin(
@Param('professionalId') professionalId: string,
@Query('page') page?: string,
@Query('limit') limit?: string,
) {
return this.services.getServicesByProfessionalAdmin(professionalId, +(page || 1), +(limit || 50));
}
@Get(':id')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
+16
View File
@@ -296,6 +296,22 @@ export class ServicesService {
return { schedules, services };
}
async getServicesByProfessionalAdmin(professionalId: string, page = 1, limit = 50) {
const skip = (page - 1) * limit;
const where = { professional_id: professionalId };
const [data, total] = await Promise.all([
this.prisma.services.findMany({
where,
skip,
take: limit,
include: { users: { select: { id: true, name: true, picture: true, phone: true } } },
orderBy: { day: 'desc' },
}),
this.prisma.services.count({ where }),
]);
return { data, meta: { total, page, limit, totalPages: Math.ceil(total / limit) || 1 } };
}
async findAll(page = 1, limit = 20) {
const skip = (page - 1) * limit;
const [data, total] = await Promise.all([