Appearance
Templates Module - Módulo de Templates
Endpoints de Templates
Listagem e CRUD
| Endpoint | Método | Descrição |
|---|---|---|
/templates | GET | Lista templates com filtros opcionais |
/templates/:id | GET | Retorna um template pelo ID |
/templates | POST | Cria um novo template |
/templates/:id | PUT | Atualiza um template existente |
/templates/:id | DELETE | Remove um template |
/templates/recent-pdfs | GET | Lista PDFs enviados recentemente |
PDFs Recentes (Recent PDFs)
| Endpoint | Método | Descrição |
|---|---|---|
/templates/recent-pdfs | GET | Lista PDFs já enviados para reutilização |
Query Parameters:
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
search | string | Não | Filtro por nome do arquivo (case insensitive) |
Response:
typescript
type RecentPdf = {
id: string // UUID do arquivo no storage
fileName: string // Nome do arquivo definido pelo usuário
filePath: string // Caminho: templates/{companyId}/{uuid}.pdf
fileSize: number // Tamanho em bytes
uploadedAt: Date // Data/hora do upload
}
// Response: RecentPdf[]Exemplo de Request:
GET /templates/recent-pdfs
GET /templates/recent-pdfs?search=contratoExemplo de Response:
json
[
{
"id": "pdf-001",
"fileName": "Contrato de Prestacao de Servicos.pdf",
"filePath": "templates/company-123/pdf-001.pdf",
"fileSize": 524288,
"uploadedAt": "2024-03-20T14:30:00.000Z"
},
{
"id": "pdf-002",
"fileName": "Modelo NDA Padrao.pdf",
"filePath": "templates/company-123/pdf-002.pdf",
"fileSize": 256000,
"uploadedAt": "2024-03-18T10:15:00.000Z"
}
]Ordenação:
Os resultados são retornados ordenados por uploadedAt em ordem decrescente (mais recentes primeiro).
Uso no Frontend:
O usuário pode selecionar um PDF da lista de uploads recentes ao invés de fazer um novo upload. Isso:
- Evita duplicação de arquivos no storage
- Acelera o processo de criação de templates
- Permite reutilizar PDFs base já enviados
Upload de PDF
| Endpoint | Método | Descrição |
|---|---|---|
/templates/upload-pdf | POST | Faz upload de PDF para S3 e retorna path |
Request:
Content-Type: multipart/form-data
file: <arquivo PDF> (máx. 2MB)
fileName: <nome do arquivo definido pelo usuário>Response:
typescript
type UploadPdfResponse = {
fileId: string // UUID do arquivo no storage
filePath: string // Caminho: templates/{companyId}/{uuid}.pdf
fileName: string // Nome do arquivo definido pelo usuário
}Nota: O store mapeia
fileId→pdfIdefilePath→pdfPathpara uso no payload do template.
Validações (Frontend):
| Validação | Regra |
|---|---|
| Formato | Apenas application/pdf |
| Tamanho | Máximo 2MB (2 _ 1024 _ 1024 bytes) |
Criação de Template
Após o upload do PDF, usa-se o pdfId retornado (mapeado de fileId) no payload do POST /templates:
Request POST /templates:
typescript
type CreateTemplatePayload = {
name: string // obrigatório
description?: string // opcional
pdfId: string // obrigatório (mapeado de fileId do upload-pdf)
variables?: object // opcional (JSON)
status?: TemplateStatus // opcional: 'draft' | 'active' | 'archived'
}Request PUT /templates/🆔
typescript
type UpdateTemplatePayload = Partial<CreateTemplatePayload> & {
id: string // ID do template a atualizar
}Fluxo Completo:
PdfUploader.vue
↓
Usuário seleciona arquivo PDF
↓
Valida formato e tamanho (frontend)
↓
Abre modal para definir nome do arquivo
↓
Usuário clica em "Iniciar"
↓
uploadTemplatePdfService(file, fileName)
↓
POST /templates/upload-pdf (multipart/form-data)
- file: arquivo PDF
- fileName: nome definido pelo usuário
↓
Backend:
- Faz upload do PDF para S3
- Retorna { fileId, filePath, fileName }
↓
Store atualiza (mapeia campos):
- pdfId = response.fileId
- pdfPath = response.filePath
- currentStep = 'editing'
↓
Usuário preenche nome, descrição, variáveis
↓
createTemplateService(payload)
↓
POST /templates
- payload: { name, description, pdfId, variables, status }
↓
Backend:
- Cria template com status 'draft' (default)
- Retorna template completoTypes do Módulo Templates
typescript
// src/modules/templates/models/template.type.ts
interface Template {
id?: string
name: string
description?: string
content: string
variables: TemplateVariable[]
status: TemplateStatus
createdAt?: Date
updatedAt?: Date
}
interface TemplateVariable {
id: string
name: string
type: VariableType // 'text' | 'date' | 'number'
required: boolean
}
interface UploadPdfResponse {
pdfId: string
pdfPath: string
}
interface CreateTemplatePayload {
name: string
description?: string
pdfId: string
pdfPath: string
variables?: object
status?: TemplateStatus
}
interface UpdateTemplatePayload extends CreateTemplatePayload {
id: string
}
type TemplateStatus = 'draft' | 'active' | 'archived'
type VariableType = 'text' | 'date' | 'number'Services do Módulo Templates
typescript
// src/modules/templates/services/templates.ts
// CRUD
getTemplatesService(params?: Partial<TemplateFilter>)
getTemplateByIdService(id: string)
createTemplateService(payload: CreateTemplatePayload)
updateTemplateService({ id, ...payload }: UpdateTemplatePayload)
deleteTemplateService(id: string)
// Upload
uploadTemplatePdfService(file: File, fileName: string)
// PDFs Recentes
getRecentPdfsService(search?: string)Store do Editor de Templates
typescript
// src/modules/templates/stores/templateEditor.ts
// Estado
currentStep: 'upload' | 'editing'
isLoading, isSaving, isUploading: boolean
templateId, templateName, templateDescription: string
templateStatus: TemplateStatus
templateVariables: TemplateVariable[]
pdfFile: File | null
pdfUrl: string // URL local (blob)
pdfId: string // UUID do arquivo no storage
pdfPath: string // Caminho no S3: templates/{companyId}/{uuid}.pdf
totalPages: number
variableMappings: VariableMapping[]
// Métodos principais
uploadPdf(file: File, fileName: string) // Faz upload e guarda pdfId/pdfPath
useExistingPdf(fileId, filePath, fileName) // Usa PDF já existente (sem upload)
createTemplate() // Cria template com pdfId/pdfPath
saveTemplate() // Salva alterações
publishTemplate() // Publica o template
reset() // Limpa o estadoMocks de Templates
Os dados mockados estão em src/mocks/data.json na coleção templates.
IMPORTANTE: O endpoint POST /templates/upload-pdf não é suportado pelo JSON Server pois requer upload de arquivos. Para desenvolvimento local com mocks, o backend real deve estar rodando ou deve-se criar um middleware customizado.