Compare commits
2 Commits
master
...
attestatio
Author | SHA1 | Date |
---|---|---|
LAB-MI | 6a5f269560 | |
LAB-MI | 86b15a4d6e |
|
@ -9,6 +9,7 @@ module.exports = {
|
||||||
"no-console": process.env.NODE_ENV === "production" ? "error" : "off",
|
"no-console": process.env.NODE_ENV === "production" ? "error" : "off",
|
||||||
"no-debugger": process.env.NODE_ENV === "production" ? "error" : "off",
|
"no-debugger": process.env.NODE_ENV === "production" ? "error" : "off",
|
||||||
"comma-dangle": [2, "always-multiline"],
|
"comma-dangle": [2, "always-multiline"],
|
||||||
|
"no-var": 2,
|
||||||
},
|
},
|
||||||
overrides: [
|
overrides: [
|
||||||
{
|
{
|
||||||
|
|
42
CHANGELOG.md
|
@ -1,45 +1,5 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## [1.0.13] - 2020-04-06
|
## [1.0.0] - 2020-04-15
|
||||||
### Added
|
### Added
|
||||||
- first public release
|
- first public release
|
||||||
## [1.1.0] - 2020-04-08
|
|
||||||
### Added
|
|
||||||
- (#21, #23, #25, #26, #27, #28, #29) :wheelchair: improve A11Y support
|
|
||||||
- adds github links in footer
|
|
||||||
- (#19) clear localstorage
|
|
||||||
- prevent sending personal data
|
|
||||||
- 💚 Publish html as workflow asset and code in public repository
|
|
||||||
- Add sitemap and tell robots.txt to scan the sitemap
|
|
||||||
- Add Changelog
|
|
||||||
### Changes
|
|
||||||
- (#18) 📝 Update header for reasons section
|
|
||||||
- (#3) ✏ Replace codiv by covid in package.json, README
|
|
||||||
- changes start target
|
|
||||||
- (#1) 🐛 Autocomplete birthday field only on keyup, not when deleting
|
|
||||||
- (#1) 🎨 Improve regex control pattern for birhtday
|
|
||||||
- :recycle: Move check update code to dedicated file
|
|
||||||
- :recycle: Move dom utils in dedicated file
|
|
||||||
- :sparkles: Notify user about newer version
|
|
||||||
- :sparkles: Add cache with service workers
|
|
||||||
- :recycle: Cleanup directory structure
|
|
||||||
- :heavy_plus_sign: Avoid using env specific syntax in npm scripts
|
|
||||||
- changes PWA display
|
|
||||||
## [1.1.1] - 2020-04-09
|
|
||||||
### Fixed
|
|
||||||
- :wrench: Fix parcel-plugin-sw-cache configuration
|
|
||||||
### Added
|
|
||||||
- :pencil: add CONTRIBUTORS
|
|
||||||
### Changes
|
|
||||||
- :pencil: change LICENCE ( #16 )
|
|
||||||
## [1.1.2] - 2020-04-10
|
|
||||||
### Added
|
|
||||||
- ♿ Increase contrast ratio hover link color (#29)
|
|
||||||
- ♿ Add landmarks roles to header, main and footer sections (#43)
|
|
||||||
- ♿ Add title to open stores link and add more explicit text (#44, #45)
|
|
||||||
- ♿ Expose aria-invalid field assistance technologies (#24)
|
|
||||||
- ✨ Add timestamp to generated pdf (#9)
|
|
||||||
- 💄 Don't use autocompletion for release date and time (#31)
|
|
||||||
- 💄 Add underline on hover links
|
|
||||||
### Fixes
|
|
||||||
- Fix Typo site.webmanifest (#52)
|
|
||||||
|
|
21
CONTRIBUTORS
|
@ -1,20 +1,13 @@
|
||||||
Ce générateur d'attestation de déplacement dérogatoire a été mis en place dans le cadre du confinement lié à la pandémie du virus COVID-19 de 2020.
|
Ce générateur d'attestation de déplacement international dérogatoire a été mis en place dans le cadre du confinement lié à la pandémie du virus COVID-19 de 2020.
|
||||||
Ce service repose sur l'utilisation initale du projet covid-19-certificate <https://github.com/nesk/covid-19-certificate> de Johann Pardanaud <https://github.com/nesk>.
|
Ce service repose sur l'utilisation initale du projet covid-19-certificate <https://github.com/nesk/covid-19-certificate> de Johann Pardanaud <https://github.com/nesk> et de l'attestation de déplacement nationale dérogatoire <https://github.com/LAB-MI/deplacement-covid-19> du ministère de l'intérieur.
|
||||||
Il a été enrichi par l'incubateur du ministère de l'intérieur : le LAB-MI <https://beta.interieur.gouv.fr>.
|
Il a été enrichi par l'incubateur du ministère de l'intérieur : le LAB-MI <https://beta.interieur.gouv.fr>.
|
||||||
|
|
||||||
La liste qui suit mentionne les différents participants ayant contribué à rendre ce service utile à la fois à la population et aux forces de l'ordre :
|
La liste qui suit mentionne les différents participants ayant contribué à rendre ce service utile à la fois à la population et aux forces de l'ordre :
|
||||||
|
|
||||||
Johann Pardanaud (https://github.com/nesk)
|
|
||||||
|
La liste qui suit mentionne les différents participants ayant contribué à rendre ce service utile à la fois à la population et aux forces de l'ordre :
|
||||||
|
|
||||||
Philippe Bron (https://github.com/PhilippeBron)
|
Philippe Bron (https://github.com/PhilippeBron)
|
||||||
Cristian (https://github.com/cristianpb)
|
Cristian (https://github.com/cristianpb)
|
||||||
Stanislas Ormières (https://github.com/laruiss)
|
Victor Journé (https://github.com/victorjourne)
|
||||||
Caroline Robillard (https://github.com/Carolinedanslesnuages)
|
Philippe (https://github.com/pli01)
|
||||||
Joel Pagniez (https://github.com/JoelPagniez)
|
|
||||||
Sophie GUERLAIS
|
|
||||||
Philippe (https://github.com/pli01)
|
|
||||||
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)
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Générateur de certificat de déplacement
|
# Générateur: ATTESTATION DE DÉPLACEMENT INTERNATIONAL DÉROGATOIRE VERS LA FRANCE MÉTROPOLITAINE
|
||||||
|
|
||||||
## Développer
|
## Développer
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
# Attestation de déplacement international dérogatoire vers la France métropolitaine
|
||||||
|
|
||||||
|
## Fichiers pdf des attestations papier :
|
||||||
|
|
||||||
|
- version française : 07-04-20-Attestation-etranger-metropole-FR.pdf
|
||||||
|
- version anglaise : Attestation_deplacement_International_EN-1.pdf
|
||||||
|
|
||||||
|
## Analyse de la structure du document
|
||||||
|
|
||||||
|
### Champs ajoutés :
|
||||||
|
|
||||||
|
- nationalité
|
||||||
|
- typologie de nationalités : pays tiers ; eu ou assimilés ; française
|
||||||
|
|
||||||
|
### Champs supprimés :
|
||||||
|
|
||||||
|
- lieu de naissance
|
||||||
|
- date de sortie
|
||||||
|
- heure de sortie
|
||||||
|
|
||||||
|
### Remarques :
|
||||||
|
|
||||||
|
- Les motifs sont identiques pour les types tiers et eu.
|
||||||
|
- Pas de motif pour les français.
|
||||||
|
- Un seul motif possible défini en fonction du type de nationalité
|
||||||
|
|
||||||
|
## Structure des champs du QR Code
|
||||||
|
|
||||||
|
- **Cree le:** creationDate a creationHour;\n
|
||||||
|
- **Nom:** `firstname`;\n
|
||||||
|
- **Prenom:** `lastname`;\n
|
||||||
|
- **Naissance:** `birthday` (`nationality`);\n
|
||||||
|
- **Adresse:** `address` `zipcode` `town` `country`;\n
|
||||||
|
- **Sortie:** N/A;\n
|
||||||
|
- **Motifs:** `national`-`reason` (`reaseon` à vide pour les français)
|
||||||
|
|
||||||
|
### Correspondances formulaire/QR Code
|
||||||
|
|
||||||
|
Afin de pouvoir être sotckées dans le QR Code, à chaque choix du formulaire est associé un alias.
|
||||||
|
|
||||||
|
#### types de nationalités
|
||||||
|
|
||||||
|
| libellé formulaire | alias |
|
||||||
|
|:-----|:-----|
|
||||||
|
| Ressortissants de pays tiers | tiers |
|
||||||
|
| Ressortissants de l’Union européenne et assimilés | eu |
|
||||||
|
| Ressortissants de nationalité française | fr |
|
||||||
|
|
||||||
|
#### types de motifs
|
||||||
|
|
||||||
|
| libellé formulaire | alias |
|
||||||
|
|:-----|:-----|
|
||||||
|
| Personnes ayant leur résidence principale en France | residence |
|
||||||
|
| Personnes transitant par la France pour rejoindre leur résidence | transit |
|
||||||
|
| Professionnels de santé aux fins de lutter contre le Covid-19 | prof._sante |
|
||||||
|
| Transporteurs de marchandises | marchandises |
|
||||||
|
| Equipages et personnels exploitant des vols | equipage |
|
||||||
|
| Personnels des missions diplomatiques et consulaires | diplomatique |
|
||||||
|
| Travailleurs frontaliers | frontalier |
|
|
@ -0,0 +1,52 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<script src="https://unpkg.com/pdf-lib@1.4.1"></script>
|
||||||
|
<script src="https://unpkg.com/downloadjs@1.4.7"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<label for="file">Sélectionner le pdf</label>
|
||||||
|
<input type="file" id="file" name="file" onchange="generatePdf()">
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
const { PDFDocument, StandardFonts, rgb } = PDFLib
|
||||||
|
|
||||||
|
async function generatePdf () {
|
||||||
|
var pdfBase = document.getElementById("file").files[0];
|
||||||
|
var buffer = await pdfBase.arrayBuffer();
|
||||||
|
|
||||||
|
const pdfDoc = await PDFDocument.load(buffer)
|
||||||
|
|
||||||
|
const page1 = pdfDoc.getPages()[0]
|
||||||
|
|
||||||
|
const font = await pdfDoc.embedFont(StandardFonts.Helvetica)
|
||||||
|
const drawText = (text, x, y, size = 11) => {
|
||||||
|
page1.drawText(text, { x, y, size, font })
|
||||||
|
}
|
||||||
|
|
||||||
|
var x;
|
||||||
|
var y;
|
||||||
|
for (x = 25; x < 1000; x += 25) {
|
||||||
|
for (y = 25; y < 1000; y += 25) {
|
||||||
|
|
||||||
|
page1.drawText('.', { x: x, y: y, size: 11, font: font, color: rgb(0.95, 0.1, 0.1) })
|
||||||
|
page1.drawText(`${x}`, { x: x+3, y: y, size: 7, font: font, color: rgb(0, 0, 0) })
|
||||||
|
page1.drawText(`${y}`, { x: x+3, y: y-6, size: 7, font: font, color: rgb(0, 0, 0) })
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pdfDoc.addPage()
|
||||||
|
|
||||||
|
const pdfBytes = await pdfDoc.save()
|
||||||
|
|
||||||
|
// Trigger the browser to download the PDF document
|
||||||
|
download(pdfBytes, "grid.pdf", "application/pdf");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</html>
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "deplacement-covid-19",
|
"name": "deplacement-vers-france-covid-19",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
|
|
25
package.json
|
@ -1,15 +1,16 @@
|
||||||
{
|
{
|
||||||
"name": "deplacement-covid-19",
|
"name": "deplacement-vers-france-covid-19",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"description": "Générateur d'attestation de déplacement dérogatoire'",
|
"description": "Générateur d'attestation de déplacement international dérogatoire vers la France",
|
||||||
"main": "certificate.js",
|
"main": "certificate.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "eslint ./*.js",
|
"lint": "eslint src/*.js",
|
||||||
"start": "cross-env VERSION=${VERSION:-localversion} parcel --public-url ${PUBLIC_URL:-/deplacement-covid-19} ./src/index.html",
|
"format": "npm run lint -- --fix",
|
||||||
|
"start": "cross-env VERSION=${VERSION:-localversion} parcel --public-url ${PUBLIC_URL:-/deplacement-vers-france-covid-19} ./src/index.html",
|
||||||
"clean:dist": "rimraf dist",
|
"clean:dist": "rimraf dist",
|
||||||
"prebuild": "run-s lint clean:dist",
|
"prebuild": "run-s lint clean:dist",
|
||||||
"build": "parcel build --public-url ${PUBLIC_URL:-/deplacement-covid-19} ./src/index.html ./src/robots.txt ./src/sitemap.xml",
|
"build": "parcel build --public-url ${PUBLIC_URL:-/deplacement-vers-france-covid-19} ./src/index.html ./src/index-en.html ./src/robots.txt ./src/sitemap.xml",
|
||||||
"postbuild": "PUBLIC_URL=${PUBLIC_URL:-/deplacement-covid-19} react-snap",
|
"postbuild": "PUBLIC_URL=${PUBLIC_URL:-/deplacement-vers-france-covid-19} react-snap",
|
||||||
"preserve": "npm run build",
|
"preserve": "npm run build",
|
||||||
"serve": "serve dist",
|
"serve": "serve dist",
|
||||||
"serve:dist": "serve dist"
|
"serve:dist": "serve dist"
|
||||||
|
@ -19,7 +20,7 @@
|
||||||
"url": "git+https://github.com/lab-mi/deplacement-covid-19"
|
"url": "git+https://github.com/lab-mi/deplacement-covid-19"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "Ministère de l'Intérieur",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/lab-mi/deplacement-covid-19/issues"
|
"url": "https://github.com/lab-mi/deplacement-covid-19/issues"
|
||||||
|
@ -55,7 +56,8 @@
|
||||||
"qrcode": "^1.4.4"
|
"qrcode": "^1.4.4"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"last 5 versions"
|
"last 5 versions",
|
||||||
|
"ios_saf >= 7"
|
||||||
],
|
],
|
||||||
"reactSnap": {
|
"reactSnap": {
|
||||||
"source": "dist",
|
"source": "dist",
|
||||||
|
@ -73,6 +75,9 @@
|
||||||
"strategy": "default",
|
"strategy": "default",
|
||||||
"clearDist": false,
|
"clearDist": false,
|
||||||
"templatedURLs": {
|
"templatedURLs": {
|
||||||
"./": ["index.html"]
|
"./": [
|
||||||
} }
|
"index.html"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 24.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 900 600" style="enable-background:new 0 0 900 600;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#ED2939;}
|
||||||
|
.st1{fill:#FFFFFF;}
|
||||||
|
.st2{fill:#002395;}
|
||||||
|
</style>
|
||||||
|
<rect y="0" class="st0" width="900" height="600"/>
|
||||||
|
<rect y="0" class="st1" width="600" height="600"/>
|
||||||
|
<rect y="0" class="st2" width="300" height="600"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 606 B |
|
@ -0,0 +1,328 @@
|
||||||
|
import 'bootstrap/dist/css/bootstrap.min.css'
|
||||||
|
|
||||||
|
import './main.css'
|
||||||
|
|
||||||
|
import { PDFDocument, StandardFonts } from 'pdf-lib'
|
||||||
|
import QRCode from 'qrcode'
|
||||||
|
import { library, dom } from '@fortawesome/fontawesome-svg-core'
|
||||||
|
import { faEye, faFilePdf } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
|
import './check-updates'
|
||||||
|
import { $, $$ } from './dom-utils'
|
||||||
|
import pdfBase from './Attestation_deplacement_International_EN-1.pdf'
|
||||||
|
|
||||||
|
library.add(faEye, faFilePdf)
|
||||||
|
|
||||||
|
dom.watch()
|
||||||
|
|
||||||
|
$('#radio-language-fr').addEventListener('click', async event => {
|
||||||
|
window.location.href = `${process.env.PUBLIC_URL === '/' ? '' : process.env.PUBLIC_URL}/index.html`
|
||||||
|
})
|
||||||
|
|
||||||
|
const generateQR = async text => {
|
||||||
|
try {
|
||||||
|
const opts = {
|
||||||
|
errorCorrectionLevel: 'M',
|
||||||
|
type: 'image/png',
|
||||||
|
quality: 0.92,
|
||||||
|
margin: 1,
|
||||||
|
}
|
||||||
|
return await QRCode.toDataURL(text, opts)
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveProfile () {
|
||||||
|
for (const field of $$('#form-profile input')) {
|
||||||
|
localStorage.setItem(field.id.substring('field-'.length), field.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getProfile () {
|
||||||
|
const fields = {}
|
||||||
|
for (let i = 0; i < localStorage.length; i++) {
|
||||||
|
const name = localStorage.key(i)
|
||||||
|
fields[name] = localStorage.getItem(name)
|
||||||
|
}
|
||||||
|
return fields
|
||||||
|
}
|
||||||
|
|
||||||
|
function idealFontSize (font, text, maxWidth, minSize, defaultSize) {
|
||||||
|
let currentSize = defaultSize
|
||||||
|
let textWidth = font.widthOfTextAtSize(text, defaultSize)
|
||||||
|
|
||||||
|
while (textWidth > maxWidth && currentSize > minSize) {
|
||||||
|
textWidth = font.widthOfTextAtSize(text, --currentSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (textWidth > maxWidth) ? null : currentSize
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generatePdf (profile, typeNationality, reasons) {
|
||||||
|
const creationDate = new Date().toLocaleDateString('fr-FR')
|
||||||
|
const creationHour = new Date().toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' }).replace(':', 'h')
|
||||||
|
|
||||||
|
const { lastname, firstname, birthday, nationality, address, zipcode, town, country } = profile
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
`Cree le: ${creationDate} a ${creationHour}`,
|
||||||
|
`Nom: ${lastname}`,
|
||||||
|
`Prenom: ${firstname}`,
|
||||||
|
`Naissance: ${birthday} (${nationality})`,
|
||||||
|
`Adresse: ${address} ${zipcode} ${town} ${country}`,
|
||||||
|
'Sortie: N/A',
|
||||||
|
`Motifs: ${typeNationality}-${reasons}`,
|
||||||
|
].join(';\n ')
|
||||||
|
|
||||||
|
const existingPdfBytes = await fetch(pdfBase).then(res => res.arrayBuffer())
|
||||||
|
|
||||||
|
const pdfDoc = await PDFDocument.load(existingPdfBytes)
|
||||||
|
const page1 = pdfDoc.getPages()[0]
|
||||||
|
|
||||||
|
const font = await pdfDoc.embedFont(StandardFonts.Helvetica)
|
||||||
|
const drawText = (text, x, y, size = 11) => {
|
||||||
|
page1.drawText(text, { x, y, size, font })
|
||||||
|
}
|
||||||
|
|
||||||
|
drawText(`${firstname} ${lastname}`, 125, 590)
|
||||||
|
drawText(birthday, 125, 567)
|
||||||
|
drawText(nationality, 125, 545)
|
||||||
|
drawText(`${address} ${zipcode}`, 127, 527)
|
||||||
|
drawText(`${town}, ${country}`, 127, 505)
|
||||||
|
|
||||||
|
if (typeNationality === 'tiers') {
|
||||||
|
if (reasons.includes('residence')) {
|
||||||
|
drawText('x', 49, 449, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('transit')) {
|
||||||
|
drawText('x', 49, 412, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('prof._sante')) {
|
||||||
|
drawText('x', 49, 385, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('marchandises')) {
|
||||||
|
drawText('x', 49, 370, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('equipage')) {
|
||||||
|
drawText('x', 49, 354, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('diplomatique')) {
|
||||||
|
drawText('x', 49, 339, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('frontalier')) {
|
||||||
|
drawText('x', 49, 313, 19)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeNationality === 'eu') {
|
||||||
|
if (reasons.includes('resident')) {
|
||||||
|
drawText('x', 49, 276, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('transit')) {
|
||||||
|
drawText('x', 49, 263, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('prof._sante')) {
|
||||||
|
drawText('x', 49, 250, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('marchandises')) {
|
||||||
|
drawText('x', 49, 238, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('equipage')) {
|
||||||
|
drawText('x', 49, 225, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('diplomatique')) {
|
||||||
|
drawText('x', 49, 212, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('frontalier')) {
|
||||||
|
drawText('x', 49, 189, 19)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeNationality === 'fr') {
|
||||||
|
drawText('x', 49, 162, 19)
|
||||||
|
}
|
||||||
|
let locationSize = idealFontSize(font, profile.town, 83, 7, 11)
|
||||||
|
|
||||||
|
if (!locationSize) {
|
||||||
|
alert('Le nom de la ville risque de ne pas être affiché correctement en raison de sa longueur. ' +
|
||||||
|
'Essayez d\'utiliser des abréviations ("Saint" en "St." par exemple) quand cela est possible.')
|
||||||
|
locationSize = 7
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fait à :
|
||||||
|
drawText(profile.town, 395, 142, locationSize)
|
||||||
|
// Le
|
||||||
|
drawText(`${new Date().toLocaleDateString('fr-FR', { month: 'numeric', day: 'numeric' })}`, 488, 142)
|
||||||
|
|
||||||
|
const generatedQR = await generateQR(data)
|
||||||
|
|
||||||
|
const qrImage = await pdfDoc.embedPng(generatedQR)
|
||||||
|
|
||||||
|
page1.drawImage(qrImage, {
|
||||||
|
x: 450,
|
||||||
|
y: 572,
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
})
|
||||||
|
|
||||||
|
pdfDoc.addPage()
|
||||||
|
const page2 = pdfDoc.getPages()[1]
|
||||||
|
page2.drawImage(qrImage, {
|
||||||
|
x: 50,
|
||||||
|
y: page2.getHeight() - 350,
|
||||||
|
width: 300,
|
||||||
|
height: 300,
|
||||||
|
})
|
||||||
|
|
||||||
|
const pdfBytes = await pdfDoc.save()
|
||||||
|
|
||||||
|
return new Blob([pdfBytes], { type: 'application/pdf' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function downloadBlob (blob, fileName) {
|
||||||
|
const link = document.createElement('a')
|
||||||
|
const url = URL.createObjectURL(blob)
|
||||||
|
link.href = url
|
||||||
|
link.download = fileName
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAndSaveReasons () {
|
||||||
|
const values = $$('input[name="field-reason"]:checked')
|
||||||
|
.map(x => x.value)
|
||||||
|
.join('-')
|
||||||
|
localStorage.setItem('reasons', values)
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAndSaveTypeNationality () {
|
||||||
|
const typeNationality = $$('input[name="field-type-nationality"]:checked')
|
||||||
|
.map(x => x.value)
|
||||||
|
.join('-')
|
||||||
|
localStorage.setItem('typeNationality', typeNationality)
|
||||||
|
|
||||||
|
return typeNationality
|
||||||
|
}
|
||||||
|
|
||||||
|
// see: https://stackoverflow.com/a/32348687/1513045
|
||||||
|
function isFacebookBrowser () {
|
||||||
|
const ua = navigator.userAgent || navigator.vendor || window.opera
|
||||||
|
return ua.includes('FBAN') || ua.includes('FBAV')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFacebookBrowser()) {
|
||||||
|
$('#alert-facebook').value = 'ATTENTION !! Vous utilisez actuellement le navigateur Facebook, ce générateur ne fonctionne pas correctement au sein de ce navigateur ! Merci d\'ouvrir Chrome sur Android ou bien Safari sur iOS.'
|
||||||
|
$('#alert-facebook').classList.remove('d-none')
|
||||||
|
}
|
||||||
|
|
||||||
|
function addSlash () {
|
||||||
|
$('#field-birthday').value = $('#field-birthday').value.replace(/^(\d{2})$/g, '$1/')
|
||||||
|
$('#field-birthday').value = $('#field-birthday').value.replace(/^(\d{2})\/(\d{2})$/g, '$1/$2/')
|
||||||
|
$('#field-birthday').value = $('#field-birthday').value.replace(/\/\//g, '/')
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#field-birthday').onkeyup = function () {
|
||||||
|
const key = event.keyCode || event.charCode
|
||||||
|
if (key === 8 || key === 46) {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
addSlash()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const snackbar = $('#snackbar')
|
||||||
|
|
||||||
|
$('#generate-btn').addEventListener('click', async event => {
|
||||||
|
event.preventDefault()
|
||||||
|
|
||||||
|
saveProfile()
|
||||||
|
const typeNationality = getAndSaveTypeNationality()
|
||||||
|
let reasons
|
||||||
|
if (typeNationality === 'fr') {
|
||||||
|
reasons = 'N/A'
|
||||||
|
} else {
|
||||||
|
reasons = getAndSaveReasons()
|
||||||
|
}
|
||||||
|
|
||||||
|
const pdfBlob = await generatePdf(getProfile(), typeNationality, reasons)
|
||||||
|
localStorage.clear()
|
||||||
|
const creationDate = new Date().toLocaleDateString('fr-CA')
|
||||||
|
const creationHour = new Date().toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' }).replace(':', '-')
|
||||||
|
downloadBlob(pdfBlob, `attestation-${creationDate}_${creationHour}.pdf`)
|
||||||
|
|
||||||
|
snackbar.classList.remove('d-none')
|
||||||
|
setTimeout(() => snackbar.classList.add('show'), 100)
|
||||||
|
|
||||||
|
setTimeout(function () {
|
||||||
|
snackbar.classList.remove('show')
|
||||||
|
setTimeout(() => snackbar.classList.add('d-none'), 500)
|
||||||
|
}, 6000)
|
||||||
|
})
|
||||||
|
|
||||||
|
$$('input').forEach(input => {
|
||||||
|
const exempleElt = input.parentNode.parentNode.querySelector('.exemple')
|
||||||
|
if (input.placeholder && exempleElt) {
|
||||||
|
input.addEventListener('input', (event) => {
|
||||||
|
if (input.value) {
|
||||||
|
exempleElt.innerHTML = 'ex. : ' + input.placeholder
|
||||||
|
} else {
|
||||||
|
exempleElt.innerHTML = ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const conditions = {
|
||||||
|
'#field-firstname': {
|
||||||
|
condition: 'length',
|
||||||
|
},
|
||||||
|
'#field-lastname': {
|
||||||
|
condition: 'length',
|
||||||
|
},
|
||||||
|
'#field-birthday': {
|
||||||
|
condition: 'pattern',
|
||||||
|
pattern: /^([0][1-9]|[1-2][0-9]|30|31)\/([0][1-9]|10|11|12)\/(19[0-9][0-9]|20[0-1][0-9]|2020)/g,
|
||||||
|
},
|
||||||
|
'#field-nationality': {
|
||||||
|
condition: 'length',
|
||||||
|
},
|
||||||
|
'#field-address': {
|
||||||
|
condition: 'length',
|
||||||
|
},
|
||||||
|
'#field-town': {
|
||||||
|
condition: 'length',
|
||||||
|
},
|
||||||
|
'#field-zipcode': {
|
||||||
|
condition: 'lenght',
|
||||||
|
},
|
||||||
|
'#field-country': {
|
||||||
|
condition: 'length',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(conditions).forEach(field => {
|
||||||
|
$(field).addEventListener('input', () => {
|
||||||
|
if (conditions[field].condition === 'pattern') {
|
||||||
|
const pattern = conditions[field].pattern
|
||||||
|
if ($(field).value.match(pattern)) {
|
||||||
|
$(field).setAttribute('aria-invalid', 'false')
|
||||||
|
} else {
|
||||||
|
$(field).setAttribute('aria-invalid', 'true')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (conditions[field].condition === 'length') {
|
||||||
|
if ($(field).value.length > 0) {
|
||||||
|
$(field).setAttribute('aria-invalid', 'false')
|
||||||
|
} else {
|
||||||
|
$(field).setAttribute('aria-invalid', 'true')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
function addVersion () {
|
||||||
|
document.getElementById('version').innerHTML = `${new Date().getFullYear()} - ${process.env.VERSION}`
|
||||||
|
}
|
||||||
|
addVersion()
|
|
@ -9,17 +9,19 @@ import { faEye, faFilePdf } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
import './check-updates'
|
import './check-updates'
|
||||||
import { $, $$ } from './dom-utils'
|
import { $, $$ } from './dom-utils'
|
||||||
import pdfBase from './certificate.pdf'
|
import pdfBase from './07-04-20-Attestation-etranger-metropole-FR.pdf'
|
||||||
|
|
||||||
library.add(faEye, faFilePdf)
|
library.add(faEye, faFilePdf)
|
||||||
|
|
||||||
dom.watch()
|
dom.watch()
|
||||||
|
|
||||||
var year, month, day
|
$('#radio-language-en').addEventListener('click', async event => {
|
||||||
|
window.location.href = `${process.env.PUBLIC_URL === '/' ? '' : process.env.PUBLIC_URL}/index-en.html`
|
||||||
|
})
|
||||||
|
|
||||||
const generateQR = async text => {
|
const generateQR = async text => {
|
||||||
try {
|
try {
|
||||||
var opts = {
|
const opts = {
|
||||||
errorCorrectionLevel: 'M',
|
errorCorrectionLevel: 'M',
|
||||||
type: 'image/png',
|
type: 'image/png',
|
||||||
quality: 0.92,
|
quality: 0.92,
|
||||||
|
@ -31,39 +33,9 @@ const generateQR = async text => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function pad (str) {
|
|
||||||
return String(str).padStart(2, '0')
|
|
||||||
}
|
|
||||||
|
|
||||||
function setDateNow (date) {
|
|
||||||
year = date.getFullYear()
|
|
||||||
month = pad(date.getMonth() + 1) // Les mois commencent à 0
|
|
||||||
day = pad(date.getDate())
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', setReleaseDateTime)
|
|
||||||
|
|
||||||
function setReleaseDateTime () {
|
|
||||||
const loadedDate = new Date()
|
|
||||||
setDateNow(loadedDate)
|
|
||||||
const releaseDateInput = document.querySelector('#field-datesortie')
|
|
||||||
releaseDateInput.value = `${year}-${month}-${day}`
|
|
||||||
|
|
||||||
const hour = pad(loadedDate.getHours())
|
|
||||||
const minute = pad(loadedDate.getMinutes())
|
|
||||||
|
|
||||||
const releaseTimeInput = document.querySelector('#field-heuresortie')
|
|
||||||
releaseTimeInput.value = `${hour}:${minute}`
|
|
||||||
}
|
|
||||||
|
|
||||||
function saveProfile () {
|
function saveProfile () {
|
||||||
for (const field of $$('#form-profile input')) {
|
for (const field of $$('#form-profile input')) {
|
||||||
if (field.id === 'field-datesortie') {
|
localStorage.setItem(field.id.substring('field-'.length), field.value)
|
||||||
var dateSortie = field.value.split('-')
|
|
||||||
localStorage.setItem(field.id.substring('field-'.length), `${dateSortie[2]}/${dateSortie[1]}/${dateSortie[0]}`)
|
|
||||||
} else {
|
|
||||||
localStorage.setItem(field.id.substring('field-'.length), field.value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,23 +59,21 @@ function idealFontSize (font, text, maxWidth, minSize, defaultSize) {
|
||||||
return (textWidth > maxWidth) ? null : currentSize
|
return (textWidth > maxWidth) ? null : currentSize
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generatePdf (profile, reasons) {
|
async function generatePdf (profile, typeNationality, reasons) {
|
||||||
const creationDate = new Date().toLocaleDateString('fr-FR')
|
const creationDate = new Date().toLocaleDateString('fr-FR')
|
||||||
const creationHour = new Date().toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' }).replace(':', 'h')
|
const creationHour = new Date().toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' }).replace(':', 'h')
|
||||||
|
|
||||||
const { lastname, firstname, birthday, lieunaissance, address, zipcode, town, datesortie, heuresortie } = profile
|
const { lastname, firstname, birthday, nationality, address, zipcode, town, country } = profile
|
||||||
const releaseHours = String(heuresortie).substring(0, 2)
|
|
||||||
const releaseMinutes = String(heuresortie).substring(3, 5)
|
|
||||||
|
|
||||||
const data = [
|
const data = [
|
||||||
`Cree le: ${creationDate} a ${creationHour}`,
|
`Cree le: ${creationDate} a ${creationHour}`,
|
||||||
`Nom: ${lastname}`,
|
`Nom: ${lastname}`,
|
||||||
`Prenom: ${firstname}`,
|
`Prenom: ${firstname}`,
|
||||||
`Naissance: ${birthday} a ${lieunaissance}`,
|
`Naissance: ${birthday} (${nationality})`,
|
||||||
`Adresse: ${address} ${zipcode} ${town}`,
|
`Adresse: ${address} ${zipcode} ${town} ${country}`,
|
||||||
`Sortie: ${datesortie} a ${releaseHours}h${releaseMinutes}`,
|
'Sortie: N/A',
|
||||||
`Motifs: ${reasons}`,
|
`Motifs: ${typeNationality}-${reasons}`,
|
||||||
].join('; ')
|
].join(';\n ')
|
||||||
|
|
||||||
const existingPdfBytes = await fetch(pdfBase).then(res => res.arrayBuffer())
|
const existingPdfBytes = await fetch(pdfBase).then(res => res.arrayBuffer())
|
||||||
|
|
||||||
|
@ -115,31 +85,61 @@ async function generatePdf (profile, reasons) {
|
||||||
page1.drawText(text, { x, y, size, font })
|
page1.drawText(text, { x, y, size, font })
|
||||||
}
|
}
|
||||||
|
|
||||||
drawText(`${firstname} ${lastname}`, 123, 686)
|
drawText(`${firstname} ${lastname}`, 125, 590)
|
||||||
drawText(birthday, 123, 661)
|
drawText(birthday, 125, 567)
|
||||||
drawText(lieunaissance, 92, 638)
|
drawText(nationality, 125, 545)
|
||||||
drawText(`${address} ${zipcode} ${town}`, 134, 613)
|
drawText(`${address} ${zipcode}`, 127, 527)
|
||||||
|
drawText(`${town}, ${country}`, 127, 505)
|
||||||
|
|
||||||
if (reasons.includes('travail')) {
|
if (typeNationality === 'tiers') {
|
||||||
drawText('x', 76, 527, 19)
|
if (reasons.includes('residence')) {
|
||||||
|
drawText('x', 49, 449, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('transit')) {
|
||||||
|
drawText('x', 49, 412, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('prof._sante')) {
|
||||||
|
drawText('x', 49, 385, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('marchandises')) {
|
||||||
|
drawText('x', 49, 370, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('equipage')) {
|
||||||
|
drawText('x', 49, 354, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('diplomatique')) {
|
||||||
|
drawText('x', 49, 328, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('frontalier')) {
|
||||||
|
drawText('x', 49, 302, 19)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (reasons.includes('courses')) {
|
|
||||||
drawText('x', 76, 478, 19)
|
if (typeNationality === 'eu') {
|
||||||
|
if (reasons.includes('resident')) {
|
||||||
|
drawText('x', 49, 265, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('transit')) {
|
||||||
|
drawText('x', 49, 249, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('prof._sante')) {
|
||||||
|
drawText('x', 49, 234, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('marchandises')) {
|
||||||
|
drawText('x', 49, 218, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('equipage')) {
|
||||||
|
drawText('x', 49, 202, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('diplomatique')) {
|
||||||
|
drawText('x', 49, 177, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('frontalier')) {
|
||||||
|
drawText('x', 49, 150, 19)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (reasons.includes('sante')) {
|
if (typeNationality === 'fr') {
|
||||||
drawText('x', 76, 436, 19)
|
drawText('x', 49, 127, 19)
|
||||||
}
|
|
||||||
if (reasons.includes('famille')) {
|
|
||||||
drawText('x', 76, 400, 19)
|
|
||||||
}
|
|
||||||
if (reasons.includes('sport')) {
|
|
||||||
drawText('x', 76, 345, 19)
|
|
||||||
}
|
|
||||||
if (reasons.includes('judiciaire')) {
|
|
||||||
drawText('x', 76, 298, 19)
|
|
||||||
}
|
|
||||||
if (reasons.includes('missions')) {
|
|
||||||
drawText('x', 76, 260, 19)
|
|
||||||
}
|
}
|
||||||
let locationSize = idealFontSize(font, profile.town, 83, 7, 11)
|
let locationSize = idealFontSize(font, profile.town, 83, 7, 11)
|
||||||
|
|
||||||
|
@ -149,26 +149,18 @@ async function generatePdf (profile, reasons) {
|
||||||
locationSize = 7
|
locationSize = 7
|
||||||
}
|
}
|
||||||
|
|
||||||
drawText(profile.town, 111, 226, locationSize)
|
// Fait à :
|
||||||
|
drawText(profile.town, 388, 107, locationSize)
|
||||||
if (reasons !== '') {
|
// Le
|
||||||
// Date sortie
|
drawText(`${new Date().toLocaleDateString('fr-FR', { month: 'numeric', day: 'numeric' })}`, 488, 107)
|
||||||
drawText(`${profile.datesortie}`, 92, 200)
|
|
||||||
drawText(releaseHours, 200, 201)
|
|
||||||
drawText(releaseMinutes, 220, 201)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Date création
|
|
||||||
drawText('Date de création:', 464, 150, 7)
|
|
||||||
drawText(`${creationDate} à ${creationHour}`, 455, 144, 7)
|
|
||||||
|
|
||||||
const generatedQR = await generateQR(data)
|
const generatedQR = await generateQR(data)
|
||||||
|
|
||||||
const qrImage = await pdfDoc.embedPng(generatedQR)
|
const qrImage = await pdfDoc.embedPng(generatedQR)
|
||||||
|
|
||||||
page1.drawImage(qrImage, {
|
page1.drawImage(qrImage, {
|
||||||
x: page1.getWidth() - 170,
|
x: 450,
|
||||||
y: 155,
|
y: 572,
|
||||||
width: 100,
|
width: 100,
|
||||||
height: 100,
|
height: 100,
|
||||||
})
|
})
|
||||||
|
@ -189,7 +181,7 @@ async function generatePdf (profile, reasons) {
|
||||||
|
|
||||||
function downloadBlob (blob, fileName) {
|
function downloadBlob (blob, fileName) {
|
||||||
const link = document.createElement('a')
|
const link = document.createElement('a')
|
||||||
var url = URL.createObjectURL(blob)
|
const url = URL.createObjectURL(blob)
|
||||||
link.href = url
|
link.href = url
|
||||||
link.download = fileName
|
link.download = fileName
|
||||||
document.body.appendChild(link)
|
document.body.appendChild(link)
|
||||||
|
@ -204,6 +196,15 @@ function getAndSaveReasons () {
|
||||||
return values
|
return values
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getAndSaveTypeNationality () {
|
||||||
|
const typeNationality = $$('input[name="field-type-nationality"]:checked')
|
||||||
|
.map(x => x.value)
|
||||||
|
.join('-')
|
||||||
|
localStorage.setItem('typeNationality', typeNationality)
|
||||||
|
|
||||||
|
return typeNationality
|
||||||
|
}
|
||||||
|
|
||||||
// see: https://stackoverflow.com/a/32348687/1513045
|
// see: https://stackoverflow.com/a/32348687/1513045
|
||||||
function isFacebookBrowser () {
|
function isFacebookBrowser () {
|
||||||
const ua = navigator.userAgent || navigator.vendor || window.opera
|
const ua = navigator.userAgent || navigator.vendor || window.opera
|
||||||
|
@ -237,12 +238,19 @@ $('#generate-btn').addEventListener('click', async event => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
saveProfile()
|
saveProfile()
|
||||||
const reasons = getAndSaveReasons()
|
const typeNationality = getAndSaveTypeNationality()
|
||||||
const pdfBlob = await generatePdf(getProfile(), reasons)
|
let reasons
|
||||||
|
if (typeNationality === 'fr') {
|
||||||
|
reasons = 'N/A'
|
||||||
|
} else {
|
||||||
|
reasons = getAndSaveReasons()
|
||||||
|
}
|
||||||
|
|
||||||
|
const pdfBlob = await generatePdf(getProfile(), typeNationality, reasons)
|
||||||
localStorage.clear()
|
localStorage.clear()
|
||||||
const creationDate = new Date().toLocaleDateString('fr-CA')
|
const creationDate = new Date().toLocaleDateString('fr-CA')
|
||||||
const creationHour = new Date().toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' }).replace(':', '-')
|
const creationHour = new Date().toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' }).replace(':', '-')
|
||||||
downloadBlob(pdfBlob, `attestation-${creationDate}_${creationHour}.pdf`)
|
downloadBlob(pdfBlob, `attestation-${creationDate}_${creationHour}.pdf`)
|
||||||
|
|
||||||
snackbar.classList.remove('d-none')
|
snackbar.classList.remove('d-none')
|
||||||
setTimeout(() => snackbar.classList.add('show'), 100)
|
setTimeout(() => snackbar.classList.add('show'), 100)
|
||||||
|
@ -275,9 +283,9 @@ const conditions = {
|
||||||
},
|
},
|
||||||
'#field-birthday': {
|
'#field-birthday': {
|
||||||
condition: 'pattern',
|
condition: 'pattern',
|
||||||
pattern: /^([0][1-9]|[1-2][0-9]|30|31)\/([0][1-9]|10|11|12)\/(19[0-9][0-9]|20[0-1][0-9]|2020)/g
|
pattern: /^([0][1-9]|[1-2][0-9]|30|31)\/([0][1-9]|10|11|12)\/(19[0-9][0-9]|20[0-1][0-9]|2020)/g,
|
||||||
},
|
},
|
||||||
'#field-lieunaissance': {
|
'#field-nationality': {
|
||||||
condition: 'length',
|
condition: 'length',
|
||||||
},
|
},
|
||||||
'#field-address': {
|
'#field-address': {
|
||||||
|
@ -287,34 +295,28 @@ const conditions = {
|
||||||
condition: 'length',
|
condition: 'length',
|
||||||
},
|
},
|
||||||
'#field-zipcode': {
|
'#field-zipcode': {
|
||||||
condition: 'pattern',
|
condition: 'lenght',
|
||||||
pattern: /\d{5}/g
|
|
||||||
},
|
},
|
||||||
'#field-datesortie': {
|
'#field-country': {
|
||||||
condition: 'pattern',
|
condition: 'length',
|
||||||
pattern: /\d{4}-\d{2}-\d{2}/g
|
|
||||||
},
|
},
|
||||||
'#field-heuresortie': {
|
|
||||||
condition: 'pattern',
|
|
||||||
pattern: /\d{2}:\d{2}/g
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.keys(conditions).forEach(field => {
|
Object.keys(conditions).forEach(field => {
|
||||||
$(field).addEventListener('input', () => {
|
$(field).addEventListener('input', () => {
|
||||||
if (conditions[field].condition == 'pattern') {
|
if (conditions[field].condition === 'pattern') {
|
||||||
const pattern = conditions[field].pattern;
|
const pattern = conditions[field].pattern
|
||||||
if ($(field).value.match(pattern)) {
|
if ($(field).value.match(pattern)) {
|
||||||
$(field).setAttribute('aria-invalid', "false");
|
$(field).setAttribute('aria-invalid', 'false')
|
||||||
} else {
|
} else {
|
||||||
$(field).setAttribute('aria-invalid', "true");
|
$(field).setAttribute('aria-invalid', 'true')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (conditions[field].condition == 'length') {
|
if (conditions[field].condition === 'length') {
|
||||||
if ($(field).value.length > 0) {
|
if ($(field).value.length > 0) {
|
||||||
$(field).setAttribute('aria-invalid', "false");
|
$(field).setAttribute('aria-invalid', 'false')
|
||||||
} else {
|
} else {
|
||||||
$(field).setAttribute('aria-invalid', "true");
|
$(field).setAttribute('aria-invalid', 'true')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Before Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 1.1 KiB |
|
@ -14,26 +14,6 @@
|
||||||
"src": "android-chrome-512x512.png",
|
"src": "android-chrome-512x512.png",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "apple-touch-icon.png",
|
|
||||||
"sizes": "180x180",
|
|
||||||
"type": "image/png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "apple-touch-icon-precomposed.png",
|
|
||||||
"sizes": "180x180",
|
|
||||||
"type": "image/png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "apple-touch-icon-120x120.png",
|
|
||||||
"sizes": "120x120",
|
|
||||||
"type": "image/png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "apple-touch-icon-120x120-precomposed.png",
|
|
||||||
"sizes": "120x120",
|
|
||||||
"type": "image/png"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"orientation": "portrait-primary",
|
"orientation": "portrait-primary",
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 24.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="flag_EN" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 207 133.5" style="enable-background:new 0 0 207 133.5;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#EDEDED;}
|
||||||
|
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:#CE0100;}
|
||||||
|
.st2{fill-rule:evenodd;clip-rule:evenodd;fill:#1E359B;}
|
||||||
|
.st3{fill:#EDEDED;}
|
||||||
|
.st4{fill:#CC0B1B;}
|
||||||
|
.st5{fill:#2C4DB5;}
|
||||||
|
</style>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<rect x="9.7" y="38.3" class="st0" width="138.6" height="92.4"/>
|
||||||
|
<polygon class="st1" points="148.3,76.8 148.3,92.3 85.8,92.3 85.8,130.7 72.2,130.7 72.2,92.3 9.7,92.3 9.7,76.8 72.2,76.8
|
||||||
|
72.2,38.3 85.8,38.3 85.8,76.8 "/>
|
||||||
|
<path class="st2" d="M22.5,38.3h46.2v30.5L22.5,38.3z M89.3,38.3h46.2L89.3,68.8V38.3z M148.3,47.8l-37.6,24.8h37.6V47.8z
|
||||||
|
M110.7,96.5h37.6v24.8L110.7,96.5z M135.6,130.7l-46.2-30.5v30.5H135.6z M9.7,96.5h37.6L9.7,121.3V96.5z M68.7,100.3l-46.2,30.5
|
||||||
|
h46.2V100.3z M47.3,72.6L9.7,47.8v24.8H47.3z"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st1" points="52.3,72.6 9.7,44.5 9.7,38.8 61,72.6 "/>
|
||||||
|
<polygon class="st1" points="68.7,97.2 17.8,130.7 9.7,130.7 9.7,130.4 61.1,96.5 68.7,96.5 "/>
|
||||||
|
<polygon class="st1" points="148.3,39 97.4,72.6 89.3,72.6 89.3,72.1 140.7,38.3 148.3,38.3 "/>
|
||||||
|
<polygon class="st1" points="148.3,130 97.4,96.5 106.1,96.5 148.3,124.3 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect x="64" y="4.4" class="st3" width="138.6" height="92.4"/>
|
||||||
|
<path class="st4" d="M64,89.7h138.6v7.1H64V89.7z M64,4.4h138.6v7.1H64V4.4z M64,18.6h138.6v7.1H64V18.6z M64,32.9h138.6V40H64
|
||||||
|
V32.9z M64,47.1h138.6v7.1H64V47.1z M64,61.3h138.6v7.1H64V61.3z M64,75.5h138.6v7.1H64V75.5z"/>
|
||||||
|
<rect x="64" y="4.4" class="st5" width="70.2" height="49.8"/>
|
||||||
|
<path class="st3" d="M128.9,18.4l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2l-0.6-2l1.7-1.2H128.9z M71.1,9.7l1.7-1.2h-2.1
|
||||||
|
l-0.6-2l-0.6,2h-2.1L69,9.7l-0.6,2l1.7-1.2l1.7,1.2L71.1,9.7z M82.7,9.7l1.7-1.2h-2.1l-0.6-2l-0.6,2H79l1.7,1.2l-0.6,2l1.7-1.2
|
||||||
|
l1.7,1.2L82.7,9.7z M94.3,9.7L96,8.5H94l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L94.3,9.7z M106,9.7l1.7-1.2h-2.1
|
||||||
|
l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L106,9.7z M77.2,44.4l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2
|
||||||
|
l1.7,1.2L77.2,44.4z M77,34.7l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L77,34.7z M77,25l1.7-1.2h-2.1
|
||||||
|
l-0.6-2l-0.6,2h-2.1L75,25l-0.6,2l1.7-1.2l1.7,1.2L77,25z M117.6,9.7l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2
|
||||||
|
l1.7,1.2L117.6,9.7z M129.3,9.7l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L129.3,9.7z M88.7,25l1.7-1.2h-2.1
|
||||||
|
l-0.6-2l-0.6,2h-2.1l1.7,1.2L86,27l1.7-1.2l1.7,1.2L88.7,25z M88.6,34.7l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2
|
||||||
|
l1.7,1.2L88.6,34.7z M88.8,44.4l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L88.8,44.4z M100.5,44.4l1.7-1.2
|
||||||
|
h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L100.5,44.4z M100.3,34.7l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2
|
||||||
|
l1.7-1.2l1.7,1.2L100.3,34.7z M100.3,25l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L100.3,25z M76.9,14.7
|
||||||
|
l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L76.9,14.7z M88.5,14.7l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2
|
||||||
|
l-0.6,2l1.7-1.2l1.7,1.2L88.5,14.7z M112,25l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L112,25z M111.9,34.7
|
||||||
|
l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L111.9,34.7z M112.1,44.4l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1
|
||||||
|
l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L112.1,44.4z M123.8,44.4l1.7-1.2h-2.1l-0.6-2l-0.6,2H120l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2
|
||||||
|
L123.8,44.4z M123.5,34.7l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L123.5,34.7z M123.6,25l1.7-1.2h-2.1
|
||||||
|
l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L123.6,25z M100.2,14.7l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2
|
||||||
|
l1.7-1.2l1.7,1.2L100.2,14.7z M111.8,14.7l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L111.8,14.7z
|
||||||
|
M123.5,14.7l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L123.5,14.7z M71.4,49.4l1.7-1.2H71l-0.6-2l-0.6,2
|
||||||
|
h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L71.4,49.4z M71.1,39.7l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2
|
||||||
|
L71.1,39.7z M71.2,30l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L71.2,30z M82.8,30l1.7-1.2h-2.1l-0.6-2
|
||||||
|
l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L82.8,30z M82.8,39.7l1.7-1.2h-2.1l-0.6-2l-0.6,2H79l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2
|
||||||
|
L82.8,39.7z M83,49.4l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L83,49.4z M94.7,49.4l1.7-1.2h-2.1l-0.6-2
|
||||||
|
l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L94.7,49.4z M94.4,39.7l1.7-1.2H94l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2
|
||||||
|
L94.4,39.7z M94.5,30l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L94.5,30z M71.1,19.7l1.7-1.2h-2.1l-0.6-2
|
||||||
|
l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L71.1,19.7z M82.7,19.7l1.7-1.2h-2.1l-0.6-2l-0.6,2H79l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2
|
||||||
|
L82.7,19.7z M106.1,30l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L106.1,30z M106.1,39.7l1.7-1.2h-2.1l-0.6-2
|
||||||
|
l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L106.1,39.7z M106.3,49.4l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2
|
||||||
|
l1.7,1.2L106.3,49.4z M117.9,49.4l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L117.9,49.4z M129.6,49.4
|
||||||
|
l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L129.6,49.4z M117.7,39.7l1.7-1.2h-2.1l-0.6-2l-0.6,2H114l1.7,1.2
|
||||||
|
l-0.6,2l1.7-1.2l1.7,1.2L117.7,39.7z M129.4,39.7l1.7-1.2H129l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L129.4,39.7z
|
||||||
|
M117.8,30l1.7-1.2h-2.1l-0.6-2l-0.6,2H114l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L117.8,30z M129.4,30l1.7-1.2H129l-0.6-2l-0.6,2h-2.1
|
||||||
|
l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L129.4,30z M94.3,19.7l1.7-1.2H94l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L94.3,19.7z
|
||||||
|
M106,19.7l1.7-1.2h-2.1l-0.6-2l-0.6,2h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L106,19.7z M117.6,19.7l1.7-1.2h-2.1l-0.6-2l-0.6,2
|
||||||
|
h-2.1l1.7,1.2l-0.6,2l1.7-1.2l1.7,1.2L117.6,19.7z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 6.1 KiB |
|
@ -0,0 +1,378 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="msapplication-TileColor" content="#603cba">
|
||||||
|
<meta name="msapplication-config" content="./favicons/browserconfig.xml">
|
||||||
|
<meta name="theme-color" content="#ffffff">
|
||||||
|
<meta name="title" content="international travel certificate to mainland France - COVID-19">
|
||||||
|
<meta name="description" content="Ce service officiel génère une version numérique de l’attestation déplacement covid-19 à présenter aux forces de sécurité lors d’un contrôle.">
|
||||||
|
<meta name="keywords" content="covid19, covid-19, certificate, travel, international, official, government">
|
||||||
|
<meta name="robots" content="index, follow">
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
|
<meta name="language" content="English">
|
||||||
|
<meta property="og:title" content="Generator of international travel certificate to mainland France - COVID-19" />
|
||||||
|
<meta property="og:locale" content="fr_FR" />
|
||||||
|
<meta property="og:description" content="Ce service officiel génère une version numérique de l’attestation déplacement covid-19 à présenter aux forces de sécurité lors d’un contrôle." />
|
||||||
|
<link rel="canonical" href="https://media.interieur.gouv.fr/deplacement-vers-france-covid-19/" />
|
||||||
|
<meta property="og:url" content="https://media.interieur.gouv.fr/deplacement-vers-france-covid-19/" />
|
||||||
|
<meta property="og:site_name" content="Generator of international travel certificate to mainland France - COVID-19" />
|
||||||
|
<script type='application/ld+json'>{"@context":"http://www.schema.org","@type":"GovernmentOrganization","name":"Générateur d'attestation de déplacement international dérogatoire vers la France métropolitaine - COVID-19","description":"Ce service officiel génère une version numérique de l’attestation déplacement covid-19 à présenter aux forces de sécurité lors d’un contrôle.","address":{"@type":"PostalAddress","addressCountry":"France"}}</script>
|
||||||
|
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="./favicons/apple-touch-icon.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="./favicons/favicon-32x32.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="./favicons/favicon-16x16.png">
|
||||||
|
<link rel="manifest" href="./favicons/site.webmanifest">
|
||||||
|
<link rel="mask-icon" href="./favicons/safari-pinned-tab.svg" color="#21bf73">
|
||||||
|
|
||||||
|
<title>COVID-19 – Generator of international travel certificate to mainland France</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header role="banner" class="wrapper">
|
||||||
|
<ul class="flex-justify">
|
||||||
|
<img class="logo" src="/MIN_Interieur_RVB.svg" alt="Ministère de l'intérieur. Liberté, égalité, fraternité.">
|
||||||
|
<fieldset class="form-language">
|
||||||
|
<legend class="legend-language">Select your language</legend>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-language" id="radio-language-en" value="en" checked>
|
||||||
|
<label class="form-check-label" for="radio-language-en">ENGLISH</label>
|
||||||
|
<img class="flags" src="flag EN.svg">
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-language" id="radio-language-fr" value="fr">
|
||||||
|
<label class="form-check-label" for="radio-language-fr">FRANCAIS</label>
|
||||||
|
<img class="flags" src="Flag_of_France.svg">
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</ul>
|
||||||
|
<div>
|
||||||
|
<h1 class="flex flex-wrap">
|
||||||
|
<span class="covid-title">
|
||||||
|
COVID-19
|
||||||
|
</span>
|
||||||
|
<span class="covid-subtitle">
|
||||||
|
Generator of international travel certificate to mainland France
|
||||||
|
</span>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<p class="text-alert">
|
||||||
|
Filled in data is exclusively stored on your mobile phone or computer.
|
||||||
|
No information is collected by the Ministry of the Interior.
|
||||||
|
The generated pdf certificate has a QR Code.
|
||||||
|
This visual barcode makes it possible to read the information on your certificate at the time it was entered.
|
||||||
|
It is readable with all generic QR code readers.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This certificate must be presented to transportation companies, before boarding, by passengers travelling to
|
||||||
|
mainland France. It must also be presented to border control authorities, for any type of border:
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>European external borders of France (air, maritime, land including railway connections).</li>
|
||||||
|
<li>European internal borders of France.</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<main role="main">
|
||||||
|
<p class="alert alert-danger d-none" role="alert" id="alert-facebook"></p>
|
||||||
|
|
||||||
|
<div class="wrapper">
|
||||||
|
|
||||||
|
<form id="form-profile" accept-charset="UTF-8">
|
||||||
|
<h2 class="titre-2">Fill online your digital certificate :</h2>
|
||||||
|
<p class="text-alert">All fields are mandatory.</p>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="field-firstname" id="field-firstname-label">First name</label>
|
||||||
|
<div class="input-group align-items-center">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="field-firstname"
|
||||||
|
name="firstname"
|
||||||
|
autocomplete="given-name"
|
||||||
|
placeholder="Jean"
|
||||||
|
required
|
||||||
|
aria-invalid="true"
|
||||||
|
>
|
||||||
|
<span class="validity" aria-hidden="true"></span>
|
||||||
|
</div>
|
||||||
|
<p class="exemple"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="field-lastname" id="field-lastname-label">Surname</label>
|
||||||
|
<div class="input-group align-items-center">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="field-lastname"
|
||||||
|
name="lastname"
|
||||||
|
autocomplete="family-name"
|
||||||
|
placeholder="Dupont"
|
||||||
|
aria-invalid="true"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<span class="validity" aria-hidden="true"></span>
|
||||||
|
</div>
|
||||||
|
<p class="exemple"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="field-birthday" id="field-birthday-label">Date of birth (dd/mm/yyyy)</label>
|
||||||
|
<div class="input-group align-items-center">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
pattern="^([0][1-9]|[1-2][0-9]|30|31)\/([0][1-9]|10|11|12)\/(19[0-9][0-9]|20[0-1][0-9]|2020)"
|
||||||
|
inputmode="numeric"
|
||||||
|
class="form-control"
|
||||||
|
id="field-birthday"
|
||||||
|
name="birthday"
|
||||||
|
aria-invalid="true"
|
||||||
|
autocomplete="bday"
|
||||||
|
placeholder="01/01/1970"
|
||||||
|
maxlength="10"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<span class="validity" aria-hidden="true"></span>
|
||||||
|
</div>
|
||||||
|
<p class="exemple"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="field-nationality" id="field-nationality-label">Nationality</label>
|
||||||
|
<div class="input-group align-items-center">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="field-nationality"
|
||||||
|
name="nationality"
|
||||||
|
autocomplete="country-name"
|
||||||
|
aria-invalid="true"
|
||||||
|
placeholder="Belgian"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<span class="validity" aria-hidden="true"></span>
|
||||||
|
</div>
|
||||||
|
<p class="exemple"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="field-address" id="field-address-label">Address</label>
|
||||||
|
<div class="input-group align-items-center">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="field-address"
|
||||||
|
name="address"
|
||||||
|
aria-invalid="true"
|
||||||
|
autocomplete="address-line1"
|
||||||
|
placeholder="999 avenue de Belgique"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<span class="validity" aria-hidden="true"></span>
|
||||||
|
</div>
|
||||||
|
<p class="exemple"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="field-town" id="field-town-label">City</label>
|
||||||
|
<div class="input-group align-items-center">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="field-town"
|
||||||
|
name="town"
|
||||||
|
autocomplete="address-level1"
|
||||||
|
aria-invalid="true"
|
||||||
|
placeholder="Brussels"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<span class="validity" aria-hidden="true"></span>
|
||||||
|
</div>
|
||||||
|
<p class="exemple"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="field-zipcode" id="field-zipcode-label" >Zip code</label>
|
||||||
|
<div class="input-group align-items-center">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="field-zipcode"
|
||||||
|
name="zipcode"
|
||||||
|
aria-invalid="true"
|
||||||
|
autocomplete="postal-code"
|
||||||
|
placeholder="1000"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<span class="validity" aria-hidden="true"></span>
|
||||||
|
</div>
|
||||||
|
<p class="exemple"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="field-country" id="field-country-label">Country</label>
|
||||||
|
<div class="input-group align-items-center">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="field-country"
|
||||||
|
name="country"
|
||||||
|
autocomplete="country-name"
|
||||||
|
aria-invalid="true"
|
||||||
|
placeholder="Belgium"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<span class="validity" aria-hidden="true"></span>
|
||||||
|
</div>
|
||||||
|
<p class="exemple"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<fieldset class="control">
|
||||||
|
<legend class="titre-3">You are : </legend>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-type-nationality" id="radio-tiers" value="tiers">
|
||||||
|
<label class="form-nationality-label" for="radio-tiers">Third country nationals.</label>
|
||||||
|
|
||||||
|
<fieldset class='conditional'>
|
||||||
|
<legend class="titre-4">Choose the reason :</legend>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-residence-tiers" value="residence">
|
||||||
|
<label class="form-check-label" for="radio-residence-tiers">Individuals having their primary residence in France or in the European Union or assimilated countries<a href="#footnote1">[1]</a>, who are holders of a French or European residence permit or valid long-stay visa, accompanied by their spouse and
|
||||||
|
children.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-transit-tiers" value="transit">
|
||||||
|
<label class="form-check-label" for="radio-transit-tiers">Individuals in transit to reach their country of origin who are holders of a travel document to their country of origin and remaining in the international area with no intention to enter the national territory.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-prof._sante-tiers" value="prof._sante">
|
||||||
|
<label class="form-check-label" for="radio-prof._sante-tiers">Healthcare workers supporting the fight against Covid-19.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-marchandises-tiers" value="marchandises">
|
||||||
|
<label class="form-check-label" for="radio-marchandises-tiers">Goods carriers, including seamen.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-equipage-tiers" value="equipage">
|
||||||
|
<label class="form-check-label" for="radio-equipage-tiers">Flight and cargo crews, or travelling as a passenger to their departure base.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-diplomatique-tiers" value="diplomatique">
|
||||||
|
<label class="form-check-label" for="radio-diplomatique-tiers">Diplomatic mission staff, or international organisations staff working in headquarters or offices located in France, who are holders of a special residence permit or a type D promae visa.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-frontalier-tiers" value="frontalier">
|
||||||
|
<label class="form-check-label" for="radio-frontalier-tiers">Cross-border workers at internal land borders.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-type-nationality" id="radio-eu" value="eu">
|
||||||
|
<label class="form-nationality-label" for="radio-eu">European Union or assimilated countries nationals<a href="#footnote2">[2]</a>.</label>
|
||||||
|
|
||||||
|
<fieldset class='conditional'>
|
||||||
|
<legend class="titre-4">Choose the reason :</legend>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-residence-eu" value="residence">
|
||||||
|
<label class="form-check-label" for="radio-residence-eu">Individuals having their primary residence in France, accompanied by their spouse and children.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-transit-eu" value="transit">
|
||||||
|
<label class="form-check-label" for="radio-transit-eu">Individuals transiting through France to reach their residence, accompanied by their spouse and children.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-prof._sante-eu" value="prof._sante">
|
||||||
|
<label class="form-check-label" for="radio-prof._sante-eu">Healthcare workers supporting the fight against Covid-19.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-marchandises-eu" value="marchandises">
|
||||||
|
<label class="form-check-label" for="radio-marchandises-eu">Goods carriers, including seamen.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-equipage-eu" value="equipage">
|
||||||
|
<label class="form-check-label" for="radio-equipage-eu">Flight and cargo crews, or travelling as a passenger to their departure base.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-diplomatique-eu" value="diplomatique">
|
||||||
|
<label class="form-check-label" for="radio-diplomatique-eu">Diplomatic mission staff, or international organisations staff working in headquarters or offices located in France,
|
||||||
|
who are hold ers of a special residence permit or a type D promae visa.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-frontalier" value="frontalier">
|
||||||
|
<label class="form-check-label" for="radio-frontalier">Cross-border workers at internal land borders.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-type-nationality" id="radio-fr" value="fr">
|
||||||
|
<label class="form-nationality-label" for="radio-fr">French nationals, accompanied by their spouse and children.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<p class="text-center mt-5">
|
||||||
|
<button type="button" id="generate-btn" class="btn btn-primary btn-attestation"><span ><i class="fa fa-file-pdf inline-block mr-1"></i> Generate my certificate</span></button>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="bg-primary d-none" id="snackbar">
|
||||||
|
The certificate is downloaded on your terminal.
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="">
|
||||||
|
<p id="footnotes">
|
||||||
|
<span id="footnote1">[1] United Kingdom, Iceland, Liechtenstein, Norway, Andorra, Monaco, Switzerland, San Marino, Holy See.</span><br>
|
||||||
|
<span id="footnote2">[2] European Union, United Kingdom, Iceland, Liechtenstein, Norway, Andorra, Monaco, Switzerland, San Marino and Holy See nationals (2004/38/CE directive).</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="github">
|
||||||
|
The source code of this service is available for consultation on <a href="https://github.com/LAB-MI/deplacement-covid-19" class="github-link">GitHub</a>.
|
||||||
|
</p>
|
||||||
|
<p class="label-mi">
|
||||||
|
Ministry of the Interior - DNUM - SDIT
|
||||||
|
</p>
|
||||||
|
<img class="center" src="/logo_dnum.svg" alt="logo dnum">
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<footer role="contentinfo" class="main-footer">
|
||||||
|
<div class="footer-links">
|
||||||
|
<a href="./confidentialite.html" title="Confidentialité - nouvelle page" target="_blank" class="footer-line footer-link">Privacy policy</a>
|
||||||
|
<a href="https://www.interieur.gouv.fr/Infos-du-site/Mentions-legales" title="Mentions légales - nouvelle page" target="_blank" class="footer-line footer-link">Legal notices</a>
|
||||||
|
<a href="https://www.gouvernement.fr/info-coronavirus" title="Informations du gouvernement sur le Covid-19 - nouvelle page" target="_blank" class="footer-line footer-link">Government information on COVID-19</a>
|
||||||
|
<div class="footer-line" >For more information, call <a class="num-08" href="tel:0800130000">0 800 130 000</a></div>
|
||||||
|
<p class="footer-line" id="version"></p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<div class="alert alert-info d-none" id="update-alert">
|
||||||
|
A new version is available. Click on the button to get it.
|
||||||
|
<p class="text-right">
|
||||||
|
<button id="reload-btn" class="btn btn-info">Update</button>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="./certificate-en.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
259
src/index.html
|
@ -6,19 +6,19 @@
|
||||||
<meta name="msapplication-TileColor" content="#603cba">
|
<meta name="msapplication-TileColor" content="#603cba">
|
||||||
<meta name="msapplication-config" content="./favicons/browserconfig.xml">
|
<meta name="msapplication-config" content="./favicons/browserconfig.xml">
|
||||||
<meta name="theme-color" content="#ffffff">
|
<meta name="theme-color" content="#ffffff">
|
||||||
<meta name="title" content="Générateur d'attestation de déplacement dérogatoire - COVID-19">
|
<meta name="title" content="Générateur d'attestation de déplacement international dérogatoire vers la France métropolitaine - COVID-19">
|
||||||
<meta name="description" content="Ce service officiel génère une version numérique de l’attestation déplacement covid-19 à présenter aux forces de sécurité lors d’un contrôle.">
|
<meta name="description" content="Ce service officiel génère une version numérique de l’attestation déplacement covid-19 à présenter aux forces de sécurité lors d’un contrôle.">
|
||||||
<meta name="keywords" content="covid19, covid-19, attestation, déplacement, officielle, gouvernement">
|
<meta name="keywords" content="covid19, covid-19, attestation, déplacement, international, officielle, gouvernement">
|
||||||
<meta name="robots" content="index, follow">
|
<meta name="robots" content="index, follow">
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
<meta name="language" content="French">
|
<meta name="language" content="French">
|
||||||
<meta property="og:title" content="Générateur d'attestation de déplacement dérogatoire - COVID-19" />
|
<meta property="og:title" content="Générateur d'attestation de déplacement international dérogatoire vers la France métropolitaine - COVID-19" />
|
||||||
<meta property="og:locale" content="fr_FR" />
|
<meta property="og:locale" content="fr_FR" />
|
||||||
<meta property="og:description" content="Ce service officiel génère une version numérique de l’attestation déplacement covid-19 à présenter aux forces de sécurité lors d’un contrôle." />
|
<meta property="og:description" content="Ce service officiel génère une version numérique de l’attestation déplacement covid-19 à présenter aux forces de sécurité lors d’un contrôle." />
|
||||||
<link rel="canonical" href="https://media.interieur.gouv.fr/deplacement-covid-19/" />
|
<link rel="canonical" href="https://media.interieur.gouv.fr/deplacement-vers-france-covid-19/" />
|
||||||
<meta property="og:url" content="https://media.interieur.gouv.fr/deplacement-covid-19/" />
|
<meta property="og:url" content="https://media.interieur.gouv.fr/deplacement-vers-france-covid-19/" />
|
||||||
<meta property="og:site_name" content="Générateur d'attestation de déplacement dérogatoire - COVID-19" />
|
<meta property="og:site_name" content="Générateur d'attestation de déplacement international dérogatoire vers la France métropolitaine - COVID-19" />
|
||||||
<script type='application/ld+json'>{"@context":"http://www.schema.org","@type":"GovernmentOrganization","name":"Générateur d'attestation de déplacement dérogatoire - COVID-19","description":"Ce service officiel génère une version numérique de l’attestation déplacement covid-19 à présenter aux forces de sécurité lors d’un contrôle.","address":{"@type":"PostalAddress","addressCountry":"France"}}</script>
|
<script type='application/ld+json'>{"@context":"http://www.schema.org","@type":"GovernmentOrganization","name":"Générateur d'attestation de déplacement international dérogatoire vers la France métropolitaine - COVID-19","description":"Ce service officiel génère une version numérique de l’attestation déplacement covid-19 à présenter aux forces de sécurité lors d’un contrôle.","address":{"@type":"PostalAddress","addressCountry":"France"}}</script>
|
||||||
|
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="./favicons/apple-touch-icon.png">
|
<link rel="apple-touch-icon" sizes="180x180" href="./favicons/apple-touch-icon.png">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="./favicons/favicon-32x32.png">
|
<link rel="icon" type="image/png" sizes="32x32" href="./favicons/favicon-32x32.png">
|
||||||
|
@ -26,25 +26,50 @@
|
||||||
<link rel="manifest" href="./favicons/site.webmanifest">
|
<link rel="manifest" href="./favicons/site.webmanifest">
|
||||||
<link rel="mask-icon" href="./favicons/safari-pinned-tab.svg" color="#21bf73">
|
<link rel="mask-icon" href="./favicons/safari-pinned-tab.svg" color="#21bf73">
|
||||||
|
|
||||||
<title>COVID-19 – Générateur d'attestation de déplacement dérogatoire</title>
|
<title>COVID-19 – Générateur d'attestation de déplacement international dérogatoire vers la France métropolitaine</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header role="banner" class="wrapper">
|
<header role="banner" class="wrapper">
|
||||||
<img class="logo" src="/MIN_Interieur_RVB.svg" alt="Ministère de l'intérieur. Liberté, égalité, fraternité.">
|
<ul class="flex-justify">
|
||||||
|
<img class="logo" src="/MIN_Interieur_RVB.svg" alt="Ministère de l'intérieur. Liberté, égalité, fraternité.">
|
||||||
|
<fieldset class="form-language">
|
||||||
|
<legend class="legend-language">Choisissez votre langue</legend>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-language" id="radio-language-en" value="en">
|
||||||
|
<label class="form-check-label" for="radio-language-en">ENGLISH</label>
|
||||||
|
<img class="flags" src="flag EN.svg">
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-language" id="radio-language-fr" value="fr" checked>
|
||||||
|
<label class="form-check-label" for="radio-language-fr">FRANCAIS</label>
|
||||||
|
<img class="flags" src="Flag_of_France.svg">
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</ul>
|
||||||
<div>
|
<div>
|
||||||
<h1 class="flex flex-wrap">
|
<h1 class="flex flex-wrap">
|
||||||
<span class="covid-title">
|
<span class="covid-title">
|
||||||
COVID-19
|
COVID-19
|
||||||
</span>
|
</span>
|
||||||
<span class="covid-subtitle">
|
<span class="covid-subtitle">
|
||||||
Générateur d'attestation de déplacement dérogatoire
|
Générateur d'attestation de déplacement international dérogatoire vers la France métropolitaine
|
||||||
</span>
|
</span>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<p class="text-alert">
|
<p class="text-alert">
|
||||||
Les données saisies sont stockées exclusivement sur votre téléphone ou votre ordinateur. Aucune information n'est collectée par le Ministère de l'Intérieur.
|
Les données saisies sont stockées exclusivement sur votre téléphone ou votre ordinateur. Aucune information n'est collectée par le Ministère de l'Intérieur.
|
||||||
L'attestation pdf générée contient un QR Code. Ce code-barres graphique permet de lire les informations portées dans votre attestation au moment de leur saisie.
|
L'attestation pdf générée contient un QR Code. Ce code-barres graphique permet de lire les informations portées dans votre attestation au moment de leur saisie.
|
||||||
Il peut être déchiffré à l'aide de tout type de lecteur de QR code générique.
|
Il peut être déchiffré à l'aide de tout type de lecteur de QR code générique.
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
Cette attestation est à présenter aux compagnies de transport, avant l’utilisation du titre de transport, par les
|
||||||
|
passagers qui souhaitent voyager à destination de la France métropolitaine. Elle sera aussi présentée aux autorités en
|
||||||
|
charge du contrôle frontières, pour tout type de frontière :
|
||||||
|
<ul>
|
||||||
|
<li>Aux frontières extérieures de la France (liaisons aériennes, maritimes, terrestres, dont les liaisons ferroviaires).</li>
|
||||||
|
<li>Aux frontières intérieures de la France.</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<main role="main">
|
<main role="main">
|
||||||
|
@ -55,7 +80,7 @@
|
||||||
<form id="form-profile" accept-charset="UTF-8">
|
<form id="form-profile" accept-charset="UTF-8">
|
||||||
<h2 class="titre-2">Remplissez en ligne votre attestation numérique :</h2>
|
<h2 class="titre-2">Remplissez en ligne votre attestation numérique :</h2>
|
||||||
<p class="text-alert">Tous les champs sont obligatoires.</p>
|
<p class="text-alert">Tous les champs sont obligatoires.</p>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="field-firstname" id="field-firstname-label">Prénom</label>
|
<label for="field-firstname" id="field-firstname-label">Prénom</label>
|
||||||
<div class="input-group align-items-center">
|
<div class="input-group align-items-center">
|
||||||
|
@ -67,14 +92,13 @@
|
||||||
autocomplete="given-name"
|
autocomplete="given-name"
|
||||||
placeholder="Jean"
|
placeholder="Jean"
|
||||||
required
|
required
|
||||||
autofocus
|
|
||||||
aria-invalid="true"
|
aria-invalid="true"
|
||||||
>
|
>
|
||||||
<span class="validity" aria-hidden="true"></span>
|
<span class="validity" aria-hidden="true"></span>
|
||||||
</div>
|
</div>
|
||||||
<p class="exemple"></p>
|
<p class="exemple"></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="field-lastname" id="field-lastname-label">Nom</label>
|
<label for="field-lastname" id="field-lastname-label">Nom</label>
|
||||||
<div class="input-group align-items-center">
|
<div class="input-group align-items-center">
|
||||||
|
@ -87,13 +111,12 @@
|
||||||
placeholder="Dupont"
|
placeholder="Dupont"
|
||||||
aria-invalid="true"
|
aria-invalid="true"
|
||||||
required
|
required
|
||||||
autofocus
|
|
||||||
>
|
>
|
||||||
<span class="validity" aria-hidden="true"></span>
|
<span class="validity" aria-hidden="true"></span>
|
||||||
</div>
|
</div>
|
||||||
<p class="exemple"></p>
|
<p class="exemple"></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="field-birthday" id="field-birthday-label">Date de naissance (au format jj/mm/aaaa)</label>
|
<label for="field-birthday" id="field-birthday-label">Date de naissance (au format jj/mm/aaaa)</label>
|
||||||
<div class="input-group align-items-center">
|
<div class="input-group align-items-center">
|
||||||
|
@ -114,24 +137,25 @@
|
||||||
</div>
|
</div>
|
||||||
<p class="exemple"></p>
|
<p class="exemple"></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="field-lieunaissance" id="field-lieunaissance-label">Lieu de naissance</label>
|
<label for="field-nationality" id="field-nationality-label">Nationalité</label>
|
||||||
<div class="input-group align-items-center">
|
<div class="input-group align-items-center">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
id="field-lieunaissance"
|
id="field-nationality"
|
||||||
name="lieunaissance"
|
name="nationality"
|
||||||
|
autocomplete="country-name"
|
||||||
aria-invalid="true"
|
aria-invalid="true"
|
||||||
placeholder="Lyon"
|
placeholder="Belge"
|
||||||
required
|
required
|
||||||
>
|
>
|
||||||
<span class="validity" aria-hidden="true"></span>
|
<span class="validity" aria-hidden="true"></span>
|
||||||
</div>
|
</div>
|
||||||
<p class="exemple"></p>
|
<p class="exemple"></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="field-address" id="field-address-label">Adresse</label>
|
<label for="field-address" id="field-address-label">Adresse</label>
|
||||||
<div class="input-group align-items-center">
|
<div class="input-group align-items-center">
|
||||||
|
@ -141,15 +165,15 @@
|
||||||
id="field-address"
|
id="field-address"
|
||||||
name="address"
|
name="address"
|
||||||
aria-invalid="true"
|
aria-invalid="true"
|
||||||
autocomplete="address-line1"
|
autocomplete="address-line1"
|
||||||
placeholder="999 avenue de france"
|
placeholder="999 avenue de Belgique"
|
||||||
required
|
required
|
||||||
>
|
>
|
||||||
<span class="validity" aria-hidden="true"></span>
|
<span class="validity" aria-hidden="true"></span>
|
||||||
</div>
|
</div>
|
||||||
<p class="exemple"></p>
|
<p class="exemple"></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="field-town" id="field-town-label">Ville</label>
|
<label for="field-town" id="field-town-label">Ville</label>
|
||||||
<div class="input-group align-items-center">
|
<div class="input-group align-items-center">
|
||||||
|
@ -160,91 +184,151 @@
|
||||||
name="town"
|
name="town"
|
||||||
autocomplete="address-level1"
|
autocomplete="address-level1"
|
||||||
aria-invalid="true"
|
aria-invalid="true"
|
||||||
placeholder="Paris"
|
placeholder="Bruxelles"
|
||||||
required
|
required
|
||||||
>
|
>
|
||||||
<span class="validity" aria-hidden="true"></span>
|
<span class="validity" aria-hidden="true"></span>
|
||||||
</div>
|
</div>
|
||||||
<p class="exemple"></p>
|
<p class="exemple"></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="field-zipcode" id="field-zipcode-label" >Code Postal</label>
|
<label for="field-zipcode" id="field-zipcode-label" >Code Postal</label>
|
||||||
<div class="input-group align-items-center">
|
<div class="input-group align-items-center">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
inputmode="numeric"
|
|
||||||
pattern="[0-9]{5}"
|
|
||||||
min="00000"
|
|
||||||
max="99999"
|
|
||||||
class="form-control"
|
class="form-control"
|
||||||
id="field-zipcode"
|
id="field-zipcode"
|
||||||
name="zipcode"
|
name="zipcode"
|
||||||
aria-invalid="true"
|
aria-invalid="true"
|
||||||
autocomplete="postal-code"
|
autocomplete="postal-code"
|
||||||
minlength="4"
|
placeholder="1000"
|
||||||
maxlength="5"
|
|
||||||
placeholder="75001"
|
|
||||||
required
|
required
|
||||||
>
|
>
|
||||||
<span class="validity" aria-hidden="true"></span>
|
<span class="validity" aria-hidden="true"></span>
|
||||||
</div>
|
</div>
|
||||||
<p class="exemple"></p>
|
<p class="exemple"></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<fieldset>
|
<div class="form-group">
|
||||||
<legend class="title-3">Choisissez le ou les motif(s) de sortie</legend>
|
<label for="field-country" id="field-country-label">Pays</label>
|
||||||
<div class="form-check">
|
<div class="input-group align-items-center">
|
||||||
<input class="form-check-input" type="checkbox" name="field-reason" id="checkbox-travail" value="travail">
|
<input
|
||||||
<label class="form-check-label" for="checkbox-travail">Déplacements entre le domicile et le lieu d’exercice de l’activité professionnelle, lorsqu'ils sont indispensables à l'exercice d’activités ne pouvant être organisées sous forme de télétravail ou déplacements professionnels ne pouvant être différés.</label>
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="field-country"
|
||||||
|
name="country"
|
||||||
|
autocomplete="country-name"
|
||||||
|
aria-invalid="true"
|
||||||
|
placeholder="Belgique"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<span class="validity" aria-hidden="true"></span>
|
||||||
</div>
|
</div>
|
||||||
|
<p class="exemple"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<fieldset class="control">
|
||||||
|
<legend class="titre-3">Vous êtes : </legend>
|
||||||
|
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input class="form-check-input" type="checkbox" name="field-reason" id="checkbox-courses" value="courses">
|
<input class="form-check-input" type="radio" name="field-type-nationality" id="radio-tiers" value="tiers">
|
||||||
<label class="form-check-label" for="checkbox-courses">Déplacements pour effectuer des achats de fournitures nécessaires à l’activité professionnelle et des achats de première nécessité dans des établissements dont les activités demeurent autorisées (<a href="https://www.service-public.fr/particuliers/actualites/A13921" class="stores-link" title="Liste des commerces et établissements qui restent ouverts - nouvelle page" target="_blank">liste des commerces et établissements qui restent ouverts</a>).</label>
|
<label class="form-nationality-label" for="radio-tiers">Ressortissant de pays tiers.</label>
|
||||||
|
|
||||||
|
<fieldset class='conditional'>
|
||||||
|
<legend class="titre-4">Choisissez le motif :</legend>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-residence-tiers" value="residence">
|
||||||
|
<label class="form-check-label" for="radio-residence-tiers">Personnes ayant leur résidence principale en France ou dans l’Union européenne et pays assimilés<a href="#footnote1">[1]</a>, titulaires d’un titre de séjour ou d’un visa de long séjour français ou européen en cours de validité, ainsi que leurs conjoints et leurs enfants.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-transit-tiers" value="transit">
|
||||||
|
<label class="form-check-label" for="radio-transit-tiers">Personnes en transit pour rejoindre leur pays d’origine, présentant le titre de voyage vers leur pays d’origine et
|
||||||
|
restant en zone internationale sans entrer sur le territoire national.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-prof._sante-tiers" value="prof._sante">
|
||||||
|
<label class="form-check-label" for="radio-prof._sante-tiers">Professionnels de santé aux fins de lutter contre le Covid-19.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-marchandises-tiers" value="marchandises">
|
||||||
|
<label class="form-check-label" for="radio-marchandises-tiers">Transporteurs de marchandises, dont les marins.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-equipage-tiers" value="equipage">
|
||||||
|
<label class="form-check-label" for="radio-equipage-tiers">Équipages et personnels exploitant des vols passagers et cargo, ou voyageant comme passagers pour se positionner sur leur base de départ.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-diplomatique-tiers" value="diplomatique">
|
||||||
|
<label class="form-check-label" for="radio-diplomatique-tiers">Personnels des missions diplomatiques et consulaires, ainsi que des organisations internationales ayant leur siège
|
||||||
|
ou un bureau en France, titulaires d’un titre de séjour spécial ou d’un visa D promae.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-frontalier-tiers" value="frontalier">
|
||||||
|
<label class="form-check-label" for="radio-frontalier-tiers">Travailleurs frontaliers aux frontières intérieures terrestres.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input class="form-check-input" type="checkbox" name="field-reason" id="checkbox-sante" value="sante">
|
<input class="form-check-input" type="radio" name="field-type-nationality" id="radio-eu" value="eu">
|
||||||
<label class="form-check-label" for="checkbox-sante">Consultations et soins ne pouvant être assurés à distance et ne pouvant être différés ; consultations et soins des patients atteints d'une affection de longue durée.</label>
|
<label class="form-nationality-label" for="radio-eu">Ressortissant de l’Union européenne et assimilés<a href="#footnote2">[2]</a>.</label>
|
||||||
|
|
||||||
|
<fieldset class='conditional'>
|
||||||
|
<legend class="titre-4">Choisissez le motif</legend>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-residence-eu" value="residence">
|
||||||
|
<label class="form-check-label" for="radio-residence-eu">Personnes ayant leur résidence principale en France, ainsi que leurs conjoints et leurs enfants.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-transit-eu" value="transit">
|
||||||
|
<label class="form-check-label" for="radio-transit-eu">Personnes transitant par la France pour rejoindre leur résidence, ainsi que leurs conjoints et leurs enfants.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-prof._sante-eu" value="prof._sante">
|
||||||
|
<label class="form-check-label" for="radio-prof._sante-eu">Professionnels de santé aux fins de lutter contre le Covid-19.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-marchandises-eu" value="marchandises">
|
||||||
|
<label class="form-check-label" for="radio-marchandises-eu">Transporteurs de marchandises, dont les marins.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-equipage-eu" value="equipage">
|
||||||
|
<label class="form-check-label" for="radio-equipage-eu">Équipages et personnels exploitant des vols passagers et cargo, ou voyageant comme passagers pour se positionner sur leur base de départ.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-diplomatique-eu" value="diplomatique">
|
||||||
|
<label class="form-check-label" for="radio-diplomatique-eu">Personnels des missions diplomatiques et consulaires, ainsi que des organisations internationales ayant leur siège
|
||||||
|
ou un bureau en France, titulaires d’un titre de séjour spécial ou d’un visa D promae.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="field-reason" id="radio-frontalier" value="frontalier">
|
||||||
|
<label class="form-check-label" for="radio-frontalier">Travailleurs frontaliers aux frontières intérieures terrestres.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input class="form-check-input" type="checkbox" name="field-reason" id="checkbox-famille" value="famille">
|
<input class="form-check-input" type="radio" name="field-type-nationality" id="radio-fr" value="fr">
|
||||||
<label class="form-check-label" for="checkbox-famille">Déplacements pour motif familial impérieux, pour l’assistance aux personnes vulnérables ou la garde d’enfants.</label>
|
<label class="form-nationality-label" for="radio-fr">Ressortissant de nationalité française, ainsi que votre conjoint et enfants.</label>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-check">
|
|
||||||
<input class="form-check-input" type="checkbox" name="field-reason" id="checkbox-sport" value="sport">
|
|
||||||
<label class="form-check-label" for="checkbox-sport">Déplacements brefs, dans la limite d'une heure quotidienne et dans un rayon maximal d'un kilomètre 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, soit aux besoins des animaux de compagnie.</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check">
|
|
||||||
<input class="form-check-input" type="checkbox" name="field-reason" id="checkbox-judiciaire" value="judiciaire">
|
|
||||||
<label class="form-check-label" for="checkbox-judiciaire">Convocation judiciaire ou administrative.</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check">
|
|
||||||
<input class="form-check-input" type="checkbox" name="field-reason" id="checkbox-missions" value="missions">
|
|
||||||
<label class="form-check-label" for="checkbox-missions">Participation à des missions d’intérêt général sur demande de l’autorité administrative.</label>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="field-datesortie">Date de sortie</label>
|
|
||||||
<div class="input-group align-items-center">
|
|
||||||
<input type="date" class="form-control" id="field-datesortie" name="datesortie" autocomplete="off" placeholder="JJ/MM/YYYY" aria-invalid="true" required>
|
|
||||||
<span class="validity" aria-hidden="true"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="field-heuresortie">Heure de sortie</label>
|
|
||||||
<div class="input-group align-items-center">
|
|
||||||
<input type="time" class="form-control" id="field-heuresortie" name="heure" autocomplete="off" aria-invalid="true" required>
|
|
||||||
<span class="validity" aria-hidden="true"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<p class="text-center mt-5">
|
<p class="text-center mt-5">
|
||||||
<button type="button" id="generate-btn" class="btn btn-primary btn-attestation"><span ><i class="fa fa-file-pdf inline-block mr-1"></i> Générer mon attestation</span></button>
|
<button type="button" id="generate-btn" class="btn btn-primary btn-attestation"><span ><i class="fa fa-file-pdf inline-block mr-1"></i> Générer mon attestation</span></button>
|
||||||
</p>
|
</p>
|
||||||
|
@ -253,14 +337,21 @@
|
||||||
L'attestation est téléchargée sur votre appareil.
|
L'attestation est téléchargée sur votre appareil.
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="">
|
<div class="">
|
||||||
|
<p id="footnotes">
|
||||||
|
<span id="footnote1">[1] Royaume-Uni, Islande, Liechtenstein, Norvège, Andorre, Monaco, Suisse, Saint-Marin, Saint Siège.</span><br>
|
||||||
|
<span id="footnote2">[2] Ressortissants de l’Union européenne et ressortissants britanniques, ainsi que les ressortissants islandais, liechtensteinois, norvégiens, andorrans, monégasques, suisses, saint-marinais, citoyens du Saint Siège (directive 2004/38/CE).</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
<p class="github">
|
<p class="github">
|
||||||
Le code source de ce service est consultable sur <a href="https://github.com/LAB-MI/deplacement-covid-19" class="github-link">Github</a>.
|
Le code source de ce service est consultable sur <a href="https://github.com/LAB-MI/deplacement-covid-19" class="github-link">Github</a>.
|
||||||
</p>
|
</p>
|
||||||
<p class="label-mi">
|
<p class="label-mi">
|
||||||
Ministère de l'Intérieur - DNUM - SDIT
|
Ministère de l'Intérieur - DNUM - SDIT
|
||||||
</p>
|
</p>
|
||||||
<img class="center" src="/logo_dnum.svg" alt="logo dnum">
|
<img class="center" src="/logo_dnum.svg" alt="logo dnum">
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
@ -268,11 +359,11 @@
|
||||||
<div class="footer-links">
|
<div class="footer-links">
|
||||||
<a href="./confidentialite.html" title="Confidentialité - nouvelle page" target="_blank" class="footer-line footer-link">Confidentialité</a>
|
<a href="./confidentialite.html" title="Confidentialité - nouvelle page" target="_blank" class="footer-line footer-link">Confidentialité</a>
|
||||||
<a href="https://www.interieur.gouv.fr/Infos-du-site/Mentions-legales" title="Mentions légales - nouvelle page" target="_blank" class="footer-line footer-link">Mentions légales</a>
|
<a href="https://www.interieur.gouv.fr/Infos-du-site/Mentions-legales" title="Mentions légales - nouvelle page" target="_blank" class="footer-line footer-link">Mentions légales</a>
|
||||||
<a href="https://www.gouvernement.fr/info-coronavirus" title="Information du gouvernement sur le Covid-19 - nouvelle page" target="_blank" class="footer-line footer-link">Informations du gouvernement sur le Covid-19</a>
|
<a href="https://www.gouvernement.fr/info-coronavirus" title="Information du gouvernement sur le Covid-19 - nouvelle page" target="_blank" class="footer-line footer-link">Informations du gouvernement sur le Covid-19</a>
|
||||||
<div class="footer-line" >Plus d’infos au <a class="num-08" href="tel:0800130000">0 800 130 000</a></div>
|
<div class="footer-line" >Plus d’infos au <a class="num-08" href="tel:0800130000">0 800 130 000</a></div>
|
||||||
<p class="footer-line" id="version"></p>
|
<p class="footer-line" id="version"></p>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<div class="alert alert-info d-none" id="update-alert">
|
<div class="alert alert-info d-none" id="update-alert">
|
||||||
Une nouvelle version est disponible. Cliquer sur le bouton pour l'obtenir.
|
Une nouvelle version est disponible. Cliquer sur le bouton pour l'obtenir.
|
||||||
|
|
64
src/main.css
|
@ -29,14 +29,14 @@ h1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Small devices (landscape phones, 576px and up) */
|
/* Small devices (landscape phones, 576px and up) */
|
||||||
@media (min-width: 576px) {
|
@media (min-width: 576px) {
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 2.5em;
|
font-size: 2.5em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Medium devices (tablets, 768px and up) */
|
/* Medium devices (tablets, 768px and up) */
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 3em;
|
font-size: 3em;
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,14 @@ svg {
|
||||||
height: 1em;
|
height: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ul.flex-justify {
|
||||||
|
display: -webkit-flex; /* Safari */
|
||||||
|
-webkit-align-items: center; /* Safari 7.0+ */
|
||||||
|
justify-content:space-between;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
h1.flex.flex-wrap {
|
h1.flex.flex-wrap {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
@ -83,6 +91,11 @@ a {
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#form-profile .form-nationality-label {
|
||||||
|
font-weight: 800;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
#form-generate .form-check {
|
#form-generate .form-check {
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
}
|
}
|
||||||
|
@ -155,6 +168,27 @@ input:valid+span:after {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fieldset .form-language {
|
||||||
|
display: flex;
|
||||||
|
align-items: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend-language {
|
||||||
|
text-align: left;
|
||||||
|
font-size: 1rem;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-language .form-check-label {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flags {
|
||||||
|
width: 20px;
|
||||||
|
height: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
.covid-title {
|
.covid-title {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -185,11 +219,10 @@ input:valid+span:after {
|
||||||
|
|
||||||
.text-alert{
|
.text-alert{
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
font-style: italic;
|
||||||
color: #000000;
|
color: #000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.btn-attestation {
|
.btn-attestation {
|
||||||
padding: 0.9em;
|
padding: 0.9em;
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
|
@ -308,13 +341,13 @@ input:valid+span:after {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
em {
|
em {
|
||||||
font-size: .8rem;
|
font-size: .8rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.titre-2 {
|
.titre-2 {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
|
@ -401,3 +434,22 @@ input:valid+span:after {
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.control:not(:checked) ~ .conditional,
|
||||||
|
#radio-fr:not(:checked) ~ .conditional,
|
||||||
|
#radio-eu:not(:checked) ~ .conditional,
|
||||||
|
#radio-tiers:not(:checked) ~ .conditional {
|
||||||
|
clip: rect(0 0 0 0);
|
||||||
|
margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
[id^="footnote"] {
|
||||||
|
margin: 30px auto;
|
||||||
|
max-width: 400px;
|
||||||
|
font-size: 0.8em;
|
||||||
|
color: #000000;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Sitemap: https://media.interieur.gouv.fr/deplacement-covid-19/sitemap.xml
|
Sitemap: https://media.interieur.gouv.fr/deplacement-vers-france-covid-19/sitemap.xml
|
||||||
|
|
|
@ -8,20 +8,20 @@
|
||||||
|
|
||||||
|
|
||||||
<url>
|
<url>
|
||||||
<loc>https://media.interieur.gouv.fr/deplacement-covid-19/</loc>
|
<loc>https://media.interieur.gouv.fr/deplacement-vers-france-covid-19/</loc>
|
||||||
<lastmod>2020-04-06T04:22:03+00:00</lastmod>
|
<lastmod>2020-04-06T04:22:03+00:00</lastmod>
|
||||||
<priority>1.00</priority>
|
<priority>1.00</priority>
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://media.interieur.gouv.fr/deplacement-covid-19/confidentialite.html</loc>
|
<loc>https://media.interieur.gouv.fr/deplacement-vers-france-covid-19/confidentialite.html</loc>
|
||||||
<lastmod>2020-04-06T04:22:03+00:00</lastmod>
|
<lastmod>2020-04-06T04:22:03+00:00</lastmod>
|
||||||
<priority>0.80</priority>
|
<priority>0.80</priority>
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://media.interieur.gouv.fr/deplacement-covid-19/index.html</loc>
|
<loc>https://media.interieur.gouv.fr/deplacement-vers-france-covid-19/index.html</loc>
|
||||||
<lastmod>2020-04-06T04:22:03+00:00</lastmod>
|
<lastmod>2020-04-06T04:22:03+00:00</lastmod>
|
||||||
<priority>0.64</priority>
|
<priority>0.64</priority>
|
||||||
</url>
|
</url>
|
||||||
|
|
||||||
|
|
||||||
</urlset>
|
</urlset>
|
||||||
|
|