mirror of
https://github.com/covidpass-org/covidpass.git
synced 2025-02-16 11:41:19 +01:00
commit
2b4b4423dd
@ -10,7 +10,7 @@ function Alert(props: AlertProps): JSX.Element {
|
||||
|
||||
return (
|
||||
<div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 mt-5 rounded relative" role="alert">
|
||||
<span className="block sm:inline" id="message">{props.errorMessage}</span>
|
||||
<span className="block sm:inline pr-6" id="message">{props.errorMessage}</span>
|
||||
<span className="absolute top-0 bottom-0 right-0 px-4 py-3" onClick={props.onClose}>
|
||||
<svg className="fill-current h-6 w-6 text-red-500" role="button" xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20">
|
||||
|
@ -29,6 +29,11 @@ function Form(): JSX.Element {
|
||||
|
||||
// Check if there is a translation and replace message accordingly
|
||||
const setErrorMessage = (message: string) => {
|
||||
if (message == undefined) {
|
||||
_setErrorMessage(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
const translation = t('errors:'.concat(message));
|
||||
_setErrorMessage(translation !== message ? translation : message);
|
||||
};
|
||||
@ -68,7 +73,20 @@ function Form(): JSX.Element {
|
||||
const codeReader = new BrowserQRCodeReader();
|
||||
|
||||
// Needs to be called before any camera can be accessed
|
||||
await BrowserQRCodeReader.listVideoInputDevices();
|
||||
let deviceList: MediaDeviceInfo[];
|
||||
|
||||
try {
|
||||
deviceList = await BrowserQRCodeReader.listVideoInputDevices();
|
||||
} catch (e) {
|
||||
setErrorMessage('noCameraAccess');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if camera device is present
|
||||
if (deviceList.length == 0) {
|
||||
setErrorMessage("noCameraFound");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get preview Element to show camera stream
|
||||
const previewElem: HTMLVideoElement = document.querySelector('#cameraPreview');
|
||||
@ -89,6 +107,9 @@ function Form(): JSX.Element {
|
||||
setGlobalControls(undefined);
|
||||
setIsCameraOpen(false);
|
||||
}
|
||||
if (error !== undefined) {
|
||||
setErrorMessage(error.message);
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
@ -101,6 +122,12 @@ function Form(): JSX.Element {
|
||||
event.preventDefault();
|
||||
setLoading(true);
|
||||
|
||||
if(navigator.userAgent.match('CriOS')) {
|
||||
setErrorMessage('safariSupportOnly');
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!file && !qrCode) {
|
||||
setErrorMessage('noFileOrQrCode')
|
||||
setLoading(false);
|
||||
@ -228,7 +255,7 @@ function Form(): JSX.Element {
|
||||
{t('index:addToWallet')}
|
||||
</button>
|
||||
<div id="spin" className={loading ? undefined : "hidden"}>
|
||||
<svg className="animate-spin h-5 w-5 ml-2" viewBox="0 0 24 24">
|
||||
<svg className="animate-spin h-5 w-5 ml-3" viewBox="0 0 24 24">
|
||||
<circle className="opacity-0" cx="12" cy="12" r="10" stroke="currentColor"
|
||||
strokeWidth="4"/>
|
||||
<path className="opacity-75" fill="currentColor"
|
||||
|
@ -14,4 +14,7 @@ couldNotFindQrCode: QR-Code konnte in der ausgewählten Datei nicht gefunden wer
|
||||
invalidQrCode: Ungültiger QR-Code
|
||||
certificateType: Kein gültiger Zertifikatstyp gefunden
|
||||
invalidTestResult: Ungültiges Testergebnis
|
||||
invalidTestType: Ungültiger Testtyp
|
||||
invalidTestType: Ungültiger Testtyp
|
||||
noCameraAccess: Kein Zugriff auf die Kamera möglich. Überprüfe die Berechtigungen unter Einstellungen > Safari > Kamera.
|
||||
noCameraFound: Keine Kamera gefunden.
|
||||
safariSupportOnly: Bitte verwende unter iOS den Safari Browser.
|
@ -14,4 +14,7 @@ couldNotFindQrCode: Could not find QR Code in provided file
|
||||
invalidQrCode: Invalid QR code
|
||||
certificateType: No valid certificate type found
|
||||
invalidTestResult: Invalid test result
|
||||
invalidTestType: Invalid test type
|
||||
invalidTestType: Invalid test type
|
||||
noCameraAccess: Could not access camera. Check permissions under Settings > Safari > Camera.
|
||||
noCameraFound: Could not find camera.
|
||||
safariSupportOnly: On iOS, please use the Safari Browser.
|
@ -14,4 +14,7 @@ couldNotFindQrCode: QR-koodia ei löytynyt annetusta tiedostosta
|
||||
invalidQrCode: Virheellinen QR-koodi
|
||||
certificateType: Kelvollista varmennetyyppiä ei löytynyt
|
||||
invalidTestResult: Virheellinen testitulos
|
||||
invalidTestType: Virheellinen testityyppi
|
||||
invalidTestType: Virheellinen testityyppi
|
||||
noCameraAccess: Kameraan ei päässyt käsiksi. Tarkista käyttöoikeudet kohdasta Asetukset > Safari > Kamera.
|
||||
noCameraFound: En löytänyt kameraa.
|
||||
safariSupportOnly: Käytä iOS:ssä Safari-selainta.
|
@ -14,4 +14,7 @@ couldNotFindQrCode: Impossible de trouver le QR Code dans le fichier fourni
|
||||
invalidQrCode: QR Code non valide
|
||||
certificateType: Aucun type de certificat valide n'a été trouvé
|
||||
invalidTestResult: Résultat du test non valide
|
||||
invalidTestType: Type de test non valide
|
||||
invalidTestType: Type de test non valide
|
||||
noCameraAccess: Impossible d'accéder à la caméra. Vérifiez les autorisations sous Paramètres > Safari > Appareil photo.
|
||||
noCameraFound: Impossible de trouver la caméra.
|
||||
safariSupportOnly: Sur iOS, veuillez utiliser le navigateur Safari.
|
@ -14,4 +14,7 @@ couldNotFindQrCode: Kon de QR-code niet vinden in het verstrekte bestand
|
||||
invalidQrCode: Ongeldige QR-code
|
||||
certificateType: Geen geldig certificaattype gevonden
|
||||
invalidTestResult: Ongeldig testresultaat
|
||||
invalidTestType: Ongeldig testtype
|
||||
invalidTestType: Ongeldig testtype
|
||||
noCameraAccess: Kon geen toegang krijgen tot de camera. Controleer de machtigingen onder Instellingen > Safari > Camera.
|
||||
noCameraFound: Ik kon de camera niet vinden.
|
||||
safariSupportOnly: Gebruik op iOS de Safari-browser.
|
115
src/payload.ts
115
src/payload.ts
@ -2,7 +2,7 @@ import {ValueSets} from "./value_sets";
|
||||
import {Constants} from "./constants";
|
||||
|
||||
enum CertificateType {
|
||||
Vaccination = 'Vaccination',
|
||||
Vaccine = 'Vaccine',
|
||||
Test = 'Test',
|
||||
Recovery = 'Recovery',
|
||||
}
|
||||
@ -63,25 +63,35 @@ export class Payload {
|
||||
throw new Error('certificateData');
|
||||
}
|
||||
|
||||
// Get name and date of birth information
|
||||
// Get name information
|
||||
const nameInformation = covidCertificate['nam'];
|
||||
const dateOfBirthInformation = covidCertificate['dob'];
|
||||
|
||||
if (nameInformation == undefined) {
|
||||
throw new Error('nameMissing');
|
||||
}
|
||||
if (dateOfBirthInformation == undefined) {
|
||||
throw new Error('dobMissing');
|
||||
}
|
||||
|
||||
const name = `${nameInformation['fn']}, ${nameInformation['gn']}`;
|
||||
const dateOfBirth = dateOfBirthInformation;
|
||||
const firstName = nameInformation['gn'];
|
||||
const lastName = nameInformation['fn'];
|
||||
|
||||
const transliteratedFirstName = nameInformation['gnt'].replaceAll('<', ' ');
|
||||
const transliteratedLastName = nameInformation['fnt'].replaceAll('<', ' ');
|
||||
|
||||
// Check if name contains non-latin characters
|
||||
const nameRegex = new RegExp('^[\\p{Script=Latin}\\p{P}\\p{M}\\p{Z}]+$', 'u');
|
||||
|
||||
let name: string;
|
||||
|
||||
if (nameRegex.test(firstName) && nameRegex.test(lastName)) {
|
||||
name = `${firstName} ${lastName}`;
|
||||
} else {
|
||||
name = `${transliteratedFirstName} ${transliteratedLastName}`;
|
||||
}
|
||||
|
||||
let properties: object;
|
||||
|
||||
// Set certificate type and properties
|
||||
if (covidCertificate['v'] !== undefined) {
|
||||
this.certificateType = CertificateType.Vaccination;
|
||||
this.certificateType = CertificateType.Vaccine;
|
||||
properties = covidCertificate['v'][0];
|
||||
}
|
||||
if (covidCertificate['t'] !== undefined) {
|
||||
@ -96,23 +106,16 @@ export class Payload {
|
||||
throw new Error('certificateType')
|
||||
}
|
||||
|
||||
// Get country code, identifier and issuer
|
||||
const countryCode = properties['co'];
|
||||
// Get identifier and issuer
|
||||
const uvci = properties['ci'];
|
||||
const certificateIssuer = properties['is'];
|
||||
|
||||
if (!(countryCode in valueSets.countryCodes)) {
|
||||
throw new Error('invalidCountryCode');
|
||||
}
|
||||
|
||||
const country = valueSets.countryCodes[countryCode].display;
|
||||
|
||||
const generic: PassDictionary = {
|
||||
headerFields: [
|
||||
{
|
||||
key: "type",
|
||||
label: "Certificate Type",
|
||||
value: this.certificateType
|
||||
label: "EU Digital COVID",
|
||||
value: this.certificateType + " Certificate"
|
||||
}
|
||||
],
|
||||
primaryFields: [
|
||||
@ -123,14 +126,7 @@ export class Payload {
|
||||
}
|
||||
],
|
||||
secondaryFields: [],
|
||||
auxiliaryFields: [
|
||||
{
|
||||
key: "dob",
|
||||
label: "Date of Birth",
|
||||
value: dateOfBirth,
|
||||
textAlignment: TextAlignment.right
|
||||
}
|
||||
],
|
||||
auxiliaryFields: [],
|
||||
backFields: [
|
||||
{
|
||||
key: "uvci",
|
||||
@ -141,11 +137,6 @@ export class Payload {
|
||||
key: "issuer",
|
||||
label: "Certificate Issuer",
|
||||
value: certificateIssuer
|
||||
},
|
||||
{
|
||||
key: "country",
|
||||
label: "Country",
|
||||
value: country
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -164,8 +155,17 @@ export class Payload {
|
||||
}
|
||||
|
||||
static fillPassData(type: CertificateType, data: PassDictionary, properties: Object, valueSets: ValueSets): PassDictionary {
|
||||
// Get country name
|
||||
const countryCode = properties['co'];
|
||||
|
||||
if (!(countryCode in valueSets.countryCodes)) {
|
||||
throw new Error('invalidCountryCode');
|
||||
}
|
||||
|
||||
const country = valueSets.countryCodes[countryCode].display;
|
||||
|
||||
switch (type) {
|
||||
case CertificateType.Vaccination:
|
||||
case CertificateType.Vaccine:
|
||||
const dose = `${properties['dn']}/${properties['sd']}`;
|
||||
const dateOfVaccination = properties['dt'];
|
||||
const medialProductKey = properties['mp'];
|
||||
@ -178,7 +178,7 @@ export class Payload {
|
||||
throw new Error('invalidManufacturer')
|
||||
}
|
||||
|
||||
const vaccineName = valueSets.medicalProducts[medialProductKey].display;
|
||||
const vaccineName = valueSets.medicalProducts[medialProductKey].display.replace(/\s*\([^)]*\)\s*/g, "");
|
||||
const manufacturer = valueSets.manufacturers[manufacturerKey].display;
|
||||
|
||||
data.secondaryFields.push(...[
|
||||
@ -194,11 +194,19 @@ export class Payload {
|
||||
textAlignment: TextAlignment.right
|
||||
}
|
||||
]);
|
||||
data.auxiliaryFields.splice(0, 0, {
|
||||
key: "vaccine",
|
||||
label: "Vaccine",
|
||||
value: vaccineName
|
||||
});
|
||||
data.auxiliaryFields.push(...[
|
||||
{
|
||||
key: "vaccine",
|
||||
label: "Vaccine",
|
||||
value: vaccineName
|
||||
},
|
||||
{
|
||||
key: "cov",
|
||||
label: "Country of Vaccination",
|
||||
value: country,
|
||||
textAlignment: TextAlignment.right
|
||||
}
|
||||
]);
|
||||
data.backFields.push(...[
|
||||
{
|
||||
key: "manufacturer",
|
||||
@ -234,7 +242,7 @@ export class Payload {
|
||||
data.secondaryFields.push(...[
|
||||
{
|
||||
key: "result",
|
||||
label: "Result",
|
||||
label: "Test Result",
|
||||
value: testResult
|
||||
},
|
||||
{
|
||||
@ -244,7 +252,6 @@ export class Payload {
|
||||
textAlignment: TextAlignment.right
|
||||
}
|
||||
]);
|
||||
data.auxiliaryFields.pop();
|
||||
data.auxiliaryFields.push(...[
|
||||
{
|
||||
key: "test",
|
||||
@ -258,6 +265,11 @@ export class Payload {
|
||||
textAlignment: TextAlignment.right
|
||||
},
|
||||
]);
|
||||
data.backFields.push({
|
||||
key: "cot",
|
||||
label: "Country of Test",
|
||||
value: country
|
||||
});
|
||||
if (testingCentre !== undefined)
|
||||
data.backFields.push({
|
||||
key: "centre",
|
||||
@ -276,29 +288,28 @@ export class Payload {
|
||||
const validUntil = properties['du'];
|
||||
|
||||
data.secondaryFields.push(...[
|
||||
{
|
||||
key: "result",
|
||||
label: "Test Result",
|
||||
value: "Detected"
|
||||
},
|
||||
{
|
||||
key: "from",
|
||||
label: "Valid From",
|
||||
value: validFrom,
|
||||
},
|
||||
{
|
||||
key: "dov",
|
||||
label: "Date of positive Test",
|
||||
value: firstPositiveTestDate,
|
||||
textAlignment: TextAlignment.right
|
||||
}
|
||||
]);
|
||||
data.auxiliaryFields.pop();
|
||||
data.auxiliaryFields.push(...[
|
||||
{
|
||||
key: "testdate",
|
||||
label: "Test Date",
|
||||
value: firstPositiveTestDate
|
||||
},
|
||||
{
|
||||
key: "until",
|
||||
label: "Valid Until",
|
||||
value: validUntil,
|
||||
},
|
||||
{
|
||||
key: "cov",
|
||||
label: "Country of Test",
|
||||
value: country,
|
||||
textAlignment: TextAlignment.right
|
||||
},
|
||||
]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user