diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index b09191c..175f6c0 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -1,26 +1,27 @@ -Ce générateur d'attestation de déplacement dérogatoire a été mis en place dans le cadre du couvre-feu lié à la pandémie du virus COVID-19 de 2020. -Ce service repose sur l'utilisation du code de l'application de génération d'attestation de déplacement dérogatoire développée lors du confinement . - -La liste qui suit mentionne les participants des différents dépôts ayant contribué aux attestations développées par la LAB-MI . Un grand merci à ceux qui ont permis de rendre ce service utile à la fois à la population et aux forces de l'ordre : - - Johann Pardanaud (https://github.com/nesk) - Philippe Bron (https://github.com/PhilippeBron) - Cristian (https://github.com/cristianpb) - Stanislas Ormières (https://github.com/laruiss) - Caroline Robillard (https://github.com/Carolinedanslesnuages) - Joel Pagniez (https://github.com/JoelPagniez) - Sophie GUERLAIS - Philippe (https://github.com/pli01) - Victor Journe (https://github.com/victorjourne) - Matthieu Bacconnier (https://github.com/Neamar) - Hugo Cartigny (https://github.com/BlueskyFR) - Sébastien Touzé (https://github.com/SebastienTouze) - John Livingston (https://github.com/JohnXLivingston) - David Libeau (https://github.com/DavidLibeau) - Arnaud Delafosse (https://github.com/ArnaudDelafosse) - Florent Morin (https://github.com/florentmorin) - gissehel (https://github.com/gissehel) - Olivier Djian (https://github.com/odjpromi) - Stéphane Ritter (https://github.com/infosteph) - Enguerran P. (https://github.com/theblackhole) - Quentin Dunand (https://github.com/tar-gezed) +Ce générateur d'attestation de déplacement dérogatoire a été mis en place dans le cadre du couvre-feu lié à la pandémie du virus COVID-19 de 2020. +Ce service repose sur l'utilisation du code de l'application de génération d'attestation de déplacement dérogatoire développée lors du confinement . + +La liste qui suit mentionne les participants des différents dépôts ayant contribué aux attestations développées par la LAB-MI . Un grand merci à ceux qui ont permis de rendre ce service utile à la fois à la population et aux forces de l'ordre : + + Johann Pardanaud (https://github.com/nesk) + Philippe Bron (https://github.com/PhilippeBron) + Cristian (https://github.com/cristianpb) + Stanislas Ormières (https://github.com/laruiss) + Caroline Robillard (https://github.com/Carolinedanslesnuages) + Joel Pagniez (https://github.com/JoelPagniez) + Sophie GUERLAIS + Philippe (https://github.com/pli01) + Victor Journe (https://github.com/victorjourne) + Matthieu Bacconnier (https://github.com/Neamar) + Hugo Cartigny (https://github.com/BlueskyFR) + Sébastien Touzé (https://github.com/SebastienTouze) + John Livingston (https://github.com/JohnXLivingston) + David Libeau (https://github.com/DavidLibeau) + Arnaud Delafosse (https://github.com/ArnaudDelafosse) + Florent Morin (https://github.com/florentmorin) + gissehel (https://github.com/gissehel) + Olivier Djian (https://github.com/odjpromi) + Stéphane Ritter (https://github.com/infosteph) + Enguerran P. (https://github.com/theblackhole) + Quentin Dunand (https://github.com/tar-gezed) + François Mathieu (https://github.com/mapsred) diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..47f4b19 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,15 @@ +version: '3.5' +services: + node: + image: node:lts-alpine + container_name: attestation-covid + working_dir: /var/www + command: + - /bin/sh + - '-c' + - 'npm start' + volumes: + - ./:/var/www + ports: + - '5000:5000' + - '3000:3000' diff --git a/src/certificate-curfew.pdf b/src/certificate-curfew.pdf new file mode 100644 index 0000000..01a551f Binary files /dev/null and b/src/certificate-curfew.pdf differ diff --git a/src/certificate-quarantine.pdf b/src/certificate-quarantine.pdf new file mode 100644 index 0000000..1c2f689 Binary files /dev/null and b/src/certificate-quarantine.pdf differ diff --git a/src/certificate.pdf b/src/certificate.pdf deleted file mode 100644 index 5da392c..0000000 Binary files a/src/certificate.pdf and /dev/null differ diff --git a/src/css/main.css b/src/css/main.css index 6385b16..2c3c9ac 100644 --- a/src/css/main.css +++ b/src/css/main.css @@ -791,4 +791,4 @@ input[type=number] { .quarantine-subtitle, .curfew-subtitle { padding: 1rem 0; -} \ No newline at end of file +} diff --git a/src/form-data.json b/src/form-data.json index f5e246d..adfa34d 100644 --- a/src/form-data.json +++ b/src/form-data.json @@ -103,35 +103,35 @@ "items": [ { "code": "travail", - "label": " 1. Activité professionnelle, enseignement et formation
Déplacements entre le domicile et le lieu d’exercice de l’activité professionnelle ou le lieu d’enseignement et de formation, déplacements professionnels ne pouvant être différés ;" + "label": " 1. Activité professionnelle, enseignement et formation
Déplacements entre le domicile et le lieu d’exercice de l’activité professionnelle ou le lieu d’enseignement\net de formation, déplacements professionnels ne pouvant être différés" }, { "code": "sante", - "label": " 2. Consultation et soins
Déplacements pour des consultations, examens, actes de prévention (dont vaccination) et soins ne pouvant être assurés à distance ou pour l’achat de produits de santé ;" + "label": " 2. Consultation et soins
Déplacements pour des consultations, examens, actes de prévention (dont vaccination) et soins ne\npouvant être assurés à distance ou pour l’achat de produits de santé" }, { - "code": "famille", - "label": " 3. Motif familial impérieux, personnes vulnérables ou précaires ou gardes d’enfants
Déplacements pour motif familial impérieux, pour l’assistance aux personnes vulnérables ou précaires ou pour la garde d’enfants ;" + "code": "imperial", + "label": " 3. Motif familial impérieux, personnes vulnérables ou précaires ou gardes d’enfants
Déplacements pour motif familial impérieux, pour l’assistance aux personnes vulnérables ou précaires ou\npour la garde d’enfants" }, { "code": "handicap", - "label": " 4. Situation de handicap
Déplacements des personnes en situation de handicap et de leur accompagnant ;" + "label": " 4. Situation de handicap
Déplacements des personnes en situation de handicap et de leur accompagnant" }, { "code": "judiciaire", - "label": " 5. Convocation judiciaire ou administrative
Déplacements pour répondre à une convocation judiciaire ou administrative, déplacements pour se rendre chez un professionnel du droit, pour un acte ou une démarche qui ne peuvent être réalisés à distance ;" + "label": " 5. Convocation judiciaire ou administrative
Déplacements pour répondre à une convocation judiciaire ou administrative, déplacements pour se\nrendre chez un professionnel du droit, pour un acte ou une démarche qui ne peuvent être réalisés à distance" }, { "code": "missions", - "label": " 6. Mission d’intérêt général
Déplacements pour participer à des missions d’intérêt général sur demande de l’autorité administrative ;" + "label": " 6. Mission d’intérêt général
Déplacements pour participer à des missions d’intérêt général sur demande de l’autorité administrative" }, { "code": "transit", - "label": " 7. Déplacements de transit et longue distance
Déplacements liés à des transits ferroviaires, aériens ou en bus pour des déplacements de longues distances ;" + "label": " 7. Déplacements de transit et longue distance
Déplacements liés à des transits ferroviaires, aériens ou en bus pour des déplacements de longues\ndistances" }, { "code": "animaux", - "label": " 8. Animaux de compagnie
Déplacements brefs autour du domicile pour les besoins des animaux de compagnie [2] ;" + "label": " 8. Animaux de compagnie
Déplacements brefs dans un rayon maximal d'un kilomètre autour du domicile pour les besoins des\nanimaux de compagnie" } ] }, @@ -139,21 +139,53 @@ "key": "reason-quarantine", "type": "list", "items": [ + { + "code": "sport", + "label": " 1. Activité physique et promenade
Déplacements liés soit à la promenade, soit à l'activité physique individuelle despersonnes.
[Attestation à remplir seulement à défaut de pouvoir présenter un justificatif de domicile]" + }, { "code": "courses", - "label": " 9. Achats
Déplacements pour effectuer des achats de fournitures nécessaires à l'activité professionnelle, des achats de première nécessité, des retraits de commandes, des livraisons à domicile, ainsi que pour les déménagements ;" + "label": " 2. Achats 2
Déplacements pour effectuer des achats de première nécessité ou des retraits decommandes" }, { - "code": "sport", - "label": " 10. Activités physiques
Déplacements brefs, dans la limite d'une heure quotidienne et dans un rayon maximal de cinq kilomètres autour du domicile, liés soit à l'activité physique individuelle des personnes, à l'exclusion de toute pratique sportive collective et de toute proximité avec d'autres personnes, soit à la promenade avec les seules personnes regroupées dans un même domicile [3] ;" + "code": "famille", + "label": " 3. Accompagnement des enfants à l’école 2
Déplacements pour emmener et aller chercher les enfants à l’école et à l’occasion deleurs activités péri-scolaires" }, { - "code": "rassemblement", - "label": " 11. Participation à des rassemblements autorisés
Déplacements à destination ou en provenance d'un lieu de culte, participation à des rassemblements, réunions ou activités sur la voie publique ou dans un lieu ouvert au public qui ne sont pas interdits en application de l'article 3 ;" + "code": "culte", + "label": " 4. Etablissement culturel ou lieu de culte 2
Déplacements pour se rendre dans un établissement culturel (bibliothèques etmédiathèques) ou un lieu de culte" }, { "code": "demarche", - "label": " 12. Démarches administratives ou juridiques
Déplacements pour se rendre dans un service public." + "label": " 5. Démarches administratives ou juridiques 2
Déplacements pour se rendre dans un service public pour un acte ou une démarche quine peuvent être réalisés à distance" + }, + { + "code": "travail", + "label": " 6. Activité professionnelle, enseignement et formation, mission d’intérêt général
Déplacements entre le domicile et le lieu d’exercice de l’activité professionnelle ou le lieud’enseignement et de formation, déplacements professionnels ne pouvant être différés,livraisons à domicile, déplacements pour effectuer des achats de fournitures nécessaires àl'activité professionnelle, déplacements liés à des missions d’intérêt général sur demandede l’autorité administrative" + }, + { + "code": "sante", + "label": " 7. Santé (consultations et soins)
Déplacements pour des consultations, examens, actes de prévention (dont vaccination)et soins ne pouvant être assurés à distance ou pour l’achat de produits de santé" + }, + { + "code": "imperieux", + "label": " 8. Motif familial impérieux, personnes vulnérables ou précaires ou gardes d’enfants
Déplacements pour motif familial impérieux, pour l’assistance aux personnes vulnérablesou précaires ou pour la garde d’enfants" + }, + { + "code": "handicap", + "label": " 9. Situation de handicap
Déplacements des personnes en situation de handicap et de leur accompagnant" + }, + { + "code": "judiciaire", + "label": " 10. Convocation judiciaire ou administrative
Déplacements pour répondre à une convocation judiciaire ou administrative,déplacements pour se rendre chez un professionnel du droit, pour un acte ou unedémarche qui ne peuvent être réalisés à distance" + }, + { + "code": "demenagement", + "label": " 11. Déménagement
Déplacements liés à un déménagement résultant d'un changement de domicile etdéplacements indispensables à l'acquisition ou à la location d’une résidence principale,insusceptibles d'être différés" + }, + { + "code": "transit", + "label": "12. Déplacement de transit vers les gares et les aéroports " } ] } diff --git a/src/index.html b/src/index.html index 1942460..523d0ea 100644 --- a/src/index.html +++ b/src/index.html @@ -1,149 +1,149 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - + + + + + - Attestation de déplacement dérogatoire + Attestation de déplacement dérogatoire - +
+ -
-
-
- - -
-

- -

+ +

-
- L'attestation est téléchargée sur votre appareil. -
+
+ L'attestation est téléchargée sur votre appareil. +
-

- -

-
- Les données du formulaire et les données sauvegardées ont été effacées. -
-
+ +

+
+ Les données du formulaire et les données sauvegardées ont été effacées. +
+ -
-

- [1] Les personnes souhaitant bénéficier de l’une de ces exceptions doivent se munir s’il y a lieu, lors de leurs déplacements hors de leur domicile, d’un document leur permettant de justifier que le déplacement considéré entre dans le champ de l’une de ces exceptions.. -

-

- [2] La distance autorisée pour ces déplacements peut varier. -

-

- [3] La distance et la durée autorisées peuvent varier en fonction des mesures locales. -

-
-

Pour lutter contre l’épidémie, l’application TousAntiCovid est disponible sur :

- logo appstore - logo playstore -

- Le code source de ce service est consultable sur GitHub. -

-

- Ministère de l'Intérieur - DNUM - SDIT -

- - - logo dnum - -
- +
+

+ [1] Les personnes souhaitant bénéficier de l’une de ces exceptions doivent se munir s’il y a lieu, lors de leurs déplacements hors de leur domicile, d’un document leur permettant de justifier que le déplacement considéré entre dans le champ de l’une de ces exceptions. +

+

+ [2] Pour les personnes résidant aux frontières d’un département, une tolérance de 30 kms au-delà du département est acceptée. +

+

+ [3] La distance et la durée autorisées peuvent varier en fonction des mesures locales. +

+
+

Pour lutter contre l’épidémie, l’application TousAntiCovid est disponible sur :

+ logo appstore + logo playstore +

+ Le code source de ce service est consultable sur GitHub. +

+

+ Ministère de l'Intérieur - DNUM - SDIT +

+ + + logo dnum + + + -
- Une nouvelle version est disponible. Cliquer sur le bouton pour l'obtenir. -

- -

-
+
+ Une nouvelle version est disponible. Cliquer sur le bouton pour l'obtenir. +

+ +

+
- + diff --git a/src/js/form-util.js b/src/js/form-util.js index ff75ba2..f8649a3 100644 --- a/src/js/form-util.js +++ b/src/js/form-util.js @@ -2,7 +2,8 @@ import removeAccents from 'remove-accents' import { $, $$, downloadBlob } from './dom-utils' import { addSlash, getFormattedDate } from './util' -import pdfBase from '../certificate.pdf' +import quarantinePdfBase from '../certificate-quarantine.pdf' +import curfewPdfBase from '../certificate-curfew.pdf' import { generatePdf } from './pdf-util' import SecureLS from 'secure-ls' @@ -101,6 +102,13 @@ export function setReleaseDateTime (releaseDateInput) { releaseDateInput.value = getFormattedDate(loadedDate) } +export function setReleaseHour (releaseHour) { + const loadedDate = new Date() + let hours = loadedDate.getHours() + hours = ('0' + hours).slice(-2) + releaseHour.value = `${hours}:${loadedDate.getMinutes()}` +} + export function toAscii (string) { if (typeof string !== 'string') { throw new Error('Need string') @@ -200,7 +208,10 @@ export function prepareInputs (formInputs, reasonInputs, reasonFieldsetsWrapper, return } updateSecureLS(formInputs) - const pdfBlob = await generatePdf(getProfile(formInputs), reasons, pdfBase) + + const pdfType = $('#curfew-reason-fieldset').classList.contains('targeted') ? 'curfew' : 'quarantine' + const pdfBase = pdfType === 'curfew' ? curfewPdfBase : quarantinePdfBase + const pdfBlob = await generatePdf(getProfile(formInputs), reasons, pdfBase, pdfType) const creationInstant = new Date() const creationDate = creationInstant.toLocaleDateString('fr-CA') @@ -227,8 +238,8 @@ export function prepareInputs (formInputs, reasonInputs, reasonFieldsetsWrapper, quarantineSubtitle.classList.toggle('hidden', true) } if (event.target.className.includes('quarantine-button')) { - curfewFieldset.classList.toggle('in-quarantine', true) - curfewFieldset.classList.toggle('targeted', true) + curfewFieldset.classList.toggle('in-quarantine', false) + curfewFieldset.classList.toggle('targeted', false) quarantineFieldset.classList.toggle('targeted', true) curfewSubtitle.classList.toggle('hidden', true) quarantineSubtitle.classList.toggle('hidden', false) @@ -243,7 +254,9 @@ export function prepareForm () { const reasonFieldsetsWrapper = $('.fieldset-wrapper') const reasonAlerts = $$('.msg-alert') const releaseDateInput = $('#field-datesortie') + const releaseHour = $('#field-heuresortie') const contextWrapper = $('.context-wrapper') setReleaseDateTime(releaseDateInput) + setReleaseHour(releaseHour) prepareInputs(formInputs, reasonInputs, reasonFieldsetsWrapper, reasonAlerts, snackbar, releaseDateInput, contextWrapper) } diff --git a/src/js/form.js b/src/js/form.js index c7946b3..3fc644b 100644 --- a/src/js/form.js +++ b/src/js/form.js @@ -95,9 +95,9 @@ const createReasonField = (reasonData) => { return formReason } -const createReasonFieldset = (reasonsData, sanitaryContextData) => { +const createReasonFieldset = (reasonsData, id) => { const fieldsetAttrs = { - id: 'curfew-reason-fieldset', + id: id, className: 'fieldset reason-fieldset', } @@ -105,7 +105,7 @@ const createReasonFieldset = (reasonsData, sanitaryContextData) => { const appendToFieldset = appendTo(fieldset) const textSubscribeReasonAttrs = { - innerHTML: 'Je certifie que mon déplacement est lié au motif suivant (cocher la case) autorisé par le décret n°2020-1310 du 29 octobre 2020 prescrivant les mesures générales nécessaires pour faire face à l\'épidémie de Covid19 dans le cadre de l\'état d\'urgence sanitaire [1] :', + innerHTML: 'Je certifie que mon déplacement est lié au motif suivant (cocher la case) autorisé en application des mesures générales nécessaires pour faire face à l\'épidémie de COVID-19 dans le cadre de l\'état d\'urgence sanitaire [1] :', } const textSubscribeReason = createElement('p', textSubscribeReasonAttrs) @@ -125,22 +125,6 @@ const createReasonFieldset = (reasonsData, sanitaryContextData) => { return fieldset } -const createReasonFieldsetQuarantine = (reasonsData) => { - const fieldsetAttrs = { - id: 'quarantine-reason-fieldset', - className: 'fieldset reason-fieldset', - } - - const fieldset = createElement('fieldset', fieldsetAttrs) - const appendToFieldset = appendTo(fieldset) - - const reasonsFields = reasonsData.items.map(createReasonField) - - appendToFieldset([...reasonsFields]) - // Créer un form-checkbox par motif - return fieldset -} - export function createForm () { const form = $('#form-profile') // Évite de recréer le formulaire s'il est déjà créé par react-snap (ou un autre outil de prerender) @@ -174,13 +158,13 @@ export function createForm () { .flat(1) .find(field => field.key === 'reason-quarantine') - const reasonFieldsetCurfew = createReasonFieldset(reasonsDataCurfew) - const reasonFieldsetQuarantine = createReasonFieldsetQuarantine(reasonsDataQuarantine) + const reasonFieldsetCurfew = createReasonFieldset(reasonsDataCurfew, 'curfew-reason-fieldset') + const reasonFieldsetQuarantine = createReasonFieldset(reasonsDataQuarantine, 'quarantine-reason-fieldset') const curfewButton = createElement('button', { type: 'button', className: 'curfew-button context-button btn' }) - const curfewLink = document.createTextNode('Couvre-feu (18h-6h)') + const curfewLink = document.createTextNode('Couvre-feu (19h-6h)') curfewButton.appendChild(curfewLink) const quarantineButton = createElement('button', { type: 'button', className: 'quarantine-button context-button btn' }) - const quarantineLink = document.createTextNode('Week-end * (6h-18h)') + const quarantineLink = document.createTextNode('Journée * (6h-19h)') quarantineButton.appendChild(quarantineLink) const buttonWrapper = createElement('div', { className: 'button-wrapper' }) buttonWrapper.appendChild(curfewButton) @@ -189,7 +173,7 @@ export function createForm () { const contextTitleText = document.createTextNode('Choisissez un contexte') contextTitle.appendChild(contextTitleText) const contextSubtitle = createElement('p', { className: 'context-subtitle' }) - const contextSubtitleText = document.createTextNode('* Le contexte "Week-end (6h-18h)" ne s\'applique qu\'aux territoires concernés par des dispositions spécifiques') + const contextSubtitleText = document.createTextNode('* Le contexte "Journée (6h-19h)" ne s\'applique qu\'aux territoires concernés par des dispositions spécifiques') contextSubtitle.appendChild(contextSubtitleText) const contextWrapper = createElement('div', { className: 'context-wrapper' }) contextWrapper.appendChild(contextTitle) @@ -198,12 +182,12 @@ export function createForm () { const reasonFielsetWrapper = createElement('div', { className: 'fieldset-wrapper hidden' }) const quarantineSubtitle = createElement('div', { className: 'quarantine-subtitle hidden' }) - const quarantineSubtitleText = document.createTextNode('J\'effectue un déplacement le week-end entre 06h00 et 18h00 sur un territoire soumis au confinement') + const quarantineSubtitleText = document.createTextNode('J\'effectue un déplacement la journée entre 06h00 et 19h00 sur un territoire soumis au confinement') quarantineSubtitle.appendChild(quarantineSubtitleText) const curfewSubtitle = createElement('div', { className: 'curfew-subtitle hidden' }) - const curfewSubtitleText = document.createTextNode('J\'effectue un déplacement entre 18h00 et 06h00 sur un territoire soumis au couvre-feu.') + const curfewSubtitleText = document.createTextNode('J\'effectue un déplacement entre 19h00 et 06h00 sur un territoire soumis au couvre-feu.') curfewSubtitle.appendChild(curfewSubtitleText) - reasonFieldsetCurfew.prepend(quarantineSubtitle) + reasonFieldsetQuarantine.prepend(quarantineSubtitle) reasonFieldsetCurfew.prepend(curfewSubtitle) reasonFielsetWrapper.appendChild(reasonFieldsetCurfew) reasonFielsetWrapper.appendChild(reasonFieldsetQuarantine) diff --git a/src/js/pdf-util.js b/src/js/pdf-util.js index 14c5942..374106e 100644 --- a/src/js/pdf-util.js +++ b/src/js/pdf-util.js @@ -1,22 +1,55 @@ import { generateQR } from './util' import { PDFDocument, rgb, StandardFonts } from 'pdf-lib' -const ys = { - travail: 579, - sante: 546, - famille: 512, - handicap: 478, - judiciaire: 460, - missions: 410, - transit: 378, - animaux: 343, - courses: 280, - sport: 235, - rassemblement: 167, - demarche: 121, +const positions = { + curfew: { + context_x: 60, + name: { x: 104, y: 650, page: 1 }, + birthday: { x: 104, y: 637, page: 1 }, + placeofbirth: { x: 180, y: 637, page: 1 }, + address: { x: 120, y: 623, page: 1 }, + city: { x: 90, y: 212, page: 1 }, + datesortie: { x: 74, y: 201, page: 1 }, + heuresortie: { x: 149, y: 201, page: 1 }, + context: { + travail: { y: 548, page: 1 }, + sante: { y: 502, page: 1 }, + imperial: { y: 455, page: 1 }, + handicap: { y: 410, page: 1 }, + judiciaire: { y: 374, page: 1 }, + missions: { y: 328, page: 1 }, + transit: { y: 295, page: 1 }, + animaux: { y: 248, page: 1 }, + }, + }, + quarantine: { + context_x: 63, + name: { x: 112, y: 516, page: 1 }, + birthday: { x: 110, y: 501, page: 1 }, + placeofbirth: { x: 225, y: 501, page: 1 }, + address: { x: 127, y: 488, page: 1 }, + city: { x: 98, y: 236, page: 2 }, + datesortie: { x: 78, y: 222, page: 2 }, + heuresortie: { x: 155, y: 223, page: 2 }, + context: { + sport: { y: 381, page: 1 }, + courses: { y: 269, page: 1 }, + famille: { y: 214, page: 1 }, + culte: { y: 160, page: 1 }, + demarche: { y: 760, page: 2 }, + travail: { y: 662, page: 2 }, + sante: { y: 564, page: 2 }, + imperieux: { y: 511, page: 2 }, + handicap: { y: 457, page: 2 }, + judiciaire: { y: 415, page: 2 }, + demenagement: { y: 346, page: 2 }, + transit: { y: 278, page: 2 }, + }, + }, } -export async function generatePdf (profile, reasons, pdfBase) { +export async function generatePdf (profile, reasons, pdfBase, pdfType) { + const pdfPositions = positions[pdfType] const creationInstant = new Date() const creationDate = creationInstant.toLocaleDateString('fr-FR') const creationHour = creationInstant @@ -67,21 +100,24 @@ export async function generatePdf (profile, reasons, pdfBase) { pdfDoc.setAuthor("Ministère de l'intérieur") const page1 = pdfDoc.getPages()[0] + const page2 = pdfDoc.getPages()[1] const font = await pdfDoc.embedFont(StandardFonts.Helvetica) - const drawText = (text, x, y, size = 11) => { - page1.drawText(text, { x, y, size, font }) + const drawText = (text, x, y, size = 11, pageNumber = 1) => { + const page = pageNumber === 1 ? page1 : page2 + page.drawText(text, { x, y, size, font }) } - drawText(`${firstname} ${lastname}`, 144, 705) - drawText(birthday, 144, 684) - drawText(placeofbirth, 310, 684) - drawText(`${address} ${zipcode} ${city}`, 148, 665) + drawText(`${firstname} ${lastname}`, pdfPositions.name.x, pdfPositions.name.y) + drawText(birthday, pdfPositions.birthday.x, pdfPositions.birthday.y) + drawText(placeofbirth, pdfPositions.placeofbirth.x, pdfPositions.placeofbirth.y) + drawText(`${address} ${zipcode} ${city}`, pdfPositions.address.x, pdfPositions.address.y) reasons .split(', ') .forEach(reason => { - drawText('x', 72, ys[reason], 12) + const val = pdfPositions.context[reason] + drawText('x', pdfPositions.context_x, val.y, 12, val.page) }) let locationSize = getIdealFontSize(font, profile.city, 83, 7, 11) @@ -94,19 +130,18 @@ export async function generatePdf (profile, reasons, pdfBase) { locationSize = 7 } - drawText(profile.city, 103, 99, locationSize) - drawText(`${profile.datesortie}`, 91, 83, 11) - drawText(`${profile.heuresortie}`, 310, 83, 11) + drawText(profile.city, pdfPositions.city.x, pdfPositions.city.y, locationSize, pdfPositions.city.page) + drawText(`${profile.datesortie}`, pdfPositions.datesortie.x, pdfPositions.datesortie.y, 11, pdfPositions.datesortie.page) + drawText(`${profile.heuresortie}`, pdfPositions.heuresortie.x, pdfPositions.heuresortie.y, 11, pdfPositions.heuresortie.page) - // const shortCreationDate = `${creationDate.split('/')[0]}/${ - // creationDate.split('/')[1] - // }` - // drawText(shortCreationDate, 314, 189, locationSize) + await generateQRPage(data, font, pdfDoc, pdfType) - // // Date création - // drawText('Date de création:', 479, 130, 6) - // drawText(`${creationDate} à ${creationHour}`, 470, 124, 6) + const pdfBytes = await pdfDoc.save() + return new Blob([pdfBytes], { type: 'application/pdf' }) +} + +async function generateQRPage (data, font, pdfDoc, pdfType) { const qrTitle1 = 'QR-code contenant les informations ' const qrTitle2 = 'de votre attestation numérique' @@ -114,28 +149,16 @@ export async function generatePdf (profile, reasons, pdfBase) { const qrImage = await pdfDoc.embedPng(generatedQR) - page1.drawText(qrTitle1 + '\n' + qrTitle2, { x: 440, y: 630, size: 6, font, lineHeight: 10, color: rgb(1, 1, 1) }) - - page1.drawImage(qrImage, { - x: page1.getWidth() - 107, - y: 660, - width: 82, - height: 82, - }) - pdfDoc.addPage() - const page2 = pdfDoc.getPages()[1] - page2.drawText(qrTitle1 + qrTitle2, { x: 50, y: page2.getHeight() - 70, size: 11, font, color: rgb(1, 1, 1) }) - page2.drawImage(qrImage, { + const index = pdfType === 'curfew' ? 1 : 2 + const page = pdfDoc.getPages()[index] + page.drawText(qrTitle1 + qrTitle2, { x: 50, y: page.getHeight() - 70, size: 11, font, color: rgb(1, 1, 1) }) + page.drawImage(qrImage, { x: 50, - y: page2.getHeight() - 390, + y: page.getHeight() - 390, width: 300, height: 300, }) - - const pdfBytes = await pdfDoc.save() - - return new Blob([pdfBytes], { type: 'application/pdf' }) } function getIdealFontSize (font, text, maxWidth, minSize, defaultSize) {