mirror of
https://github.com/covidpass-org/covidpass.git
synced 2025-02-23 23:17:37 +01:00
Version 1.1
incorporated feedback from the team
This commit is contained in:
parent
3f3ed17d50
commit
b3e8f09ac5
1
.env.production
Normal file
1
.env.production
Normal file
@ -0,0 +1 @@
|
|||||||
|
API_BASE_URL=https://covidpassapinet-pnrnxf7lvq-pd.a.run.app
|
@ -65,6 +65,10 @@ function Form(): JSX.Element {
|
|||||||
inputFile.current.click();
|
inputFile.current.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function gotoOntarioHealth() {
|
||||||
|
window.location.href = 'https://covid19.ontariohealth.ca';
|
||||||
|
}
|
||||||
|
|
||||||
// Hide camera view
|
// Hide camera view
|
||||||
async function hideCameraView() {
|
async function hideCameraView() {
|
||||||
if (globalControls !== undefined) {
|
if (globalControls !== undefined) {
|
||||||
@ -125,6 +129,7 @@ function Form(): JSX.Element {
|
|||||||
|
|
||||||
// Add Pass to wallet
|
// Add Pass to wallet
|
||||||
async function addToWallet(event: FormEvent<HTMLFormElement>) {
|
async function addToWallet(event: FormEvent<HTMLFormElement>) {
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
@ -146,15 +151,14 @@ function Form(): JSX.Element {
|
|||||||
try {
|
try {
|
||||||
if (file) {
|
if (file) {
|
||||||
payloadBody = await getPayloadBodyFromFile(file, color);
|
payloadBody = await getPayloadBodyFromFile(file, color);
|
||||||
} else {
|
let pass = await PassData.generatePass(payloadBody);
|
||||||
payloadBody = await getPayloadBodyFromQR(qrCode, color);
|
|
||||||
|
const passBlob = new Blob([pass], {type: "application/vnd.apple.pkpass"});
|
||||||
|
saveAs(passBlob, 'covid.pkpass');
|
||||||
|
setLoading(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
let pass = await PassData.generatePass(payloadBody);
|
|
||||||
|
|
||||||
const passBlob = new Blob([pass], {type: "application/vnd.apple.pkpass"});
|
|
||||||
saveAs(passBlob, 'covid.pkpass');
|
|
||||||
setLoading(false);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setErrorMessage(e.message);
|
setErrorMessage(e.message);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
@ -164,7 +168,27 @@ function Form(): JSX.Element {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<form className="space-y-5" id="form" onSubmit={addToWallet}>
|
<form className="space-y-5" id="form" onSubmit={addToWallet}>
|
||||||
<Card step="1" heading={t('index:selectCertificate')} content={
|
<Card step="1" heading={t('index:downloadReceipt')} content={
|
||||||
|
<div className="space-y-5">
|
||||||
|
<p>
|
||||||
|
{t('index:visit')}
|
||||||
|
|
||||||
|
<Link href="https://covid19.ontariohealth.ca">
|
||||||
|
<a className="underline">
|
||||||
|
{t('index:ontarioHealth')}
|
||||||
|
</a>
|
||||||
|
</Link>
|
||||||
|
{t('index:downloadSignedPDF')}
|
||||||
|
</p>
|
||||||
|
<button id="ontariohealth" onClick={gotoOntarioHealth}
|
||||||
|
|
||||||
|
className="focus:outline-none bg-green-600 py-2 px-3 text-white font-semibold rounded-md disabled:bg-gray-400">
|
||||||
|
{t('index:gotoOntarioHealth')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}/>
|
||||||
|
|
||||||
|
<Card step="2" heading={t('index:selectCertificate')} content={
|
||||||
<div className="space-y-5">
|
<div className="space-y-5">
|
||||||
<p>{t('index:selectCertificateDescription')}</p>
|
<p>{t('index:selectCertificateDescription')}</p>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-5">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-5">
|
||||||
@ -182,8 +206,8 @@ function Form(): JSX.Element {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<video id="cameraPreview"
|
{/* <video id="cameraPreview"
|
||||||
className={`${isCameraOpen ? undefined : "hidden"} rounded-md w-full`}/>
|
className={`${isCameraOpen ? undefined : "hidden"} rounded-md w-full`}/> */}
|
||||||
<input type='file'
|
<input type='file'
|
||||||
id='file'
|
id='file'
|
||||||
accept="application/pdf,image/png"
|
accept="application/pdf,image/png"
|
||||||
@ -209,15 +233,8 @@ function Form(): JSX.Element {
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
}/>
|
}/>
|
||||||
{/* <Card step="2" heading={t('index:pickColor')} content={
|
|
||||||
<div className="space-y-5">
|
<Card step="3" heading={t('index:addToWallet')} content={
|
||||||
<p>{t('index:pickColorDescription')}</p>
|
|
||||||
<div className="relative inline-block w-full">
|
|
||||||
<Colors onChange={setSelectedColor} initialValue={selectedColor}/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}/> */}
|
|
||||||
<Card step="2" heading={t('index:addToWallet')} content={
|
|
||||||
<div className="space-y-5">
|
<div className="space-y-5">
|
||||||
<p>
|
<p>
|
||||||
{t('index:dataPrivacyDescription')}
|
{t('index:dataPrivacyDescription')}
|
||||||
@ -234,17 +251,7 @@ function Form(): JSX.Element {
|
|||||||
{/* <Check text={t('hostedInEU')}/> */}
|
{/* <Check text={t('hostedInEU')}/> */}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{/* <label htmlFor="privacy" className="flex flex-row space-x-4 items-center pb-2">
|
|
||||||
<input type="checkbox" id="privacy" value="privacy" required className="h-5 w-5 outline-none"/>
|
|
||||||
<p>
|
|
||||||
{t('index:iAcceptThe')}
|
|
||||||
<Link href="/privacy">
|
|
||||||
<a className="underline">
|
|
||||||
{t('index:privacyPolicy')}
|
|
||||||
</a>
|
|
||||||
</Link>.
|
|
||||||
</p>
|
|
||||||
</label> */}
|
|
||||||
<div className="flex flex-row items-center justify-start">
|
<div className="flex flex-row items-center justify-start">
|
||||||
<button id="download" type="submit"
|
<button id="download" type="submit"
|
||||||
className="focus:outline-none bg-green-600 py-2 px-3 text-white font-semibold rounded-md disabled:bg-gray-400">
|
className="focus:outline-none bg-green-600 py-2 px-3 text-white font-semibold rounded-md disabled:bg-gray-400">
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
title: Vaccination Receipt to Wallet
|
title: Vaccination Receipt to Wallet
|
||||||
subtitle: This tool verifies your electronic receipt (PDF) and save the record onto your Apple Wallet securely.
|
subtitle: This tool converts your vaccination receipt from Ontario Health to an Apple Wallet pass with an QR code. Other organizations (e.g. school, workplaces) can then scan the QR code to verify your vaccination status easily.
|
||||||
privacyPolicy: Privacy Policy
|
privacyPolicy: Privacy Policy
|
||||||
donate: Sponsor
|
donate: Sponsor
|
||||||
gitHub: GitHub
|
gitHub: GitHub
|
||||||
|
@ -2,11 +2,16 @@ iosHint: On iOS, please use Safari.
|
|||||||
errorClose: Close
|
errorClose: Close
|
||||||
selectCertificate: Select vaccination receipt (PDF)
|
selectCertificate: Select vaccination receipt (PDF)
|
||||||
selectCertificateDescription: |
|
selectCertificateDescription: |
|
||||||
If you have more than one receipts, download the most recent one from covid19.ontariohealth.ca
|
Press "Select File", "Browse..." and select the PDF file you have saved in Step 1.
|
||||||
#stopCamera: Stop Camera
|
#stopCamera: Stop Camera
|
||||||
#startCamera: Start Camera
|
#startCamera: Start Camera
|
||||||
openFile: Select File
|
openFile: Select File
|
||||||
#foundQrCode: Found QR Code!
|
#foundQrCode: Found QR Code!
|
||||||
|
downloadReceipt: Download official receipt from Ontario Health
|
||||||
|
visit: Visit
|
||||||
|
ontarioHealth: Ontario Health
|
||||||
|
gotoOntarioHealth: Go to Ontario Health
|
||||||
|
downloadSignedPDF: and enter your information to display your official vaccination receipt. Press the Share Icon at the bottom, "Save As Files" to store it onto your iPhone.
|
||||||
pickColor: Pick a Color
|
pickColor: Pick a Color
|
||||||
pickColorDescription: Pick a background color for your pass.
|
pickColorDescription: Pick a background color for your pass.
|
||||||
colorWhite: white
|
colorWhite: white
|
||||||
@ -19,7 +24,7 @@ colorPurple: purple
|
|||||||
colorTeal: teal
|
colorTeal: teal
|
||||||
addToWallet: Add to Wallet
|
addToWallet: Add to Wallet
|
||||||
dataPrivacyDescription: |
|
dataPrivacyDescription: |
|
||||||
Your vaccination receipt is processed on your mobile phone only.
|
Press the "Add to Wallet" below to import the data in Wallet.
|
||||||
iAcceptThe: I accept the
|
iAcceptThe: I accept the
|
||||||
privacyPolicy: Privacy Policy
|
privacyPolicy: Privacy Policy
|
||||||
createdOnDevice: No personal data is sent to the Internet.
|
createdOnDevice: No personal data is sent to the Internet.
|
||||||
|
@ -15,7 +15,8 @@ export enum COLORS {
|
|||||||
PURPLE = 'rgb(137, 68, 171)',
|
PURPLE = 'rgb(137, 68, 171)',
|
||||||
RED = 'rgb(215, 0, 21)',
|
RED = 'rgb(215, 0, 21)',
|
||||||
TEAL = 'rgb(0, 130, 153)',
|
TEAL = 'rgb(0, 130, 153)',
|
||||||
YELLOW = 'rgb(178, 80, 0)'
|
YELLOW = 'rgb(178, 80, 0)',
|
||||||
|
LIGHTGREEN = 'rgb(144, 238, 144)'
|
||||||
}
|
}
|
||||||
|
|
||||||
export function rgbToHex(rgbString: string) {
|
export function rgbToHex(rgbString: string) {
|
||||||
|
@ -157,5 +157,6 @@ export class PassData {
|
|||||||
this.barcodes = [qrCode];
|
this.barcodes = [qrCode];
|
||||||
this.barcode = qrCode;
|
this.barcode = qrCode;
|
||||||
this.generic = payload.generic;
|
this.generic = payload.generic;
|
||||||
|
this.sharingProhibited = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,22 +84,20 @@ export class Payload {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
auxiliaryFields: [
|
auxiliaryFields: [
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
],
|
|
||||||
backFields: [
|
|
||||||
{
|
|
||||||
key: "name",
|
key: "name",
|
||||||
label: "Name",
|
label: "Name",
|
||||||
value: name
|
value: name
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "dob",
|
|
||||||
label: "Date of Birth",
|
|
||||||
value: body.receipt.dateOfBirth,
|
|
||||||
textAlignment: TextAlignment.right
|
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
backFields: [
|
||||||
|
|
||||||
|
// {
|
||||||
|
// key: "dob",
|
||||||
|
// label: "Date of Birth",
|
||||||
|
// value: body.receipt.dateOfBirth,
|
||||||
|
// textAlignment: TextAlignment.right
|
||||||
|
// }
|
||||||
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -114,7 +112,7 @@ export class Payload {
|
|||||||
this.backgroundColor = COLORS.YELLOW;
|
this.backgroundColor = COLORS.YELLOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.labelColor = COLORS.WHITE
|
this.labelColor = COLORS.BLACK
|
||||||
this.foregroundColor = COLORS.BLACK
|
this.foregroundColor = COLORS.BLACK
|
||||||
this.img1x = Constants.img1xBlack
|
this.img1x = Constants.img1xBlack
|
||||||
this.img2x = Constants.img2xBlack
|
this.img2x = Constants.img2xBlack
|
||||||
|
@ -2,6 +2,7 @@ import {PayloadBody, Receipt} from "./payload";
|
|||||||
import * as PdfJS from 'pdfjs-dist'
|
import * as PdfJS from 'pdfjs-dist'
|
||||||
import {COLORS} from "./colors";
|
import {COLORS} from "./colors";
|
||||||
import { getCertificatesInfoFromPDF } from "@ninja-labs/verify-pdf"; // ES6
|
import { getCertificatesInfoFromPDF } from "@ninja-labs/verify-pdf"; // ES6
|
||||||
|
import { TextItem } from "pdfjs-dist/types/display/api";
|
||||||
// import verifyPDF from "@ninja-labs/verify-pdf";
|
// import verifyPDF from "@ninja-labs/verify-pdf";
|
||||||
// import {PNG} from 'pngjs'
|
// import {PNG} from 'pngjs'
|
||||||
// import {decodeData} from "./decode";
|
// import {decodeData} from "./decode";
|
||||||
@ -83,22 +84,22 @@ async function getPdfDetails(fileBuffer: ArrayBuffer): Promise<Receipt> {
|
|||||||
let name, vaccinationDate, vaccineName, dateOfBirth, numDoses, organization;
|
let name, vaccinationDate, vaccineName, dateOfBirth, numDoses, organization;
|
||||||
|
|
||||||
for (let i = 0; i < numItems; i++) {
|
for (let i = 0; i < numItems; i++) {
|
||||||
const item = content.items[i];
|
let item = content.items[i] as TextItem;
|
||||||
const value = item.str;
|
const value = item.str;
|
||||||
if (value.includes('Name / Nom'))
|
if (value.includes('Name / Nom'))
|
||||||
name = content.items[i+1].str;
|
name = (content.items[i+1] as TextItem).str;
|
||||||
if (value.includes('Date:')) {
|
if (value.includes('Date:')) {
|
||||||
vaccinationDate = content.items[i+1].str;
|
vaccinationDate = (content.items[i+1] as TextItem).str;
|
||||||
vaccinationDate = vaccinationDate.split(',')[0];
|
vaccinationDate = vaccinationDate.split(',')[0];
|
||||||
}
|
}
|
||||||
if (value.includes('Product name')) {
|
if (value.includes('Product name')) {
|
||||||
vaccineName = content.items[i+1].str;
|
vaccineName = (content.items[i+1] as TextItem).str;
|
||||||
vaccineName = vaccineName.split(' ')[0];
|
vaccineName = vaccineName.split(' ')[0];
|
||||||
}
|
}
|
||||||
if (value.includes('Date of birth'))
|
if (value.includes('Date of birth'))
|
||||||
dateOfBirth = content.items[i+1].str;
|
dateOfBirth = (content.items[i+1] as TextItem).str;
|
||||||
if (value.includes('Authorized organization'))
|
if (value.includes('Authorized organization'))
|
||||||
organization = content.items[i+1].str;
|
organization = (content.items[i+1] as TextItem).str;
|
||||||
if (value.includes('You have received'))
|
if (value.includes('You have received'))
|
||||||
numDoses = Number(value.split(' ')[3]);
|
numDoses = Number(value.split(' ')[3]);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user