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 [barCodeId, setBarCodeId] = useState<string>('');
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 [samples, setSamples] = useState<Sample[]>([]);
const [lineCounts, setLineCounts] = useState<LineCount[]>([]);
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(() => {
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) => {
if (value.granted) {
setAppState(BarcodeScannerAppState.DEFAULT);
@ -238,6 +255,7 @@ export default function Main() {
case BarcodeScannerAppState.PRINTING:
return <View style={styles.container}>
<PrintingMessage
numCopies={numCopies}
onCancel={_printed}
id={sampleId}
barCodeId={barCodeId}
@ -275,10 +293,27 @@ export default function Main() {
case BarcodeScannerAppState.SETTINGS:
return <SettingsScreen
cameraType={cameraType}
numCopies={numCopies}
locationStr={locationStr}
onSave={(newCameraType: CameraType, newLocationStr: string) => {
onSave={(newCameraType: CameraType, newNumCopies: number, newLocationStr: string) => {
setCameraType(newCameraType);
setNumCopies(newNumCopies);
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();
}}
onCancel={_home}

View File

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

View File

@ -17,10 +17,10 @@ export const Scanner = (props: ScannerProps): ReactElement => {
</View>
<View style={styles.centerMiddle}>
<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>
<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}>
<Button
mode="text"
@ -78,6 +78,7 @@ export const IdNumberInput = (props: ScannerProps): ReactElement => {
onChangeText={inputStr => setInputStr(inputStr)}
mode="outlined"
theme={DefaultTheme}
keyboardType="numeric"
/>
<HelperText type="error" visible={hasErrors()}>
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 {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 => {
const [newCameraType, setNewCameraType] = useState<CameraType>(props.cameraType);
const [newNumCopies, setNewNumCopies] = useState<number>(props.numCopies);
const [newLocationStr, setNewLocationStr] = useState<string>(props.locationStr);
const pattern = /^[\d]{4}$/;
const hasErrors = () => {
return !pattern.test(newLocationStr);
const _numCopiesHasErrors = () => {
return newNumCopies <= 0 || newNumCopies > 10;
};
const locPattern = /^[\d]{4}$/;
const _locHasErrors = () => {
return !locPattern.test(newLocationStr);
};
return <View style={styles.settings}>
@ -34,6 +48,24 @@ export const SettingsScreen = (props: SettingsScreenProps): ReactElement => {
</RadioButton.Group>
</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}}>
<Subheading style={{color: DefaultTheme.colors.text}}>Location Code</Subheading>
<Paragraph style={{color: DefaultTheme.colors.text}}>
@ -46,8 +78,9 @@ export const SettingsScreen = (props: SettingsScreenProps): ReactElement => {
onChangeText={inputStr => setNewLocationStr(inputStr)}
mode="outlined"
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.
</HelperText>
<Button
@ -55,8 +88,8 @@ export const SettingsScreen = (props: SettingsScreenProps): ReactElement => {
mode="contained"
color={colors.primary}
style={{marginBottom: 10}}
disabled={hasErrors()}
onPress={() => props.onSave(newCameraType, newLocationStr)}
disabled={_locHasErrors() || _numCopiesHasErrors()}
onPress={() => props.onSave(newCameraType, newNumCopies, newLocationStr)}
>Save</Button>
<Button
icon="cancel"

View File

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

View File

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