Stores and restores settings to/from local AsyncStorage

This commit is contained in:
Aaron Louie 2020-09-10 18:23:55 -04:00
parent 53369bb0a4
commit fbcbd67a1d
6 changed files with 93 additions and 26 deletions

39
App.tsx
View File

@ -55,13 +55,30 @@ export default function Main() {
const [sampleId, setSampleId] = useState<string>(''); const [sampleId, setSampleId] = useState<string>('');
const [barCodeId, setBarCodeId] = useState<string>(''); const [barCodeId, setBarCodeId] = useState<string>('');
const [sampleDate, setSampleDate] = useState<Date>(new Date()); const [sampleDate, setSampleDate] = useState<Date>(new Date());
const [locationStr, setLocationStr] = useState<string>('4321'); const [locationStr, setLocationStr] = useState<string>('0000');
const [errorMessage, setErrorMessage] = useState<string>(''); const [errorMessage, setErrorMessage] = useState<string>('');
const [samples, setSamples] = useState<Sample[]>([]); const [samples, setSamples] = useState<Sample[]>([]);
const [lineCounts, setLineCounts] = useState<LineCount[]>([]); const [lineCounts, setLineCounts] = useState<LineCount[]>([]);
const [cameraType, setCameraType] = useState<CameraType>('back'); const [cameraType, setCameraType] = useState<CameraType>('back');
const [numCopies, setNumCopies] = useState<number>(0);
const defaultsInitializers = {
'default.cameraType': (s: string) => setCameraType(s as CameraType),
'default.numCopies': (s: string) => setNumCopies(parseInt(s, 10)),
'default.locationStr': (s: string) => setLocationStr(s),
};
useEffect(() => { useEffect(() => {
AsyncStorage.multiGet(Object.keys(defaultsInitializers)).then(storedDefaults => {
console.log('storedDefaults', storedDefaults);
storedDefaults.forEach(d => {
if (d[1] !== null) {
// @ts-ignore
defaultsInitializers[d[0]](d[1]);
}
});
});
BarCodeScanner.requestPermissionsAsync().then((value: PermissionResponse) => { BarCodeScanner.requestPermissionsAsync().then((value: PermissionResponse) => {
if (value.granted) { if (value.granted) {
setAppState(BarcodeScannerAppState.DEFAULT); setAppState(BarcodeScannerAppState.DEFAULT);
@ -238,6 +255,7 @@ export default function Main() {
case BarcodeScannerAppState.PRINTING: case BarcodeScannerAppState.PRINTING:
return <View style={styles.container}> return <View style={styles.container}>
<PrintingMessage <PrintingMessage
numCopies={numCopies}
onCancel={_printed} onCancel={_printed}
id={sampleId} id={sampleId}
barCodeId={barCodeId} barCodeId={barCodeId}
@ -275,10 +293,27 @@ export default function Main() {
case BarcodeScannerAppState.SETTINGS: case BarcodeScannerAppState.SETTINGS:
return <SettingsScreen return <SettingsScreen
cameraType={cameraType} cameraType={cameraType}
numCopies={numCopies}
locationStr={locationStr} locationStr={locationStr}
onSave={(newCameraType: CameraType, newLocationStr: string) => { onSave={(newCameraType: CameraType, newNumCopies: number, newLocationStr: string) => {
setCameraType(newCameraType); setCameraType(newCameraType);
setNumCopies(newNumCopies);
setLocationStr(newLocationStr); setLocationStr(newLocationStr);
console.log(newCameraType);
console.log(newLocationStr);
console.log(newNumCopies);
AsyncStorage.multiSet([
['default.cameraType', newCameraType as string],
['default.locationStr', newLocationStr],
['default.numCopies', newNumCopies.toString()],
]).then(() => {
console.log('New defaults stored.');
AsyncStorage.multiGet(Object.keys(defaultsInitializers)).then(storedDefaults => {
console.log('stored defaults after saving Settings:', storedDefaults);
});
});
_home(); _home();
}} }}
onCancel={_home} onCancel={_home}

View File

@ -28,7 +28,7 @@ const _save = (props: PrintingProps): Promise<void> => {
} }
const _print = async (props: PrintingProps): Promise<void> => { const _print = async (props: PrintingProps): Promise<void> => {
const numCopies = 2; // Number of copies to print const numCopies = props.numCopies; // Number of copies to print
const units = 'mm'; const units = 'mm';
const pageSize = 28.6; const pageSize = 28.6;
const pageWidth = `${pageSize}${units}`; const pageWidth = `${pageSize}${units}`;
@ -111,12 +111,7 @@ const _print = async (props: PrintingProps): Promise<void> => {
const pagesArray = []; const pagesArray = [];
for (let i=0; i<numCopies; i++) { for (let i=0; i<numCopies; i++) {
// TODO: Comment out these two lines, because this is just for testing. const svgString = await qrcode.toString(props.id, {
const fakeBarcodeId = `${i}`.padStart(9, '0');
const fakeDate = new Date();
const fakeId = fakeBarcodeId + '-' + format(fakeDate, 'yyyyMMddHH') + '-' + `${i}`.padStart(2, '0') + '-' + props.location;
const svgString = await qrcode.toString(fakeId, {
width: 72, // 20mm width: 72, // 20mm
height: 72, height: 72,
margin: 10, margin: 10,
@ -132,18 +127,18 @@ const _print = async (props: PrintingProps): Promise<void> => {
<div class="page-container"> <div class="page-container">
<div class="circle"></div> <div class="circle"></div>
${svgString} ${svgString}
<div class="date">${format(fakeDate, 'yyyy-MM-dd')}</div> <div class="date">${format(props.date, 'yyyy-MM-dd')}</div>
<div class="time"> <div class="time">
T<br /> T<br />
${format(fakeDate, 'HH')}<br /> ${format(props.date, 'HH')}<br />
${`${i}`.padStart(2, '0')} ${format(props.date, 'mm')}
</div> </div>
<div class="location"> <div class="location">
L<br /> L<br />
${props.location.slice(0, 2)}<br /> ${props.location.slice(0, 2)}<br />
${props.location.slice(2)}<br /> ${props.location.slice(2)}<br />
</div> </div>
<div class="barCodeId">#${fakeBarcodeId}</div> <div class="barCodeId">#${props.barCodeId}</div>
</div> </div>
`; `;

View File

@ -17,10 +17,10 @@ export const Scanner = (props: ScannerProps): ReactElement => {
</View> </View>
<View style={styles.centerMiddle}> <View style={styles.centerMiddle}>
<View style={styles.captureBox}/> <View style={styles.captureBox}/>
<Subheading style={styles.shadow}>
Place ID card with the barcode facing the camera. Keep the barcode in the green box.
</Subheading>
</View> </View>
<Subheading style={styles.shadow}>
Instruct the patient to hold their card up with the barcode facing the camera. Keep the barcode in the orange box.
</Subheading>
<View style={styles.centerMiddle}> <View style={styles.centerMiddle}>
<Button <Button
mode="text" mode="text"
@ -78,6 +78,7 @@ export const IdNumberInput = (props: ScannerProps): ReactElement => {
onChangeText={inputStr => setInputStr(inputStr)} onChangeText={inputStr => setInputStr(inputStr)}
mode="outlined" mode="outlined"
theme={DefaultTheme} theme={DefaultTheme}
keyboardType="numeric"
/> />
<HelperText type="error" visible={hasErrors()}> <HelperText type="error" visible={hasErrors()}>
ID number must be exactly 9 digits. No other characters are allowed. ID number must be exactly 9 digits. No other characters are allowed.

View File

@ -4,13 +4,27 @@ import {DefaultTheme, Subheading, Title, RadioButton, Paragraph, TextInput, Help
import {CameraType, SettingsScreenProps} from '../models/ElementProps'; import {CameraType, SettingsScreenProps} from '../models/ElementProps';
import {colors, styles} from './Styles'; import {colors, styles} from './Styles';
const _stringToInt = (inputStr: string): number => {
const num = parseInt(inputStr || '0', 10);
if (!isNaN(num)) {
return num;
}
return 0;
}
export const SettingsScreen = (props: SettingsScreenProps): ReactElement => { export const SettingsScreen = (props: SettingsScreenProps): ReactElement => {
const [newCameraType, setNewCameraType] = useState<CameraType>(props.cameraType); const [newCameraType, setNewCameraType] = useState<CameraType>(props.cameraType);
const [newNumCopies, setNewNumCopies] = useState<number>(props.numCopies);
const [newLocationStr, setNewLocationStr] = useState<string>(props.locationStr); const [newLocationStr, setNewLocationStr] = useState<string>(props.locationStr);
const pattern = /^[\d]{4}$/; const _numCopiesHasErrors = () => {
const hasErrors = () => { return newNumCopies <= 0 || newNumCopies > 10;
return !pattern.test(newLocationStr); };
const locPattern = /^[\d]{4}$/;
const _locHasErrors = () => {
return !locPattern.test(newLocationStr);
}; };
return <View style={styles.settings}> return <View style={styles.settings}>
@ -34,6 +48,24 @@ export const SettingsScreen = (props: SettingsScreenProps): ReactElement => {
</RadioButton.Group> </RadioButton.Group>
</View> </View>
<View style={{marginBottom: 40}}>
<Subheading style={{color: DefaultTheme.colors.text}}>Copies of labels</Subheading>
<Paragraph style={{color: DefaultTheme.colors.text}}>
Input the number of sets of labels to print for each patient
</Paragraph>
<TextInput
label="# of copies"
value={newNumCopies.toString()}
onChangeText={inputStr => setNewNumCopies(_stringToInt(inputStr))}
mode="outlined"
theme={DefaultTheme}
keyboardType="numeric"
/>
<HelperText type="error" visible={_numCopiesHasErrors()}>
Please enter a number from 1 to 10.
</HelperText>
</View>
<View style={{marginBottom: 10}}> <View style={{marginBottom: 10}}>
<Subheading style={{color: DefaultTheme.colors.text}}>Location Code</Subheading> <Subheading style={{color: DefaultTheme.colors.text}}>Location Code</Subheading>
<Paragraph style={{color: DefaultTheme.colors.text}}> <Paragraph style={{color: DefaultTheme.colors.text}}>
@ -46,8 +78,9 @@ export const SettingsScreen = (props: SettingsScreenProps): ReactElement => {
onChangeText={inputStr => setNewLocationStr(inputStr)} onChangeText={inputStr => setNewLocationStr(inputStr)}
mode="outlined" mode="outlined"
theme={DefaultTheme} theme={DefaultTheme}
keyboardType="numeric"
/> />
<HelperText type="error" visible={hasErrors()}> <HelperText type="error" visible={_locHasErrors()}>
Location number must be exactly 4 digits. No other characters are allowed. Location number must be exactly 4 digits. No other characters are allowed.
</HelperText> </HelperText>
<Button <Button
@ -55,8 +88,8 @@ export const SettingsScreen = (props: SettingsScreenProps): ReactElement => {
mode="contained" mode="contained"
color={colors.primary} color={colors.primary}
style={{marginBottom: 10}} style={{marginBottom: 10}}
disabled={hasErrors()} disabled={_locHasErrors() || _numCopiesHasErrors()}
onPress={() => props.onSave(newCameraType, newLocationStr)} onPress={() => props.onSave(newCameraType, newNumCopies, newLocationStr)}
>Save</Button> >Save</Button>
<Button <Button
icon="cancel" icon="cancel"

View File

@ -36,9 +36,9 @@ const _common = StyleSheet.create({
export const styles = StyleSheet.create({ export const styles = StyleSheet.create({
captureBox: { captureBox: {
borderStyle: 'solid', borderStyle: 'solid',
borderColor: 'green', borderColor: colors.accent,
borderWidth: 10, borderWidth: 10,
height: '30%', height: '40%',
width: '90%', width: '90%',
borderRadius: 20, borderRadius: 20,
}, },
@ -77,7 +77,8 @@ export const styles = StyleSheet.create({
color: colors.onBackground, color: colors.onBackground,
fontSize: 20, fontSize: 20,
marginHorizontal: '15%', marginHorizontal: '15%',
marginVertical: 40, marginTop: 0,
marginBottom: 40,
textAlign: 'center', textAlign: 'center',
textShadowOffset: {width: 0, height: 0}, textShadowOffset: {width: 0, height: 0},
textShadowRadius: 4, textShadowRadius: 4,

View File

@ -30,8 +30,9 @@ export interface InputLineCountScreenProps extends ElementProps {
export interface SettingsScreenProps extends ElementProps { export interface SettingsScreenProps extends ElementProps {
cameraType: CameraType; cameraType: CameraType;
numCopies: number;
locationStr: string; locationStr: string;
onSave: (newCameraType: CameraType, newLocationStr: string) => void; onSave: (newCameraType: CameraType, newNumCopies: number, newLocationStr: string) => void;
onCancel: () => void; onCancel: () => void;
} }
@ -42,5 +43,6 @@ export interface ScannerProps extends ElementProps {
} }
export interface PrintingProps extends BarCodeProps { export interface PrintingProps extends BarCodeProps {
numCopies: number;
onCancel: () => void; onCancel: () => void;
} }