Area restrita - Questionario

This commit is contained in:
2026-06-08 23:50:59 -03:00
parent f2e2400637
commit ef968f10ae
6972 changed files with 23454 additions and 2267883 deletions
+211
View File
@@ -0,0 +1,211 @@
// ============================================================================
// 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;
}),
});