Area restrita - Questionario
This commit is contained in:
@@ -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;
|
||||
}),
|
||||
});
|
||||
Reference in New Issue
Block a user