212 lines
6.7 KiB
TypeScript
212 lines
6.7 KiB
TypeScript
// ============================================================================
|
|
// FORM ROUTER - Area do Cliente Avanzato
|
|
// ============================================================================
|
|
// Routers para gestao de formularios e respostas
|
|
// ============================================================================
|
|
|
|
import { z } from "zod";
|
|
import { createRouter, publicQuery, authedQuery } from "./middleware";
|
|
import { getDb } from "./queries/connection";
|
|
import { clientForms, formSections, formQuestions, formAnswers, formSubmissions } from "../db/schema";
|
|
import { eq, desc, and } from "drizzle-orm";
|
|
|
|
// Gerar codigo aleatorio de 8 caracteres
|
|
function generateCode(): string {
|
|
return Math.random().toString(36).substring(2, 10).toUpperCase();
|
|
}
|
|
|
|
export const formRouter = createRouter({
|
|
// ==========================================================================
|
|
// ADMIN - Gerenciamento de Formularios
|
|
// ==========================================================================
|
|
|
|
// Listar todos os formularios
|
|
list: publicQuery.query(async () => {
|
|
const db = getDb();
|
|
const forms = await db.select().from(clientForms).orderBy(desc(clientForms.createdAt));
|
|
return forms;
|
|
}),
|
|
|
|
// Criar novo formulario
|
|
create: publicQuery
|
|
.input(
|
|
z.object({
|
|
title: z.string().min(1),
|
|
description: z.string().optional(),
|
|
clientName: z.string().min(1),
|
|
clientEmail: z.string().email().optional(),
|
|
})
|
|
)
|
|
.mutation(async ({ input }) => {
|
|
const db = getDb();
|
|
const code = generateCode();
|
|
|
|
await db.insert(clientForms).values({
|
|
title: input.title,
|
|
description: input.description || "",
|
|
clientName: input.clientName,
|
|
clientEmail: input.clientEmail || "",
|
|
status: "active",
|
|
accessCode: code,
|
|
createdBy: "Avanzato",
|
|
});
|
|
|
|
return { code, message: "Formulario criado com sucesso" };
|
|
}),
|
|
|
|
// Atualizar status (active/inactive/archived)
|
|
updateStatus: publicQuery
|
|
.input(
|
|
z.object({
|
|
accessCode: z.string(),
|
|
status: z.enum(["active", "inactive", "archived"]),
|
|
})
|
|
)
|
|
.mutation(async ({ input }) => {
|
|
const db = getDb();
|
|
await db
|
|
.update(clientForms)
|
|
.set({ status: input.status })
|
|
.where(eq(clientForms.accessCode, input.accessCode));
|
|
return { message: "Status atualizado" };
|
|
}),
|
|
|
|
// Excluir formulario
|
|
delete: publicQuery
|
|
.input(z.object({ accessCode: z.string() }))
|
|
.mutation(async ({ input }) => {
|
|
const db = getDb();
|
|
// Primeiro excluir respostas e perguntas
|
|
await db.delete(formAnswers).where(eq(formAnswers.formId, input.accessCode));
|
|
await db.delete(formQuestions).where(eq(formQuestions.formId, input.accessCode));
|
|
await db.delete(formSections).where(eq(formSections.formId, input.accessCode));
|
|
await db.delete(formSubmissions).where(eq(formSubmissions.formId, input.accessCode));
|
|
await db.delete(clientForms).where(eq(clientForms.accessCode, input.accessCode));
|
|
return { message: "Formulario excluido" };
|
|
}),
|
|
|
|
// Renovar codigo de acesso
|
|
regenerateCode: publicQuery
|
|
.input(z.object({ accessCode: z.string() }))
|
|
.mutation(async ({ input }) => {
|
|
const db = getDb();
|
|
const newCode = generateCode();
|
|
await db
|
|
.update(clientForms)
|
|
.set({ accessCode: newCode })
|
|
.where(eq(clientForms.accessCode, input.accessCode));
|
|
return { newCode };
|
|
}),
|
|
|
|
// ==========================================================================
|
|
// PUBLICO - Acesso ao Formulario via Codigo
|
|
// ==========================================================================
|
|
|
|
// Buscar formulario por codigo (publico)
|
|
getByCode: publicQuery
|
|
.input(z.object({ code: z.string() }))
|
|
.query(async ({ input }) => {
|
|
const db = getDb();
|
|
const [form] = await db
|
|
.select()
|
|
.from(clientForms)
|
|
.where(eq(clientForms.accessCode, input.code));
|
|
|
|
if (!form) return null;
|
|
if (form.status !== "active") return { ...form, _blocked: true };
|
|
|
|
// Buscar perguntas agrupadas por secao
|
|
const questions = await db
|
|
.select()
|
|
.from(formQuestions)
|
|
.where(eq(formQuestions.formId, input.code))
|
|
.orderBy(formQuestions.id);
|
|
|
|
const sections = await db
|
|
.select()
|
|
.from(formSections)
|
|
.where(eq(formSections.formId, input.code))
|
|
.orderBy(formSections.id);
|
|
|
|
return { ...form, questions, sections };
|
|
}),
|
|
|
|
// Submeter respostas do formulario
|
|
submit: publicQuery
|
|
.input(
|
|
z.object({
|
|
formId: z.string(),
|
|
code: z.string(),
|
|
answers: z.array(
|
|
z.object({
|
|
questionId: z.string(),
|
|
answer: z.string(),
|
|
})
|
|
),
|
|
submittedBy: z.string().optional(),
|
|
submittedByEmail: z.string().optional(),
|
|
})
|
|
)
|
|
.mutation(async ({ input }) => {
|
|
const db = getDb();
|
|
|
|
// Verificar se formulario esta ativo
|
|
const [form] = await db
|
|
.select()
|
|
.from(clientForms)
|
|
.where(eq(clientForms.accessCode, input.code));
|
|
|
|
if (!form || form.status !== "active") {
|
|
throw new Error("Formulario nao encontrado ou inativo");
|
|
}
|
|
|
|
// Inserir submissao
|
|
await db.insert(formSubmissions).values({
|
|
formId: input.formId,
|
|
submittedBy: input.submittedBy || "Anonimo",
|
|
submittedByEmail: input.submittedByEmail || "",
|
|
});
|
|
|
|
// Inserir respostas
|
|
for (const a of input.answers) {
|
|
await db.insert(formAnswers).values({
|
|
formId: input.formId,
|
|
questionId: a.questionId,
|
|
answer: a.answer,
|
|
});
|
|
}
|
|
|
|
return { message: "Respostas submetidas com sucesso" };
|
|
}),
|
|
|
|
// ==========================================================================
|
|
// ADMIN - Visualizar Respostas
|
|
// ==========================================================================
|
|
|
|
// Listar submissoes de um formulario
|
|
getSubmissions: publicQuery
|
|
.input(z.object({ accessCode: z.string() }))
|
|
.query(async ({ input }) => {
|
|
const db = getDb();
|
|
const submissions = await db
|
|
.select()
|
|
.from(formSubmissions)
|
|
.where(eq(formSubmissions.formId, input.accessCode))
|
|
.orderBy(desc(formSubmissions.createdAt));
|
|
return submissions;
|
|
}),
|
|
|
|
// Obter todas as respostas de uma submissao
|
|
getAnswers: publicQuery
|
|
.input(z.object({ formId: z.string() }))
|
|
.query(async ({ input }) => {
|
|
const db = getDb();
|
|
const answers = await db
|
|
.select()
|
|
.from(formAnswers)
|
|
.where(eq(formAnswers.formId, input.formId))
|
|
.orderBy(formAnswers.id);
|
|
return answers;
|
|
}),
|
|
});
|