diff --git a/admin/src/app/professionals/[id]/page.tsx b/admin/src/app/professionals/[id]/page.tsx index 4122a98..49bc87b 100644 --- a/admin/src/app/professionals/[id]/page.tsx +++ b/admin/src/app/professionals/[id]/page.tsx @@ -21,6 +21,7 @@ interface Professional { profession?: string; identification?: string; address?: string; rethus_code?: string; rethus_validated?: boolean; rate?: number; average_score?: number; + identification_picture?: string; certificate_picture?: string; banner_picture?: string; users?: User; schedules?: Schedule[]; specializations?: Specialization[]; payment_methods?: PaymentMethod[]; } @@ -138,10 +139,21 @@ export default function ProfessionalDetailPage() { }; const deny = async () => { + if (!confirm('¿Rechazar esta solicitud? Se eliminará el perfil profesional.')) return; try { await api.post(`/professionals/${id}/deny`); toast.success('Solicitud rechazada'); load(); } catch { toast.error('Error al rechazar'); } }; + const deactivate = async () => { + try { await api.post(`/professionals/${id}/deactivate`); toast.success('Profesional desactivado'); load(); } + catch { toast.error('Error al desactivar'); } + }; + + const setPending = async () => { + try { await api.post(`/professionals/${id}/set-pending`); toast.success('Puesto en revisión'); load(); } + catch { toast.error('Error al cambiar estado'); } + }; + if (loading) return
Cargando...
; if (error || !professional) return (
@@ -163,9 +175,22 @@ export default function ProfessionalDetailPage() {

ID profesional: {id}

- - {professional.is_active ? 'Activo' : 'Pendiente'} - +
+ + {professional.is_active ? 'Activo' : 'Pendiente / Inactivo'} + + {professional.is_active ? ( + <> + + + + ) : ( + <> + + + + )} +
{/* Datos del usuario */} @@ -356,6 +381,51 @@ export default function ProfessionalDetailPage() { + {/* Documentos subidos */} + {(professional.identification_picture || professional.certificate_picture || professional.banner_picture) && ( + + Documentos y fotos + + {professional.identification_picture && ( +
+

Foto de cédula

+ {professional.identification_picture.match(/\.(jpg|jpeg|png|webp)$/i) ? ( + + Cédula + + ) : ( + + Ver documento + + )} +
+ )} + {professional.certificate_picture && ( +
+

Certificado / Diploma

+ {professional.certificate_picture.match(/\.(jpg|jpeg|png|webp)$/i) ? ( + + Certificado + + ) : ( + + Ver documento + + )} +
+ )} + {professional.banner_picture && ( +
+

Foto de perfil / Banner

+ + Banner + +
+ )} +
+
+ )} + {/* Métodos de pago */} {professional.payment_methods && professional.payment_methods.length > 0 && ( diff --git a/backend/src/professionals/professionals.controller.ts b/backend/src/professionals/professionals.controller.ts index 80e22d0..ff5d9f0 100644 --- a/backend/src/professionals/professionals.controller.ts +++ b/backend/src/professionals/professionals.controller.ts @@ -82,6 +82,20 @@ export class ProfessionalsController { return this.pros.upsert(req.user.sub, dto); } + @Post(':id/deactivate') + @UseGuards(JwtAuthGuard) + @ApiBearerAuth() + deactivate(@Param('id') id: string) { + return this.pros.deactivate(id); + } + + @Post(':id/set-pending') + @UseGuards(JwtAuthGuard) + @ApiBearerAuth() + setPending(@Param('id') id: string) { + return this.pros.setPending(id); + } + @Patch(':id') @UseGuards(JwtAuthGuard) @ApiBearerAuth() diff --git a/backend/src/professionals/professionals.service.ts b/backend/src/professionals/professionals.service.ts index 5053c82..7fa742d 100644 --- a/backend/src/professionals/professionals.service.ts +++ b/backend/src/professionals/professionals.service.ts @@ -155,6 +155,26 @@ export class ProfessionalsService { return { message: 'Solicitud rechazada' }; } + async deactivate(id: string) { + const prof = await this.prisma.professionals.findUnique({ where: { id } }); + if (!prof) throw new NotFoundException('Profesional no encontrado'); + await this.prisma.$transaction([ + this.prisma.professionals.update({ where: { id }, data: { is_active: false } }), + this.prisma.users.update({ where: { id: prof.user_id }, data: { pro_state: 3 } }), + ]); + return { message: 'Profesional desactivado' }; + } + + async setPending(id: string) { + const prof = await this.prisma.professionals.findUnique({ where: { id } }); + if (!prof) throw new NotFoundException('Profesional no encontrado'); + await this.prisma.$transaction([ + this.prisma.professionals.update({ where: { id }, data: { is_active: false } }), + this.prisma.users.update({ where: { id: prof.user_id }, data: { pro_state: 1 } }), + ]); + return { message: 'Profesional puesto en revisión' }; + } + async validateRethus(id: string) { const prof = await this.prisma.professionals.findUnique({ where: { id } }); if (!prof) throw new NotFoundException('Profesional no encontrado');