155 lines
4.5 KiB
TypeScript
155 lines
4.5 KiB
TypeScript
import {
|
|
Document,
|
|
Page,
|
|
Text,
|
|
View,
|
|
StyleSheet,
|
|
pdf
|
|
} from "@react-pdf/renderer";
|
|
import type { getBriefingPdfData } from "@/lib/pdf-data";
|
|
|
|
type PdfData = Awaited<ReturnType<typeof getBriefingPdfData>>;
|
|
|
|
const styles = StyleSheet.create({
|
|
page: {
|
|
padding: 32,
|
|
fontSize: 10,
|
|
color: "#1f2933",
|
|
fontFamily: "Helvetica"
|
|
},
|
|
title: {
|
|
fontSize: 20,
|
|
marginBottom: 6,
|
|
fontWeight: 700
|
|
},
|
|
subtitle: {
|
|
fontSize: 10,
|
|
color: "#52606d",
|
|
marginBottom: 16
|
|
},
|
|
section: {
|
|
marginTop: 16,
|
|
paddingTop: 10,
|
|
borderTop: "1 solid #d9e2ec"
|
|
},
|
|
sectionTitle: {
|
|
fontSize: 13,
|
|
fontWeight: 700,
|
|
marginBottom: 8
|
|
},
|
|
question: {
|
|
marginBottom: 10
|
|
},
|
|
label: {
|
|
fontWeight: 700,
|
|
marginBottom: 3
|
|
},
|
|
answer: {
|
|
color: "#52606d",
|
|
lineHeight: 1.5
|
|
},
|
|
meta: {
|
|
marginBottom: 4
|
|
}
|
|
});
|
|
|
|
function selectedText(value: unknown) {
|
|
return Array.isArray(value)
|
|
? value.filter((item): item is string => typeof item === "string").join(", ")
|
|
: "";
|
|
}
|
|
|
|
function opcoesTexto(opcoes: unknown, selecionadas: unknown) {
|
|
const options = Array.isArray(opcoes)
|
|
? opcoes.filter((item): item is string => typeof item === "string")
|
|
: [];
|
|
const selected = Array.isArray(selecionadas)
|
|
? selecionadas.filter((item): item is string => typeof item === "string")
|
|
: [];
|
|
|
|
if (options.length === 0) {
|
|
return selected.join(", ");
|
|
}
|
|
|
|
return options
|
|
.map((opcao) => `${selected.includes(opcao) ? "☒" : "☐"} ${opcao}`)
|
|
.join(" ");
|
|
}
|
|
|
|
function respostaTexto(resposta: {
|
|
texto: string | null;
|
|
complemento: string | null;
|
|
selecionadas: unknown;
|
|
}) {
|
|
const partes = [
|
|
resposta.texto?.trim(),
|
|
selectedText(resposta.selecionadas),
|
|
resposta.complemento?.trim() ? `Complemento: ${resposta.complemento.trim()}` : ""
|
|
].filter(Boolean);
|
|
|
|
return partes.join(" | ");
|
|
}
|
|
|
|
function BriefingPdfDocument({ data }: { data: PdfData }) {
|
|
return (
|
|
<Document>
|
|
<Page size="A4" style={styles.page}>
|
|
<Text style={styles.title}>{data.briefing.titulo}</Text>
|
|
<Text style={styles.subtitle}>Briefing de Site | SeConectai</Text>
|
|
|
|
<View>
|
|
<Text style={styles.meta}>Cliente: {data.briefing.cliente.nomeCompleto}</Text>
|
|
<Text style={styles.meta}>E-mail: {data.briefing.cliente.user.email}</Text>
|
|
<Text style={styles.meta}>WhatsApp: {data.briefing.cliente.whatsapp}</Text>
|
|
<Text style={styles.meta}>CPF: {data.cpfMascarado}</Text>
|
|
<Text style={styles.meta}>Status: {data.briefing.status}</Text>
|
|
<Text style={styles.meta}>
|
|
Enviado em: {data.briefing.enviadoEm ? data.briefing.enviadoEm.toLocaleString("pt-BR") : "Nao enviado"}
|
|
</Text>
|
|
</View>
|
|
|
|
{data.secoes.map((secao) => (
|
|
<View key={secao.id} style={styles.section} wrap={false}>
|
|
<Text style={styles.sectionTitle}>{secao.ordem}. {secao.titulo}</Text>
|
|
{secao.perguntas.map((pergunta) => {
|
|
const resposta = pergunta.respostas[0];
|
|
const texto =
|
|
resposta && (pergunta.tipo === "RADIO" || pergunta.tipo === "CHECKBOX")
|
|
? [
|
|
opcoesTexto(pergunta.opcoes, resposta.selecionadas),
|
|
resposta.complemento?.trim() ? `Complemento: ${resposta.complemento.trim()}` : ""
|
|
].filter(Boolean).join(" | ")
|
|
: resposta
|
|
? respostaTexto(resposta)
|
|
: "";
|
|
|
|
return (
|
|
<View key={pergunta.id} style={styles.question}>
|
|
<Text style={styles.label}>{pergunta.rotulo}</Text>
|
|
<Text style={styles.answer}>{texto || "Sem resposta informada."}</Text>
|
|
{pergunta.anexos.length > 0 ? (
|
|
<Text style={styles.answer}>
|
|
Anexos: {pergunta.anexos.map((anexo) => anexo.nomeOriginal).join(", ")}
|
|
</Text>
|
|
) : null}
|
|
</View>
|
|
);
|
|
})}
|
|
</View>
|
|
))}
|
|
|
|
<View style={styles.section}>
|
|
<Text style={styles.sectionTitle}>Confirmacao do cliente</Text>
|
|
<Text style={styles.answer}>
|
|
Confirmado em: {data.briefing.confirmadoEm ? data.briefing.confirmadoEm.toLocaleString("pt-BR") : "Nao confirmado"}
|
|
</Text>
|
|
</View>
|
|
</Page>
|
|
</Document>
|
|
);
|
|
}
|
|
|
|
export async function gerarBriefingPdfBuffer(data: PdfData) {
|
|
return pdf(<BriefingPdfDocument data={data} />).toBuffer();
|
|
}
|