BACKEND: - Implementa [CredentialsHandler](cci:2://file:///C:/Projetos/gohorsejobs/backend/internal/api/handlers/credentials_handler.go:9:0-11:1) e rotas /api/v1/system/credentials para gestão segura de chaves. - Adiciona criptografia RSA no [CredentialsService](cci:2://file:///C:/Projetos/gohorsejobs/backend/internal/services/credentials_service.go:17:0-22:1) para proteger chaves de API (Stripe, Cloudflare, etc). - Automatiza geração de pares de chaves RSA no .env via script. FRONTEND: - Refatora /dashboard/backoffice organizando em Abas: Dashboard, Planos, Stripe e Sistema. - Implementa CRUD completo para gestão de Planos (criar, editar, remover). - Adiciona visualização de status do Stripe e botão para limpar cache Cloudflare. - Ajusta formatação de data nos logs para fuso horário America/Sao_Paulo. - Atualiza pi.ts para suportar novos endpoints de planos e credenciais.
130 lines
2.9 KiB
TypeScript
130 lines
2.9 KiB
TypeScript
import { Controller, Get, Post, Patch, Delete, Param, Body, NotFoundException } from '@nestjs/common';
|
|
import { ApiTags, ApiOperation, ApiBody, ApiBearerAuth } from '@nestjs/swagger';
|
|
import { PlansService, Plan } from './plans.service';
|
|
|
|
import { IsString, IsNumber, IsArray, IsBoolean, IsOptional } from 'class-validator';
|
|
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
|
|
|
class CreatePlanDto {
|
|
@ApiPropertyOptional()
|
|
@IsString()
|
|
@IsOptional()
|
|
id?: string;
|
|
|
|
@ApiProperty()
|
|
@IsString()
|
|
name: string;
|
|
|
|
@ApiProperty()
|
|
@IsString()
|
|
description: string;
|
|
|
|
@ApiProperty()
|
|
@IsNumber()
|
|
monthlyPrice: number;
|
|
|
|
@ApiProperty()
|
|
@IsNumber()
|
|
yearlyPrice: number;
|
|
|
|
@ApiProperty()
|
|
@IsArray()
|
|
@IsString({ each: true })
|
|
features: string[];
|
|
|
|
@ApiPropertyOptional()
|
|
@IsBoolean()
|
|
@IsOptional()
|
|
popular?: boolean;
|
|
}
|
|
|
|
class UpdatePlanDto {
|
|
@ApiPropertyOptional()
|
|
@IsString()
|
|
@IsOptional()
|
|
name?: string;
|
|
|
|
@ApiPropertyOptional()
|
|
@IsString()
|
|
@IsOptional()
|
|
description?: string;
|
|
|
|
@ApiPropertyOptional()
|
|
@IsNumber()
|
|
@IsOptional()
|
|
monthlyPrice?: number;
|
|
|
|
@ApiPropertyOptional()
|
|
@IsNumber()
|
|
@IsOptional()
|
|
yearlyPrice?: number;
|
|
|
|
@ApiPropertyOptional()
|
|
@IsArray()
|
|
@IsString({ each: true })
|
|
@IsOptional()
|
|
features?: string[];
|
|
|
|
@ApiPropertyOptional()
|
|
@IsBoolean()
|
|
@IsOptional()
|
|
popular?: boolean;
|
|
}
|
|
|
|
@ApiTags('Plans')
|
|
@Controller('plans')
|
|
export class PlansController {
|
|
constructor(private readonly plansService: PlansService) { }
|
|
|
|
@Get()
|
|
@ApiOperation({ summary: 'Get all plans' })
|
|
getAllPlans() {
|
|
return this.plansService.getAllPlans();
|
|
}
|
|
|
|
@Get(':id')
|
|
@ApiOperation({ summary: 'Get plan by ID' })
|
|
getPlanById(@Param('id') id: string) {
|
|
const plan = this.plansService.getPlanById(id);
|
|
if (!plan) {
|
|
throw new NotFoundException(`Plan with ID ${id} not found`);
|
|
}
|
|
return plan;
|
|
}
|
|
|
|
@Post()
|
|
@ApiBearerAuth()
|
|
@ApiOperation({ summary: 'Create a new plan' })
|
|
@ApiBody({ type: CreatePlanDto })
|
|
createPlan(@Body() body: CreatePlanDto) {
|
|
const plan: Plan = {
|
|
...body,
|
|
id: body.id || body.name.toLowerCase().replace(/\s+/g, '-'),
|
|
};
|
|
return this.plansService.createPlan(plan);
|
|
}
|
|
|
|
@Patch(':id')
|
|
@ApiBearerAuth()
|
|
@ApiOperation({ summary: 'Update a plan' })
|
|
@ApiBody({ type: UpdatePlanDto })
|
|
updatePlan(@Param('id') id: string, @Body() body: UpdatePlanDto) {
|
|
const plan = this.plansService.updatePlan(id, body);
|
|
if (!plan) {
|
|
throw new NotFoundException(`Plan with ID ${id} not found`);
|
|
}
|
|
return plan;
|
|
}
|
|
|
|
@Delete(':id')
|
|
@ApiBearerAuth()
|
|
@ApiOperation({ summary: 'Delete a plan' })
|
|
deletePlan(@Param('id') id: string) {
|
|
const deleted = this.plansService.deletePlan(id);
|
|
if (!deleted) {
|
|
throw new NotFoundException(`Plan with ID ${id} not found`);
|
|
}
|
|
return { message: `Plan ${id} deleted successfully` };
|
|
}
|
|
}
|
|
|