Advertisement
Guest User

Attestation Numérique FR 20200406

a guest
Apr 6th, 2020
2,541
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import 'bootstrap/dist/css/bootstrap.min.css'
  2.  
  3. import { PDFDocument, StandardFonts } from 'pdf-lib'
  4. import QRCode from 'qrcode'
  5.  
  6. import pdfBase from './certificate.pdf'
  7. import './main.css'
  8.  
  9. const $ = (...args) => document.querySelector(...args)
  10. const $$ = (...args) => [...document.querySelectorAll(...args)]
  11. var year, month, day
  12.  
  13. const generateQR = async text => {
  14.   try {
  15.     var opts = {
  16.       errorCorrectionLevel: 'M',
  17.       type: 'image/png',
  18.       quality: 0.92,
  19.       margin: 1,
  20.     }
  21.     return await QRCode.toDataURL(text, opts)
  22.   } catch (err) {
  23.     console.error(err)
  24.   }
  25. }
  26.  
  27. function pad (str) {
  28.   return String(str).padStart(2, '0')
  29. }
  30.  
  31. function setDateNow (date) {
  32.   year = date.getFullYear()
  33.   month = pad(date.getMonth() + 1) // Les mois commencent à 0
  34.   day = pad(date.getDate())
  35. }
  36.  
  37. document.addEventListener('DOMContentLoaded', setReleaseDateTime)
  38.  
  39. function setReleaseDateTime () {
  40.   const loadedDate = new Date()
  41.   setDateNow(loadedDate)
  42.   const releaseDateInput = document.querySelector('#field-datesortie')
  43.   releaseDateInput.value = `${year}-${month}-${day}`
  44.  
  45.   const hour = pad(loadedDate.getHours())
  46.   const minute = pad(loadedDate.getMinutes())
  47.  
  48.   const releaseTimeInput = document.querySelector('#field-heuresortie')
  49.   releaseTimeInput.value = `${hour}:${minute}`
  50. }
  51.  
  52. function saveProfile () {
  53.   for (const field of $$('#form-profile input')) {
  54.     if (field.id === 'field-datesortie') {
  55.       var dateSortie = field.value.split('-')
  56.       localStorage.setItem(field.id.substring('field-'.length), `${dateSortie[2]}/${dateSortie[1]}/${dateSortie[0]}`)
  57.     } else {
  58.       localStorage.setItem(field.id.substring('field-'.length), field.value)
  59.     }
  60.   }
  61. }
  62.  
  63. function getProfile () {
  64.   const fields = {}
  65.   for (let i = 0; i < localStorage.length; i++) {
  66.     const name = localStorage.key(i)
  67.     fields[name] = localStorage.getItem(name)
  68.   }
  69.   return fields
  70. }
  71.  
  72. function idealFontSize (font, text, maxWidth, minSize, defaultSize) {
  73.   let currentSize = defaultSize
  74.   let textWidth = font.widthOfTextAtSize(text, defaultSize)
  75.  
  76.   while (textWidth > maxWidth && currentSize > minSize) {
  77.     textWidth = font.widthOfTextAtSize(text, --currentSize)
  78.   }
  79.  
  80.   return (textWidth > maxWidth) ? null : currentSize
  81. }
  82.  
  83. async function generatePdf (profile, reasons) {
  84.   const generatedDate = new Date()
  85.   setDateNow(generatedDate)
  86.   const creationDate = `${day}/${month}/${year}`
  87.  
  88.   const hour = pad(generatedDate.getHours())
  89.   const minute = pad(generatedDate.getMinutes())
  90.   const creationHour = `${hour}h${minute}`
  91.  
  92.   const { lastname, firstname, birthday, lieunaissance, address, zipcode, town, datesortie, heuresortie } = profile
  93.   const releaseHours = String(heuresortie).substring(0, 2)
  94.   const releaseMinutes = String(heuresortie).substring(3, 5)
  95.  
  96.   const data = [
  97.     `Cree le: ${creationDate} a ${creationHour}`,
  98.     `Nom: ${lastname}`,
  99.     `Prenom: ${firstname}`,
  100.     `Naissance: ${birthday} a ${lieunaissance}`,
  101.     `Adresse: ${address} ${zipcode} ${town}`,
  102.     `Sortie: ${datesortie} a ${releaseHours}h${releaseMinutes}`,
  103.     `Motifs: ${reasons}`,
  104.   ].join('; ')
  105.  
  106.   const existingPdfBytes = await fetch(pdfBase).then(res => res.arrayBuffer())
  107.  
  108.   const pdfDoc = await PDFDocument.load(existingPdfBytes)
  109.   const page1 = pdfDoc.getPages()[0]
  110.  
  111.   const font = await pdfDoc.embedFont(StandardFonts.Helvetica)
  112.   const drawText = (text, x, y, size = 11) => {
  113.     page1.drawText(text, { x, y, size, font })
  114.   }
  115.  
  116.   drawText(`${firstname} ${lastname}`, 123, 686)
  117.   drawText(birthday, 123, 661)
  118.   drawText(lieunaissance, 92, 638)
  119.   drawText(`${address} ${zipcode} ${town}`, 134, 613)
  120.  
  121.   if (reasons.includes('travail')) {
  122.     drawText('x', 76, 527, 19)
  123.   }
  124.   if (reasons.includes('courses')) {
  125.     drawText('x', 76, 478, 19)
  126.   }
  127.   if (reasons.includes('sante')) {
  128.     drawText('x', 76, 436, 19)
  129.   }
  130.   if (reasons.includes('famille')) {
  131.     drawText('x', 76, 400, 19)
  132.   }
  133.   if (reasons.includes('sport')) {
  134.     drawText('x', 76, 345, 19)
  135.   }
  136.   if (reasons.includes('judiciaire')) {
  137.     drawText('x', 76, 298, 19)
  138.   }
  139.   if (reasons.includes('missions')) {
  140.     drawText('x', 76, 260, 19)
  141.   }
  142.   let locationSize = idealFontSize(font, profile.town, 83, 7, 11)
  143.  
  144.   if (!locationSize) {
  145.     alert('Le nom de la ville risque de ne pas être affiché correctement en raison de sa longueur. ' +
  146.       'Essayez d\'utiliser des abréviations ("Saint" en "St." par exemple) quand cela est possible.')
  147.     locationSize = 7
  148.   }
  149.  
  150.   drawText(profile.town, 111, 226, locationSize)
  151.  
  152.   if (reasons !== '') {
  153.     // Date sortie
  154.     drawText(`${profile.datesortie}`, 92, 200)
  155.     drawText(releaseHours, 200, 201)
  156.     drawText(releaseMinutes, 220, 201)
  157.   }
  158.  
  159.   // Date création
  160.   drawText('Date de création:', 464, 150, 7)
  161.   drawText(`${creationDate} à ${creationHour}`, 455, 144, 7)
  162.  
  163.   const generatedQR = await generateQR(data)
  164.  
  165.   const qrImage = await pdfDoc.embedPng(generatedQR)
  166.  
  167.   page1.drawImage(qrImage, {
  168.     x: page1.getWidth() - 170,
  169.     y: 155,
  170.     width: 100,
  171.     height: 100,
  172.   })
  173.  
  174.   pdfDoc.addPage()
  175.   const page2 = pdfDoc.getPages()[1]
  176.   page2.drawImage(qrImage, {
  177.     x: 50,
  178.     y: page2.getHeight() - 350,
  179.     width: 300,
  180.     height: 300,
  181.   })
  182.  
  183.   const pdfBytes = await pdfDoc.save()
  184.  
  185.   return new Blob([pdfBytes], { type: 'application/pdf' })
  186. }
  187.  
  188. function downloadBlob (blob, fileName) {
  189.   const link = document.createElement('a')
  190.   var url = URL.createObjectURL(blob)
  191.   link.href = url
  192.   link.download = fileName
  193.   document.body.appendChild(link)
  194.   link.click()
  195. }
  196.  
  197. function getAndSaveReasons () {
  198.   const values = $$('input[name="field-reason"]:checked')
  199.     .map(x => x.value)
  200.     .join('-')
  201.   localStorage.setItem('reasons', values)
  202.   return values
  203. }
  204.  
  205. // see: https://stackoverflow.com/a/32348687/1513045
  206. function isFacebookBrowser () {
  207.   const ua = navigator.userAgent || navigator.vendor || window.opera
  208.   return ua.includes('FBAN') || ua.includes('FBAV')
  209. }
  210.  
  211. if (isFacebookBrowser()) {
  212.   $('#alert-facebook').classList.remove('d-none')
  213. }
  214.  
  215. function addSlash () {
  216.   this.value = this.value.replace(/^(\d{2})$/g, '$1/')
  217.   this.value = this.value.replace(/^(\d{2})\/(\d{2})$/g, '$1/$2/')
  218. }
  219.  
  220. $('#field-birthday').addEventListener('keyup', addSlash)
  221.  
  222. const snackbar = $('#snackbar')
  223.  
  224. $('#form-profile').addEventListener('submit', async event => {
  225.   event.preventDefault()
  226.  
  227.   saveProfile()
  228.   const reasons = getAndSaveReasons()
  229.   const pdfBlob = await generatePdf(getProfile(), reasons)
  230.   downloadBlob(pdfBlob, 'attestation.pdf')
  231.  
  232.   snackbar.classList.remove('d-none')
  233.   setTimeout(() => snackbar.classList.add('show'), 100)
  234.  
  235.   setTimeout(function () {
  236.     snackbar.classList.remove('show')
  237.     setTimeout(() => snackbar.classList.add('d-none'), 500)
  238.   }, 6000)
  239. })
  240.  
  241. $$('input').forEach(input => {
  242.   const exempleElt = input.parentNode.parentNode.querySelector('.exemple')
  243.   if (input.placeholder && exempleElt) {
  244.     input.addEventListener('input', (event) => {
  245.       if (input.value) {
  246.         exempleElt.innerHTML = 'ex.&nbsp;: ' + input.placeholder
  247.       } else {
  248.         exempleElt.innerHTML = ''
  249.       }
  250.     })
  251.   }
  252. })
  253.  
  254. function addVersion () {
  255.   document.getElementById('version').innerHTML = `${new Date().getFullYear()} - ${process.env.VERSION}`
  256. }
  257. addVersion()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement