Adiciona o frontend Next.js em frontend/ (setup, design system, autenticação/tema, layout/navegação, área master, área tenant completa: clientes, produtos, vendas, recebimentos, whatsapp, e-mail, alertas, equipe e perfil). Estende o backend de forma aditiva e autorizada: cookie httpOnly para refresh token (Etapa 13) e CRUD de equipe + edição de perfil do tenant (Etapa 18, módulo src/modules/equipe/ novo e PUT /tenant/perfil). Detalhes completos em Etapas/V2/*. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
114 lines
4.1 KiB
TypeScript
114 lines
4.1 KiB
TypeScript
import { apiClient } from '@/lib/api/client';
|
|
import { buildQuery, type PaginatedResult } from '@/lib/api/types';
|
|
|
|
/** Espelha `alert-template-tipos.ts` do backend. */
|
|
export const TIPOS_TEMPLATE = [
|
|
'mensalidade_tenant',
|
|
'cobranca_cliente',
|
|
'venda_confirmada',
|
|
'lembrete_vencimento',
|
|
] as const;
|
|
export type TipoTemplate = (typeof TIPOS_TEMPLATE)[number];
|
|
|
|
export const CANAIS_TEMPLATE = ['whatsapp', 'email'] as const;
|
|
export type CanalTemplate = (typeof CANAIS_TEMPLATE)[number];
|
|
|
|
export const TIPO_TEMPLATE_LABEL: Record<TipoTemplate, string> = {
|
|
mensalidade_tenant: 'Mensalidade do tenant',
|
|
cobranca_cliente: 'Cobrança ao cliente',
|
|
venda_confirmada: 'Venda confirmada',
|
|
lembrete_vencimento: 'Lembrete de vencimento',
|
|
};
|
|
|
|
export const CANAL_TEMPLATE_LABEL: Record<CanalTemplate, string> = {
|
|
whatsapp: 'WhatsApp',
|
|
email: 'E-mail',
|
|
};
|
|
|
|
interface PlaceholderDoc {
|
|
chave: string;
|
|
descricao: string;
|
|
}
|
|
|
|
/**
|
|
* Espelha `src/modules/alerts/placeholders.ts` (`PLACEHOLDERS_POR_TIPO`) —
|
|
* não existe endpoint que exponha isso (é uma constante interna do
|
|
* backend, nunca importada por nenhum controller), então é replicada aqui
|
|
* manualmente para o editor de template desta etapa. Se o backend mudar
|
|
* essa lista, esta cópia precisa ser atualizada junto.
|
|
*/
|
|
export const PLACEHOLDERS_POR_TIPO: Record<TipoTemplate, PlaceholderDoc[]> = {
|
|
mensalidade_tenant: [
|
|
{ chave: 'nome', descricao: 'Nome fantasia (ou razão social) do tenant' },
|
|
{ chave: 'valor', descricao: 'Valor da fatura, formatado como "R$ 199,90"' },
|
|
{ chave: 'vencimento', descricao: 'Data de vencimento da fatura, formato dd/mm/aaaa' },
|
|
{ chave: 'referencia', descricao: 'Mês/ano de referência da fatura, formato aaaa-mm' },
|
|
],
|
|
cobranca_cliente: [
|
|
{ chave: 'nome', descricao: 'Nome fantasia (ou razão social) do customer' },
|
|
{ chave: 'valor', descricao: 'Valor da parcela, formatado como "R$ 199,90"' },
|
|
{ chave: 'vencimento', descricao: 'Data de vencimento da parcela, formato dd/mm/aaaa' },
|
|
{ chave: 'numero_venda', descricao: 'Número sequencial da venda' },
|
|
{ chave: 'numero_parcela', descricao: 'Número da parcela dentro da venda (1, 2, 3...)' },
|
|
],
|
|
venda_confirmada: [
|
|
{ chave: 'nome', descricao: 'Nome fantasia (ou razão social) do customer' },
|
|
{ chave: 'numero_venda', descricao: 'Número sequencial da venda' },
|
|
{ chave: 'valor', descricao: 'Valor total da venda, formatado como "R$ 199,90"' },
|
|
],
|
|
lembrete_vencimento: [
|
|
{ chave: 'nome', descricao: 'Nome fantasia (ou razão social) do customer' },
|
|
{ chave: 'valor', descricao: 'Valor da parcela, formatado como "R$ 199,90"' },
|
|
{ chave: 'vencimento', descricao: 'Data de vencimento da parcela, formato dd/mm/aaaa' },
|
|
],
|
|
};
|
|
|
|
/** Espelha o model `alert_templates` (sempre `tenant_id: null` em `/master`). */
|
|
export interface AlertTemplate {
|
|
id: string;
|
|
tenant_id: string | null;
|
|
tipo: TipoTemplate;
|
|
canal: CanalTemplate;
|
|
assunto: string | null;
|
|
corpo: string;
|
|
ativo: boolean;
|
|
criado_em: string;
|
|
}
|
|
|
|
/** Espelha `CreateMasterAlertTemplateDto`/`UpdateMasterAlertTemplateDto`. */
|
|
export interface AlertTemplateInput {
|
|
tipo: TipoTemplate;
|
|
canal: CanalTemplate;
|
|
/** Obrigatório só quando `canal === 'email'`. */
|
|
assunto?: string;
|
|
corpo: string;
|
|
ativo?: boolean;
|
|
}
|
|
|
|
export interface ListAlertTemplatesParams {
|
|
tipo?: TipoTemplate;
|
|
canal?: CanalTemplate;
|
|
ativo?: boolean;
|
|
page?: number;
|
|
limit?: number;
|
|
}
|
|
|
|
export function listAlertTemplates(params: ListAlertTemplatesParams) {
|
|
return apiClient.get<PaginatedResult<AlertTemplate>>(
|
|
`/master/alertas/templates${buildQuery(params)}`,
|
|
);
|
|
}
|
|
|
|
export function createAlertTemplate(input: AlertTemplateInput) {
|
|
return apiClient.post<AlertTemplate>('/master/alertas/templates', input);
|
|
}
|
|
|
|
export function updateAlertTemplate(id: string, input: Partial<AlertTemplateInput>) {
|
|
return apiClient.put<AlertTemplate>(`/master/alertas/templates/${id}`, input);
|
|
}
|
|
|
|
/** Soft delete no backend (`ativo: false`) — não remove o registro. */
|
|
export function deleteAlertTemplate(id: string) {
|
|
return apiClient.delete<AlertTemplate>(`/master/alertas/templates/${id}`);
|
|
}
|