WIP: Displays QRCode instead of 1D barcode
Former-commit-id: 5a7dd6b7582fa2dea2131d4997eb6d0b8234eead
This commit is contained in:
parent
5729def6ca
commit
0a16a7b4f9
|
@ -533,3 +533,70 @@ buck-out/
|
||||||
# Expo
|
# Expo
|
||||||
.expo/*
|
.expo/*
|
||||||
web-build/
|
web-build/
|
||||||
|
|
||||||
|
# The following contents were automatically generated by expo-cli during eject
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# OSX
|
||||||
|
#
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Xcode
|
||||||
|
#
|
||||||
|
build/
|
||||||
|
*.pbxuser
|
||||||
|
!default.pbxuser
|
||||||
|
*.mode1v3
|
||||||
|
!default.mode1v3
|
||||||
|
*.mode2v3
|
||||||
|
!default.mode2v3
|
||||||
|
*.perspectivev3
|
||||||
|
!default.perspectivev3
|
||||||
|
xcuserdata
|
||||||
|
*.xccheckout
|
||||||
|
*.moved-aside
|
||||||
|
DerivedData
|
||||||
|
*.hmap
|
||||||
|
*.ipa
|
||||||
|
*.xcuserstate
|
||||||
|
project.xcworkspace
|
||||||
|
|
||||||
|
# Android/IntelliJ
|
||||||
|
#
|
||||||
|
build/
|
||||||
|
.idea
|
||||||
|
.gradle
|
||||||
|
local.properties
|
||||||
|
*.iml
|
||||||
|
|
||||||
|
# node.js
|
||||||
|
#
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
|
||||||
|
# BUCK
|
||||||
|
buck-out/
|
||||||
|
\.buckd/
|
||||||
|
*.keystore
|
||||||
|
|
||||||
|
# fastlane
|
||||||
|
#
|
||||||
|
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
|
||||||
|
# screenshots whenever they are needed.
|
||||||
|
# For more information about the recommended setup visit:
|
||||||
|
# https://docs.fastlane.tools/best-practices/source-control/
|
||||||
|
|
||||||
|
*/fastlane/report.xml
|
||||||
|
*/fastlane/Preview.html
|
||||||
|
*/fastlane/screenshots
|
||||||
|
|
||||||
|
# Bundle artifacts
|
||||||
|
*.jsbundle
|
||||||
|
|
||||||
|
# CocoaPods
|
||||||
|
/ios/Pods/
|
||||||
|
|
||||||
|
# Expo
|
||||||
|
.expo/*
|
||||||
|
web-build/
|
||||||
|
|
130
App.tsx
130
App.tsx
|
@ -1,16 +1,24 @@
|
||||||
|
// @refresh reset
|
||||||
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
|
import {format, parse} from 'date-fns';
|
||||||
import {BarCodeEvent, BarCodeScanner, PermissionResponse} from 'expo-barcode-scanner';
|
import {BarCodeEvent, BarCodeScanner, PermissionResponse} from 'expo-barcode-scanner';
|
||||||
import React, {ReactElement, useEffect, useState} from 'react';
|
// @ts-ignore
|
||||||
import {AppRegistry, SafeAreaView, View} from 'react-native';
|
import * as firebase from 'firebase';
|
||||||
|
import 'firebase/firestore';
|
||||||
|
import React, {ReactElement, useCallback, useEffect, useState} from 'react';
|
||||||
|
import {AppRegistry, SafeAreaView, View, YellowBox} from 'react-native';
|
||||||
import {
|
import {
|
||||||
Appbar,
|
Appbar,
|
||||||
Button, DarkTheme,
|
Button,
|
||||||
DefaultTheme,
|
DefaultTheme,
|
||||||
HelperText,
|
HelperText,
|
||||||
Provider as PaperProvider,
|
Provider as PaperProvider,
|
||||||
Snackbar, Subheading,
|
Snackbar,
|
||||||
|
Subheading,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title
|
Title
|
||||||
} from 'react-native-paper';
|
} from 'react-native-paper';
|
||||||
|
import QRCode from 'react-native-qrcode-svg';
|
||||||
import {expo as appExpo} from './app.json';
|
import {expo as appExpo} from './app.json';
|
||||||
import {CancelButton} from './components/Common';
|
import {CancelButton} from './components/Common';
|
||||||
import {BarCodeDisplay, PrintButton, PrintingMessage} from './components/Print';
|
import {BarCodeDisplay, PrintButton, PrintingMessage} from './components/Print';
|
||||||
|
@ -18,6 +26,29 @@ import {IdNumberInput, InputIdButton, ScanButton, Scanner} from './components/Sc
|
||||||
import {colors, styles} from './components/Styles';
|
import {colors, styles} from './components/Styles';
|
||||||
import {BarcodeScannerAppState} from './models/BarcodeScannerAppState';
|
import {BarcodeScannerAppState} from './models/BarcodeScannerAppState';
|
||||||
import {ElementProps, StateProps} from './models/ElementProps';
|
import {ElementProps, StateProps} from './models/ElementProps';
|
||||||
|
import {Sample} from './models/Sample';
|
||||||
|
|
||||||
|
const firebaseConfig = {
|
||||||
|
apiKey: 'api_key_goes_here',
|
||||||
|
authDomain: 'auth_domain_goes_here',
|
||||||
|
databaseURL: 'database_url_goes_here',
|
||||||
|
projectId: 'project_id_goes_here',
|
||||||
|
storageBucket: 'storage_bucket_goes_here',
|
||||||
|
messagingSenderId: 'sender_id_goes_here',
|
||||||
|
appId: 'app_id_goes_here'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialize Firebase if not already initialized.
|
||||||
|
if (firebase.apps.length === 0) {
|
||||||
|
firebase.initializeApp(firebaseConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
YellowBox.ignoreWarnings([
|
||||||
|
'Setting a timer for a long period of time', // Ignore Firebase timer warnings
|
||||||
|
]);
|
||||||
|
|
||||||
|
const db = firebase.firestore();
|
||||||
|
const samplesCollection = db.collection('samples');
|
||||||
|
|
||||||
const theme = {
|
const theme = {
|
||||||
...DefaultTheme,
|
...DefaultTheme,
|
||||||
|
@ -26,10 +57,13 @@ const theme = {
|
||||||
|
|
||||||
export default function Main() {
|
export default function Main() {
|
||||||
const [appState, setAppState] = useState<BarcodeScannerAppState>(BarcodeScannerAppState.INITIAL);
|
const [appState, setAppState] = useState<BarcodeScannerAppState>(BarcodeScannerAppState.INITIAL);
|
||||||
const [barCodeData, setBarCodeData] = useState<string>('');
|
const [sampleId, setSampleId] = useState<string>('');
|
||||||
const [date, setDate] = useState<Date>(new Date());
|
const [barCodeId, setBarCodeId] = useState<string>('');
|
||||||
|
const [sampleDate, setSampleDate] = useState<Date>(new Date());
|
||||||
const [locationStr, setLocationStr] = useState<string>('4321');
|
const [locationStr, setLocationStr] = useState<string>('4321');
|
||||||
|
const [svgQrCode, setSvgQrCode] = useState<any>();
|
||||||
const [errorMessage, setErrorMessage] = useState<string>('');
|
const [errorMessage, setErrorMessage] = useState<string>('');
|
||||||
|
const [samples, setSamples] = useState<Sample[]>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
BarCodeScanner.requestPermissionsAsync().then((value: PermissionResponse) => {
|
BarCodeScanner.requestPermissionsAsync().then((value: PermissionResponse) => {
|
||||||
|
@ -39,9 +73,26 @@ export default function Main() {
|
||||||
setAppState(BarcodeScannerAppState.ERROR);
|
setAppState(BarcodeScannerAppState.ERROR);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const unsubscribe = samplesCollection.onSnapshot(querySnapshot => {
|
||||||
|
// Transform and sort the data returned from Firebase
|
||||||
|
const samplesFirestore = querySnapshot
|
||||||
|
.docChanges()
|
||||||
|
.filter(({type}) => type === 'added')
|
||||||
|
.map(({doc}) => {
|
||||||
|
const sample = doc.data();
|
||||||
|
return {...sample, createdAt: sample.createdAt.toDate()} as Sample;
|
||||||
|
})
|
||||||
|
.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
||||||
|
|
||||||
|
appendSamples(samplesFirestore);
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => unsubscribe()
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const _doNothing = () => {};
|
const _doNothing = () => {
|
||||||
|
};
|
||||||
const _scan = () => {
|
const _scan = () => {
|
||||||
setErrorMessage('');
|
setErrorMessage('');
|
||||||
setAppState(BarcodeScannerAppState.SCANNING);
|
setAppState(BarcodeScannerAppState.SCANNING);
|
||||||
|
@ -51,6 +102,7 @@ export default function Main() {
|
||||||
setAppState(BarcodeScannerAppState.INPUT);
|
setAppState(BarcodeScannerAppState.INPUT);
|
||||||
};
|
};
|
||||||
const _print = () => setAppState(BarcodeScannerAppState.PRINTING);
|
const _print = () => setAppState(BarcodeScannerAppState.PRINTING);
|
||||||
|
const _printed = () => setAppState(BarcodeScannerAppState.PRINTED);
|
||||||
const _home = () => setAppState(BarcodeScannerAppState.DEFAULT);
|
const _home = () => setAppState(BarcodeScannerAppState.DEFAULT);
|
||||||
const _settings = () => setAppState(BarcodeScannerAppState.SETTINGS);
|
const _settings = () => setAppState(BarcodeScannerAppState.SETTINGS);
|
||||||
|
|
||||||
|
@ -62,15 +114,31 @@ export default function Main() {
|
||||||
const pattern = /^[\d]{14}$|^[\d]{9}$/;
|
const pattern = /^[\d]{14}$|^[\d]{9}$/;
|
||||||
if (pattern.test(barCodeString)) {
|
if (pattern.test(barCodeString)) {
|
||||||
const cardId = e.data.slice(0, 9);
|
const cardId = e.data.slice(0, 9);
|
||||||
setBarCodeData(cardId);
|
setBarCodeId(cardId);
|
||||||
setDate(new Date());
|
setSampleDate(new Date());
|
||||||
setAppState(BarcodeScannerAppState.SCANNED);
|
setAppState(BarcodeScannerAppState.SCANNED);
|
||||||
|
setSampleId([barCodeId, format(sampleDate, 'yyyyMMddHHmm'), locationStr].join('-'));
|
||||||
|
|
||||||
|
console.log('sampleId', sampleId);
|
||||||
|
new QRCode({value: sampleId, ecl: 'H', getRef: c => {
|
||||||
|
setSvgQrCode(c);
|
||||||
|
console.log('svgQrCode', svgQrCode);
|
||||||
|
}});
|
||||||
} else {
|
} else {
|
||||||
setErrorMessage(`The barcode data "${e.data}" is not from a valid ID card.`);
|
setErrorMessage(`The barcode data "${e.data}" is not from a valid ID card.`);
|
||||||
setAppState(BarcodeScannerAppState.ERROR);
|
setAppState(BarcodeScannerAppState.ERROR);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const appendSamples = useCallback((newSamples) => {
|
||||||
|
setSamples((previousSamples) => previousSamples.concat(newSamples));
|
||||||
|
}, [samples]);
|
||||||
|
|
||||||
|
const sendDataToFirebase = async (newSamples: Sample[]) => {
|
||||||
|
const writes = newSamples.map(s => samplesCollection.doc(s.id).set(s));
|
||||||
|
await Promise.all(writes);
|
||||||
|
}
|
||||||
|
|
||||||
function ErrorMessage(props: ElementProps): ReactElement {
|
function ErrorMessage(props: ElementProps): ReactElement {
|
||||||
return <View style={styles.fullScreen}>
|
return <View style={styles.fullScreen}>
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
|
@ -114,7 +182,8 @@ export default function Main() {
|
||||||
<Title style={styles.headingInverse}>Settings</Title>
|
<Title style={styles.headingInverse}>Settings</Title>
|
||||||
<View style={{marginBottom: 10}}>
|
<View style={{marginBottom: 10}}>
|
||||||
<Subheading style={{color: DefaultTheme.colors.text, marginBottom: 60}}>
|
<Subheading style={{color: DefaultTheme.colors.text, marginBottom: 60}}>
|
||||||
Please do NOT change this unless you know what you are doing. Entering an incorrect location number may prevent patients from getting accurate info about their test results.
|
Please do NOT change this unless you know what you are doing. Entering an incorrect location number may
|
||||||
|
prevent patients from getting accurate info about their test results.
|
||||||
</Subheading>
|
</Subheading>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Location #"
|
label="Location #"
|
||||||
|
@ -157,16 +226,45 @@ export default function Main() {
|
||||||
<InputIdButton onClicked={_inputIdNumber}/>
|
<InputIdButton onClicked={_inputIdNumber}/>
|
||||||
</View>;
|
</View>;
|
||||||
case BarcodeScannerAppState.PRINTED:
|
case BarcodeScannerAppState.PRINTED:
|
||||||
|
// Upload any changes to Firebase
|
||||||
|
AsyncStorage.getAllKeys().then(keys => {
|
||||||
|
const newSamples = keys
|
||||||
|
.filter(s => /^[\d]{9}-[\d]{12}-[\d]{4}$/.test(s))
|
||||||
|
.map(s => {
|
||||||
|
const propsArray = s.split('-');
|
||||||
|
return {
|
||||||
|
id: s,
|
||||||
|
barcodeId: propsArray[0],
|
||||||
|
createdAt: parse(propsArray[1], 'yyyyMMddHHmm', new Date()),
|
||||||
|
locationId: propsArray[2],
|
||||||
|
} as Sample;
|
||||||
|
});
|
||||||
|
sendDataToFirebase(newSamples);
|
||||||
|
});
|
||||||
|
|
||||||
|
_home();
|
||||||
|
|
||||||
return <SuccessMessage/>;
|
return <SuccessMessage/>;
|
||||||
case BarcodeScannerAppState.PRINTING:
|
case BarcodeScannerAppState.PRINTING:
|
||||||
return <PrintingMessage
|
return <View style={styles.container}>
|
||||||
onCancel={_home}
|
<PrintingMessage
|
||||||
id={barCodeData}
|
onCancel={_printed}
|
||||||
date={date} location={locationStr}
|
id={sampleId}
|
||||||
/>;
|
barCodeId={barCodeId}
|
||||||
|
date={sampleDate}
|
||||||
|
location={locationStr}
|
||||||
|
svg={svgQrCode}
|
||||||
|
/>
|
||||||
|
</View>;
|
||||||
case BarcodeScannerAppState.SCANNED:
|
case BarcodeScannerAppState.SCANNED:
|
||||||
return <View style={styles.container}>
|
return <View style={styles.container}>
|
||||||
<BarCodeDisplay id={barCodeData} date={date} location={locationStr}/>
|
<BarCodeDisplay
|
||||||
|
id={sampleId}
|
||||||
|
barCodeId={barCodeId}
|
||||||
|
date={sampleDate}
|
||||||
|
location={locationStr}
|
||||||
|
svg={svgQrCode}
|
||||||
|
/>
|
||||||
<ActionButtons/>
|
<ActionButtons/>
|
||||||
</View>;
|
</View>;
|
||||||
case BarcodeScannerAppState.SCANNING:
|
case BarcodeScannerAppState.SCANNING:
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import React, {ReactElement, useEffect, useState} from 'react';
|
import React, {ReactElement, useEffect, useState} from 'react';
|
||||||
import {Text, View} from 'react-native';
|
import {Text, View} from 'react-native';
|
||||||
// @ts-ignore
|
|
||||||
import Barcode from 'react-native-barcode-builder';
|
|
||||||
import {Button, Title} from 'react-native-paper';
|
import {Button, Title} from 'react-native-paper';
|
||||||
|
import QRCode from 'react-native-qrcode-svg';
|
||||||
import {BarCodeProps, ButtonProps, PrintingProps} from '../models/ElementProps';
|
import {BarCodeProps, ButtonProps, PrintingProps} from '../models/ElementProps';
|
||||||
|
import {Sample} from '../models/Sample';
|
||||||
import {colors, styles} from './Styles';
|
import {colors, styles} from './Styles';
|
||||||
import AsyncStorage from '@react-native-community/async-storage';
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
import * as Print from 'expo-print';
|
import * as Print from 'expo-print';
|
||||||
|
@ -15,44 +15,18 @@ enum PrintStatus {
|
||||||
DONE = 'DONE',
|
DONE = 'DONE',
|
||||||
}
|
}
|
||||||
|
|
||||||
const _renderBarCodeRects = (props: PrintingProps): string => {
|
|
||||||
const dataStr = _propsToDataString(props);
|
|
||||||
const rects: string[] = [];
|
|
||||||
|
|
||||||
// TODO: set base width from label width in pixels
|
|
||||||
// 2 inches = 190 pixels
|
|
||||||
// for now, just guesstimate.
|
|
||||||
const baseWidth = 7;
|
|
||||||
|
|
||||||
for (let i = 0; i < dataStr.length; i++) {
|
|
||||||
// TODO: Convert dataStr to barcode rectangles with x, y, width, height
|
|
||||||
// barcodejs library has some useful stuff?
|
|
||||||
// Or maybe somehow use something in the guts of react-native-barcode-builder?
|
|
||||||
// For now, just put in some dummy x values and widths.
|
|
||||||
rects.push(`<rect width="${Math.floor(Math.random() * baseWidth)}" height="20" x="${baseWidth * i}" y="70" fill="black" />`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rects.join(' ')
|
|
||||||
}
|
|
||||||
|
|
||||||
const _propsToDataString = (props: BarCodeProps): string => {
|
|
||||||
return props.id + format(props.date, 'yyyymmdd') + props.location;
|
|
||||||
}
|
|
||||||
|
|
||||||
const _save = (props: PrintingProps): Promise<void> => {
|
const _save = (props: PrintingProps): Promise<void> => {
|
||||||
const storageKey = _propsToDataString(props);
|
const storageVal: Sample = {
|
||||||
const storageVal = {
|
|
||||||
id: props.id,
|
id: props.id,
|
||||||
date: props.date,
|
barcodeId: props.barCodeId,
|
||||||
location: props.location,
|
createdAt: props.date,
|
||||||
|
locationId: props.location,
|
||||||
};
|
};
|
||||||
console.log('storageKey', storageKey);
|
return AsyncStorage.setItem(props.id, JSON.stringify(storageVal));
|
||||||
console.log('storageVal', storageVal);
|
|
||||||
return AsyncStorage.setItem(storageKey, JSON.stringify(storageVal));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const _print = (props: PrintingProps): Promise<void> => {
|
const _print = (props: PrintingProps): Promise<void> => {
|
||||||
const dataStr = _propsToDataString(props);
|
console.log('props.svg', props.svg);
|
||||||
return Print.printAsync({
|
return Print.printAsync({
|
||||||
html: `
|
html: `
|
||||||
<style>
|
<style>
|
||||||
|
@ -90,13 +64,11 @@ const _print = (props: PrintingProps): Promise<void> => {
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<p>ID#: ${props.id}</p>
|
<p>ID#: ${props.barCodeId}</p>
|
||||||
<p>Date: ${props.date.toLocaleDateString()} ${props.date.toLocaleTimeString()}</p>
|
<p>Date: ${props.date.toLocaleDateString()} ${props.date.toLocaleTimeString()}</p>
|
||||||
<p>Loc#: ${props.location}</p>
|
<p>Loc#: ${props.location}</p>
|
||||||
<svg width="190" height="90" id="barCode">
|
${props.svg}
|
||||||
${_renderBarCodeRects(props)}
|
<p>${props.id}</p>
|
||||||
</svg>
|
|
||||||
<p>${dataStr}</p>
|
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
});
|
});
|
||||||
|
@ -142,11 +114,15 @@ export const PrintingMessage = (props: PrintingProps): ReactElement => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return <View style={styles.container}>
|
return <View style={styles.container}>
|
||||||
<View style={styles.preview}>
|
<View style={styles.preview}>
|
||||||
<BarCodeDisplay id={props.id} date={props.date} location={props.location} />
|
<BarCodeDisplay
|
||||||
<BarCodeDisplay id={props.id} date={props.date} location={props.location} />
|
id={props.id}
|
||||||
|
barCodeId={props.barCodeId}
|
||||||
|
date={props.date}
|
||||||
|
location={props.location}
|
||||||
|
svg={props.svg}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<Title style={styles.heading}>{statusStr}</Title>
|
<Title style={styles.heading}>{statusStr}</Title>
|
||||||
|
@ -165,11 +141,11 @@ export const PrintingMessage = (props: PrintingProps): ReactElement => {
|
||||||
|
|
||||||
|
|
||||||
export const BarCodeDisplay = (props: BarCodeProps): ReactElement => {
|
export const BarCodeDisplay = (props: BarCodeProps): ReactElement => {
|
||||||
const data = _propsToDataString(props);
|
console.log('BarCodeDisplay props.svg', props.svg);
|
||||||
return <View style={styles.printPreview}>
|
return <View style={styles.printPreview}>
|
||||||
<Text style={styles.label}>ID#: {props.id}</Text>
|
<Text style={styles.label}>ID#: {props.id}</Text>
|
||||||
<Text style={styles.label}>Date: {props.date.toLocaleDateString()}, {props.date.toLocaleTimeString()}</Text>
|
<Text style={styles.label}>Date: {props.date.toLocaleDateString()}, {props.date.toLocaleTimeString()}</Text>
|
||||||
<Text style={styles.label}>Location {props.location}</Text>
|
<Text style={styles.label}>Location {props.location}</Text>
|
||||||
<Barcode width={1.1} height={40} text={data} value={data} format={'CODE128'}/>
|
<QRCode value={props.id} />
|
||||||
</View>;
|
</View>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,10 @@ export interface StateProps extends ElementProps {
|
||||||
|
|
||||||
export interface BarCodeProps extends ElementProps {
|
export interface BarCodeProps extends ElementProps {
|
||||||
id: string;
|
id: string;
|
||||||
|
barCodeId: string;
|
||||||
date: Date;
|
date: Date;
|
||||||
location: string;
|
location: string;
|
||||||
|
svg: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ButtonProps extends ElementProps {
|
export interface ButtonProps extends ElementProps {
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
export interface Sample {
|
||||||
|
id: string;
|
||||||
|
barcodeId: string;
|
||||||
|
locationId: string;
|
||||||
|
createdAt: Date;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -15,17 +15,18 @@
|
||||||
"expo-splash-screen": "^0.5.0",
|
"expo-splash-screen": "^0.5.0",
|
||||||
"expo-status-bar": "^1.0.2",
|
"expo-status-bar": "^1.0.2",
|
||||||
"expo-updates": "~0.2.10",
|
"expo-updates": "~0.2.10",
|
||||||
|
"firebase": "7.9.0",
|
||||||
"jsbarcode": "^3.11.0",
|
"jsbarcode": "^3.11.0",
|
||||||
"react": "~16.11.0",
|
"react": "~16.11.0",
|
||||||
"react-dom": "~16.11.0",
|
"react-dom": "~16.11.0",
|
||||||
"react-native": "~0.62.2",
|
"react-native": "~0.62.2",
|
||||||
"react-native-barcode-builder": "github:cdesch/react-native-barcode-builder#master",
|
|
||||||
"react-native-canvas": "^0.1.37",
|
"react-native-canvas": "^0.1.37",
|
||||||
"react-native-easy-grid": "^0.2.2",
|
"react-native-easy-grid": "^0.2.2",
|
||||||
"react-native-gesture-handler": "~1.6.1",
|
"react-native-gesture-handler": "~1.6.1",
|
||||||
"react-native-html-to-pdf": "^0.8.0",
|
"react-native-html-to-pdf": "^0.8.0",
|
||||||
"react-native-paper": "^4.1.0",
|
"react-native-paper": "^4.1.0",
|
||||||
"react-native-print": "^0.6.0",
|
"react-native-print": "^0.6.0",
|
||||||
|
"react-native-qrcode-svg": "^6.0.6",
|
||||||
"react-native-reanimated": "~1.9.0",
|
"react-native-reanimated": "~1.9.0",
|
||||||
"react-native-screens": "~2.9.0",
|
"react-native-screens": "~2.9.0",
|
||||||
"react-native-share": "^3.7.0",
|
"react-native-share": "^3.7.0",
|
||||||
|
|
Loading…
Reference in New Issue