279 lines
9.0 KiB
Vue
279 lines
9.0 KiB
Vue
<template>
|
|
<div class="space-y-4 bg-surface text-accent rounded-2xl px-4 sm:px-10 py-12 w-full max-w-2xl h-fit">
|
|
<section id="pdf-content" class="space-y-4">
|
|
<img src="../public/logo-bravio.png" alt="logo-bravio-blanco" class="h-12 md:h-14 object-cover hidden" />
|
|
<h2 class="text-3xl font-semibold text-center">{{ data.title[langcode] }} {{ universityName }}</h2>
|
|
<p class="text-center text-muted">{{ data.subtitle[langcode] }} <span class="font-bold text-white">{{ country }}</span></p>
|
|
<!-- <div class="text-center">
|
|
<h3 class="text-lg font-semibold my-4">Tu puntuación total es {{ totalScore?.score }}/{{ totalScore?.totalPossiblePoints }}</h3>
|
|
<p v-if="totalScore?.recommendations" class="text-lg font-semibold my-4">Recomendarión: {{ totalScore?.recommendations[langcode] }}</p>
|
|
</div> -->
|
|
<section v-for="(res, index) in results" :key="index" class="border border-border rounded-2xl">
|
|
<div v-if="res.results[0] !== 'SIN REGLA'" class="flex flex-col gap-2 justify-start items-center p-6 mb-4">
|
|
<div class="w-full flex flex-row justify-center items-center gap-2 border-b border-border pb-4">
|
|
<h3 class="font-semibold text-xl">{{ res.sectionTitle[langcode] }}</h3>
|
|
<img src="../assets/img/x-cross.png" alt="cruz roja" class="h-6 w-6">
|
|
<!-- <div class="flex gap-4 justify-end items-center w-full">
|
|
<p class="text-muted">Puntuación</p>
|
|
<div class="p-1 rounded-xl bg-[#DAB2F4] flex justify-center min-w-20"><p>{{ res.score }}/{{ res.sectionPossibleTotalPoints }}</p></div>
|
|
</div> -->
|
|
</div>
|
|
<div v-for="(item, index) in res.results" :key="index" class="flex flex-col">
|
|
<p v-if="item[langcode] !== ''" class="text-sm mb-2" v-html="item[langcode]"></p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</section>
|
|
<p class="my-4 text-center">{{ langcode === 'es' ? 'Revisa la aplicación normativa con Asesoría Jurídica de tu universidad' : 'Reveja a aplicação normativa com a Assessoria Jurídica da sua universidade' }}</p>
|
|
<client-only>
|
|
<div class="flex justify-center gap-2 mt-4">
|
|
<ButtonCTA color="transparent" @click="reloadPage">
|
|
{{ langcode === 'es' ? 'Cerrar asistente' : 'Fechar assistente' }}
|
|
</ButtonCTA>
|
|
<ButtonCTA color="accent" @click="downloadResultsAsPDF">
|
|
{{ langcode === 'es' ? 'Descargar Informe (PDF)' : 'Baixar Relatório (PDF)' }}
|
|
</ButtonCTA>
|
|
</div>
|
|
</client-only>
|
|
</div>
|
|
|
|
</template>
|
|
|
|
<script>
|
|
import { mapGetters } from 'vuex'
|
|
|
|
export default {
|
|
name: "SliceEnd",
|
|
props: {
|
|
data: {
|
|
type: Object,
|
|
default: () => ({})
|
|
},
|
|
currentIndex: { type: Number, default: 0 },
|
|
total: { type: Number, default: 1 }
|
|
},
|
|
emits: ['previous'],
|
|
data() {
|
|
return {
|
|
results: null,
|
|
totalScore: null,
|
|
recommendations: [],
|
|
universityName: '',
|
|
country: ''
|
|
}
|
|
},
|
|
computed: {
|
|
...mapGetters(['langcode']),
|
|
resultsByLanguage() {
|
|
if (!this.results) return []
|
|
|
|
return this.results.map(group => {
|
|
const filteredResults = group.results
|
|
.map(item => {
|
|
return item[this.langcode] ? { [this.langcode]: item[this.langcode] } : null
|
|
})
|
|
.filter(item => item !== null)
|
|
|
|
return {
|
|
...group,
|
|
results: filteredResults
|
|
}
|
|
})
|
|
}
|
|
},
|
|
mounted() {
|
|
this.getGroupedResults()
|
|
this.getUniversityAndCountry()
|
|
},
|
|
methods: {
|
|
getResults() {
|
|
this.results = JSON.parse(localStorage.getItem('results'))
|
|
this.totalScore = JSON.parse(localStorage.getItem('final-score'))
|
|
},
|
|
getUniversityAndCountry() {
|
|
const storedAnswers = localStorage.getItem("answers")
|
|
if (!storedAnswers) return
|
|
const parsed = JSON.parse(storedAnswers)
|
|
const uniAnswer = parsed.find(item => item.sliceId === "P1-01")
|
|
const countryAnswer = parsed.find(item => item.sliceId === "P1-02")
|
|
|
|
this.universityName = uniAnswer?.value?.university || ""
|
|
this.country = countryAnswer?.value || ""
|
|
},
|
|
getGroupedResults() {
|
|
const storedResults = localStorage.getItem("results")
|
|
if (!storedResults) return []
|
|
|
|
const results = JSON.parse(storedResults).filter(r => r.sectionId)
|
|
const grouped = {}
|
|
|
|
results.forEach(item => {
|
|
const groupId = item.sectionId.split("_")[0] || item.sectionId
|
|
|
|
if (!grouped[groupId]) {
|
|
grouped[groupId] = {
|
|
sectionGroup: groupId,
|
|
sectionTitle: item.sectionTitle,
|
|
results: [],
|
|
}
|
|
}
|
|
|
|
if (
|
|
item.result &&
|
|
(
|
|
(item.result.es && item.result.es.trim() !== "") ||
|
|
(item.result.pt && item.result.pt.trim() !== "")
|
|
)
|
|
) {
|
|
grouped[groupId].results.push(item.result)
|
|
}
|
|
})
|
|
|
|
this.results = Object.values(grouped).filter(
|
|
group => group.results.length > 0
|
|
)
|
|
|
|
localStorage.setItem("grouped-results", JSON.stringify(this.results))
|
|
},
|
|
reloadPage() {
|
|
if (import.meta.client) {
|
|
localStorage.clear()
|
|
window.location.reload()
|
|
}
|
|
},
|
|
|
|
async downloadResultsAsPDF() {
|
|
if (!this.results || !this.results.length) {
|
|
alert("No hay resultados para exportar.")
|
|
return
|
|
}
|
|
|
|
if (import.meta.server) return // Evitar SSR
|
|
|
|
// Carga dinámica segura de pdfMake y las fuentes
|
|
const pdfMakeModule = await import("pdfmake/build/pdfmake")
|
|
const pdfFontsModule = await import("pdfmake/build/vfs_fonts")
|
|
|
|
const pdfMake = pdfMakeModule.default || pdfMakeModule
|
|
const pdfFonts = pdfFontsModule.default || pdfFontsModule
|
|
|
|
if (pdfFonts.pdfMake && pdfFonts.pdfMake.vfs) {
|
|
pdfMake.vfs = pdfFonts.pdfMake.vfs
|
|
} else if (pdfFonts.vfs) {
|
|
pdfMake.vfs = pdfFonts.vfs
|
|
} else {
|
|
pdfMake.vfs = pdfFonts
|
|
}
|
|
|
|
|
|
const lang = this.langcode
|
|
const title =
|
|
lang === "es"
|
|
? "Informe de Recomendaciones"
|
|
: "Relatório de Recomendações"
|
|
|
|
const content = []
|
|
|
|
// Logo de Bravio
|
|
content.push({
|
|
image: await new Promise((resolve) => {
|
|
const img = new Image()
|
|
img.src = "/logo-bravio.png"
|
|
img.onload = () => {
|
|
const canvas = document.createElement("canvas")
|
|
canvas.width = img.width
|
|
canvas.height = img.height
|
|
const ctx = canvas.getContext("2d")
|
|
ctx.drawImage(img, 0, 0)
|
|
resolve(canvas.toDataURL("image/png"))
|
|
}
|
|
}),
|
|
width: 150,
|
|
alignment: "start",
|
|
margin: [0, 0, 0, 10],
|
|
})
|
|
|
|
// Encabezado
|
|
content.push({
|
|
text: `${title}\n${this.universityName}`,
|
|
style: "header",
|
|
alignment: "center",
|
|
margin: [0, 0, 0, 10],
|
|
})
|
|
content.push({
|
|
text: this.country,
|
|
alignment: "center",
|
|
margin: [0, 0, 0, 20],
|
|
italics: true,
|
|
})
|
|
content.push({
|
|
text:
|
|
lang === "es"
|
|
? "En base a las respuesta que nos ha facilitado en cada una de las áreas, le listamos una serie de recomendaciones que pueden ser de utilidad y guiarle a poner en marcha su defensoría, comisionado u oficina similar."
|
|
: "Com base nas respostas que você nos forneceu em cada uma das áreas, listamos uma série de recomendações que podem ser úteis e guiá-lo a iniciar sua defensoría, comissariado ou escritório similar.",
|
|
alignment: "start",
|
|
margin: [0, 0, 0, 10],
|
|
})
|
|
|
|
// Cuerpo del PDF
|
|
this.results.forEach((section) => {
|
|
content.push({
|
|
text: section.sectionTitle[lang],
|
|
style: "sectionTitle",
|
|
margin: [0, 10, 0, 5],
|
|
})
|
|
|
|
section.results.forEach((item, index) => {
|
|
const cleanText = item[lang]
|
|
.replace(/<br\s*\/?>/gi, "\n")
|
|
.replace(/✔/g, "")
|
|
.replace(/<\/?[^>]+(>|$)/g, "")
|
|
|
|
content.push({
|
|
text: `${index + 1}. ${cleanText}`,
|
|
style: "resultText",
|
|
margin: [0, 2, 0, 10],
|
|
})
|
|
})
|
|
})
|
|
|
|
// Objeto de definición del documento PDF
|
|
const docDefinition = {
|
|
pageSize: "A4",
|
|
pageMargins: [40, 60, 40, 60],
|
|
content,
|
|
styles: {
|
|
header: {
|
|
fontSize: 18,
|
|
bold: true,
|
|
color: "#4F2773",
|
|
},
|
|
sectionTitle: {
|
|
fontSize: 13,
|
|
bold: true,
|
|
color: "#4F2773",
|
|
margin: [0, 10, 0, 4],
|
|
},
|
|
resultText: {
|
|
fontSize: 12,
|
|
lineHeight: 1.3,
|
|
},
|
|
},
|
|
defaultStyle: {
|
|
font: "Roboto",
|
|
},
|
|
}
|
|
|
|
// Generar PDF solo si pdfMake está correctamente inicializado
|
|
try {
|
|
pdfMake.createPdf(docDefinition).download(`${title}_Bravioo.pdf`)
|
|
} catch (error) {
|
|
console.error("Error al generar PDF:", error)
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
</script>
|